Class: IiifPrint::JP2ImageMetadata
- Inherits:
-
Object
- Object
- IiifPrint::JP2ImageMetadata
- Defined in:
- lib/iiif_print/jp2_image_metadata.rb
Constant Summary collapse
- TOKEN_MARKER_START =
"\xFF".force_encoding("BINARY").freeze
- TOKEN_MARKER_SIZ =
"\x51".force_encoding("BINARY").freeze
- TOKEN_IHDR =
'ihdr'.freeze
Instance Attribute Summary collapse
-
#path ⇒ Object
Returns the value of attribute path.
Instance Method Summary collapse
-
#extract_jp2_components(io) ⇒ Array(Integer, Integer)
Number components, bits-per-component.
-
#extract_jp2_dim(io) ⇒ Array(Integer, Integer)
X size, Y size, in Integer-typed px.
-
#initialize(path) ⇒ JP2ImageMetadata
constructor
A new instance of JP2ImageMetadata.
-
#technical_metadata ⇒ Hash
Hash.
- #validate_jp2(io) ⇒ Object
Constructor Details
#initialize(path) ⇒ JP2ImageMetadata
Returns a new instance of JP2ImageMetadata.
9 10 11 |
# File 'lib/iiif_print/jp2_image_metadata.rb', line 9 def initialize(path) @path = path end |
Instance Attribute Details
#path ⇒ Object
Returns the value of attribute path.
7 8 9 |
# File 'lib/iiif_print/jp2_image_metadata.rb', line 7 def path @path end |
Instance Method Details
#extract_jp2_components(io) ⇒ Array(Integer, Integer)
Returns number components, bits-per-component.
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/iiif_print/jp2_image_metadata.rb', line 43 def extract_jp2_components(io) raise IOError, 'file not open in binary mode' unless io.binmode? io.seek(0, IO::SEEK_SET) # IHDR should be in first 64 bytes buffer = io.read(64) ihdr_data = buffer.split(TOKEN_IHDR)[-1] raise IOError if ihdr_data.nil? num_components = ihdr_data.byteslice(8, 2).unpack('n').first # stored as "bit depth of the components in the codestream, minus 1", so add 1 bits_per_component = ihdr_data.byteslice(10, 1).unpack('c').first + 1 [num_components, bits_per_component] end |
#extract_jp2_dim(io) ⇒ Array(Integer, Integer)
Returns X size, Y size, in Integer-typed px.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/iiif_print/jp2_image_metadata.rb', line 15 def extract_jp2_dim(io) raise IOError, 'file not open in binary mode' unless io.binmode? buffer = '' siz_found = false # Informed by ISO/IEC 15444-1:2000, pp. 26-27 # via: # http://hosting.astro.cornell.edu/~carcich/LRO/jp2/ISO_JPEG200_Standard/INCITS+ISO+IEC+15444-1-2000.pdf # # first 23 bytes are file-magic, we can skip io.seek(23, IO::SEEK_SET) while !siz_found && !buffer.nil? # read one byte at a time, until we hit marker start 0xFF buffer = io.read(1) while buffer != TOKEN_MARKER_START # - on 0xFF read subsequent byte; if value != 0x51, continue buffer = io.read(1) next if buffer != TOKEN_MARKER_SIZ # - on 0x51, read next 12 bytes buffer = io.read(12) siz_found = true end # discard first 4 bytes; next 4 bytes are XSiz; last 4 bytes are YSiz x_siz = buffer.byteslice(4, 4).unpack('N').first y_siz = buffer.byteslice(8, 4).unpack('N').first [x_siz, y_siz] end |
#technical_metadata ⇒ Hash
Returns hash.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/iiif_print/jp2_image_metadata.rb', line 64 def io = File.open(path, 'rb') io.seek(0, IO::SEEK_SET) validate_jp2(io) x_siz, y_siz = extract_jp2_dim(io) nc, bpc = extract_jp2_components(io) color = nc >= 3 ? 'color' : 'gray' io.close { color: bpc == 1 ? 'monochrome' : color, num_components: nc, bits_per_component: bpc, width: x_siz, height: y_siz } end |
#validate_jp2(io) ⇒ Object
56 57 58 59 60 |
# File 'lib/iiif_print/jp2_image_metadata.rb', line 56 def validate_jp2(io) # verify file is jp2 magic = io.read(23) raise IOError, 'Not JP2 file' unless magic.end_with?('ftypjp2') end |