pixmap.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051
  1. // Copyright (C) 2004-2025 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 <limits.h>
  27. #include <string.h>
  28. #include <math.h>
  29. #include <float.h>
  30. fz_pixmap *
  31. fz_keep_pixmap(fz_context *ctx, fz_pixmap *pix)
  32. {
  33. return fz_keep_storable(ctx, &pix->storable);
  34. }
  35. void
  36. fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix)
  37. {
  38. fz_drop_storable(ctx, &pix->storable);
  39. }
  40. void
  41. fz_drop_pixmap_imp(fz_context *ctx, fz_storable *pix_)
  42. {
  43. fz_pixmap *pix = (fz_pixmap *)pix_;
  44. fz_drop_colorspace(ctx, pix->colorspace);
  45. fz_drop_separations(ctx, pix->seps);
  46. if (pix->flags & FZ_PIXMAP_FLAG_FREE_SAMPLES)
  47. fz_free(ctx, pix->samples);
  48. fz_drop_pixmap(ctx, pix->underlying);
  49. fz_free(ctx, pix);
  50. }
  51. fz_pixmap *
  52. fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, fz_separations *seps, int alpha, int stride, unsigned char *samples)
  53. {
  54. fz_pixmap *pix;
  55. int s = fz_count_active_separations(ctx, seps);
  56. int n;
  57. if (w < 0 || h < 0)
  58. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Illegal dimensions for pixmap %d %d", w, h);
  59. n = alpha + s + fz_colorspace_n(ctx, colorspace);
  60. if (stride < n*w && stride > -n*w)
  61. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Illegal stride for pixmap (n=%d w=%d, stride=%d)", n, w, stride);
  62. if (samples == NULL && stride < n*w)
  63. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Illegal -ve stride for pixmap without data");
  64. if (n > FZ_MAX_COLORS)
  65. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Illegal number of colorants");
  66. pix = fz_malloc_struct(ctx, fz_pixmap);
  67. FZ_INIT_STORABLE(pix, 1, fz_drop_pixmap_imp);
  68. pix->x = 0;
  69. pix->y = 0;
  70. pix->w = w;
  71. pix->h = h;
  72. pix->alpha = alpha = !!alpha;
  73. pix->flags = FZ_PIXMAP_FLAG_INTERPOLATE;
  74. pix->xres = 96;
  75. pix->yres = 96;
  76. pix->colorspace = NULL;
  77. pix->n = n;
  78. pix->s = s;
  79. pix->seps = fz_keep_separations(ctx, seps);
  80. pix->stride = stride;
  81. if (colorspace)
  82. {
  83. pix->colorspace = fz_keep_colorspace(ctx, colorspace);
  84. }
  85. else
  86. {
  87. assert(alpha || s);
  88. }
  89. pix->samples = samples;
  90. if (!samples && pix->h > 0 && pix->w > 0)
  91. {
  92. fz_try(ctx)
  93. {
  94. if ((size_t)pix->stride > SIZE_MAX / (size_t)pix->h)
  95. fz_throw(ctx, FZ_ERROR_LIMIT, "Overly large image");
  96. pix->samples = Memento_label(fz_malloc(ctx, pix->h * pix->stride), "pixmap_data");
  97. }
  98. fz_catch(ctx)
  99. {
  100. fz_drop_separations(ctx, pix->seps);
  101. fz_drop_colorspace(ctx, pix->colorspace);
  102. fz_free(ctx, pix);
  103. fz_rethrow(ctx);
  104. }
  105. pix->flags |= FZ_PIXMAP_FLAG_FREE_SAMPLES;
  106. }
  107. return pix;
  108. }
  109. fz_pixmap *
  110. fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h, fz_separations *seps, int alpha)
  111. {
  112. int stride;
  113. int s = fz_count_active_separations(ctx, seps);
  114. int n;
  115. if (!colorspace && s == 0) alpha = 1;
  116. n = fz_colorspace_n(ctx, colorspace) + s + alpha;
  117. if (w > INT_MAX / n)
  118. fz_throw(ctx, FZ_ERROR_LIMIT, "Overly wide image");
  119. stride = n * w;
  120. return fz_new_pixmap_with_data(ctx, colorspace, w, h, seps, alpha, stride, NULL);
  121. }
  122. fz_pixmap *
  123. fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_irect bbox, fz_separations *seps, int alpha)
  124. {
  125. fz_pixmap *pixmap;
  126. pixmap = fz_new_pixmap(ctx, colorspace, fz_irect_width(bbox), fz_irect_height(bbox), seps, alpha);
  127. pixmap->x = bbox.x0;
  128. pixmap->y = bbox.y0;
  129. return pixmap;
  130. }
  131. fz_pixmap *
  132. fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_irect bbox, fz_separations *seps, int alpha, unsigned char *samples)
  133. {
  134. int w = fz_irect_width(bbox);
  135. int stride;
  136. int s = fz_count_active_separations(ctx, seps);
  137. fz_pixmap *pixmap;
  138. if (!colorspace && s == 0) alpha = 1;
  139. stride = (fz_colorspace_n(ctx, colorspace) + s + alpha) * w;
  140. pixmap = fz_new_pixmap_with_data(ctx, colorspace, w, fz_irect_height(bbox), seps, alpha, stride, samples);
  141. pixmap->x = bbox.x0;
  142. pixmap->y = bbox.y0;
  143. return pixmap;
  144. }
  145. fz_pixmap *fz_new_pixmap_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, const fz_irect *rect)
  146. {
  147. fz_irect local_rect;
  148. fz_pixmap *subpix;
  149. if (!pixmap)
  150. return NULL;
  151. if (rect == NULL)
  152. {
  153. rect = &local_rect;
  154. local_rect.x0 = pixmap->x;
  155. local_rect.y0 = pixmap->y;
  156. local_rect.x1 = pixmap->x + pixmap->w;
  157. local_rect.y1 = pixmap->y + pixmap->h;
  158. }
  159. else if (rect->x0 < pixmap->x || rect->y0 < pixmap->y || rect->x1 > pixmap->x + pixmap->w || rect->y1 > pixmap->y + pixmap->h)
  160. fz_throw(ctx, FZ_ERROR_ARGUMENT, "Pixmap region is not a subarea");
  161. subpix = fz_malloc_struct(ctx, fz_pixmap);
  162. *subpix = *pixmap;
  163. subpix->storable.refs = 1;
  164. subpix->x = rect->x0;
  165. subpix->y = rect->y0;
  166. subpix->w = fz_irect_width(*rect);
  167. subpix->h = fz_irect_height(*rect);
  168. subpix->samples += (rect->x0 - pixmap->x) + (rect->y0 - pixmap->y) * pixmap->stride;
  169. subpix->underlying = fz_keep_pixmap(ctx, pixmap);
  170. subpix->colorspace = fz_keep_colorspace(ctx, pixmap->colorspace);
  171. subpix->seps = fz_keep_separations(ctx, pixmap->seps);
  172. subpix->flags &= ~FZ_PIXMAP_FLAG_FREE_SAMPLES;
  173. return subpix;
  174. }
  175. fz_pixmap *fz_clone_pixmap(fz_context *ctx, const fz_pixmap *old)
  176. {
  177. fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, old->colorspace, fz_make_irect(old->x, old->y, old->w, old->h), old->seps, old->alpha);
  178. memcpy(pix->samples, old->samples, pix->stride * pix->h);
  179. return pix;
  180. }
  181. fz_irect
  182. fz_pixmap_bbox(fz_context *ctx, const fz_pixmap *pix)
  183. {
  184. fz_irect bbox;
  185. bbox.x0 = pix->x;
  186. bbox.y0 = pix->y;
  187. bbox.x1 = pix->x + pix->w;
  188. bbox.y1 = pix->y + pix->h;
  189. return bbox;
  190. }
  191. fz_irect
  192. fz_pixmap_bbox_no_ctx(const fz_pixmap *pix)
  193. {
  194. fz_irect bbox;
  195. bbox.x0 = pix->x;
  196. bbox.y0 = pix->y;
  197. bbox.x1 = pix->x + pix->w;
  198. bbox.y1 = pix->y + pix->h;
  199. return bbox;
  200. }
  201. fz_colorspace *
  202. fz_pixmap_colorspace(fz_context *ctx, const fz_pixmap *pix)
  203. {
  204. if (!pix)
  205. return NULL;
  206. return pix->colorspace;
  207. }
  208. int
  209. fz_pixmap_x(fz_context *ctx, const fz_pixmap *pix)
  210. {
  211. return pix->x;
  212. }
  213. int
  214. fz_pixmap_y(fz_context *ctx, const fz_pixmap *pix)
  215. {
  216. return pix->y;
  217. }
  218. int
  219. fz_pixmap_width(fz_context *ctx, const fz_pixmap *pix)
  220. {
  221. return pix->w;
  222. }
  223. int
  224. fz_pixmap_height(fz_context *ctx, const fz_pixmap *pix)
  225. {
  226. return pix->h;
  227. }
  228. int
  229. fz_pixmap_components(fz_context *ctx, const fz_pixmap *pix)
  230. {
  231. return pix->n;
  232. }
  233. int
  234. fz_pixmap_colorants(fz_context *ctx, const fz_pixmap *pix)
  235. {
  236. return pix->n - pix->alpha - pix->s;
  237. }
  238. int
  239. fz_pixmap_spots(fz_context *ctx, const fz_pixmap *pix)
  240. {
  241. return pix->s;
  242. }
  243. int
  244. fz_pixmap_alpha(fz_context *ctx, const fz_pixmap *pix)
  245. {
  246. return pix->alpha;
  247. }
  248. int
  249. fz_pixmap_stride(fz_context *ctx, const fz_pixmap *pix)
  250. {
  251. return pix->stride;
  252. }
  253. unsigned char *
  254. fz_pixmap_samples(fz_context *ctx, const fz_pixmap *pix)
  255. {
  256. if (!pix)
  257. return NULL;
  258. return pix->samples;
  259. }
  260. /*
  261. The slowest routine in most CMYK rendering profiles.
  262. We therefore spend some effort to improve it. Rather than
  263. writing bytes, we write uint32_t's.
  264. */
  265. #ifdef ARCH_ARM
  266. static void
  267. clear_cmyka_bitmap_ARM(uint32_t *samples, int c, int value)
  268. __attribute__((naked));
  269. static void
  270. clear_cmyka_bitmap_ARM(uint32_t *samples, int c, int value)
  271. {
  272. asm volatile(
  273. ENTER_ARM
  274. "stmfd r13!,{r4-r6,r14} \n"
  275. "@ r0 = samples \n"
  276. "@ r1 = c \n"
  277. "@ r2 = value \n"
  278. "mov r3, #255 \n"
  279. "mov r12,#0 @ r12= 0 \n"
  280. "subs r1, r1, #3 \n"
  281. "ble 2f \n"
  282. "str r12,[r13,#-20]! \n"
  283. "str r12,[r13,#4] \n"
  284. "str r12,[r13,#8] \n"
  285. "str r12,[r13,#12] \n"
  286. "str r12,[r13,#16] \n"
  287. "strb r2, [r13,#3] \n"
  288. "strb r3, [r13,#4] \n"
  289. "strb r2, [r13,#8] \n"
  290. "strb r3, [r13,#9] \n"
  291. "strb r2, [r13,#13] \n"
  292. "strb r3, [r13,#14] \n"
  293. "strb r2, [r13,#18] \n"
  294. "strb r3, [r13,#19] \n"
  295. "ldmfd r13!,{r4,r5,r6,r12,r14} \n"
  296. "1: \n"
  297. "stmia r0!,{r4,r5,r6,r12,r14} \n"
  298. "subs r1, r1, #4 \n"
  299. "bgt 1b \n"
  300. "2: \n"
  301. "adds r1, r1, #3 \n"
  302. "ble 4f \n"
  303. "3: \n"
  304. "strb r12,[r0], #1 \n"
  305. "strb r12,[r0], #1 \n"
  306. "strb r12,[r0], #1 \n"
  307. "strb r2, [r0], #1 \n"
  308. "strb r3, [r0], #1 \n"
  309. "subs r1, r1, #1 \n"
  310. "bgt 3b \n"
  311. "4: \n"
  312. "ldmfd r13!,{r4-r6,PC} \n"
  313. ENTER_THUMB
  314. );
  315. }
  316. #endif
  317. static void
  318. clear_cmyk_bitmap(unsigned char *samples, int w, int h, int spots, int stride, int value, int alpha)
  319. {
  320. uint32_t *s = (uint32_t *)(void *)samples;
  321. uint8_t *t;
  322. if (w < 0 || h < 0)
  323. return;
  324. if (spots)
  325. {
  326. int x, i;
  327. spots += 4;
  328. stride -= w * (spots + alpha);
  329. for (; h > 0; h--)
  330. {
  331. for (x = w; x > 0; x--)
  332. {
  333. for (i = spots; i > 0; i--)
  334. *samples++ = value;
  335. if (alpha)
  336. *samples++ = 255;
  337. }
  338. samples += stride;
  339. }
  340. return;
  341. }
  342. if (alpha)
  343. {
  344. int c = w;
  345. stride -= w*5;
  346. if (stride == 0)
  347. {
  348. #ifdef ARCH_ARM
  349. clear_cmyka_bitmap_ARM(s, c, alpha);
  350. return;
  351. #else
  352. /* We can do it all fast (except for maybe a few stragglers) */
  353. union
  354. {
  355. uint8_t bytes[20];
  356. uint32_t words[5];
  357. } d;
  358. c *= h;
  359. h = 1;
  360. d.words[0] = 0;
  361. d.words[1] = 0;
  362. d.words[2] = 0;
  363. d.words[3] = 0;
  364. d.words[4] = 0;
  365. d.bytes[3] = value;
  366. d.bytes[4] = 255;
  367. d.bytes[8] = value;
  368. d.bytes[9] = 255;
  369. d.bytes[13] = value;
  370. d.bytes[14] = 255;
  371. d.bytes[18] = value;
  372. d.bytes[19] = 255;
  373. c -= 3;
  374. {
  375. const uint32_t a0 = d.words[0];
  376. const uint32_t a1 = d.words[1];
  377. const uint32_t a2 = d.words[2];
  378. const uint32_t a3 = d.words[3];
  379. const uint32_t a4 = d.words[4];
  380. while (c > 0)
  381. {
  382. *s++ = a0;
  383. *s++ = a1;
  384. *s++ = a2;
  385. *s++ = a3;
  386. *s++ = a4;
  387. c -= 4;
  388. }
  389. }
  390. c += 3;
  391. #endif
  392. }
  393. t = (unsigned char *)s;
  394. w = c;
  395. while (h--)
  396. {
  397. c = w;
  398. while (c > 0)
  399. {
  400. *t++ = 0;
  401. *t++ = 0;
  402. *t++ = 0;
  403. *t++ = value;
  404. *t++ = 255;
  405. c--;
  406. }
  407. t += stride;
  408. }
  409. }
  410. else
  411. {
  412. stride -= w*4;
  413. if ((stride & 3) == 0)
  414. {
  415. size_t W = w;
  416. if (stride == 0)
  417. {
  418. W *= h;
  419. h = 1;
  420. }
  421. W *= 4;
  422. if (value == 0)
  423. {
  424. while (h--)
  425. {
  426. memset(s, 0, W);
  427. s += (stride>>2);
  428. }
  429. }
  430. else
  431. {
  432. /* We can do it all fast */
  433. union
  434. {
  435. uint8_t bytes[4];
  436. uint32_t word;
  437. } d;
  438. d.word = 0;
  439. d.bytes[3] = value;
  440. {
  441. const uint32_t a0 = d.word;
  442. while (h--)
  443. {
  444. size_t WW = W >> 2;
  445. while (WW--)
  446. {
  447. *s++ = a0;
  448. }
  449. s += (stride>>2);
  450. }
  451. }
  452. }
  453. }
  454. else
  455. {
  456. t = (unsigned char *)s;
  457. while (h--)
  458. {
  459. int c = w;
  460. while (c > 0)
  461. {
  462. *t++ = 0;
  463. *t++ = 0;
  464. *t++ = 0;
  465. *t++ = value;
  466. c--;
  467. }
  468. t += stride;
  469. }
  470. }
  471. }
  472. }
  473. void
  474. fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix)
  475. {
  476. ptrdiff_t stride = pix->w * (ptrdiff_t)pix->n;
  477. int h = pix->h;
  478. unsigned char *s = pix->samples;
  479. if (stride == pix->stride)
  480. {
  481. stride *= h;
  482. h = 1;
  483. }
  484. if (pix->alpha || fz_colorspace_is_subtractive(ctx, pix->colorspace))
  485. {
  486. while (h--)
  487. {
  488. memset(s, 0, stride);
  489. s += pix->stride;
  490. }
  491. }
  492. else if (pix->s == 0)
  493. {
  494. while (h--)
  495. {
  496. memset(s, 0xff, stride);
  497. s += pix->stride;
  498. }
  499. }
  500. else
  501. {
  502. /* Horrible, slow case: additive with spots */
  503. size_t w = stride/pix->n;
  504. int spots = pix->s;
  505. int colorants = pix->n - spots; /* We know there is no alpha */
  506. while (h--)
  507. {
  508. size_t w2 = w;
  509. while (w2--)
  510. {
  511. int i = colorants;
  512. do
  513. {
  514. *s++ = 0xff;
  515. i--;
  516. }
  517. while (i != 0);
  518. i = spots;
  519. do
  520. {
  521. *s++ = 0;
  522. i--;
  523. }
  524. while (i != 0);
  525. }
  526. }
  527. }
  528. }
  529. void
  530. fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value)
  531. {
  532. unsigned char *s;
  533. int w, h, n;
  534. ptrdiff_t stride, len;
  535. int alpha = pix->alpha;
  536. w = pix->w;
  537. h = pix->h;
  538. if (w < 0 || h < 0)
  539. return;
  540. /* CMYK needs special handling (and potentially any other subtractive colorspaces) */
  541. if (fz_colorspace_n(ctx, pix->colorspace) == 4)
  542. {
  543. clear_cmyk_bitmap(pix->samples, w, h, pix->s, pix->stride, 255-value, pix->alpha);
  544. return;
  545. }
  546. n = pix->n;
  547. stride = pix->stride;
  548. len = (ptrdiff_t)w * n;
  549. s = pix->samples;
  550. if (value == 255 || !alpha)
  551. {
  552. if (stride == len)
  553. {
  554. len *= h;
  555. h = 1;
  556. }
  557. while (h--)
  558. {
  559. memset(s, value, len);
  560. s += stride;
  561. }
  562. }
  563. else
  564. {
  565. int k, x, y;
  566. stride -= len;
  567. for (y = 0; y < pix->h; y++)
  568. {
  569. for (x = 0; x < pix->w; x++)
  570. {
  571. for (k = 0; k < pix->n - 1; k++)
  572. *s++ = value;
  573. if (alpha)
  574. *s++ = 255;
  575. }
  576. s += stride;
  577. }
  578. }
  579. }
  580. void
  581. fz_fill_pixmap_with_color(fz_context *ctx, fz_pixmap *pix, fz_colorspace *colorspace, float *color, fz_color_params color_params)
  582. {
  583. float colorfv[FZ_MAX_COLORS];
  584. unsigned char colorbv[FZ_MAX_COLORS];
  585. int i, n, a, s, x, y, w, h;
  586. n = fz_colorspace_n(ctx, pix->colorspace);
  587. a = pix->alpha;
  588. s = pix->s;
  589. fz_convert_color(ctx, colorspace, color, pix->colorspace, colorfv, NULL, color_params);
  590. for (i = 0; i < n; ++i)
  591. colorbv[i] = colorfv[i] * 255;
  592. w = pix->w;
  593. h = pix->h;
  594. for (y = 0; y < h; ++y)
  595. {
  596. unsigned char *p = pix->samples + y * pix->stride;
  597. for (x = 0; x < w; ++x)
  598. {
  599. for (i = 0; i < n; ++i)
  600. *p++ = colorbv[i];
  601. for (i = 0; i < s; ++i)
  602. *p++ = 0;
  603. if (a)
  604. *p++ = 255;
  605. }
  606. }
  607. }
  608. void
  609. fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_irect b, const fz_default_colorspaces *default_cs)
  610. {
  611. unsigned char *srcp;
  612. unsigned char *destp;
  613. unsigned int y, w;
  614. size_t destspan, srcspan;
  615. b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
  616. b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, src));
  617. if (fz_is_empty_irect(b))
  618. return;
  619. w = (unsigned int)(b.x1 - b.x0);
  620. y = (unsigned int)(b.y1 - b.y0);
  621. srcspan = src->stride;
  622. srcp = src->samples + srcspan * (b.y0 - src->y) + (b.x0 - src->x) * (size_t)src->n;
  623. destspan = dest->stride;
  624. destp = dest->samples + destspan * (b.y0 - dest->y) + (b.x0 - dest->x) * (size_t)dest->n;
  625. if (src->n == dest->n)
  626. {
  627. w *= src->n;
  628. do
  629. {
  630. memcpy(destp, srcp, w);
  631. srcp += srcspan;
  632. destp += destspan;
  633. }
  634. while (--y);
  635. }
  636. else
  637. {
  638. fz_pixmap fake_src = *src;
  639. fake_src.x = b.x0;
  640. fake_src.y = b.y0;
  641. fake_src.w = w;
  642. fake_src.h = y;
  643. fake_src.samples = srcp;
  644. fz_convert_pixmap_samples(ctx, &fake_src, dest, NULL, default_cs, fz_default_color_params, 0);
  645. }
  646. }
  647. void
  648. fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, fz_irect b)
  649. {
  650. unsigned char *destp;
  651. int x, y, w, k;
  652. size_t destspan;
  653. b = fz_intersect_irect(b, fz_pixmap_bbox(ctx, dest));
  654. w = b.x1 - b.x0;
  655. y = b.y1 - b.y0;
  656. if (w <= 0 || y <= 0)
  657. return;
  658. destspan = dest->stride;
  659. destp = dest->samples + destspan * (b.y0 - dest->y) + (b.x0 - dest->x) * (size_t)dest->n;
  660. /* CMYK needs special handling (and potentially any other subtractive colorspaces) */
  661. if (fz_colorspace_n(ctx, dest->colorspace) == 4)
  662. {
  663. value = 255 - value;
  664. do
  665. {
  666. unsigned char *s = destp;
  667. for (x = 0; x < w; x++)
  668. {
  669. *s++ = 0;
  670. *s++ = 0;
  671. *s++ = 0;
  672. *s++ = value;
  673. *s++ = 255;
  674. }
  675. destp += destspan;
  676. }
  677. while (--y);
  678. return;
  679. }
  680. if (value == 255)
  681. {
  682. do
  683. {
  684. memset(destp, 255, w * (size_t)dest->n);
  685. destp += destspan;
  686. }
  687. while (--y);
  688. }
  689. else
  690. {
  691. do
  692. {
  693. unsigned char *s = destp;
  694. for (x = 0; x < w; x++)
  695. {
  696. for (k = 0; k < dest->n - 1; k++)
  697. *s++ = value;
  698. *s++ = 255;
  699. }
  700. destp += destspan;
  701. }
  702. while (--y);
  703. }
  704. }
  705. void
  706. fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
  707. {
  708. unsigned char *s = pix->samples;
  709. unsigned char a;
  710. int k, x, y;
  711. size_t stride = pix->stride - pix->w * (size_t)pix->n;
  712. if (!pix->alpha)
  713. return;
  714. for (y = 0; y < pix->h; y++)
  715. {
  716. for (x = 0; x < pix->w; x++)
  717. {
  718. a = s[pix->n - 1];
  719. for (k = 0; k < pix->n - 1; k++)
  720. s[k] = fz_mul255(s[k], a);
  721. s += pix->n;
  722. }
  723. s += stride;
  724. }
  725. }
  726. fz_pixmap *
  727. fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray)
  728. {
  729. fz_pixmap *alpha;
  730. unsigned char *sp, *dp;
  731. int w, h, sstride, dstride;
  732. assert(gray->n == 1);
  733. alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, gray), 0, 1);
  734. dp = alpha->samples;
  735. dstride = alpha->stride;
  736. sp = gray->samples;
  737. sstride = gray->stride;
  738. h = gray->h;
  739. w = gray->w;
  740. while (h--)
  741. {
  742. memcpy(dp, sp, w);
  743. sp += sstride;
  744. dp += dstride;
  745. }
  746. return alpha;
  747. }
  748. void
  749. fz_tint_pixmap(fz_context *ctx, fz_pixmap *pix, int black, int white)
  750. {
  751. unsigned char *s = pix->samples;
  752. int n = pix->n;
  753. int x, y, save;
  754. int rb = (black>>16)&255;
  755. int gb = (black>>8)&255;
  756. int bb = (black)&255;
  757. int rw = (white>>16)&255;
  758. int gw = (white>>8)&255;
  759. int bw = (white)&255;
  760. int rm = (rw - rb);
  761. int gm = (gw - gb);
  762. int bm = (bw - bb);
  763. switch (fz_colorspace_type(ctx, pix->colorspace))
  764. {
  765. case FZ_COLORSPACE_GRAY:
  766. gw = (rw + gw + bw) / 3;
  767. gb = (rb + gb + bb) / 3;
  768. gm = gw - gb;
  769. for (y = 0; y < pix->h; y++)
  770. {
  771. for (x = 0; x < pix->w; x++)
  772. {
  773. *s = gb + fz_mul255(*s, gm);
  774. s += n;
  775. }
  776. s += pix->stride - pix->w * n;
  777. }
  778. break;
  779. case FZ_COLORSPACE_BGR:
  780. save = rm; rm = bm; bm = save;
  781. save = rb; rb = bb; bb = save;
  782. /* fall through */
  783. case FZ_COLORSPACE_RGB:
  784. for (y = 0; y < pix->h; y++)
  785. {
  786. for (x = 0; x < pix->w; x++)
  787. {
  788. s[0] = rb + fz_mul255(s[0], rm);
  789. s[1] = gb + fz_mul255(s[1], gm);
  790. s[2] = bb + fz_mul255(s[2], bm);
  791. s += n;
  792. }
  793. s += pix->stride - pix->w * n;
  794. }
  795. break;
  796. default:
  797. fz_throw(ctx, FZ_ERROR_ARGUMENT, "can only tint RGB, BGR and Gray pixmaps");
  798. break;
  799. }
  800. }
  801. /* Invert luminance in RGB/BGR pixmap, but keep the colors as is. */
  802. static inline void invert_luminance(int type, unsigned char *s)
  803. {
  804. int r, g, b, y;
  805. /* Convert to YUV */
  806. if (type == FZ_COLORSPACE_RGB)
  807. {
  808. r = s[0];
  809. g = s[1];
  810. b = s[2];
  811. }
  812. else
  813. {
  814. r = s[2];
  815. g = s[1];
  816. b = s[0];
  817. }
  818. y = (39336 * r + 76884 * g + 14900 * b + 32768)>>16;
  819. y = 259-y;
  820. r += y;
  821. g += y;
  822. b += y;
  823. if (type == FZ_COLORSPACE_RGB)
  824. {
  825. s[0] = r > 255 ? 255 : r < 0 ? 0 : r;
  826. s[1] = g > 255 ? 255 : g < 0 ? 0 : g;
  827. s[2] = b > 255 ? 255 : b < 0 ? 0 : b;
  828. }
  829. else
  830. {
  831. s[2] = r > 255 ? 255 : r < 0 ? 0 : r;
  832. s[1] = g > 255 ? 255 : g < 0 ? 0 : g;
  833. s[0] = b > 255 ? 255 : b < 0 ? 0 : b;
  834. }
  835. }
  836. void
  837. fz_invert_pixmap_luminance(fz_context *ctx, fz_pixmap *pix)
  838. {
  839. unsigned char *s = pix->samples;
  840. int x, y, n = pix->n;
  841. int type = pix->colorspace ? pix->colorspace->type : FZ_COLORSPACE_NONE;
  842. if (type == FZ_COLORSPACE_GRAY)
  843. {
  844. fz_invert_pixmap(ctx, pix);
  845. }
  846. else if (type == FZ_COLORSPACE_RGB || type == FZ_COLORSPACE_BGR)
  847. {
  848. for (y = 0; y < pix->h; y++)
  849. {
  850. for (x = 0; x < pix->w; x++)
  851. {
  852. invert_luminance(type, s);
  853. s += n;
  854. }
  855. s += pix->stride - pix->w * n;
  856. }
  857. }
  858. else
  859. {
  860. fz_throw(ctx, FZ_ERROR_ARGUMENT, "can only invert luminance of Gray and RGB pixmaps");
  861. }
  862. }
  863. void
  864. fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix)
  865. {
  866. fz_irect rect = { pix->x, pix->y, pix->x + pix->w, pix->y + pix->h };
  867. fz_invert_pixmap_rect(ctx, pix, rect);
  868. }
  869. void
  870. fz_invert_pixmap_alpha(fz_context *ctx, fz_pixmap *pix)
  871. {
  872. unsigned char *s = pix->samples;
  873. int x, y;
  874. int n1 = pix->n - pix->alpha;
  875. int n = pix->n;
  876. if (!pix->alpha)
  877. return;
  878. for (y = 0; y < pix->h; y++)
  879. {
  880. s += n1;
  881. for (x = 0; x < pix->w; x++)
  882. {
  883. *s = 255 - *s;
  884. s += n;
  885. }
  886. s += pix->stride - pix->w * n;
  887. }
  888. }
  889. void fz_invert_pixmap_rect(fz_context *ctx, fz_pixmap *pix, fz_irect rect)
  890. {
  891. int x0 = fz_clampi(rect.x0 - pix->x, 0, pix->w);
  892. int x1 = fz_clampi(rect.x1 - pix->x, 0, pix->w);
  893. int y0 = fz_clampi(rect.y0 - pix->y, 0, pix->h);
  894. int y1 = fz_clampi(rect.y1 - pix->y, 0, pix->h);
  895. int x, y;
  896. int n = pix->n;
  897. int s = pix->s;
  898. int cmyk = (pix->colorspace && pix->colorspace->type == FZ_COLORSPACE_CMYK);
  899. if (cmyk)
  900. {
  901. /* For cmyk, we're storing: (a.c, a.m, a.y, a.k, a)
  902. * So, a.r = a - a.c - a.k
  903. * a.g = a - a.m - a.k
  904. * a.b = a - a.y - a.k
  905. * Invert that:
  906. * a.R = a.c + a.k
  907. * a.G = a.m + a.k
  908. * a.B = a.y + a.k
  909. * Convert that back to cmy
  910. * a.C = a - a.c - a.k;
  911. * a.M = a - a.m - a.k;
  912. * a.Y = a - a.y - a.k;
  913. * Extract K:
  914. * a.K' = min(a.C, a.M, a.Y)
  915. * = a - a.k - max(a.c, a.m, a.y)
  916. * a.C' = a.C - a.K' = a - a.c - a.k - (a - a.k - max(a.c, a.m, a.y)) = max(a.c, a.m, a.y) - a.c
  917. * a.M' = a.M - a.K' = a - a.m - a.k - (a - a.k - max(a.c, a.m, a.y)) = max(a.c, a.m, a.y) - a.m
  918. * a.Y' = a.Y - a.K' = a - a.y - a.k - (a - a.k - max(a.c, a.m, a.y)) = max(a.c, a.m, a.y) - a.y
  919. * */
  920. if (pix->alpha)
  921. {
  922. int n1 = pix->n - pix->alpha - s;
  923. for (y = y0; y < y1; y++)
  924. {
  925. unsigned char *d = pix->samples + ((y * (size_t)pix->stride) + (x0 * (size_t)pix->n));
  926. for (x = x0; x < x1; x++)
  927. {
  928. int ac = d[0];
  929. int am = d[1];
  930. int ay = d[2];
  931. int ak = d[3];
  932. int a = d[n1];
  933. int mx = fz_maxi(fz_maxi(ac, am), ay);
  934. d[0] = mx-ac;
  935. d[1] = mx-am;
  936. d[2] = mx-ay;
  937. ak = a - ak - mx;
  938. if (ak < 0)
  939. ak = 0;
  940. d[3] = ak;
  941. d += n;
  942. }
  943. }
  944. }
  945. else
  946. {
  947. for (y = y0; y < y1; y++)
  948. {
  949. unsigned char *d = pix->samples + ((y * (size_t)pix->stride) + (x0 * (size_t)pix->n));
  950. for (x = x0; x < x1; x++)
  951. {
  952. int c = d[0];
  953. int m = d[1];
  954. int ye = d[2];
  955. int k = d[3];
  956. int mx = fz_maxi(fz_maxi(c, m), ye);
  957. d[0] = mx-c;
  958. d[1] = mx-m;
  959. d[2] = mx-ye;
  960. k = 255 - k - mx;
  961. if (k < 0)
  962. k = 0;
  963. d[3] = k;
  964. d += n;
  965. }
  966. }
  967. }
  968. }
  969. else if (pix->alpha)
  970. {
  971. int n1 = pix->n - pix->alpha - s;
  972. for (y = y0; y < y1; y++)
  973. {
  974. unsigned char *d = pix->samples + ((y * (size_t)pix->stride) + (x0 * (size_t)pix->n));
  975. for (x = x0; x < x1; x++)
  976. {
  977. int a = d[n1];
  978. int k;
  979. for (k = 0; k < n1; k++)
  980. d[k] = a - d[k];
  981. d += n;
  982. }
  983. }
  984. }
  985. else if (s)
  986. {
  987. int n1 = pix->n - s;
  988. for (y = y0; y < y1; y++)
  989. {
  990. unsigned char *d = pix->samples + ((y * (size_t)pix->stride) + (x0 * (size_t)pix->n));
  991. for (x = x0; x < x1; x++)
  992. {
  993. int k;
  994. for (k = 0; k < n1; k++)
  995. d[k] = 255 - d[k];
  996. d += n;
  997. }
  998. }
  999. }
  1000. else
  1001. {
  1002. for (y = y0; y < y1; y++)
  1003. {
  1004. unsigned char *d = pix->samples + ((y * (size_t)pix->stride) + (x0 * (size_t)pix->n));
  1005. for (x = x0; x < x1; x++)
  1006. {
  1007. int k;
  1008. for (k = 0; k < n; k++)
  1009. d[k] = 255 - d[k];
  1010. d += n;
  1011. }
  1012. }
  1013. }
  1014. }
  1015. void
  1016. fz_invert_pixmap_raw(fz_context *ctx, fz_pixmap *pix)
  1017. {
  1018. unsigned char *s = pix->samples;
  1019. int k, x, y;
  1020. int n1 = pix->n - pix->alpha;
  1021. int n = pix->n;
  1022. for (y = 0; y < pix->h; y++)
  1023. {
  1024. for (x = 0; x < pix->w; x++)
  1025. {
  1026. for (k = 0; k < n1; k++)
  1027. s[k] = 255 - s[k];
  1028. s += n;
  1029. }
  1030. s += pix->stride - pix->w * n;
  1031. }
  1032. }
  1033. void
  1034. fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma)
  1035. {
  1036. unsigned char gamma_map[256];
  1037. unsigned char *s = pix->samples;
  1038. int n1 = pix->n - pix->alpha;
  1039. int n = pix->n;
  1040. int k, x, y;
  1041. for (k = 0; k < 256; k++)
  1042. gamma_map[k] = powf(k / 255.0f, gamma) * 255;
  1043. for (y = 0; y < pix->h; y++)
  1044. {
  1045. for (x = 0; x < pix->w; x++)
  1046. {
  1047. for (k = 0; k < n1; k++)
  1048. s[k] = gamma_map[s[k]];
  1049. s += n;
  1050. }
  1051. s += pix->stride - pix->w * n;
  1052. }
  1053. }
  1054. size_t
  1055. fz_pixmap_size(fz_context *ctx, fz_pixmap * pix)
  1056. {
  1057. if (pix == NULL)
  1058. return 0;
  1059. return sizeof(*pix) + (size_t)pix->n * pix->w * pix->h;
  1060. }
  1061. fz_pixmap *
  1062. fz_convert_pixmap(fz_context *ctx, const fz_pixmap *pix, fz_colorspace *ds, fz_colorspace *prf, fz_default_colorspaces *default_cs, fz_color_params color_params, int keep_alpha)
  1063. {
  1064. fz_pixmap *cvt;
  1065. if (!ds && !keep_alpha)
  1066. fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot both throw away and keep alpha");
  1067. cvt = fz_new_pixmap(ctx, ds, pix->w, pix->h, pix->seps, keep_alpha && pix->alpha);
  1068. cvt->xres = pix->xres;
  1069. cvt->yres = pix->yres;
  1070. cvt->x = pix->x;
  1071. cvt->y = pix->y;
  1072. if (pix->flags & FZ_PIXMAP_FLAG_INTERPOLATE)
  1073. cvt->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
  1074. else
  1075. cvt->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
  1076. fz_try(ctx)
  1077. {
  1078. fz_convert_pixmap_samples(ctx, pix, cvt, prf, default_cs, color_params, 1);
  1079. }
  1080. fz_catch(ctx)
  1081. {
  1082. fz_drop_pixmap(ctx, cvt);
  1083. fz_rethrow(ctx);
  1084. }
  1085. return cvt;
  1086. }
  1087. fz_pixmap *
  1088. fz_new_pixmap_from_8bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span)
  1089. {
  1090. fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h, NULL, 1);
  1091. int stride = pixmap->stride;
  1092. unsigned char *s = pixmap->samples;
  1093. pixmap->x = x;
  1094. pixmap->y = y;
  1095. for (y = 0; y < h; y++)
  1096. {
  1097. memcpy(s, sp + y * span, w);
  1098. s += stride;
  1099. }
  1100. return pixmap;
  1101. }
  1102. fz_pixmap *
  1103. fz_new_pixmap_from_1bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span)
  1104. {
  1105. fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h, NULL, 1);
  1106. int stride = pixmap->stride - pixmap->w;
  1107. pixmap->x = x;
  1108. pixmap->y = y;
  1109. for (y = 0; y < h; y++)
  1110. {
  1111. unsigned char *out = pixmap->samples + y * w;
  1112. unsigned char *in = sp + y * span;
  1113. unsigned char bit = 0x80;
  1114. int ww = w;
  1115. while (ww--)
  1116. {
  1117. *out++ = (*in & bit) ? 255 : 0;
  1118. bit >>= 1;
  1119. if (bit == 0)
  1120. bit = 0x80, in++;
  1121. }
  1122. out += stride;
  1123. }
  1124. return pixmap;
  1125. }
  1126. static float
  1127. calc_percentile(int *hist, float thr, float scale, float minval, float maxval)
  1128. {
  1129. float prct;
  1130. int k = 0, count = 0;
  1131. while (count < thr)
  1132. count += hist[k++];
  1133. if (k <= 0)
  1134. prct = k;
  1135. else
  1136. {
  1137. float c0 = count - thr;
  1138. float c1 = thr - (count - hist[k - 1]);
  1139. prct = (c1 * k + c0 * (k - 1)) / (c0 + c1);
  1140. }
  1141. prct /= scale;
  1142. prct += minval;
  1143. return fz_clamp(prct, minval, maxval);
  1144. }
  1145. static void
  1146. calc_percentiles(fz_context *ctx, float *samples, size_t nsamples, float *minprct, float *maxprct)
  1147. {
  1148. float minval, maxval, scale;
  1149. size_t size, k;
  1150. int *hist;
  1151. minval = maxval = samples[0];
  1152. for (k = 1; k < nsamples; k++)
  1153. {
  1154. minval = fz_min(minval, samples[k]);
  1155. maxval = fz_max(maxval, samples[k]);
  1156. }
  1157. if (minval - maxval == 0)
  1158. {
  1159. *minprct = *maxprct = minval;
  1160. return;
  1161. }
  1162. size = fz_minz(65535, nsamples);
  1163. scale = (size - 1) / (maxval - minval);
  1164. hist = fz_calloc(ctx, size, sizeof(int));
  1165. *minprct = 0;
  1166. *maxprct = 0;
  1167. for (k = 0; k < nsamples; k++)
  1168. hist[(uint16_t) (scale * (samples[k] - minval))]++;
  1169. *minprct = calc_percentile(hist, 0.01f * nsamples, scale, minval, maxval);
  1170. *maxprct = calc_percentile(hist, 0.99f * nsamples, scale, minval, maxval);
  1171. fz_free(ctx, hist);
  1172. }
  1173. /* Tone mapping according to "Consistent Tone Reproduction" by Min H. Kim and Jan Kautz. */
  1174. fz_pixmap *
  1175. fz_new_pixmap_from_float_data(fz_context *ctx, fz_colorspace *cs, int w, int h, float *samples)
  1176. {
  1177. fz_pixmap *pixmap = NULL;
  1178. unsigned char *dp;
  1179. float *sample;
  1180. float minsample, maxsample, mu;
  1181. float k1, d0, sigma, sigmasq2;
  1182. float minprct, maxprct, range;
  1183. size_t k, nsamples;
  1184. int y;
  1185. #define KIMKAUTZC1 (3.0f)
  1186. #define KIMKAUTZC2 (0.5f)
  1187. #define MAXLD (logf(300.0f))
  1188. #define MINLD (logf(0.3f))
  1189. pixmap = fz_new_pixmap(ctx, cs, w, h, NULL, 0);
  1190. if (w > 0 && h > 0 && pixmap->n > 0)
  1191. {
  1192. fz_try(ctx)
  1193. {
  1194. nsamples = (size_t) w * h;
  1195. if ((size_t) pixmap->n > SIZE_MAX / nsamples)
  1196. fz_throw(ctx, FZ_ERROR_LIMIT, "too many floating point samples to convert to pixmap");
  1197. nsamples *= pixmap->n;
  1198. mu = 0;
  1199. minsample = FLT_MAX;
  1200. maxsample = -FLT_MAX;
  1201. for (k = 0; k < nsamples; k++)
  1202. {
  1203. float v = logf(samples[k] == 0 ? FLT_MIN : samples[k]);
  1204. mu += v;
  1205. minsample = fz_min(minsample, v);
  1206. maxsample = fz_max(maxsample, v);
  1207. }
  1208. mu /= nsamples;
  1209. d0 = maxsample - minsample;
  1210. k1 = (MAXLD - MINLD) / d0;
  1211. sigma = d0 / KIMKAUTZC1;
  1212. sigmasq2 = sigma * sigma * 2;
  1213. for (k = 0; k < nsamples; k++)
  1214. {
  1215. float samplemu = samples[k] - mu;
  1216. float samplemu2 = samplemu * samplemu;
  1217. float fw = expf(-samplemu2 / sigmasq2);
  1218. float k2 = (1 - k1) * fw + k1;
  1219. samples[k] = expf(KIMKAUTZC2 * k2 * (logf(samples[k] == 0 ? FLT_MIN : samples[k]) - mu) + mu);
  1220. }
  1221. calc_percentiles(ctx, samples, nsamples, &minprct, &maxprct);
  1222. range = maxprct - minprct;
  1223. dp = pixmap->samples + pixmap->stride * (h - 1);
  1224. sample = samples;
  1225. for (y = 0; y < h; y++)
  1226. {
  1227. unsigned char *dpp = dp;
  1228. for (k = 0; k < (size_t) w * pixmap->n; k++)
  1229. *dpp++ = 255.0f * (fz_clamp(*sample++, minprct, maxprct) - minprct) / range;
  1230. dp -= pixmap->stride;
  1231. }
  1232. }
  1233. fz_catch(ctx)
  1234. {
  1235. fz_drop_pixmap(ctx, pixmap);
  1236. fz_rethrow(ctx);
  1237. }
  1238. }
  1239. return pixmap;
  1240. }
  1241. fz_pixmap *
  1242. fz_new_pixmap_from_alpha_channel(fz_context *ctx, fz_pixmap *src)
  1243. {
  1244. fz_pixmap *dst;
  1245. int w, h, n, x;
  1246. unsigned char *sp, *dp;
  1247. if (!src->alpha)
  1248. return NULL;
  1249. dst = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, src), NULL, 1);
  1250. w = src->w;
  1251. h = src->h;
  1252. n = src->n;
  1253. sp = src->samples + n - 1;
  1254. dp = dst->samples;
  1255. while (h--)
  1256. {
  1257. unsigned char *s = sp;
  1258. unsigned char *d = dp;
  1259. for (x = 0; x < w; ++x)
  1260. {
  1261. *d++ = *s;
  1262. s += n;
  1263. }
  1264. sp += src->stride;
  1265. dp += dst->stride;
  1266. }
  1267. return dst;
  1268. }
  1269. fz_pixmap *
  1270. fz_new_pixmap_from_color_and_mask(fz_context *ctx, fz_pixmap *color, fz_pixmap *mask)
  1271. {
  1272. fz_pixmap *dst;
  1273. int w = color->w;
  1274. int h = color->h;
  1275. int n = color->n;
  1276. int x, y, k;
  1277. if (color->alpha)
  1278. fz_throw(ctx, FZ_ERROR_ARGUMENT, "color pixmap must not have an alpha channel");
  1279. if (mask->n != 1)
  1280. fz_throw(ctx, FZ_ERROR_ARGUMENT, "mask pixmap must have exactly one channel");
  1281. if (mask->w != color->w || mask->h != color->h)
  1282. fz_throw(ctx, FZ_ERROR_ARGUMENT, "color and mask pixmaps must be the same size");
  1283. dst = fz_new_pixmap_with_bbox(ctx, color->colorspace, fz_pixmap_bbox(ctx, color), NULL, 1);
  1284. for (y = 0; y < h; ++y)
  1285. {
  1286. unsigned char *cs = &color->samples[y * color->stride];
  1287. unsigned char *ms = &mask->samples[y * mask->stride];
  1288. unsigned char *ds = &dst->samples[y * dst->stride];
  1289. for (x = 0; x < w; ++x)
  1290. {
  1291. unsigned char a = *ms++;
  1292. for (k = 0; k < n; ++k)
  1293. *ds++ = fz_mul255(*cs++, a);
  1294. *ds++ = a;
  1295. }
  1296. }
  1297. return dst;
  1298. }
  1299. int
  1300. fz_is_pixmap_monochrome(fz_context *ctx, fz_pixmap *pixmap)
  1301. {
  1302. int n = pixmap->n;
  1303. int w = pixmap->w;
  1304. int h = pixmap->h;
  1305. unsigned char *s = pixmap->samples;
  1306. int x;
  1307. if (n != 1)
  1308. return 0;
  1309. while (h--)
  1310. {
  1311. for (x = 0; x < w; ++x)
  1312. {
  1313. unsigned char v = s[x];
  1314. if (v != 0 && v != 255)
  1315. return 0;
  1316. }
  1317. s += pixmap->stride;
  1318. }
  1319. return 1;
  1320. }
  1321. #ifdef ARCH_ARM
  1322. static void
  1323. fz_subsample_pixmap_ARM(unsigned char *ptr, int w, int h, int f, int factor,
  1324. int n, int fwd, int back, int back2, int fwd2,
  1325. int divX, int back4, int fwd4, int fwd3,
  1326. int divY, int back5, int divXY)
  1327. __attribute__((naked));
  1328. static void
  1329. fz_subsample_pixmap_ARM(unsigned char *ptr, int w, int h, int f, int factor,
  1330. int n, int fwd, int back, int back2, int fwd2,
  1331. int divX, int back4, int fwd4, int fwd3,
  1332. int divY, int back5, int divXY)
  1333. {
  1334. asm volatile(
  1335. ENTER_ARM
  1336. "stmfd r13!,{r1,r4-r11,r14} \n"
  1337. "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
  1338. "@ r0 = src = ptr \n"
  1339. "@ r1 = w \n"
  1340. "@ r2 = h \n"
  1341. "@ r3 = f \n"
  1342. "mov r9, r0 @ r9 = dst = ptr \n"
  1343. "ldr r6, [r13,#4*12] @ r6 = fwd \n"
  1344. "ldr r7, [r13,#4*13] @ r7 = back \n"
  1345. "subs r2, r2, r3 @ r2 = h -= f \n"
  1346. "blt 12f @ Skip if less than a full row \n"
  1347. "1: @ for (y = h; y > 0; y--) { \n"
  1348. "ldr r1, [r13] @ r1 = w \n"
  1349. "subs r1, r1, r3 @ r1 = w -= f \n"
  1350. "blt 6f @ Skip if less than a full col \n"
  1351. "ldr r4, [r13,#4*10] @ r4 = factor \n"
  1352. "ldr r8, [r13,#4*14] @ r8 = back2 \n"
  1353. "ldr r12,[r13,#4*15] @ r12= fwd2 \n"
  1354. "2: @ for (x = w; x > 0; x--) { \n"
  1355. "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
  1356. "3: @ \n"
  1357. "mov r14,#0 @ r14= v = 0 \n"
  1358. "sub r5, r5, r3, LSL #8 @ for (xx = f; xx > 0; x--) { \n"
  1359. "4: @ \n"
  1360. "add r5, r5, r3, LSL #16 @ for (yy = f; yy > 0; y--) { \n"
  1361. "5: @ \n"
  1362. "ldrb r11,[r0], r6 @ r11= *src src += fwd \n"
  1363. "subs r5, r5, #1<<16 @ xx-- \n"
  1364. "add r14,r14,r11 @ v += r11 \n"
  1365. "bgt 5b @ } \n"
  1366. "sub r0, r0, r7 @ src -= back \n"
  1367. "adds r5, r5, #1<<8 @ yy-- \n"
  1368. "blt 4b @ } \n"
  1369. "mov r14,r14,LSR r4 @ r14 = v >>= factor \n"
  1370. "strb r14,[r9], #1 @ *d++ = r14 \n"
  1371. "sub r0, r0, r8 @ s -= back2 \n"
  1372. "subs r5, r5, #1 @ n-- \n"
  1373. "bgt 3b @ } \n"
  1374. "add r0, r0, r12 @ s += fwd2 \n"
  1375. "subs r1, r1, r3 @ x -= f \n"
  1376. "bge 2b @ } \n"
  1377. "6: @ Less than a full column left \n"
  1378. "adds r1, r1, r3 @ x += f \n"
  1379. "beq 11f @ if (x == 0) next row \n"
  1380. "@ r0 = src \n"
  1381. "@ r1 = x \n"
  1382. "@ r2 = y \n"
  1383. "@ r3 = f \n"
  1384. "@ r4 = factor \n"
  1385. "@ r6 = fwd \n"
  1386. "@ r7 = back \n"
  1387. "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
  1388. "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
  1389. "ldr r4, [r13,#4*16] @ r4 = divX \n"
  1390. "ldr r8, [r13,#4*17] @ r8 = back4 \n"
  1391. "ldr r12,[r13,#4*18] @ r12= fwd4 \n"
  1392. "8: @ \n"
  1393. "mov r14,#0 @ r14= v = 0 \n"
  1394. "sub r5, r5, r1, LSL #8 @ for (xx = x; xx > 0; x--) { \n"
  1395. "9: @ \n"
  1396. "add r5, r5, r3, LSL #16 @ for (yy = f; yy > 0; y--) { \n"
  1397. "10: @ \n"
  1398. "ldrb r11,[r0], r6 @ r11= *src src += fwd \n"
  1399. "subs r5, r5, #1<<16 @ xx-- \n"
  1400. "add r14,r14,r11 @ v += r11 \n"
  1401. "bgt 10b @ } \n"
  1402. "sub r0, r0, r7 @ src -= back \n"
  1403. "adds r5, r5, #1<<8 @ yy-- \n"
  1404. "blt 9b @ } \n"
  1405. "mul r14,r4, r14 @ r14= v *= divX \n"
  1406. "mov r14,r14,LSR #16 @ r14= v >>= 16 \n"
  1407. "strb r14,[r9], #1 @ *d++ = r14 \n"
  1408. "sub r0, r0, r8 @ s -= back4 \n"
  1409. "subs r5, r5, #1 @ n-- \n"
  1410. "bgt 8b @ } \n"
  1411. "add r0, r0, r12 @ s += fwd4 \n"
  1412. "11: @ \n"
  1413. "ldr r14,[r13,#4*19] @ r14 = fwd3 \n"
  1414. "subs r2, r2, r3 @ h -= f \n"
  1415. "add r0, r0, r14 @ s += fwd3 \n"
  1416. "bge 1b @ } \n"
  1417. "12: \n"
  1418. "adds r2, r2, r3 @ h += f \n"
  1419. "beq 21f @ if no stray row, end \n"
  1420. "@ So doing one last (partial) row \n"
  1421. "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
  1422. "@ r0 = src = ptr \n"
  1423. "@ r1 = w \n"
  1424. "@ r2 = h \n"
  1425. "@ r3 = f \n"
  1426. "@ r4 = factor \n"
  1427. "@ r5 = n \n"
  1428. "@ r6 = fwd \n"
  1429. " @ for (y = h; y > 0; y--) { \n"
  1430. "ldr r1, [r13] @ r1 = w \n"
  1431. "ldr r7, [r13,#4*21] @ r7 = back5 \n"
  1432. "ldr r8, [r13,#4*14] @ r8 = back2 \n"
  1433. "subs r1, r1, r3 @ r1 = w -= f \n"
  1434. "blt 17f @ Skip if less than a full col \n"
  1435. "ldr r4, [r13,#4*20] @ r4 = divY \n"
  1436. "ldr r12,[r13,#4*15] @ r12= fwd2 \n"
  1437. "13: @ for (x = w; x > 0; x--) { \n"
  1438. "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
  1439. "14: @ \n"
  1440. "mov r14,#0 @ r14= v = 0 \n"
  1441. "sub r5, r5, r3, LSL #8 @ for (xx = f; xx > 0; x--) { \n"
  1442. "15: @ \n"
  1443. "add r5, r5, r2, LSL #16 @ for (yy = y; yy > 0; y--) { \n"
  1444. "16: @ \n"
  1445. "ldrb r11,[r0], r6 @ r11= *src src += fwd \n"
  1446. "subs r5, r5, #1<<16 @ xx-- \n"
  1447. "add r14,r14,r11 @ v += r11 \n"
  1448. "bgt 16b @ } \n"
  1449. "sub r0, r0, r7 @ src -= back5 \n"
  1450. "adds r5, r5, #1<<8 @ yy-- \n"
  1451. "blt 15b @ } \n"
  1452. "mul r14,r4, r14 @ r14 = x *= divY \n"
  1453. "mov r14,r14,LSR #16 @ r14 = v >>= 16 \n"
  1454. "strb r14,[r9], #1 @ *d++ = r14 \n"
  1455. "sub r0, r0, r8 @ s -= back2 \n"
  1456. "subs r5, r5, #1 @ n-- \n"
  1457. "bgt 14b @ } \n"
  1458. "add r0, r0, r12 @ s += fwd2 \n"
  1459. "subs r1, r1, r3 @ x -= f \n"
  1460. "bge 13b @ } \n"
  1461. "17: @ Less than a full column left \n"
  1462. "adds r1, r1, r3 @ x += f \n"
  1463. "beq 21f @ if (x == 0) end \n"
  1464. "@ r0 = src \n"
  1465. "@ r1 = x \n"
  1466. "@ r2 = y \n"
  1467. "@ r3 = f \n"
  1468. "@ r4 = factor \n"
  1469. "@ r6 = fwd \n"
  1470. "@ r7 = back5 \n"
  1471. "@ r8 = back2 \n"
  1472. "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
  1473. "ldr r4, [r13,#4*22] @ r4 = divXY \n"
  1474. "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
  1475. "ldr r8, [r13,#4*17] @ r8 = back4 \n"
  1476. "18: @ \n"
  1477. "mov r14,#0 @ r14= v = 0 \n"
  1478. "sub r5, r5, r1, LSL #8 @ for (xx = x; xx > 0; x--) { \n"
  1479. "19: @ \n"
  1480. "add r5, r5, r2, LSL #16 @ for (yy = y; yy > 0; y--) { \n"
  1481. "20: @ \n"
  1482. "ldrb r11,[r0],r6 @ r11= *src src += fwd \n"
  1483. "subs r5, r5, #1<<16 @ xx-- \n"
  1484. "add r14,r14,r11 @ v += r11 \n"
  1485. "bgt 20b @ } \n"
  1486. "sub r0, r0, r7 @ src -= back5 \n"
  1487. "adds r5, r5, #1<<8 @ yy-- \n"
  1488. "blt 19b @ } \n"
  1489. "mul r14,r4, r14 @ r14= v *= divX \n"
  1490. "mov r14,r14,LSR #16 @ r14= v >>= 16 \n"
  1491. "strb r14,[r9], #1 @ *d++ = r14 \n"
  1492. "sub r0, r0, r8 @ s -= back4 \n"
  1493. "subs r5, r5, #1 @ n-- \n"
  1494. "bgt 18b @ } \n"
  1495. "21: @ \n"
  1496. "ldmfd r13!,{r1,r4-r11,PC} @ pop, return to thumb \n"
  1497. ENTER_THUMB
  1498. );
  1499. }
  1500. #endif
  1501. void
  1502. fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
  1503. {
  1504. int f;
  1505. if (!tile)
  1506. return;
  1507. assert(tile->stride >= tile->w * tile->n);
  1508. fz_subsample_pixblock(tile->samples, tile->w, tile->h, tile->n, factor, tile->stride);
  1509. f = 1<<factor;
  1510. tile->w = (tile->w + f-1)>>factor;
  1511. tile->h = (tile->h + f-1)>>factor;
  1512. tile->stride = tile->w * (size_t)tile->n;
  1513. /* Redundant test? We only ever make pixmaps smaller! */
  1514. if (tile->h > INT_MAX / (tile->w * tile->n))
  1515. fz_throw(ctx, FZ_ERROR_LIMIT, "pixmap too large");
  1516. tile->samples = fz_realloc(ctx, tile->samples, (size_t)tile->h * tile->w * tile->n);
  1517. }
  1518. void
  1519. fz_subsample_pixblock(unsigned char *s, int w, int h, int n, int factor, ptrdiff_t stride)
  1520. {
  1521. int fwd, fwd2, fwd3, back, back2, f;
  1522. unsigned char *d;
  1523. #ifndef ARCH_ARM
  1524. int x, y, xx, yy, nn;
  1525. #endif
  1526. d = s;
  1527. f = 1<<factor;
  1528. fwd = stride;
  1529. back = f*fwd-n;
  1530. back2 = f*n-1;
  1531. fwd2 = (f-1)*n;
  1532. fwd3 = (f-1)*fwd + (int)stride - w * n;
  1533. factor *= 2;
  1534. #ifdef ARCH_ARM
  1535. {
  1536. int strayX = w%f;
  1537. int divX = (strayX ? 65536/(strayX*f) : 0);
  1538. int fwd4 = (strayX-1) * n;
  1539. int back4 = strayX*n-1;
  1540. int strayY = h%f;
  1541. int divY = (strayY ? 65536/(strayY*f) : 0);
  1542. int back5 = fwd * strayY - n;
  1543. int divXY = (strayY*strayX ? 65536/(strayX*strayY) : 0);
  1544. fz_subsample_pixmap_ARM(s, w, h, f, factor, n, fwd, back,
  1545. back2, fwd2, divX, back4, fwd4, fwd3,
  1546. divY, back5, divXY);
  1547. }
  1548. #else
  1549. for (y = h - f; y >= 0; y -= f)
  1550. {
  1551. for (x = w - f; x >= 0; x -= f)
  1552. {
  1553. for (nn = n; nn > 0; nn--)
  1554. {
  1555. int v = 0;
  1556. for (xx = f; xx > 0; xx--)
  1557. {
  1558. for (yy = f; yy > 0; yy--)
  1559. {
  1560. v += *s;
  1561. s += fwd;
  1562. }
  1563. s -= back;
  1564. }
  1565. *d++ = v >> factor;
  1566. s -= back2;
  1567. }
  1568. s += fwd2;
  1569. }
  1570. /* Do any strays */
  1571. x += f;
  1572. if (x > 0)
  1573. {
  1574. int div = x * f;
  1575. int fwd4 = (x-1) * n;
  1576. int back4 = x*n-1;
  1577. for (nn = n; nn > 0; nn--)
  1578. {
  1579. int v = 0;
  1580. for (xx = x; xx > 0; xx--)
  1581. {
  1582. for (yy = f; yy > 0; yy--)
  1583. {
  1584. v += *s;
  1585. s += fwd;
  1586. }
  1587. s -= back;
  1588. }
  1589. *d++ = v / div;
  1590. s -= back4;
  1591. }
  1592. s += fwd4;
  1593. }
  1594. s += fwd3;
  1595. }
  1596. /* Do any stray line */
  1597. y += f;
  1598. if (y > 0)
  1599. {
  1600. int div = y * f;
  1601. int back5 = fwd * y - n;
  1602. for (x = w - f; x >= 0; x -= f)
  1603. {
  1604. for (nn = n; nn > 0; nn--)
  1605. {
  1606. int v = 0;
  1607. for (xx = f; xx > 0; xx--)
  1608. {
  1609. for (yy = y; yy > 0; yy--)
  1610. {
  1611. v += *s;
  1612. s += fwd;
  1613. }
  1614. s -= back5;
  1615. }
  1616. *d++ = v / div;
  1617. s -= back2;
  1618. }
  1619. s += fwd2;
  1620. }
  1621. /* Do any stray at the end of the stray line */
  1622. x += f;
  1623. if (x > 0)
  1624. {
  1625. int back4 = x * n - 1;
  1626. div = x * y;
  1627. for (nn = n; nn > 0; nn--)
  1628. {
  1629. int v = 0;
  1630. for (xx = x; xx > 0; xx--)
  1631. {
  1632. for (yy = y; yy > 0; yy--)
  1633. {
  1634. v += *s;
  1635. s += fwd;
  1636. }
  1637. s -= back5;
  1638. }
  1639. *d++ = v / div;
  1640. s -= back4;
  1641. }
  1642. }
  1643. }
  1644. #endif
  1645. }
  1646. void
  1647. fz_set_pixmap_resolution(fz_context *ctx, fz_pixmap *pix, int xres, int yres)
  1648. {
  1649. pix->xres = xres;
  1650. pix->yres = yres;
  1651. }
  1652. /*
  1653. Return the md5 digest for a pixmap
  1654. */
  1655. void
  1656. fz_md5_pixmap(fz_context *ctx, fz_pixmap *pix, unsigned char digest[16])
  1657. {
  1658. fz_md5 md5;
  1659. fz_md5_init(&md5);
  1660. if (pix)
  1661. {
  1662. unsigned char *s = pix->samples;
  1663. int h = pix->h;
  1664. int ss = pix->stride;
  1665. int len = pix->w * pix->n;
  1666. while (h--)
  1667. {
  1668. fz_md5_update(&md5, s, len);
  1669. s += ss;
  1670. }
  1671. }
  1672. fz_md5_final(&md5, digest);
  1673. }
  1674. #ifdef HAVE_VALGRIND
  1675. int fz_valgrind_pixmap(const fz_pixmap *pix)
  1676. {
  1677. int w, h, n, total;
  1678. int ww, hh, nn;
  1679. int stride;
  1680. const unsigned char *p = pix->samples;
  1681. if (pix == NULL)
  1682. return 0;
  1683. total = 0;
  1684. ww = pix->w;
  1685. hh = pix->h;
  1686. nn = pix->n;
  1687. stride = pix->stride - ww*nn;
  1688. for (h = 0; h < hh; h++)
  1689. {
  1690. for (w = 0; w < ww; w++)
  1691. for (n = 0; n < nn; n++)
  1692. if (*p++) total ++;
  1693. p += stride;
  1694. }
  1695. return total;
  1696. }
  1697. #endif /* HAVE_VALGRIND */
  1698. fz_pixmap *
  1699. fz_convert_indexed_pixmap_to_base(fz_context *ctx, const fz_pixmap *src)
  1700. {
  1701. fz_pixmap *dst;
  1702. fz_colorspace *base;
  1703. const unsigned char *s;
  1704. unsigned char *d;
  1705. int y, x, k, n, high;
  1706. unsigned char *lookup;
  1707. ptrdiff_t s_line_inc, d_line_inc;
  1708. if (src->colorspace->type != FZ_COLORSPACE_INDEXED)
  1709. fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot convert non-indexed pixmap");
  1710. if (src->n != 1 + src->alpha)
  1711. fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot convert indexed pixmap mis-matching components");
  1712. base = src->colorspace->u.indexed.base;
  1713. high = src->colorspace->u.indexed.high;
  1714. lookup = src->colorspace->u.indexed.lookup;
  1715. n = base->n;
  1716. dst = fz_new_pixmap_with_bbox(ctx, base, fz_pixmap_bbox(ctx, src), src->seps, src->alpha);
  1717. s = src->samples;
  1718. d = dst->samples;
  1719. s_line_inc = src->stride - src->w * (ptrdiff_t)src->n;
  1720. d_line_inc = dst->stride - dst->w * (ptrdiff_t)dst->n;
  1721. if (src->alpha)
  1722. {
  1723. for (y = 0; y < src->h; y++)
  1724. {
  1725. for (x = 0; x < src->w; x++)
  1726. {
  1727. int v = *s++;
  1728. int a = *s++;
  1729. int aa = a + (a>>7);
  1730. v = fz_mini(v, high);
  1731. for (k = 0; k < n; k++)
  1732. *d++ = (aa * lookup[v * n + k] + 128)>>8;
  1733. *d++ = a;
  1734. }
  1735. s += s_line_inc;
  1736. d += d_line_inc;
  1737. }
  1738. }
  1739. else
  1740. {
  1741. for (y = 0; y < src->h; y++)
  1742. {
  1743. for (x = 0; x < src->w; x++)
  1744. {
  1745. int v = *s++;
  1746. v = fz_mini(v, high);
  1747. for (k = 0; k < n; k++)
  1748. *d++ = lookup[v * n + k];
  1749. }
  1750. s += s_line_inc;
  1751. d += d_line_inc;
  1752. }
  1753. }
  1754. if (src->flags & FZ_PIXMAP_FLAG_INTERPOLATE)
  1755. dst->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
  1756. else
  1757. dst->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
  1758. return dst;
  1759. }
  1760. fz_pixmap *
  1761. fz_convert_separation_pixmap_to_base(fz_context *ctx, const fz_pixmap *src)
  1762. {
  1763. fz_pixmap *dst;
  1764. fz_colorspace *ss, *base;
  1765. const unsigned char *s;
  1766. unsigned char *d;
  1767. int y, x, k, sn, bn, a;
  1768. float src_v[FZ_MAX_COLORS];
  1769. float base_v[FZ_MAX_COLORS];
  1770. ptrdiff_t s_line_inc, d_line_inc;
  1771. ss = src->colorspace;
  1772. if (ss->type != FZ_COLORSPACE_SEPARATION)
  1773. fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot expand non-separation pixmap");
  1774. if (src->n != ss->n + src->alpha)
  1775. fz_throw(ctx, FZ_ERROR_ARGUMENT, "cannot expand separation pixmap mis-matching alpha channel");
  1776. base = ss->u.separation.base;
  1777. dst = fz_new_pixmap_with_bbox(ctx, base, fz_pixmap_bbox(ctx, src), src->seps, src->alpha);
  1778. fz_clear_pixmap(ctx, dst);
  1779. fz_try(ctx)
  1780. {
  1781. s = src->samples;
  1782. d = dst->samples;
  1783. s_line_inc = src->stride - src->w * (ptrdiff_t)src->n;
  1784. d_line_inc = dst->stride - dst->w * (ptrdiff_t)dst->n;
  1785. sn = ss->n;
  1786. bn = base->n;
  1787. if (base->type == FZ_COLORSPACE_LAB)
  1788. {
  1789. if (src->alpha)
  1790. {
  1791. for (y = 0; y < src->h; y++)
  1792. {
  1793. for (x = 0; x < src->w; x++)
  1794. {
  1795. for (k = 0; k < sn; ++k)
  1796. src_v[k] = *s++ / 255.0f;
  1797. a = *s++;
  1798. ss->u.separation.eval(ctx, ss->u.separation.tint, src_v, sn, base_v, bn);
  1799. *d++ = (base_v[0] / 100) * 255.0f;
  1800. *d++ = base_v[1] + 128;
  1801. *d++ = base_v[2] + 128;
  1802. *d++ = a;
  1803. }
  1804. s += s_line_inc;
  1805. d += d_line_inc;
  1806. }
  1807. }
  1808. else
  1809. {
  1810. for (y = 0; y < src->h; y++)
  1811. {
  1812. for (x = 0; x < src->w; x++)
  1813. {
  1814. for (k = 0; k < sn; ++k)
  1815. src_v[k] = *s++ / 255.0f;
  1816. ss->u.separation.eval(ctx, ss->u.separation.tint, src_v, sn, base_v, bn);
  1817. *d++ = (base_v[0] / 100) * 255.0f;
  1818. *d++ = base_v[1] + 128;
  1819. *d++ = base_v[2] + 128;
  1820. }
  1821. s += s_line_inc;
  1822. d += d_line_inc;
  1823. }
  1824. }
  1825. }
  1826. else
  1827. {
  1828. if (src->alpha)
  1829. {
  1830. for (y = 0; y < src->h; y++)
  1831. {
  1832. for (x = 0; x < src->w; x++)
  1833. {
  1834. for (k = 0; k < sn; ++k)
  1835. src_v[k] = *s++ / 255.0f;
  1836. a = *s++;
  1837. ss->u.separation.eval(ctx, ss->u.separation.tint, src_v, sn, base_v, bn);
  1838. for (k = 0; k < bn; ++k)
  1839. *d++ = base_v[k] * 255.0f;
  1840. *d++ = a;
  1841. }
  1842. s += s_line_inc;
  1843. d += d_line_inc;
  1844. }
  1845. }
  1846. else
  1847. {
  1848. for (y = 0; y < src->h; y++)
  1849. {
  1850. for (x = 0; x < src->w; x++)
  1851. {
  1852. for (k = 0; k < sn; ++k)
  1853. src_v[k] = *s++ / 255.0f;
  1854. ss->u.separation.eval(ctx, ss->u.separation.tint, src_v, sn, base_v, bn);
  1855. for (k = 0; k < bn; ++k)
  1856. *d++ = base_v[k] * 255.0f;
  1857. }
  1858. s += s_line_inc;
  1859. d += d_line_inc;
  1860. }
  1861. }
  1862. }
  1863. if (src->flags & FZ_PIXMAP_FLAG_INTERPOLATE)
  1864. dst->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
  1865. else
  1866. dst->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
  1867. }
  1868. fz_catch(ctx)
  1869. {
  1870. fz_drop_pixmap(ctx, dst);
  1871. fz_rethrow(ctx);
  1872. }
  1873. return dst;
  1874. }