Paste.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /*
  2. * The Python Imaging Library
  3. * $Id$
  4. *
  5. * paste image on another image
  6. *
  7. * history:
  8. * 96-03-27 fl Created
  9. * 96-07-16 fl Support "1", "L" and "RGBA" masks
  10. * 96-08-16 fl Merged with opaque paste
  11. * 97-01-17 fl Faster blending, added support for RGBa images
  12. * 97-08-27 fl Faster masking for 32-bit images
  13. * 98-02-02 fl Fixed MULDIV255 macro for gcc
  14. * 99-02-02 fl Added "RGBa" mask support
  15. * 99-02-06 fl Rewritten. Added support for masked fill operations.
  16. * 99-12-08 fl Fixed matte fill.
  17. *
  18. * Copyright (c) Fredrik Lundh 1996-97.
  19. * Copyright (c) Secret Labs AB 1997-99.
  20. *
  21. * See the README file for information on usage and redistribution.
  22. */
  23. #include "Imaging.h"
  24. static inline void
  25. paste(
  26. Imaging imOut,
  27. Imaging imIn,
  28. int dx,
  29. int dy,
  30. int sx,
  31. int sy,
  32. int xsize,
  33. int ysize,
  34. int pixelsize) {
  35. /* paste opaque region */
  36. int y;
  37. dx *= pixelsize;
  38. sx *= pixelsize;
  39. xsize *= pixelsize;
  40. for (y = 0; y < ysize; y++) {
  41. memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
  42. }
  43. }
  44. static inline void
  45. paste_mask_1(
  46. Imaging imOut,
  47. Imaging imIn,
  48. Imaging imMask,
  49. int dx,
  50. int dy,
  51. int sx,
  52. int sy,
  53. int xsize,
  54. int ysize,
  55. int pixelsize) {
  56. /* paste with mode "1" mask */
  57. int x, y;
  58. if (imOut->image8) {
  59. for (y = 0; y < ysize; y++) {
  60. UINT8 *out = imOut->image8[y + dy] + dx;
  61. UINT8 *in = imIn->image8[y + sy] + sx;
  62. UINT8 *mask = imMask->image8[y + sy] + sx;
  63. for (x = 0; x < xsize; x++) {
  64. if (*mask++) {
  65. *out = *in;
  66. }
  67. out++, in++;
  68. }
  69. }
  70. } else {
  71. for (y = 0; y < ysize; y++) {
  72. INT32 *out = imOut->image32[y + dy] + dx;
  73. INT32 *in = imIn->image32[y + sy] + sx;
  74. UINT8 *mask = imMask->image8[y + sy] + sx;
  75. for (x = 0; x < xsize; x++) {
  76. if (*mask++) {
  77. *out = *in;
  78. }
  79. out++, in++;
  80. }
  81. }
  82. }
  83. }
  84. static inline void
  85. paste_mask_L(
  86. Imaging imOut,
  87. Imaging imIn,
  88. Imaging imMask,
  89. int dx,
  90. int dy,
  91. int sx,
  92. int sy,
  93. int xsize,
  94. int ysize,
  95. int pixelsize) {
  96. /* paste with mode "L" matte */
  97. int x, y;
  98. unsigned int tmp1;
  99. if (imOut->image8) {
  100. for (y = 0; y < ysize; y++) {
  101. UINT8 *out = imOut->image8[y + dy] + dx;
  102. UINT8 *in = imIn->image8[y + sy] + sx;
  103. UINT8 *mask = imMask->image8[y + sy] + sx;
  104. for (x = 0; x < xsize; x++) {
  105. *out = BLEND(*mask, *out, *in, tmp1);
  106. out++, in++, mask++;
  107. }
  108. }
  109. } else {
  110. for (y = 0; y < ysize; y++) {
  111. UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
  112. UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
  113. UINT8 *mask = (UINT8 *)(imMask->image8[y + sy] + sx);
  114. for (x = 0; x < xsize; x++) {
  115. UINT8 a = mask[0];
  116. out[0] = BLEND(a, out[0], in[0], tmp1);
  117. out[1] = BLEND(a, out[1], in[1], tmp1);
  118. out[2] = BLEND(a, out[2], in[2], tmp1);
  119. out[3] = BLEND(a, out[3], in[3], tmp1);
  120. out += 4;
  121. in += 4;
  122. mask++;
  123. }
  124. }
  125. }
  126. }
  127. static inline void
  128. paste_mask_RGBA(
  129. Imaging imOut,
  130. Imaging imIn,
  131. Imaging imMask,
  132. int dx,
  133. int dy,
  134. int sx,
  135. int sy,
  136. int xsize,
  137. int ysize,
  138. int pixelsize) {
  139. /* paste with mode "RGBA" matte */
  140. int x, y;
  141. unsigned int tmp1;
  142. if (imOut->image8) {
  143. for (y = 0; y < ysize; y++) {
  144. UINT8 *out = imOut->image8[y + dy] + dx;
  145. UINT8 *in = imIn->image8[y + sy] + sx;
  146. UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
  147. for (x = 0; x < xsize; x++) {
  148. *out = BLEND(*mask, *out, *in, tmp1);
  149. out++, in++, mask += 4;
  150. }
  151. }
  152. } else {
  153. for (y = 0; y < ysize; y++) {
  154. UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
  155. UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
  156. UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
  157. for (x = 0; x < xsize; x++) {
  158. UINT8 a = mask[3];
  159. out[0] = BLEND(a, out[0], in[0], tmp1);
  160. out[1] = BLEND(a, out[1], in[1], tmp1);
  161. out[2] = BLEND(a, out[2], in[2], tmp1);
  162. out[3] = BLEND(a, out[3], in[3], tmp1);
  163. out += 4;
  164. in += 4;
  165. mask += 4;
  166. }
  167. }
  168. }
  169. }
  170. static inline void
  171. paste_mask_RGBa(
  172. Imaging imOut,
  173. Imaging imIn,
  174. Imaging imMask,
  175. int dx,
  176. int dy,
  177. int sx,
  178. int sy,
  179. int xsize,
  180. int ysize,
  181. int pixelsize) {
  182. /* paste with mode "RGBa" matte */
  183. int x, y;
  184. unsigned int tmp1;
  185. if (imOut->image8) {
  186. for (y = 0; y < ysize; y++) {
  187. UINT8 *out = imOut->image8[y + dy] + dx;
  188. UINT8 *in = imIn->image8[y + sy] + sx;
  189. UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
  190. for (x = 0; x < xsize; x++) {
  191. *out = PREBLEND(*mask, *out, *in, tmp1);
  192. out++, in++, mask += 4;
  193. }
  194. }
  195. } else {
  196. for (y = 0; y < ysize; y++) {
  197. UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
  198. UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
  199. UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
  200. for (x = 0; x < xsize; x++) {
  201. UINT8 a = mask[3];
  202. out[0] = PREBLEND(a, out[0], in[0], tmp1);
  203. out[1] = PREBLEND(a, out[1], in[1], tmp1);
  204. out[2] = PREBLEND(a, out[2], in[2], tmp1);
  205. out[3] = PREBLEND(a, out[3], in[3], tmp1);
  206. out += 4;
  207. in += 4;
  208. mask += 4;
  209. }
  210. }
  211. }
  212. }
  213. int
  214. ImagingPaste(
  215. Imaging imOut, Imaging imIn, Imaging imMask, int dx0, int dy0, int dx1, int dy1) {
  216. int xsize, ysize;
  217. int pixelsize;
  218. int sx0, sy0;
  219. ImagingSectionCookie cookie;
  220. if (!imOut || !imIn) {
  221. (void)ImagingError_ModeError();
  222. return -1;
  223. }
  224. pixelsize = imOut->pixelsize;
  225. xsize = dx1 - dx0;
  226. ysize = dy1 - dy0;
  227. if (xsize != imIn->xsize || ysize != imIn->ysize || pixelsize != imIn->pixelsize) {
  228. (void)ImagingError_Mismatch();
  229. return -1;
  230. }
  231. if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
  232. (void)ImagingError_Mismatch();
  233. return -1;
  234. }
  235. /* Determine which region to copy */
  236. sx0 = sy0 = 0;
  237. if (dx0 < 0) {
  238. xsize += dx0, sx0 = -dx0, dx0 = 0;
  239. }
  240. if (dx0 + xsize > imOut->xsize) {
  241. xsize = imOut->xsize - dx0;
  242. }
  243. if (dy0 < 0) {
  244. ysize += dy0, sy0 = -dy0, dy0 = 0;
  245. }
  246. if (dy0 + ysize > imOut->ysize) {
  247. ysize = imOut->ysize - dy0;
  248. }
  249. if (xsize <= 0 || ysize <= 0) {
  250. return 0;
  251. }
  252. if (!imMask) {
  253. ImagingSectionEnter(&cookie);
  254. paste(imOut, imIn, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  255. ImagingSectionLeave(&cookie);
  256. } else if (strcmp(imMask->mode, "1") == 0) {
  257. ImagingSectionEnter(&cookie);
  258. paste_mask_1(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  259. ImagingSectionLeave(&cookie);
  260. } else if (strcmp(imMask->mode, "L") == 0) {
  261. ImagingSectionEnter(&cookie);
  262. paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  263. ImagingSectionLeave(&cookie);
  264. } else if (strcmp(imMask->mode, "LA") == 0 || strcmp(imMask->mode, "RGBA") == 0) {
  265. ImagingSectionEnter(&cookie);
  266. paste_mask_RGBA(
  267. imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  268. ImagingSectionLeave(&cookie);
  269. } else if (strcmp(imMask->mode, "RGBa") == 0) {
  270. ImagingSectionEnter(&cookie);
  271. paste_mask_RGBa(
  272. imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  273. ImagingSectionLeave(&cookie);
  274. } else {
  275. (void)ImagingError_ValueError("bad transparency mask");
  276. return -1;
  277. }
  278. return 0;
  279. }
  280. static inline void
  281. fill(
  282. Imaging imOut,
  283. const void *ink_,
  284. int dx,
  285. int dy,
  286. int xsize,
  287. int ysize,
  288. int pixelsize) {
  289. /* fill opaque region */
  290. int x, y;
  291. UINT8 ink8 = 0;
  292. INT32 ink32 = 0L;
  293. memcpy(&ink32, ink_, pixelsize);
  294. memcpy(&ink8, ink_, sizeof(ink8));
  295. if (imOut->image8 || ink32 == 0L) {
  296. dx *= pixelsize;
  297. xsize *= pixelsize;
  298. for (y = 0; y < ysize; y++) {
  299. memset(imOut->image[y + dy] + dx, ink8, xsize);
  300. }
  301. } else {
  302. for (y = 0; y < ysize; y++) {
  303. INT32 *out = imOut->image32[y + dy] + dx;
  304. for (x = 0; x < xsize; x++) {
  305. out[x] = ink32;
  306. }
  307. }
  308. }
  309. }
  310. static inline void
  311. fill_mask_1(
  312. Imaging imOut,
  313. const void *ink_,
  314. Imaging imMask,
  315. int dx,
  316. int dy,
  317. int sx,
  318. int sy,
  319. int xsize,
  320. int ysize,
  321. int pixelsize) {
  322. /* fill with mode "1" mask */
  323. int x, y;
  324. UINT8 ink8 = 0;
  325. INT32 ink32 = 0L;
  326. memcpy(&ink32, ink_, pixelsize);
  327. memcpy(&ink8, ink_, sizeof(ink8));
  328. if (imOut->image8) {
  329. for (y = 0; y < ysize; y++) {
  330. UINT8 *out = imOut->image8[y + dy] + dx;
  331. UINT8 *mask = imMask->image8[y + sy] + sx;
  332. for (x = 0; x < xsize; x++) {
  333. if (*mask++) {
  334. *out = ink8;
  335. }
  336. out++;
  337. }
  338. }
  339. } else {
  340. for (y = 0; y < ysize; y++) {
  341. INT32 *out = imOut->image32[y + dy] + dx;
  342. UINT8 *mask = imMask->image8[y + sy] + sx;
  343. for (x = 0; x < xsize; x++) {
  344. if (*mask++) {
  345. *out = ink32;
  346. }
  347. out++;
  348. }
  349. }
  350. }
  351. }
  352. static inline void
  353. fill_mask_L(
  354. Imaging imOut,
  355. const UINT8 *ink,
  356. Imaging imMask,
  357. int dx,
  358. int dy,
  359. int sx,
  360. int sy,
  361. int xsize,
  362. int ysize,
  363. int pixelsize) {
  364. /* fill with mode "L" matte */
  365. int x, y, i;
  366. unsigned int tmp1;
  367. if (imOut->image8) {
  368. for (y = 0; y < ysize; y++) {
  369. UINT8 *out = imOut->image8[y + dy] + dx;
  370. if (strncmp(imOut->mode, "I;16", 4) == 0) {
  371. out += dx;
  372. }
  373. UINT8 *mask = imMask->image8[y + sy] + sx;
  374. for (x = 0; x < xsize; x++) {
  375. *out = BLEND(*mask, *out, ink[0], tmp1);
  376. if (strncmp(imOut->mode, "I;16", 4) == 0) {
  377. out++;
  378. *out = BLEND(*mask, *out, ink[1], tmp1);
  379. }
  380. out++, mask++;
  381. }
  382. }
  383. } else {
  384. int alpha_channel = strcmp(imOut->mode, "RGBa") == 0 ||
  385. strcmp(imOut->mode, "RGBA") == 0 ||
  386. strcmp(imOut->mode, "La") == 0 ||
  387. strcmp(imOut->mode, "LA") == 0 ||
  388. strcmp(imOut->mode, "PA") == 0;
  389. for (y = 0; y < ysize; y++) {
  390. UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx * pixelsize;
  391. UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
  392. for (x = 0; x < xsize; x++) {
  393. for (i = 0; i < pixelsize; i++) {
  394. UINT8 channel_mask = *mask;
  395. if (alpha_channel && i != 3 && channel_mask != 0) {
  396. channel_mask =
  397. 255 - (255 - channel_mask) * (1 - (255 - out[3]) / 255);
  398. }
  399. out[i] = BLEND(channel_mask, out[i], ink[i], tmp1);
  400. }
  401. out += pixelsize;
  402. mask++;
  403. }
  404. }
  405. }
  406. }
  407. static inline void
  408. fill_mask_RGBA(
  409. Imaging imOut,
  410. const UINT8 *ink,
  411. Imaging imMask,
  412. int dx,
  413. int dy,
  414. int sx,
  415. int sy,
  416. int xsize,
  417. int ysize,
  418. int pixelsize) {
  419. /* fill with mode "RGBA" matte */
  420. int x, y, i;
  421. unsigned int tmp1;
  422. if (imOut->image8) {
  423. sx = sx * 4 + 3;
  424. for (y = 0; y < ysize; y++) {
  425. UINT8 *out = imOut->image8[y + dy] + dx;
  426. UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
  427. for (x = 0; x < xsize; x++) {
  428. *out = BLEND(*mask, *out, ink[0], tmp1);
  429. out++, mask += 4;
  430. }
  431. }
  432. } else {
  433. dx *= pixelsize;
  434. sx = sx * 4 + 3;
  435. for (y = 0; y < ysize; y++) {
  436. UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx;
  437. UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
  438. for (x = 0; x < xsize; x++) {
  439. for (i = 0; i < pixelsize; i++) {
  440. *out = BLEND(*mask, *out, ink[i], tmp1);
  441. out++;
  442. }
  443. mask += 4;
  444. }
  445. }
  446. }
  447. }
  448. static inline void
  449. fill_mask_RGBa(
  450. Imaging imOut,
  451. const UINT8 *ink,
  452. Imaging imMask,
  453. int dx,
  454. int dy,
  455. int sx,
  456. int sy,
  457. int xsize,
  458. int ysize,
  459. int pixelsize) {
  460. /* fill with mode "RGBa" matte */
  461. int x, y, i;
  462. unsigned int tmp1;
  463. if (imOut->image8) {
  464. sx = sx * 4 + 3;
  465. for (y = 0; y < ysize; y++) {
  466. UINT8 *out = imOut->image8[y + dy] + dx;
  467. UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
  468. for (x = 0; x < xsize; x++) {
  469. *out = PREBLEND(*mask, *out, ink[0], tmp1);
  470. out++, mask += 4;
  471. }
  472. }
  473. } else {
  474. dx *= pixelsize;
  475. sx = sx * 4 + 3;
  476. for (y = 0; y < ysize; y++) {
  477. UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx;
  478. UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
  479. for (x = 0; x < xsize; x++) {
  480. for (i = 0; i < pixelsize; i++) {
  481. *out = PREBLEND(*mask, *out, ink[i], tmp1);
  482. out++;
  483. }
  484. mask += 4;
  485. }
  486. }
  487. }
  488. }
  489. int
  490. ImagingFill2(
  491. Imaging imOut,
  492. const void *ink,
  493. Imaging imMask,
  494. int dx0,
  495. int dy0,
  496. int dx1,
  497. int dy1) {
  498. ImagingSectionCookie cookie;
  499. int xsize, ysize;
  500. int pixelsize;
  501. int sx0, sy0;
  502. if (!imOut || !ink) {
  503. (void)ImagingError_ModeError();
  504. return -1;
  505. }
  506. pixelsize = imOut->pixelsize;
  507. xsize = dx1 - dx0;
  508. ysize = dy1 - dy0;
  509. if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
  510. (void)ImagingError_Mismatch();
  511. return -1;
  512. }
  513. /* Determine which region to fill */
  514. sx0 = sy0 = 0;
  515. if (dx0 < 0) {
  516. xsize += dx0, sx0 = -dx0, dx0 = 0;
  517. }
  518. if (dx0 + xsize > imOut->xsize) {
  519. xsize = imOut->xsize - dx0;
  520. }
  521. if (dy0 < 0) {
  522. ysize += dy0, sy0 = -dy0, dy0 = 0;
  523. }
  524. if (dy0 + ysize > imOut->ysize) {
  525. ysize = imOut->ysize - dy0;
  526. }
  527. if (xsize <= 0 || ysize <= 0) {
  528. return 0;
  529. }
  530. if (!imMask) {
  531. ImagingSectionEnter(&cookie);
  532. fill(imOut, ink, dx0, dy0, xsize, ysize, pixelsize);
  533. ImagingSectionLeave(&cookie);
  534. } else if (strcmp(imMask->mode, "1") == 0) {
  535. ImagingSectionEnter(&cookie);
  536. fill_mask_1(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  537. ImagingSectionLeave(&cookie);
  538. } else if (strcmp(imMask->mode, "L") == 0) {
  539. ImagingSectionEnter(&cookie);
  540. fill_mask_L(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  541. ImagingSectionLeave(&cookie);
  542. } else if (strcmp(imMask->mode, "RGBA") == 0) {
  543. ImagingSectionEnter(&cookie);
  544. fill_mask_RGBA(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  545. ImagingSectionLeave(&cookie);
  546. } else if (strcmp(imMask->mode, "RGBa") == 0) {
  547. ImagingSectionEnter(&cookie);
  548. fill_mask_RGBa(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  549. ImagingSectionLeave(&cookie);
  550. } else {
  551. (void)ImagingError_ValueError("bad transparency mask");
  552. return -1;
  553. }
  554. return 0;
  555. }