HRESULT PngDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) { PngDecoder *This; HRESULT ret; TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv); *ppv = NULL; if (pUnkOuter) return CLASS_E_NOAGGREGATION; if (!libpng_handle && !load_libpng()) { ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG); return E_FAIL; } This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngDecoder)); if (!This) return E_OUTOFMEMORY; This->lpVtbl = &PngDecoder_Vtbl; This->lpFrameVtbl = &PngDecoder_FrameVtbl; This->ref = 1; This->png_ptr = NULL; This->info_ptr = NULL; This->end_info = NULL; This->initialized = FALSE; This->image_bits = NULL; ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv); IUnknown_Release((IUnknown*)This); return ret; }
HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv) { PngDecoder *This; HRESULT ret; TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); *ppv = NULL; if (!libpng_handle && !load_libpng()) { ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG); return E_FAIL; } This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngDecoder)); if (!This) return E_OUTOFMEMORY; This->IWICBitmapDecoder_iface.lpVtbl = &PngDecoder_Vtbl; This->IWICBitmapFrameDecode_iface.lpVtbl = &PngDecoder_FrameVtbl; This->IWICMetadataBlockReader_iface.lpVtbl = &PngDecoder_BlockVtbl; This->ref = 1; This->png_ptr = NULL; This->info_ptr = NULL; This->end_info = NULL; This->initialized = FALSE; This->image_bits = NULL; InitializeCriticalSection(&This->lock); This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngDecoder.lock"); ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); return ret; }
HRESULT PngEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) { PngEncoder *This; HRESULT ret; TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv); *ppv = NULL; if (pUnkOuter) return CLASS_E_NOAGGREGATION; if (!libpng_handle && !load_libpng()) { ERR("Failed writing PNG because unable to find %s\n",SONAME_LIBPNG); return E_FAIL; } This = HeapAlloc(GetProcessHeap(), 0, sizeof(PngEncoder)); if (!This) return E_OUTOFMEMORY; This->IWICBitmapEncoder_iface.lpVtbl = &PngEncoder_Vtbl; This->IWICBitmapFrameEncode_iface.lpVtbl = &PngEncoder_FrameVtbl; This->ref = 1; This->png_ptr = NULL; This->info_ptr = NULL; This->stream = NULL; This->frame_count = 0; This->frame_initialized = FALSE; This->format = NULL; This->info_written = FALSE; This->width = 0; This->height = 0; This->xres = 0.0; This->yres = 0.0; This->lines_written = 0; This->frame_committed = FALSE; This->committed = FALSE; InitializeCriticalSection(&This->lock); This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngEncoder.lock"); ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv); IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface); return ret; }
static BOOL SaveIconResAsPNG(const BITMAPINFO *pIcon, const char *png_filename, LPCWSTR commentW) { static const char comment_key[] = "Created from"; FILE *fp; png_structp png_ptr; png_infop info_ptr; png_text comment; int nXORWidthBytes, nANDWidthBytes, color_type = 0, i, j; BYTE *row, *copy = NULL; const BYTE *pXOR, *pAND = NULL; int nWidth = pIcon->bmiHeader.biWidth; int nHeight = pIcon->bmiHeader.biHeight; int nBpp = pIcon->bmiHeader.biBitCount; switch (nBpp) { case 32: color_type |= PNG_COLOR_MASK_ALPHA; /* fall through */ case 24: color_type |= PNG_COLOR_MASK_COLOR; break; default: return FALSE; } if (!libpng_handle && !load_libpng()) { WINE_WARN("Unable to load libpng\n"); return FALSE; } if (!(fp = fopen(png_filename, "w"))) { WINE_ERR("unable to open '%s' for writing: %s\n", png_filename, strerror(errno)); return FALSE; } nXORWidthBytes = 4 * ((nWidth * nBpp + 31) / 32); nANDWidthBytes = 4 * ((nWidth + 31 ) / 32); pXOR = (const BYTE*) pIcon + sizeof(BITMAPINFOHEADER) + pIcon->bmiHeader.biClrUsed * sizeof(RGBQUAD); if (nHeight > nWidth) { nHeight /= 2; pAND = pXOR + nHeight * nXORWidthBytes; } /* Apply mask if present */ if (pAND) { RGBQUAD bgColor; /* copy bytes before modifying them */ copy = HeapAlloc( GetProcessHeap(), 0, nHeight * nXORWidthBytes ); memcpy( copy, pXOR, nHeight * nXORWidthBytes ); pXOR = copy; /* image and mask are upside down reversed */ row = copy + (nHeight - 1) * nXORWidthBytes; /* top left corner */ bgColor.rgbRed = row[0]; bgColor.rgbGreen = row[1]; bgColor.rgbBlue = row[2]; bgColor.rgbReserved = 0; for (i = 0; i < nHeight; i++, row -= nXORWidthBytes) for (j = 0; j < nWidth; j++, row += nBpp >> 3) if (MASK(j, i)) { RGBQUAD *pixel = (RGBQUAD *)row; pixel->rgbBlue = bgColor.rgbBlue; pixel->rgbGreen = bgColor.rgbGreen; pixel->rgbRed = bgColor.rgbRed; if (nBpp == 32) pixel->rgbReserved = bgColor.rgbReserved; } } comment.text = NULL; if (!(png_ptr = ppng_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) || !(info_ptr = ppng_create_info_struct(png_ptr))) goto error; if (setjmp(png_jmpbuf(png_ptr))) { /* All future errors jump here */ WINE_ERR("png error\n"); goto error; } ppng_init_io(png_ptr, fp); ppng_set_IHDR(png_ptr, info_ptr, nWidth, nHeight, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Set comment */ comment.compression = PNG_TEXT_COMPRESSION_NONE; comment.key = (png_charp)comment_key; i = WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, NULL, 0, NULL, NULL); comment.text = HeapAlloc(GetProcessHeap(), 0, i); WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, comment.text, i, NULL, NULL); comment.text_length = i - 1; ppng_set_text(png_ptr, info_ptr, &comment, 1); ppng_write_info(png_ptr, info_ptr); ppng_set_bgr(png_ptr); for (i = nHeight - 1; i >= 0 ; i--) ppng_write_row(png_ptr, (png_bytep)pXOR + nXORWidthBytes * i); ppng_write_end(png_ptr, info_ptr); ppng_destroy_write_struct(&png_ptr, &info_ptr); if (png_ptr) ppng_destroy_write_struct(&png_ptr, NULL); fclose(fp); HeapFree(GetProcessHeap(), 0, copy); HeapFree(GetProcessHeap(), 0, comment.text); return TRUE; error: if (png_ptr) ppng_destroy_write_struct(&png_ptr, NULL); fclose(fp); unlink(png_filename); HeapFree(GetProcessHeap(), 0, copy); HeapFree(GetProcessHeap(), 0, comment.text); return FALSE; }