diff options
Diffstat (limited to 'source/fitz/output-psd.c')
-rw-r--r-- | source/fitz/output-psd.c | 130 |
1 files changed, 119 insertions, 11 deletions
diff --git a/source/fitz/output-psd.c b/source/fitz/output-psd.c index 1c7adbc5..4d0f9574 100644 --- a/source/fitz/output-psd.c +++ b/source/fitz/output-psd.c @@ -11,7 +11,7 @@ fz_save_pixmap_as_psd(fz_context *ctx, fz_pixmap *pixmap, const char *filename) fz_try(ctx) { writer = fz_new_psd_band_writer(ctx, out); - fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace); + fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace, pixmap->seps); fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples); } fz_always(ctx) @@ -37,7 +37,7 @@ fz_write_pixmap_as_psd(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap) fz_try(ctx) { - fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace); + fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace, pixmap->seps); fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples); } fz_always(ctx) @@ -53,6 +53,7 @@ fz_write_pixmap_as_psd(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap) typedef struct psd_band_writer_s { fz_band_writer super; + int num_additive; } psd_band_writer; static void @@ -62,21 +63,29 @@ psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace * fz_output *out = writer->super.out; int w = writer->super.w; int h = writer->super.h; + int s = writer->super.s; int n = writer->super.n; - int alpha = writer->super.alpha; + int c = n - writer->super.alpha - s; + fz_separations *seps = writer->super.seps; + int i; + size_t len; static const char psdsig[12] = { '8', 'B', 'P', 'S', 0, 1, 0, 0, 0, 0, 0, 0 }; static const char ressig[4] = { '8', 'B', 'I', 'M' }; fz_buffer *buffer = fz_icc_data_from_icc_colorspace(ctx, cs); unsigned char *data; size_t size = fz_buffer_storage(ctx, buffer, &data); + if (!fz_colorspace_is_subtractive(ctx, cs)) + writer->num_additive = fz_colorspace_n(ctx, cs); + /* File Header Section */ fz_write_data(ctx, out, psdsig, 12); fz_write_int16_be(ctx, out, n); fz_write_int32_be(ctx, out, h); fz_write_int32_be(ctx, out, w); fz_write_int16_be(ctx, out, 8); /* bits per channel */ - switch (n - alpha) + + switch (c) { case 0: case 1: @@ -96,22 +105,105 @@ psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace * /* Color Mode Data Section - empty */ fz_write_int32_be(ctx, out, 0); - /* Image Resources Section */ - if (size == 0) - fz_write_int32_be(ctx, out, 0); - else + /* Image Resources Section - Spot Names, Equivalent colors, resolution, ICC Profile */ + /* Spot names */ + len = 0; + for (i = 0; i < s; i++) + { + const char *name = fz_get_separation(ctx, seps, i, NULL, NULL); + char text[32]; + size_t len2; + if (name == NULL) + { + sprintf(text, "Spot%d", i-4); + name = text; + } + len2 = strlen(name); + if (len2 > 255) + len2 = 255; + len += len2 + 1; + } + + /* Write the size of all the following resources */ + fz_write_int32_be(ctx, out, + (s ? 12 + ((len + 1)&~1) : 0) + /* Spot Names */ + (s ? 12 + (14 * s) : 0) + /* DisplayInfo */ + 28 + /* Resolutions */ + (size ? (size+19)&~1 : 0)); /* ICC Profile */ + + /* Spot names */ + if (s != 0) + { + fz_write_data(ctx, out, ressig, 4); + fz_write_int16_be(ctx, out , 0x03EE); + fz_write_int16_be(ctx, out, 0); /* PString */ + fz_write_int32_be(ctx, out, (len + 1)&~1); + for (i = 0; i < s; i++) { + size_t len2; + const char *name = fz_get_separation(ctx, seps, i, NULL, NULL); + char text[32]; + if (name == NULL) + { + sprintf(text, "Spot%d", i-4); + name = text; + } + len2 = strlen(name); + if (len2 > 255) + len2 = 255; + fz_write_byte(ctx, out, len2); + fz_write_data(ctx, out, name, len2); + } + if (len & 1) + { + fz_write_byte(ctx, out, 0); + } + + /* DisplayInfo - Colors for each spot channel */ + fz_write_data(ctx, out, ressig, 4); + fz_write_int16_be(ctx, out, 0x03EF); + fz_write_int16_be(ctx, out, 0); /* PString */ + fz_write_int32_be(ctx, out, 14 * s); /* Length */ + for (i = 0; i < s; i++) { + uint32_t cmyk; + (void)fz_get_separation(ctx, seps, i, NULL, &cmyk); + fz_write_int16_be(ctx, out, 02); /* CMYK */ + /* PhotoShop stores all component values as if they were additive. */ + fz_write_int16_be(ctx, out, 257 * (cmyk & 0xFF));/* Cyan */ + fz_write_int16_be(ctx, out, 257 * ((cmyk>>8) & 0xFF));/* Magenta */ + fz_write_int16_be(ctx, out, 257 * ((cmyk>>16) & 0xFF));/* Yellow */ + fz_write_int16_be(ctx, out, 257 * ((cmyk>>24) & 0xFF));/* Black */ + fz_write_int16_be(ctx, out, 0); /* Opacity 0 to 100 */ + fz_write_byte(ctx, out, 2); /* Don't know */ + fz_write_byte(ctx, out, 0); /* Padding - Always Zero */ + } + } + + /* ICC Profile - (size + 19)&~1 bytes */ + if (size != 0) { - /* ICC Profile */ - fz_write_int32_be(ctx, out, 4+2+8+size+(size&1)); /* Image Resource block */ fz_write_data(ctx, out, ressig, 4); fz_write_int16_be(ctx, out, 0x40f); /* ICC Profile */ - fz_write_data(ctx, out, "\0Profile", 8); /* Profile name (must be even!) */ + fz_write_data(ctx, out, "\x07Profile", 8); /* Profile name (must be even!) */ + fz_write_int32_be(ctx, out, size); fz_write_data(ctx, out, data, size); /* Actual data */ if (size & 1) fz_write_byte(ctx, out, 0); /* Pad to even */ } + /* Image resolution - 28 bytes */ + fz_write_data(ctx, out, ressig, 4); + fz_write_int16_be(ctx, out, 0x03ED); + fz_write_int16_be(ctx, out, 0); /* PString */ + fz_write_int32_be(ctx, out, 16); /* Length */ + /* Resolution is specified as a fixed 16.16 bits */ + fz_write_int32_be(ctx, out, writer->super.xres); + fz_write_int16_be(ctx, out, 1); /* width: 1 --> resolution is pixels per inch */ + fz_write_int16_be(ctx, out, 1); /* width: 1 --> resolution is pixels per inch */ + fz_write_int32_be(ctx, out, writer->super.yres); + fz_write_int16_be(ctx, out, 1); /* height: 1 --> resolution is pixels per inch */ + fz_write_int16_be(ctx, out, 1); /* height: 1 --> resolution is pixels per inch */ + /* Layer and Mask Information Section */ fz_write_int32_be(ctx, out, 0); @@ -120,6 +212,15 @@ psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace * } static void +psd_invert_buffer(unsigned char *buffer, int size) +{ + int k; + + for (k = 0; k < size; k++) + buffer[k] = 255 - buffer[k]; +} + +static void psd_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_start, int band_height, const unsigned char *sp) { psd_band_writer *writer = (psd_band_writer *)(void *)writer_; @@ -131,6 +232,7 @@ psd_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_st unsigned char *b; int plane_inc; int line_skip; + int num_additive = writer->num_additive; if (!out) return; @@ -156,6 +258,8 @@ psd_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_st sp += n; if (b == buffer_end) { + if (k >= num_additive) + psd_invert_buffer(buffer, sizeof(buffer)); fz_write_data(ctx, out, buffer, sizeof(buffer)); b = buffer; } @@ -165,6 +269,8 @@ psd_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_st sp -= stride * band_height - 1; if (b != buffer) { + if (k >= num_additive) + psd_invert_buffer(buffer, sizeof(buffer)); fz_write_data(ctx, out, buffer, b - buffer); b = buffer; } @@ -200,5 +306,7 @@ fz_band_writer *fz_new_psd_band_writer(fz_context *ctx, fz_output *out) writer->super.trailer = psd_write_trailer; writer->super.drop = psd_drop_band_writer; + writer->num_additive = 0; + return &writer->super; } |