/src/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp
C++ | 747 lines | 455 code | 142 blank | 150 comment | 148 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 25#include "FreeImage.h" 26#include "Utilities.h" 27 28// ---------------------------------------------------------- 29// Helpers 30// ---------------------------------------------------------- 31 32///////////////////////////////////////////////////////////// 33// Alpha blending / combine functions 34 35// ---------------------------------------------------------- 36/// 1-bit 37static BOOL Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); 38/// 4-bit 39static BOOL Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); 40/// 8-bit 41static BOOL Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); 42/// 16-bit 555 43static BOOL Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); 44/// 16-bit 565 45static BOOL Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); 46/// 24-bit 47static BOOL Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); 48/// 32- bit 49static BOOL Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); 50// ---------------------------------------------------------- 51 52// ---------------------------------------------------------- 53// 1-bit 54// ---------------------------------------------------------- 55 56static BOOL 57Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { 58 BOOL value; 59 60 // check the bit depth of src and dst images 61 if((FreeImage_GetBPP(dst_dib) != 1) || (FreeImage_GetBPP(src_dib) != 1)) { 62 return FALSE; 63 } 64 65 // check the size of src image 66 if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { 67 return FALSE; 68 } 69 70 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)); 71 BYTE *src_bits = FreeImage_GetBits(src_dib); 72 73 // combine images 74 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 75 for(unsigned cols = 0; cols < FreeImage_GetWidth(src_dib); cols++) { 76 // get bit at (rows, cols) in src image 77 value = (src_bits[cols >> 3] & (0x80 >> (cols & 0x07))) != 0; 78 // set bit at (rows, x+cols) in dst image 79 value ? dst_bits[(x + cols) >> 3] |= (0x80 >> ((x + cols) & 0x7)) : dst_bits[(x + cols) >> 3] &= (0xFF7F >> ((x + cols) & 0x7)); 80 } 81 82 dst_bits += FreeImage_GetPitch(dst_dib); 83 src_bits += FreeImage_GetPitch(src_dib); 84 } 85 86 return TRUE; 87} 88 89// ---------------------------------------------------------- 90// 4-bit 91// ---------------------------------------------------------- 92 93static BOOL 94Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { 95 96 int swapTable[16]; 97 BOOL bOddStart, bOddEnd; 98 99 // check the bit depth of src and dst images 100 if((FreeImage_GetBPP(dst_dib) != 4) || (FreeImage_GetBPP(src_dib) != 4)) { 101 return FALSE; 102 } 103 104 // check the size of src image 105 if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { 106 return FALSE; 107 } 108 109 // get src and dst palettes 110 RGBQUAD *src_pal = FreeImage_GetPalette(src_dib); 111 RGBQUAD *dst_pal = FreeImage_GetPalette(dst_dib); 112 if (src_pal == NULL || dst_pal == NULL) { 113 return FALSE; 114 } 115 116 // build a swap table for the closest color match from the source palette to the destination palette 117 118 for (int i = 0; i < 16; i++) { 119 WORD min_diff = (WORD)-1; 120 121 for (int j = 0; j < 16; j++) { 122 // calculates the color difference using a Manhattan distance 123 WORD abs_diff = (WORD)( 124 abs(src_pal[i].rgbBlue - dst_pal[j].rgbBlue) 125 + abs(src_pal[i].rgbGreen - dst_pal[j].rgbGreen) 126 + abs(src_pal[i].rgbRed - dst_pal[j].rgbRed) 127 ); 128 129 if (abs_diff < min_diff) { 130 swapTable[i] = j; 131 min_diff = abs_diff; 132 if (abs_diff == 0) { 133 break; 134 } 135 } 136 } 137 } 138 139 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x >> 1); 140 BYTE *src_bits = FreeImage_GetBits(src_dib); 141 142 // combine images 143 144 // allocate space for our temporary row 145 unsigned src_line = FreeImage_GetLine(src_dib); 146 unsigned src_width = FreeImage_GetWidth(src_dib); 147 unsigned src_height = FreeImage_GetHeight(src_dib); 148 149 BYTE *buffer = (BYTE *)malloc(src_line * sizeof(BYTE)); 150 if (buffer == NULL) { 151 return FALSE; 152 } 153 154 bOddStart = (x & 0x01) ? TRUE : FALSE; 155 156 if ((bOddStart && !(src_width & 0x01)) || (!bOddStart && (src_width & 0x01))) { 157 bOddEnd = TRUE; 158 } 159 else { 160 bOddEnd = FALSE; 161 } 162 163 for(unsigned rows = 0; rows < src_height; rows++) { 164 memcpy(buffer, src_bits, src_line); 165 166 // change the values in the temp row to be those from the swap table 167 168 for (unsigned cols = 0; cols < src_line; cols++) { 169 buffer[cols] = (BYTE)((swapTable[HINIBBLE(buffer[cols]) >> 4] << 4) + swapTable[LOWNIBBLE(buffer[cols])]); 170 } 171 172 if (bOddStart) { 173 buffer[0] = HINIBBLE(dst_bits[0]) + LOWNIBBLE(buffer[0]); 174 } 175 176 if (bOddEnd) { 177 buffer[src_line - 1] = HINIBBLE(buffer[src_line - 1]) + LOWNIBBLE(dst_bits[src_line - 1]); 178 } 179 180 memcpy(dst_bits, buffer, src_line); 181 182 dst_bits += FreeImage_GetPitch(dst_dib); 183 src_bits += FreeImage_GetPitch(src_dib); 184 } 185 186 free(buffer); 187 188 return TRUE; 189 190} 191 192// ---------------------------------------------------------- 193// 8-bit 194// ---------------------------------------------------------- 195 196static BOOL 197Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { 198 // check the bit depth of src and dst images 199 if((FreeImage_GetBPP(dst_dib) != 8) || (FreeImage_GetBPP(src_dib) != 8)) { 200 return FALSE; 201 } 202 203 // check the size of src image 204 if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { 205 return FALSE; 206 } 207 208 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x); 209 BYTE *src_bits = FreeImage_GetBits(src_dib); 210 211 if(alpha > 255) { 212 // combine images 213 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 214 memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); 215 216 dst_bits += FreeImage_GetPitch(dst_dib); 217 src_bits += FreeImage_GetPitch(src_dib); 218 } 219 } else { 220 // alpha blend images 221 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 222 for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) { 223 dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8); 224 } 225 226 dst_bits += FreeImage_GetPitch(dst_dib); 227 src_bits += FreeImage_GetPitch(src_dib); 228 } 229 } 230 231 return TRUE; 232} 233 234// ---------------------------------------------------------- 235// 16-bit 236// ---------------------------------------------------------- 237 238static BOOL 239Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { 240 // check the bit depth of src and dst images 241 if((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) { 242 return FALSE; 243 } 244 245 // check the size of src image 246 if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { 247 return FALSE; 248 } 249 250 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2); 251 BYTE *src_bits = FreeImage_GetBits(src_dib); 252 253 if (alpha > 255) { 254 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 255 memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); 256 257 dst_bits += FreeImage_GetPitch(dst_dib); 258 src_bits += FreeImage_GetPitch(src_dib); 259 } 260 } else { 261 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 262 for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) { 263 RGBTRIPLE color_s; 264 RGBTRIPLE color_t; 265 266 WORD *tmp1 = (WORD *)&dst_bits[cols]; 267 WORD *tmp2 = (WORD *)&src_bits[cols]; 268 269 // convert 16-bit colors to 24-bit 270 271 color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3); 272 color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3); 273 color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3); 274 275 color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3); 276 color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3); 277 color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3); 278 279 // alpha blend 280 281 color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8); 282 color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8); 283 color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8); 284 285 // convert 24-bit color back to 16-bit 286 287 *tmp1 = RGB555(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue); 288 } 289 290 dst_bits += FreeImage_GetPitch(dst_dib); 291 src_bits += FreeImage_GetPitch(src_dib); 292 } 293 } 294 295 return TRUE; 296} 297 298static BOOL 299Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { 300 // check the bit depth of src and dst images 301 if((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) { 302 return FALSE; 303 } 304 305 // check the size of src image 306 if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { 307 return FALSE; 308 } 309 310 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2); 311 BYTE *src_bits = FreeImage_GetBits(src_dib); 312 313 if (alpha > 255) { 314 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 315 memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); 316 317 dst_bits += FreeImage_GetPitch(dst_dib); 318 src_bits += FreeImage_GetPitch(src_dib); 319 } 320 } else { 321 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 322 for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) { 323 RGBTRIPLE color_s; 324 RGBTRIPLE color_t; 325 326 WORD *tmp1 = (WORD *)&dst_bits[cols]; 327 WORD *tmp2 = (WORD *)&src_bits[cols]; 328 329 // convert 16-bit colors to 24-bit 330 331 color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3); 332 color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2); 333 color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3); 334 335 color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3); 336 color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2); 337 color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3); 338 339 // alpha blend 340 341 color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8); 342 color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8); 343 color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8); 344 345 // convert 24-bit color back to 16-bit 346 347 *tmp1 = RGB565(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue); 348 } 349 350 dst_bits += FreeImage_GetPitch(dst_dib); 351 src_bits += FreeImage_GetPitch(src_dib); 352 } 353 } 354 355 return TRUE; 356} 357 358// ---------------------------------------------------------- 359// 24-bit 360// ---------------------------------------------------------- 361 362static BOOL 363Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { 364 // check the bit depth of src and dst images 365 if((FreeImage_GetBPP(dst_dib) != 24) || (FreeImage_GetBPP(src_dib) != 24)) { 366 return FALSE; 367 } 368 369 // check the size of src image 370 if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { 371 return FALSE; 372 } 373 374 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 3); 375 BYTE *src_bits = FreeImage_GetBits(src_dib); 376 377 if(alpha > 255) { 378 // combine images 379 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 380 memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); 381 382 dst_bits += FreeImage_GetPitch(dst_dib); 383 src_bits += FreeImage_GetPitch(src_dib); 384 } 385 } else { 386 // alpha blend images 387 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 388 for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) { 389 dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8); 390 } 391 392 dst_bits += FreeImage_GetPitch(dst_dib); 393 src_bits += FreeImage_GetPitch(src_dib); 394 } 395 } 396 397 return TRUE; 398} 399 400// ---------------------------------------------------------- 401// 32-bit 402// ---------------------------------------------------------- 403 404static BOOL 405Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { 406 // check the bit depth of src and dst images 407 if((FreeImage_GetBPP(dst_dib) != 32) || (FreeImage_GetBPP(src_dib) != 32)) { 408 return FALSE; 409 } 410 411 // check the size of src image 412 if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { 413 return FALSE; 414 } 415 416 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 4); 417 BYTE *src_bits = FreeImage_GetBits(src_dib); 418 419 if (alpha > 255) { 420 // combine images 421 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 422 memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); 423 424 dst_bits += FreeImage_GetPitch(dst_dib); 425 src_bits += FreeImage_GetPitch(src_dib); 426 } 427 } else { 428 // alpha blend images 429 for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { 430 for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) { 431 dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8); 432 } 433 434 dst_bits += FreeImage_GetPitch(dst_dib); 435 src_bits += FreeImage_GetPitch(src_dib); 436 } 437 } 438 439 return TRUE; 440} 441 442// ---------------------------------------------------------- 443// Any type other than FIBITMAP 444// ---------------------------------------------------------- 445 446static BOOL 447CombineSameType(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y) { 448 // check the bit depth of src and dst images 449 if(FreeImage_GetImageType(dst_dib) != FreeImage_GetImageType(src_dib)) { 450 return FALSE; 451 } 452 453 unsigned src_width = FreeImage_GetWidth(src_dib); 454 unsigned src_height = FreeImage_GetHeight(src_dib); 455 unsigned src_pitch = FreeImage_GetPitch(src_dib); 456 unsigned src_line = FreeImage_GetLine(src_dib); 457 unsigned dst_width = FreeImage_GetWidth(dst_dib); 458 unsigned dst_height = FreeImage_GetHeight(dst_dib); 459 unsigned dst_pitch = FreeImage_GetPitch(dst_dib); 460 461 // check the size of src image 462 if((x + src_width > dst_width) || (y + src_height > dst_height)) { 463 return FALSE; 464 } 465 466 BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((dst_height - src_height - y) * dst_pitch) + (x * (src_line / src_width)); 467 BYTE *src_bits = FreeImage_GetBits(src_dib); 468 469 // combine images 470 for(unsigned rows = 0; rows < src_height; rows++) { 471 memcpy(dst_bits, src_bits, src_line); 472 473 dst_bits += dst_pitch; 474 src_bits += src_pitch; 475 } 476 477 return TRUE; 478} 479 480// ---------------------------------------------------------- 481// FreeImage interface 482// ---------------------------------------------------------- 483 484/** 485Copy a sub part of the current image and returns it as a FIBITMAP*. 486Works with any bitmap type. 487@param left Specifies the left position of the cropped rectangle. 488@param top Specifies the top position of the cropped rectangle. 489@param right Specifies the right position of the cropped rectangle. 490@param bottom Specifies the bottom position of the cropped rectangle. 491@return Returns the subimage if successful, NULL otherwise. 492*/ 493FIBITMAP * DLL_CALLCONV 494FreeImage_Copy(FIBITMAP *src, int left, int top, int right, int bottom) { 495 496 if(!FreeImage_HasPixels(src)) 497 return NULL; 498 499 // normalize the rectangle 500 if(right < left) { 501 INPLACESWAP(left, right); 502 } 503 if(bottom < top) { 504 INPLACESWAP(top, bottom); 505 } 506 // check the size of the sub image 507 int src_width = FreeImage_GetWidth(src); 508 int src_height = FreeImage_GetHeight(src); 509 if((left < 0) || (right > src_width) || (top < 0) || (bottom > src_height)) { 510 return NULL; 511 } 512 513 // allocate the sub image 514 unsigned bpp = FreeImage_GetBPP(src); 515 int dst_width = (right - left); 516 int dst_height = (bottom - top); 517 518 FIBITMAP *dst = 519 FreeImage_AllocateT(FreeImage_GetImageType(src), 520 dst_width, 521 dst_height, 522 bpp, 523 FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src)); 524 525 if(NULL == dst) return NULL; 526 527 // get the dimensions 528 int dst_line = FreeImage_GetLine(dst); 529 int dst_pitch = FreeImage_GetPitch(dst); 530 int src_pitch = FreeImage_GetPitch(src); 531 532 // get the pointers to the bits and such 533 534 BYTE *src_bits = FreeImage_GetScanLine(src, src_height - top - dst_height); 535 switch(bpp) { 536 case 1: 537 // point to x = 0 538 break; 539 540 case 4: 541 // point to x = 0 542 break; 543 544 default: 545 { 546 // calculate the number of bytes per pixel 547 unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); 548 // point to x = left 549 src_bits += left * bytespp; 550 } 551 break; 552 } 553 554 // point to x = 0 555 BYTE *dst_bits = FreeImage_GetBits(dst); 556 557 // copy the palette 558 559 memcpy(FreeImage_GetPalette(dst), FreeImage_GetPalette(src), FreeImage_GetColorsUsed(src) * sizeof(RGBQUAD)); 560 561 // copy the bits 562 if(bpp == 1) { 563 BOOL value; 564 unsigned y_src, y_dst; 565 566 for(int y = 0; y < dst_height; y++) { 567 y_src = y * src_pitch; 568 y_dst = y * dst_pitch; 569 for(int x = 0; x < dst_width; x++) { 570 // get bit at (y, x) in src image 571 value = (src_bits[y_src + ((left+x) >> 3)] & (0x80 >> ((left+x) & 0x07))) != 0; 572 // set bit at (y, x) in dst image 573 value ? dst_bits[y_dst + (x >> 3)] |= (0x80 >> (x & 0x7)) : dst_bits[y_dst + (x >> 3)] &= (0xff7f >> (x & 0x7)); 574 } 575 } 576 } 577 578 else if(bpp == 4) { 579 BYTE shift, value; 580 unsigned y_src, y_dst; 581 582 for(int y = 0; y < dst_height; y++) { 583 y_src = y * src_pitch; 584 y_dst = y * dst_pitch; 585 for(int x = 0; x < dst_width; x++) { 586 // get nibble at (y, x) in src image 587 shift = (BYTE)((1 - (left+x) % 2) << 2); 588 value = (src_bits[y_src + ((left+x) >> 1)] & (0x0F << shift)) >> shift; 589 // set nibble at (y, x) in dst image 590 shift = (BYTE)((1 - x % 2) << 2); 591 dst_bits[y_dst + (x >> 1)] &= ~(0x0F << shift); 592 dst_bits[y_dst + (x >> 1)] |= ((value & 0x0F) << shift); 593 } 594 } 595 } 596 597 else if(bpp >= 8) { 598 for(int y = 0; y < dst_height; y++) { 599 memcpy(dst_bits + (y * dst_pitch), src_bits + (y * src_pitch), dst_line); 600 } 601 } 602 603 // copy metadata from src to dst 604 FreeImage_CloneMetadata(dst, src); 605 606 // copy transparency table 607 FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(src), FreeImage_GetTransparencyCount(src)); 608 609 // copy background color 610 RGBQUAD bkcolor; 611 if( FreeImage_GetBackgroundColor(src, &bkcolor) ) { 612 FreeImage_SetBackgroundColor(dst, &bkcolor); 613 } 614 615 // clone resolution 616 FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src)); 617 FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src)); 618 619 // clone ICC profile 620 FIICCPROFILE *src_profile = FreeImage_GetICCProfile(src); 621 FIICCPROFILE *dst_profile = FreeImage_CreateICCProfile(dst, src_profile->data, src_profile->size); 622 dst_profile->flags = src_profile->flags; 623 624 return dst; 625} 626 627/** 628Alpha blend or combine a sub part image with the current image. 629The bit depth of dst bitmap must be greater than or equal to the bit depth of src. 630Upper promotion of src is done internally. Supported bit depth equals to 1, 4, 8, 16, 24 or 32. 631@param src Source subimage 632@param left Specifies the left position of the sub image. 633@param top Specifies the top position of the sub image. 634@param alpha Alpha blend factor. The source and destination images are alpha blended if 635alpha = 0..255. If alpha > 255, then the source image is combined to the destination image. 636@return Returns TRUE if successful, FALSE otherwise. 637*/ 638BOOL DLL_CALLCONV 639FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left, int top, int alpha) { 640 BOOL bResult = FALSE; 641 642 if(!FreeImage_HasPixels(src) || !FreeImage_HasPixels(dst)) return FALSE; 643 644 // check the size of src image 645 if((left < 0) || (top < 0)) { 646 return FALSE; 647 } 648 if((left + FreeImage_GetWidth(src) > FreeImage_GetWidth(dst)) || (top + FreeImage_GetHeight(src) > FreeImage_GetHeight(dst))) { 649 return FALSE; 650 } 651 652 // check data type 653 const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dst); 654 if(image_type != FreeImage_GetImageType(src)) { 655 // no conversion between data type is done 656 return FALSE; 657 } 658 659 if(image_type == FIT_BITMAP) { 660 FIBITMAP *clone = NULL; 661 662 // check the bit depth of src and dst images 663 unsigned bpp_src = FreeImage_GetBPP(src); 664 unsigned bpp_dst = FreeImage_GetBPP(dst); 665 BOOL isRGB565 = FALSE; 666 667 if ((FreeImage_GetRedMask(dst) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dst) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dst) == FI16_565_BLUE_MASK)) { 668 isRGB565 = TRUE; 669 } else { 670 // includes case where all the masks are 0 671 isRGB565 = FALSE; 672 } 673 674 // perform promotion if needed 675 if(bpp_dst == bpp_src) { 676 clone = src; 677 } else if(bpp_dst > bpp_src) { 678 // perform promotion 679 switch(bpp_dst) { 680 case 4: 681 clone = FreeImage_ConvertTo4Bits(src); 682 break; 683 case 8: 684 clone = FreeImage_ConvertTo8Bits(src); 685 break; 686 case 16: 687 if (isRGB565) { 688 clone = FreeImage_ConvertTo16Bits565(src); 689 } else { 690 // includes case where all the masks are 0 691 clone = FreeImage_ConvertTo16Bits555(src); 692 } 693 break; 694 case 24: 695 clone = FreeImage_ConvertTo24Bits(src); 696 break; 697 case 32: 698 clone = FreeImage_ConvertTo32Bits(src); 699 break; 700 default: 701 return FALSE; 702 } 703 } else { 704 return FALSE; 705 } 706 707 if(!clone) return FALSE; 708 709 // paste src to dst 710 switch(FreeImage_GetBPP(dst)) { 711 case 1: 712 bResult = Combine1(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); 713 break; 714 case 4: 715 bResult = Combine4(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); 716 break; 717 case 8: 718 bResult = Combine8(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); 719 break; 720 case 16: 721 if (isRGB565) { 722 bResult = Combine16_565(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); 723 } else { 724 // includes case where all the masks are 0 725 bResult = Combine16_555(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); 726 } 727 break; 728 case 24: 729 bResult = Combine24(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); 730 break; 731 case 32: 732 bResult = Combine32(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); 733 break; 734 } 735 736 if(clone != src) 737 FreeImage_Unload(clone); 738 739 } 740 else { // any type other than FITBITMAP 741 bResult = CombineSameType(dst, src, (unsigned)left, (unsigned)top); 742 } 743 744 return bResult; 745} 746 747