1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project//-------------------------------------
2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project//  PNGFILE.C -- Image File Functions
3893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project//-------------------------------------
4893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
5a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott// Copyright 2000, Willem van Schaik.
6a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott//
7a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott// This code is released under the libpng license.
8a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott// For conditions of distribution and use, see the disclaimer
9a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott// and license in png.h
10893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
11893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include <windows.h>
12893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include <commdlg.h>
13893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include <stdio.h>
14893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include <stdlib.h>
15893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
16893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include "png.h"
17893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include "pngfile.h"
18893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include "cexcept.h"
19893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
20893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectdefine_exception_type(const char *);
21893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectextern struct exception_context the_exception_context[1];
22893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstruct exception_context the_exception_context[1];
23893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_const_charp msg;
24893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
25893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic OPENFILENAME ofn;
26893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
27893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic png_structp png_ptr = NULL;
28893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic png_infop info_ptr = NULL;
29893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
30893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
31893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project// cexcept interface
32893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
33893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic void
34893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_cexcept_error(png_structp png_ptr, png_const_charp msg)
35893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
36893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if(png_ptr)
37893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     ;
38893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifndef PNG_NO_CONSOLE_IO
39893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   fprintf(stderr, "libpng error: %s\n", msg);
40893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
41893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
42893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      Throw msg;
43893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
44893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
45893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
46893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project// Windows open-file functions
47893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
48893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PngFileInitialize (HWND hwnd)
49893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
50893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    static TCHAR szFilter[] = TEXT ("PNG Files (*.PNG)\0*.png\0")
51893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        TEXT ("All Files (*.*)\0*.*\0\0");
52893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
53893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lStructSize       = sizeof (OPENFILENAME);
54893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.hwndOwner         = hwnd;
55893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.hInstance         = NULL;
56893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrFilter       = szFilter;
57893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrCustomFilter = NULL;
58893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.nMaxCustFilter    = 0;
59893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.nFilterIndex      = 0;
60893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrFile         = NULL;          // Set in Open and Close functions
61893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.nMaxFile          = MAX_PATH;
62893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrFileTitle    = NULL;          // Set in Open and Close functions
63893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.nMaxFileTitle     = MAX_PATH;
64893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrInitialDir   = NULL;
65893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrTitle        = NULL;
66893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.Flags             = 0;             // Set in Open and Close functions
67893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.nFileOffset       = 0;
68893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.nFileExtension    = 0;
69893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrDefExt       = TEXT ("png");
70893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lCustData         = 0;
71893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpfnHook          = NULL;
72893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpTemplateName    = NULL;
73893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
74893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
75893912bfc2683463dc3e2c445336752d012563d3The Android Open Source ProjectBOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
76893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
77893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.hwndOwner         = hwnd;
78893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrFile         = pstrFileName;
79893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrFileTitle    = pstrTitleName;
80893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.Flags             = OFN_HIDEREADONLY;
81893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
82893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return GetOpenFileName (&ofn);
83893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
84893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
85893912bfc2683463dc3e2c445336752d012563d3The Android Open Source ProjectBOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
86893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
87893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.hwndOwner         = hwnd;
88893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrFile         = pstrFileName;
89893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.lpstrFileTitle    = pstrTitleName;
90893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ofn.Flags             = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
91893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
92893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return GetSaveFileName (&ofn);
93893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
94893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
95893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project// PNG image handler functions
96893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
97893912bfc2683463dc3e2c445336752d012563d3The Android Open Source ProjectBOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData,
98893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor)
99893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
100893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    static FILE        *pfFile;
101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_byte            pbSig[8];
102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    int                 iBitDepth;
103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    int                 iColorType;
104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    double              dGamma;
105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_color_16       *pBackground;
106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_uint_32         ulChannels;
107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_uint_32         ulRowBytes;
108893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_byte           *pbImageData = *ppbImageData;
109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    static png_byte   **ppbRowPointers = NULL;
110893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    int                 i;
111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    // open the PNG input file
113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
114893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!pstrFileName)
115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
116893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *ppbImageData = pbImageData = NULL;
117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
118893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
119893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
120893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!(pfFile = fopen(pstrFileName, "rb")))
121893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *ppbImageData = pbImageData = NULL;
123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
124893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    // first check the eight byte PNG signature
127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    fread(pbSig, 1, 8, pfFile);
1295f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott    if (png_sig_cmp(pbSig, 0, 8))
130893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
131893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *ppbImageData = pbImageData = NULL;
132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
133893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    // create the two png(-info) structures
136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
139893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!png_ptr)
140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
141893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *ppbImageData = pbImageData = NULL;
142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    info_ptr = png_create_info_struct(png_ptr);
146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!info_ptr)
147893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_read_struct(&png_ptr, NULL, NULL);
149893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *ppbImageData = pbImageData = NULL;
150893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
151893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
152893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
153893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    Try
154893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // initialize the png structure
157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
158893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_NO_STDIO)
159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_init_io(png_ptr, pfFile);
160893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else
161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data);
162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
164893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_sig_bytes(png_ptr, 8);
165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // read all PNG info up to image data
167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_read_info(png_ptr, info_ptr);
169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
170893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // get width, height, bit-depth and color-type
171893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
173893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            &iColorType, NULL, NULL, NULL);
174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // expand images of all color-type and bit-depth to 3x8 bit RGB images
176893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // let the library process things like alpha, transparency, background
177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (iBitDepth == 16)
179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_set_strip_16(png_ptr);
180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (iColorType == PNG_COLOR_TYPE_PALETTE)
181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_set_expand(png_ptr);
182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (iBitDepth < 8)
183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_set_expand(png_ptr);
184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_set_expand(png_ptr);
186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (iColorType == PNG_COLOR_TYPE_GRAY ||
187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
188893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_set_gray_to_rgb(png_ptr);
189893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // set the background color to draw transparent and alpha images over.
191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        {
193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            pBkgColor->red   = (byte) pBackground->red;
195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            pBkgColor->green = (byte) pBackground->green;
196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            pBkgColor->blue  = (byte) pBackground->blue;
197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
198893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        else
199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        {
200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            pBkgColor = NULL;
201893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // if required set gamma conversion
204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (png_get_gAMA(png_ptr, info_ptr, &dGamma))
205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_set_gamma(png_ptr, (double) 2.2, dGamma);
206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
207893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // after the transformations have been registered update info_ptr data
208893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_read_update_info(png_ptr, info_ptr);
210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // get again width, height and the new bit-depth and color-type
212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth,
214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            &iColorType, NULL, NULL, NULL);
215893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // row_bytes is the width x number of channels
218893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
219893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
220893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        ulChannels = png_get_channels(png_ptr, info_ptr);
221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
222893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *piChannels = ulChannels;
223893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // now we can allocate memory to store the image
225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (pbImageData)
227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        {
228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            free (pbImageData);
229893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            pbImageData = NULL;
230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
231893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight)
232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                            * sizeof(png_byte))) == NULL)
233893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        {
234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_error(png_ptr, "Visual PNG: out of memory");
235893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *ppbImageData = pbImageData;
237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // and allocate memory for an array of row-pointers
239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if ((ppbRowPointers = (png_bytepp) malloc((*piHeight)
241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                            * sizeof(png_bytep))) == NULL)
242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        {
243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            png_error(png_ptr, "Visual PNG: out of memory");
244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // set the individual row-pointers to point at the correct offsets
247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        for (i = 0; i < (*piHeight); i++)
249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ppbRowPointers[i] = pbImageData + i * ulRowBytes;
250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // now we can go ahead and just read the whole image
252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_read_image(png_ptr, ppbRowPointers);
254893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
255893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // read the additional chunks in the PNG file (not really needed)
256893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_read_end(png_ptr, NULL);
258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // and we're done
260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        free (ppbRowPointers);
262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        ppbRowPointers = NULL;
263893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // yepp, done
265893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    Catch (msg)
268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        *ppbImageData = pbImageData = NULL;
272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if(ppbRowPointers)
274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            free (ppbRowPointers);
275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
276893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        fclose(pfFile);
277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
280893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    fclose (pfFile);
282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return TRUE;
284893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
286893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source ProjectBOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData,
288893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                   int iWidth, int iHeight, png_color bkgColor)
289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    const int           ciBitDepth = 8;
291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    const int           ciChannels = 3;
292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    static FILE        *pfFile;
294893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_uint_32         ulRowBytes;
295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    static png_byte   **ppbRowPointers = NULL;
296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    int                 i;
297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    // open the PNG output file
299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
300893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!pstrFileName)
301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!(pfFile = fopen(pstrFileName, "wb")))
304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    // prepare the standard PNG structures
307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!png_ptr)
311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        fclose(pfFile);
313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
314893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
315893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    info_ptr = png_create_info_struct(png_ptr);
317893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!info_ptr) {
318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        fclose(pfFile);
319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
321893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    Try
324893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // initialize the png structure
326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_NO_STDIO)
328893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_init_io(png_ptr, pfFile);
329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else
330893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_write_fn(png_ptr, (png_voidp)pfFile, png_write_data, png_flush);
331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // we're going to write a very simple 3x8 bit RGB image
334893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth,
336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            PNG_FILTER_TYPE_BASE);
338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // write the file header information
340893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_write_info(png_ptr, info_ptr);
342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // swap the BGR pixels in the DiData structure to RGB
344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_bgr(png_ptr);
346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // row_bytes is the width x number of channels
348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        ulRowBytes = iWidth * ciChannels;
350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // we can allocate memory for an array of row-pointers
352893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL)
354893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            Throw "Visualpng: Out of memory";
355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
356893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // set the individual row-pointers to point at the correct offsets
357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        for (i = 0; i < iHeight; i++)
359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2);
360893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // write out the entire image data in one call
362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
363893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_write_image (png_ptr, ppbRowPointers);
364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // write the additional chunks to the PNG file (not really needed)
366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_write_end(png_ptr, info_ptr);
368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // and we're done
370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        free (ppbRowPointers);
372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        ppbRowPointers = NULL;
373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // clean up after the write, and free any memory allocated
375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
376893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
378893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        // yepp, done
379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
381893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    Catch (msg)
382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    {
383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if(ppbRowPointers)
386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            free (ppbRowPointers);
387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        fclose(pfFile);
389893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
390893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return FALSE;
391893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
392893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
393893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    fclose (pfFile);
394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
395893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return TRUE;
396893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_NO_STDIO
399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic void
401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
402893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_size_t check;
404893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    * instead of an int, which is what fread() actually returns.
407893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    */
408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   check = (png_size_t)fread(data, (png_size_t)1, length,
409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      (FILE *)png_ptr->io_ptr);
410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (check != length)
412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
413893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_error(png_ptr, "Read Error");
414893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
416893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
417893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic void
418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
419893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   png_uint_32 check;
421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
422893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (check != length)
424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   {
425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      png_error(png_ptr, "Write Error");
426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   }
427893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic void
430893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_flush(png_structp png_ptr)
431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   FILE *io_ptr;
433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   if (io_ptr != NULL)
435893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      fflush(io_ptr);
436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
438893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif
439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
440893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project//-----------------
441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project//  end of source
442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project//-----------------
443