Class: FaviconParty::Image
- Inherits:
-
Object
- Object
- FaviconParty::Image
show all
- Includes:
- Utils
- Defined in:
- lib/favicon_party/image.rb
Overview
For handling anything related to the image data of the favicon itself
Constant Summary
collapse
- STDEV_THRESHOLD =
Threshold for stdev of color values under which the image data is considered one color
0.005
- MAX_FILE_SIZE =
1024 * 1024
- VALID_MIME_TYPES =
%w(
image/x-ico
image/x-icon
image/png
image/gif
image/svg+xml
image/jpeg
)
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods included from Utils
#encode_utf8, #get_mime_type, #prefix_url, #with_temp_data_file
Constructor Details
#initialize(source_data) ⇒ Image
Returns a new instance of Image.
30
31
32
33
34
|
# File 'lib/favicon_party/image.rb', line 30
def initialize(source_data)
@source_data = source_data
@png_data = nil
@error = nil
end
|
Instance Attribute Details
#error ⇒ Object
Returns the value of attribute error.
28
29
30
|
# File 'lib/favicon_party/image.rb', line 28
def error
@error
end
|
#png_data ⇒ Object
Returns the value of attribute png_data.
28
29
30
|
# File 'lib/favicon_party/image.rb', line 28
def png_data
@png_data
end
|
#source_data ⇒ Object
Returns the value of attribute source_data.
28
29
30
|
# File 'lib/favicon_party/image.rb', line 28
def source_data
@source_data
end
|
Instance Method Details
#base64_png ⇒ Object
168
169
170
|
# File 'lib/favicon_party/image.rb', line 168
def base64_png
Base64.encode64(to_png).split(/\s+/).join
end
|
#base64_source_data ⇒ Object
164
165
166
|
# File 'lib/favicon_party/image.rb', line 164
def base64_source_data
Base64.encode64(@source_data).split(/\s+/).join
end
|
#blank? ⇒ Boolean
78
79
80
|
# File 'lib/favicon_party/image.rb', line 78
def blank?
@source_data.nil? || @source_data.length <= 1
end
|
#colors_stdev ⇒ Object
112
113
114
115
116
117
|
# File 'lib/favicon_party/image.rb', line 112
def colors_stdev
with_temp_data_file(to_png) do |t|
cmd = "identify -format '%[fx:image.standard_deviation]' #{t.path.to_s}"
imagemagick_run(cmd).to_f
end
end
|
#dimensions ⇒ Object
126
127
128
129
130
131
|
# File 'lib/favicon_party/image.rb', line 126
def dimensions
with_temp_data_file(@source_data) do |t|
cmd = "convert #{t.path.to_s}[0] -format '%wx%h' info:"
imagemagick_run(cmd)
end
end
|
#identify(verbose = false) ⇒ Object
52
53
54
55
56
|
# File 'lib/favicon_party/image.rb', line 52
def identify(verbose = false)
with_temp_data_file(@source_data) do |t|
imagemagick_run("identify #{"-verbose" if verbose} #{t.path.to_s}")
end
end
|
#imagemagick_run(cmd, binmode = false) ⇒ Object
36
37
38
39
40
41
42
43
44
45
|
# File 'lib/favicon_party/image.rb', line 36
def imagemagick_run(cmd, binmode = false)
stdin, stdout, stderr, t = Open3.popen3(cmd)
stdout.binmode if binmode
output = stdout.read.strip
error = stderr.read.strip
if output.empty? && !error.nil? && !error.empty?
raise FaviconParty::ImageMagickError.new(error)
end
output
end
|
#info_str ⇒ Object
139
140
141
|
# File 'lib/favicon_party/image.rb', line 139
def info_str
"#{mime_type}, #{dimensions}, #{size} bytes"
end
|
#inspect ⇒ Object
172
173
174
|
# File 'lib/favicon_party/image.rb', line 172
def inspect
%(#<FaviconParty::Image mime_type: "#{mime_type}", size: #{size}>)
end
|
#invalid_mime_type? ⇒ Boolean
TODO set an option to decide how mime-type validity is handled
88
89
90
|
# File 'lib/favicon_party/image.rb', line 88
def invalid_mime_type?
mime_type =~ /(text|html|x-empty|octet-stream|ERROR|zip|jar)/
end
|
#mime_type ⇒ Object
47
48
49
50
|
# File 'lib/favicon_party/image.rb', line 47
def mime_type
return @mime_type if defined? @mime_type
@mime_type = get_mime_type(@source_data)
end
|
#n_colors ⇒ Object
119
120
121
122
123
124
|
# File 'lib/favicon_party/image.rb', line 119
def n_colors
with_temp_data_file(@source_data) do |t|
cmd = "identify -format '%k' #{t.path.to_s}"
imagemagick_run(cmd).to_i
end
end
|
#one_color? ⇒ Boolean
108
109
110
|
# File 'lib/favicon_party/image.rb', line 108
def one_color?
colors_stdev < STDEV_THRESHOLD
end
|
#one_pixel? ⇒ Boolean
103
104
105
106
|
# File 'lib/favicon_party/image.rb', line 103
def one_pixel?
files = identify.split(/\n/)
files.length == 1 && files[0].include?(" 1x1 ")
end
|
#size ⇒ Object
number of bytes in the raw data
135
136
137
|
# File 'lib/favicon_party/image.rb', line 135
def size
@source_data && @source_data.size || 0
end
|
#size_too_big? ⇒ Boolean
82
83
84
|
# File 'lib/favicon_party/image.rb', line 82
def size_too_big?
size >= MAX_FILE_SIZE
end
|
#to_png ⇒ Object
Export source_data as a 16x16 png
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
# File 'lib/favicon_party/image.rb', line 145
def to_png
return @png_data if !@png_data.nil?
with_temp_data_file(@source_data) do |t|
sizes = imagemagick_run("identify #{t.path.to_s}").split(/\n/)
images = []
%w(16x16 32x32 64x64).each do |dims|
%w(32-bit 24-bit 16-bit 8-bit).each do |bd|
images += sizes.select {|x| x.include?(dims) and x.include?(bd) }.
map {|x| x.split(' ')[0] }
end
end
image_to_convert = images.uniq[0] || "#{t.path.to_s}[0]"
cmd = "convert -strip -resize 16x16! #{image_to_convert} png:fd:1"
@png_data = imagemagick_run(cmd, true)
raise FaviconParty::InvalidData.new("Empty png") if @png_data.empty?
@png_data
end
end
|
#transparent? ⇒ Boolean
96
97
98
99
100
101
|
# File 'lib/favicon_party/image.rb', line 96
def transparent?
with_temp_data_file(@source_data) do |t|
cmd = "convert #{t.path.to_s} -channel a -negate -format '%[mean]' info:"
imagemagick_run(cmd).to_i == 0
end
end
|
#valid? ⇒ Boolean
Does the data look like a valid favicon?
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
# File 'lib/favicon_party/image.rb', line 60
def valid?
@error =
if blank?
"source_data is blank"
elsif size_too_big?
"source_data file size too big"
elsif !valid_mime_type?
"source_data mime-type is invalid - #{mime_type}"
elsif transparent?
"source_data is a transparent image"
elsif one_pixel?
"source_data is a 1x1 image"
elsif one_color?
"png_data is one color (or close to it)"
end
@error.nil?
end
|
#valid_mime_type? ⇒ Boolean
92
93
94
|
# File 'lib/favicon_party/image.rb', line 92
def valid_mime_type?
VALID_MIME_TYPES.include? mime_type
end
|