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 }