diff --git a/pitfall/pdfkit/lib/image/png.coffee b/pitfall/pdfkit/lib/image/png.coffee index 11090ed5..e5d3f088 100644 --- a/pitfall/pdfkit/lib/image/png.coffee +++ b/pitfall/pdfkit/lib/image/png.coffee @@ -3,10 +3,15 @@ PNG = require 'png-js' class PNGImage constructor: (data, @label) -> + console.log("raw data") + console.log(data.slice(0, 20)) @image = new PNG(data) @width = @image.width @height = @image.height @imgData = @image.imgData + console.log("result from png-js") + console.log(@imgData.slice(0, 20)) + console.log(@image) @obj = null embed: (@document) -> @@ -43,12 +48,14 @@ class PNGImage # For PNG color types 0, 2 and 3, the transparency data is stored in # a dedicated PNG chunk. if @image.transparency.grayscale + console.log("transparency.grayscale") # Use Color Key Masking (spec section 4.8.5) # An array with N elements, where N is two times the number of color components. val = @image.transparency.greyscale @obj.data['Mask'] = [val, val] else if @image.transparency.rgb + console.log("transparency.rgb") # Use Color Key Masking (spec section 4.8.5) # An array with N elements, where N is two times the number of color components. rgb = @image.transparency.rgb @@ -59,11 +66,13 @@ class PNGImage @obj.data['Mask'] = mask else if @image.transparency.indexed + console.log("transparency.indexed") # Create a transparency SMask for the image based on the data # in the PLTE and tRNS sections. See below for details on SMasks. @loadIndexedAlphaChannel() else if @image.hasAlphaChannel + console.log("alphachannel") # For PNG color types 4 and 6, the transparency data is stored as a alpha # channel mixed in with the main image data. Separate this data out into an # SMask object and store it separately in the PDF. @@ -88,6 +97,7 @@ class PNGImage @obj.data['SMask'] = sMask # add the actual image data + console.log(@imgData) @obj.end @imgData # free memory diff --git a/pitfall/pdfkit/node_modules/png-js/png-node.js b/pitfall/pdfkit/node_modules/png-js/png-node.js index 76a5a34d..313e553e 100644 --- a/pitfall/pdfkit/node_modules/png-js/png-node.js +++ b/pitfall/pdfkit/node_modules/png-js/png-node.js @@ -56,6 +56,8 @@ this.text = {}; while (true) { chunkSize = this.readUInt32(); + console.log("chunkSize") + console.log(chunkSize) section = ((function() { var _i, _results; _results = []; @@ -64,6 +66,8 @@ } return _results; }).call(this)).join(''); + console.log("section") + console.log(section) switch (section) { case 'IHDR': this.width = this.readUInt32(); diff --git a/pitfall/pdfkit/node_modules/png-js/png.coffee b/pitfall/pdfkit/node_modules/png-js/png.coffee index 80605640..2bcf3774 100644 --- a/pitfall/pdfkit/node_modules/png-js/png.coffee +++ b/pitfall/pdfkit/node_modules/png-js/png.coffee @@ -145,6 +145,8 @@ class PNG when 1 then 'DeviceGray' when 3 then 'DeviceRGB' + console.log("imgdata") + console.log(@imgData) @imgData = new Uint8Array @imgData return @@ -156,6 +158,8 @@ class PNG if @pos > @data.length throw new Error "Incomplete or corrupt PNG file" + + console.log("done parsing PNG") return diff --git a/pitfall/pdfkit/node_modules/png-js/png.js b/pitfall/pdfkit/node_modules/png-js/png.js deleted file mode 100644 index e3308ad0..00000000 --- a/pitfall/pdfkit/node_modules/png-js/png.js +++ /dev/null @@ -1,458 +0,0 @@ -// Generated by CoffeeScript 1.4.0 - -/* -# MIT LICENSE -# Copyright (c) 2011 Devon Govett -# -# Permission is hereby granted, free of charge, to any person obtaining a copy of this -# software and associated documentation files (the "Software"), to deal in the Software -# without restriction, including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -# to whom the Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all copies or -# substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - - -(function() { - var PNG; - - PNG = (function() { - var APNG_BLEND_OP_OVER, APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_NONE, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx; - - PNG.load = function(url, canvas, callback) { - var xhr, - _this = this; - if (typeof canvas === 'function') { - callback = canvas; - } - xhr = new XMLHttpRequest; - xhr.open("GET", url, true); - xhr.responseType = "arraybuffer"; - xhr.onload = function() { - var data, png; - data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer); - png = new PNG(data); - if (typeof (canvas != null ? canvas.getContext : void 0) === 'function') { - png.render(canvas); - } - return typeof callback === "function" ? callback(png) : void 0; - }; - return xhr.send(null); - }; - - APNG_DISPOSE_OP_NONE = 0; - - APNG_DISPOSE_OP_BACKGROUND = 1; - - APNG_DISPOSE_OP_PREVIOUS = 2; - - APNG_BLEND_OP_SOURCE = 0; - - APNG_BLEND_OP_OVER = 1; - - function PNG(data) { - var chunkSize, colors, delayDen, delayNum, frame, i, index, key, section, short, text, _i, _j, _ref; - this.data = data; - this.pos = 8; - this.palette = []; - this.imgData = []; - this.transparency = {}; - this.animation = null; - this.text = {}; - frame = null; - while (true) { - chunkSize = this.readUInt32(); - section = ((function() { - var _i, _results; - _results = []; - for (i = _i = 0; _i < 4; i = ++_i) { - _results.push(String.fromCharCode(this.data[this.pos++])); - } - return _results; - }).call(this)).join(''); - switch (section) { - case 'IHDR': - this.width = this.readUInt32(); - this.height = this.readUInt32(); - this.bits = this.data[this.pos++]; - this.colorType = this.data[this.pos++]; - this.compressionMethod = this.data[this.pos++]; - this.filterMethod = this.data[this.pos++]; - this.interlaceMethod = this.data[this.pos++]; - break; - case 'acTL': - this.animation = { - numFrames: this.readUInt32(), - numPlays: this.readUInt32() || Infinity, - frames: [] - }; - break; - case 'PLTE': - this.palette = this.read(chunkSize); - break; - case 'fcTL': - if (frame) { - this.animation.frames.push(frame); - } - this.pos += 4; - frame = { - width: this.readUInt32(), - height: this.readUInt32(), - xOffset: this.readUInt32(), - yOffset: this.readUInt32() - }; - delayNum = this.readUInt16(); - delayDen = this.readUInt16() || 100; - frame.delay = 1000 * delayNum / delayDen; - frame.disposeOp = this.data[this.pos++]; - frame.blendOp = this.data[this.pos++]; - frame.data = []; - break; - case 'IDAT': - case 'fdAT': - if (section === 'fdAT') { - this.pos += 4; - chunkSize -= 4; - } - data = (frame != null ? frame.data : void 0) || this.imgData; - for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) { - data.push(this.data[this.pos++]); - } - break; - case 'tRNS': - this.transparency = {}; - switch (this.colorType) { - case 3: - this.transparency.indexed = this.read(chunkSize); - short = 255 - this.transparency.indexed.length; - if (short > 0) { - for (i = _j = 0; 0 <= short ? _j < short : _j > short; i = 0 <= short ? ++_j : --_j) { - this.transparency.indexed.push(255); - } - } - break; - case 0: - this.transparency.grayscale = this.read(chunkSize)[0]; - break; - case 2: - this.transparency.rgb = this.read(chunkSize); - } - break; - case 'tEXt': - text = this.read(chunkSize); - index = text.indexOf(0); - key = String.fromCharCode.apply(String, text.slice(0, index)); - this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1)); - break; - case 'IEND': - if (frame) { - this.animation.frames.push(frame); - } - this.colors = (function() { - switch (this.colorType) { - case 0: - case 3: - case 4: - return 1; - case 2: - case 6: - return 3; - } - }).call(this); - this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6; - colors = this.colors + (this.hasAlphaChannel ? 1 : 0); - this.pixelBitlength = this.bits * colors; - this.colorSpace = (function() { - switch (this.colors) { - case 1: - return 'DeviceGray'; - case 3: - return 'DeviceRGB'; - } - }).call(this); - this.imgData = new Uint8Array(this.imgData); - return; - default: - this.pos += chunkSize; - } - this.pos += 4; - if (this.pos > this.data.length) { - throw new Error("Incomplete or corrupt PNG file"); - } - } - return; - } - - PNG.prototype.read = function(bytes) { - var i, _i, _results; - _results = []; - for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) { - _results.push(this.data[this.pos++]); - } - return _results; - }; - - PNG.prototype.readUInt32 = function() { - var b1, b2, b3, b4; - b1 = this.data[this.pos++] << 24; - b2 = this.data[this.pos++] << 16; - b3 = this.data[this.pos++] << 8; - b4 = this.data[this.pos++]; - return b1 | b2 | b3 | b4; - }; - - PNG.prototype.readUInt16 = function() { - var b1, b2; - b1 = this.data[this.pos++] << 8; - b2 = this.data[this.pos++]; - return b1 | b2; - }; - - PNG.prototype.decodePixels = function(data) { - var byte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m; - if (data == null) { - data = this.imgData; - } - if (data.length === 0) { - return new Uint8Array(0); - } - data = new FlateStream(data); - data = data.getBytes(); - pixelBytes = this.pixelBitlength / 8; - scanlineLength = pixelBytes * this.width; - pixels = new Uint8Array(scanlineLength * this.height); - length = data.length; - row = 0; - pos = 0; - c = 0; - while (pos < length) { - switch (data[pos++]) { - case 0: - for (i = _i = 0; _i < scanlineLength; i = _i += 1) { - pixels[c++] = data[pos++]; - } - break; - case 1: - for (i = _j = 0; _j < scanlineLength; i = _j += 1) { - byte = data[pos++]; - left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; - pixels[c++] = (byte + left) % 256; - } - break; - case 2: - for (i = _k = 0; _k < scanlineLength; i = _k += 1) { - byte = data[pos++]; - col = (i - (i % pixelBytes)) / pixelBytes; - upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; - pixels[c++] = (upper + byte) % 256; - } - break; - case 3: - for (i = _l = 0; _l < scanlineLength; i = _l += 1) { - byte = data[pos++]; - col = (i - (i % pixelBytes)) / pixelBytes; - left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; - upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; - pixels[c++] = (byte + Math.floor((left + upper) / 2)) % 256; - } - break; - case 4: - for (i = _m = 0; _m < scanlineLength; i = _m += 1) { - byte = data[pos++]; - col = (i - (i % pixelBytes)) / pixelBytes; - left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; - if (row === 0) { - upper = upperLeft = 0; - } else { - upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)]; - upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)]; - } - p = left + upper - upperLeft; - pa = Math.abs(p - left); - pb = Math.abs(p - upper); - pc = Math.abs(p - upperLeft); - if (pa <= pb && pa <= pc) { - paeth = left; - } else if (pb <= pc) { - paeth = upper; - } else { - paeth = upperLeft; - } - pixels[c++] = (byte + paeth) % 256; - } - break; - default: - throw new Error("Invalid filter algorithm: " + data[pos - 1]); - } - row++; - } - return pixels; - }; - - PNG.prototype.decodePalette = function() { - var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1; - palette = this.palette; - transparency = this.transparency.indexed || []; - ret = new Uint8Array((transparency.length || 0) + palette.length); - pos = 0; - length = palette.length; - c = 0; - for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) { - ret[pos++] = palette[i]; - ret[pos++] = palette[i + 1]; - ret[pos++] = palette[i + 2]; - ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255; - } - return ret; - }; - - PNG.prototype.copyToImageData = function(imageData, pixels) { - var alpha, colors, data, i, input, j, k, length, palette, v, _ref; - colors = this.colors; - palette = null; - alpha = this.hasAlphaChannel; - if (this.palette.length) { - palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette(); - colors = 4; - alpha = true; - } - data = imageData.data; - length = data.length; - input = palette || pixels; - i = j = 0; - if (colors === 1) { - while (i < length) { - k = palette ? pixels[i / 4] * 4 : j; - v = input[k++]; - data[i++] = v; - data[i++] = v; - data[i++] = v; - data[i++] = alpha ? input[k++] : 255; - j = k; - } - } else { - while (i < length) { - k = palette ? pixels[i / 4] * 4 : j; - data[i++] = input[k++]; - data[i++] = input[k++]; - data[i++] = input[k++]; - data[i++] = alpha ? input[k++] : 255; - j = k; - } - } - }; - - PNG.prototype.decode = function() { - var ret; - ret = new Uint8Array(this.width * this.height * 4); - this.copyToImageData(ret, this.decodePixels()); - return ret; - }; - - scratchCanvas = document.createElement('canvas'); - - scratchCtx = scratchCanvas.getContext('2d'); - - makeImage = function(imageData) { - var img; - scratchCtx.width = imageData.width; - scratchCtx.height = imageData.height; - scratchCtx.clearRect(0, 0, imageData.width, imageData.height); - scratchCtx.putImageData(imageData, 0, 0); - img = new Image; - img.src = scratchCanvas.toDataURL(); - return img; - }; - - PNG.prototype.decodeFrames = function(ctx) { - var frame, i, imageData, pixels, _i, _len, _ref, _results; - if (!this.animation) { - return; - } - _ref = this.animation.frames; - _results = []; - for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { - frame = _ref[i]; - imageData = ctx.createImageData(frame.width, frame.height); - pixels = this.decodePixels(new Uint8Array(frame.data)); - this.copyToImageData(imageData, pixels); - frame.imageData = imageData; - _results.push(frame.image = makeImage(imageData)); - } - return _results; - }; - - PNG.prototype.renderFrame = function(ctx, number) { - var frame, frames, prev; - frames = this.animation.frames; - frame = frames[number]; - prev = frames[number - 1]; - if (number === 0) { - ctx.clearRect(0, 0, this.width, this.height); - } - if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) { - ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height); - } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) { - ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset); - } - if (frame.blendOp === APNG_BLEND_OP_SOURCE) { - ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height); - } - return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset); - }; - - PNG.prototype.animate = function(ctx) { - var doFrame, frameNumber, frames, numFrames, numPlays, _ref, - _this = this; - frameNumber = 0; - _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays; - return (doFrame = function() { - var f, frame; - f = frameNumber++ % numFrames; - frame = frames[f]; - _this.renderFrame(ctx, f); - if (numFrames > 1 && frameNumber / numFrames < numPlays) { - return _this.animation._timeout = setTimeout(doFrame, frame.delay); - } - })(); - }; - - PNG.prototype.stopAnimation = function() { - var _ref; - return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0); - }; - - PNG.prototype.render = function(canvas) { - var ctx, data; - if (canvas._png) { - canvas._png.stopAnimation(); - } - canvas._png = this; - canvas.width = this.width; - canvas.height = this.height; - ctx = canvas.getContext("2d"); - if (this.animation) { - this.decodeFrames(ctx); - return this.animate(ctx); - } else { - data = ctx.createImageData(this.width, this.height); - this.copyToImageData(data, this.decodePixels()); - return ctx.putImageData(data, 0, 0); - } - }; - - return PNG; - - })(); - - window.PNG = PNG; - -}).call(this); diff --git a/pitfall/pitfall/document.rkt b/pitfall/pitfall/document.rkt index e8a8de96..d0871c75 100644 --- a/pitfall/pitfall/document.rkt +++ b/pitfall/pitfall/document.rkt @@ -127,7 +127,7 @@ (define/contract (_refEnd this ref) ((is-a?/c PDFReference) . ->m . void?) - (report* (· ref id) (· this _offsets)) + #;(report* (· ref id) (· this _offsets)) (hash-set! (· this _offsets) (· ref id) (· ref offset))) @@ -138,8 +138,8 @@ (define/contract (end this) ; called from source file to finish doc (->m void?) - (report* 'start-end) - (report* (· this _offsets)) + #;(report* 'start-end) + #;(report* (· this _offsets)) (flushPages this) (define _info (ref this)) @@ -147,18 +147,19 @@ ;; upgrade string literal to String struct (hash-set! (· _info payload) key (if (string? val) (String val) val))) - (report* (· this _offsets)) + + #;(report* (· this _offsets)) (· _info end) (for ([font (in-hash-values (· this _fontFamilies))]) (· font finalize)) - (report* (· this _offsets)) + #;(report* (· this _offsets)) (· this _root end) - (report* (· this _offsets)) + #;(report* (· this _offsets)) (· this _root payload Pages end) - (report* (· this _offsets)) + #;(report* (· this _offsets)) ;; generate xref (define xref-offset (· this _offset)) diff --git a/pitfall/pitfall/helper.rkt b/pitfall/pitfall/helper.rkt index d8eac67f..21e81968 100644 --- a/pitfall/pitfall/helper.rkt +++ b/pitfall/pitfall/helper.rkt @@ -1,5 +1,5 @@ #lang racket/base -(require (for-syntax racket/base racket/syntax) racket/class sugar/list racket/list (only-in br/list push! pop!) racket/string) +(require (for-syntax racket/base racket/syntax) racket/class sugar/list racket/list (only-in br/list push! pop!) racket/string racket/format) (provide (all-defined-out) push! pop!) (define-syntax (· stx) @@ -168,4 +168,11 @@ (define-syntax-rule (define-subclass CLASS-ID (SUBCLASS-ID INIT-FIELD ...) . EXPRS) (define SUBCLASS-ID (class CLASS-ID - (init-field INIT-FIELD ...) . EXPRS))) \ No newline at end of file + (init-field INIT-FIELD ...) . EXPRS))) + +(define (bytes->hex bstr) + (map (λ (b) (string->symbol (string-append (if (< b 16) + "x0" "x") (~r b #:base 16)))) (bytes->list bstr))) + +(module+ test + (check-equal? (bytes->hex #"PNG") '(x50 x4e x47))) \ No newline at end of file diff --git a/pitfall/pitfall/png-reader.rkt b/pitfall/pitfall/png-reader.rkt new file mode 100644 index 00000000..6553faf1 --- /dev/null +++ b/pitfall/pitfall/png-reader.rkt @@ -0,0 +1,55 @@ +#lang pitfall/racket +(provide read-png) + +#| +Grab key chunks from PNG. Doesn't require heavy lifting from libpng. +|# + +(define/contract (read-png ip-or-bytes) + ((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))]) + (define header (read-bytes 8)) + (let loop () + (cond + [(eof-object? (peek-byte)) png] + [else + (define chunk-size (readUInt32)) + (define chunk-name (read-bytes 4)) + (case chunk-name + [(#"IHDR") (hash-set*! png 'width (readUInt32) + 'height (readUInt32) + 'bits (read-byte) + 'colorType (read-byte) + 'compressionMethod (read-byte) + 'filterMethod (read-byte) + '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"]))] + [else (read-bytes chunk-size)]) + (read-bytes 4) ; skip crc + (loop)])))) + +(define (readUInt32) + (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")))) \ No newline at end of file diff --git a/pitfall/pitfall/png.rkt b/pitfall/pitfall/png.rkt index a86758b7..99d78db3 100644 --- a/pitfall/pitfall/png.rkt +++ b/pitfall/pitfall/png.rkt @@ -1,24 +1,20 @@ #lang pitfall/racket -(require racket/draw/unsafe/png racket/draw/private/bitmap) +(require "png-reader.rkt") (provide PNG) (define-subclass object% (PNG data label) (super-new) - (field [image (make-object bitmap% (open-input-bytes data) 'png)] - [width (· image get-width)] - [height (· image get-height)] - [imgData data] + (field [image (read-png data)] + [width (· image width)] + [height (· image height)] + [imgData (· image imgData)] [obj #f] - [document #f]) ; for `embed` + [document #f]) (as-methods - embed - finalize)) + embed)) - -(define png-grayscale 1) -(define png-color 3) (define/contract (embed this doc-in) (object? . ->m . void?) (set-field! document this doc-in) @@ -28,34 +24,34 @@ (send (· this document) ref (mhash 'Type "XObject" 'Subtype "Image" - 'BitsPerComponent (· this image get-depth) + 'BitsPerComponent (· this image bits) 'Width (· this width) 'Height (· this height) 'Filter "FlateDecode"))) - (define params (mhash)) - (unless (· this image has-alpha-channel?) - (set! params (send (· this document) ref (mhash 'Predictor 15 - 'Colors (if (· this image is-color?) - png-color - png-grayscale) - 'BitsPerComponent (· this image get-depth) - 'Columns (· this width))))) + (unless (· this image hasAlphaChannel) + (define params (send (· this document) ref (mhash 'Predictor 15 + 'Colors (· this image colors) + 'BitsPerComponent (· this image bits) + 'Columns (· this width)))) + (hash-set! (· this obj payload) 'DecodeParms params) + (send params end)) - - (hash-set! (· this obj payload) 'DecodeParms params) - (send params end) + (cond + [(hash-ref (· this image) 'palette #f) + ;; embed the color palette in the PDF as an object stream + (define palette-ref (· this document ref)) + (send palette-ref end (· this image palette)) - (send this finalize) + ;; build the color space array for the image + (hash-set! (· this object payload) 'Colorspace + (list "Indexed" "DeviceRGB" (sub1 (bytes-length (· this image palette))) palette-ref))] + [else (hash-set! (· this obj payload) 'ColorSpace "DeviceRGB")]) - #;(error 'stop-in-png:embed))) + -(define (finalize this) - ;; add the actual image data - (send (· this obj) end (· this imgData))) + ;; todo: transparency & alpha channel shit -#;(module+ test - (define data (file->bytes "test/assets/test.png")) - (define bm (make-object bitmap% (open-input-bytes data) 'png)) - bm) + ;; embed the actual image data + (send (· this obj) end (· this imgData)))) diff --git a/pitfall/pitfall/reference.rkt b/pitfall/pitfall/reference.rkt index 9860a38a..0f43161d 100644 --- a/pitfall/pitfall/reference.rkt +++ b/pitfall/pitfall/reference.rkt @@ -26,11 +26,11 @@ (when chunk (send this write chunk)) - (report* 'end! (· this id)) + #;(report* 'end! (· this id)) (define bstrs-to-write (let ([current-bstrs (reverse (· this byte-strings))]) - (if (and (or (compress-streams?) - (equal? (hash-ref (· this payload) 'Filter #f) "FlateDecode")) + (if (and (compress-streams?) + (not (hash-ref (· this payload) 'Filter #f)) (got-byte-strings? current-bstrs)) (let ([deflated-chunk (deflate (apply bytes-append current-bstrs))]) (hash-set! (· this payload) 'Filter "FlateDecode") @@ -53,7 +53,7 @@ (doc_write "\nendstream")) (doc_write "endobj")) - (report (· this id)) + #;(report (· this id)) (send this-doc _refEnd this)) diff --git a/pitfall/pitfall/test/test5.coffee b/pitfall/pitfall/test/test5.coffee index 0ab93a18..f01098e7 100644 --- a/pitfall/pitfall/test/test5.coffee +++ b/pitfall/pitfall/test/test5.coffee @@ -5,7 +5,7 @@ make = (doc) -> # Set the font, draw some text, and embed an image doc.font('Times-Italic') .fontSize(25) - .text('Some text with an embedded font!', 100, 100, lineBreak: no) + .text('Some fantastic text!', 100, 100, lineBreak: no) .image('death.png', 100, 160, width: 412) doc.end() @@ -14,7 +14,7 @@ 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 +doc = new PDFDocument({compress: yes}) +doc.pipe(fs.createWriteStream('test5c.pdf')) +make doc diff --git a/pitfall/pitfall/test/test5.pdf b/pitfall/pitfall/test/test5.pdf index 042173e5..6e8d1bd0 100644 Binary files a/pitfall/pitfall/test/test5.pdf and b/pitfall/pitfall/test/test5.pdf differ diff --git a/pitfall/pitfall/test/test5.rkt b/pitfall/pitfall/test/test5.rkt index 0e754ff3..ac7e3ed3 100644 --- a/pitfall/pitfall/test/test5.rkt +++ b/pitfall/pitfall/test/test5.rkt @@ -4,13 +4,11 @@ (send* doc [font "Times-Italic"] [fontSize 25] - [text "Some text with an embedded font!" 100 100 (hash 'lineBreak #f)] - [image "death.png" 100 160 (hash 'width 412)] - #;[image "assets/test.jpeg" 190 400 (hash 'height 300)])) + [text "Some fantastic text!" 100 100 (hash 'lineBreak #f)] + [image "death.png" 100 160 (hash 'width 412)])) (define-runtime-path this "test5rkt.pdf") -(make-doc this #f proc #:test #f) - -#;(define-runtime-path that "test5crkt.pdf") -#;(make-doc that #t proc) +(make-doc this #f proc #:test #t) +(define-runtime-path that "test5crkt.pdf") +(make-doc that #t proc) diff --git a/pitfall/pitfall/test/test5c.pdf b/pitfall/pitfall/test/test5c.pdf index b332743f..a947322f 100644 Binary files a/pitfall/pitfall/test/test5c.pdf and b/pitfall/pitfall/test/test5c.pdf differ diff --git a/pitfall/pitfall/test/test5crkt copy.pdf b/pitfall/pitfall/test/test5crkt copy.pdf new file mode 100644 index 00000000..1af043e4 Binary files /dev/null and b/pitfall/pitfall/test/test5crkt copy.pdf differ diff --git a/pitfall/pitfall/test/test5crkt.pdf b/pitfall/pitfall/test/test5crkt.pdf index e69de29b..1af043e4 100644 Binary files a/pitfall/pitfall/test/test5crkt.pdf and b/pitfall/pitfall/test/test5crkt.pdf differ diff --git a/pitfall/pitfall/test/test5rkt copy.pdf b/pitfall/pitfall/test/test5rkt copy.pdf new file mode 100644 index 00000000..ca62972b Binary files /dev/null and b/pitfall/pitfall/test/test5rkt copy.pdf differ diff --git a/pitfall/pitfall/test/test5rkt.pdf b/pitfall/pitfall/test/test5rkt.pdf index b3a70dc3..ca62972b 100644 Binary files a/pitfall/pitfall/test/test5rkt.pdf and b/pitfall/pitfall/test/test5rkt.pdf differ