static ULONG WINAPI PngDecoder_AddRef(IWICBitmapDecoder *iface) { PngDecoder *This = impl_from_IWICBitmapDecoder(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) refcount=%u\n", iface, ref); return ref; }
static HRESULT WINAPI JpegDecoder_GetFrame(IWICBitmapDecoder *iface, UINT index, IWICBitmapFrameDecode **ppIBitmapFrame) { JpegDecoder *This = impl_from_IWICBitmapDecoder(iface); TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame); if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED; if (index != 0) return E_INVALIDARG; IWICBitmapDecoder_AddRef(iface); *ppIBitmapFrame = &This->IWICBitmapFrameDecode_iface; return S_OK; }
static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface) { PngDecoder *This = impl_from_IWICBitmapDecoder(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) refcount=%u\n", iface, ref); if (ref == 0) { if (This->png_ptr) ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info); This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, This->image_bits); HeapFree(GetProcessHeap(), 0, This); } return ref; }
static ULONG WINAPI JpegDecoder_Release(IWICBitmapDecoder *iface) { JpegDecoder *This = impl_from_IWICBitmapDecoder(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) refcount=%u\n", iface, ref); if (ref == 0) { This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock); if (This->cinfo_initialized) pjpeg_destroy_decompress(&This->cinfo); if (This->stream) IStream_Release(This->stream); HeapFree(GetProcessHeap(), 0, This->image_data); HeapFree(GetProcessHeap(), 0, This); } return ref; }
static HRESULT WINAPI PngDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, void **ppv) { PngDecoder *This = impl_from_IWICBitmapDecoder(iface); TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); if (!ppv) return E_INVALIDARG; if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid)) { *ppv = &This->IWICBitmapDecoder_iface; } else { *ppv = NULL; return E_NOINTERFACE; } IUnknown_AddRef((IUnknown*)*ppv); return S_OK; }
static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, WICDecodeOptions cacheOptions) { PngDecoder *This = impl_from_IWICBitmapDecoder(iface); LARGE_INTEGER seek; HRESULT hr=S_OK; png_bytep *row_pointers=NULL; UINT image_size; UINT i; int color_type, bit_depth; png_bytep trans; int num_trans; png_uint_32 transparency; png_color_16p trans_values; jmp_buf jmpbuf; TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions); EnterCriticalSection(&This->lock); /* initialize libpng */ This->png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!This->png_ptr) { hr = E_FAIL; goto end; } This->info_ptr = ppng_create_info_struct(This->png_ptr); if (!This->info_ptr) { ppng_destroy_read_struct(&This->png_ptr, NULL, NULL); This->png_ptr = NULL; hr = E_FAIL; goto end; } This->end_info = ppng_create_info_struct(This->png_ptr); if (!This->info_ptr) { ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, NULL); This->png_ptr = NULL; hr = E_FAIL; goto end; } /* set up setjmp/longjmp error handling */ if (setjmp(jmpbuf)) { ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info); HeapFree(GetProcessHeap(), 0, row_pointers); This->png_ptr = NULL; hr = E_FAIL; goto end; } ppng_set_error_fn(This->png_ptr, jmpbuf, user_error_fn, user_warning_fn); ppng_set_crc_action(This->png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); /* seek to the start of the stream */ seek.QuadPart = 0; hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL); if (FAILED(hr)) goto end; /* set up custom i/o handling */ ppng_set_read_fn(This->png_ptr, pIStream, user_read_data); /* read the header */ ppng_read_info(This->png_ptr, This->info_ptr); /* choose a pixel format */ color_type = ppng_get_color_type(This->png_ptr, This->info_ptr); bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr); /* check for color-keyed alpha */ transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values); if (transparency && color_type != PNG_COLOR_TYPE_PALETTE) { /* expand to RGBA */ if (color_type == PNG_COLOR_TYPE_GRAY) { if (bit_depth < 8) { #ifdef HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8 ppng_set_expand_gray_1_2_4_to_8(This->png_ptr); #else ppng_set_gray_1_2_4_to_8(This->png_ptr); #endif bit_depth = 8; } ppng_set_gray_to_rgb(This->png_ptr); } ppng_set_tRNS_to_alpha(This->png_ptr); color_type = PNG_COLOR_TYPE_RGB_ALPHA; } switch (color_type) { case PNG_COLOR_TYPE_GRAY: This->bpp = bit_depth; switch (bit_depth) { case 1: This->format = &GUID_WICPixelFormatBlackWhite; break; case 2: This->format = &GUID_WICPixelFormat2bppGray; break; case 4: This->format = &GUID_WICPixelFormat4bppGray; break; case 8: This->format = &GUID_WICPixelFormat8bppGray; break; case 16: This->format = &GUID_WICPixelFormat16bppGray; break; default: ERR("invalid grayscale bit depth: %i\n", bit_depth); hr = E_FAIL; goto end; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: /* WIC does not support grayscale alpha formats so use RGBA */ ppng_set_gray_to_rgb(This->png_ptr); /* fall through */ case PNG_COLOR_TYPE_RGB_ALPHA: This->bpp = bit_depth * 4; switch (bit_depth) { case 8: ppng_set_bgr(This->png_ptr); This->format = &GUID_WICPixelFormat32bppBGRA; break; case 16: This->format = &GUID_WICPixelFormat64bppRGBA; break; default: ERR("invalid RGBA bit depth: %i\n", bit_depth); hr = E_FAIL; goto end; } break; case PNG_COLOR_TYPE_PALETTE: This->bpp = bit_depth; switch (bit_depth) { case 1: This->format = &GUID_WICPixelFormat1bppIndexed; break; case 2: This->format = &GUID_WICPixelFormat2bppIndexed; break; case 4: This->format = &GUID_WICPixelFormat4bppIndexed; break; case 8: This->format = &GUID_WICPixelFormat8bppIndexed; break; default: ERR("invalid indexed color bit depth: %i\n", bit_depth); hr = E_FAIL; goto end; } break; case PNG_COLOR_TYPE_RGB: This->bpp = bit_depth * 3; switch (bit_depth) { case 8: ppng_set_bgr(This->png_ptr); This->format = &GUID_WICPixelFormat24bppBGR; break; case 16: This->format = &GUID_WICPixelFormat48bppRGB; break; default: ERR("invalid RGB color bit depth: %i\n", bit_depth); hr = E_FAIL; goto end; } break; default: ERR("invalid color type %i\n", color_type); hr = E_FAIL; goto end; } /* read the image data */ This->width = ppng_get_image_width(This->png_ptr, This->info_ptr); This->height = ppng_get_image_height(This->png_ptr, This->info_ptr); This->stride = This->width * This->bpp; image_size = This->stride * This->height; This->image_bits = HeapAlloc(GetProcessHeap(), 0, image_size); if (!This->image_bits) { hr = E_OUTOFMEMORY; goto end; } row_pointers = HeapAlloc(GetProcessHeap(), 0, sizeof(png_bytep)*This->height); if (!row_pointers) { hr = E_OUTOFMEMORY; goto end; } for (i=0; i<This->height; i++) row_pointers[i] = This->image_bits + i * This->stride; ppng_read_image(This->png_ptr, row_pointers); HeapFree(GetProcessHeap(), 0, row_pointers); row_pointers = NULL; ppng_read_end(This->png_ptr, This->end_info); This->initialized = TRUE; end: LeaveCriticalSection(&This->lock); return hr; }
static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, WICDecodeOptions cacheOptions) { JpegDecoder *This = impl_from_IWICBitmapDecoder(iface); int ret; LARGE_INTEGER seek; jmp_buf jmpbuf; TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions); EnterCriticalSection(&This->lock); if (This->cinfo_initialized) { LeaveCriticalSection(&This->lock); return WINCODEC_ERR_WRONGSTATE; } pjpeg_std_error(&This->jerr); This->jerr.error_exit = error_exit_fn; This->jerr.emit_message = emit_message_fn; This->cinfo.err = &This->jerr; This->cinfo.client_data = &jmpbuf; if (setjmp(jmpbuf)) { LeaveCriticalSection(&This->lock); return E_FAIL; } pjpeg_CreateDecompress(&This->cinfo, JPEG_LIB_VERSION, sizeof(struct jpeg_decompress_struct)); This->cinfo_initialized = TRUE; This->stream = pIStream; IStream_AddRef(pIStream); seek.QuadPart = 0; IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL); This->source_mgr.bytes_in_buffer = 0; This->source_mgr.init_source = source_mgr_init_source; This->source_mgr.fill_input_buffer = source_mgr_fill_input_buffer; This->source_mgr.skip_input_data = source_mgr_skip_input_data; This->source_mgr.resync_to_restart = pjpeg_resync_to_restart; This->source_mgr.term_source = source_mgr_term_source; This->cinfo.src = &This->source_mgr; ret = pjpeg_read_header(&This->cinfo, TRUE); if (ret != JPEG_HEADER_OK) { WARN("Jpeg image in stream has bad format, read header returned %d.\n",ret); LeaveCriticalSection(&This->lock); return E_FAIL; } switch (This->cinfo.jpeg_color_space) { case JCS_GRAYSCALE: This->cinfo.out_color_space = JCS_GRAYSCALE; break; case JCS_RGB: case JCS_YCbCr: This->cinfo.out_color_space = JCS_RGB; break; case JCS_CMYK: case JCS_YCCK: This->cinfo.out_color_space = JCS_CMYK; break; default: ERR("Unknown JPEG color space %i\n", This->cinfo.jpeg_color_space); LeaveCriticalSection(&This->lock); return E_FAIL; } if (!pjpeg_start_decompress(&This->cinfo)) { ERR("jpeg_start_decompress failed\n"); LeaveCriticalSection(&This->lock); return E_FAIL; } This->initialized = TRUE; LeaveCriticalSection(&This->lock); return S_OK; }