|
|
|
@ -9,18 +9,19 @@ Grab key chunks from PNG. Doesn't require heavy lifting from libpng.
|
|
|
|
|
((or/c input-port? bytes?) . -> . hash?)
|
|
|
|
|
(define png (make-hasheq))
|
|
|
|
|
(parameterize ([current-input-port (if (input-port? ip-or-bytes)
|
|
|
|
|
ip-or-bytes
|
|
|
|
|
(open-input-bytes ip-or-bytes))])
|
|
|
|
|
ip-or-bytes
|
|
|
|
|
(open-input-bytes ip-or-bytes))])
|
|
|
|
|
(define header (read-bytes 8))
|
|
|
|
|
(let loop ()
|
|
|
|
|
(cond
|
|
|
|
|
[(eof-object? (peek-byte)) png]
|
|
|
|
|
[else
|
|
|
|
|
(define chunk-size (readUInt32))
|
|
|
|
|
(define chunk-size (read-32bit-integer))
|
|
|
|
|
(define chunk-name (read-bytes 4))
|
|
|
|
|
(case chunk-name
|
|
|
|
|
[(#"IHDR") (hash-set*! png 'width (readUInt32)
|
|
|
|
|
'height (readUInt32)
|
|
|
|
|
[(#"IHDR") (hash-set*! png
|
|
|
|
|
'width (read-32bit-integer)
|
|
|
|
|
'height (read-32bit-integer)
|
|
|
|
|
'bits (read-byte)
|
|
|
|
|
'colorType (read-byte)
|
|
|
|
|
'compressionMethod (read-byte)
|
|
|
|
@ -28,28 +29,28 @@ Grab key chunks from PNG. Doesn't require heavy lifting from libpng.
|
|
|
|
|
'interlaceMethod (read-byte))]
|
|
|
|
|
[(#"PLTE") (hash-set*! png 'palette (read-bytes chunk-size))]
|
|
|
|
|
[(#"IDAT") (hash-set*! png 'imgData (read-bytes chunk-size))]
|
|
|
|
|
[(#"tRNS") (read-bytes chunk-size)]
|
|
|
|
|
[(#"tEXt") (read-bytes chunk-size)]
|
|
|
|
|
[(#"IEND") (hash-set! png 'colors
|
|
|
|
|
(case (hash-ref png 'colorType)
|
|
|
|
|
[(0 3 4) 1]
|
|
|
|
|
[(2 6) 3]))
|
|
|
|
|
(hash-set! png 'hasAlphaChannel (member (hash-ref png 'colorType) '(4 6)))
|
|
|
|
|
(define colors (+ (hash-ref png 'colors) (if (hash-ref png 'hasAlphaChannel) 1 0)))
|
|
|
|
|
(hash-set! png 'pixelBitlength (* (hash-ref png 'bits) colors))
|
|
|
|
|
(hash-set! png 'colorSpace
|
|
|
|
|
(case (hash-ref png 'colors)
|
|
|
|
|
[(1) "DeviceGray"]
|
|
|
|
|
[(3) "DeviceRGB"]))]
|
|
|
|
|
[(#"tRNS") (read-bytes chunk-size)] ; todo implement this section
|
|
|
|
|
[(#"tEXt") (read-bytes chunk-size)] ; todo implement this section
|
|
|
|
|
[(#"IEND") (define color-value (case (hash-ref png 'colorType)
|
|
|
|
|
[(0 3 4) 1]
|
|
|
|
|
[(2 6) 3]))
|
|
|
|
|
(define alpha-value (member (hash-ref png 'colorType) '(4 6)))
|
|
|
|
|
(hash-set*! png
|
|
|
|
|
'colors color-value
|
|
|
|
|
'hasAlphaChannel alpha-value
|
|
|
|
|
'pixelBitlength (* (hash-ref png 'bits) (+ color-value (if alpha-value 1 0)))
|
|
|
|
|
'colorSpace (case color-value
|
|
|
|
|
[(1) "DeviceGray"]
|
|
|
|
|
[(3) "DeviceRGB"]))]
|
|
|
|
|
[else (read-bytes chunk-size)])
|
|
|
|
|
(read-bytes 4) ; skip crc
|
|
|
|
|
(loop)]))))
|
|
|
|
|
|
|
|
|
|
(define (readUInt32)
|
|
|
|
|
(define (read-32bit-integer)
|
|
|
|
|
(integer-bytes->integer (read-bytes 4) #t #t))
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(require rackunit)
|
|
|
|
|
(check-equal?
|
|
|
|
|
(read-png (open-input-file "test/assets/test.png"))
|
|
|
|
|
(read-png (file->bytes "test/assets/test.png"))))
|
|
|
|
|
(read-png (open-input-file "test/assets/test.png"))
|
|
|
|
|
(read-png (file->bytes "test/assets/test.png"))))
|