Damjan Jovanovic : windowscodecs: Read PNGs sequentially.
Alexandre Julliard
julliard at winehq.org
Thu Oct 6 17:24:31 CDT 2011
Module: wine
Branch: master
Commit: ea35386b2b11f4f74f8dfbae5f614ee49689e6af
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ea35386b2b11f4f74f8dfbae5f614ee49689e6af
Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date: Tue Oct 4 16:44:46 2011 +0200
windowscodecs: Read PNGs sequentially.
---
dlls/windowscodecs/pngformat.c | 185 +++++++++++++++++++---------------------
1 files changed, 87 insertions(+), 98 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index f5f6fdb..b3d92fd 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -56,11 +56,8 @@ MAKE_FUNCPTR(png_get_image_height);
MAKE_FUNCPTR(png_get_image_width);
MAKE_FUNCPTR(png_get_io_ptr);
MAKE_FUNCPTR(png_get_pHYs);
-MAKE_FUNCPTR(png_get_progressive_ptr);
MAKE_FUNCPTR(png_get_PLTE);
MAKE_FUNCPTR(png_get_tRNS);
-MAKE_FUNCPTR(png_process_data);
-MAKE_FUNCPTR(png_progressive_combine_row);
MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_error_fn);
#if HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8
@@ -72,7 +69,6 @@ MAKE_FUNCPTR(png_set_filler);
MAKE_FUNCPTR(png_set_gray_to_rgb);
MAKE_FUNCPTR(png_set_IHDR);
MAKE_FUNCPTR(png_set_pHYs);
-MAKE_FUNCPTR(png_set_progressive_read_fn);
MAKE_FUNCPTR(png_set_read_fn);
MAKE_FUNCPTR(png_set_strip_16);
MAKE_FUNCPTR(png_set_tRNS_to_alpha);
@@ -80,7 +76,6 @@ MAKE_FUNCPTR(png_set_write_fn);
MAKE_FUNCPTR(png_read_end);
MAKE_FUNCPTR(png_read_image);
MAKE_FUNCPTR(png_read_info);
-MAKE_FUNCPTR(png_read_update_info);
MAKE_FUNCPTR(png_write_end);
MAKE_FUNCPTR(png_write_info);
MAKE_FUNCPTR(png_write_rows);
@@ -108,11 +103,8 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_get_image_width);
LOAD_FUNCPTR(png_get_io_ptr);
LOAD_FUNCPTR(png_get_pHYs);
- LOAD_FUNCPTR(png_get_progressive_ptr);
LOAD_FUNCPTR(png_get_PLTE);
LOAD_FUNCPTR(png_get_tRNS);
- LOAD_FUNCPTR(png_process_data);
- LOAD_FUNCPTR(png_progressive_combine_row);
LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_error_fn);
#if HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8
@@ -124,7 +116,6 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_set_gray_to_rgb);
LOAD_FUNCPTR(png_set_IHDR);
LOAD_FUNCPTR(png_set_pHYs);
- LOAD_FUNCPTR(png_set_progressive_read_fn);
LOAD_FUNCPTR(png_set_read_fn);
LOAD_FUNCPTR(png_set_strip_16);
LOAD_FUNCPTR(png_set_tRNS_to_alpha);
@@ -132,7 +123,6 @@ static void *load_libpng(void)
LOAD_FUNCPTR(png_read_end);
LOAD_FUNCPTR(png_read_image);
LOAD_FUNCPTR(png_read_info);
- LOAD_FUNCPTR(png_read_update_info);
LOAD_FUNCPTR(png_write_end);
LOAD_FUNCPTR(png_write_info);
LOAD_FUNCPTR(png_write_rows);
@@ -165,6 +155,7 @@ typedef struct {
LONG ref;
png_structp png_ptr;
png_infop info_ptr;
+ png_infop end_info;
BOOL initialized;
int bpp;
int width, height;
@@ -228,7 +219,7 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
if (ref == 0)
{
if (This->png_ptr)
- ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, NULL);
+ 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);
@@ -245,18 +236,86 @@ static HRESULT WINAPI PngDecoder_QueryCapability(IWICBitmapDecoder *iface, IStre
return E_NOTIMPL;
}
-static void info_callback(png_structp png_ptr, png_infop info)
+static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
+ IStream *stream = ppng_get_io_ptr(png_ptr);
+ HRESULT hr;
+ ULONG bytesread;
+
+ hr = IStream_Read(stream, data, length, &bytesread);
+ if (FAILED(hr) || bytesread != length)
+ {
+ ppng_error(png_ptr, "failed reading data");
+ }
+}
+
+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;
- UINT image_size;
- HRESULT hr = S_OK;
- PngDecoder *This;
+ 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 = (PngDecoder*) ppng_get_progressive_ptr(png_ptr);
+ 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);
+
+ /* 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);
@@ -355,6 +414,7 @@ static void info_callback(png_structp png_ptr, png_infop info)
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;
@@ -367,96 +427,24 @@ static void info_callback(png_structp png_ptr, png_infop info)
goto end;
}
- ppng_read_update_info(This->png_ptr, This->info_ptr);
- This->initialized = TRUE;
-
-end:
- if (FAILED(hr))
- ERR("PNG info parsing failed, hr=0x%08X\n", hr);
-}
-
-static void row_callback(png_structp png_ptr, png_bytep new_row,
- png_uint_32 row_num, int pass)
-{
- png_bytep old_row;
- PngDecoder *This;
-
- This = (PngDecoder*) ppng_get_progressive_ptr(png_ptr);
- if (!This->initialized)
- return;
-
- old_row = ((png_bytep)This->image_bits) + row_num*This->stride;
- ppng_progressive_combine_row(png_ptr, old_row, new_row);
-}
-
-static void end_callback(png_structp png_ptr, png_infop info)
-{
-}
-
-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;
- jmp_buf jmpbuf;
- BYTE buffer[8096];
- ULONG bytesRead = 0;
-
- 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)
+ row_pointers = HeapAlloc(GetProcessHeap(), 0, sizeof(png_bytep)*This->height);
+ if (!row_pointers)
{
- hr = E_FAIL;
+ hr = E_OUTOFMEMORY;
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;
- }
+ for (i=0; i<This->height; i++)
+ row_pointers[i] = This->image_bits + i * This->stride;
- /* set up setjmp/longjmp error handling */
- if (setjmp(jmpbuf))
- {
- ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, NULL);
- 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_read_image(This->png_ptr, row_pointers);
- /* seek to the start of the stream */
- seek.QuadPart = 0;
- hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
- if (FAILED(hr)) goto end;
+ HeapFree(GetProcessHeap(), 0, row_pointers);
+ row_pointers = NULL;
- /* set up progressive loading */
- ppng_set_progressive_read_fn(This->png_ptr, (void*)This,
- info_callback, row_callback, end_callback);
+ ppng_read_end(This->png_ptr, This->end_info);
- do
- {
- hr = IStream_Read(pIStream, buffer, sizeof(buffer), &bytesRead);
- if (SUCCEEDED(hr))
- ppng_process_data(This->png_ptr, This->info_ptr, buffer, bytesRead);
- } while (bytesRead == sizeof(buffer));
- if (hr == S_FALSE)
- hr = S_OK;
- if (FAILED(hr))
- ERR("reading PNG file failed, error 0x%08X\n", hr);
- if (!This->initialized)
- hr = E_FAIL;
+ This->initialized = TRUE;
end:
@@ -780,6 +768,7 @@ HRESULT PngDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
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);
More information about the wine-cvs
mailing list