PNG.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. #if SUPPORT_PNG
  4. #include "../../../../ThirdPartyLibs/begin.h"
  5. #define PNG_NO_STDIO
  6. #include "../../../../ThirdPartyLibs/Png/src/png.h"
  7. #include "../../../../ThirdPartyLibs/end.h"
  8. #endif
  9. namespace EE{
  10. /******************************************************************************/
  11. #if SUPPORT_PNG
  12. static void PngReadData (png_structp png_ptr, png_bytep data, png_size_t size) {if(!((File*)png_get_io_ptr(png_ptr))->get(data, (Int)size))png_error(png_ptr, "Read Error" );}
  13. static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t size) {if(!((File*)png_get_io_ptr(png_ptr))->put(data, (Int)size))png_error(png_ptr, "Write Error");}
  14. #endif
  15. Bool Image::ImportPNG(File &f)
  16. {
  17. #if SUPPORT_PNG
  18. Bool ok=false, created=false;
  19. png_uint_32 width=0,
  20. height=0,
  21. channels=0;
  22. int color_type=0,
  23. bit_depth=0;
  24. png_structp png_ptr=null;
  25. png_infop info_ptr=null;
  26. Memt<png_byte*> row_ptrs;
  27. png_byte signature[8]; f>>signature; if(png_sig_cmp(signature, 0, 8))goto error;
  28. png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, null, null, null); if(! png_ptr)goto error; if(setjmp(png_jmpbuf(png_ptr)))goto error;
  29. info_ptr=png_create_info_struct(png_ptr ); if(!info_ptr)goto error;
  30. {
  31. // initialize the png structure
  32. png_set_read_fn (png_ptr, (png_voidp)&f, PngReadData);
  33. png_set_sig_bytes(png_ptr, 8);
  34. png_read_info (png_ptr, info_ptr);
  35. png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, null, null, null);
  36. if(color_type!=PNG_COLOR_TYPE_GRAY && bit_depth==16)png_set_strip_16(png_ptr);
  37. if(color_type==PNG_COLOR_TYPE_GRAY && bit_depth==16)png_set_swap (png_ptr);
  38. if(color_type==PNG_COLOR_TYPE_PALETTE || bit_depth < 8)png_set_expand (png_ptr);
  39. if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) )png_set_expand (png_ptr);
  40. Dbl gamma; if(png_get_gAMA (png_ptr, info_ptr, &gamma))png_set_gamma(png_ptr, 2.2, gamma); // if required set gamma conversion
  41. png_read_update_info(png_ptr, info_ptr); // after the transformations have been registered update info_ptr data
  42. png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, null, null, null); // get again width, height and the new bit-depth and color-type
  43. channels=png_get_channels (png_ptr, info_ptr);
  44. switch(color_type)
  45. {
  46. default : goto error;
  47. case PNG_COLOR_TYPE_GRAY : if(channels!=1 || (bit_depth!=8 && bit_depth!=16))goto error; createSoftTry(width, height, 1, (bit_depth==8) ? IMAGE_L8 : IMAGE_I16); break;
  48. case PNG_COLOR_TYPE_GRAY_ALPHA: if(channels!=2 || bit_depth!=8 )goto error; createSoftTry(width, height, 1, IMAGE_L8A8 ); break;
  49. case PNG_COLOR_TYPE_RGB : if(channels!=3 || bit_depth!=8 )goto error; createSoftTry(width, height, 1, IMAGE_R8G8B8 ); break;
  50. case PNG_COLOR_TYPE_RGB_ALPHA : if(channels!=4 || bit_depth!=8 )goto error; createSoftTry(width, height, 1, IMAGE_R8G8B8A8 ); break;
  51. }
  52. created=true;
  53. row_ptrs.setNum(height); REPAO(row_ptrs)=data()+pitch()*i; // set the individual row-pointers to point at the correct offsets
  54. png_read_image(png_ptr, row_ptrs.data()); // now we can go ahead and just read the whole image
  55. png_read_end (png_ptr, null ); // read the end marker
  56. ok=f.ok();
  57. }
  58. error:;
  59. png_destroy_read_struct(&png_ptr, &info_ptr, null);
  60. if(!ok && !created)del(); return ok; // if failed but the image was created, then it's possible that some data was read, keep that in case user wants to preview what was read
  61. #else
  62. del(); return false;
  63. #endif
  64. }
  65. Bool Image::ExportPNG(File &f, Flt compression_level)C
  66. {
  67. #if SUPPORT_PNG
  68. C Image *src=this;
  69. Image temp;
  70. if(!src->is ())return false;
  71. if( src->cube()){if(!temp.fromCube(*src, ImageTI[src->type()].compressed ? IMAGE_R8G8B8A8 : -1, IMAGE_SOFT))return false; src=&temp;}
  72. Int bit_depth=0, color_type=0;
  73. switch(src->hwType())
  74. {
  75. case IMAGE_I16 : bit_depth=16; color_type=PNG_COLOR_TYPE_GRAY ; break;
  76. case IMAGE_L8 : bit_depth= 8; color_type=PNG_COLOR_TYPE_GRAY ; break;
  77. case IMAGE_A8 : bit_depth= 8; color_type=PNG_COLOR_TYPE_GRAY ; break;
  78. case IMAGE_L8A8 : bit_depth= 8; color_type=PNG_COLOR_TYPE_GRAY_ALPHA; break;
  79. case IMAGE_R8G8B8 : bit_depth= 8; color_type=PNG_COLOR_TYPE_RGB ; break;
  80. case IMAGE_R8G8B8A8: bit_depth= 8; color_type=PNG_COLOR_TYPE_RGB_ALPHA ; break;
  81. case IMAGE_I24:
  82. case IMAGE_I32:
  83. case IMAGE_F16:
  84. case IMAGE_F32: if(!src->copyTry(temp, -1, -1, 1, IMAGE_I16, IMAGE_SOFT, 1))return false; src=&temp; bit_depth=16; color_type=PNG_COLOR_TYPE_GRAY; break;
  85. default: if(!src->copyTry(temp, -1, -1, 1, IMAGE_R8G8B8A8, IMAGE_SOFT, 1))return false; src=&temp; bit_depth=8; color_type=PNG_COLOR_TYPE_RGB_ALPHA; break;
  86. }
  87. if(src->lockRead())
  88. {
  89. Bool ok=false;
  90. png_structp png_ptr=null;
  91. png_infop info_ptr=null;
  92. Memt<png_byte*> row_ptrs;
  93. png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, null, null, null); if(! png_ptr)goto error; if(setjmp(png_jmpbuf(png_ptr)))goto error;
  94. info_ptr=png_create_info_struct (png_ptr ); if(!info_ptr)goto error;
  95. {
  96. if(compression_level>=0)png_set_compression_level(png_ptr, Mid(RoundPos(compression_level*9), 0, 9));
  97. png_set_write_fn(png_ptr, (png_voidp)&f, PngWriteData, null); // initialize the png structure
  98. png_set_IHDR (png_ptr, info_ptr, src->w(), src->h(), bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  99. png_write_info (png_ptr, info_ptr);
  100. if(color_type==PNG_COLOR_TYPE_GRAY && bit_depth==16)png_set_swap(png_ptr);
  101. row_ptrs.setNum(src->h()); REPAO(row_ptrs)=ConstCast(src->data()+i*src->pitch()); // set the individual row-pointers to point at the correct offsets
  102. png_write_image(png_ptr, row_ptrs.data()); // write out the entire image data in one call
  103. png_write_end (png_ptr, info_ptr ); // write the end marker
  104. ok=f.ok();
  105. }
  106. error:;
  107. png_destroy_write_struct(&png_ptr, &info_ptr);
  108. src->unlock();
  109. return ok;
  110. }
  111. #endif
  112. return false;
  113. }
  114. /******************************************************************************/
  115. Bool Image::ExportPNG(C Str &name, Flt compression_level)C
  116. {
  117. #if SUPPORT_PNG
  118. File f; if(f.writeTry(name)){if(ExportPNG(f, compression_level) && f.flush())return true; f.del(); FDelFile(name);}
  119. #endif
  120. return false;
  121. }
  122. Bool Image::ImportPNG(C Str &name)
  123. {
  124. #if SUPPORT_PNG
  125. File f; if(f.readTry(name))return ImportPNG(f);
  126. #endif
  127. del(); return false;
  128. }
  129. /******************************************************************************/
  130. }
  131. /******************************************************************************/