Class: Libpng::SimplifiedDecoder
- Inherits:
-
Object
- Object
- Libpng::SimplifiedDecoder
- Defined in:
- lib/libpng/simplified_decoder.rb
Overview
Decodes a PNG byte buffer into raw pixels via libpng's "simplified" read API (png_image_begin_read_from_memory + png_image_finish_read).
Also parses the byte buffer via ChunkWalker to populate DecodedImage#bit_depth, #color_type, #interlace (from IHDR), #text (from tEXt/zTXt/iTXt), and #color (from gAMA/cHRM/sRGB/iCCP). The simplified API itself drops these ancillary chunks on read -- walking them separately is the only way to surface their content.
One instance per decode call. Ractor-safe.
Instance Method Summary collapse
-
#call ⇒ Object
Returns a Libpng::DecodedImage.
-
#initialize(png, pixel_format: 'RGBA') ⇒ SimplifiedDecoder
constructor
A new instance of SimplifiedDecoder.
Constructor Details
#initialize(png, pixel_format: 'RGBA') ⇒ SimplifiedDecoder
Returns a new instance of SimplifiedDecoder.
15 16 17 18 19 20 21 22 |
# File 'lib/libpng/simplified_decoder.rb', line 15 def initialize(png, pixel_format: 'RGBA') raise Error, 'input PNG buffer is nil' if png.nil? raise Error, 'input PNG buffer must be a String' unless png.is_a?(String) @png = png @pixel_format = pixel_format raise Error, "unknown pixel_format #{@pixel_format.inspect}" unless format_value end |
Instance Method Details
#call ⇒ Object
Returns a Libpng::DecodedImage.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/libpng/simplified_decoder.rb', line 25 def call fmt = format_value img = FFI::MemoryPointer.new(:uint8, PNG_IMAGE_SIZE) img.clear img.put_uint32(PNG_IMAGE_OFF_VERSION, PNG_IMAGE_VERSION) FFI::MemoryPointer.new(:uint8, @png.bytesize) do |in_buf| in_buf.write_bytes(@png) ok = Libpng::Binding.png_image_begin_read_from_memory(img, in_buf, @png.bytesize) raise Error, "png_image_begin_read_from_memory failed: #{(img)}" if ok.zero? img.put_uint32(PNG_IMAGE_OFF_FORMAT, fmt) width = img.get_uint32(PNG_IMAGE_OFF_WIDTH) height = img.get_uint32(PNG_IMAGE_OFF_HEIGHT) stride = width * BytesPerPixel.for_format(fmt) out_size = stride * height FFI::MemoryPointer.new(:uint8, out_size) do |out_buf| ok = Libpng::Binding.png_image_finish_read(img, nil, out_buf, stride, nil) raise Error, "png_image_finish_read failed: #{(img)}" if ok.zero? return DecodedImage.new( width: width, height: height, format: @pixel_format.to_s.upcase, pixels: out_buf.read_bytes(out_size), ** ) end end ensure Libpng::Binding.png_image_free(img) unless img.nil? || img.null? end |