diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bcf648..8f63db7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ set(BASISU_SRC_LIST ${COMMON_SRC_LIST} basisu_bc7enc.cpp lodepng.cpp apg_bmp.c + jpgd.cpp transcoder/basisu_transcoder.cpp ) diff --git a/basisu.vcxproj b/basisu.vcxproj index c61c4a2..c23a715 100644 --- a/basisu.vcxproj +++ b/basisu.vcxproj @@ -154,6 +154,7 @@ + @@ -173,6 +174,7 @@ + diff --git a/basisu.vcxproj.filters b/basisu.vcxproj.filters index 218c3f1..1764b4b 100644 --- a/basisu.vcxproj.filters +++ b/basisu.vcxproj.filters @@ -22,6 +22,7 @@ + @@ -58,6 +59,7 @@ transcoder + diff --git a/basisu_enc.cpp b/basisu_enc.cpp index a18bb36..488eaf2 100644 --- a/basisu_enc.cpp +++ b/basisu_enc.cpp @@ -20,6 +20,7 @@ #include "transcoder/basisu_transcoder.h" #include "basisu_bc7enc.h" #include "apg_bmp.h" +#include "jpgd.h" #if defined(_WIN32) // For QueryPerformanceCounter/QueryPerformanceFrequency @@ -229,7 +230,7 @@ namespace basisu return true; } - + bool load_tga(const char* pFilename, image& img) { int w = 0, h = 0, n_chans = 0; @@ -326,6 +327,20 @@ namespace basisu return true; } + bool load_jpg(const char *pFilename, image& img) + { + int width = 0, height = 0, actual_comps = 0; + uint8_t *pImage_data = jpgd::decompress_jpeg_image_from_file(pFilename, &width, &height, &actual_comps, 4, 0); + if (!pImage_data) + return false; + + img.init(pImage_data, width, height, 4); + + free(pImage_data); + + return true; + } + bool load_image(const char* pFilename, image& img) { std::string ext(string_get_extension(std::string(pFilename))); @@ -341,6 +356,8 @@ namespace basisu return load_bmp(pFilename, img); if (strcasecmp(pExt, "tga") == 0) return load_tga(pFilename, img); + if ( (strcasecmp(pExt, "jpg") == 0) || (strcasecmp(pExt, "jfif") == 0) || (strcasecmp(pExt, "jpeg") == 0) ) + return load_jpg(pFilename, img); return false; } @@ -1933,5 +1950,5 @@ namespace basisu return read_tga(&filedata[0], (uint32_t)filedata.size(), width, height, n_chans); } - + } // namespace basisu diff --git a/basisu_enc.h b/basisu_enc.h index 2267b95..b1abba0 100644 --- a/basisu_enc.h +++ b/basisu_enc.h @@ -132,6 +132,16 @@ namespace basisu return v; } + inline uint32_t wang_hash(uint32_t seed) + { + seed = (seed ^ 61) ^ (seed >> 16); + seed *= 9; + seed = seed ^ (seed >> 4); + seed *= 0x27d4eb2d; + seed = seed ^ (seed >> 15); + return seed; + } + uint32_t hash_hsieh(const uint8_t* pBuf, size_t len); template @@ -2270,6 +2280,12 @@ namespace basisu resize(w, h, p); } + image(const uint8_t *pImage, uint32_t width, uint32_t height, uint32_t comps) : + m_width(0), m_height(0), m_pitch(0) + { + init(pImage, width, height, comps); + } + image(const image &other) : m_width(0), m_height(0), m_pitch(0) { @@ -2318,6 +2334,47 @@ namespace basisu return *this; } + void init(const uint8_t *pImage, uint32_t width, uint32_t height, uint32_t comps) + { + assert(comps >= 1 && comps <= 4); + + resize(width, height); + + for (uint32_t y = 0; y < height; y++) + { + for (uint32_t x = 0; x < width; x++) + { + const uint8_t *pSrc = &pImage[(x + y * width) * comps]; + color_rgba &dst = (*this)(x, y); + + if (comps == 1) + { + dst.r = pSrc[0]; + dst.g = pSrc[0]; + dst.b = pSrc[0]; + dst.a = 255; + } + else if (comps == 2) + { + dst.r = pSrc[0]; + dst.g = pSrc[0]; + dst.b = pSrc[0]; + dst.a = pSrc[1]; + } + else + { + dst.r = pSrc[0]; + dst.g = pSrc[1]; + dst.b = pSrc[2]; + if (comps == 4) + dst.a = pSrc[3]; + else + dst.a = 255; + } + } + } + } + image &fill_box(uint32_t x, uint32_t y, uint32_t w, uint32_t h, const color_rgba &c) { for (uint32_t iy = 0; iy < h; iy++) @@ -2807,6 +2864,9 @@ namespace basisu bool load_tga(const char* pFilename, image& img); inline bool load_tga(const std::string &filename, image &img) { return load_tga(filename.c_str(), img); } + + bool load_jpg(const char *pFilename, image& img); + inline bool load_jpg(const std::string &filename, image &img) { return load_jpg(filename.c_str(), img); } // Currently loads .BMP, .PNG, or .TGA. bool load_image(const char* pFilename, image& img); @@ -2814,7 +2874,7 @@ namespace basisu uint8_t *read_tga(const uint8_t *pBuf, uint32_t buf_size, int &width, int &height, int &n_chans); uint8_t *read_tga(const char *pFilename, int &width, int &height, int &n_chans); - + enum { cImageSaveGrayscale = 1, diff --git a/basisu_tool.cpp b/basisu_tool.cpp index b661693..813d08b 100644 --- a/basisu_tool.cpp +++ b/basisu_tool.cpp @@ -52,11 +52,11 @@ static void print_usage() printf("\nUsage: basisu filename [filename ...] \n"); puts("\n" - "The default mode is compression of one or more PNG/BMP/TGA files to a .basis file. Alternate modes:\n" + "The default mode is compression of one or more PNG/BMP/TGA/JPG files to a .basis file. Alternate modes:\n" " -unpack: Use transcoder to unpack .basis file to one or more .ktx/.png files\n" " -validate: Validate and display information about a .basis file\n" " -info: Display high-level information about a .basis file\n" - " -compare: Compare two PNG/BMP/TGA images specified with -file, output PSNR and SSIM statistics and RGB/A delta images\n" + " -compare: Compare two PNG/BMP/TGA/JPG images specified with -file, output PSNR and SSIM statistics and RGB/A delta images\n" " -version: Print basisu version and exit\n" "Unless an explicit mode is specified, if one or more files have the .basis extension this tool defaults to unpack mode.\n" "\n" @@ -66,8 +66,8 @@ static void print_usage() "Filenames prefixed with a @ symbol are read as filename listing files. Listing text files specify which actual filenames to process (one filename per line).\n" "\n" "Options:\n" - " -file filename.png/bmp/tga: Input image filename, multiple images are OK, use -file X for each input filename (prefixing input filenames with -file is optional)\n" - " -alpha_file filename.png/bmp/tga: Input alpha image filename, multiple images are OK, use -file X for each input filename (must be paired with -file), images converted to REC709 grayscale and used as input alpha\n" + " -file filename.png/bmp/tga/jpg: Input image filename, multiple images are OK, use -file X for each input filename (prefixing input filenames with -file is optional)\n" + " -alpha_file filename.png/bmp/tga/jpg: Input alpha image filename, multiple images are OK, use -file X for each input filename (must be paired with -file), images converted to REC709 grayscale and used as input alpha\n" " -multifile_printf: printf() format strint to use to compose multiple filenames\n" " -multifile_first: The index of the first file to process, default is 0 (must specify -multifile_printf and -multifile_num)\n" " -multifile_num: The total number of files to process.\n"