crn_image_utils.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // File: crn_image_utils.h
  2. // See Copyright Notice and license at the end of inc/crnlib.h
  3. #pragma once
  4. #include "crn_image.h"
  5. #include "crn_data_stream_serializer.h"
  6. namespace crnlib
  7. {
  8. enum pixel_format;
  9. namespace image_utils
  10. {
  11. enum read_flags_t
  12. {
  13. cReadFlagForceSTB = 1,
  14. cReadFlagsAllFlags = 1
  15. };
  16. bool read_from_stream_stb(data_stream_serializer& serializer, image_u8& img);
  17. bool read_from_stream_jpgd(data_stream_serializer& serializer, image_u8& img);
  18. bool read_from_stream(image_u8& dest, data_stream_serializer& serializer, uint read_flags = 0);
  19. bool read_from_file(image_u8& dest, const char* pFilename, uint read_flags = 0);
  20. // Reads texture from memory, results returned stb_image.c style.
  21. // *pActual_comps is set to 1, 3, or 4. req_comps must range from 1-4.
  22. uint8* read_from_memory(const uint8* pImage, int nSize, int* pWidth, int* pHeight, int* pActualComps, int req_comps, const char* pFilename);
  23. enum
  24. {
  25. cWriteFlagIgnoreAlpha = 0x00000001,
  26. cWriteFlagGrayscale = 0x00000002,
  27. cWriteFlagJPEGH1V1 = 0x00010000,
  28. cWriteFlagJPEGH2V1 = 0x00020000,
  29. cWriteFlagJPEGH2V2 = 0x00040000,
  30. cWriteFlagJPEGTwoPass = 0x00080000,
  31. cWriteFlagJPEGNoChromaDiscrim = 0x00100000,
  32. cWriteFlagJPEGQualityLevelMask = 0xFF000000,
  33. cWriteFlagJPEGQualityLevelShift = 24,
  34. };
  35. const int cLumaComponentIndex = -1;
  36. inline uint create_jpeg_write_flags(uint base_flags, uint quality_level) { CRNLIB_ASSERT(quality_level <= 100); return base_flags | ((quality_level << cWriteFlagJPEGQualityLevelShift) & cWriteFlagJPEGQualityLevelMask); }
  37. bool write_to_file(const char* pFilename, const image_u8& img, uint write_flags = 0, int grayscale_comp_index = cLumaComponentIndex);
  38. bool has_alpha(const image_u8& img);
  39. bool is_normal_map(const image_u8& img, const char* pFilename = NULL);
  40. void renorm_normal_map(image_u8& img);
  41. struct resample_params
  42. {
  43. resample_params() :
  44. m_dst_width(0),
  45. m_dst_height(0),
  46. m_pFilter("lanczos4"),
  47. m_filter_scale(1.0f),
  48. m_srgb(true),
  49. m_wrapping(false),
  50. m_first_comp(0),
  51. m_num_comps(4),
  52. m_source_gamma(2.2f), // 1.75f
  53. m_multithreaded(true)
  54. {
  55. }
  56. uint m_dst_width;
  57. uint m_dst_height;
  58. const char* m_pFilter;
  59. float m_filter_scale;
  60. bool m_srgb;
  61. bool m_wrapping;
  62. uint m_first_comp;
  63. uint m_num_comps;
  64. float m_source_gamma;
  65. bool m_multithreaded;
  66. };
  67. bool resample_single_thread(const image_u8& src, image_u8& dst, const resample_params& params);
  68. bool resample_multithreaded(const image_u8& src, image_u8& dst, const resample_params& params);
  69. bool resample(const image_u8& src, image_u8& dst, const resample_params& params);
  70. bool compute_delta(image_u8& dest, image_u8& a, image_u8& b, uint scale = 2);
  71. class error_metrics
  72. {
  73. public:
  74. error_metrics() { utils::zero_this(this); }
  75. void print(const char* pName) const;
  76. // If num_channels==0, luma error is computed.
  77. // If pHist != NULL, it must point to a 256 entry array.
  78. bool compute(const image_u8& a, const image_u8& b, uint first_channel, uint num_channels, bool average_component_error = true);
  79. uint mMax;
  80. double mMean;
  81. double mMeanSquared;
  82. double mRootMeanSquared;
  83. double mPeakSNR;
  84. inline bool operator== (const error_metrics& other) const
  85. {
  86. return mPeakSNR == other.mPeakSNR;
  87. }
  88. inline bool operator< (const error_metrics& other) const
  89. {
  90. return mPeakSNR < other.mPeakSNR;
  91. }
  92. inline bool operator> (const error_metrics& other) const
  93. {
  94. return mPeakSNR > other.mPeakSNR;
  95. }
  96. };
  97. void print_image_metrics(const image_u8& src_img, const image_u8& dst_img);
  98. double compute_block_ssim(uint n, const uint8* pX, const uint8* pY);
  99. double compute_ssim(const image_u8& a, const image_u8& b, int channel_index);
  100. void print_ssim(const image_u8& src_img, const image_u8& dst_img);
  101. enum conversion_type
  102. {
  103. cConversion_Invalid = -1,
  104. cConversion_To_CCxY,
  105. cConversion_From_CCxY,
  106. cConversion_To_xGxR,
  107. cConversion_From_xGxR,
  108. cConversion_To_xGBR,
  109. cConversion_From_xGBR,
  110. cConversion_To_AGBR,
  111. cConversion_From_AGBR,
  112. cConversion_XY_to_XYZ,
  113. cConversion_Y_To_A,
  114. cConversion_A_To_RGBA,
  115. cConversion_Y_To_RGB,
  116. cConversion_To_Y,
  117. cConversionTotal
  118. };
  119. void convert_image(image_u8& img, conversion_type conv_type);
  120. template<typename image_type>
  121. inline uint8* pack_image(const image_type& img, const pixel_packer& packer, uint& n)
  122. {
  123. n = 0;
  124. if (!packer.is_valid())
  125. return NULL;
  126. const uint width = img.get_width(), height = img.get_height();
  127. uint dst_pixel_stride = packer.get_pixel_stride();
  128. uint dst_pitch = width * dst_pixel_stride;
  129. n = dst_pitch * height;
  130. uint8* pImage = static_cast<uint8*>(crnlib_malloc(n));
  131. uint8* pDst = pImage;
  132. for (uint y = 0; y < height; y++)
  133. {
  134. const typename image_type::color_t* pSrc = img.get_scanline(y);
  135. for (uint x = 0; x < width; x++)
  136. pDst = (uint8*)packer.pack(*pSrc++, pDst);
  137. }
  138. return pImage;
  139. }
  140. image_utils::conversion_type get_conversion_type(bool cooking, pixel_format fmt);
  141. image_utils::conversion_type get_image_conversion_type_from_crn_format(crn_format fmt);
  142. double compute_std_dev(uint n, const color_quad_u8* pPixels, uint first_channel, uint num_channels);
  143. uint8* read_image_from_memory(const uint8* pImage, int nSize, int* pWidth, int* pHeight, int* pActualComps, int req_comps, const char* pFilename);
  144. } // namespace image_utils
  145. } // namespace crnlib