00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <string.h>
00044
00045 #include "OSGConfig.h"
00046
00047 #ifdef OSG_SGI_LIB
00048 #include <limits>
00049 #endif
00050 #ifdef OSG_WITH_PNG
00051 #include <png.h>
00052 #endif
00053
00054 #include "OSGPNGImageFileType.h"
00055 #include <OSGLog.h>
00056
00057 #include <iostream>
00058
00059 #ifndef OSG_DO_DOC
00060 # ifdef OSG_WITH_PNG
00061 # define OSG_PNG_ARG(ARG) ARG
00062 # else
00063 # define OSG_PNG_ARG(ARG)
00064 # endif
00065 #else
00066 # define OSG_PNG_ARG(ARG) ARG
00067 #endif
00068
00069 OSG_USING_NAMESPACE
00070
00086
00087
00088
00089
00090
00091
00092
00093 static const Char8 *suffixArray[] = {
00094 "png"
00095 };
00096
00097
00098
00099
00100
00101 #ifdef OSG_WITH_PNG
00102
00103 static void isReadFunc(png_structp png_ptr, png_bytep data, png_size_t length)
00104 {
00105 std::istream *is = reinterpret_cast<std::istream*>(png_get_io_ptr(png_ptr));
00106 is->read(reinterpret_cast<char*>(data), length);
00107 if (is->gcount() != length)
00108 png_error(png_ptr, "Cannot read from input stream");
00109 }
00110
00111 static void osWriteFunc(png_structp png_ptr, png_bytep data, png_size_t length)
00112 {
00113 std::ostream *os = reinterpret_cast<std::ostream*>(png_get_io_ptr(png_ptr));
00114 os->write(reinterpret_cast<char*>(data), length);
00115 if (os->good() == false)
00116 png_error(png_ptr, "Cannot write to output stream");
00117 }
00118
00119 static void osFlushFunc(png_structp png_ptr)
00120 {
00121 std::ostream *os = reinterpret_cast<std::ostream*>(png_get_io_ptr(png_ptr));
00122 os->flush();
00123 if (os->good() == false)
00124 png_error(png_ptr, "Cannot flush output stream");
00125 }
00126
00127 static void errorOutput (png_structp png_ptr, const char *message)
00128 {
00129 FFATAL (("PNG: %s\n", message ));
00130
00131 longjmp(png_ptr->jmpbuf, 1);
00132 }
00133
00134 static void warningOutput (png_structp OSG_CHECK_ARG(png_ptr),
00135 const char *message)
00136 {
00137 FWARNING (("PNG: %s\n", message ));
00138 }
00139
00140 #endif
00141
00142 PNGImageFileType PNGImageFileType:: _the("image/png",
00143 suffixArray, sizeof(suffixArray),
00144 OSG_READ_SUPPORTED |
00145 OSG_WRITE_SUPPORTED);
00146
00147
00148
00149
00150
00151 PNGImageFileType& PNGImageFileType::the (void)
00152 {
00153 return _the;
00154 }
00155
00156
00157
00158
00159
00160
00165 bool PNGImageFileType::read(ImagePtr &OSG_PNG_ARG(image), std::istream &OSG_PNG_ARG(is),
00166 const std::string &OSG_PNG_ARG(mimetype))
00167 {
00168 #ifdef OSG_WITH_PNG
00169
00170 bool retCode;
00171 Image::PixelFormat pixelFormat = osg::Image::OSG_INVALID_PF;
00172 png_structp png_ptr;
00173 png_infop info_ptr;
00174 png_uint_32 width, wc, height, h, i, res_x, res_y;
00175 png_byte bit_depth, channels, color_type;
00176 png_bytep *row_pointers, base;
00177
00178 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00179 if(!png_ptr)
00180 return false;
00181
00182 png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput);
00183
00184 info_ptr = png_create_info_struct(png_ptr);
00185 if(!info_ptr)
00186 {
00187 png_destroy_read_struct(&png_ptr, 0, 0);
00188 return false;
00189 }
00190
00191 if(setjmp(png_ptr->jmpbuf))
00192 {
00193 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00194 return false;
00195 }
00196
00197 png_set_read_fn(png_ptr, &is, &isReadFunc);
00198
00199 png_read_info(png_ptr, info_ptr);
00200
00201 width = png_get_image_width(png_ptr, info_ptr);
00202 height = png_get_image_height(png_ptr, info_ptr);
00203 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00204 res_x = png_get_x_pixels_per_meter(png_ptr, info_ptr);
00205 res_y = png_get_y_pixels_per_meter(png_ptr, info_ptr);
00206 channels = png_get_channels(png_ptr, info_ptr);
00207 color_type = png_get_color_type(png_ptr, info_ptr);
00208
00209
00210 if (color_type == PNG_COLOR_TYPE_PALETTE)
00211 {
00212 png_set_palette_to_rgb(png_ptr);
00213 channels = 3;
00214 bit_depth = 8;
00215 }
00216
00217
00218 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
00219 png_set_gray_1_2_4_to_8(png_ptr);
00220 bit_depth = 8;
00221 }
00222
00223 #if BYTE_ORDER == LITTLE_ENDIAN
00224 if (bit_depth == 16)
00225 png_set_swap(png_ptr);
00226 #endif
00227
00228
00229
00230 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00231 {
00232 png_set_tRNS_to_alpha(png_ptr);
00233 ++channels;
00234 }
00235 Int32 dataType;
00236 switch (bit_depth) {
00237 case 8:
00238 dataType = Image::OSG_UINT8_IMAGEDATA;
00239 break;
00240 case 16:
00241 dataType = Image::OSG_UINT16_IMAGEDATA;
00242 break;
00243 default:
00244 FWARNING (( "Invalid bit_depth: %d, can not read png-data\n",
00245 bit_depth ));
00246 return false;
00247 }
00248
00249 switch(channels)
00250 {
00251 case 1:
00252 pixelFormat = Image::OSG_L_PF;
00253 break;
00254 case 2:
00255 pixelFormat = Image::OSG_LA_PF;
00256 break;
00257 case 3:
00258 pixelFormat = Image::OSG_RGB_PF;
00259 break;
00260 case 4:
00261 pixelFormat = Image::OSG_RGBA_PF;
00262 break;
00263 };
00264
00265 if(image->set( pixelFormat, width, height,
00266 1, 1, 1, 0.0, 0,
00267 dataType ))
00268 {
00269
00270
00271 res_x = png_uint_32((Real32(res_x) / 39.37007874f) < 0.0f ?
00272 (Real32(res_x) / 39.37007874f) - 0.5f :
00273 (Real32(res_x) / 39.37007874f) + 0.5f);
00274 res_y = png_uint_32((Real32(res_y) / 39.37007874f) < 0.0f ?
00275 (Real32(res_y) / 39.37007874f) - 0.5f :
00276 (Real32(res_y) / 39.37007874f) + 0.5f);
00277
00278 image->setResX(Real32(res_x));
00279 image->setResY(Real32(res_y));
00280 image->setResUnit(Image::OSG_RESUNIT_INCH);
00281
00282
00283 row_pointers = new png_bytep[height];
00284 wc = width * channels * (bit_depth / 8);
00285 h = height - 1;
00286 base = image->getData();
00287 for(i = 0; i < height; ++i)
00288 row_pointers[i] = base + (h - i) * wc;
00289
00290
00291 png_read_image(png_ptr, row_pointers);
00292
00293 delete[] row_pointers;
00294
00295 retCode = true;
00296 }
00297 else
00298 retCode = false;
00299
00300 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00301
00302 return retCode;
00303
00304 #else
00305
00306 SWARNING <<
00307 getMimeType() <<
00308 " read is not compiled into the current binary " <<
00309 std::endl;
00310 return false;
00311
00312 #endif
00313
00314 }
00315
00316
00322 bool PNGImageFileType::write(const ImagePtr &OSG_PNG_ARG(img), std::ostream &OSG_PNG_ARG(os),
00323 const std::string &OSG_PNG_ARG(mimetype))
00324 {
00325 #ifdef OSG_WITH_PNG
00326
00327 png_structp png_ptr;
00328 png_infop info_ptr;
00329
00330 if(img->getDimension() < 1 || img->getDimension() > 2)
00331 {
00332 FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
00333 img->getDimension()));
00334 return false;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00344 0, &errorOutput, &warningOutput);
00345
00346 if (png_ptr == NULL)
00347 return false;
00348
00349
00350 info_ptr = png_create_info_struct(png_ptr);
00351 if (info_ptr == NULL)
00352 {
00353 png_destroy_write_struct(&png_ptr, NULL);
00354 return false;
00355 }
00356
00357
00358 png_set_write_fn(png_ptr, &os, &osWriteFunc, &osFlushFunc);
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 Int32 ctype;
00371 switch(img->getPixelFormat())
00372 {
00373 case Image::OSG_L_PF: ctype = PNG_COLOR_TYPE_GRAY;
00374 break;
00375
00376 case Image::OSG_LA_PF: ctype = PNG_COLOR_TYPE_GRAY_ALPHA;
00377 break;
00378
00379 #if defined(GL_BGR) || defined(GL_BGR_EXT)
00380 case Image::OSG_BGR_PF:
00381 #endif
00382 case Image::OSG_RGB_PF: ctype = PNG_COLOR_TYPE_RGB;
00383 break;
00384
00385 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
00386 case Image::OSG_BGRA_PF:
00387 #endif
00388 case Image::OSG_RGBA_PF: ctype = PNG_COLOR_TYPE_RGB_ALPHA;
00389 break;
00390
00391 default:
00392 FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
00393 img->getPixelFormat()));
00394 png_destroy_write_struct(&png_ptr, NULL);
00395 return false;
00396
00397 }
00398
00399 Int32 bit_depth;
00400 switch (img->getDataType()) {
00401 case Image::OSG_UINT8_IMAGEDATA:
00402 bit_depth = 8;
00403 break;
00404 case Image::OSG_UINT16_IMAGEDATA:
00405 bit_depth = 16;
00406 break;
00407 default:
00408 FWARNING (("Invalid pixeldepth, cannot store data\n"));
00409 return false;
00410 };
00411
00412 png_set_IHDR(png_ptr, info_ptr, img->getWidth(), img->getHeight(),
00413 bit_depth, ctype,
00414 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00415
00416
00417
00418 png_uint_32 res_x = img->getResX();
00419 png_uint_32 res_y = img->getResY();
00420 if(img->getResUnit() == Image::OSG_RESUNIT_INCH)
00421 {
00422 res_x = png_uint_32((img->getResX() * 39.37007874f) < 0.0f ?
00423 (img->getResX() * 39.37007874f) - 0.5f :
00424 (img->getResX() * 39.37007874f) + 0.5f);
00425 res_y = png_uint_32((img->getResY() * 39.37007874f) < 0.0f ?
00426 (img->getResY() * 39.37007874f) - 0.5f :
00427 (img->getResY() * 39.37007874f) + 0.5f);
00428 }
00429
00430 png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
00431 PNG_RESOLUTION_METER);
00432
00433 #if 0
00434
00435
00436 sig_bit.gray = true_bit_depth;
00437
00438 sig_bit.red = true_red_bit_depth;
00439 sig_bit.green = true_green_bit_depth;
00440 sig_bit.blue = true_blue_bit_depth;
00441
00442 sig_bit.alpha = true_alpha_bit_depth;
00443 png_set_sBIT(png_ptr, info_ptr, sig_bit);
00444
00445
00446
00447
00448
00449 png_set_gAMA(png_ptr, info_ptr, gamma);
00450
00451
00452 text_ptr[0].key = "Title";
00453 text_ptr[0].text = "Mona Lisa";
00454 text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00455 text_ptr[1].key = "Author";
00456 text_ptr[1].text = "Leonardo DaVinci";
00457 text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
00458 text_ptr[2].key = "Description";
00459 text_ptr[2].text = "<long text>";
00460 text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
00461 #ifdef PNG_iTXt_SUPPORTED
00462 text_ptr[0].lang = NULL;
00463 text_ptr[1].lang = NULL;
00464 text_ptr[2].lang = NULL;
00465 #endif
00466 png_set_text(png_ptr, info_ptr, text_ptr, 3);
00467 #endif
00468
00469
00470
00471
00472
00473 png_write_info(png_ptr, info_ptr);
00474
00475 #if BYTE_ORDER == LITTLE_ENDIAN
00476
00477 if (bit_depth == 16)
00478 png_set_swap(png_ptr);
00479
00480 #endif
00481
00482
00483 #if 0
00484
00485 png_set_invert_mono(png_ptr);
00486
00487
00488
00489
00490 png_set_shift(png_ptr, &sig_bit);
00491
00492
00493 png_set_packing(png_ptr);
00494
00495
00496
00497
00498 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
00499
00500
00501 png_set_swap(png_ptr);
00502
00503
00504 png_set_packswap(png_ptr);
00505 #endif
00506
00507 if(img->getPixelFormat() == Image::OSG_BGR_PF ||
00508 img->getPixelFormat() == Image::OSG_BGRA_PF
00509 )
00510 {
00511
00512 png_set_bgr(png_ptr);
00513
00514
00515 png_set_swap_alpha(png_ptr);
00516 }
00517
00518
00519
00520
00521
00522 png_bytep *row_pointers = new png_bytep [img->getHeight()];
00523
00524 for(Int32 k = 0; k < img->getHeight(); k++)
00525 {
00526 row_pointers[k] = img->getData() +
00527 (img->getHeight() - 1 - k) *
00528 img->getWidth() * img->getBpp();
00529 }
00530
00531
00532 png_write_image(png_ptr, row_pointers);
00533
00534
00535 png_write_end(png_ptr, info_ptr);
00536
00537
00538 png_destroy_write_struct(&png_ptr, &info_ptr);
00539
00540 delete [] row_pointers;
00541
00542
00543 return true;
00544
00545 #else
00546 SWARNING <<
00547 getMimeType() <<
00548 " write is not compiled into the current binary " <<
00549 endLog;
00550 return false;
00551 #endif
00552 }
00553
00554
00560 std::string PNGImageFileType::determineMimetypeFromStream(std::istream &is)
00561 {
00562 char filecode[4];
00563 is.read(filecode, 4);
00564 is.seekg(-4, std::ios::cur);
00565 return strncmp(filecode, "\x89PNG", 4) == 0 ?
00566 std::string(getMimeType()) : std::string();
00567 }
00568
00569
00570
00571 bool PNGImageFileType::validateHeader( const Char8 *fileName, bool &implemented)
00572 {
00573 implemented = true;
00574
00575 if(fileName == NULL)
00576 return false;
00577
00578 FILE *file = fopen(fileName, "rb");
00579 if(file == NULL)
00580 return false;
00581
00582 std::string magic;
00583 magic.resize(4);
00584 fread((void *) &magic[0], 4, 1, file);
00585 fclose(file);
00586
00587 if(magic == "\x89PNG")
00588 {
00589 return true;
00590 }
00591
00592 return false;
00593 }
00594
00595 #ifdef OSG_WITH_PNG
00596 typedef struct
00597 {
00598 UChar8 *buffer;
00599 UInt64 length;
00600 } BufferInfo;
00601
00602 static void user_read_data(png_structp png_ptr,
00603 png_bytep data, png_size_t length)
00604 {
00605 BufferInfo *bufferInfo = (BufferInfo *) png_get_io_ptr(png_ptr);
00606 memcpy((void *) data, (void *) bufferInfo->buffer, length);
00607 bufferInfo->buffer += length;
00608 bufferInfo->length += length;
00609 }
00610 #endif
00611
00612
00613
00614 UInt64 PNGImageFileType::restoreData( ImagePtr &OSG_PNG_ARG(image ),
00615 const UChar8 *OSG_PNG_ARG(buffer ),
00616 Int32 OSG_CHECK_ARG(memSize))
00617 {
00618 #ifdef OSG_WITH_PNG
00619
00620 UInt64 retCode;
00621 Image::PixelFormat pixelFormat = osg::Image::OSG_INVALID_PF;
00622 png_structp png_ptr;
00623 png_infop info_ptr;
00624 png_uint_32 width, wc, height, h, i;
00625 png_byte bit_depth, channels, color_type;
00626 png_bytep *row_pointers, base;
00627
00628 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00629 if(!png_ptr)
00630 {
00631 return 0;
00632 }
00633
00634 png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput);
00635
00636 info_ptr = png_create_info_struct(png_ptr);
00637 if(!info_ptr)
00638 {
00639 png_destroy_read_struct(&png_ptr, 0, 0);
00640 return 0;
00641 }
00642
00643 if(setjmp(png_ptr->jmpbuf))
00644 {
00645 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00646 return 0;
00647 }
00648
00649 BufferInfo bufferInfo;
00650 bufferInfo.buffer = (UChar8 *) buffer;
00651 bufferInfo.length = 0;
00652 png_set_read_fn(png_ptr, (void *) &bufferInfo, user_read_data);
00653
00654 png_read_info(png_ptr, info_ptr);
00655
00656 width = png_get_image_width(png_ptr, info_ptr);
00657 height = png_get_image_height(png_ptr, info_ptr);
00658 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00659 channels = png_get_channels(png_ptr, info_ptr);
00660 color_type = png_get_color_type(png_ptr, info_ptr);
00661
00662
00663 if (color_type == PNG_COLOR_TYPE_PALETTE)
00664 {
00665 png_set_palette_to_rgb(png_ptr);
00666 channels = 3;
00667 bit_depth = 8;
00668 }
00669
00670
00671 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
00672 png_set_gray_1_2_4_to_8(png_ptr);
00673 bit_depth = 8;
00674 }
00675
00676 #if BYTE_ORDER == LITTLE_ENDIAN
00677 if (bit_depth == 16)
00678 png_set_swap(png_ptr);
00679 #endif
00680
00681
00682
00683 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00684 {
00685 png_set_tRNS_to_alpha(png_ptr);
00686 ++channels;
00687 }
00688 Int32 dataType;
00689 switch (bit_depth) {
00690 case 8:
00691 dataType = Image::OSG_UINT8_IMAGEDATA;
00692 break;
00693 case 16:
00694 dataType = Image::OSG_UINT16_IMAGEDATA;
00695 break;
00696 default:
00697 FWARNING (( "Invalid bit_depth: %d, can not read png-data\n",
00698 bit_depth ));
00699 return false;
00700 }
00701
00702 switch(channels)
00703 {
00704 case 1:
00705 pixelFormat = Image::OSG_L_PF;
00706 break;
00707 case 2:
00708 pixelFormat = Image::OSG_LA_PF;
00709 break;
00710 case 3:
00711 pixelFormat = Image::OSG_RGB_PF;
00712 break;
00713 case 4:
00714 pixelFormat = Image::OSG_RGBA_PF;
00715 break;
00716 };
00717
00718 if(image->set( pixelFormat, width, height,
00719 1, 1, 1, 0.0, 0,
00720 dataType ))
00721 {
00722
00723 row_pointers = new png_bytep[height];
00724 wc = width * channels * (bit_depth / 8);
00725 h = height - 1;
00726 base = image->getData();
00727 for(i = 0; i < height; ++i)
00728 row_pointers[i] = base + (h - i) * wc;
00729
00730
00731 png_read_image(png_ptr, row_pointers);
00732
00733 delete[] row_pointers;
00734
00735 retCode = bufferInfo.length;
00736 }
00737 else
00738 retCode = 0;
00739
00740 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00741
00742 return retCode;
00743
00744 #else
00745 SWARNING <<
00746 getMimeType() <<
00747 " restoreData is not compiled into the current binary " <<
00748 std::endl;
00749 return 0;
00750 #endif
00751 }
00752
00753 #ifdef OSG_WITH_PNG
00754
00755 static void user_write_data(png_structp png_ptr,
00756 png_bytep data, png_size_t length)
00757 {
00758 BufferInfo *bufferInfo = (BufferInfo *) png_get_io_ptr(png_ptr);
00759 memcpy((void *) bufferInfo->buffer, (void *) data, length);
00760 bufferInfo->buffer += length;
00761 bufferInfo->length += length;
00762 }
00763
00764 static void user_flush_data(png_structp OSG_CHECK_ARG(png_ptr))
00765 {
00766 }
00767
00768 #endif
00769
00770
00775 UInt64 PNGImageFileType::storeData(const ImagePtr &OSG_PNG_ARG(image ),
00776 UChar8 *OSG_PNG_ARG(buffer ),
00777 Int32 OSG_CHECK_ARG(memSize))
00778 {
00779 #ifdef OSG_WITH_PNG
00780
00781 png_structp png_ptr;
00782 png_infop info_ptr;
00783
00784 if(image->getDimension() < 1 || image->getDimension() > 2)
00785 {
00786 FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
00787 image->getDimension()));
00788 return 0;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00798 0, &errorOutput, &warningOutput);
00799
00800 if (png_ptr == NULL)
00801 {
00802 return 0;
00803 }
00804
00805
00806 info_ptr = png_create_info_struct(png_ptr);
00807 if (info_ptr == NULL)
00808 {
00809 png_destroy_write_struct(&png_ptr, NULL);
00810 return 0;
00811 }
00812
00813 BufferInfo bufferInfo;
00814 bufferInfo.buffer = buffer;
00815 bufferInfo.length = 0;
00816 png_set_write_fn(png_ptr, (void *) &bufferInfo, user_write_data, user_flush_data);
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 Int32 ctype;
00829 switch(image->getPixelFormat())
00830 {
00831 case Image::OSG_L_PF: ctype = PNG_COLOR_TYPE_GRAY;
00832 break;
00833
00834 case Image::OSG_LA_PF: ctype = PNG_COLOR_TYPE_GRAY_ALPHA;
00835 break;
00836
00837 #if defined(GL_BGR) || defined(GL_BGR_EXT)
00838 case Image::OSG_BGR_PF:
00839 #endif
00840 case Image::OSG_RGB_PF: ctype = PNG_COLOR_TYPE_RGB;
00841 break;
00842
00843 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
00844 case Image::OSG_BGRA_PF:
00845 #endif
00846 case Image::OSG_RGBA_PF: ctype = PNG_COLOR_TYPE_RGB_ALPHA;
00847 break;
00848
00849 default:
00850 FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
00851 image->getPixelFormat()));
00852 png_destroy_write_struct(&png_ptr, NULL);
00853 return 0;
00854
00855 }
00856
00857 Int32 bit_depth;
00858 switch (image->getDataType()) {
00859 case Image::OSG_UINT8_IMAGEDATA:
00860 bit_depth = 8;
00861 break;
00862 case Image::OSG_UINT16_IMAGEDATA:
00863 bit_depth = 16;
00864 break;
00865 default:
00866 FWARNING (("Invalid pixeldepth, cannot store data\n"));
00867 return 0;
00868 };
00869
00870 png_set_IHDR(png_ptr, info_ptr, image->getWidth(), image->getHeight(),
00871 bit_depth, ctype,
00872 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00873
00874
00875
00876
00877
00878
00879 png_write_info(png_ptr, info_ptr);
00880
00881 #if BYTE_ORDER == LITTLE_ENDIAN
00882 if (bit_depth == 16)
00883 png_set_swap(png_ptr);
00884 #endif
00885
00886 if(image->getPixelFormat() == Image::OSG_BGR_PF ||
00887 image->getPixelFormat() == Image::OSG_BGRA_PF
00888 )
00889 {
00890
00891 png_set_bgr(png_ptr);
00892
00893
00894 png_set_swap_alpha(png_ptr);
00895 }
00896
00897
00898
00899
00900
00901 png_bytep *row_pointers = new png_bytep [image->getHeight()];
00902
00903 for(Int32 k = 0; k < image->getHeight(); k++)
00904 {
00905 row_pointers[k] = image->getData() +
00906 (image->getHeight() - 1 - k) *
00907 image->getWidth() * image->getBpp();
00908 }
00909
00910
00911 png_write_image(png_ptr, row_pointers);
00912
00913
00914 png_write_end(png_ptr, info_ptr);
00915
00916
00917 png_destroy_write_struct(&png_ptr, &info_ptr);
00918
00919 delete [] row_pointers;
00920
00921
00922 return bufferInfo.length;
00923
00924 #else
00925 SWARNING <<
00926 getMimeType() <<
00927 " storeData is not compiled into the current binary " <<
00928 std::endl;
00929 return 0;
00930 #endif
00931 }
00932
00933
00937 PNGImageFileType::PNGImageFileType ( const Char8 *mimeType,
00938 const Char8 *suffixArray[],
00939 UInt16 suffixByteCount,
00940 UInt32 flags) :
00941 ImageFileType(mimeType, suffixArray, suffixByteCount, flags)
00942 {}
00943
00944
00948 PNGImageFileType::~PNGImageFileType(void) {}