separation.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243
  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 "color-imp.h"
  24. #include "pixmap-imp.h"
  25. #include <assert.h>
  26. #include <string.h>
  27. enum
  28. {
  29. FZ_SEPARATION_DISABLED_RENDER = 3
  30. };
  31. struct fz_separations
  32. {
  33. int refs;
  34. int num_separations;
  35. int controllable;
  36. uint32_t state[(2*FZ_MAX_SEPARATIONS + 31) / 32];
  37. fz_colorspace *cs[FZ_MAX_SEPARATIONS];
  38. uint8_t cs_pos[FZ_MAX_SEPARATIONS];
  39. uint32_t rgba[FZ_MAX_SEPARATIONS];
  40. uint32_t cmyk[FZ_MAX_SEPARATIONS];
  41. char *name[FZ_MAX_SEPARATIONS];
  42. };
  43. fz_separations *fz_new_separations(fz_context *ctx, int controllable)
  44. {
  45. fz_separations *sep;
  46. sep = fz_malloc_struct(ctx, fz_separations);
  47. sep->refs = 1;
  48. sep->controllable = controllable;
  49. return sep;
  50. }
  51. fz_separations *fz_keep_separations(fz_context *ctx, fz_separations *sep)
  52. {
  53. return fz_keep_imp(ctx, sep, &sep->refs);
  54. }
  55. void fz_drop_separations(fz_context *ctx, fz_separations *sep)
  56. {
  57. if (fz_drop_imp(ctx, sep, &sep->refs))
  58. {
  59. int i;
  60. for (i = 0; i < sep->num_separations; i++)
  61. {
  62. fz_free(ctx, sep->name[i]);
  63. fz_drop_colorspace(ctx, sep->cs[i]);
  64. }
  65. fz_free(ctx, sep);
  66. }
  67. }
  68. void fz_add_separation(fz_context *ctx, fz_separations *sep, const char *name, fz_colorspace *cs, int colorant)
  69. {
  70. int n;
  71. if (!sep)
  72. fz_throw(ctx, FZ_ERROR_ARGUMENT, "can't add to non-existent separations");
  73. n = sep->num_separations;
  74. if (n == FZ_MAX_SEPARATIONS)
  75. fz_throw(ctx, FZ_ERROR_ARGUMENT, "too many separations");
  76. sep->name[n] = fz_strdup(ctx, name);
  77. sep->cs[n] = fz_keep_colorspace(ctx, cs);
  78. sep->cs_pos[n] = colorant;
  79. sep->num_separations++;
  80. }
  81. void fz_add_separation_equivalents(fz_context *ctx, fz_separations *sep, uint32_t rgba, uint32_t cmyk, const char *name)
  82. {
  83. int n;
  84. if (!sep)
  85. fz_throw(ctx, FZ_ERROR_ARGUMENT, "can't add to non-existent separations");
  86. n = sep->num_separations;
  87. if (n == FZ_MAX_SEPARATIONS)
  88. fz_throw(ctx, FZ_ERROR_ARGUMENT, "too many separations");
  89. sep->name[n] = fz_strdup(ctx, name);
  90. sep->rgba[n] = rgba;
  91. sep->cmyk[n] = cmyk;
  92. sep->num_separations++;
  93. }
  94. void fz_set_separation_behavior(fz_context *ctx, fz_separations *sep, int separation, fz_separation_behavior beh)
  95. {
  96. int shift;
  97. fz_separation_behavior old;
  98. if (!sep || separation < 0 || separation >= sep->num_separations)
  99. fz_throw(ctx, FZ_ERROR_ARGUMENT, "can't control non-existent separation");
  100. if (beh == FZ_SEPARATION_DISABLED && !sep->controllable)
  101. beh = FZ_SEPARATION_DISABLED_RENDER;
  102. shift = ((2*separation) & 31);
  103. separation >>= 4;
  104. old = (sep->state[separation]>>shift) & 3;
  105. if (old == (fz_separation_behavior)FZ_SEPARATION_DISABLED_RENDER)
  106. old = FZ_SEPARATION_DISABLED;
  107. /* If no change, great */
  108. if (old == beh)
  109. return;
  110. sep->state[separation] = (sep->state[separation] & ~(3<<shift)) | (beh<<shift);
  111. /* FIXME: Could only empty images from the store, or maybe only
  112. * images that depend on separations. */
  113. fz_empty_store(ctx);
  114. }
  115. static inline fz_separation_behavior
  116. sep_state(const fz_separations *sep, int i)
  117. {
  118. return (fz_separation_behavior)((sep->state[i>>5]>>((2*i) & 31)) & 3);
  119. }
  120. fz_separation_behavior fz_separation_current_behavior_internal(fz_context *ctx, const fz_separations *sep, int separation)
  121. {
  122. if (!sep || separation < 0 || separation >= sep->num_separations)
  123. fz_throw(ctx, FZ_ERROR_ARGUMENT, "can't disable non-existent separation");
  124. return sep_state(sep, separation);
  125. }
  126. fz_separation_behavior fz_separation_current_behavior(fz_context *ctx, const fz_separations *sep, int separation)
  127. {
  128. int beh = fz_separation_current_behavior_internal(ctx, sep, separation);
  129. if (beh == FZ_SEPARATION_DISABLED_RENDER)
  130. return FZ_SEPARATION_DISABLED;
  131. return beh;
  132. }
  133. const char *fz_separation_name(fz_context *ctx, const fz_separations *sep, int separation)
  134. {
  135. if (!sep || separation < 0 || separation >= sep->num_separations)
  136. fz_throw(ctx, FZ_ERROR_ARGUMENT, "can't access non-existent separation");
  137. return sep->name[separation];
  138. }
  139. int fz_count_separations(fz_context *ctx, const fz_separations *sep)
  140. {
  141. if (!sep)
  142. return 0;
  143. return sep->num_separations;
  144. }
  145. int fz_count_active_separations(fz_context *ctx, const fz_separations *sep)
  146. {
  147. int i, n, c;
  148. if (!sep)
  149. return 0;
  150. n = sep->num_separations;
  151. c = 0;
  152. for (i = 0; i < n; i++)
  153. if (sep_state(sep, i) == FZ_SEPARATION_SPOT)
  154. c++;
  155. return c;
  156. }
  157. int fz_compare_separations(fz_context *ctx, const fz_separations *sep1, const fz_separations *sep2)
  158. {
  159. int i, n1, n2;
  160. if (sep1 == sep2)
  161. return 0; /* Match */
  162. if (sep1 == NULL || sep2 == NULL)
  163. return 1; /* No match */
  164. n1 = sep1->num_separations;
  165. n2 = sep2->num_separations;
  166. if (n1 != n2)
  167. return 1; /* No match */
  168. if (sep1->controllable != sep2->controllable)
  169. return 1; /* No match */
  170. for (i = 0; i < n1; i++)
  171. {
  172. if (sep_state(sep1, i) != sep_state(sep2, i))
  173. return 1; /* No match */
  174. if (sep1->name[i] == NULL && sep2->name[i] == NULL)
  175. { /* Two unnamed separations match */ }
  176. else if (sep1->name[i] == NULL || sep2->name[i] == NULL || strcmp(sep1->name[i], sep2->name[i]))
  177. return 1; /* No match */
  178. if (sep1->cs[i] != sep2->cs[i] ||
  179. sep1->cs_pos[i] != sep2->cs_pos[i] ||
  180. sep1->rgba[i] != sep2->rgba[i] ||
  181. sep1->cmyk[i] != sep2->cmyk[i])
  182. return 1; /* No match */
  183. }
  184. return 0;
  185. }
  186. fz_separations *fz_clone_separations_for_overprint(fz_context *ctx, fz_separations *sep)
  187. {
  188. int i, j, n, c;
  189. fz_separations *clone;
  190. if (!sep)
  191. return NULL;
  192. n = sep->num_separations;
  193. if (n == 0)
  194. return NULL;
  195. c = 0;
  196. for (i = 0; i < n; i++)
  197. {
  198. fz_separation_behavior state = sep_state(sep, i);
  199. if (state == FZ_SEPARATION_COMPOSITE)
  200. c++;
  201. }
  202. /* If no composites, then we don't need to create a new seps object
  203. * with the composite ones enabled, so just reuse our current object. */
  204. if (c == 0)
  205. return fz_keep_separations(ctx, sep);
  206. /* We need to clone us a separation structure, with all
  207. * the composite separations marked as enabled. */
  208. clone = fz_malloc_struct(ctx, fz_separations);
  209. clone->refs = 1;
  210. clone->controllable = 0;
  211. fz_try(ctx)
  212. {
  213. for (i = 0; i < n; i++)
  214. {
  215. fz_separation_behavior beh = sep_state(sep, i);
  216. if (beh == FZ_SEPARATION_DISABLED)
  217. continue;
  218. j = clone->num_separations++;
  219. if (beh == FZ_SEPARATION_COMPOSITE)
  220. beh = FZ_SEPARATION_SPOT;
  221. fz_set_separation_behavior(ctx, clone, j, beh);
  222. clone->name[j] = sep->name[i] ? fz_strdup(ctx, sep->name[i]) : NULL;
  223. clone->cs[j] = fz_keep_colorspace(ctx, sep->cs[i]);
  224. clone->cs_pos[j] = sep->cs_pos[i];
  225. }
  226. }
  227. fz_catch(ctx)
  228. {
  229. fz_drop_separations(ctx, clone);
  230. fz_rethrow(ctx);
  231. }
  232. return clone;
  233. }
  234. fz_pixmap *
  235. fz_clone_pixmap_area_with_different_seps(fz_context *ctx, fz_pixmap *src, const fz_irect *bbox, fz_colorspace *dcs, fz_separations *dseps, fz_color_params color_params, fz_default_colorspaces *default_cs)
  236. {
  237. fz_irect local_bbox;
  238. fz_pixmap *dst, *pix;
  239. int drop_src = 0;
  240. if (bbox == NULL)
  241. {
  242. local_bbox.x0 = src->x;
  243. local_bbox.y0 = src->y;
  244. local_bbox.x1 = src->x + src->w;
  245. local_bbox.y1 = src->y + src->h;
  246. bbox = &local_bbox;
  247. }
  248. dst = fz_new_pixmap_with_bbox(ctx, dcs, *bbox, dseps, src->alpha);
  249. if (src->flags & FZ_PIXMAP_FLAG_INTERPOLATE)
  250. dst->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
  251. else
  252. dst->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
  253. if (fz_colorspace_is_indexed(ctx, src->colorspace))
  254. {
  255. src = fz_convert_indexed_pixmap_to_base(ctx, src);
  256. drop_src = 1;
  257. }
  258. fz_try(ctx)
  259. pix = fz_copy_pixmap_area_converting_seps(ctx, src, dst, NULL, color_params, default_cs);
  260. fz_always(ctx)
  261. if (drop_src)
  262. fz_drop_pixmap(ctx, src);
  263. fz_catch(ctx)
  264. {
  265. fz_drop_pixmap(ctx, dst);
  266. fz_rethrow(ctx);
  267. }
  268. return pix;
  269. }
  270. fz_pixmap *
  271. fz_copy_pixmap_area_converting_seps(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, fz_colorspace *prf, fz_color_params color_params, fz_default_colorspaces *default_cs)
  272. {
  273. int dw = dst->w;
  274. int dh = dst->h;
  275. fz_separations *sseps = src->seps;
  276. fz_separations *dseps = dst->seps;
  277. int sseps_n = sseps ? sseps->num_separations : 0;
  278. int dseps_n = dseps ? dseps->num_separations : 0;
  279. int sstride = src->stride;
  280. int dstride = dst->stride;
  281. int sn = src->n;
  282. int dn = dst->n;
  283. int sa = src->alpha;
  284. int da = dst->alpha;
  285. int ss = src->s;
  286. int ds = dst->s;
  287. int sc = sn - ss - sa;
  288. int dc = dn - ds - da;
  289. const unsigned char *sdata = src->samples + sstride * (dst->y - src->y) + (dst->x - src->x) * sn;
  290. unsigned char *ddata = dst->samples;
  291. int x, y, i, j, k, n;
  292. unsigned char mapped[FZ_MAX_COLORS];
  293. int unmapped = sseps_n;
  294. int src_is_device_n = fz_colorspace_is_device_n(ctx, src->colorspace);
  295. fz_colorspace *proof_cs = (prf == src->colorspace ? NULL : prf);
  296. assert(da == sa);
  297. assert(ss == fz_count_active_separations(ctx, sseps));
  298. assert(ds == fz_count_active_separations(ctx, dseps));
  299. dstride -= dn * dw;
  300. sstride -= sn * dw;
  301. if (dst->x < src->x || dst->x + dst->w > src->x + src->w ||
  302. dst->y < src->y || dst->y + dst->h > src->y + src-> h)
  303. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Cannot convert pixmap where dst is not within src!");
  304. /* Process colorants (and alpha) first */
  305. if (dst->colorspace == src->colorspace && proof_cs == NULL && dst->s == 0 && src->s == 0)
  306. {
  307. /* Simple copy - no spots to worry about. */
  308. unsigned char *dd = ddata;
  309. const unsigned char *sd = sdata;
  310. for (y = dh; y > 0; y--)
  311. {
  312. for (x = dw; x > 0; x--)
  313. {
  314. for (i = 0; i < dc; i++)
  315. dd[i] = sd[i];
  316. dd += dn;
  317. sd += sn;
  318. if (da)
  319. dd[-1] = sd[-1];
  320. }
  321. dd += dstride;
  322. sd += sstride;
  323. }
  324. }
  325. else if (src_is_device_n)
  326. {
  327. fz_color_converter cc;
  328. /* Init the target pixmap. */
  329. if (!da)
  330. {
  331. /* No alpha to worry about, just clear it. */
  332. fz_clear_pixmap(ctx, dst);
  333. }
  334. else if (fz_colorspace_is_subtractive(ctx, dst->colorspace))
  335. {
  336. /* Subtractive space, so copy the alpha, and set process and spot colors to 0. */
  337. unsigned char *dd = ddata;
  338. const unsigned char *sd = sdata;
  339. int dcs = dc + ds;
  340. for (y = dh; y > 0; y--)
  341. {
  342. for (x = dw; x > 0; x--)
  343. {
  344. for (i = 0; i < dcs; i++)
  345. dd[i] = 0;
  346. dd += dn;
  347. sd += sn;
  348. dd[-1] = sd[-1];
  349. }
  350. dd += dstride;
  351. sd += sstride;
  352. }
  353. }
  354. else
  355. {
  356. /* Additive space; tricky case. We need to copy the alpha, and
  357. * init the process colors "full", and the spots to 0. Because
  358. * we are in an additive space, and premultiplied, this means
  359. * setting the process colors to alpha. */
  360. unsigned char *dd = ddata;
  361. const unsigned char *sd = sdata + sn - 1;
  362. int dcs = dc + ds;
  363. for (y = dh; y > 0; y--)
  364. {
  365. for (x = dw; x > 0; x--)
  366. {
  367. int a = *sd;
  368. for (i = 0; i < dc; i++)
  369. dd[i] = a;
  370. for (; i < dcs; i++)
  371. dd[i] = 0;
  372. dd[i] = a;
  373. dd += dn;
  374. sd += sn;
  375. }
  376. dd += dstride;
  377. sd += sstride;
  378. }
  379. }
  380. /* Now map the colorants down. */
  381. n = fz_colorspace_n(ctx, src->colorspace);
  382. fz_find_color_converter(ctx, &cc, src->colorspace, dst->colorspace, NULL, proof_cs, color_params);
  383. fz_try(ctx)
  384. {
  385. unmapped = 0;
  386. for (i = 0; i < n; i++)
  387. {
  388. const char *name = fz_colorspace_colorant(ctx, src->colorspace, i);
  389. mapped[i] = 1;
  390. if (name)
  391. {
  392. if (!strcmp(name, "None")) {
  393. mapped[i] = 0;
  394. continue;
  395. }
  396. if (!strcmp(name, "All"))
  397. {
  398. int n1 = dn - da;
  399. unsigned char *dd = ddata;
  400. const unsigned char *sd = sdata + i;
  401. for (y = dh; y > 0; y--)
  402. {
  403. for (x = dw; x > 0; x--)
  404. {
  405. unsigned char v = *sd;
  406. sd += sn;
  407. for (k = 0; k < n1; k++)
  408. dd[k] = v;
  409. dd += dn;
  410. }
  411. dd += dstride;
  412. sd += sstride;
  413. }
  414. continue;
  415. }
  416. for (j = 0; j < dc; j++)
  417. {
  418. const char *dname = fz_colorspace_colorant(ctx, dst->colorspace, j);
  419. if (dname && !strcmp(name, dname))
  420. goto map_device_n_spot;
  421. }
  422. for (j = 0; j < dseps_n; j++)
  423. {
  424. const char *dname = dseps->name[j];
  425. if (dname && !strcmp(name, dname))
  426. {
  427. j += dc;
  428. goto map_device_n_spot;
  429. }
  430. }
  431. }
  432. if (0)
  433. {
  434. unsigned char *dd;
  435. const unsigned char *sd;
  436. map_device_n_spot:
  437. /* Directly map a devicen colorant to a
  438. * component (either process or spot)
  439. * in the destination. */
  440. dd = ddata + j;
  441. sd = sdata + i;
  442. for (y = dh; y > 0; y--)
  443. {
  444. for (x = dw; x > 0; x--)
  445. {
  446. *dd = *sd;
  447. dd += dn;
  448. sd += sn;
  449. }
  450. dd += dstride;
  451. sd += sstride;
  452. }
  453. }
  454. else
  455. {
  456. unmapped = 1;
  457. mapped[i] = 0;
  458. }
  459. }
  460. if (unmapped)
  461. {
  462. /* The standard spot mapping algorithm assumes that it's reasonable
  463. * to treat the components of deviceN spaces as being orthogonal,
  464. * and to add them together at the end. This avoids a color lookup
  465. * per pixel. The alternative mapping algorithm looks up each
  466. * pixel at a time, and is hence slower. */
  467. #define ALTERNATIVE_SPOT_MAP
  468. #ifndef ALTERNATIVE_SPOT_MAP
  469. for (i = 0; i < n; i++)
  470. {
  471. unsigned char *dd = ddata;
  472. const unsigned char *sd = sdata;
  473. float convert[FZ_MAX_COLORS];
  474. float colors[FZ_MAX_COLORS];
  475. if (mapped[i])
  476. continue;
  477. /* Src component i is not mapped. We need to convert that down. */
  478. memset(colors, 0, sizeof(float) * n);
  479. colors[i] = 1;
  480. cc.convert(ctx, &cc, colors, convert);
  481. if (fz_colorspace_is_subtractive(ctx, dst->colorspace))
  482. {
  483. if (sa)
  484. {
  485. for (y = dh; y > 0; y--)
  486. {
  487. for (x = dw; x > 0; x--)
  488. {
  489. unsigned char v = sd[i];
  490. sd += sn;
  491. if (v != 0)
  492. {
  493. int a = dd[-1];
  494. for (j = 0; j < dc; j++)
  495. dd[j] = fz_clampi(dd[j] + v * convert[j], 0, a);
  496. }
  497. dd += dn;
  498. }
  499. dd += dstride;
  500. sd += sstride;
  501. }
  502. }
  503. else
  504. {
  505. for (y = dh; y > 0; y--)
  506. {
  507. for (x = dw; x > 0; x--)
  508. {
  509. unsigned char v = sd[i];
  510. if (v != 0)
  511. {
  512. for (j = 0; j < dc; j++)
  513. dd[j] = fz_clampi(dd[j] + v * convert[j], 0, 255);
  514. }
  515. dd += dn;
  516. sd += sn;
  517. }
  518. dd += dstride;
  519. sd += sstride;
  520. }
  521. }
  522. }
  523. else
  524. {
  525. if (sa)
  526. {
  527. for (y = dh; y > 0; y--)
  528. {
  529. for (x = dw; x > 0; x--)
  530. {
  531. unsigned char v = sd[i];
  532. sd += sn;
  533. if (v != 0)
  534. {
  535. int a = sd[-1];
  536. for (j = 0; j < dc; j++)
  537. dd[j] = fz_clampi(dd[j] - v * (1-convert[j]), 0, a);
  538. }
  539. dd += dn;
  540. }
  541. dd += dstride;
  542. sd += sstride;
  543. }
  544. }
  545. else
  546. {
  547. for (y = dh; y > 0; y--)
  548. {
  549. for (x = dw; x > 0; x--)
  550. {
  551. unsigned char v = sd[i];
  552. if (v != 0)
  553. {
  554. for (j = 0; j < dc; j++)
  555. dd[j] = fz_clampi(dd[j] - v * (1-convert[j]), 0, 255);
  556. }
  557. dd += dn;
  558. sd += sn;
  559. }
  560. dd += dstride;
  561. sd += sstride;
  562. }
  563. }
  564. }
  565. }
  566. #else
  567. /* If space is subtractive then treat spots like Adobe does in Photoshop.
  568. * Which is to just use an equivalent CMYK value. If we are in an additive
  569. * color space we will need to convert on a pixel-by-pixel basis.
  570. */
  571. float convert[FZ_MAX_COLORS];
  572. float colors[FZ_MAX_COLORS];
  573. if (fz_colorspace_is_subtractive(ctx, dst->colorspace))
  574. {
  575. for (i = 0; i < n; i++)
  576. {
  577. unsigned char *dd = ddata;
  578. const unsigned char *sd = sdata;
  579. if (mapped[i])
  580. continue;
  581. memset(colors, 0, sizeof(float) * n);
  582. colors[i] = 1;
  583. cc.convert(ctx, &cc, colors, convert);
  584. if (sa)
  585. {
  586. for (y = dh; y > 0; y--)
  587. {
  588. for (x = dw; x > 0; x--)
  589. {
  590. unsigned char v = sd[i];
  591. if (v != 0)
  592. {
  593. unsigned char a = sd[sc];
  594. for (j = 0; j < dc; j++)
  595. dd[j] = fz_clampi(dd[j] + v * convert[j], 0, a);
  596. }
  597. dd += dn;
  598. sd += sn;
  599. }
  600. dd += dstride;
  601. sd += sstride;
  602. }
  603. }
  604. else
  605. {
  606. for (y = dh; y > 0; y--)
  607. {
  608. for (x = dw; x > 0; x--)
  609. {
  610. unsigned char v = sd[i];
  611. if (v != 0)
  612. for (j = 0; j < dc; j++)
  613. dd[j] = fz_clampi(dd[j] + v * convert[j], 0, 255);
  614. dd += dn;
  615. sd += sn;
  616. }
  617. dd += dstride;
  618. sd += sstride;
  619. }
  620. }
  621. }
  622. }
  623. else
  624. {
  625. unsigned char *dd = ddata;
  626. const unsigned char *sd = sdata;
  627. if (!sa)
  628. {
  629. for (y = dh; y > 0; y--)
  630. {
  631. for (x = dw; x > 0; x--)
  632. {
  633. for (j = 0; j < n; j++)
  634. colors[j] = mapped[j] ? 0 : sd[j] / 255.0f;
  635. cc.convert(ctx, &cc, colors, convert);
  636. for (j = 0; j < dc; j++)
  637. dd[j] = fz_clampi(255 * convert[j], 0, 255);
  638. dd += dn;
  639. sd += sn;
  640. }
  641. dd += dstride;
  642. sd += sstride;
  643. }
  644. }
  645. else
  646. {
  647. for (y = dh; y > 0; y--)
  648. {
  649. for (x = dw; x > 0; x--)
  650. {
  651. unsigned char a = sd[sc];
  652. if (a == 0)
  653. memset(dd, 0, dc);
  654. else
  655. {
  656. float inva = 1.0f/a;
  657. for (j = 0; j < n; j++)
  658. colors[j] = mapped[j] ? 0 : sd[j] * inva;
  659. cc.convert(ctx, &cc, colors, convert);
  660. for (j = 0; j < dc; j++)
  661. dd[j] = fz_clampi(a * convert[j], 0, a);
  662. }
  663. dd += dn;
  664. sd += sn;
  665. }
  666. dd += dstride;
  667. sd += sstride;
  668. }
  669. }
  670. }
  671. #endif
  672. }
  673. }
  674. fz_always(ctx)
  675. fz_drop_color_converter(ctx, &cc);
  676. fz_catch(ctx)
  677. fz_rethrow(ctx);
  678. }
  679. else
  680. {
  681. signed char map[FZ_MAX_COLORS];
  682. /* We have a special case here. Converting from CMYK + Spots
  683. * to RGB with less spots, involves folding (at least some of)
  684. * the spots down via their equivalent colors. Merging a spot's
  685. * equivalent colour (generally expressed in CMYK) with an RGB
  686. * one works badly, (presumably because RGB colors have
  687. * different linearity to CMYK ones). For best results we want
  688. * to merge the spots into the CMYK color, and then convert
  689. * that into RGB. We handle that case here. */
  690. if (fz_colorspace_is_subtractive(ctx, src->colorspace) &&
  691. !fz_colorspace_is_subtractive(ctx, dst->colorspace) &&
  692. src->seps > 0 &&
  693. fz_compare_separations(ctx, dst->seps, src->seps))
  694. {
  695. /* Converting from CMYK + Spots -> RGB with a change in spots. */
  696. fz_pixmap *temp = fz_new_pixmap(ctx, src->colorspace, src->w, src->h, dst->seps, dst->alpha);
  697. /* Match the regions exactly (this matters in particular when we are
  698. * using rotation, and the src region is not origined at 0,0 - see bug
  699. * 704726. */
  700. temp->x = src->x;
  701. temp->y = src->y;
  702. fz_try(ctx)
  703. {
  704. temp = fz_copy_pixmap_area_converting_seps(ctx, src, temp, prf, color_params, default_cs);
  705. dst = fz_copy_pixmap_area_converting_seps(ctx, temp, dst, NULL, color_params, default_cs);
  706. }
  707. fz_always(ctx)
  708. fz_drop_pixmap(ctx, temp);
  709. fz_catch(ctx)
  710. fz_rethrow(ctx);
  711. return dst;
  712. }
  713. /* Use a standard pixmap converter to convert the process + alpha. */
  714. fz_convert_pixmap_samples(ctx, src, dst, proof_cs, default_cs, fz_default_color_params, 0);
  715. /* And handle the spots ourselves. First make a map of what spots go where. */
  716. /* We want to set it up so that:
  717. * For each source spot, i, mapped[i] != 0 implies that it maps directly to a dest spot.
  718. * For each dest spot, j, map[j] = the source spot that goes there (or -1 if none).
  719. */
  720. for (i = 0; i < sseps_n; i++)
  721. mapped[i] = 0;
  722. for (i = 0; i < dseps_n; i++)
  723. {
  724. const char *name;
  725. int state = sep_state(dseps, i);
  726. map[i] = -1;
  727. if (state != FZ_SEPARATION_SPOT)
  728. continue;
  729. name = dseps->name[i];
  730. if (name == NULL)
  731. continue;
  732. for (j = 0; j < sseps_n; j++)
  733. {
  734. const char *sname;
  735. if (mapped[j])
  736. continue;
  737. if (sep_state(sseps, j) != FZ_SEPARATION_SPOT)
  738. continue;
  739. sname = sseps->name[j];
  740. if (sname && !strcmp(name, sname))
  741. {
  742. map[i] = j;
  743. unmapped--;
  744. mapped[j] = 1;
  745. break;
  746. }
  747. }
  748. }
  749. if (sa)
  750. map[i] = sseps_n;
  751. /* map[i] is now defined for all 0 <= i < dseps_n+sa */
  752. /* Now we need to make d[i] = map[i] < 0 : 0 ? s[map[i]] */
  753. if (ds)
  754. {
  755. unsigned char *dd = ddata + dc;
  756. const unsigned char *sd = sdata + sc;
  757. for (y = dh; y > 0; y--)
  758. {
  759. for (x = dw; x > 0; x--)
  760. {
  761. for (i = 0; i < ds; i++)
  762. dd[i] = map[i] < 0 ? 0 : sd[map[i]];
  763. dd += dn;
  764. sd += sn;
  765. }
  766. dd += dstride;
  767. sd += sstride;
  768. }
  769. }
  770. /* So that's all the process colors, the alpha, and the
  771. * directly mapped spots done. Now, are there any that
  772. * remain unmapped? */
  773. if (unmapped)
  774. {
  775. int m;
  776. /* Still need to handle mapping 'lost' spots down to process colors */
  777. for (i = -1, m = 0; m < sseps_n; m++)
  778. {
  779. float convert[FZ_MAX_COLORS];
  780. if (mapped[m])
  781. continue;
  782. if (fz_separation_current_behavior(ctx, sseps, m) != FZ_SEPARATION_SPOT)
  783. continue;
  784. i++;
  785. /* Src spot m (the i'th one) is not mapped. We need to convert that down. */
  786. fz_separation_equivalent(ctx, sseps, m, dst->colorspace, convert, proof_cs, color_params);
  787. if (fz_colorspace_is_subtractive(ctx, dst->colorspace))
  788. {
  789. if (fz_colorspace_is_subtractive(ctx, src->colorspace))
  790. {
  791. unsigned char *dd = ddata;
  792. const unsigned char *sd = sdata + sc;
  793. if (sa)
  794. {
  795. for (y = dh; y > 0; y--)
  796. {
  797. for (x = dw; x > 0; x--)
  798. {
  799. unsigned char v = sd[i];
  800. if (v != 0)
  801. {
  802. unsigned char a = sd[ss];
  803. for (k = 0; k < dc; k++)
  804. dd[k] = fz_clampi(dd[k] + v * convert[k], 0, a);
  805. }
  806. dd += dn;
  807. sd += sn;
  808. }
  809. dd += dstride;
  810. sd += sstride;
  811. }
  812. }
  813. else
  814. {
  815. /* This case is exercised by: -o out%d.pgm -r72 -D -F pgm -stm ../perf-testing-gpdl/pdf/Ad_InDesign.pdf */
  816. for (y = dh; y > 0; y--)
  817. {
  818. for (x = dw; x > 0; x--)
  819. {
  820. unsigned char v = sd[i];
  821. if (v != 0)
  822. for (k = 0; k < dc; k++)
  823. dd[k] = fz_clampi(dd[k] + v * convert[k], 0, 255);
  824. dd += dn;
  825. sd += sn;
  826. }
  827. dd += dstride;
  828. sd += sstride;
  829. }
  830. }
  831. }
  832. else
  833. {
  834. unsigned char *dd = ddata;
  835. const unsigned char *sd = sdata + sc;
  836. if (sa)
  837. {
  838. for (y = dh; y > 0; y--)
  839. {
  840. for (x = dw; x > 0; x--)
  841. {
  842. unsigned char v = sd[i];
  843. if (v != 0)
  844. {
  845. unsigned char a = sd[ss];
  846. for (k = 0; k < dc; k++)
  847. dd[k] = fz_clampi(dd[k] + v * convert[k], 0, a);
  848. }
  849. dd += dn;
  850. sd += sn;
  851. }
  852. dd += dstride;
  853. sd += sstride;
  854. }
  855. }
  856. else
  857. {
  858. /* This case is exercised by: -o out.pkm -r72 -D ../MyTests/Bug704778.pdf 1 */
  859. for (y = dh; y > 0; y--)
  860. {
  861. for (x = dw; x > 0; x--)
  862. {
  863. unsigned char v = sd[i];
  864. if (v != 0)
  865. for (k = 0; k < dc; k++)
  866. dd[k] = fz_clampi(dd[k] + v * convert[k], 0, 255);
  867. dd += dn;
  868. sd += sn;
  869. }
  870. dd += dstride;
  871. sd += sstride;
  872. }
  873. }
  874. }
  875. }
  876. else
  877. {
  878. for (k = 0; k < dc; k++)
  879. convert[k] = 1-convert[k];
  880. if (fz_colorspace_is_subtractive(ctx, src->colorspace))
  881. {
  882. unsigned char *dd = ddata;
  883. const unsigned char *sd = sdata + sc;
  884. if (sa)
  885. {
  886. for (y = dh; y > 0; y--)
  887. {
  888. for (x = dw; x > 0; x--)
  889. {
  890. unsigned char v = sd[i];
  891. if (v != 0)
  892. {
  893. unsigned char a = sd[ss];
  894. for (k = 0; k < dc; k++)
  895. dd[k] = fz_clampi(dd[k] - v * convert[k], 0, a);
  896. }
  897. dd += dn;
  898. sd += sn;
  899. }
  900. dd += dstride;
  901. sd += sstride;
  902. }
  903. }
  904. else
  905. {
  906. /* Nothing in the cluster tests this case. */
  907. for (y = dh; y > 0; y--)
  908. {
  909. for (x = dw; x > 0; x--)
  910. {
  911. unsigned char v = sd[i];
  912. if (v != 0)
  913. for (k = 0; k < dc; k++)
  914. dd[k] = fz_clampi(dd[k] - v * convert[k], 0, 255);
  915. dd += dn;
  916. sd += sn;
  917. }
  918. dd += dstride;
  919. sd += sstride;
  920. }
  921. }
  922. }
  923. else
  924. {
  925. unsigned char *dd = ddata;
  926. const unsigned char *sd = sdata + sc;
  927. if (sa)
  928. {
  929. for (y = dh; y > 0; y--)
  930. {
  931. for (x = dw; x > 0; x--)
  932. {
  933. unsigned char v = sd[i];
  934. if (v != 0)
  935. {
  936. unsigned char a = sd[ss];
  937. for (k = 0; k < dc; k++)
  938. dd[k] = fz_clampi(dd[k] - v * convert[k], 0, a);
  939. }
  940. dd += dn;
  941. sd += sn;
  942. }
  943. dd += dstride;
  944. sd += sstride;
  945. }
  946. }
  947. else
  948. {
  949. /* This case is exercised by: -o out.png -r72 -D ../MyTests/Bug704778.pdf 1 */
  950. for (y = dh; y > 0; y--)
  951. {
  952. for (x = dw; x > 0; x--)
  953. {
  954. unsigned char v = sd[i];
  955. if (v != 0)
  956. for (k = 0; k < dc; k++)
  957. dd[k] = fz_clampi(dd[k] - v * convert[k], 0, 255);
  958. dd += dn;
  959. sd += sn;
  960. }
  961. dd += dstride;
  962. sd += sstride;
  963. }
  964. }
  965. }
  966. }
  967. }
  968. }
  969. }
  970. return dst;
  971. }
  972. void
  973. fz_convert_separation_colors(fz_context *ctx,
  974. fz_colorspace *src_cs, const float *src_color,
  975. fz_separations *dst_seps, fz_colorspace *dst_cs, float *dst_color,
  976. fz_color_params color_params)
  977. {
  978. int i, j, n, dc, ds, dn, pred;
  979. float remainders[FZ_MAX_COLORS];
  980. int remaining = 0;
  981. assert(dst_cs && src_cs && dst_color && src_color);
  982. assert(fz_colorspace_is_device_n(ctx, src_cs));
  983. dc = fz_colorspace_n(ctx, dst_cs);
  984. ds = (dst_seps == NULL ? 0: dst_seps->num_separations);
  985. dn = dc + ds;
  986. i = 0;
  987. if (!fz_colorspace_is_subtractive(ctx, dst_cs))
  988. for (; i < dc; i++)
  989. dst_color[i] = 1;
  990. for (; i < dn; i++)
  991. dst_color[i] = 0;
  992. n = fz_colorspace_n(ctx, src_cs);
  993. pred = 0;
  994. for (i = 0; i < n; i++)
  995. {
  996. const char *name = fz_colorspace_colorant(ctx, src_cs, i);
  997. if (name == NULL)
  998. continue;
  999. if (i == 0 && !strcmp(name, "All"))
  1000. {
  1001. /* This is only supposed to happen in separation spaces, not DeviceN */
  1002. if (n != 1)
  1003. fz_warn(ctx, "All found in DeviceN space");
  1004. for (i = 0; i < dn; i++)
  1005. dst_color[i] = src_color[0];
  1006. break;
  1007. }
  1008. if (!strcmp(name, "None"))
  1009. continue;
  1010. /* The most common case is that the colorant we match is the
  1011. * one after the one we matched before, so optimise for that. */
  1012. for (j = pred; j < ds; j++)
  1013. {
  1014. const char *dname = dst_seps->name[j];
  1015. if (dname && !strcmp(name, dname))
  1016. goto found_sep;
  1017. }
  1018. for (j = 0; j < pred; j++)
  1019. {
  1020. const char *dname = dst_seps->name[j];
  1021. if (dname && !strcmp(name, dname))
  1022. goto found_sep;
  1023. }
  1024. for (j = 0; j < dc; j++)
  1025. {
  1026. const char *dname = fz_colorspace_colorant(ctx, dst_cs, j);
  1027. if (dname && !strcmp(name, dname))
  1028. goto found_process;
  1029. }
  1030. if (0) {
  1031. found_sep:
  1032. dst_color[j+dc] = src_color[i];
  1033. pred = j+1;
  1034. }
  1035. else if (0)
  1036. {
  1037. found_process:
  1038. dst_color[j] += src_color[i];
  1039. }
  1040. else
  1041. {
  1042. if (remaining == 0)
  1043. {
  1044. memset(remainders, 0, sizeof(float) * n);
  1045. remaining = 1;
  1046. }
  1047. remainders[i] = src_color[i];
  1048. }
  1049. }
  1050. if (remaining)
  1051. {
  1052. /* There were some spots that didn't copy over */
  1053. float converted[FZ_MAX_COLORS];
  1054. fz_convert_color(ctx, src_cs, remainders, dst_cs, converted, NULL, color_params);
  1055. for (i = 0; i < dc; i++)
  1056. dst_color[i] += converted[i];
  1057. }
  1058. }
  1059. void
  1060. fz_separation_equivalent(fz_context *ctx,
  1061. const fz_separations *seps,
  1062. int i,
  1063. fz_colorspace *dst_cs, float *convert,
  1064. fz_colorspace *prf,
  1065. fz_color_params color_params)
  1066. {
  1067. float colors[FZ_MAX_COLORS];
  1068. if (!seps->cs[i])
  1069. {
  1070. switch (fz_colorspace_n(ctx, dst_cs))
  1071. {
  1072. case 3:
  1073. convert[0] = (seps->rgba[i] & 0xff)/ 255.0f;
  1074. convert[1] = ((seps->rgba[i]>>8) & 0xff)/ 255.0f;
  1075. convert[2] = ((seps->rgba[i]>>16) & 0xff)/ 255.0f;
  1076. convert[3] = ((seps->rgba[i]>>24) & 0xff)/ 255.0f;
  1077. return;
  1078. case 4:
  1079. convert[0] = (seps->cmyk[i] & 0xff)/ 255.0f;
  1080. convert[1] = ((seps->cmyk[i]>>8) & 0xff)/ 255.0f;
  1081. convert[2] = ((seps->cmyk[i]>>16) & 0xff)/ 255.0f;
  1082. convert[3] = ((seps->cmyk[i]>>24) & 0xff)/ 255.0f;
  1083. return;
  1084. default:
  1085. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Cannot return equivalent in this colorspace");
  1086. }
  1087. }
  1088. memset(colors, 0, sizeof(float) * fz_colorspace_n(ctx, seps->cs[i]));
  1089. colors[seps->cs_pos[i]] = 1;
  1090. fz_convert_color(ctx, seps->cs[i], colors, dst_cs, convert, prf, color_params);
  1091. }
  1092. static void
  1093. convert_by_copying_separations(fz_context *ctx, fz_color_converter *cc, const float *src, float *dst)
  1094. {
  1095. int i, o;
  1096. int n = cc->dst_n;
  1097. fz_separations *dseps = (fz_separations *)cc->opaque;
  1098. for (i = 0; i < n; i++)
  1099. dst[i] = 0;
  1100. n = dseps->num_separations;
  1101. o = cc->ds->n;
  1102. for (i = 0; i < n; i++)
  1103. if (dseps->cs[i] == cc->ss)
  1104. dst[o+i] = src[dseps->cs_pos[i]];
  1105. }
  1106. int
  1107. fz_init_separation_copy_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *ss, fz_colorspace *ds, fz_separations *dseps, fz_colorspace *is, fz_color_params params)
  1108. {
  1109. int i, n;
  1110. /* No idea how to cope with intermediate space here. Bale. */
  1111. if (is != NULL && is != ss)
  1112. return 0;
  1113. /* If all the separations for ss are catered for in dseps, we can just copy the values. */
  1114. n = 0;
  1115. for (i = 0; i < dseps->num_separations; i++)
  1116. {
  1117. if (dseps->cs[i] == ss)
  1118. n++;
  1119. }
  1120. /* If all of the components of ss were found, we're happy. (We assume the destination space
  1121. * doesn't have any component twice.) */
  1122. if (n != ss->n)
  1123. return 0;
  1124. cc->ss = ss;
  1125. cc->ss_via = NULL;
  1126. cc->ds = ds;
  1127. cc->opaque = dseps;
  1128. cc->convert = convert_by_copying_separations;
  1129. return 1;
  1130. }