WEBP.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. #if SUPPORT_WEBP
  4. #include "../../../../ThirdPartyLibs/begin.h"
  5. #include "../../../../ThirdPartyLibs/Webp/src/webp/decode.h"
  6. #include "../../../../ThirdPartyLibs/Webp/src/webp/encode.h"
  7. #include "../../../../ThirdPartyLibs/end.h"
  8. #endif
  9. namespace EE{
  10. /******************************************************************************/
  11. Bool Image::ImportWEBP(File &f)
  12. {
  13. Bool ok=false;
  14. #if SUPPORT_WEBP
  15. if(f.getUInt()==CC4('R','I','F','F'))
  16. {
  17. UInt size; f>>size;
  18. if(f.left()>=size
  19. && f.getUInt()==CC4('W','E','B','P'))
  20. {
  21. f.skip(-12);
  22. WebPDecoderConfig config;
  23. WebPDecBuffer *const output_buffer=&config.output;
  24. WebPBitstreamFeatures *const bitstream =&config.input;
  25. if(WebPInitDecoderConfig(&config))
  26. {
  27. //config.options.use_threads=1; made no difference in performance
  28. Memt<Byte> temp; temp.setNum(size+8); // we have to add 8 for the RIFF+size data
  29. if(f.getFast(temp.data(), temp.elms()))
  30. if(WebPGetFeatures(temp.data(), temp.elms(), bitstream)==VP8_STATUS_OK)
  31. {
  32. IMAGE_TYPE type;
  33. if(bitstream->has_alpha)
  34. {
  35. type =IMAGE_R8G8B8A8;
  36. output_buffer->colorspace=MODE_RGBA;
  37. }else
  38. {
  39. type =IMAGE_R8G8B8;
  40. output_buffer->colorspace=MODE_RGB;
  41. }
  42. if(createSoftTry(bitstream->width, bitstream->height, 1, type))
  43. {
  44. output_buffer->is_external_memory=true;
  45. output_buffer->u.RGBA.stride=pitch ();
  46. output_buffer->u.RGBA.size =pitch2();
  47. output_buffer->u.RGBA.rgba =data ();
  48. if(WebPDecode(temp.data(), temp.elms(), &config)==VP8_STATUS_OK)ok=true;
  49. }
  50. }
  51. WebPFreeDecBuffer(output_buffer);
  52. }
  53. }
  54. }
  55. #endif
  56. if(!ok)del(); return ok;
  57. }
  58. Bool Image::ImportWEBP(C Str &name)
  59. {
  60. #if SUPPORT_WEBP
  61. File f; if(f.readTry(name))return ImportWEBP(f);
  62. #endif
  63. del(); return false;
  64. }
  65. /******************************************************************************/
  66. #if SUPPORT_WEBP
  67. static int WEBPWriter(const uint8_t* data, size_t data_size, const WebPPicture* const pic)
  68. {
  69. File &f=*(File*)pic->custom_ptr;
  70. return f.put(data, (Int)data_size);
  71. }
  72. #endif
  73. Bool Image::ExportWEBP(File &f, Flt rgb_quality, Flt alpha_quality)C
  74. {
  75. Bool ok=false;
  76. #if SUPPORT_WEBP
  77. C Image *src=this;
  78. Image temp;
  79. if(src->cube () ){ temp.fromCube(*src , IMAGE_B8G8R8A8, IMAGE_SOFT ); src=&temp;}
  80. if(src->hwType()!=IMAGE_B8G8R8A8){if(!src->copyTry ( temp, -1, -1, -1, IMAGE_B8G8R8A8, IMAGE_SOFT, 1))return false; src=&temp;}
  81. if(src->w()<=WEBP_MAX_DIMENSION
  82. && src->h()<=WEBP_MAX_DIMENSION)
  83. if(src->lockRead())
  84. {
  85. WebPPicture picture;
  86. WebPConfig config;
  87. if(WebPPictureInit(&picture)
  88. && WebPConfigInit (&config))
  89. {
  90. Int q=RoundPos(rgb_quality*100);
  91. if( q< 0)q=100;else // default to 100=lossless
  92. if( q>100)q=100;
  93. Int aq=RoundPos(alpha_quality*100);
  94. if( aq< 0)aq= q;else // default to 'q'=rgb_quality
  95. if( aq>100)aq=100;
  96. //config .pass =10; // very little difference, not sure if better or worse
  97. //config .method =6; // this affects only lossy, 5 and 6 are supposed to be better quality, however they actually made image lose detail
  98. //config .thread_level =2; // 1=no performance difference, >=1 actually makes the compression to fail
  99. //config .near_lossless=; // made things much worse
  100. config .lossless =(q>=100);
  101. config . quality= q;
  102. config .alpha_quality=aq;
  103. config .exact =true;
  104. picture.width =src->w();
  105. picture.height =src->h();
  106. #if 1 // RGBA
  107. picture.use_argb =true;
  108. picture.argb =(uint32_t*)src->data();
  109. picture.argb_stride =src->pitch()/src->bytePP(); // in pixel units
  110. #else // YUVA, this didn't improve the quality, we could use it mainly if we had the source already in YUV format
  111. Image Y, U, V, A;
  112. Y.createSoftTry(src->w(), src->h(), 1, IMAGE_L8);
  113. U.createSoftTry(src->w(), src->h(), 1, IMAGE_L8);
  114. V.createSoftTry(src->w(), src->h(), 1, IMAGE_L8);
  115. if(ImageTI[src->type()].a)
  116. if(src->copyTry(A, -1, -1, -1, IMAGE_A8, IMAGE_SOFT, 1))
  117. {
  118. picture.a =(uint8_t*)A.data();
  119. picture.a_stride=A.pitch()/A.bytePP(); // in pixel units
  120. }
  121. REPD(y, src->h())
  122. REPD(x, src->w())
  123. {
  124. Vec yuv=RgbToYuv(src->colorF(x, y).xyz);
  125. Y.pixelF(x, y, yuv.x);
  126. U.pixelF(x, y, yuv.y);
  127. V.pixelF(x, y, yuv.z);
  128. }
  129. U.downSample();
  130. V.downSample();
  131. picture.use_argb =false;
  132. picture.y =(uint8_t*)Y.data();
  133. picture.u =(uint8_t*)U.data();
  134. picture.v =(uint8_t*)V.data();
  135. picture.y_stride =Y.pitch()/Y.bytePP(); // in pixel units
  136. picture.uv_stride=U.pitch()/U.bytePP(); // in pixel units
  137. #endif
  138. picture.custom_ptr =&f;
  139. picture.writer =WEBPWriter;
  140. if(WebPEncode(&config, &picture))ok=f.ok();
  141. WebPPictureFree(&picture);
  142. }
  143. src->unlock();
  144. }
  145. #endif
  146. return ok;
  147. }
  148. Bool Image::ExportWEBP(C Str &name, Flt rgb_quality, Flt alpha_quality)C
  149. {
  150. #if SUPPORT_WEBP
  151. File f; if(f.writeTry(name)){if(ExportWEBP(f, rgb_quality, alpha_quality) && f.flush())return true; f.del(); FDelFile(name);}
  152. #endif
  153. return false;
  154. }
  155. /******************************************************************************/
  156. }
  157. /******************************************************************************/