test7 works

main
Matthew Butterick 7 years ago
parent abbb36330d
commit 71dd3b0b23

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

@ -10,7 +10,7 @@
)))
(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
[(isBuffer? src) src]
;;else if src instanceof ArrayBuffer
@ -20,7 +20,7 @@
[else (file->bytes src)]))
(cond
[(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)))))
(make-object PNG data label)]
[else (raise-argument-error 'PDFImage-open "valid image format" src)]))

@ -1 +1,74 @@
#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)]))))
(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
(require rackunit)

@ -9,19 +9,17 @@
[width (· image width)]
[height (· image height)]
[imgData (· image imgData)]
[obj #f]
[document #f])
[obj #f])
(as-methods
embed))
(define/contract (embed this doc-in)
(object? . ->m . void?)
(set-field! document this doc-in)
(unless (· this obj)
(set-field! obj this
(send (· this document) ref
(send doc-in ref
(mhash 'Type "XObject"
'Subtype "Image"
'BitsPerComponent (· this image bits)
@ -30,7 +28,7 @@
'Filter "FlateDecode")))
(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)
'BitsPerComponent (· this image bits)
'Columns (· this width))))
@ -40,7 +38,7 @@
(cond
[(hash-ref (· this image) 'palette #f)
;; 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))
;; 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')
.fontSize(25)
.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()

@ -1,6 +1,6 @@
#lang pitfall/pdftest
(define-runtime-path death "death.png")
(define-runtime-path death "assets/death.png")
(define (proc 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