1 /* 2 * Copyright 2009 Vincent Povirk 3 * Copyright 2016 Dmitry Timoshkov 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "config.h" 21 22 #include <stdarg.h> 23 #include <math.h> 24 25 #define COBJMACROS 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "objbase.h" 30 31 #include "wincodecs_private.h" 32 33 #include "wine/debug.h" 34 35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 36 37 struct FormatConverter; 38 39 enum pixelformat { 40 format_1bppIndexed, 41 format_2bppIndexed, 42 format_4bppIndexed, 43 format_8bppIndexed, 44 format_BlackWhite, 45 format_2bppGray, 46 format_4bppGray, 47 format_8bppGray, 48 format_16bppGray, 49 format_16bppBGR555, 50 format_16bppBGR565, 51 format_16bppBGRA5551, 52 format_24bppBGR, 53 format_24bppRGB, 54 format_32bppGrayFloat, 55 format_32bppBGR, 56 format_32bppRGB, 57 format_32bppBGRA, 58 format_32bppRGBA, 59 format_32bppPBGRA, 60 format_32bppPRGBA, 61 format_48bppRGB, 62 format_64bppRGBA, 63 format_32bppCMYK, 64 }; 65 66 typedef HRESULT (*copyfunc)(struct FormatConverter *This, const WICRect *prc, 67 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format); 68 69 struct pixelformatinfo { 70 enum pixelformat format; 71 const WICPixelFormatGUID *guid; 72 copyfunc copy_function; 73 }; 74 75 typedef struct FormatConverter { 76 IWICFormatConverter IWICFormatConverter_iface; 77 LONG ref; 78 IWICBitmapSource *source; 79 const struct pixelformatinfo *dst_format, *src_format; 80 WICBitmapDitherType dither; 81 double alpha_threshold; 82 IWICPalette *palette; 83 CRITICAL_SECTION lock; /* must be held when initialized */ 84 } FormatConverter; 85 86 /* https://www.w3.org/Graphics/Color/srgb */ 87 #ifndef __REACTOS__ 88 static inline float from_sRGB_component(float f) 89 { 90 if (f <= 0.04045f) return f / 12.92f; 91 return powf((f + 0.055f) / 1.055f, 2.4f); 92 } 93 #endif 94 95 static inline float to_sRGB_component(float f) 96 { 97 if (f <= 0.0031308f) return 12.92f * f; 98 return 1.055f * powf(f, 1.0f/2.4f) - 0.055f; 99 } 100 101 #if 0 /* FIXME: enable once needed */ 102 static void from_sRGB(BYTE *bgr) 103 { 104 float r, g, b; 105 106 r = bgr[2] / 255.0f; 107 g = bgr[1] / 255.0f; 108 b = bgr[0] / 255.0f; 109 110 r = from_sRGB_component(r); 111 g = from_sRGB_component(g); 112 b = from_sRGB_component(b); 113 114 bgr[2] = (BYTE)(r * 255.0f); 115 bgr[1] = (BYTE)(g * 255.0f); 116 bgr[0] = (BYTE)(b * 255.0f); 117 } 118 119 static void to_sRGB(BYTE *bgr) 120 { 121 float r, g, b; 122 123 r = bgr[2] / 255.0f; 124 g = bgr[1] / 255.0f; 125 b = bgr[0] / 255.0f; 126 127 r = to_sRGB_component(r); 128 g = to_sRGB_component(g); 129 b = to_sRGB_component(b); 130 131 bgr[2] = (BYTE)(r * 255.0f); 132 bgr[1] = (BYTE)(g * 255.0f); 133 bgr[0] = (BYTE)(b * 255.0f); 134 } 135 #endif 136 137 static inline FormatConverter *impl_from_IWICFormatConverter(IWICFormatConverter *iface) 138 { 139 return CONTAINING_RECORD(iface, FormatConverter, IWICFormatConverter_iface); 140 } 141 142 static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRect *prc, 143 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 144 { 145 switch (source_format) 146 { 147 case format_1bppIndexed: 148 case format_BlackWhite: 149 if (prc) 150 { 151 HRESULT res; 152 INT x, y; 153 BYTE *srcdata; 154 UINT srcstride, srcdatasize; 155 const BYTE *srcrow; 156 const BYTE *srcbyte; 157 BYTE *dstrow; 158 DWORD *dstpixel; 159 WICColor colors[2]; 160 IWICPalette *palette; 161 UINT actualcolors; 162 163 res = PaletteImpl_Create(&palette); 164 if (FAILED(res)) return res; 165 166 if (source_format == format_1bppIndexed) 167 res = IWICBitmapSource_CopyPalette(This->source, palette); 168 else 169 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedBW, FALSE); 170 171 if (SUCCEEDED(res)) 172 res = IWICPalette_GetColors(palette, 2, colors, &actualcolors); 173 174 IWICPalette_Release(palette); 175 if (FAILED(res)) return res; 176 177 srcstride = (prc->Width+7)/8; 178 srcdatasize = srcstride * prc->Height; 179 180 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 181 if (!srcdata) return E_OUTOFMEMORY; 182 183 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 184 185 if (SUCCEEDED(res)) 186 { 187 srcrow = srcdata; 188 dstrow = pbBuffer; 189 for (y=0; y<prc->Height; y++) { 190 srcbyte = srcrow; 191 dstpixel=(DWORD*)dstrow; 192 for (x=0; x<prc->Width; x+=8) { 193 BYTE srcval; 194 srcval=*srcbyte++; 195 *dstpixel++ = colors[srcval>>7&1]; 196 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>6&1]; 197 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>5&1]; 198 if (x+3 < prc->Width) *dstpixel++ = colors[srcval>>4&1]; 199 if (x+4 < prc->Width) *dstpixel++ = colors[srcval>>3&1]; 200 if (x+5 < prc->Width) *dstpixel++ = colors[srcval>>2&1]; 201 if (x+6 < prc->Width) *dstpixel++ = colors[srcval>>1&1]; 202 if (x+7 < prc->Width) *dstpixel++ = colors[srcval&1]; 203 } 204 srcrow += srcstride; 205 dstrow += cbStride; 206 } 207 } 208 209 HeapFree(GetProcessHeap(), 0, srcdata); 210 211 return res; 212 } 213 return S_OK; 214 case format_2bppIndexed: 215 case format_2bppGray: 216 if (prc) 217 { 218 HRESULT res; 219 INT x, y; 220 BYTE *srcdata; 221 UINT srcstride, srcdatasize; 222 const BYTE *srcrow; 223 const BYTE *srcbyte; 224 BYTE *dstrow; 225 DWORD *dstpixel; 226 WICColor colors[4]; 227 IWICPalette *palette; 228 UINT actualcolors; 229 230 res = PaletteImpl_Create(&palette); 231 if (FAILED(res)) return res; 232 233 if (source_format == format_2bppIndexed) 234 res = IWICBitmapSource_CopyPalette(This->source, palette); 235 else 236 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray4, FALSE); 237 238 if (SUCCEEDED(res)) 239 res = IWICPalette_GetColors(palette, 4, colors, &actualcolors); 240 241 IWICPalette_Release(palette); 242 if (FAILED(res)) return res; 243 244 srcstride = (prc->Width+3)/4; 245 srcdatasize = srcstride * prc->Height; 246 247 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 248 if (!srcdata) return E_OUTOFMEMORY; 249 250 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 251 252 if (SUCCEEDED(res)) 253 { 254 srcrow = srcdata; 255 dstrow = pbBuffer; 256 for (y=0; y<prc->Height; y++) { 257 srcbyte = srcrow; 258 dstpixel=(DWORD*)dstrow; 259 for (x=0; x<prc->Width; x+=4) { 260 BYTE srcval; 261 srcval=*srcbyte++; 262 *dstpixel++ = colors[srcval>>6]; 263 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>4&0x3]; 264 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>2&0x3]; 265 if (x+3 < prc->Width) *dstpixel++ = colors[srcval&0x3]; 266 } 267 srcrow += srcstride; 268 dstrow += cbStride; 269 } 270 } 271 272 HeapFree(GetProcessHeap(), 0, srcdata); 273 274 return res; 275 } 276 return S_OK; 277 case format_4bppIndexed: 278 case format_4bppGray: 279 if (prc) 280 { 281 HRESULT res; 282 INT x, y; 283 BYTE *srcdata; 284 UINT srcstride, srcdatasize; 285 const BYTE *srcrow; 286 const BYTE *srcbyte; 287 BYTE *dstrow; 288 DWORD *dstpixel; 289 WICColor colors[16]; 290 IWICPalette *palette; 291 UINT actualcolors; 292 293 res = PaletteImpl_Create(&palette); 294 if (FAILED(res)) return res; 295 296 if (source_format == format_4bppIndexed) 297 res = IWICBitmapSource_CopyPalette(This->source, palette); 298 else 299 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray16, FALSE); 300 301 if (SUCCEEDED(res)) 302 res = IWICPalette_GetColors(palette, 16, colors, &actualcolors); 303 304 IWICPalette_Release(palette); 305 if (FAILED(res)) return res; 306 307 srcstride = (prc->Width+1)/2; 308 srcdatasize = srcstride * prc->Height; 309 310 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 311 if (!srcdata) return E_OUTOFMEMORY; 312 313 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 314 315 if (SUCCEEDED(res)) 316 { 317 srcrow = srcdata; 318 dstrow = pbBuffer; 319 for (y=0; y<prc->Height; y++) { 320 srcbyte = srcrow; 321 dstpixel=(DWORD*)dstrow; 322 for (x=0; x<prc->Width; x+=2) { 323 BYTE srcval; 324 srcval=*srcbyte++; 325 *dstpixel++ = colors[srcval>>4]; 326 if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0xf]; 327 } 328 srcrow += srcstride; 329 dstrow += cbStride; 330 } 331 } 332 333 HeapFree(GetProcessHeap(), 0, srcdata); 334 335 return res; 336 } 337 return S_OK; 338 case format_8bppGray: 339 if (prc) 340 { 341 HRESULT res; 342 INT x, y; 343 BYTE *srcdata; 344 UINT srcstride, srcdatasize; 345 const BYTE *srcrow; 346 const BYTE *srcbyte; 347 BYTE *dstrow; 348 DWORD *dstpixel; 349 350 srcstride = prc->Width; 351 srcdatasize = srcstride * prc->Height; 352 353 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 354 if (!srcdata) return E_OUTOFMEMORY; 355 356 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 357 358 if (SUCCEEDED(res)) 359 { 360 srcrow = srcdata; 361 dstrow = pbBuffer; 362 for (y=0; y<prc->Height; y++) { 363 srcbyte = srcrow; 364 dstpixel=(DWORD*)dstrow; 365 for (x=0; x<prc->Width; x++) 366 { 367 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte; 368 srcbyte++; 369 } 370 srcrow += srcstride; 371 dstrow += cbStride; 372 } 373 } 374 375 HeapFree(GetProcessHeap(), 0, srcdata); 376 377 return res; 378 } 379 return S_OK; 380 case format_8bppIndexed: 381 if (prc) 382 { 383 HRESULT res; 384 INT x, y; 385 BYTE *srcdata; 386 UINT srcstride, srcdatasize; 387 const BYTE *srcrow; 388 const BYTE *srcbyte; 389 BYTE *dstrow; 390 DWORD *dstpixel; 391 WICColor colors[256]; 392 IWICPalette *palette; 393 UINT actualcolors; 394 395 res = PaletteImpl_Create(&palette); 396 if (FAILED(res)) return res; 397 398 res = IWICBitmapSource_CopyPalette(This->source, palette); 399 if (SUCCEEDED(res)) 400 res = IWICPalette_GetColors(palette, 256, colors, &actualcolors); 401 402 IWICPalette_Release(palette); 403 404 if (FAILED(res)) return res; 405 406 srcstride = prc->Width; 407 srcdatasize = srcstride * prc->Height; 408 409 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 410 if (!srcdata) return E_OUTOFMEMORY; 411 412 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 413 414 if (SUCCEEDED(res)) 415 { 416 srcrow = srcdata; 417 dstrow = pbBuffer; 418 for (y=0; y<prc->Height; y++) { 419 srcbyte = srcrow; 420 dstpixel=(DWORD*)dstrow; 421 for (x=0; x<prc->Width; x++) 422 *dstpixel++ = colors[*srcbyte++]; 423 srcrow += srcstride; 424 dstrow += cbStride; 425 } 426 } 427 428 HeapFree(GetProcessHeap(), 0, srcdata); 429 430 return res; 431 } 432 return S_OK; 433 case format_16bppGray: 434 if (prc) 435 { 436 HRESULT res; 437 INT x, y; 438 BYTE *srcdata; 439 UINT srcstride, srcdatasize; 440 const BYTE *srcrow; 441 const BYTE *srcbyte; 442 BYTE *dstrow; 443 DWORD *dstpixel; 444 445 srcstride = prc->Width * 2; 446 srcdatasize = srcstride * prc->Height; 447 448 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 449 if (!srcdata) return E_OUTOFMEMORY; 450 451 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 452 453 if (SUCCEEDED(res)) 454 { 455 srcrow = srcdata; 456 dstrow = pbBuffer; 457 for (y=0; y<prc->Height; y++) { 458 srcbyte = srcrow; 459 dstpixel=(DWORD*)dstrow; 460 for (x=0; x<prc->Width; x++) 461 { 462 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte; 463 srcbyte+=2; 464 } 465 srcrow += srcstride; 466 dstrow += cbStride; 467 } 468 } 469 470 HeapFree(GetProcessHeap(), 0, srcdata); 471 472 return res; 473 } 474 return S_OK; 475 case format_16bppBGR555: 476 if (prc) 477 { 478 HRESULT res; 479 INT x, y; 480 BYTE *srcdata; 481 UINT srcstride, srcdatasize; 482 const BYTE *srcrow; 483 const WORD *srcpixel; 484 BYTE *dstrow; 485 DWORD *dstpixel; 486 487 srcstride = 2 * prc->Width; 488 srcdatasize = srcstride * prc->Height; 489 490 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 491 if (!srcdata) return E_OUTOFMEMORY; 492 493 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 494 495 if (SUCCEEDED(res)) 496 { 497 srcrow = srcdata; 498 dstrow = pbBuffer; 499 for (y=0; y<prc->Height; y++) { 500 srcpixel=(const WORD*)srcrow; 501 dstpixel=(DWORD*)dstrow; 502 for (x=0; x<prc->Width; x++) { 503 WORD srcval; 504 srcval=*srcpixel++; 505 *dstpixel++=0xff000000 | /* constant 255 alpha */ 506 ((srcval << 9) & 0xf80000) | /* r */ 507 ((srcval << 4) & 0x070000) | /* r - 3 bits */ 508 ((srcval << 6) & 0x00f800) | /* g */ 509 ((srcval << 1) & 0x000700) | /* g - 3 bits */ 510 ((srcval << 3) & 0x0000f8) | /* b */ 511 ((srcval >> 2) & 0x000007); /* b - 3 bits */ 512 } 513 srcrow += srcstride; 514 dstrow += cbStride; 515 } 516 } 517 518 HeapFree(GetProcessHeap(), 0, srcdata); 519 520 return res; 521 } 522 return S_OK; 523 case format_16bppBGR565: 524 if (prc) 525 { 526 HRESULT res; 527 INT x, y; 528 BYTE *srcdata; 529 UINT srcstride, srcdatasize; 530 const BYTE *srcrow; 531 const WORD *srcpixel; 532 BYTE *dstrow; 533 DWORD *dstpixel; 534 535 srcstride = 2 * prc->Width; 536 srcdatasize = srcstride * prc->Height; 537 538 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 539 if (!srcdata) return E_OUTOFMEMORY; 540 541 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 542 543 if (SUCCEEDED(res)) 544 { 545 srcrow = srcdata; 546 dstrow = pbBuffer; 547 for (y=0; y<prc->Height; y++) { 548 srcpixel=(const WORD*)srcrow; 549 dstpixel=(DWORD*)dstrow; 550 for (x=0; x<prc->Width; x++) { 551 WORD srcval; 552 srcval=*srcpixel++; 553 *dstpixel++=0xff000000 | /* constant 255 alpha */ 554 ((srcval << 8) & 0xf80000) | /* r */ 555 ((srcval << 3) & 0x070000) | /* r - 3 bits */ 556 ((srcval << 5) & 0x00fc00) | /* g */ 557 ((srcval >> 1) & 0x000300) | /* g - 2 bits */ 558 ((srcval << 3) & 0x0000f8) | /* b */ 559 ((srcval >> 2) & 0x000007); /* b - 3 bits */ 560 } 561 srcrow += srcstride; 562 dstrow += cbStride; 563 } 564 } 565 566 HeapFree(GetProcessHeap(), 0, srcdata); 567 568 return res; 569 } 570 return S_OK; 571 case format_16bppBGRA5551: 572 if (prc) 573 { 574 HRESULT res; 575 INT x, y; 576 BYTE *srcdata; 577 UINT srcstride, srcdatasize; 578 const BYTE *srcrow; 579 const WORD *srcpixel; 580 BYTE *dstrow; 581 DWORD *dstpixel; 582 583 srcstride = 2 * prc->Width; 584 srcdatasize = srcstride * prc->Height; 585 586 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 587 if (!srcdata) return E_OUTOFMEMORY; 588 589 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 590 591 if (SUCCEEDED(res)) 592 { 593 srcrow = srcdata; 594 dstrow = pbBuffer; 595 for (y=0; y<prc->Height; y++) { 596 srcpixel=(const WORD*)srcrow; 597 dstpixel=(DWORD*)dstrow; 598 for (x=0; x<prc->Width; x++) { 599 WORD srcval; 600 srcval=*srcpixel++; 601 *dstpixel++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */ 602 ((srcval << 9) & 0xf80000) | /* r */ 603 ((srcval << 4) & 0x070000) | /* r - 3 bits */ 604 ((srcval << 6) & 0x00f800) | /* g */ 605 ((srcval << 1) & 0x000700) | /* g - 3 bits */ 606 ((srcval << 3) & 0x0000f8) | /* b */ 607 ((srcval >> 2) & 0x000007); /* b - 3 bits */ 608 } 609 srcrow += srcstride; 610 dstrow += cbStride; 611 } 612 } 613 614 HeapFree(GetProcessHeap(), 0, srcdata); 615 616 return res; 617 } 618 return S_OK; 619 case format_24bppBGR: 620 if (prc) 621 { 622 HRESULT res; 623 INT x, y; 624 BYTE *srcdata; 625 UINT srcstride, srcdatasize; 626 const BYTE *srcrow; 627 const BYTE *srcpixel; 628 BYTE *dstrow; 629 BYTE *dstpixel; 630 631 srcstride = 3 * prc->Width; 632 srcdatasize = srcstride * prc->Height; 633 634 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 635 if (!srcdata) return E_OUTOFMEMORY; 636 637 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 638 639 if (SUCCEEDED(res)) 640 { 641 srcrow = srcdata; 642 dstrow = pbBuffer; 643 for (y=0; y<prc->Height; y++) { 644 srcpixel=srcrow; 645 dstpixel=dstrow; 646 for (x=0; x<prc->Width; x++) { 647 *dstpixel++=*srcpixel++; /* blue */ 648 *dstpixel++=*srcpixel++; /* green */ 649 *dstpixel++=*srcpixel++; /* red */ 650 *dstpixel++=255; /* alpha */ 651 } 652 srcrow += srcstride; 653 dstrow += cbStride; 654 } 655 } 656 657 HeapFree(GetProcessHeap(), 0, srcdata); 658 659 return res; 660 } 661 return S_OK; 662 case format_24bppRGB: 663 if (prc) 664 { 665 HRESULT res; 666 INT x, y; 667 BYTE *srcdata; 668 UINT srcstride, srcdatasize; 669 const BYTE *srcrow; 670 const BYTE *srcpixel; 671 BYTE *dstrow; 672 BYTE *dstpixel; 673 BYTE tmppixel[3]; 674 675 srcstride = 3 * prc->Width; 676 srcdatasize = srcstride * prc->Height; 677 678 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 679 if (!srcdata) return E_OUTOFMEMORY; 680 681 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 682 683 if (SUCCEEDED(res)) 684 { 685 srcrow = srcdata; 686 dstrow = pbBuffer; 687 for (y=0; y<prc->Height; y++) { 688 srcpixel=srcrow; 689 dstpixel=dstrow; 690 for (x=0; x<prc->Width; x++) { 691 tmppixel[0]=*srcpixel++; /* red */ 692 tmppixel[1]=*srcpixel++; /* green */ 693 tmppixel[2]=*srcpixel++; /* blue */ 694 695 *dstpixel++=tmppixel[2]; /* blue */ 696 *dstpixel++=tmppixel[1]; /* green */ 697 *dstpixel++=tmppixel[0]; /* red */ 698 *dstpixel++=255; /* alpha */ 699 } 700 srcrow += srcstride; 701 dstrow += cbStride; 702 } 703 } 704 705 HeapFree(GetProcessHeap(), 0, srcdata); 706 707 return res; 708 } 709 return S_OK; 710 case format_32bppBGR: 711 if (prc) 712 { 713 HRESULT res; 714 INT x, y; 715 716 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 717 if (FAILED(res)) return res; 718 719 /* set all alpha values to 255 */ 720 for (y=0; y<prc->Height; y++) 721 for (x=0; x<prc->Width; x++) 722 pbBuffer[cbStride*y+4*x+3] = 0xff; 723 } 724 return S_OK; 725 case format_32bppBGRA: 726 if (prc) 727 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 728 return S_OK; 729 case format_32bppPBGRA: 730 if (prc) 731 { 732 HRESULT res; 733 INT x, y; 734 735 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 736 if (FAILED(res)) return res; 737 738 for (y=0; y<prc->Height; y++) 739 for (x=0; x<prc->Width; x++) 740 { 741 BYTE alpha = pbBuffer[cbStride*y+4*x+3]; 742 if (alpha != 0 && alpha != 255) 743 { 744 pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha; 745 pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha; 746 pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha; 747 } 748 } 749 } 750 return S_OK; 751 case format_48bppRGB: 752 if (prc) 753 { 754 HRESULT res; 755 INT x, y; 756 BYTE *srcdata; 757 UINT srcstride, srcdatasize; 758 const BYTE *srcrow; 759 const BYTE *srcpixel; 760 BYTE *dstrow; 761 DWORD *dstpixel; 762 763 srcstride = 6 * prc->Width; 764 srcdatasize = srcstride * prc->Height; 765 766 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 767 if (!srcdata) return E_OUTOFMEMORY; 768 769 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 770 771 if (SUCCEEDED(res)) 772 { 773 srcrow = srcdata; 774 dstrow = pbBuffer; 775 for (y=0; y<prc->Height; y++) { 776 srcpixel=srcrow; 777 dstpixel=(DWORD*)dstrow; 778 for (x=0; x<prc->Width; x++) { 779 BYTE red, green, blue; 780 red = *srcpixel++; srcpixel++; 781 green = *srcpixel++; srcpixel++; 782 blue = *srcpixel++; srcpixel++; 783 *dstpixel++=0xff000000|red<<16|green<<8|blue; 784 } 785 srcrow += srcstride; 786 dstrow += cbStride; 787 } 788 } 789 790 HeapFree(GetProcessHeap(), 0, srcdata); 791 792 return res; 793 } 794 return S_OK; 795 case format_64bppRGBA: 796 if (prc) 797 { 798 HRESULT res; 799 INT x, y; 800 BYTE *srcdata; 801 UINT srcstride, srcdatasize; 802 const BYTE *srcrow; 803 const BYTE *srcpixel; 804 BYTE *dstrow; 805 DWORD *dstpixel; 806 807 srcstride = 8 * prc->Width; 808 srcdatasize = srcstride * prc->Height; 809 810 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 811 if (!srcdata) return E_OUTOFMEMORY; 812 813 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 814 815 if (SUCCEEDED(res)) 816 { 817 srcrow = srcdata; 818 dstrow = pbBuffer; 819 for (y=0; y<prc->Height; y++) { 820 srcpixel=srcrow; 821 dstpixel=(DWORD*)dstrow; 822 for (x=0; x<prc->Width; x++) { 823 BYTE red, green, blue, alpha; 824 red = *srcpixel++; srcpixel++; 825 green = *srcpixel++; srcpixel++; 826 blue = *srcpixel++; srcpixel++; 827 alpha = *srcpixel++; srcpixel++; 828 *dstpixel++=alpha<<24|red<<16|green<<8|blue; 829 } 830 srcrow += srcstride; 831 dstrow += cbStride; 832 } 833 } 834 835 HeapFree(GetProcessHeap(), 0, srcdata); 836 837 return res; 838 } 839 return S_OK; 840 case format_32bppCMYK: 841 if (prc) 842 { 843 HRESULT res; 844 UINT x, y; 845 846 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 847 if (FAILED(res)) return res; 848 849 for (y=0; y<prc->Height; y++) 850 for (x=0; x<prc->Width; x++) 851 { 852 BYTE *pixel = pbBuffer+cbStride*y+4*x; 853 BYTE c=pixel[0], m=pixel[1], y=pixel[2], k=pixel[3]; 854 pixel[0] = (255-y)*(255-k)/255; /* blue */ 855 pixel[1] = (255-m)*(255-k)/255; /* green */ 856 pixel[2] = (255-c)*(255-k)/255; /* red */ 857 pixel[3] = 255; /* alpha */ 858 } 859 } 860 return S_OK; 861 default: 862 return WINCODEC_ERR_UNSUPPORTEDOPERATION; 863 } 864 } 865 866 static HRESULT copypixels_to_32bppRGBA(struct FormatConverter *This, const WICRect *prc, 867 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 868 { 869 HRESULT hr; 870 871 switch (source_format) 872 { 873 case format_32bppRGB: 874 case format_32bppRGBA: 875 case format_32bppPRGBA: 876 if (prc) 877 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 878 return S_OK; 879 default: 880 hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); 881 if (SUCCEEDED(hr) && prc) 882 reverse_bgr8(4, pbBuffer, prc->Width, prc->Height, cbStride); 883 return hr; 884 } 885 } 886 887 static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc, 888 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 889 { 890 switch (source_format) 891 { 892 case format_32bppBGR: 893 case format_32bppBGRA: 894 case format_32bppPBGRA: 895 if (prc) 896 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 897 return S_OK; 898 default: 899 return copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); 900 } 901 } 902 903 static HRESULT copypixels_to_32bppRGB(struct FormatConverter *This, const WICRect *prc, 904 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 905 { 906 switch (source_format) 907 { 908 case format_32bppRGB: 909 case format_32bppRGBA: 910 case format_32bppPRGBA: 911 if (prc) 912 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 913 return S_OK; 914 default: 915 return copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); 916 } 917 } 918 919 static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICRect *prc, 920 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 921 { 922 HRESULT hr; 923 924 switch (source_format) 925 { 926 case format_32bppPBGRA: 927 if (prc) 928 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 929 return S_OK; 930 default: 931 hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); 932 if (SUCCEEDED(hr) && prc) 933 { 934 INT x, y; 935 936 for (y=0; y<prc->Height; y++) 937 for (x=0; x<prc->Width; x++) 938 { 939 BYTE alpha = pbBuffer[cbStride*y+4*x+3]; 940 if (alpha != 255) 941 { 942 pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255; 943 pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255; 944 pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255; 945 } 946 } 947 } 948 return hr; 949 } 950 } 951 952 static HRESULT copypixels_to_32bppPRGBA(struct FormatConverter *This, const WICRect *prc, 953 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 954 { 955 HRESULT hr; 956 957 switch (source_format) 958 { 959 case format_32bppPRGBA: 960 if (prc) 961 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 962 return S_OK; 963 default: 964 hr = copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); 965 if (SUCCEEDED(hr) && prc) 966 { 967 INT x, y; 968 969 for (y=0; y<prc->Height; y++) 970 for (x=0; x<prc->Width; x++) 971 { 972 BYTE alpha = pbBuffer[cbStride*y+4*x+3]; 973 if (alpha != 255) 974 { 975 pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255; 976 pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255; 977 pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255; 978 } 979 } 980 } 981 return hr; 982 } 983 } 984 985 static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRect *prc, 986 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 987 { 988 HRESULT hr; 989 990 switch (source_format) 991 { 992 case format_24bppBGR: 993 case format_24bppRGB: 994 if (prc) 995 { 996 hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 997 if (SUCCEEDED(hr) && source_format == format_24bppRGB) 998 reverse_bgr8(3, pbBuffer, prc->Width, prc->Height, cbStride); 999 return hr; 1000 } 1001 return S_OK; 1002 case format_32bppBGR: 1003 case format_32bppBGRA: 1004 case format_32bppPBGRA: 1005 if (prc) 1006 { 1007 HRESULT res; 1008 INT x, y; 1009 BYTE *srcdata; 1010 UINT srcstride, srcdatasize; 1011 const BYTE *srcrow; 1012 const BYTE *srcpixel; 1013 BYTE *dstrow; 1014 BYTE *dstpixel; 1015 1016 srcstride = 4 * prc->Width; 1017 srcdatasize = srcstride * prc->Height; 1018 1019 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 1020 if (!srcdata) return E_OUTOFMEMORY; 1021 1022 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 1023 1024 if (SUCCEEDED(res)) 1025 { 1026 srcrow = srcdata; 1027 dstrow = pbBuffer; 1028 for (y=0; y<prc->Height; y++) { 1029 srcpixel=srcrow; 1030 dstpixel=dstrow; 1031 for (x=0; x<prc->Width; x++) { 1032 *dstpixel++=*srcpixel++; /* blue */ 1033 *dstpixel++=*srcpixel++; /* green */ 1034 *dstpixel++=*srcpixel++; /* red */ 1035 srcpixel++; /* alpha */ 1036 } 1037 srcrow += srcstride; 1038 dstrow += cbStride; 1039 } 1040 } 1041 1042 HeapFree(GetProcessHeap(), 0, srcdata); 1043 1044 return res; 1045 } 1046 return S_OK; 1047 1048 case format_32bppGrayFloat: 1049 if (prc) 1050 { 1051 BYTE *srcdata; 1052 UINT srcstride, srcdatasize; 1053 1054 srcstride = 4 * prc->Width; 1055 srcdatasize = srcstride * prc->Height; 1056 1057 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 1058 if (!srcdata) return E_OUTOFMEMORY; 1059 1060 hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 1061 1062 if (SUCCEEDED(hr)) 1063 { 1064 INT x, y; 1065 BYTE *src = srcdata, *dst = pbBuffer; 1066 1067 for (y = 0; y < prc->Height; y++) 1068 { 1069 float *gray_float = (float *)src; 1070 BYTE *bgr = dst; 1071 1072 for (x = 0; x < prc->Width; x++) 1073 { 1074 BYTE gray = (BYTE)floorf(to_sRGB_component(gray_float[x]) * 255.0f + 0.51f); 1075 *bgr++ = gray; 1076 *bgr++ = gray; 1077 *bgr++ = gray; 1078 } 1079 src += srcstride; 1080 dst += cbStride; 1081 } 1082 } 1083 1084 HeapFree(GetProcessHeap(), 0, srcdata); 1085 1086 return hr; 1087 } 1088 return S_OK; 1089 1090 default: 1091 FIXME("Unimplemented conversion path!\n"); 1092 return WINCODEC_ERR_UNSUPPORTEDOPERATION; 1093 } 1094 } 1095 1096 static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRect *prc, 1097 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 1098 { 1099 HRESULT hr; 1100 1101 switch (source_format) 1102 { 1103 case format_24bppBGR: 1104 case format_24bppRGB: 1105 if (prc) 1106 { 1107 hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 1108 if (SUCCEEDED(hr) && source_format == format_24bppBGR) 1109 reverse_bgr8(3, pbBuffer, prc->Width, prc->Height, cbStride); 1110 return hr; 1111 } 1112 return S_OK; 1113 case format_32bppBGR: 1114 case format_32bppBGRA: 1115 case format_32bppPBGRA: 1116 if (prc) 1117 { 1118 HRESULT res; 1119 INT x, y; 1120 BYTE *srcdata; 1121 UINT srcstride, srcdatasize; 1122 const BYTE *srcrow; 1123 const BYTE *srcpixel; 1124 BYTE *dstrow; 1125 BYTE *dstpixel; 1126 BYTE tmppixel[3]; 1127 1128 srcstride = 4 * prc->Width; 1129 srcdatasize = srcstride * prc->Height; 1130 1131 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 1132 if (!srcdata) return E_OUTOFMEMORY; 1133 1134 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 1135 1136 if (SUCCEEDED(res)) 1137 { 1138 srcrow = srcdata; 1139 dstrow = pbBuffer; 1140 for (y=0; y<prc->Height; y++) { 1141 srcpixel=srcrow; 1142 dstpixel=dstrow; 1143 for (x=0; x<prc->Width; x++) { 1144 tmppixel[0]=*srcpixel++; /* blue */ 1145 tmppixel[1]=*srcpixel++; /* green */ 1146 tmppixel[2]=*srcpixel++; /* red */ 1147 srcpixel++; /* alpha */ 1148 1149 *dstpixel++=tmppixel[2]; /* red */ 1150 *dstpixel++=tmppixel[1]; /* green */ 1151 *dstpixel++=tmppixel[0]; /* blue */ 1152 } 1153 srcrow += srcstride; 1154 dstrow += cbStride; 1155 } 1156 } 1157 1158 HeapFree(GetProcessHeap(), 0, srcdata); 1159 1160 return res; 1161 } 1162 return S_OK; 1163 default: 1164 FIXME("Unimplemented conversion path!\n"); 1165 return WINCODEC_ERR_UNSUPPORTEDOPERATION; 1166 } 1167 } 1168 1169 static HRESULT copypixels_to_32bppGrayFloat(struct FormatConverter *This, const WICRect *prc, 1170 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 1171 { 1172 HRESULT hr; 1173 1174 switch (source_format) 1175 { 1176 case format_32bppBGR: 1177 case format_32bppBGRA: 1178 case format_32bppPBGRA: 1179 case format_32bppGrayFloat: 1180 if (prc) 1181 { 1182 hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 1183 break; 1184 } 1185 return S_OK; 1186 1187 default: 1188 hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); 1189 break; 1190 } 1191 1192 if (SUCCEEDED(hr) && prc && source_format != format_32bppGrayFloat) 1193 { 1194 INT x, y; 1195 BYTE *p = pbBuffer; 1196 1197 for (y = 0; y < prc->Height; y++) 1198 { 1199 BYTE *bgr = p; 1200 for (x = 0; x < prc->Width; x++) 1201 { 1202 float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f; 1203 *(float *)bgr = gray; 1204 bgr += 4; 1205 } 1206 p += cbStride; 1207 } 1208 } 1209 return hr; 1210 } 1211 1212 static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRect *prc, 1213 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 1214 { 1215 HRESULT hr; 1216 BYTE *srcdata; 1217 UINT srcstride, srcdatasize; 1218 1219 if (source_format == format_8bppGray) 1220 { 1221 if (prc) 1222 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 1223 1224 return S_OK; 1225 } 1226 1227 if (source_format == format_32bppGrayFloat) 1228 { 1229 hr = S_OK; 1230 1231 if (prc) 1232 { 1233 srcstride = 4 * prc->Width; 1234 srcdatasize = srcstride * prc->Height; 1235 1236 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 1237 if (!srcdata) return E_OUTOFMEMORY; 1238 1239 hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); 1240 if (SUCCEEDED(hr)) 1241 { 1242 INT x, y; 1243 BYTE *src = srcdata, *dst = pbBuffer; 1244 1245 for (y=0; y < prc->Height; y++) 1246 { 1247 float *srcpixel = (float*)src; 1248 BYTE *dstpixel = dst; 1249 1250 for (x=0; x < prc->Width; x++) 1251 *dstpixel++ = (BYTE)floorf(to_sRGB_component(*srcpixel++) * 255.0f + 0.51f); 1252 1253 src += srcstride; 1254 dst += cbStride; 1255 } 1256 } 1257 1258 HeapFree(GetProcessHeap(), 0, srcdata); 1259 } 1260 1261 return hr; 1262 } 1263 1264 srcstride = 3 * prc->Width; 1265 srcdatasize = srcstride * prc->Height; 1266 1267 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 1268 if (!srcdata) return E_OUTOFMEMORY; 1269 1270 hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); 1271 if (SUCCEEDED(hr) && prc) 1272 { 1273 INT x, y; 1274 BYTE *src = srcdata, *dst = pbBuffer; 1275 1276 for (y = 0; y < prc->Height; y++) 1277 { 1278 BYTE *bgr = src; 1279 1280 for (x = 0; x < prc->Width; x++) 1281 { 1282 float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f; 1283 1284 gray = to_sRGB_component(gray) * 255.0f; 1285 dst[x] = (BYTE)floorf(gray + 0.51f); 1286 bgr += 3; 1287 } 1288 src += srcstride; 1289 dst += cbStride; 1290 } 1291 } 1292 1293 HeapFree(GetProcessHeap(), 0, srcdata); 1294 return hr; 1295 } 1296 1297 static UINT rgb_to_palette_index(BYTE r, BYTE g, BYTE b, WICColor *colors, UINT count) 1298 { 1299 UINT best_diff, best_index, i; 1300 1301 best_diff = ~0; 1302 best_index = 0; 1303 1304 for (i = 0; i < count; i++) 1305 { 1306 BYTE pal_r, pal_g, pal_b; 1307 DWORD diff_r, diff_g, diff_b, diff; 1308 1309 pal_r = colors[i] >> 16; 1310 pal_g = colors[i] >> 8; 1311 pal_b = colors[i]; 1312 1313 diff_r = r - pal_r; 1314 diff_g = g - pal_g; 1315 diff_b = b - pal_b; 1316 1317 diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b; 1318 if (diff == 0) return i; 1319 1320 if (diff < best_diff) 1321 { 1322 best_diff = diff; 1323 best_index = i; 1324 } 1325 } 1326 1327 return best_index; 1328 } 1329 1330 static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WICRect *prc, 1331 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) 1332 { 1333 HRESULT hr; 1334 BYTE *srcdata; 1335 WICColor colors[256]; 1336 UINT srcstride, srcdatasize, count; 1337 1338 if (source_format == format_8bppIndexed) 1339 { 1340 if (prc) 1341 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); 1342 1343 return S_OK; 1344 } 1345 1346 if (!This->palette) return WINCODEC_ERR_WRONGSTATE; 1347 1348 hr = IWICPalette_GetColors(This->palette, 256, colors, &count); 1349 if (hr != S_OK) return hr; 1350 1351 srcstride = 3 * prc->Width; 1352 srcdatasize = srcstride * prc->Height; 1353 1354 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); 1355 if (!srcdata) return E_OUTOFMEMORY; 1356 1357 hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); 1358 if (SUCCEEDED(hr) && prc) 1359 { 1360 INT x, y; 1361 BYTE *src = srcdata, *dst = pbBuffer; 1362 1363 for (y = 0; y < prc->Height; y++) 1364 { 1365 BYTE *bgr = src; 1366 1367 for (x = 0; x < prc->Width; x++) 1368 { 1369 dst[x] = rgb_to_palette_index(bgr[2], bgr[1], bgr[0], colors, count); 1370 bgr += 3; 1371 } 1372 src += srcstride; 1373 dst += cbStride; 1374 } 1375 } 1376 1377 HeapFree(GetProcessHeap(), 0, srcdata); 1378 return hr; 1379 } 1380 1381 static const struct pixelformatinfo supported_formats[] = { 1382 {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL}, 1383 {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL}, 1384 {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL}, 1385 {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed}, 1386 {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL}, 1387 {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL}, 1388 {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL}, 1389 {format_8bppGray, &GUID_WICPixelFormat8bppGray, copypixels_to_8bppGray}, 1390 {format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL}, 1391 {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL}, 1392 {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL}, 1393 {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL}, 1394 {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, copypixels_to_24bppBGR}, 1395 {format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB}, 1396 {format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat, copypixels_to_32bppGrayFloat}, 1397 {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR}, 1398 {format_32bppRGB, &GUID_WICPixelFormat32bppRGB, copypixels_to_32bppRGB}, 1399 {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA}, 1400 {format_32bppRGBA, &GUID_WICPixelFormat32bppRGBA, copypixels_to_32bppRGBA}, 1401 {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA}, 1402 {format_32bppPRGBA, &GUID_WICPixelFormat32bppPRGBA, copypixels_to_32bppPRGBA}, 1403 {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL}, 1404 {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL}, 1405 {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL}, 1406 {0} 1407 }; 1408 1409 static const struct pixelformatinfo *get_formatinfo(const WICPixelFormatGUID *format) 1410 { 1411 UINT i; 1412 1413 for (i=0; supported_formats[i].guid; i++) 1414 if (IsEqualGUID(supported_formats[i].guid, format)) return &supported_formats[i]; 1415 1416 return NULL; 1417 } 1418 1419 static HRESULT WINAPI FormatConverter_QueryInterface(IWICFormatConverter *iface, REFIID iid, 1420 void **ppv) 1421 { 1422 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1423 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 1424 1425 if (!ppv) return E_INVALIDARG; 1426 1427 if (IsEqualIID(&IID_IUnknown, iid) || 1428 IsEqualIID(&IID_IWICBitmapSource, iid) || 1429 IsEqualIID(&IID_IWICFormatConverter, iid)) 1430 { 1431 *ppv = &This->IWICFormatConverter_iface; 1432 } 1433 else 1434 { 1435 *ppv = NULL; 1436 return E_NOINTERFACE; 1437 } 1438 1439 IUnknown_AddRef((IUnknown*)*ppv); 1440 return S_OK; 1441 } 1442 1443 static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface) 1444 { 1445 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1446 ULONG ref = InterlockedIncrement(&This->ref); 1447 1448 TRACE("(%p) refcount=%u\n", iface, ref); 1449 1450 return ref; 1451 } 1452 1453 static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface) 1454 { 1455 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1456 ULONG ref = InterlockedDecrement(&This->ref); 1457 1458 TRACE("(%p) refcount=%u\n", iface, ref); 1459 1460 if (ref == 0) 1461 { 1462 This->lock.DebugInfo->Spare[0] = 0; 1463 DeleteCriticalSection(&This->lock); 1464 if (This->source) IWICBitmapSource_Release(This->source); 1465 if (This->palette) IWICPalette_Release(This->palette); 1466 HeapFree(GetProcessHeap(), 0, This); 1467 } 1468 1469 return ref; 1470 } 1471 1472 static HRESULT WINAPI FormatConverter_GetSize(IWICFormatConverter *iface, 1473 UINT *puiWidth, UINT *puiHeight) 1474 { 1475 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1476 1477 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight); 1478 1479 if (This->source) 1480 return IWICBitmapSource_GetSize(This->source, puiWidth, puiHeight); 1481 else 1482 return WINCODEC_ERR_NOTINITIALIZED; 1483 } 1484 1485 static HRESULT WINAPI FormatConverter_GetPixelFormat(IWICFormatConverter *iface, 1486 WICPixelFormatGUID *pPixelFormat) 1487 { 1488 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1489 1490 TRACE("(%p,%p)\n", iface, pPixelFormat); 1491 1492 if (This->source) 1493 memcpy(pPixelFormat, This->dst_format->guid, sizeof(GUID)); 1494 else 1495 return WINCODEC_ERR_NOTINITIALIZED; 1496 1497 return S_OK; 1498 } 1499 1500 static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface, 1501 double *pDpiX, double *pDpiY) 1502 { 1503 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1504 1505 TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY); 1506 1507 if (This->source) 1508 return IWICBitmapSource_GetResolution(This->source, pDpiX, pDpiY); 1509 else 1510 return WINCODEC_ERR_NOTINITIALIZED; 1511 } 1512 1513 static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface, 1514 IWICPalette *palette) 1515 { 1516 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1517 1518 TRACE("(%p,%p)\n", iface, palette); 1519 1520 if (!palette) return E_INVALIDARG; 1521 if (!This->source) return WINCODEC_ERR_WRONGSTATE; 1522 1523 if (!This->palette) 1524 { 1525 HRESULT hr; 1526 UINT bpp; 1527 1528 hr = get_pixelformat_bpp(This->dst_format->guid, &bpp); 1529 if (hr != S_OK) return hr; 1530 if (bpp <= 8) return WINCODEC_ERR_WRONGSTATE; 1531 return IWICBitmapSource_CopyPalette(This->source, palette); 1532 } 1533 1534 return IWICPalette_InitializeFromPalette(palette, This->palette); 1535 } 1536 1537 static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface, 1538 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) 1539 { 1540 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1541 WICRect rc; 1542 HRESULT hr; 1543 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer); 1544 1545 if (This->source) 1546 { 1547 if (!prc) 1548 { 1549 UINT width, height; 1550 hr = IWICBitmapSource_GetSize(This->source, &width, &height); 1551 if (FAILED(hr)) return hr; 1552 rc.X = 0; 1553 rc.Y = 0; 1554 rc.Width = width; 1555 rc.Height = height; 1556 prc = &rc; 1557 } 1558 1559 return This->dst_format->copy_function(This, prc, cbStride, cbBufferSize, 1560 pbBuffer, This->src_format->format); 1561 } 1562 else 1563 return WINCODEC_ERR_WRONGSTATE; 1564 } 1565 1566 static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, 1567 IWICBitmapSource *source, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither, 1568 IWICPalette *palette, double alpha_threshold, WICBitmapPaletteType palette_type) 1569 { 1570 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1571 const struct pixelformatinfo *srcinfo, *dstinfo; 1572 GUID srcFormat; 1573 HRESULT res; 1574 1575 TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat), 1576 dither, palette, alpha_threshold, palette_type); 1577 1578 if (!palette) 1579 { 1580 UINT bpp; 1581 res = get_pixelformat_bpp(dstFormat, &bpp); 1582 if (res != S_OK) return res; 1583 1584 res = PaletteImpl_Create(&palette); 1585 if (res != S_OK) return res; 1586 1587 switch (palette_type) 1588 { 1589 case WICBitmapPaletteTypeCustom: 1590 IWICPalette_Release(palette); 1591 palette = NULL; 1592 if (bpp <= 8) return E_INVALIDARG; 1593 break; 1594 1595 case WICBitmapPaletteTypeMedianCut: 1596 { 1597 if (bpp <= 8) 1598 res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE); 1599 break; 1600 } 1601 1602 default: 1603 if (bpp <= 8) 1604 res = IWICPalette_InitializePredefined(palette, palette_type, FALSE); 1605 break; 1606 } 1607 1608 if (res != S_OK) 1609 { 1610 IWICPalette_Release(palette); 1611 return res; 1612 } 1613 } 1614 else 1615 IWICPalette_AddRef(palette); 1616 1617 EnterCriticalSection(&This->lock); 1618 1619 if (This->source) 1620 { 1621 res = WINCODEC_ERR_WRONGSTATE; 1622 goto end; 1623 } 1624 1625 res = IWICBitmapSource_GetPixelFormat(source, &srcFormat); 1626 if (FAILED(res)) goto end; 1627 1628 srcinfo = get_formatinfo(&srcFormat); 1629 if (!srcinfo) 1630 { 1631 res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; 1632 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat)); 1633 goto end; 1634 } 1635 1636 dstinfo = get_formatinfo(dstFormat); 1637 if (!dstinfo) 1638 { 1639 res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; 1640 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat)); 1641 goto end; 1642 } 1643 1644 if (dstinfo->copy_function) 1645 { 1646 IWICBitmapSource_AddRef(source); 1647 This->src_format = srcinfo; 1648 This->dst_format = dstinfo; 1649 This->dither = dither; 1650 This->alpha_threshold = alpha_threshold; 1651 This->palette = palette; 1652 This->source = source; 1653 } 1654 else 1655 { 1656 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat)); 1657 res = WINCODEC_ERR_UNSUPPORTEDOPERATION; 1658 } 1659 1660 end: 1661 1662 LeaveCriticalSection(&This->lock); 1663 1664 if (res != S_OK && palette) 1665 IWICPalette_Release(palette); 1666 1667 return res; 1668 } 1669 1670 static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface, 1671 REFWICPixelFormatGUID srcPixelFormat, REFWICPixelFormatGUID dstPixelFormat, 1672 BOOL *pfCanConvert) 1673 { 1674 FormatConverter *This = impl_from_IWICFormatConverter(iface); 1675 const struct pixelformatinfo *srcinfo, *dstinfo; 1676 1677 TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(srcPixelFormat), 1678 debugstr_guid(dstPixelFormat), pfCanConvert); 1679 1680 srcinfo = get_formatinfo(srcPixelFormat); 1681 if (!srcinfo) 1682 { 1683 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat)); 1684 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; 1685 } 1686 1687 dstinfo = get_formatinfo(dstPixelFormat); 1688 if (!dstinfo) 1689 { 1690 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat)); 1691 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; 1692 } 1693 1694 if (dstinfo->copy_function && 1695 SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format))) 1696 *pfCanConvert = TRUE; 1697 else 1698 { 1699 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat), debugstr_guid(dstPixelFormat)); 1700 *pfCanConvert = FALSE; 1701 } 1702 1703 return S_OK; 1704 } 1705 1706 static const IWICFormatConverterVtbl FormatConverter_Vtbl = { 1707 FormatConverter_QueryInterface, 1708 FormatConverter_AddRef, 1709 FormatConverter_Release, 1710 FormatConverter_GetSize, 1711 FormatConverter_GetPixelFormat, 1712 FormatConverter_GetResolution, 1713 FormatConverter_CopyPalette, 1714 FormatConverter_CopyPixels, 1715 FormatConverter_Initialize, 1716 FormatConverter_CanConvert 1717 }; 1718 1719 HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv) 1720 { 1721 FormatConverter *This; 1722 HRESULT ret; 1723 1724 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); 1725 1726 *ppv = NULL; 1727 1728 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter)); 1729 if (!This) return E_OUTOFMEMORY; 1730 1731 This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl; 1732 This->ref = 1; 1733 This->source = NULL; 1734 This->palette = NULL; 1735 InitializeCriticalSection(&This->lock); 1736 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock"); 1737 1738 ret = IWICFormatConverter_QueryInterface(&This->IWICFormatConverter_iface, iid, ppv); 1739 IWICFormatConverter_Release(&This->IWICFormatConverter_iface); 1740 1741 return ret; 1742 } 1743