static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels) { PngEncoder *This = encoder_from_frame(iface); png_byte **row_pointers=NULL; UINT i; jmp_buf jmpbuf; TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels); if (!This->frame_initialized || !This->width || !This->height || !This->format) return WINCODEC_ERR_WRONGSTATE; if (lineCount == 0 || lineCount + This->lines_written > This->height) return E_INVALIDARG; /* set up setjmp/longjmp error handling */ if (setjmp(jmpbuf)) { HeapFree(GetProcessHeap(), 0, row_pointers); return E_FAIL; } ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn); if (!This->info_written) { ppng_set_IHDR(This->png_ptr, This->info_ptr, This->width, This->height, This->format->bit_depth, This->format->color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (This->xres != 0.0 && This->yres != 0.0) { ppng_set_pHYs(This->png_ptr, This->info_ptr, (This->xres+0.0127) / 0.0254, (This->yres+0.0127) / 0.0254, PNG_RESOLUTION_METER); } ppng_write_info(This->png_ptr, This->info_ptr); if (This->format->remove_filler) ppng_set_filler(This->png_ptr, 0, PNG_FILLER_AFTER); if (This->format->swap_rgb) ppng_set_bgr(This->png_ptr); This->info_written = TRUE; } row_pointers = HeapAlloc(GetProcessHeap(), 0, lineCount * sizeof(png_byte*)); if (!row_pointers) return E_OUTOFMEMORY; for (i=0; i<lineCount; i++) row_pointers[i] = pbPixels + cbStride * i; ppng_write_rows(This->png_ptr, row_pointers, lineCount); This->lines_written += lineCount; HeapFree(GetProcessHeap(), 0, row_pointers); return S_OK; }
static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels) { PngEncoder *This = impl_from_IWICBitmapFrameEncode(iface); png_byte **row_pointers=NULL; UINT i; jmp_buf jmpbuf; TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels); EnterCriticalSection(&This->lock); if (!This->frame_initialized || !This->width || !This->height || !This->format) { LeaveCriticalSection(&This->lock); return WINCODEC_ERR_WRONGSTATE; } if (lineCount == 0 || lineCount + This->lines_written > This->height) { LeaveCriticalSection(&This->lock); return E_INVALIDARG; } /* set up setjmp/longjmp error handling */ if (setjmp(jmpbuf)) { LeaveCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, row_pointers); return E_FAIL; } ppng_set_error_fn(This->png_ptr, jmpbuf, user_error_fn, user_warning_fn); if (!This->info_written) { if (This->interlace) { /* libpng requires us to write all data multiple times in this case. */ This->stride = (This->format->bpp * This->width + 7)/8; This->data = HeapAlloc(GetProcessHeap(), 0, This->height * This->stride); if (!This->data) { LeaveCriticalSection(&This->lock); return E_OUTOFMEMORY; } } ppng_set_IHDR(This->png_ptr, This->info_ptr, This->width, This->height, This->format->bit_depth, This->format->color_type, This->interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (This->xres != 0.0 && This->yres != 0.0) { ppng_set_pHYs(This->png_ptr, This->info_ptr, (This->xres+0.0127) / 0.0254, (This->yres+0.0127) / 0.0254, PNG_RESOLUTION_METER); } ppng_write_info(This->png_ptr, This->info_ptr); if (This->format->remove_filler) ppng_set_filler(This->png_ptr, 0, PNG_FILLER_AFTER); if (This->format->swap_rgb) ppng_set_bgr(This->png_ptr); if (This->interlace) This->passes = ppng_set_interlace_handling(This->png_ptr); This->info_written = TRUE; } if (This->interlace) { /* Just store the data so we can write it in multiple passes in Commit. */ for (i=0; i<lineCount; i++) memcpy(This->data + This->stride * (This->lines_written + i), pbPixels + cbStride * i, This->stride); This->lines_written += lineCount; LeaveCriticalSection(&This->lock); return S_OK; } row_pointers = HeapAlloc(GetProcessHeap(), 0, lineCount * sizeof(png_byte*)); if (!row_pointers) { LeaveCriticalSection(&This->lock); return E_OUTOFMEMORY; } for (i=0; i<lineCount; i++) row_pointers[i] = pbPixels + cbStride * i; ppng_write_rows(This->png_ptr, row_pointers, lineCount); This->lines_written += lineCount; LeaveCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, row_pointers); return S_OK; }