text: // File: crn_pixel_format.h
  // See Copyright Notice and license at the end of inc/crnlib.h
  #pragma once
  #include "crn_dxt.h"
  #include "../inc/crnlib.h"
  #include "../inc/dds_defs.h"
  
  namespace crnlib {
  namespace pixel_format_helpers {
  uint get_num_formats();
  pixel_format get_pixel_format_by_index(uint index);
  
  const char* get_pixel_format_string(pixel_format fmt);
  
  const char* get_crn_format_string(crn_format fmt);
  
  inline bool is_grayscale(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_L8:
      case PIXEL_FMT_A8L8:
        return true;
      default:
        break;
    }
    return false;
  }
  
  inline bool is_dxt1(pixel_format fmt) {
    return (fmt == PIXEL_FMT_DXT1) || (fmt == PIXEL_FMT_DXT1A);
  }
  
  // has_alpha() should probably be called "has_opacity()" - it indicates if the format encodes opacity
  // because some swizzled DXT5 formats do not encode opacity.
  inline bool has_alpha(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_DXT1A:
      case PIXEL_FMT_DXT2:
      case PIXEL_FMT_DXT3:
      case PIXEL_FMT_DXT4:
      case PIXEL_FMT_DXT5:
      case PIXEL_FMT_DXT5A:
      case PIXEL_FMT_A8R8G8B8:
      case PIXEL_FMT_A8:
      case PIXEL_FMT_A8L8:
      case PIXEL_FMT_DXT5_AGBR:
      case PIXEL_FMT_ETC2A:
      case PIXEL_FMT_ETC2AS:
        return true;
      default:
        break;
    }
    return false;
  }
  
  inline bool is_alpha_only(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_A8:
      case PIXEL_FMT_DXT5A:
        return true;
      default:
        break;
    }
    return false;
  }
  
  inline bool is_normal_map(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_3DC:
      case PIXEL_FMT_DXN:
      case PIXEL_FMT_DXT5_xGBR:
      case PIXEL_FMT_DXT5_xGxR:
      case PIXEL_FMT_DXT5_AGBR:
        return true;
      default:
        break;
    }
    return false;
  }
  
  inline int is_dxt(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_DXT1:
      case PIXEL_FMT_DXT1A:
      case PIXEL_FMT_DXT2:
      case PIXEL_FMT_DXT3:
      case PIXEL_FMT_DXT4:
      case PIXEL_FMT_DXT5:
      case PIXEL_FMT_3DC:
      case PIXEL_FMT_DXT5A:
      case PIXEL_FMT_DXN:
      case PIXEL_FMT_DXT5_CCxY:
      case PIXEL_FMT_DXT5_xGxR:
      case PIXEL_FMT_DXT5_xGBR:
      case PIXEL_FMT_DXT5_AGBR:
      case PIXEL_FMT_ETC1:
      case PIXEL_FMT_ETC2:
      case PIXEL_FMT_ETC2A:
      case PIXEL_FMT_ETC1S:
      case PIXEL_FMT_ETC2AS:
        return true;
      default:
        break;
    }
    return false;
  }
  
  inline int get_fundamental_format(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_DXT1A:
        return PIXEL_FMT_DXT1;
      case PIXEL_FMT_DXT5_CCxY:
      case PIXEL_FMT_DXT5_xGxR:
      case PIXEL_FMT_DXT5_xGBR:
      case PIXEL_FMT_DXT5_AGBR:
        return PIXEL_FMT_DXT5;
      default:
        break;
    }
    return fmt;
  }
  
  inline dxt_format get_dxt_format(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_DXT1:
        return cDXT1;
      case PIXEL_FMT_DXT1A:
        return cDXT1A;
      case PIXEL_FMT_DXT2:
        return cDXT3;
      case PIXEL_FMT_DXT3:
        return cDXT3;
      case PIXEL_FMT_DXT4:
        return cDXT5;
      case PIXEL_FMT_DXT5:
        return cDXT5;
      case PIXEL_FMT_3DC:
        return cDXN_YX;
      case PIXEL_FMT_DXT5A:
        return cDXT5A;
      case PIXEL_FMT_DXN:
        return cDXN_XY;
      case PIXEL_FMT_DXT5_CCxY:
        return cDXT5;
      case PIXEL_FMT_DXT5_xGxR:
        return cDXT5;
      case PIXEL_FMT_DXT5_xGBR:
        return cDXT5;
      case PIXEL_FMT_DXT5_AGBR:
        return cDXT5;
      case PIXEL_FMT_ETC1:
        return cETC1;
      case PIXEL_FMT_ETC2:
        return cETC2;
      case PIXEL_FMT_ETC2A:
        return cETC2A;
      case PIXEL_FMT_ETC1S:
        return cETC1S;
      case PIXEL_FMT_ETC2AS:
        return cETC2AS;
      default:
        break;
    }
    return cDXTInvalid;
  }
  
  inline pixel_format from_dxt_format(dxt_format dxt_fmt) {
    switch (dxt_fmt) {
      case cDXT1:
        return PIXEL_FMT_DXT1;
      case cDXT1A:
        return PIXEL_FMT_DXT1A;
      case cDXT3:
        return PIXEL_FMT_DXT3;
      case cDXT5:
        return PIXEL_FMT_DXT5;
      case cDXN_XY:
        return PIXEL_FMT_DXN;
      case cDXN_YX:
        return PIXEL_FMT_3DC;
      case cDXT5A:
        return PIXEL_FMT_DXT5A;
      case cETC1:
        return PIXEL_FMT_ETC1;
      case cETC2:
        return PIXEL_FMT_ETC2;
      case cETC2A:
        return PIXEL_FMT_ETC2A;
      case cETC1S:
        return PIXEL_FMT_ETC1S;
      case cETC2AS:
        return PIXEL_FMT_ETC2AS;
      default:
        break;
    }
    CRNLIB_ASSERT(false);
    return PIXEL_FMT_INVALID;
  }
  
  inline bool is_pixel_format_non_srgb(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_3DC:
      case PIXEL_FMT_DXN:
      case PIXEL_FMT_DXT5A:
      case PIXEL_FMT_DXT5_CCxY:
      case PIXEL_FMT_DXT5_xGxR:
      case PIXEL_FMT_DXT5_xGBR:
      case PIXEL_FMT_DXT5_AGBR:
        return true;
      default:
        break;
    }
    return false;
  }
  
  inline bool is_crn_format_non_srgb(crn_format fmt) {
    switch (fmt) {
      case cCRNFmtDXN_XY:
      case cCRNFmtDXN_YX:
      case cCRNFmtDXT5A:
      case cCRNFmtDXT5_CCxY:
      case cCRNFmtDXT5_xGxR:
      case cCRNFmtDXT5_xGBR:
      case cCRNFmtDXT5_AGBR:
        return true;
      default:
        break;
    }
    return false;
  }
  
  inline uint get_bpp(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_DXT1:
        return 4;
      case PIXEL_FMT_DXT1A:
        return 4;
      case PIXEL_FMT_ETC1:
        return 4;
      case PIXEL_FMT_ETC2:
        return 4;
      case PIXEL_FMT_ETC2A:
        return 8;
      case PIXEL_FMT_ETC1S:
        return 4;
      case PIXEL_FMT_ETC2AS:
        return 8;
      case PIXEL_FMT_DXT2:
        return 8;
      case PIXEL_FMT_DXT3:
        return 8;
      case PIXEL_FMT_DXT4:
        return 8;
      case PIXEL_FMT_DXT5:
        return 8;
      case PIXEL_FMT_3DC:
        return 8;
      case PIXEL_FMT_DXT5A:
        return 4;
      case PIXEL_FMT_R8G8B8:
        return 24;
      case PIXEL_FMT_A8R8G8B8:
        return 32;
      case PIXEL_FMT_A8:
        return 8;
      case PIXEL_FMT_L8:
        return 8;
      case PIXEL_FMT_A8L8:
        return 16;
      case PIXEL_FMT_DXN:
        return 8;
      case PIXEL_FMT_DXT5_CCxY:
        return 8;
      case PIXEL_FMT_DXT5_xGxR:
        return 8;
      case PIXEL_FMT_DXT5_xGBR:
        return 8;
      case PIXEL_FMT_DXT5_AGBR:
        return 8;
      default:
        break;
    }
    CRNLIB_ASSERT(false);
    return 0;
  };
  
  inline uint get_dxt_bytes_per_block(pixel_format fmt) {
    switch (fmt) {
      case PIXEL_FMT_DXT1:
        return 8;
      case PIXEL_FMT_DXT1A:
        return 8;
      case PIXEL_FMT_DXT5A:
        return 8;
      case PIXEL_FMT_ETC1:
        return 8;
      case PIXEL_FMT_ETC2:
        return 8;
      case PIXEL_FMT_ETC2A:
        return 16;
      case PIXEL_FMT_ETC1S:
        return 8;
      case PIXEL_FMT_ETC2AS:
        return 16;
      case PIXEL_FMT_DXT2:
        return 16;
      case PIXEL_FMT_DXT3:
        return 16;
      case PIXEL_FMT_DXT4:
        return 16;
      case PIXEL_FMT_DXT5:
        return 16;
      case PIXEL_FMT_3DC:
        return 16;
      case PIXEL_FMT_DXN:
        return 16;
      case PIXEL_FMT_DXT5_CCxY:
        return 16;
      case PIXEL_FMT_DXT5_xGxR:
        return 16;
      case PIXEL_FMT_DXT5_xGBR:
        return 16;
      case PIXEL_FMT_DXT5_AGBR:
        return 16;
      default:
        break;
    }
    CRNLIB_ASSERT(false);
    return 0;
  }
  
  enum component_flags {
    cCompFlagRValid = 1,
    cCompFlagGValid = 2,
    cCompFlagBValid = 4,
    cCompFlagAValid = 8,
  
    cCompFlagGrayscale = 16,
    cCompFlagNormalMap = 32,
    cCompFlagLumaChroma = 64,
  
    cDefaultCompFlags = cCompFlagRValid | cCompFlagGValid | cCompFlagBValid | cCompFlagAValid
  };
  
  component_flags get_component_flags(pixel_format fmt);
  
  crn_format convert_pixel_format_to_best_crn_format(pixel_format crn_fmt);
  
  pixel_format convert_crn_format_to_pixel_format(crn_format fmt);
  
  }  // namespace pixel_format_helpers
  
  }  // namespace crnlib
  