/src/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 747 lines · 455 code · 142 blank · 150 comment · 151 complexity · d1cd20fd1e97339cc0e85d5f8ce2d3d6 MD5 · raw file

  1. // ==========================================================
  2. // Copy / paste routines
  3. //
  4. // - Floris van den Berg (flvdberg@wxs.nl)
  5. // - Alexander Dymerets (sashad@te.net.ua)
  6. // - Hervé Drolon (drolon@infonie.fr)
  7. // - Manfred Tausch (manfred.tausch@t-online.de)
  8. // - Riley McNiff (rmcniff@marexgroup.com)
  9. //
  10. // This file is part of FreeImage 3
  11. //
  12. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  13. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  14. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  15. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  16. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  17. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  18. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  19. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  20. // THIS DISCLAIMER.
  21. //
  22. // Use at your own risk!
  23. // ==========================================================
  24. #include "FreeImage.h"
  25. #include "Utilities.h"
  26. // ----------------------------------------------------------
  27. // Helpers
  28. // ----------------------------------------------------------
  29. /////////////////////////////////////////////////////////////
  30. // Alpha blending / combine functions
  31. // ----------------------------------------------------------
  32. /// 1-bit
  33. static BOOL Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
  34. /// 4-bit
  35. static BOOL Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
  36. /// 8-bit
  37. static BOOL Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
  38. /// 16-bit 555
  39. static BOOL Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
  40. /// 16-bit 565
  41. static BOOL Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
  42. /// 24-bit
  43. static BOOL Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
  44. /// 32- bit
  45. static BOOL Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
  46. // ----------------------------------------------------------
  47. // ----------------------------------------------------------
  48. // 1-bit
  49. // ----------------------------------------------------------
  50. static BOOL
  51. Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
  52. BOOL value;
  53. // check the bit depth of src and dst images
  54. if((FreeImage_GetBPP(dst_dib) != 1) || (FreeImage_GetBPP(src_dib) != 1)) {
  55. return FALSE;
  56. }
  57. // check the size of src image
  58. if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
  59. return FALSE;
  60. }
  61. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib));
  62. BYTE *src_bits = FreeImage_GetBits(src_dib);
  63. // combine images
  64. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  65. for(unsigned cols = 0; cols < FreeImage_GetWidth(src_dib); cols++) {
  66. // get bit at (rows, cols) in src image
  67. value = (src_bits[cols >> 3] & (0x80 >> (cols & 0x07))) != 0;
  68. // set bit at (rows, x+cols) in dst image
  69. value ? dst_bits[(x + cols) >> 3] |= (0x80 >> ((x + cols) & 0x7)) : dst_bits[(x + cols) >> 3] &= (0xFF7F >> ((x + cols) & 0x7));
  70. }
  71. dst_bits += FreeImage_GetPitch(dst_dib);
  72. src_bits += FreeImage_GetPitch(src_dib);
  73. }
  74. return TRUE;
  75. }
  76. // ----------------------------------------------------------
  77. // 4-bit
  78. // ----------------------------------------------------------
  79. static BOOL
  80. Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
  81. int swapTable[16];
  82. BOOL bOddStart, bOddEnd;
  83. // check the bit depth of src and dst images
  84. if((FreeImage_GetBPP(dst_dib) != 4) || (FreeImage_GetBPP(src_dib) != 4)) {
  85. return FALSE;
  86. }
  87. // check the size of src image
  88. if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
  89. return FALSE;
  90. }
  91. // get src and dst palettes
  92. RGBQUAD *src_pal = FreeImage_GetPalette(src_dib);
  93. RGBQUAD *dst_pal = FreeImage_GetPalette(dst_dib);
  94. if (src_pal == NULL || dst_pal == NULL) {
  95. return FALSE;
  96. }
  97. // build a swap table for the closest color match from the source palette to the destination palette
  98. for (int i = 0; i < 16; i++) {
  99. WORD min_diff = (WORD)-1;
  100. for (int j = 0; j < 16; j++) {
  101. // calculates the color difference using a Manhattan distance
  102. WORD abs_diff = (WORD)(
  103. abs(src_pal[i].rgbBlue - dst_pal[j].rgbBlue)
  104. + abs(src_pal[i].rgbGreen - dst_pal[j].rgbGreen)
  105. + abs(src_pal[i].rgbRed - dst_pal[j].rgbRed)
  106. );
  107. if (abs_diff < min_diff) {
  108. swapTable[i] = j;
  109. min_diff = abs_diff;
  110. if (abs_diff == 0) {
  111. break;
  112. }
  113. }
  114. }
  115. }
  116. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x >> 1);
  117. BYTE *src_bits = FreeImage_GetBits(src_dib);
  118. // combine images
  119. // allocate space for our temporary row
  120. unsigned src_line = FreeImage_GetLine(src_dib);
  121. unsigned src_width = FreeImage_GetWidth(src_dib);
  122. unsigned src_height = FreeImage_GetHeight(src_dib);
  123. BYTE *buffer = (BYTE *)malloc(src_line * sizeof(BYTE));
  124. if (buffer == NULL) {
  125. return FALSE;
  126. }
  127. bOddStart = (x & 0x01) ? TRUE : FALSE;
  128. if ((bOddStart && !(src_width & 0x01)) || (!bOddStart && (src_width & 0x01))) {
  129. bOddEnd = TRUE;
  130. }
  131. else {
  132. bOddEnd = FALSE;
  133. }
  134. for(unsigned rows = 0; rows < src_height; rows++) {
  135. memcpy(buffer, src_bits, src_line);
  136. // change the values in the temp row to be those from the swap table
  137. for (unsigned cols = 0; cols < src_line; cols++) {
  138. buffer[cols] = (BYTE)((swapTable[HINIBBLE(buffer[cols]) >> 4] << 4) + swapTable[LOWNIBBLE(buffer[cols])]);
  139. }
  140. if (bOddStart) {
  141. buffer[0] = HINIBBLE(dst_bits[0]) + LOWNIBBLE(buffer[0]);
  142. }
  143. if (bOddEnd) {
  144. buffer[src_line - 1] = HINIBBLE(buffer[src_line - 1]) + LOWNIBBLE(dst_bits[src_line - 1]);
  145. }
  146. memcpy(dst_bits, buffer, src_line);
  147. dst_bits += FreeImage_GetPitch(dst_dib);
  148. src_bits += FreeImage_GetPitch(src_dib);
  149. }
  150. free(buffer);
  151. return TRUE;
  152. }
  153. // ----------------------------------------------------------
  154. // 8-bit
  155. // ----------------------------------------------------------
  156. static BOOL
  157. Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
  158. // check the bit depth of src and dst images
  159. if((FreeImage_GetBPP(dst_dib) != 8) || (FreeImage_GetBPP(src_dib) != 8)) {
  160. return FALSE;
  161. }
  162. // check the size of src image
  163. if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
  164. return FALSE;
  165. }
  166. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x);
  167. BYTE *src_bits = FreeImage_GetBits(src_dib);
  168. if(alpha > 255) {
  169. // combine images
  170. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  171. memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
  172. dst_bits += FreeImage_GetPitch(dst_dib);
  173. src_bits += FreeImage_GetPitch(src_dib);
  174. }
  175. } else {
  176. // alpha blend images
  177. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  178. for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) {
  179. dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8);
  180. }
  181. dst_bits += FreeImage_GetPitch(dst_dib);
  182. src_bits += FreeImage_GetPitch(src_dib);
  183. }
  184. }
  185. return TRUE;
  186. }
  187. // ----------------------------------------------------------
  188. // 16-bit
  189. // ----------------------------------------------------------
  190. static BOOL
  191. Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
  192. // check the bit depth of src and dst images
  193. if((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) {
  194. return FALSE;
  195. }
  196. // check the size of src image
  197. if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
  198. return FALSE;
  199. }
  200. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2);
  201. BYTE *src_bits = FreeImage_GetBits(src_dib);
  202. if (alpha > 255) {
  203. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  204. memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
  205. dst_bits += FreeImage_GetPitch(dst_dib);
  206. src_bits += FreeImage_GetPitch(src_dib);
  207. }
  208. } else {
  209. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  210. for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) {
  211. RGBTRIPLE color_s;
  212. RGBTRIPLE color_t;
  213. WORD *tmp1 = (WORD *)&dst_bits[cols];
  214. WORD *tmp2 = (WORD *)&src_bits[cols];
  215. // convert 16-bit colors to 24-bit
  216. color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3);
  217. color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3);
  218. color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3);
  219. color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3);
  220. color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3);
  221. color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3);
  222. // alpha blend
  223. color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8);
  224. color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8);
  225. color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8);
  226. // convert 24-bit color back to 16-bit
  227. *tmp1 = RGB555(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue);
  228. }
  229. dst_bits += FreeImage_GetPitch(dst_dib);
  230. src_bits += FreeImage_GetPitch(src_dib);
  231. }
  232. }
  233. return TRUE;
  234. }
  235. static BOOL
  236. Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
  237. // check the bit depth of src and dst images
  238. if((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) {
  239. return FALSE;
  240. }
  241. // check the size of src image
  242. if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
  243. return FALSE;
  244. }
  245. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2);
  246. BYTE *src_bits = FreeImage_GetBits(src_dib);
  247. if (alpha > 255) {
  248. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  249. memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
  250. dst_bits += FreeImage_GetPitch(dst_dib);
  251. src_bits += FreeImage_GetPitch(src_dib);
  252. }
  253. } else {
  254. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  255. for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) {
  256. RGBTRIPLE color_s;
  257. RGBTRIPLE color_t;
  258. WORD *tmp1 = (WORD *)&dst_bits[cols];
  259. WORD *tmp2 = (WORD *)&src_bits[cols];
  260. // convert 16-bit colors to 24-bit
  261. color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3);
  262. color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2);
  263. color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3);
  264. color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3);
  265. color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2);
  266. color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3);
  267. // alpha blend
  268. color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8);
  269. color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8);
  270. color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8);
  271. // convert 24-bit color back to 16-bit
  272. *tmp1 = RGB565(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue);
  273. }
  274. dst_bits += FreeImage_GetPitch(dst_dib);
  275. src_bits += FreeImage_GetPitch(src_dib);
  276. }
  277. }
  278. return TRUE;
  279. }
  280. // ----------------------------------------------------------
  281. // 24-bit
  282. // ----------------------------------------------------------
  283. static BOOL
  284. Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
  285. // check the bit depth of src and dst images
  286. if((FreeImage_GetBPP(dst_dib) != 24) || (FreeImage_GetBPP(src_dib) != 24)) {
  287. return FALSE;
  288. }
  289. // check the size of src image
  290. if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
  291. return FALSE;
  292. }
  293. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 3);
  294. BYTE *src_bits = FreeImage_GetBits(src_dib);
  295. if(alpha > 255) {
  296. // combine images
  297. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  298. memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
  299. dst_bits += FreeImage_GetPitch(dst_dib);
  300. src_bits += FreeImage_GetPitch(src_dib);
  301. }
  302. } else {
  303. // alpha blend images
  304. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  305. for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) {
  306. dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8);
  307. }
  308. dst_bits += FreeImage_GetPitch(dst_dib);
  309. src_bits += FreeImage_GetPitch(src_dib);
  310. }
  311. }
  312. return TRUE;
  313. }
  314. // ----------------------------------------------------------
  315. // 32-bit
  316. // ----------------------------------------------------------
  317. static BOOL
  318. Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
  319. // check the bit depth of src and dst images
  320. if((FreeImage_GetBPP(dst_dib) != 32) || (FreeImage_GetBPP(src_dib) != 32)) {
  321. return FALSE;
  322. }
  323. // check the size of src image
  324. if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
  325. return FALSE;
  326. }
  327. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 4);
  328. BYTE *src_bits = FreeImage_GetBits(src_dib);
  329. if (alpha > 255) {
  330. // combine images
  331. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  332. memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
  333. dst_bits += FreeImage_GetPitch(dst_dib);
  334. src_bits += FreeImage_GetPitch(src_dib);
  335. }
  336. } else {
  337. // alpha blend images
  338. for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
  339. for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) {
  340. dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8);
  341. }
  342. dst_bits += FreeImage_GetPitch(dst_dib);
  343. src_bits += FreeImage_GetPitch(src_dib);
  344. }
  345. }
  346. return TRUE;
  347. }
  348. // ----------------------------------------------------------
  349. // Any type other than FIBITMAP
  350. // ----------------------------------------------------------
  351. static BOOL
  352. CombineSameType(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y) {
  353. // check the bit depth of src and dst images
  354. if(FreeImage_GetImageType(dst_dib) != FreeImage_GetImageType(src_dib)) {
  355. return FALSE;
  356. }
  357. unsigned src_width = FreeImage_GetWidth(src_dib);
  358. unsigned src_height = FreeImage_GetHeight(src_dib);
  359. unsigned src_pitch = FreeImage_GetPitch(src_dib);
  360. unsigned src_line = FreeImage_GetLine(src_dib);
  361. unsigned dst_width = FreeImage_GetWidth(dst_dib);
  362. unsigned dst_height = FreeImage_GetHeight(dst_dib);
  363. unsigned dst_pitch = FreeImage_GetPitch(dst_dib);
  364. // check the size of src image
  365. if((x + src_width > dst_width) || (y + src_height > dst_height)) {
  366. return FALSE;
  367. }
  368. BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((dst_height - src_height - y) * dst_pitch) + (x * (src_line / src_width));
  369. BYTE *src_bits = FreeImage_GetBits(src_dib);
  370. // combine images
  371. for(unsigned rows = 0; rows < src_height; rows++) {
  372. memcpy(dst_bits, src_bits, src_line);
  373. dst_bits += dst_pitch;
  374. src_bits += src_pitch;
  375. }
  376. return TRUE;
  377. }
  378. // ----------------------------------------------------------
  379. // FreeImage interface
  380. // ----------------------------------------------------------
  381. /**
  382. Copy a sub part of the current image and returns it as a FIBITMAP*.
  383. Works with any bitmap type.
  384. @param left Specifies the left position of the cropped rectangle.
  385. @param top Specifies the top position of the cropped rectangle.
  386. @param right Specifies the right position of the cropped rectangle.
  387. @param bottom Specifies the bottom position of the cropped rectangle.
  388. @return Returns the subimage if successful, NULL otherwise.
  389. */
  390. FIBITMAP * DLL_CALLCONV
  391. FreeImage_Copy(FIBITMAP *src, int left, int top, int right, int bottom) {
  392. if(!FreeImage_HasPixels(src))
  393. return NULL;
  394. // normalize the rectangle
  395. if(right < left) {
  396. INPLACESWAP(left, right);
  397. }
  398. if(bottom < top) {
  399. INPLACESWAP(top, bottom);
  400. }
  401. // check the size of the sub image
  402. int src_width = FreeImage_GetWidth(src);
  403. int src_height = FreeImage_GetHeight(src);
  404. if((left < 0) || (right > src_width) || (top < 0) || (bottom > src_height)) {
  405. return NULL;
  406. }
  407. // allocate the sub image
  408. unsigned bpp = FreeImage_GetBPP(src);
  409. int dst_width = (right - left);
  410. int dst_height = (bottom - top);
  411. FIBITMAP *dst =
  412. FreeImage_AllocateT(FreeImage_GetImageType(src),
  413. dst_width,
  414. dst_height,
  415. bpp,
  416. FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src));
  417. if(NULL == dst) return NULL;
  418. // get the dimensions
  419. int dst_line = FreeImage_GetLine(dst);
  420. int dst_pitch = FreeImage_GetPitch(dst);
  421. int src_pitch = FreeImage_GetPitch(src);
  422. // get the pointers to the bits and such
  423. BYTE *src_bits = FreeImage_GetScanLine(src, src_height - top - dst_height);
  424. switch(bpp) {
  425. case 1:
  426. // point to x = 0
  427. break;
  428. case 4:
  429. // point to x = 0
  430. break;
  431. default:
  432. {
  433. // calculate the number of bytes per pixel
  434. unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
  435. // point to x = left
  436. src_bits += left * bytespp;
  437. }
  438. break;
  439. }
  440. // point to x = 0
  441. BYTE *dst_bits = FreeImage_GetBits(dst);
  442. // copy the palette
  443. memcpy(FreeImage_GetPalette(dst), FreeImage_GetPalette(src), FreeImage_GetColorsUsed(src) * sizeof(RGBQUAD));
  444. // copy the bits
  445. if(bpp == 1) {
  446. BOOL value;
  447. unsigned y_src, y_dst;
  448. for(int y = 0; y < dst_height; y++) {
  449. y_src = y * src_pitch;
  450. y_dst = y * dst_pitch;
  451. for(int x = 0; x < dst_width; x++) {
  452. // get bit at (y, x) in src image
  453. value = (src_bits[y_src + ((left+x) >> 3)] & (0x80 >> ((left+x) & 0x07))) != 0;
  454. // set bit at (y, x) in dst image
  455. value ? dst_bits[y_dst + (x >> 3)] |= (0x80 >> (x & 0x7)) : dst_bits[y_dst + (x >> 3)] &= (0xff7f >> (x & 0x7));
  456. }
  457. }
  458. }
  459. else if(bpp == 4) {
  460. BYTE shift, value;
  461. unsigned y_src, y_dst;
  462. for(int y = 0; y < dst_height; y++) {
  463. y_src = y * src_pitch;
  464. y_dst = y * dst_pitch;
  465. for(int x = 0; x < dst_width; x++) {
  466. // get nibble at (y, x) in src image
  467. shift = (BYTE)((1 - (left+x) % 2) << 2);
  468. value = (src_bits[y_src + ((left+x) >> 1)] & (0x0F << shift)) >> shift;
  469. // set nibble at (y, x) in dst image
  470. shift = (BYTE)((1 - x % 2) << 2);
  471. dst_bits[y_dst + (x >> 1)] &= ~(0x0F << shift);
  472. dst_bits[y_dst + (x >> 1)] |= ((value & 0x0F) << shift);
  473. }
  474. }
  475. }
  476. else if(bpp >= 8) {
  477. for(int y = 0; y < dst_height; y++) {
  478. memcpy(dst_bits + (y * dst_pitch), src_bits + (y * src_pitch), dst_line);
  479. }
  480. }
  481. // copy metadata from src to dst
  482. FreeImage_CloneMetadata(dst, src);
  483. // copy transparency table
  484. FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(src), FreeImage_GetTransparencyCount(src));
  485. // copy background color
  486. RGBQUAD bkcolor;
  487. if( FreeImage_GetBackgroundColor(src, &bkcolor) ) {
  488. FreeImage_SetBackgroundColor(dst, &bkcolor);
  489. }
  490. // clone resolution
  491. FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src));
  492. FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src));
  493. // clone ICC profile
  494. FIICCPROFILE *src_profile = FreeImage_GetICCProfile(src);
  495. FIICCPROFILE *dst_profile = FreeImage_CreateICCProfile(dst, src_profile->data, src_profile->size);
  496. dst_profile->flags = src_profile->flags;
  497. return dst;
  498. }
  499. /**
  500. Alpha blend or combine a sub part image with the current image.
  501. The bit depth of dst bitmap must be greater than or equal to the bit depth of src.
  502. Upper promotion of src is done internally. Supported bit depth equals to 1, 4, 8, 16, 24 or 32.
  503. @param src Source subimage
  504. @param left Specifies the left position of the sub image.
  505. @param top Specifies the top position of the sub image.
  506. @param alpha Alpha blend factor. The source and destination images are alpha blended if
  507. alpha = 0..255. If alpha > 255, then the source image is combined to the destination image.
  508. @return Returns TRUE if successful, FALSE otherwise.
  509. */
  510. BOOL DLL_CALLCONV
  511. FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left, int top, int alpha) {
  512. BOOL bResult = FALSE;
  513. if(!FreeImage_HasPixels(src) || !FreeImage_HasPixels(dst)) return FALSE;
  514. // check the size of src image
  515. if((left < 0) || (top < 0)) {
  516. return FALSE;
  517. }
  518. if((left + FreeImage_GetWidth(src) > FreeImage_GetWidth(dst)) || (top + FreeImage_GetHeight(src) > FreeImage_GetHeight(dst))) {
  519. return FALSE;
  520. }
  521. // check data type
  522. const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dst);
  523. if(image_type != FreeImage_GetImageType(src)) {
  524. // no conversion between data type is done
  525. return FALSE;
  526. }
  527. if(image_type == FIT_BITMAP) {
  528. FIBITMAP *clone = NULL;
  529. // check the bit depth of src and dst images
  530. unsigned bpp_src = FreeImage_GetBPP(src);
  531. unsigned bpp_dst = FreeImage_GetBPP(dst);
  532. BOOL isRGB565 = FALSE;
  533. if ((FreeImage_GetRedMask(dst) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dst) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dst) == FI16_565_BLUE_MASK)) {
  534. isRGB565 = TRUE;
  535. } else {
  536. // includes case where all the masks are 0
  537. isRGB565 = FALSE;
  538. }
  539. // perform promotion if needed
  540. if(bpp_dst == bpp_src) {
  541. clone = src;
  542. } else if(bpp_dst > bpp_src) {
  543. // perform promotion
  544. switch(bpp_dst) {
  545. case 4:
  546. clone = FreeImage_ConvertTo4Bits(src);
  547. break;
  548. case 8:
  549. clone = FreeImage_ConvertTo8Bits(src);
  550. break;
  551. case 16:
  552. if (isRGB565) {
  553. clone = FreeImage_ConvertTo16Bits565(src);
  554. } else {
  555. // includes case where all the masks are 0
  556. clone = FreeImage_ConvertTo16Bits555(src);
  557. }
  558. break;
  559. case 24:
  560. clone = FreeImage_ConvertTo24Bits(src);
  561. break;
  562. case 32:
  563. clone = FreeImage_ConvertTo32Bits(src);
  564. break;
  565. default:
  566. return FALSE;
  567. }
  568. } else {
  569. return FALSE;
  570. }
  571. if(!clone) return FALSE;
  572. // paste src to dst
  573. switch(FreeImage_GetBPP(dst)) {
  574. case 1:
  575. bResult = Combine1(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
  576. break;
  577. case 4:
  578. bResult = Combine4(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
  579. break;
  580. case 8:
  581. bResult = Combine8(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
  582. break;
  583. case 16:
  584. if (isRGB565) {
  585. bResult = Combine16_565(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
  586. } else {
  587. // includes case where all the masks are 0
  588. bResult = Combine16_555(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
  589. }
  590. break;
  591. case 24:
  592. bResult = Combine24(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
  593. break;
  594. case 32:
  595. bResult = Combine32(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
  596. break;
  597. }
  598. if(clone != src)
  599. FreeImage_Unload(clone);
  600. }
  601. else { // any type other than FITBITMAP
  602. bResult = CombineSameType(dst, src, (unsigned)left, (unsigned)top);
  603. }
  604. return bResult;
  605. }