test7 works

main
Matthew Butterick 7 years ago
parent abbb36330d
commit 71dd3b0b23

@ -7,5 +7,6 @@
pitfall/test/test4 pitfall/test/test4
pitfall/test/test5 pitfall/test/test5
pitfall/test/test6 pitfall/test/test6
pitfall/test/test7
pitfall/page-test pitfall/page-test
(submod pitfall/zlib test))) (submod pitfall/zlib test)))

@ -10,7 +10,7 @@
))) )))
(define/contract (PDFImage-open src label) (define/contract (PDFImage-open src label)
(any/c any/c . -> . (or/c (is-a?/c PNG))) (any/c any/c . -> . (or/c (is-a?/c PNG) (is-a?/c JPEG)))
(define data (cond (define data (cond
[(isBuffer? src) src] [(isBuffer? src) src]
;;else if src instanceof ArrayBuffer ;;else if src instanceof ArrayBuffer
@ -20,7 +20,7 @@
[else (file->bytes src)])) [else (file->bytes src)]))
(cond (cond
[(equal? (subbytes data 0 2) (bytes #xff #xd8)) [(equal? (subbytes data 0 2) (bytes #xff #xd8))
(error 'do-jpeg-unimplemented)] (make-object JPEG data label)]
[(equal? (subbytes data 0 4) (apply bytes (cons #x89 (map char->integer '(#\P #\N #\G))))) [(equal? (subbytes data 0 4) (apply bytes (cons #x89 (map char->integer '(#\P #\N #\G)))))
(make-object PNG data label)] (make-object PNG data label)]
[else (raise-argument-error 'PDFImage-open "valid image format" src)])) [else (raise-argument-error 'PDFImage-open "valid image format" src)]))

@ -1 +1,74 @@
#lang pitfall/racket #lang pitfall/racket
(provide JPEG)
(define MARKERS '(#xffc0 #xffc1 #xffc2 #xffc3 #xffc5 #xffc6 #xffc7
#xffc8 #xffc9 #xffca #xffcb #xffcc #xffcd #xffce #xffcf))
(define-subclass object% (JPEG data [label #f])
(super-new)
(define last-ip (current-input-port))
(current-input-port (if (input-port? data)
data
(open-input-bytes data)))
(unless (equal? (read-16bit-integer) #xffd8)
(error 'JPEG "Start of Input marker byte not found"))
(define marker (let loop ([skip 0])
(read-bytes skip)
(define m (read-16bit-integer))
(if (memv m MARKERS)
m
(loop (read-16bit-integer (peek-bytes 2 0))))))
(read-16bit-integer)
(field [bits (read-byte)]
[height (read-16bit-integer)]
[width (read-16bit-integer)]
[channels (read-byte)]
[colorSpace (case channels
[(1) "DeviceGray"]
[(3) "DeviceRGB"]
[(4) "DeviceCMYK"])]
[obj #f])
(current-input-port last-ip)
(as-methods
embed))
(define (read-16bit-integer [bytes-or-port #f])
(define signed #f) (define big-endian #t)
(integer-bytes->integer (read-bytes 2 (cond
[(bytes? bytes-or-port)
(open-input-bytes bytes-or-port)]
[(port? bytes-or-port) bytes-or-port]
[else
(current-input-port)])) signed big-endian))
(define/contract (embed this doc-in)
(object? . ->m . void?)
(unless (· this obj)
(set-field! obj this
(send doc-in ref
(mhash
'Type "XObject"
'Subtype "Image"
'BitsPerComponent (· this bits)
'Width (· this width)
'Height (· this height)
'ColorSpace (· this colorSpace)
'Filter "DCTDecode")))
;; add extra decode params for CMYK images. By swapping the
;; min and max values from the default, we invert the colors. See
;; section 4.8.4 of the spec.
(when (equal? (· this colorSpace) "DeviceCMYK")
(hash-set! (· this obj payload) 'Decode '(1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0)))
(send (· this obj) end (· this data))))
(module+ test
(require rackunit)
(check-equal? (number->string (read-16bit-integer (bytes #x12 #x34 #x56)) 16) "1234")
(make-object JPEG (open-input-file "test/assets/test.jpeg")))

@ -47,7 +47,8 @@ Grab key chunks from PNG. Doesn't require heavy lifting from libpng.
(loop)])))) (loop)]))))
(define (read-32bit-integer) (define (read-32bit-integer)
(integer-bytes->integer (read-bytes 4) #t #t)) (define signed #f) (define big-endian #t)
(integer-bytes->integer (read-bytes 4) signed big-endian))
(module+ test (module+ test
(require rackunit) (require rackunit)

@ -9,19 +9,17 @@
[width (· image width)] [width (· image width)]
[height (· image height)] [height (· image height)]
[imgData (· image imgData)] [imgData (· image imgData)]
[obj #f] [obj #f])
[document #f])
(as-methods (as-methods
embed)) embed))
(define/contract (embed this doc-in) (define/contract (embed this doc-in)
(object? . ->m . void?) (object? . ->m . void?)
(set-field! document this doc-in)
(unless (· this obj) (unless (· this obj)
(set-field! obj this (set-field! obj this
(send (· this document) ref (send doc-in ref
(mhash 'Type "XObject" (mhash 'Type "XObject"
'Subtype "Image" 'Subtype "Image"
'BitsPerComponent (· this image bits) 'BitsPerComponent (· this image bits)
@ -30,7 +28,7 @@
'Filter "FlateDecode"))) 'Filter "FlateDecode")))
(unless (· this image hasAlphaChannel) (unless (· this image hasAlphaChannel)
(define params (send (· this document) ref (mhash 'Predictor 15 (define params (send doc-in ref (mhash 'Predictor 15
'Colors (· this image colors) 'Colors (· this image colors)
'BitsPerComponent (· this image bits) 'BitsPerComponent (· this image bits)
'Columns (· this width)))) 'Columns (· this width))))
@ -40,7 +38,7 @@
(cond (cond
[(hash-ref (· this image) 'palette #f) [(hash-ref (· this image) 'palette #f)
;; embed the color palette in the PDF as an object stream ;; embed the color palette in the PDF as an object stream
(define palette-ref (· this document ref)) (define palette-ref (· doc-in ref))
(send palette-ref end (· this image palette)) (send palette-ref end (· this image palette))
;; build the color space array for the image ;; build the color space array for the image

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

@ -0,0 +1,20 @@
PDFDocument = require 'pdfkit'
fs = require 'fs'
make = (doc) ->
# Set the font, draw some text, and embed an image
doc.font('Times-Italic')
.fontSize(25)
.text('Here comes a JPEG!', 100, 100, lineBreak: no)
.image('assets/test.jpeg', 100, 160, width: 412)
doc.end()
doc = new PDFDocument({compress: no})
doc.pipe(fs.createWriteStream('test5.pdf'))
make doc
doc = new PDFDocument({compress: yes})
doc.pipe(fs.createWriteStream('test5c.pdf'))
make doc

@ -6,7 +6,7 @@ make = (doc) ->
doc.font('Times-Italic') doc.font('Times-Italic')
.fontSize(25) .fontSize(25)
.text('Some fantastic text!', 100, 100, lineBreak: no) .text('Some fantastic text!', 100, 100, lineBreak: no)
.image('death.png', 100, 160, width: 412) .image('assets/death.png', 100, 160, width: 412)
doc.end() doc.end()

@ -1,6 +1,6 @@
#lang pitfall/pdftest #lang pitfall/pdftest
(define-runtime-path death "death.png") (define-runtime-path death "assets/death.png")
(define (proc doc) (define (proc doc)
(send* doc (send* doc

Binary file not shown.

@ -0,0 +1,16 @@
#lang pitfall/pdftest
(define-runtime-path test-jpeg "assets/test.jpeg")
(define (proc doc)
(send* doc
[font "Times-Italic"]
[fontSize 25]
[text "Here comes a JPEG!" 100 100 (hash 'lineBreak #f)]
[image test-jpeg 100 160 (hash 'width 412)]))
(define-runtime-path this "test7rkt.pdf")
(make-doc this #f proc)
(define-runtime-path that "test7crkt.pdf")
(make-doc that #t proc)

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save