Paste.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  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(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy,
  26. int xsize, int ysize, int pixelsize)
  27. {
  28. /* paste opaque region */
  29. int y;
  30. dx *= pixelsize;
  31. sx *= pixelsize;
  32. xsize *= pixelsize;
  33. for (y = 0; y < ysize; y++)
  34. memcpy(imOut->image[y+dy]+dx, imIn->image[y+sy]+sx, xsize);
  35. }
  36. static inline void
  37. paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask,
  38. int dx, int dy, int sx, int sy,
  39. int xsize, int ysize, int pixelsize)
  40. {
  41. /* paste with mode "1" mask */
  42. int x, y;
  43. if (imOut->image8) {
  44. for (y = 0; y < ysize; y++) {
  45. UINT8* out = imOut->image8[y+dy]+dx;
  46. UINT8* in = imIn->image8[y+sy]+sx;
  47. UINT8* mask = imMask->image8[y+sy]+sx;
  48. for (x = 0; x < xsize; x++) {
  49. if (*mask++)
  50. *out = *in;
  51. out++, in++;
  52. }
  53. }
  54. } else {
  55. for (y = 0; y < ysize; y++) {
  56. INT32* out = imOut->image32[y+dy]+dx;
  57. INT32* in = imIn->image32[y+sy]+sx;
  58. UINT8* mask = imMask->image8[y+sy]+sx;
  59. for (x = 0; x < xsize; x++) {
  60. if (*mask++)
  61. *out = *in;
  62. out++, in++;
  63. }
  64. }
  65. }
  66. }
  67. static inline void
  68. paste_mask_L(Imaging imOut, Imaging imIn, Imaging imMask,
  69. int dx, int dy, int sx, int sy,
  70. int xsize, int ysize, int pixelsize)
  71. {
  72. /* paste with mode "L" matte */
  73. int x, y;
  74. unsigned int tmp1;
  75. if (imOut->image8) {
  76. for (y = 0; y < ysize; y++) {
  77. UINT8* out = imOut->image8[y+dy]+dx;
  78. UINT8* in = imIn->image8[y+sy]+sx;
  79. UINT8* mask = imMask->image8[y+sy]+sx;
  80. for (x = 0; x < xsize; x++) {
  81. *out = BLEND(*mask, *out, *in, tmp1);
  82. out++, in++, mask++;
  83. }
  84. }
  85. } else {
  86. for (y = 0; y < ysize; y++) {
  87. UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx);
  88. UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx);
  89. UINT8* mask = (UINT8*) (imMask->image8[y+sy] + sx);
  90. for (x = 0; x < xsize; x++) {
  91. UINT8 a = mask[0];
  92. out[0] = BLEND(a, out[0], in[0], tmp1);
  93. out[1] = BLEND(a, out[1], in[1], tmp1);
  94. out[2] = BLEND(a, out[2], in[2], tmp1);
  95. out[3] = BLEND(a, out[3], in[3], tmp1);
  96. out += 4; in += 4; mask ++;
  97. }
  98. }
  99. }
  100. }
  101. static inline void
  102. paste_mask_RGBA(Imaging imOut, Imaging imIn, Imaging imMask,
  103. int dx, int dy, int sx, int sy,
  104. int xsize, int ysize, int pixelsize)
  105. {
  106. /* paste with mode "RGBA" matte */
  107. int x, y;
  108. unsigned int tmp1;
  109. if (imOut->image8) {
  110. for (y = 0; y < ysize; y++) {
  111. UINT8* out = imOut->image8[y+dy]+dx;
  112. UINT8* in = imIn->image8[y+sy]+sx;
  113. UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
  114. for (x = 0; x < xsize; x++) {
  115. *out = BLEND(*mask, *out, *in, tmp1);
  116. out++, in++, mask += 4;
  117. }
  118. }
  119. } else {
  120. for (y = 0; y < ysize; y++) {
  121. UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx);
  122. UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx);
  123. UINT8* mask = (UINT8*) (imMask->image32[y+sy] + sx);
  124. for (x = 0; x < xsize; x++) {
  125. UINT8 a = mask[3];
  126. out[0] = BLEND(a, out[0], in[0], tmp1);
  127. out[1] = BLEND(a, out[1], in[1], tmp1);
  128. out[2] = BLEND(a, out[2], in[2], tmp1);
  129. out[3] = BLEND(a, out[3], in[3], tmp1);
  130. out += 4; in += 4; mask += 4;
  131. }
  132. }
  133. }
  134. }
  135. static inline void
  136. paste_mask_RGBa(Imaging imOut, Imaging imIn, Imaging imMask,
  137. int dx, int dy, int sx, int sy,
  138. int xsize, int ysize, int pixelsize)
  139. {
  140. /* paste with mode "RGBa" matte */
  141. int x, y;
  142. unsigned int tmp1;
  143. if (imOut->image8) {
  144. for (y = 0; y < ysize; y++) {
  145. UINT8* out = imOut->image8[y+dy]+dx;
  146. UINT8* in = imIn->image8[y+sy]+sx;
  147. UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
  148. for (x = 0; x < xsize; x++) {
  149. *out = PREBLEND(*mask, *out, *in, tmp1);
  150. out++, in++, mask += 4;
  151. }
  152. }
  153. } else {
  154. for (y = 0; y < ysize; y++) {
  155. UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx);
  156. UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx);
  157. UINT8* mask = (UINT8*) (imMask->image32[y+sy] + sx);
  158. for (x = 0; x < xsize; x++) {
  159. UINT8 a = mask[3];
  160. out[0] = PREBLEND(a, out[0], in[0], tmp1);
  161. out[1] = PREBLEND(a, out[1], in[1], tmp1);
  162. out[2] = PREBLEND(a, out[2], in[2], tmp1);
  163. out[3] = PREBLEND(a, out[3], in[3], tmp1);
  164. out += 4; in += 4; mask += 4;
  165. }
  166. }
  167. }
  168. }
  169. int
  170. ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
  171. int dx0, int dy0, int dx1, int dy1)
  172. {
  173. int xsize, ysize;
  174. int pixelsize;
  175. int sx0, sy0;
  176. ImagingSectionCookie cookie;
  177. if (!imOut || !imIn) {
  178. (void) ImagingError_ModeError();
  179. return -1;
  180. }
  181. pixelsize = imOut->pixelsize;
  182. xsize = dx1 - dx0;
  183. ysize = dy1 - dy0;
  184. if (xsize != imIn->xsize || ysize != imIn->ysize ||
  185. pixelsize != imIn->pixelsize) {
  186. (void) ImagingError_Mismatch();
  187. return -1;
  188. }
  189. if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
  190. (void) ImagingError_Mismatch();
  191. return -1;
  192. }
  193. /* Determine which region to copy */
  194. sx0 = sy0 = 0;
  195. if (dx0 < 0)
  196. xsize += dx0, sx0 = -dx0, dx0 = 0;
  197. if (dx0 + xsize > imOut->xsize)
  198. xsize = imOut->xsize - dx0;
  199. if (dy0 < 0)
  200. ysize += dy0, sy0 = -dy0, dy0 = 0;
  201. if (dy0 + ysize > imOut->ysize)
  202. ysize = imOut->ysize - dy0;
  203. if (xsize <= 0 || ysize <= 0)
  204. return 0;
  205. if (!imMask) {
  206. ImagingSectionEnter(&cookie);
  207. paste(imOut, imIn, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
  208. ImagingSectionLeave(&cookie);
  209. } else if (strcmp(imMask->mode, "1") == 0) {
  210. ImagingSectionEnter(&cookie);
  211. paste_mask_1(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
  212. xsize, ysize, pixelsize);
  213. ImagingSectionLeave(&cookie);
  214. } else if (strcmp(imMask->mode, "L") == 0) {
  215. ImagingSectionEnter(&cookie);
  216. paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
  217. xsize, ysize, pixelsize);
  218. ImagingSectionLeave(&cookie);
  219. } else if (strcmp(imMask->mode, "RGBA") == 0) {
  220. ImagingSectionEnter(&cookie);
  221. paste_mask_RGBA(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
  222. xsize, ysize, pixelsize);
  223. ImagingSectionLeave(&cookie);
  224. } else if (strcmp(imMask->mode, "RGBa") == 0) {
  225. ImagingSectionEnter(&cookie);
  226. paste_mask_RGBa(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
  227. xsize, ysize, pixelsize);
  228. ImagingSectionLeave(&cookie);
  229. } else {
  230. (void) ImagingError_ValueError("bad transparency mask");
  231. return -1;
  232. }
  233. return 0;
  234. }
  235. static inline void
  236. fill(Imaging imOut, const void* ink_, int dx, int dy,
  237. int xsize, int ysize, int pixelsize)
  238. {
  239. /* fill opaque region */
  240. int x, y;
  241. UINT8 ink8 = 0;
  242. INT32 ink32 = 0L;
  243. memcpy(&ink32, ink_, pixelsize);
  244. memcpy(&ink8, ink_, sizeof(ink8));
  245. if (imOut->image8 || ink32 == 0L) {
  246. dx *= pixelsize;
  247. xsize *= pixelsize;
  248. for (y = 0; y < ysize; y++)
  249. memset(imOut->image[y+dy]+dx, ink8, xsize);
  250. } else {
  251. for (y = 0; y < ysize; y++) {
  252. INT32* out = imOut->image32[y+dy]+dx;
  253. for (x = 0; x < xsize; x++)
  254. out[x] = ink32;
  255. }
  256. }
  257. }
  258. static inline void
  259. fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
  260. int dx, int dy, int sx, int sy,
  261. int xsize, int ysize, int pixelsize)
  262. {
  263. /* fill with mode "1" mask */
  264. int x, y;
  265. UINT8 ink8 = 0;
  266. INT32 ink32 = 0L;
  267. memcpy(&ink32, ink_, pixelsize);
  268. memcpy(&ink8, ink_, sizeof(ink8));
  269. if (imOut->image8) {
  270. for (y = 0; y < ysize; y++) {
  271. UINT8* out = imOut->image8[y+dy]+dx;
  272. UINT8* mask = imMask->image8[y+sy]+sx;
  273. for (x = 0; x < xsize; x++) {
  274. if (*mask++)
  275. *out = ink8;
  276. out++;
  277. }
  278. }
  279. } else {
  280. for (y = 0; y < ysize; y++) {
  281. INT32* out = imOut->image32[y+dy]+dx;
  282. UINT8* mask = imMask->image8[y+sy]+sx;
  283. for (x = 0; x < xsize; x++) {
  284. if (*mask++)
  285. *out = ink32;
  286. out++;
  287. }
  288. }
  289. }
  290. }
  291. static inline void
  292. fill_mask_L(Imaging imOut, const UINT8* ink, Imaging imMask,
  293. int dx, int dy, int sx, int sy,
  294. int xsize, int ysize, int pixelsize)
  295. {
  296. /* fill with mode "L" matte */
  297. int x, y, i;
  298. unsigned int tmp1;
  299. if (imOut->image8) {
  300. for (y = 0; y < ysize; y++) {
  301. UINT8* out = imOut->image8[y+dy]+dx;
  302. UINT8* mask = imMask->image8[y+sy]+sx;
  303. for (x = 0; x < xsize; x++) {
  304. *out = BLEND(*mask, *out, ink[0], tmp1);
  305. out++, mask++;
  306. }
  307. }
  308. } else {
  309. for (y = 0; y < ysize; y++) {
  310. UINT8* out = (UINT8*) imOut->image[y+dy]+dx*pixelsize;
  311. UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
  312. for (x = 0; x < xsize; x++) {
  313. for (i = 0; i < pixelsize; i++) {
  314. *out = BLEND(*mask, *out, ink[i], tmp1);
  315. out++;
  316. }
  317. mask++;
  318. }
  319. }
  320. }
  321. }
  322. static inline void
  323. fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask,
  324. int dx, int dy, int sx, int sy,
  325. int xsize, int ysize, int pixelsize)
  326. {
  327. /* fill with mode "RGBA" matte */
  328. int x, y, i;
  329. unsigned int tmp1;
  330. if (imOut->image8) {
  331. sx = sx*4+3;
  332. for (y = 0; y < ysize; y++) {
  333. UINT8* out = imOut->image8[y+dy]+dx;
  334. UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
  335. for (x = 0; x < xsize; x++) {
  336. *out = BLEND(*mask, *out, ink[0], tmp1);
  337. out++, mask += 4;
  338. }
  339. }
  340. } else {
  341. dx *= pixelsize;
  342. sx = sx*4 + 3;
  343. for (y = 0; y < ysize; y++) {
  344. UINT8* out = (UINT8*) imOut->image[y+dy]+dx;
  345. UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
  346. for (x = 0; x < xsize; x++) {
  347. for (i = 0; i < pixelsize; i++) {
  348. *out = BLEND(*mask, *out, ink[i], tmp1);
  349. out++;
  350. }
  351. mask += 4;
  352. }
  353. }
  354. }
  355. }
  356. static inline void
  357. fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask,
  358. int dx, int dy, int sx, int sy,
  359. int xsize, int ysize, int pixelsize)
  360. {
  361. /* fill with mode "RGBa" matte */
  362. int x, y, i;
  363. unsigned int tmp1;
  364. if (imOut->image8) {
  365. sx = sx*4 + 3;
  366. for (y = 0; y < ysize; y++) {
  367. UINT8* out = imOut->image8[y+dy]+dx;
  368. UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
  369. for (x = 0; x < xsize; x++) {
  370. *out = PREBLEND(*mask, *out, ink[0], tmp1);
  371. out++, mask += 4;
  372. }
  373. }
  374. } else {
  375. dx *= pixelsize;
  376. sx = sx*4 + 3;
  377. for (y = 0; y < ysize; y++) {
  378. UINT8* out = (UINT8*) imOut->image[y+dy]+dx;
  379. UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
  380. for (x = 0; x < xsize; x++) {
  381. for (i = 0; i < pixelsize; i++) {
  382. *out = PREBLEND(*mask, *out, ink[i], tmp1);
  383. out++;
  384. }
  385. mask += 4;
  386. }
  387. }
  388. }
  389. }
  390. int
  391. ImagingFill2(Imaging imOut, const void* ink, Imaging imMask,
  392. int dx0, int dy0, int dx1, int dy1)
  393. {
  394. ImagingSectionCookie cookie;
  395. int xsize, ysize;
  396. int pixelsize;
  397. int sx0, sy0;
  398. if (!imOut || !ink) {
  399. (void) ImagingError_ModeError();
  400. return -1;
  401. }
  402. pixelsize = imOut->pixelsize;
  403. xsize = dx1 - dx0;
  404. ysize = dy1 - dy0;
  405. if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
  406. (void) ImagingError_Mismatch();
  407. return -1;
  408. }
  409. /* Determine which region to fill */
  410. sx0 = sy0 = 0;
  411. if (dx0 < 0)
  412. xsize += dx0, sx0 = -dx0, dx0 = 0;
  413. if (dx0 + xsize > imOut->xsize)
  414. xsize = imOut->xsize - dx0;
  415. if (dy0 < 0)
  416. ysize += dy0, sy0 = -dy0, dy0 = 0;
  417. if (dy0 + ysize > imOut->ysize)
  418. ysize = imOut->ysize - dy0;
  419. if (xsize <= 0 || ysize <= 0)
  420. return 0;
  421. if (!imMask) {
  422. ImagingSectionEnter(&cookie);
  423. fill(imOut, ink, dx0, dy0, xsize, ysize, pixelsize);
  424. ImagingSectionLeave(&cookie);
  425. } else if (strcmp(imMask->mode, "1") == 0) {
  426. ImagingSectionEnter(&cookie);
  427. fill_mask_1(imOut, ink, imMask, dx0, dy0, sx0, sy0,
  428. xsize, ysize, pixelsize);
  429. ImagingSectionLeave(&cookie);
  430. } else if (strcmp(imMask->mode, "L") == 0) {
  431. ImagingSectionEnter(&cookie);
  432. fill_mask_L(imOut, ink, imMask, dx0, dy0, sx0, sy0,
  433. xsize, ysize, pixelsize);
  434. ImagingSectionLeave(&cookie);
  435. } else if (strcmp(imMask->mode, "RGBA") == 0) {
  436. ImagingSectionEnter(&cookie);
  437. fill_mask_RGBA(imOut, ink, imMask, dx0, dy0, sx0, sy0,
  438. xsize, ysize, pixelsize);
  439. ImagingSectionLeave(&cookie);
  440. } else if (strcmp(imMask->mode, "RGBa") == 0) {
  441. ImagingSectionEnter(&cookie);
  442. fill_mask_RGBa(imOut, ink, imMask, dx0, dy0, sx0, sy0,
  443. xsize, ysize, pixelsize);
  444. ImagingSectionLeave(&cookie);
  445. } else {
  446. (void) ImagingError_ValueError("bad transparency mask");
  447. return -1;
  448. }
  449. return 0;
  450. }