pngwtran.c 15 KB

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