pngutil.cpp

Go to the documentation of this file.
00001 // $Id: pngutil.cpp 1372 2006-06-27 11:23:21Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // Contains useful routines for compressing a bitmap out to a PNG format file and
00100 // routines to load that file back in.
00101 
00102 #include "camtypes.h"
00103 #include "pngutil.h"
00104 #include "pngprgrs.h"
00105 
00106 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 
00110 //#include "camfiltr.h"     // BaseCamelotFilter - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "resource.h"     // _R(IDS_OUT_OF_MEMORY)
00112 //#include "accures.h"      // _R(IDW_CANCELLEDBMPIMPORT)
00113 //#include "andy.h"         // _R(IDE_FORMATNOTSUPPORTED)
00114 //#include "filtrres.h"     // _R(IDS_UNKNOWN_PNG_ERROR)
00115 
00116 // Header files supplied by PNG library
00117 #include "png.h"
00118 
00119 // Replacements for some libpng functions
00120 #include "pngfuncs.h"
00121 
00122 #define new CAM_DEBUG_NEW
00123 
00124 // Create a global pointer to the instance of the progress
00125 // bar created in the read function - needed as it is not
00126 // possible to give a C style pointer to a function in a C++
00127 // class
00128 PORTNOTE("other","png_progress_bar_read - removed progressbar")
00129 #ifndef EXCLUDE_FROM_XARALX
00130 class PNGProgressBar * png_progress_bar_read;
00131 #endif
00132 
00133 /******************************************************************* 
00134 
00135 >       void camelot_png_read_row_callback
00136             (png_structp png_ptr, png_uint_32 row_number, INT32 pass)
00137 
00138         Author: Jonathan_Payne (Xara Group Ltd) <camelotdev@xara.com>
00139         Created: 29/8/2000
00140         Inputs: png_ptr, row, pass
00141         Outputs: Status bar update
00142         Returns: void
00143         Purpose: Pointer to this function given to libpng to be
00144                  called when a row has been read.
00145 *******************************************************************/
00146 
00147 void camelot_png_read_row_callback
00148             (png_structp png_ptr, png_uint_32 row_number, INT32 pass)
00149 {
00150 PORTNOTE("other","camelot_png_read_row_callback - removed progressbar")
00151 #ifndef EXCLUDE_FROM_XARALX
00152     png_progress_bar_read->UpdateCallback(png_ptr, row_number, pass);
00153 #endif
00154 }
00155 
00156 // An implement to match the Declare in the .h file.
00157 CC_IMPLEMENT_MEMDUMP(PNGUtil, CC_CLASS_MEMDUMP)
00158 
00159 // define the statics that we require
00160 //BOOL  PNGUtil::Interlace      = FALSE;    // Use interlace or not
00161 INT32       PNGUtil::Transparent    = -1;       // colour or -1 = no transparency
00162 CCLexFile* PNGUtil::pFile           = NULL;     // The CCLexFile class that we are using
00163 
00164 /********************************************************************************************
00165 
00166 >   PNGUtil::PNGUtil()
00167 
00168     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00169     Created:    09/05/96
00170     Purpose:    Default constructor for the class. 
00171     SeeAlso:    
00172 
00173 ********************************************************************************************/
00174 
00175 PNGUtil::PNGUtil()
00176 {
00177 }
00178 
00179 /********************************************************************************************
00180 >   PNGUtil::~PNGUtil()
00181 
00182     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00183     Created:    09/05/96
00184     Purpose:    Default destructor for the class.
00185     SeeAlso:    
00186 
00187 ********************************************************************************************/
00188 
00189 PNGUtil::~PNGUtil()
00190 {
00191 }
00192 
00193 /********************************************************************************************
00194 
00195 >   static BOOL PNGUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
00196                                        INT32 *TransColour, 
00197                                        String_64 *ProgressString = NULL,
00198                                        BaseCamelotFilter *pFilter = NULL )
00199 
00200     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00201     Created:    09/05/96
00202     Inputs:     File            A opened CCLexFile that can be read from. It should be positioned at the
00203                                 start. Caller is responsible for closing it. The file needs to be in
00204                                 Binary mode.
00205                 ProgressString  allows the user to specify whether they require a progress hourglass or 
00206                                 not. If NULL then none is shown, otherwise an progress bar is shown
00207                                 using the text supplied. Defaults to NULL i.e. no progress bar.
00208                 pFilter         is an alternative way of handling the progress bar, assume the
00209                                 progress bar has been start and just call the IncProgressBarCount in 
00210                                 BaseCamelotFilter to do the progress bar update.
00211                                 Defaults to NULL i.e. no progress bar.
00212     Outputs:    Info points to a new LPBITMAPINFO struct and Bits points to the bytes.
00213                 These can be freed up with FreeDIB.
00214                 TransColour is either -1 == none or equal to the transparency colour found
00215     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
00216     Purpose:    Reads a .PNG file into memory decompressing it as it goes.
00217                 ***Errors on 16-bit builds***
00218                 A progress hourglass can be shown if required.
00219     Errors:     Calls SetError on FALSE returns.
00220     Scope:      Static, Public
00221     SeeAlso:    DIBUtil::ReadFromFile; AccusoftFilters::ReadFromFile;
00222 
00223 ********************************************************************************************/
00224 
00225 BOOL PNGUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
00226                             INT32 *TransColour, 
00227                             String_64 *ProgressString,
00228                             BaseCamelotFilter *pFilter)
00229 {
00230     TRACEUSER( "Jonathan", _T("PNG read: Start\n"));
00231     *Info = NULL;       // in case of early exit
00232     *Bits = NULL;
00233     pFile = File;
00234     Transparent     = -1;
00235     *TransColour    = -1;   // in case of early exit set to none
00236     
00237     UINT32 sig_read = 0;
00238     png_uint_32 width, height;
00239     INT32 bit_depth, color_type, interlace_type;
00240     
00241     BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
00242     BOOL OldReportingState = File->SetReportErrors( FALSE );
00243     
00244     png_structp png_ptr     = 0;    // Must be zero to avoid bad free in case of exception
00245     png_infop info_ptr      = 0;    // Must be zero to avoid bad free in case of exception
00246 
00247     png_bytepp ppbRowPointers= 0;   // Must be zero to avoid bad free in case of exception
00248 
00249     try {
00250     /* Create and initialize the png_struct with the desired error handler
00251     * functions.  If you want to use the default stderr and longjump method,
00252     * you can supply NULL for the last three parameters.  We also supply the
00253     * the compiler header file version, so that we know if the application
00254     * was compiled with a compatible version of the library.  REQUIRED
00255         */
00256         //   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00257         //      png_voidp user_error_ptr, user_error_fn, user_warning_fn);
00258         png_ptr = png_create_read_struct_2(
00259             PNG_LIBPNG_VER_STRING,  // Version of libpng
00260             0,                      // Optional pointer to be sent with errors
00261             camelot_png_error,      // Function called in case of error
00262             camelot_png_warning,        // Function called for warnings
00263             0,                      // Optional pointer to be sent with mem ops
00264             camelot_png_malloc,     // Function called to alloc memory
00265             camelot_png_free            // Function called to free memory
00266             );
00267         
00268         if (png_ptr == NULL)
00269             File->GotError( _R(IDS_OUT_OF_MEMORY) );
00270 
00271         /* Allocate/initialize the memory for image information.  REQUIRED. */
00272         info_ptr = png_create_info_struct(png_ptr);
00273         if (info_ptr == NULL)
00274         {
00275             png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
00276             File->GotError( _R(IDS_OUT_OF_MEMORY) );
00277         }
00278         
00279         /* Set up the input control if you are using standard C streams */
00280         iostream* pFStream = File->GetIOFile();
00281         // Should use our own IO functions eg.
00282         png_set_read_fn(png_ptr, pFStream, camelot_png_read_data);
00283         //   png_init_io(png_ptr, pFStream);
00284         
00285         /* If we have already read some of the signature */
00286         // Not sure about this - JP
00287         png_set_sig_bytes(png_ptr, sig_read);
00288         
00289         /* The call to png_read_info() gives us all of the information from the
00290         * PNG file before the first IDAT (image data chunk).  REQUIRED */
00291         png_read_info(png_ptr, info_ptr);
00292         
00293         png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
00294             &interlace_type, NULL, NULL);
00295         
00296         TRACEUSER( "Jonathan", _T("PNG read: Start transforms: %d channels of %d bits\n"),
00297             png_get_channels(png_ptr, info_ptr),
00298             png_get_bit_depth(png_ptr, info_ptr));
00299         
00300         /* tell libpng to strip 16 bit/color files down to 8 bits/color */
00301         png_set_strip_16(png_ptr);
00302         
00303         /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
00304         /* JP - Changed so just 2 bit images are expanded */
00305         if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 2)
00306             png_set_expand(png_ptr);
00307         
00308         /* Expand paletted images to the full 8 bits from 2 bits/pixel */
00309         if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth == 2)
00310             png_set_expand(png_ptr);
00311         
00312         if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00313             png_set_gray_to_rgb(png_ptr);
00314 
00315             /* Note that screen gamma is the display_exponent, which includes
00316         * the CRT_exponent and any correction for viewing conditions */
00317         /* A good guess for a PC monitors in a dimly lit room is 2.2 */
00318         const double screen_gamma = 2.2;  
00319         
00320         png_set_invert_alpha(png_ptr);
00321         
00322         INT32 intent;
00323         
00324         if (png_get_sRGB(png_ptr, info_ptr, &intent))
00325             png_set_gamma(png_ptr, screen_gamma, 0.45455);
00326         else
00327         {
00328             double image_gamma;
00329             if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
00330                 png_set_gamma(png_ptr, screen_gamma, image_gamma);
00331             else
00332                 png_set_gamma(png_ptr, screen_gamma, 0.45455);
00333         }
00334         
00335         /* flip the RGB pixels to BGR (or RGBA to BGRA) */
00336         if (color_type & PNG_COLOR_MASK_COLOR)
00337             png_set_bgr(png_ptr);
00338 
00339         /* Scan the palletes */
00340         png_colorp pPalette;
00341         INT32 num_palette;
00342         if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
00343             png_get_PLTE(png_ptr, info_ptr, &pPalette, &num_palette);
00344         
00345 //      TRACEUSER( "Jonathan", _T("PNG read: Number of palette colours = %d\n"), num_palette);
00346         
00347         png_bytep pTrans;
00348         INT32 num_trans = 0; // if the 'if' statement is falue 0 is the correct value
00349         png_color_16p trans_values;
00350         if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00351             png_get_tRNS(png_ptr, info_ptr, &pTrans, &num_trans, &trans_values);
00352         
00353         TRACEUSER( "Jonathan", _T("PNG read: Number of transparent colours = %d\n"), num_trans);
00354         
00355         
00356         /* Take a look at the transparency list and see it there is only one
00357         colour which is not opaque and that that colour is fully transparent
00358         (so the exported bitmap can have one-bit transparency).  If this
00359         condition is not meet, convert the bitmap up to full alpha transparency
00360         (should really give a bitmap that has paletted RGBA but the interface
00361         to the PNG stuff appears to limit our options).
00362         
00363         Warning: If the PNG reading code is asked for 256 colour with a
00364         transparent colour, it must do this, otherwise the export dialog
00365         will go wrong when it re-imports the file for preview as it can not find
00366         a palette. */
00367         
00368         if (
00369             png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr) <= 8 
00370             && png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE
00371             )
00372         {
00373             if (num_trans > 0)
00374             {
00375                 // See if the palette has the format
00376                 //      Opaque (=256)
00377                 //      Opaque (=256)
00378                 //      Opaque (=256)
00379                 //      ....
00380                 //      Fully transparent (=0)
00381                 //  so we can use a one bit transparency paletted RGB image
00382                 INT32 i = 0;
00383                 png_byte * pCurrentTransEntry = pTrans;
00384                 
00385                 // Scan throught opaque entrys
00386                 while (i <= num_trans && pCurrentTransEntry[i] == 255)
00387                     i++;
00388                 
00389                 // This looks like a good bet for transparent colour
00390                 if (pCurrentTransEntry[i] == 0)
00391                     *TransColour = i;
00392                 
00393                 // Check any entrys after this to make sure they are not transparent
00394                 if (i < num_trans)
00395                     i++;
00396                 
00397                 while (i <= num_trans && pCurrentTransEntry[i] == 255)
00398                     i++;
00399                 
00400                 // Check we got to the end of the palette without finding any other
00401                 // transparent colours
00402                 if (i != num_trans)
00403                 {
00404                     // There are other transparent colours so convert to RGBA
00405                     *TransColour = -1;
00406                     
00407                     // Expand paletted or RGB images with transparency to full alpha channels
00408                     // so the data will be available as RGBA quartets.
00409                     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00410                         png_set_expand(png_ptr);
00411                     TRACEUSER( "Jonathan", _T("PNG read: Transparency: Converted to RGBA as there where multiple transparent colours\n"));
00412                 }
00413                 else
00414                 {
00415                     TRACEUSER( "Jonathan", _T("PNG read: Transparency: Only one transparent colour so keep the images as paletted\n"));
00416                 }
00417             }
00418             else
00419             {
00420                 TRACEUSER( "Jonathan", _T("PNG read: Transparency: No work needed as no transparency\n"));
00421             }
00422         }
00423         else
00424         {
00425             TRACEUSER( "Jonathan", _T("PNG read: Transparency: No work needed as no palette\n"));
00426         }
00427         
00428         TRACEUSER( "Jonathan", _T("PNG read: transparent colour = %d\n"), *TransColour);
00429 
00430         Transparent = *TransColour;
00431 
00432         /* Optional call to gamma correct and add the background to the palette
00433         * and update info structure.  REQUIRED if you are expecting libpng to
00434         * update the palette for you (ie you selected such a transform above). */
00435         png_read_update_info(png_ptr, info_ptr);
00436         
00437         /* Turn on interlace handling.  REQUIRED if you are not using
00438         * png_read_image().  To see how to handle interlacing passes,
00439         * see the png_read_row() method below: */
00440         //   INT32 number_passes = png_set_interlace_handling(png_ptr);
00441         
00442         
00443         TRACEUSER( "Jonathan", _T("PNG read: End transforms: %d channels of %d bits\n"),
00444             png_get_channels(png_ptr, info_ptr),
00445             png_get_bit_depth(png_ptr, info_ptr));
00446         
00447         /* Allocate the memory to hold the image using the fields of info_ptr. */
00448         INT32 bits_per_pixel = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr);
00449         if (bits_per_pixel == 1 || bits_per_pixel == 4 || bits_per_pixel == 8 ||  bits_per_pixel == 16 || bits_per_pixel == 24 || bits_per_pixel == 32)
00450             *Info = AllocDIB(width, height, png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr), Bits, NULL);
00451         else
00452             // This should never happen!
00453             File->GotError( _R(IDS_UNKNOWN_PNG_ERROR) );
00454         
00455         if (*Info == NULL || *Bits == NULL)
00456             File->GotError( _R(IDS_OUT_OF_MEMORY) );
00457         
00458         /* Set the bitmap DPI */
00459         png_uint_32 x_res, y_res;
00460         INT32 unit_type;
00461         png_get_pHYs(png_ptr, info_ptr, &x_res, &y_res, &unit_type);
00462         TRACEUSER( "Jonathan", _T("PNG read: X dpi: %d, Y dpi %d, DPI type %d\n"),
00463             x_res, y_res, unit_type);
00464 
00465         // If the unit type is in meters then use it
00466         if (unit_type == PNG_RESOLUTION_METER)
00467         {
00468             (*Info)->bmiHeader.biXPelsPerMeter = x_res;
00469             (*Info)->bmiHeader.biYPelsPerMeter = y_res;
00470         }
00471 
00472         // Check if we require a palette if we are on low bpp images.
00473         // If so then allocate one
00474         if (
00475             png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr) <= 8 
00476             && png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE
00477             )
00478         {
00479             // Palette is at info_ptr->palette
00480             INT32 PaletteSize = 1 << info_ptr->bit_depth;
00481             // Read in palette into the palette of the DIB
00482             LPRGBQUAD lpPalette = (*Info)->bmiColors;
00483             TRACEUSER( "Jonathan", _T("PNG read: allocate palette and copy size %d\n"),PaletteSize);
00484             
00485             // Get our function to read the palette from the PNG definition to the one we are
00486             // going to apply to the bitmap.
00487             if (
00488                 lpPalette == NULL ||
00489                 !ReadColourMap(num_palette, pPalette, PaletteSize, lpPalette)
00490                 )
00491             {
00492                 File->GotError( _R(IDS_PNG_ERR_READ_PALETTE) ); // Should be bad palette error
00493             }
00494         } 
00495         else if (png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr) <= 8 
00496             && png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY)
00497         {
00498             // We have a greyscale image and so generate a greyscale palette
00499             // Palette is at info_ptr->palette
00500             INT32 PaletteSize = 1 << info_ptr->bit_depth;
00501             TRACEUSER( "Jonathan", _T("PNG read: Greyscale, so set up a greyscale palette for the DIB size %d\n"),PaletteSize);
00502             // Read in palette into the palette of the DIB
00503             LPRGBQUAD lpPalette = (*Info)->bmiColors;
00504             // Get our function to read the palette from the PNG definition to the one we are
00505             // going to apply to the bitmap.
00506             if (lpPalette == NULL || !GenerateGreyPalette(PaletteSize, lpPalette))
00507                 File->GotError( _R(IDS_PNG_ERR_READ_PALETTE) ); // Should be bad palette error
00508         }
00509         
00510         /* and allocate memory for an array of row-pointers */
00511         if ((ppbRowPointers = (png_bytepp) png_malloc(png_ptr, (height) * sizeof(png_bytep))) == NULL)
00512             File->GotError(_R(IDS_OUT_OF_MEMORY));
00513         
00514         /* set the individual row-pointers to point at the correct offsets */
00515         UINT32 ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
00516         
00517         /* make the row finish on a word boundry */
00518         if (ulRowBytes % 4 != 0)
00519             ulRowBytes += 4 - (ulRowBytes % 4);
00520         
00521         for (UINT32 i = 0; i < height; i++)
00522             ppbRowPointers[height - 1 - i] = *Bits + i * ulRowBytes;
00523         
00524         bool interlace;
00525         switch (png_get_interlace_type(png_ptr, info_ptr))
00526         {
00527         case PNG_INTERLACE_NONE:
00528             interlace = false;
00529             break;
00530 
00531         case PNG_INTERLACE_ADAM7:
00532             interlace = true;
00533             break;
00534 
00535         default:
00536             File->GotError(_R(IDS_PNG_ERROR_BAD_INTERLACE));
00537             break;
00538         }
00539 
00540         /* Set up the progress bar */
00541 PORTNOTE("other","PNGUtil::ReadFromFile - removed progressbar")
00542 #ifndef EXCLUDE_FROM_XARALX
00543         PNGProgressBar ProgressBar(ProgressString, interlace, height);
00544         png_progress_bar_read = &ProgressBar;
00545 #endif
00546         png_set_read_status_fn(png_ptr, camelot_png_read_row_callback);
00547 
00548         /* now we can go ahead and just read the whole image */
00549         png_read_image(png_ptr, ppbRowPointers);
00550         
00551 #ifndef EXCLUDE_FROM_XARALX
00552         png_progress_bar_read = 0;
00553 #endif
00554 
00555         png_free(png_ptr, ppbRowPointers);
00556 
00557         /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
00558         png_read_end(png_ptr, info_ptr);
00559         
00560         /* At this point the entire image has been read */
00561         
00562         /* clean up after the read, and free any memory allocated - REQUIRED */
00563         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00564 
00565         png_ptr = NULL;
00566 
00567         /* Must set the exception throwing and reporting flags back to their entry states */
00568         File->SetThrowExceptions( OldThrowingState );
00569         File->SetReportErrors( OldReportingState );
00570         
00571         /* Reset the file pointer back to null for safety */
00572         pFile = NULL;
00573         
00574         TRACEUSER( "Jonathan", _T("PNG read: Finshed\n"));
00575         
00576         /* that's it */
00577         return (OK);
00578    }
00579    catch( CFileException )
00580    {
00581        // catch our form of a file exception
00582        TRACE( _T("PNGUtil::ReadFromFile CC catch handler\n"));
00583        
00584 //GAT   png_progress_bar_read = 0;
00585 
00586         if (ppbRowPointers != 0)
00587             png_free(png_ptr, ppbRowPointers);
00588 
00589         /* clean up after the read, and free any memory allocated */
00590         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00591 
00592         png_ptr = NULL;
00593  
00594        // Now our Camelot related bits
00595        if (*Info != NULL && *Bits != NULL)
00596            FreeDIB( *Info, *Bits );                         // free any alloced memory
00597        *Info = NULL;                                        // and NULL the pointers
00598        *Bits = NULL;
00599        
00600        // Free up the bit of memory for a palette we grabbed, if present
00601        //if (lpGlobalPalette)
00602        //{
00603        //   CCFree(lpGlobalPalette);
00604        //       lpGlobalPalette = NULL;
00605        //}
00606        
00607        // Must set the exception throwing and reporting flags back to their entry states
00608        File->SetThrowExceptions( OldThrowingState );
00609        File->SetReportErrors( OldReportingState );
00610        
00611        // Reset the file pointer back to null for safety
00612        pFile = NULL;
00613        
00614        return FALSE;
00615    }
00616        
00617    ERROR2( FALSE, "Escaped exception clause somehow" );
00618 }
00619 
00620 
00621 /********************************************************************************************
00622 
00623 >   static PNGUtil::SetCCFilePointer(CCLexFile* pNewFile)
00624 
00625     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00626     Created:    14/05/96
00627     Inputs:     the new CCLexFile pointer to used for exception handling
00628     Outputs:    -
00629     Returns:    -
00630     Purpose:    Public access to the pFile exception handling pointer
00631     SeeAlso:    DefaultErrorHandler
00632 
00633 ********************************************************************************************/
00634 
00635 BOOL PNGUtil::SetCCFilePointer(CCLexFile* pNewFile)
00636 {
00637     pFile = pNewFile;
00638     return TRUE;
00639 }
00640 
00641 /********************************************************************************************
00642 
00643 >   static CCLexFile* PNGUtil::GetCCFilePointer()
00644 
00645     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00646     Created:    14/05/96
00647     Inputs:     -
00648     Outputs:    -
00649     Returns:    the CCLexFile pointer used for exception handling
00650     Purpose:    Public access to the pFile exception handling pointer
00651     SeeAlso:    DefaultErrorHandler
00652 
00653 ********************************************************************************************/
00654 
00655 CCLexFile* PNGUtil::GetCCFilePointer()
00656 {
00657     return pFile;
00658 }
00659 
00660 /********************************************************************************************
00661 
00662 >   static void PNGUtil::DefaultErrorHandler(UINT32 MessageID, TCHAR * pMessage = NULL)
00663 
00664     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00665     Created:    13/05/96
00666     Inputs:     The id of the message
00667                 An optional error string 
00668     Outputs:    -
00669     Returns:    -
00670     Purpose:    To handle errors within the PNG code in a nice fashion.
00671                 Assumes a TRY CATCH block is present and a valid CCLexFile is specified as it
00672                 uses the CCLexFile::GotError to throw an exception.
00673                 This should become redundant as we replace the PNG error handling with IDs
00674     SeeAlso:    CCFile::GotError
00675 
00676 ********************************************************************************************/
00677 
00678 //void PNGUtil::DefaultErrorHandler(UINT32 MessageID, TCHAR * pMessage)
00679 void PNGUtil::DefaultErrorHandler()
00680 {
00681     // Use the CCLexFile GotError function to do the error handling for us 
00682     // Assumes TRY CATCH block in use
00683     if (pFile)
00684     {
00685 //      if (pMessage)
00686 //          pFile->GotError(MessageID, pMessage);
00687 //      else
00688 //          pFile->GotError(MessageID);
00689             pFile->GotError(_R(IDS_UNKNOWN_PNG_ERROR));
00690     }
00691 
00692     // This is the fall back position of oh my god we must stop execution as otherwise things
00693     // will go pear shaped.
00694 //  ERROR2RAW(MessageID);
00695     ERROR2RAW(1);
00696 
00697     // Use the C++ exception handling
00698     //AfxThrowFileException(CFileException::generic, _R(IDS_UNKNOWN_PNG_ERROR));
00699 }
00700 
00701 
00702 /********************************************************************************************
00703 
00704 >   static BOOL PNGUtil::ReadColourMap(INT32 Png_Entries, png_colorp pPNGPalette, INT32 number, LPRGBQUAD lpPalette)
00705 
00706     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00707     Created:    13/05/96
00708     Inputs:     pPNGPalette     pointer to the palette defined in the PNG data structures
00709     Outputs:    -
00710     Returns:    True if worked ok, False otherwise.
00711     Purpose:    Copy the palette entries across from the PNG palette to the bitmap palette
00712                 in Camelot.
00713     SeeAlso:    
00714 
00715 ********************************************************************************************/
00716 
00717 BOOL PNGUtil::ReadColourMap(INT32 Png_Entries, png_colorp pPNGPalette, INT32 number, LPRGBQUAD lpPalette)
00718 {
00719     ERROR2IF(pPNGPalette == NULL,FALSE,"PNGUtil::ReadColourMap no PNG palette present");
00720     ERROR2IF(lpPalette == NULL,FALSE,"PNGUtil::ReadColourMap no lpPalette present");
00721     ERROR2IF(Png_Entries <= 0,FALSE,"PNGUtil::ReadColourMap no PNG palette entries present");
00722 
00723     for (INT32 i = 0; i < Png_Entries; i++)
00724     {
00725         lpPalette->rgbBlue = pPNGPalette->blue;
00726         lpPalette->rgbGreen = pPNGPalette->green;
00727         lpPalette->rgbRed = pPNGPalette->red;
00728         lpPalette->rgbReserved = 0;
00729         lpPalette++;
00730         pPNGPalette++;
00731     }
00732     
00733     return TRUE;
00734 }
00735 
00736 /********************************************************************************************
00737 
00738 >   static BOOL PNGUtil::GenerateGreyPalette(INT32 PaletteSize, LPRGBQUAD lpPalette)
00739 
00740     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00741     Created:    13/05/96
00742     Inputs:     PaletteSize     number of palette entries that need generating
00743                 lpPalette       pointer to the palette defined in the DIB
00744                 
00745     Outputs:    -
00746     Returns:    True if worked ok, False otherwise.
00747     Purpose:    Generate a greyscale palette for a greyscale DIB.
00748     SeeAlso:    
00749 
00750 ********************************************************************************************/
00751 
00752 BOOL PNGUtil::GenerateGreyPalette(INT32 PaletteSize, LPRGBQUAD lpPalette)
00753 {
00754     ERROR2IF(lpPalette == NULL,FALSE,"PNGUtil::GenerateGreyPalette no lpPalette present");
00755     ERROR2IF(PaletteSize <= 0,FALSE,"PNGUtil::GenerateGreyPalette no PNG palette entries present");
00756 
00757     // Work out the value we require per step so on a:-
00758     //  256 colour palette we can have 256 steps of 1
00759     //  16 colour palette we have 16 steps of 16 (16 * 16 = 256)
00760     INT32 inc = 255 / (PaletteSize - 1); // Changed so palette has the right range - Jonathan
00761     INT32 value = 0;
00762     for (INT32 i = 0; i < PaletteSize; i++ )
00763     {
00764         lpPalette->rgbBlue = value;
00765         lpPalette->rgbGreen = value;
00766         lpPalette->rgbRed = value;
00767         lpPalette->rgbReserved = 0;
00768         lpPalette++;
00769         value += inc;
00770         if (value > 255)
00771             value = 255;
00772     }
00773     
00774     return TRUE;
00775 }

Generated on Sat Nov 10 03:48:47 2007 for Camelot by  doxygen 1.4.4