Class | PDF::Writer::Graphics::ImageInfo |
In: |
lib/pdf/writer/graphics/imageinfo.rb
|
Parent: | Object |
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.
Type | = | Formats |
JPEG_SOF_BLOCKS | = | %W(\xc0 \xc1 \xc2 \xc3 \xc5 \xc6 \xc7 \xc9 \xca \xcb \xcd \xce \xcf) |
JPEG_APP_BLOCKS | = | %W(\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef) |
XBM_DIMENSIONS_RE | = | %r{^\#define\s*\S*\s*(\d+)\s*\n\#define\s*\S*\s*(\d+)}mi |
XPM_DIMENSIONS_RE | = | %r<"\s*(\d+)\s+(\d+)(\s+\d+\s+\d+){1,2}\s*">m |
formats | -> | type_list |
format | -> | get_type |
height | -> | get_height |
width | -> | get_width |
bits | [R] | |
channels | [R] | |
format | [R] | |
height | [R] | |
info | [R] | |
width | [R] |
Receive image & make size. argument is image String or IO
# File lib/pdf/writer/graphics/imageinfo.rb, line 54 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 102 102: def discover_formatdiscover_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
# File lib/pdf/writer/graphics/imageinfo.rb, line 192 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 135 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 171 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 264 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 147 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 209 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 259 259: def measure_PSD 260: @width, @height = @data.read_o(26).unpack("x14NN") 261: end
The same as SWF, except that the original data is compressed with Zlib. Disabled for now.
# File lib/pdf/writer/graphics/imageinfo.rb, line 292 292: def measure_SWC 293: end
# File lib/pdf/writer/graphics/imageinfo.rb, line 272 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 296 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
# File lib/pdf/writer/graphics/imageinfo.rb, line 238 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