output-psd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. // Copyright (C) 2004-2021 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include <string.h>
  24. void
  25. fz_save_pixmap_as_psd(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
  26. {
  27. fz_output *out = fz_new_output_with_path(ctx, filename, 0);
  28. fz_band_writer *writer = NULL;
  29. fz_var(writer);
  30. fz_try(ctx)
  31. {
  32. writer = fz_new_psd_band_writer(ctx, out);
  33. fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace, pixmap->seps);
  34. fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
  35. fz_close_band_writer(ctx, writer);
  36. fz_close_output(ctx, out);
  37. }
  38. fz_always(ctx)
  39. {
  40. fz_drop_band_writer(ctx, writer);
  41. fz_drop_output(ctx, out);
  42. }
  43. fz_catch(ctx)
  44. {
  45. fz_rethrow(ctx);
  46. }
  47. }
  48. void
  49. fz_write_pixmap_as_psd(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap)
  50. {
  51. fz_band_writer *writer;
  52. if (!out)
  53. return;
  54. writer = fz_new_psd_band_writer(ctx, out);
  55. fz_try(ctx)
  56. {
  57. fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace, pixmap->seps);
  58. fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
  59. fz_close_band_writer(ctx, writer);
  60. }
  61. fz_always(ctx)
  62. {
  63. fz_drop_band_writer(ctx, writer);
  64. }
  65. fz_catch(ctx)
  66. {
  67. fz_rethrow(ctx);
  68. }
  69. }
  70. typedef struct psd_band_writer_s
  71. {
  72. fz_band_writer super;
  73. int num_additive;
  74. } psd_band_writer;
  75. static void
  76. psd_write_header(fz_context *ctx, fz_band_writer *writer_, fz_colorspace *cs)
  77. {
  78. psd_band_writer *writer = (psd_band_writer *)(void *)writer_;
  79. fz_output *out = writer->super.out;
  80. int w = writer->super.w;
  81. int h = writer->super.h;
  82. int s = writer->super.s;
  83. int n = writer->super.n;
  84. int c = n - writer->super.alpha - s;
  85. fz_separations *seps = writer->super.seps;
  86. int i;
  87. size_t len;
  88. static const char psdsig[12] = { '8', 'B', 'P', 'S', 0, 1, 0, 0, 0, 0, 0, 0 };
  89. static const char ressig[4] = { '8', 'B', 'I', 'M' };
  90. unsigned char *data;
  91. size_t size;
  92. fz_colorspace *cs_cmyk = cs;
  93. #if FZ_ENABLE_ICC
  94. size = fz_buffer_storage(ctx, cs->u.icc.buffer, &data);
  95. #else
  96. size = 0;
  97. data = NULL;
  98. #endif
  99. if (cs->n != 4)
  100. cs_cmyk = fz_device_cmyk(ctx);
  101. if (!fz_colorspace_is_subtractive(ctx, cs))
  102. writer->num_additive = cs->n;
  103. /* File Header Section */
  104. fz_write_data(ctx, out, psdsig, 12);
  105. fz_write_int16_be(ctx, out, n);
  106. fz_write_int32_be(ctx, out, h);
  107. fz_write_int32_be(ctx, out, w);
  108. fz_write_int16_be(ctx, out, 8); /* bits per channel */
  109. switch (c)
  110. {
  111. case 0:
  112. case 1:
  113. fz_write_int16_be(ctx, out, 1); /* Greyscale */
  114. break;
  115. case 3:
  116. fz_write_int16_be(ctx, out, 3); /* RGB */
  117. break;
  118. case 4:
  119. fz_write_int16_be(ctx, out, 4); /* CMYK */
  120. break;
  121. default:
  122. fz_write_int16_be(ctx, out, 7); /* Multichannel */
  123. break;
  124. }
  125. /* Color Mode Data Section - empty */
  126. fz_write_int32_be(ctx, out, 0);
  127. /* Image Resources Section - Spot Names, Equivalent colors, resolution, ICC Profile */
  128. /* Spot names */
  129. len = 0;
  130. for (i = 0; i < s; i++)
  131. {
  132. const char *name = fz_separation_name(ctx, seps, i);
  133. char text[32];
  134. size_t len2;
  135. if (name == NULL)
  136. {
  137. fz_snprintf(text, sizeof text, "Spot%d", i-4);
  138. name = text;
  139. }
  140. len2 = strlen(name);
  141. if (len2 > 255)
  142. len2 = 255;
  143. len += len2 + 1;
  144. }
  145. /* Write the size of all the following resources */
  146. fz_write_int32_be(ctx, out,
  147. (s ? 12 + ((len + 1)&~1) : 0) + /* Spot Names */
  148. (s ? 12 + (14 * s) : 0) + /* DisplayInfo */
  149. 28 + /* Resolutions */
  150. (size ? (size+19)&~1 : 0)); /* ICC Profile */
  151. /* Spot names */
  152. if (s != 0)
  153. {
  154. fz_write_data(ctx, out, ressig, 4);
  155. fz_write_int16_be(ctx, out, 0x03EE);
  156. fz_write_int16_be(ctx, out, 0); /* PString */
  157. fz_write_int32_be(ctx, out, (len + 1)&~1);
  158. for (i = 0; i < s; i++) {
  159. size_t len2;
  160. const char *name = fz_separation_name(ctx, seps, i);
  161. char text[32];
  162. if (name == NULL)
  163. {
  164. fz_snprintf(text, sizeof text, "Spot%d", i-4);
  165. name = text;
  166. }
  167. len2 = strlen(name);
  168. if (len2 > 255)
  169. len2 = 255;
  170. fz_write_byte(ctx, out, (unsigned char)len2);
  171. fz_write_data(ctx, out, name, len2);
  172. }
  173. if (len & 1)
  174. {
  175. fz_write_byte(ctx, out, 0);
  176. }
  177. /* DisplayInfo - Colors for each spot channel */
  178. fz_write_data(ctx, out, ressig, 4);
  179. fz_write_int16_be(ctx, out, 0x03EF);
  180. fz_write_int16_be(ctx, out, 0); /* PString */
  181. fz_write_int32_be(ctx, out, 14 * s); /* Length */
  182. for (i = 0; i < s; i++) {
  183. float cmyk[4];
  184. fz_separation_equivalent(ctx, seps, i, cs_cmyk, cmyk, NULL, fz_default_color_params);
  185. fz_write_int16_be(ctx, out, 02); /* CMYK */
  186. /* PhotoShop stores all component values as if they were additive. */
  187. fz_write_int16_be(ctx, out, 65535 * (1-cmyk[0]));/* Cyan */
  188. fz_write_int16_be(ctx, out, 65535 * (1-cmyk[1]));/* Magenta */
  189. fz_write_int16_be(ctx, out, 65535 * (1-cmyk[2]));/* Yellow */
  190. fz_write_int16_be(ctx, out, 65535 * (1-cmyk[3]));/* Black */
  191. fz_write_int16_be(ctx, out, 0); /* Opacity 0 to 100 */
  192. fz_write_byte(ctx, out, 2); /* Don't know */
  193. fz_write_byte(ctx, out, 0); /* Padding - Always Zero */
  194. }
  195. }
  196. /* ICC Profile - (size + 19)&~1 bytes */
  197. if (size != 0)
  198. {
  199. /* Image Resource block */
  200. fz_write_data(ctx, out, ressig, 4);
  201. fz_write_int16_be(ctx, out, 0x40f); /* ICC Profile */
  202. fz_write_data(ctx, out, "\x07Profile", 8); /* Profile name (must be even!) */
  203. fz_write_int32_be(ctx, out, (int)size);
  204. fz_write_data(ctx, out, data, size); /* Actual data */
  205. if (size & 1)
  206. fz_write_byte(ctx, out, 0); /* Pad to even */
  207. }
  208. /* Image resolution - 28 bytes */
  209. fz_write_data(ctx, out, ressig, 4);
  210. fz_write_int16_be(ctx, out, 0x03ED);
  211. fz_write_int16_be(ctx, out, 0); /* PString */
  212. fz_write_int32_be(ctx, out, 16); /* Length */
  213. /* Resolution is specified as a fixed 16.16 bits */
  214. fz_write_int32_be(ctx, out, writer->super.xres);
  215. fz_write_int16_be(ctx, out, 1); /* width: 1 --> resolution is pixels per inch */
  216. fz_write_int16_be(ctx, out, 1); /* width: 1 --> resolution is pixels per inch */
  217. fz_write_int32_be(ctx, out, writer->super.yres);
  218. fz_write_int16_be(ctx, out, 1); /* height: 1 --> resolution is pixels per inch */
  219. fz_write_int16_be(ctx, out, 1); /* height: 1 --> resolution is pixels per inch */
  220. /* Layer and Mask Information Section */
  221. fz_write_int32_be(ctx, out, 0);
  222. /* Image Data Section */
  223. fz_write_int16_be(ctx, out, 0); /* Raw image data */
  224. }
  225. static void
  226. psd_invert_buffer(unsigned char *buffer, int size)
  227. {
  228. int k;
  229. for (k = 0; k < size; k++)
  230. buffer[k] = 255 - buffer[k];
  231. }
  232. static void
  233. psd_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_start, int band_height, const unsigned char *sp)
  234. {
  235. psd_band_writer *writer = (psd_band_writer *)(void *)writer_;
  236. fz_output *out = writer->super.out;
  237. int y, x, k, finalband;
  238. int w, h, n;
  239. unsigned char buffer[256];
  240. unsigned char *buffer_end = &buffer[sizeof(buffer)];
  241. unsigned char *b;
  242. int plane_inc;
  243. int line_skip;
  244. int num_additive = writer->num_additive;
  245. if (!out)
  246. return;
  247. w = writer->super.w;
  248. h = writer->super.h;
  249. n = writer->super.n;
  250. finalband = (band_start+band_height >= h);
  251. if (finalband)
  252. band_height = h - band_start;
  253. plane_inc = w * (h - band_height);
  254. line_skip = stride - w*n;
  255. b = buffer;
  256. if (writer->super.alpha)
  257. {
  258. const unsigned char *ap = &sp[n-1];
  259. for (k = 0; k < n-1; k++)
  260. {
  261. for (y = 0; y < band_height; y++)
  262. {
  263. for (x = 0; x < w; x++)
  264. {
  265. int a = *ap;
  266. ap += n;
  267. *b++ = a != 0 ? (*sp * 255 + 128)/a : 0;
  268. sp += n;
  269. if (b == buffer_end)
  270. {
  271. if (k >= num_additive)
  272. psd_invert_buffer(buffer, sizeof(buffer));
  273. fz_write_data(ctx, out, buffer, sizeof(buffer));
  274. b = buffer;
  275. }
  276. }
  277. sp += line_skip;
  278. ap += line_skip;
  279. }
  280. sp -= stride * (ptrdiff_t)band_height - 1;
  281. ap -= stride * (ptrdiff_t)band_height;
  282. if (b != buffer)
  283. {
  284. if (k >= num_additive)
  285. psd_invert_buffer(buffer, sizeof(buffer));
  286. fz_write_data(ctx, out, buffer, b - buffer);
  287. b = buffer;
  288. }
  289. fz_seek_output(ctx, out, plane_inc, SEEK_CUR);
  290. }
  291. for (y = 0; y < band_height; y++)
  292. {
  293. for (x = 0; x < w; x++)
  294. {
  295. *b++ = *sp;
  296. sp += n;
  297. if (b == buffer_end)
  298. {
  299. fz_write_data(ctx, out, buffer, sizeof(buffer));
  300. b = buffer;
  301. }
  302. }
  303. sp += line_skip;
  304. }
  305. if (b != buffer)
  306. {
  307. fz_write_data(ctx, out, buffer, b - buffer);
  308. b = buffer;
  309. }
  310. fz_seek_output(ctx, out, plane_inc, SEEK_CUR);
  311. }
  312. else
  313. {
  314. for (k = 0; k < n; k++)
  315. {
  316. for (y = 0; y < band_height; y++)
  317. {
  318. for (x = 0; x < w; x++)
  319. {
  320. *b++ = *sp;
  321. sp += n;
  322. if (b == buffer_end)
  323. {
  324. if (k >= num_additive)
  325. psd_invert_buffer(buffer, sizeof(buffer));
  326. fz_write_data(ctx, out, buffer, sizeof(buffer));
  327. b = buffer;
  328. }
  329. }
  330. sp += line_skip;
  331. }
  332. sp -= stride * (ptrdiff_t)band_height - 1;
  333. if (b != buffer)
  334. {
  335. if (k >= num_additive)
  336. psd_invert_buffer(buffer, sizeof(buffer));
  337. fz_write_data(ctx, out, buffer, b - buffer);
  338. b = buffer;
  339. }
  340. fz_seek_output(ctx, out, plane_inc, SEEK_CUR);
  341. }
  342. }
  343. fz_seek_output(ctx, out, w * (band_height - h * (int64_t)n), SEEK_CUR);
  344. }
  345. static void
  346. psd_write_trailer(fz_context *ctx, fz_band_writer *writer_)
  347. {
  348. psd_band_writer *writer = (psd_band_writer *)(void *)writer_;
  349. fz_output *out = writer->super.out;
  350. (void)out;
  351. (void)writer;
  352. }
  353. static void
  354. psd_drop_band_writer(fz_context *ctx, fz_band_writer *writer_)
  355. {
  356. psd_band_writer *writer = (psd_band_writer *)(void *)writer_;
  357. (void)writer;
  358. }
  359. fz_band_writer *fz_new_psd_band_writer(fz_context *ctx, fz_output *out)
  360. {
  361. psd_band_writer *writer = fz_new_band_writer(ctx, psd_band_writer, out);
  362. writer->super.header = psd_write_header;
  363. writer->super.band = psd_write_band;
  364. writer->super.trailer = psd_write_trailer;
  365. writer->super.drop = psd_drop_band_writer;
  366. writer->num_additive = 0;
  367. return &writer->super;
  368. }
  369. static fz_buffer *
  370. psd_from_pixmap(fz_context *ctx, fz_pixmap *pix, fz_color_params color_params, int drop)
  371. {
  372. fz_buffer *buf = NULL;
  373. fz_output *out = NULL;
  374. fz_var(buf);
  375. fz_var(out);
  376. fz_try(ctx)
  377. {
  378. buf = fz_new_buffer(ctx, 1024);
  379. out = fz_new_output_with_buffer(ctx, buf);
  380. fz_write_pixmap_as_psd(ctx, out, pix);
  381. fz_close_output(ctx, out);
  382. }
  383. fz_always(ctx)
  384. {
  385. if (drop)
  386. fz_drop_pixmap(ctx, pix);
  387. fz_drop_output(ctx, out);
  388. }
  389. fz_catch(ctx)
  390. {
  391. fz_drop_buffer(ctx, buf);
  392. fz_rethrow(ctx);
  393. }
  394. return buf;
  395. }
  396. fz_buffer *
  397. fz_new_buffer_from_image_as_psd(fz_context *ctx, fz_image *image, fz_color_params color_params)
  398. {
  399. fz_pixmap *pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL);
  400. return psd_from_pixmap(ctx, pix, color_params, 1);
  401. }
  402. fz_buffer *
  403. fz_new_buffer_from_pixmap_as_psd(fz_context *ctx, fz_pixmap *pix, fz_color_params color_params)
  404. {
  405. return psd_from_pixmap(ctx, pix, color_params, 0);
  406. }