pngwtran.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /* pngwtran.c - transforms the data in a row for PNG writers
  2. *
  3. * Copyright (c) 2018 Cosmin Truta
  4. * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
  5. * Copyright (c) 1996-1997 Andreas Dilger
  6. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
  7. *
  8. * This code is released under the libpng license.
  9. * For conditions of distribution and use, see the disclaimer
  10. * and license in png.h
  11. */
  12. #include "pngpriv.h"
  13. #ifdef PNG_WRITE_SUPPORTED
  14. #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
  15. #ifdef PNG_WRITE_PACK_SUPPORTED
  16. /* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
  17. * row_info bit depth should be 8 (one pixel per byte). The channels
  18. * should be 1 (this only happens on grayscale and paletted images).
  19. */
  20. static void
  21. png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
  22. {
  23. png_debug(1, "in png_do_pack");
  24. if (row_info->bit_depth == 8 &&
  25. row_info->channels == 1)
  26. {
  27. switch ((int)bit_depth)
  28. {
  29. case 1:
  30. {
  31. png_bytep sp, dp;
  32. int mask, v;
  33. png_uint_32 i;
  34. png_uint_32 row_width = row_info->width;
  35. sp = row;
  36. dp = row;
  37. mask = 0x80;
  38. v = 0;
  39. for (i = 0; i < row_width; i++)
  40. {
  41. if (*sp != 0)
  42. v |= mask;
  43. sp++;
  44. if (mask > 1)
  45. mask >>= 1;
  46. else
  47. {
  48. mask = 0x80;
  49. *dp = (png_byte)v;
  50. dp++;
  51. v = 0;
  52. }
  53. }
  54. if (mask != 0x80)
  55. *dp = (png_byte)v;
  56. break;
  57. }
  58. case 2:
  59. {
  60. png_bytep sp, dp;
  61. unsigned int shift;
  62. int v;
  63. png_uint_32 i;
  64. png_uint_32 row_width = row_info->width;
  65. sp = row;
  66. dp = row;
  67. shift = 6;
  68. v = 0;
  69. for (i = 0; i < row_width; i++)
  70. {
  71. png_byte value;
  72. value = (png_byte)(*sp & 0x03);
  73. v |= (value << shift);
  74. if (shift == 0)
  75. {
  76. shift = 6;
  77. *dp = (png_byte)v;
  78. dp++;
  79. v = 0;
  80. }
  81. else
  82. shift -= 2;
  83. sp++;
  84. }
  85. if (shift != 6)
  86. *dp = (png_byte)v;
  87. break;
  88. }
  89. case 4:
  90. {
  91. png_bytep sp, dp;
  92. unsigned int shift;
  93. int v;
  94. png_uint_32 i;
  95. png_uint_32 row_width = row_info->width;
  96. sp = row;
  97. dp = row;
  98. shift = 4;
  99. v = 0;
  100. for (i = 0; i < row_width; i++)
  101. {
  102. png_byte value;
  103. value = (png_byte)(*sp & 0x0f);
  104. v |= (value << shift);
  105. if (shift == 0)
  106. {
  107. shift = 4;
  108. *dp = (png_byte)v;
  109. dp++;
  110. v = 0;
  111. }
  112. else
  113. shift -= 4;
  114. sp++;
  115. }
  116. if (shift != 4)
  117. *dp = (png_byte)v;
  118. break;
  119. }
  120. default:
  121. break;
  122. }
  123. row_info->bit_depth = (png_byte)bit_depth;
  124. row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
  125. row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
  126. row_info->width);
  127. }
  128. }
  129. #endif
  130. #ifdef PNG_WRITE_SHIFT_SUPPORTED
  131. /* Shift pixel values to take advantage of whole range. Pass the
  132. * true number of bits in bit_depth. The row should be packed
  133. * according to row_info->bit_depth. Thus, if you had a row of
  134. * bit depth 4, but the pixels only had values from 0 to 7, you
  135. * would pass 3 as bit_depth, and this routine would translate the
  136. * data to 0 to 15.
  137. */
  138. static void
  139. png_do_shift(png_row_infop row_info, png_bytep row,
  140. png_const_color_8p bit_depth)
  141. {
  142. png_debug(1, "in png_do_shift");
  143. if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
  144. {
  145. int shift_start[4], shift_dec[4];
  146. unsigned int channels = 0;
  147. if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
  148. {
  149. shift_start[channels] = row_info->bit_depth - bit_depth->red;
  150. shift_dec[channels] = bit_depth->red;
  151. channels++;
  152. shift_start[channels] = row_info->bit_depth - bit_depth->green;
  153. shift_dec[channels] = bit_depth->green;
  154. channels++;
  155. shift_start[channels] = row_info->bit_depth - bit_depth->blue;
  156. shift_dec[channels] = bit_depth->blue;
  157. channels++;
  158. }
  159. else
  160. {
  161. shift_start[channels] = row_info->bit_depth - bit_depth->gray;
  162. shift_dec[channels] = bit_depth->gray;
  163. channels++;
  164. }
  165. if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
  166. {
  167. shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
  168. shift_dec[channels] = bit_depth->alpha;
  169. channels++;
  170. }
  171. /* With low row depths, could only be grayscale, so one channel */
  172. if (row_info->bit_depth < 8)
  173. {
  174. png_bytep bp = row;
  175. size_t i;
  176. unsigned int mask;
  177. size_t row_bytes = row_info->rowbytes;
  178. if (bit_depth->gray == 1 && row_info->bit_depth == 2)
  179. mask = 0x55;
  180. else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
  181. mask = 0x11;
  182. else
  183. mask = 0xff;
  184. for (i = 0; i < row_bytes; i++, bp++)
  185. {
  186. int j;
  187. unsigned int v, out;
  188. v = *bp;
  189. out = 0;
  190. for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
  191. {
  192. if (j > 0)
  193. out |= v << j;
  194. else
  195. out |= (v >> (-j)) & mask;
  196. }
  197. *bp = (png_byte)(out & 0xff);
  198. }
  199. }
  200. else if (row_info->bit_depth == 8)
  201. {
  202. png_bytep bp = row;
  203. png_uint_32 i;
  204. png_uint_32 istop = channels * row_info->width;
  205. for (i = 0; i < istop; i++, bp++)
  206. {
  207. unsigned int c = i%channels;
  208. int j;
  209. unsigned int v, out;
  210. v = *bp;
  211. out = 0;
  212. for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
  213. {
  214. if (j > 0)
  215. out |= v << j;
  216. else
  217. out |= v >> (-j);
  218. }
  219. *bp = (png_byte)(out & 0xff);
  220. }
  221. }
  222. else
  223. {
  224. png_bytep bp;
  225. png_uint_32 i;
  226. png_uint_32 istop = channels * row_info->width;
  227. for (bp = row, i = 0; i < istop; i++)
  228. {
  229. unsigned int c = i%channels;
  230. int j;
  231. unsigned int value, v;
  232. v = png_get_uint_16(bp);
  233. value = 0;
  234. for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
  235. {
  236. if (j > 0)
  237. value |= v << j;
  238. else
  239. value |= v >> (-j);
  240. }
  241. *bp++ = (png_byte)((value >> 8) & 0xff);
  242. *bp++ = (png_byte)(value & 0xff);
  243. }
  244. }
  245. }
  246. }
  247. #endif
  248. #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
  249. static void
  250. png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
  251. {
  252. png_debug(1, "in png_do_write_swap_alpha");
  253. {
  254. if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  255. {
  256. if (row_info->bit_depth == 8)
  257. {
  258. /* This converts from ARGB to RGBA */
  259. png_bytep sp, dp;
  260. png_uint_32 i;
  261. png_uint_32 row_width = row_info->width;
  262. for (i = 0, sp = dp = row; i < row_width; i++)
  263. {
  264. png_byte save = *(sp++);
  265. *(dp++) = *(sp++);
  266. *(dp++) = *(sp++);
  267. *(dp++) = *(sp++);
  268. *(dp++) = save;
  269. }
  270. }
  271. #ifdef PNG_WRITE_16BIT_SUPPORTED
  272. else
  273. {
  274. /* This converts from AARRGGBB to RRGGBBAA */
  275. png_bytep sp, dp;
  276. png_uint_32 i;
  277. png_uint_32 row_width = row_info->width;
  278. for (i = 0, sp = dp = row; i < row_width; i++)
  279. {
  280. png_byte save[2];
  281. save[0] = *(sp++);
  282. save[1] = *(sp++);
  283. *(dp++) = *(sp++);
  284. *(dp++) = *(sp++);
  285. *(dp++) = *(sp++);
  286. *(dp++) = *(sp++);
  287. *(dp++) = *(sp++);
  288. *(dp++) = *(sp++);
  289. *(dp++) = save[0];
  290. *(dp++) = save[1];
  291. }
  292. }
  293. #endif /* WRITE_16BIT */
  294. }
  295. else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  296. {
  297. if (row_info->bit_depth == 8)
  298. {
  299. /* This converts from AG to GA */
  300. png_bytep sp, dp;
  301. png_uint_32 i;
  302. png_uint_32 row_width = row_info->width;
  303. for (i = 0, sp = dp = row; i < row_width; i++)
  304. {
  305. png_byte save = *(sp++);
  306. *(dp++) = *(sp++);
  307. *(dp++) = save;
  308. }
  309. }
  310. #ifdef PNG_WRITE_16BIT_SUPPORTED
  311. else
  312. {
  313. /* This converts from AAGG to GGAA */
  314. png_bytep sp, dp;
  315. png_uint_32 i;
  316. png_uint_32 row_width = row_info->width;
  317. for (i = 0, sp = dp = row; i < row_width; i++)
  318. {
  319. png_byte save[2];
  320. save[0] = *(sp++);
  321. save[1] = *(sp++);
  322. *(dp++) = *(sp++);
  323. *(dp++) = *(sp++);
  324. *(dp++) = save[0];
  325. *(dp++) = save[1];
  326. }
  327. }
  328. #endif /* WRITE_16BIT */
  329. }
  330. }
  331. }
  332. #endif
  333. #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
  334. static void
  335. png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
  336. {
  337. png_debug(1, "in png_do_write_invert_alpha");
  338. {
  339. if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  340. {
  341. if (row_info->bit_depth == 8)
  342. {
  343. /* This inverts the alpha channel in RGBA */
  344. png_bytep sp, dp;
  345. png_uint_32 i;
  346. png_uint_32 row_width = row_info->width;
  347. for (i = 0, sp = dp = row; i < row_width; i++)
  348. {
  349. /* Does nothing
  350. *(dp++) = *(sp++);
  351. *(dp++) = *(sp++);
  352. *(dp++) = *(sp++);
  353. */
  354. sp+=3; dp = sp;
  355. *dp = (png_byte)(255 - *(sp++));
  356. }
  357. }
  358. #ifdef PNG_WRITE_16BIT_SUPPORTED
  359. else
  360. {
  361. /* This inverts the alpha channel in RRGGBBAA */
  362. png_bytep sp, dp;
  363. png_uint_32 i;
  364. png_uint_32 row_width = row_info->width;
  365. for (i = 0, sp = dp = row; i < row_width; i++)
  366. {
  367. /* Does nothing
  368. *(dp++) = *(sp++);
  369. *(dp++) = *(sp++);
  370. *(dp++) = *(sp++);
  371. *(dp++) = *(sp++);
  372. *(dp++) = *(sp++);
  373. *(dp++) = *(sp++);
  374. */
  375. sp+=6; dp = sp;
  376. *(dp++) = (png_byte)(255 - *(sp++));
  377. *dp = (png_byte)(255 - *(sp++));
  378. }
  379. }
  380. #endif /* WRITE_16BIT */
  381. }
  382. else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  383. {
  384. if (row_info->bit_depth == 8)
  385. {
  386. /* This inverts the alpha channel in GA */
  387. png_bytep sp, dp;
  388. png_uint_32 i;
  389. png_uint_32 row_width = row_info->width;
  390. for (i = 0, sp = dp = row; i < row_width; i++)
  391. {
  392. *(dp++) = *(sp++);
  393. *(dp++) = (png_byte)(255 - *(sp++));
  394. }
  395. }
  396. #ifdef PNG_WRITE_16BIT_SUPPORTED
  397. else
  398. {
  399. /* This inverts the alpha channel in GGAA */
  400. png_bytep sp, dp;
  401. png_uint_32 i;
  402. png_uint_32 row_width = row_info->width;
  403. for (i = 0, sp = dp = row; i < row_width; i++)
  404. {
  405. /* Does nothing
  406. *(dp++) = *(sp++);
  407. *(dp++) = *(sp++);
  408. */
  409. sp+=2; dp = sp;
  410. *(dp++) = (png_byte)(255 - *(sp++));
  411. *dp = (png_byte)(255 - *(sp++));
  412. }
  413. }
  414. #endif /* WRITE_16BIT */
  415. }
  416. }
  417. }
  418. #endif
  419. /* Transform the data according to the user's wishes. The order of
  420. * transformations is significant.
  421. */
  422. void /* PRIVATE */
  423. png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
  424. {
  425. png_debug(1, "in png_do_write_transformations");
  426. if (png_ptr == NULL)
  427. return;
  428. #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
  429. if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
  430. if (png_ptr->write_user_transform_fn != NULL)
  431. (*(png_ptr->write_user_transform_fn)) /* User write transform
  432. function */
  433. (png_ptr, /* png_ptr */
  434. row_info, /* row_info: */
  435. /* png_uint_32 width; width of row */
  436. /* size_t rowbytes; number of bytes in row */
  437. /* png_byte color_type; color type of pixels */
  438. /* png_byte bit_depth; bit depth of samples */
  439. /* png_byte channels; number of channels (1-4) */
  440. /* png_byte pixel_depth; bits per pixel (depth*channels) */
  441. png_ptr->row_buf + 1); /* start of pixel data for row */
  442. #endif
  443. #ifdef PNG_WRITE_FILLER_SUPPORTED
  444. if ((png_ptr->transformations & PNG_FILLER) != 0)
  445. png_do_strip_channel(row_info, png_ptr->row_buf + 1,
  446. !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
  447. #endif
  448. #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
  449. if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
  450. png_do_packswap(row_info, png_ptr->row_buf + 1);
  451. #endif
  452. #ifdef PNG_WRITE_PACK_SUPPORTED
  453. if ((png_ptr->transformations & PNG_PACK) != 0)
  454. png_do_pack(row_info, png_ptr->row_buf + 1,
  455. (png_uint_32)png_ptr->bit_depth);
  456. #endif
  457. #ifdef PNG_WRITE_SWAP_SUPPORTED
  458. # ifdef PNG_16BIT_SUPPORTED
  459. if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
  460. png_do_swap(row_info, png_ptr->row_buf + 1);
  461. # endif
  462. #endif
  463. #ifdef PNG_WRITE_SHIFT_SUPPORTED
  464. if ((png_ptr->transformations & PNG_SHIFT) != 0)
  465. png_do_shift(row_info, png_ptr->row_buf + 1,
  466. &(png_ptr->shift));
  467. #endif
  468. #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
  469. if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
  470. png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
  471. #endif
  472. #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
  473. if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
  474. png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
  475. #endif
  476. #ifdef PNG_WRITE_BGR_SUPPORTED
  477. if ((png_ptr->transformations & PNG_BGR) != 0)
  478. png_do_bgr(row_info, png_ptr->row_buf + 1);
  479. #endif
  480. #ifdef PNG_WRITE_INVERT_SUPPORTED
  481. if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
  482. png_do_invert(row_info, png_ptr->row_buf + 1);
  483. #endif
  484. }
  485. #endif /* WRITE_TRANSFORMS */
  486. #endif /* WRITE */