class PDF::Writer::Graphics::ImageInfo
This is based on ImageSize, by Keisuke Minami <keisuke@rccn.com>. It can be found at www.rubycgi.org/tools/index.en.htm
This has been integrated into PDF::Writer
because as yet there has been no response to emails asking for my extensions to be integrated and a RubyGem package to be made available.
Constants
- JPEG_APP_BLOCKS
- JPEG_SOF_BLOCKS
- Type
Image Format Constants
- XBM_DIMENSIONS_RE
- XPM_DIMENSIONS_RE
Attributes
bits[R]
channels[R]
format[R]
get_height[R]
get_type[R]
get_width[R]
height[R]
info[R]
width[R]
Public Class Methods
formats()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 44 def formats 45 Formats.constants 46 end
Also aliased as: type_list
new(data, format = nil)
click to toggle source
Receive image & make size. argument is image String or IO
# File lib/pdf/writer/graphics/imageinfo.rb 54 def initialize(data, format = nil) 55 @data = data.dup rescue data 56 @info = {} 57 58 if @data.kind_of?(IO) 59 @top = @data.read(128) 60 @data.seek(0, 0) 61 # Define Singleton-method definition to IO (byte, offset) 62 def @data.read_o(length = 1, offset = nil) 63 self.seek(offset, 0) if offset 64 ret = self.read(length) 65 raise "cannot read!!" unless ret 66 ret 67 end 68 elsif @data.is_a?(String) 69 @top = @data[0, 128] 70 # Define Singleton-method definition to String (byte, offset) 71 @data.extend(PDF::Writer::OffsetReader) 72 else 73 raise "argument class error!! #{data.type}" 74 end 75 76 if format.nil? 77 @format = discover_format 78 else 79 match = false 80 Formats.constants.each { |t| match = true if format == t } 81 raise("format is failed. #{format}\n") unless match 82 @format = format 83 end 84 85 __send__("measure_#@format".intern) unless @format == Formats::OTHER 86 87 @data = data.dup 88 end
Private Instance Methods
discover_format()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 102 def discover_format 103 if @top =~ %r{^GIF8[79]a} 104 Formats::GIF 105 elsif @top[0, 3] == "\xff\xd8\xff" 106 Formats::JPEG 107 elsif @top[0, 8] == "\x89PNG\x0d\x0a\x1a\x0a" 108 Formats::PNG 109 elsif @top[0, 3] == "FWS" 110 Formats::SWF 111 elsif @top[0, 4] == "8BPS" 112 Formats::PSD 113 elsif @top[0, 2] == 'BM' 114 Formats::BMP 115 elsif @top[0, 4] == "MM\x00\x2a" 116 Formats::TIFF 117 elsif @top[0, 4] == "II\x2a\x00" 118 Formats::TIFF 119 elsif @top[0, 12] == "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a" 120 Formats::JP2 121 elsif @top =~ %r{^P[1-7]} 122 Formats::PPM 123 elsif @top =~ %r{\#define\s+\S+\s+\d+} 124 Formats::XBM 125 elsif @top =~ %r{/\* XPM \*/} 126 Formats::XPM 127 elsif @top[0] == 10 128 Formats::PCX 129 else 130 Formats::OTHER # might be WBMP 131 end 132 end
measure_BMP()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 192 def measure_BMP 193 # Skip the first 14 bytes of the image. 194 @data.read_o(14) 195 # Up to the next 16 bytes will be used. 196 dim = @data.read_o(16) 197 198 # Get the "size" of the image from the next four bytes. 199 size = dim.unpack("V").first # <- UNPACK RETURNS ARRAY, SO GET FIRST ELEMENT 200 201 if size == 12 202 @width, @height, @bits = dim.unpack("x4vvx3C") 203 elsif size > 12 and (size <= 64 or size == 108) 204 @width, @height, @bits = dim.unpack("x4VVv") 205 end 206 end
measure_GIF()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 135 def measure_GIF 136 @data.read_o(6) # Skip GIF8.a 137 @width, @height, @bits = @data.read_o(5).unpack('vvC') 138 if @bits & 0x80 == 0x80 139 @bits = (@bits & 0x07) + 1 140 else 141 @bits = 0 142 end 143 @channels = 3 144 end
measure_JPEG()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 171 def measure_JPEG 172 c_marker = "\xff" # Section marker. 173 @data.read_o(2) # Skip the first two bytes of JPEG identifier. 174 loop do 175 marker, code, length = @data.read_o(4).unpack('aan') 176 raise "JPEG marker not found!" if marker != c_marker 177 178 if JPEG_SOF_BLOCKS.include?(code) 179 @bits, @height, @width, @channels = @data.read_o(6).unpack("CnnC") 180 break 181 end 182 183 buffer = @data.read_o(length - 2) 184 185 if JPEG_APP_BLOCKS.include?(code) 186 @info["APP#{code.to_i - 0xe0}"] = buffer 187 end 188 end 189 end
measure_PCX()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 264 def measure_PCX 265 header = @data.read_o(128) 266 head_part = header.unpack('C4S4') 267 @width = head_part[6] - head_part[4] + 1 268 @height = head_part[7] - head_part[5] + 1 269 end
measure_PNG()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 147 def measure_PNG 148 @data.read_o(12) 149 raise "This file is not PNG." unless @data.read_o(4) == "IHDR" 150 # The file information is in the IHDR section. 151 # Offset Bytes Meaning 152 # 0 4 Width 153 # 5 4 Height 154 # 9 1 Bit Depth 155 # 10 1 Compression Method 156 # 11 1 Filter Method 157 # 12 1 Interlace Method 158 ihdr = @data.read_o(13).unpack("NNCCCCC") 159 @width = ihdr[0] 160 @height = ihdr[1] 161 @bits = ihdr[2] 162 @info[:color_type] = ihdr[3] 163 @info[:compression_method] = ihdr[4] 164 @info[:filter_method] = ihdr[5] 165 @info[:interlace_method] = ihdr[6] 166 167 168 end
measure_PPM()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 209 def measure_PPM 210 header = @data.read_o(1024) 211 header.gsub!(/^\#[^\n\r]*/m, "") 212 md = %r{^(P[1-6])\s+?(\d+)\s+?(\d+)}mo.match(header) 213 214 @width = md.captures[1] 215 @height = md.captures[2] 216 217 case md.captures[0] 218 when "P1", "P4" 219 @format = "PBM" 220 when "P2", "P5" 221 @format = "PGM" 222 when "P3", "P6" 223 @format = "PPM" 224 # when "P7" 225 # @format = "XV" 226 # header =~ /IMGINFO:(\d+)x(\d+)/m 227 # width = $1.to_i; height = $2.to_i 228 end 229 end
Also aliased as: measure_PGM, measure_PBM
measure_PSD()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 259 def measure_PSD 260 @width, @height = @data.read_o(26).unpack("x14NN") 261 end
measure_SWC()
click to toggle source
The same as SWF, except that the original data is compressed with Zlib. Disabled for now.
# File lib/pdf/writer/graphics/imageinfo.rb 292 def measure_SWC 293 end
measure_SWF()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 272 def measure_SWF 273 header = @data.read_o(9) 274 raise "This file is not SWF." unless header.unpack('a3')[0] == 'FWS' 275 276 bits = Integer("0b#{header.unpack('@8B5')}") 277 header << @data.read_o(bits * 4 / 8 + 1) 278 279 str = *(header.unpack("@8B#{5 + bits * 4}")) 280 last = 5 281 x_min = Integer("0b#{str[last, bits]}") 282 x_max = Integer("0b#{str[(last + bits), bits]}") 283 y_min = Integer("0b#{str[(last + (2 * bits)), bits]}") 284 y_max = Integer("0b#{str[(last + (3 * bits)), bits]}") 285 @width = (x_max - x_min) / 20 286 @height = (y_max - y_min) / 20 287 end
measure_TIFF()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 296 def measure_TIFF 297 # 'v' little-endian 298 # 'n' default to big-endian 299 endian = (@data.read_o(4) =~ /II\x2a\x00/o) ? 'v' : 'n' 300 301 packspec = [ 302 nil, # nothing (shouldn't happen) 303 'C', # BYTE (8-bit unsigned integer) 304 nil, # ASCII 305 endian, # SHORT (16-bit unsigned integer) 306 endian.upcase, # LONG (32-bit unsigned integer) 307 nil, # RATIONAL 308 'c', # SBYTE (8-bit signed integer) 309 nil, # UNDEFINED 310 endian, # SSHORT (16-bit unsigned integer) 311 endian.upcase, # SLONG (32-bit unsigned integer) 312 ] 313 314 # Find the IFD location. 315 ifd_addr = *(@data.read_o(4).unpack(endian.upcase)) 316 # Get the number of entries in the IFD. 317 ifd = @data.read_o(2, ifd_addr) 318 num_dirent = *(ifd.unpack(endian)) # Make it useful 319 ifd_addr += 2 320 num_dirent = ifd_addr + (num_dirent * 12) # Calc. maximum offset of IFD 321 322 loop do 323 break if @width and @height 324 325 ifd = @data.read_o(12, ifd_addr) # Get directory entry. 326 break if ifd.nil? or ifd_addr > num_dirent 327 ifd_addr += 12 328 329 tag = *(ifd.unpack(endian)) # ...decode its tag 330 type = *(ifd[2, 2].unpack(endian)) # ... and data type 331 332 # Check the type for sanity. 333 next if type > packspec.size or packspec[type].nil? 334 335 case tag 336 when 0x0100, 0xa002 # width 337 @width = *(ifd[8, 4].unpack(packspec[type])) 338 when 0x0101, 0xa003 # height 339 @height = *(ifd[8, 4].unpack(packspec[type])) 340 end 341 end 342 end
measure_XBM()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 238 def measure_XBM 239 md = XBM_DIMENSIONS_RE.match(@data.read_o(1024)) 240 241 @width = md.captures[0].to_i 242 @height = md.captures[1].to_i 243 end
measure_XPM()
click to toggle source
# File lib/pdf/writer/graphics/imageinfo.rb 247 def measure_XPM 248 while line = @data.read_o(1024) 249 md = XPM_DIMENSIONS_RE.match(line) 250 if md 251 @width = md.captures[0].to_i 252 @height = md.captures[1].to_i 253 break 254 end 255 end 256 end