summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2017-06-15 19:08:10 +0100
committerRobin Watts <robin.watts@artifex.com>2017-06-22 14:59:48 +0100
commit5f0b9ee26becaf5153e8822cdc964b5d89050321 (patch)
tree7142ef56365ad9768d58e5402e66a2d3896e8a6c
parent2764ef8c0fd10d16a41842e8834efb1bd17e65d8 (diff)
downloadmupdf-5f0b9ee26becaf5153e8822cdc964b5d89050321.tar.xz
Add PSD device
-rw-r--r--include/mupdf/fitz.h1
-rw-r--r--include/mupdf/fitz/output-psd.h30
-rw-r--r--platform/win32/libmupdf.vcproj8
-rw-r--r--source/fitz/output-psd.c204
-rw-r--r--source/tools/mudraw.c12
5 files changed, 251 insertions, 4 deletions
diff --git a/include/mupdf/fitz.h b/include/mupdf/fitz.h
index c616e72c..76d8376e 100644
--- a/include/mupdf/fitz.h
+++ b/include/mupdf/fitz.h
@@ -65,6 +65,7 @@ extern "C" {
#include "mupdf/fitz/output-pwg.h"
#include "mupdf/fitz/output-pcl.h"
#include "mupdf/fitz/output-ps.h"
+#include "mupdf/fitz/output-psd.h"
#include "mupdf/fitz/output-svg.h"
#include "mupdf/fitz/output-tga.h"
diff --git a/include/mupdf/fitz/output-psd.h b/include/mupdf/fitz/output-psd.h
new file mode 100644
index 00000000..94fc01b5
--- /dev/null
+++ b/include/mupdf/fitz/output-psd.h
@@ -0,0 +1,30 @@
+#ifndef MUPDF_FITZ_OUTPUT_PSD_H
+#define MUPDF_FITZ_OUTPUT_PSD_H
+
+#include "mupdf/fitz/system.h"
+#include "mupdf/fitz/context.h"
+#include "mupdf/fitz/output.h"
+#include "mupdf/fitz/band-writer.h"
+#include "mupdf/fitz/pixmap.h"
+#include "mupdf/fitz/bitmap.h"
+
+#include "mupdf/fitz/buffer.h"
+#include "mupdf/fitz/image.h"
+
+/*
+ fz_save_pixmap_as_psd: Save a pixmap as a PSD image file.
+*/
+void fz_save_pixmap_as_psd(fz_context *ctx, fz_pixmap *pixmap, const char *filename);
+
+/*
+ Write a pixmap to an output stream in PSD format.
+*/
+void fz_write_pixmap_as_psd(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap);
+
+/*
+ fz_new_psd_band_writer: Obtain a fz_band_writer instance
+ for producing PSD output.
+*/
+fz_band_writer *fz_new_psd_band_writer(fz_context *ctx, fz_output *out);
+
+#endif
diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj
index 03784226..874cb3b4 100644
--- a/platform/win32/libmupdf.vcproj
+++ b/platform/win32/libmupdf.vcproj
@@ -1813,6 +1813,10 @@
>
</File>
<File
+ RelativePath="..\..\source\fitz\output-psd.c"
+ >
+ </File>
+ <File
RelativePath="..\..\source\fitz\output-pwg.c"
>
</File>
@@ -2400,6 +2404,10 @@
>
</File>
<File
+ RelativePath="..\..\include\mupdf\fitz\output-psd.h"
+ >
+ </File>
+ <File
RelativePath="..\..\include\mupdf\fitz\output-pwg.h"
>
</File>
diff --git a/source/fitz/output-psd.c b/source/fitz/output-psd.c
new file mode 100644
index 00000000..1c7adbc5
--- /dev/null
+++ b/source/fitz/output-psd.c
@@ -0,0 +1,204 @@
+#include "mupdf/fitz.h"
+
+void
+fz_save_pixmap_as_psd(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
+{
+ fz_output *out = fz_new_output_with_path(ctx, filename, 0);
+ fz_band_writer *writer = NULL;
+
+ fz_var(writer);
+
+ 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_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_band_writer(ctx, writer);
+ fz_drop_output(ctx, out);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+void
+fz_write_pixmap_as_psd(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap)
+{
+ fz_band_writer *writer;
+
+ if (!out)
+ return;
+
+ writer = fz_new_psd_band_writer(ctx, out);
+
+ 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_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_band_writer(ctx, writer);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+typedef struct psd_band_writer_s
+{
+ fz_band_writer super;
+} psd_band_writer;
+
+static void
+psd_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
+{
+ psd_band_writer *writer = (psd_band_writer *)(void *)writer_;
+ fz_output *out = writer->super.out;
+ int w = writer->super.w;
+ int h = writer->super.h;
+ int n = writer->super.n;
+ int alpha = writer->super.alpha;
+ 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);
+
+ /* 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)
+ {
+ case 0:
+ case 1:
+ fz_write_int16_be(ctx, out, 1); /* Greyscale */
+ break;
+ case 3:
+ fz_write_int16_be(ctx, out, 3); /* RGB */
+ break;
+ case 4:
+ fz_write_int16_be(ctx, out, 4); /* CMYK */
+ break;
+ default:
+ fz_write_int16_be(ctx, out, 7); /* Multichannel */
+ break;
+ }
+
+ /* 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
+ {
+ /* 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, data, size); /* Actual data */
+ if (size & 1)
+ fz_write_byte(ctx, out, 0); /* Pad to even */
+ }
+
+ /* Layer and Mask Information Section */
+ fz_write_int32_be(ctx, out, 0);
+
+ /* Image Data Section */
+ fz_write_int16_be(ctx, out, 0); /* Raw image data */
+}
+
+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_;
+ fz_output *out = writer->super.out;
+ int y, x, k, finalband;
+ int w, h, n;
+ unsigned char buffer[256];
+ unsigned char *buffer_end = &buffer[sizeof(buffer)];
+ unsigned char *b;
+ int plane_inc;
+ int line_skip;
+
+ if (!out)
+ return;
+
+ w = writer->super.w;
+ h = writer->super.h;
+ n = writer->super.n;
+
+ finalband = (band_start+band_height >= h);
+ if (finalband)
+ band_height = h - band_start;
+
+ plane_inc = w * (h - band_height);
+ line_skip = stride - w*n;
+ b = buffer;
+ for (k = 0; k < n; k++)
+ {
+ for (y = 0; y < band_height; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ *b++ = *sp;
+ sp += n;
+ if (b == buffer_end)
+ {
+ fz_write_data(ctx, out, buffer, sizeof(buffer));
+ b = buffer;
+ }
+ }
+ sp += line_skip;
+ }
+ sp -= stride * band_height - 1;
+ if (b != buffer)
+ {
+ fz_write_data(ctx, out, buffer, b - buffer);
+ b = buffer;
+ }
+ fz_seek_output(ctx, out, plane_inc, FZ_SEEK_CUR);
+ }
+ fz_seek_output(ctx, out, w * h * (1-n), FZ_SEEK_CUR);
+}
+
+static void
+psd_write_trailer(fz_context *ctx, fz_band_writer *writer_)
+{
+ psd_band_writer *writer = (psd_band_writer *)(void *)writer_;
+ fz_output *out = writer->super.out;
+
+ (void)out;
+ (void)writer;
+}
+
+static void
+psd_drop_band_writer(fz_context *ctx, fz_band_writer *writer_)
+{
+ psd_band_writer *writer = (psd_band_writer *)(void *)writer_;
+
+ (void)writer;
+}
+
+fz_band_writer *fz_new_psd_band_writer(fz_context *ctx, fz_output *out)
+{
+ psd_band_writer *writer = fz_new_band_writer(ctx, psd_band_writer, out);
+
+ writer->super.header = psd_write_header;
+ writer->super.band = psd_write_band;
+ writer->super.trailer = psd_write_trailer;
+ writer->super.drop = psd_drop_band_writer;
+
+ return &writer->super;
+}
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index aebe441e..34f9778f 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -30,7 +30,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz);
enum {
OUT_NONE,
OUT_PNG, OUT_TGA, OUT_PNM, OUT_PGM, OUT_PPM, OUT_PAM,
- OUT_PBM, OUT_PKM, OUT_PWG, OUT_PCL, OUT_PS,
+ OUT_PBM, OUT_PKM, OUT_PWG, OUT_PCL, OUT_PS, OUT_PSD,
OUT_TEXT, OUT_HTML, OUT_STEXT,
OUT_TRACE, OUT_SVG,
#if FZ_ENABLE_PDF
@@ -59,10 +59,11 @@ static const suffix_t suffix_table[] =
{ ".svg", OUT_SVG },
{ ".pwg", OUT_PWG },
{ ".pcl", OUT_PCL },
- { ".ps", OUT_PS },
#if FZ_ENABLE_PDF
{ ".pdf", OUT_PDF },
#endif
+ { ".psd", OUT_PSD },
+ { ".ps", OUT_PS },
{ ".tga", OUT_TGA },
{ ".txt", OUT_TEXT },
@@ -117,6 +118,7 @@ static const format_cs_table_t format_cs_table[] =
{ OUT_PWG, CS_RGB, { CS_MONO, CS_GRAY, CS_RGB, CS_CMYK } },
{ OUT_PCL, CS_MONO, { CS_MONO, CS_RGB } },
{ OUT_PS, CS_RGB, { CS_GRAY, CS_RGB, CS_CMYK } },
+ { OUT_PSD, CS_CMYK, { CS_GRAY, CS_GRAY_ALPHA, CS_RGB, CS_RGB_ALPHA, CS_CMYK, CS_CMYK_ALPHA } },
{ OUT_TGA, CS_RGB, { CS_GRAY, CS_GRAY_ALPHA, CS_RGB, CS_RGB_ALPHA } },
{ OUT_TRACE, CS_RGB, { CS_RGB } },
@@ -787,6 +789,8 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
bander = fz_new_pkm_band_writer(ctx, out);
else if (output_format == OUT_PS)
bander = fz_new_ps_band_writer(ctx, out);
+ else if (output_format == OUT_PSD)
+ bander = fz_new_psd_band_writer(ctx, out);
else if (output_format == OUT_TGA)
bander = fz_new_tga_band_writer(ctx, out, colorspace == fz_device_bgr(ctx));
else if (output_format == OUT_PWG)
@@ -1563,9 +1567,9 @@ int mudraw_main(int argc, char **argv)
if (band_height)
{
- if (output_format != OUT_PAM && output_format != OUT_PGM && output_format != OUT_PPM && output_format != OUT_PNM && output_format != OUT_PNG && output_format != OUT_PBM && output_format != OUT_PKM && output_format != OUT_PCL && output_format != OUT_PS)
+ if (output_format != OUT_PAM && output_format != OUT_PGM && output_format != OUT_PPM && output_format != OUT_PNM && output_format != OUT_PNG && output_format != OUT_PBM && output_format != OUT_PKM && output_format != OUT_PCL && output_format != OUT_PS && output_format != OUT_PSD)
{
- fprintf(stderr, "Banded operation only possible with PAM, PBM, PGM, PKM, PPM, PNM, PCL, PS and PNG outputs\n");
+ fprintf(stderr, "Banded operation only possible with PAM, PBM, PGM, PKM, PPM, PNM, PCL, PS, PSD and PNG outputs\n");
exit(1);
}
if (showmd5)