summaryrefslogtreecommitdiff
path: root/source/fitz/output-psd.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/fitz/output-psd.c')
-rw-r--r--source/fitz/output-psd.c130
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;
}