4bb735f796
Explanation: Crunch library has been designed to work correctly when using up to 16 threads. Considering that one of those threads is the main thread, the maximum number of helper threads should be set to 15.
641 lines
25 KiB
C
641 lines
25 KiB
C
// File: crnlib.h - Advanced DXTn texture compression library.
|
|
// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC
|
|
// See copyright notice and license at the end of this file.
|
|
//
|
|
// This header file contains the public crnlib declarations for DXTn,
|
|
// clustered DXTn, and CRN compression/decompression.
|
|
//
|
|
// Note: This library does NOT need to be linked into your game executable if
|
|
// all you want to do is transcode .CRN files to raw DXTn bits at run-time.
|
|
// The crn_decomp.h header file library contains all the code necessary for
|
|
// decompression.
|
|
//
|
|
// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
|
|
#ifndef CRNLIB_H
|
|
#define CRNLIB_H
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(disable : 4127) // conditional expression is constant
|
|
#endif
|
|
|
|
#define CRNLIB_VERSION 104
|
|
|
|
#define CRNLIB_SUPPORT_ATI_COMPRESS 0
|
|
#define CRNLIB_SUPPORT_SQUISH 0
|
|
|
|
typedef unsigned char crn_uint8;
|
|
typedef unsigned short crn_uint16;
|
|
typedef unsigned int crn_uint32;
|
|
typedef signed char crn_int8;
|
|
typedef signed short crn_int16;
|
|
typedef signed int crn_int32;
|
|
typedef unsigned int crn_bool;
|
|
|
|
// crnlib can compress to these file types.
|
|
enum crn_file_type {
|
|
// .CRN
|
|
cCRNFileTypeCRN = 0,
|
|
|
|
// .DDS using regular DXT or clustered DXT
|
|
cCRNFileTypeDDS,
|
|
|
|
cCRNFileTypeForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
// Supported compressed pixel formats.
|
|
// Basically all the standard DX9 formats, with some swizzled DXT5 formats
|
|
// (most of them supported by ATI's Compressonator), along with some ATI/X360 GPU specific formats.
|
|
enum crn_format {
|
|
cCRNFmtInvalid = -1,
|
|
|
|
cCRNFmtDXT1 = 0,
|
|
|
|
cCRNFmtFirstValid = cCRNFmtDXT1,
|
|
|
|
// cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS.
|
|
cCRNFmtDXT3,
|
|
|
|
cCRNFmtDXT5,
|
|
|
|
// Various DXT5 derivatives
|
|
cCRNFmtDXT5_CCxY, // Luma-chroma
|
|
cCRNFmtDXT5_xGxR, // Swizzled 2-component
|
|
cCRNFmtDXT5_xGBR, // Swizzled 3-component
|
|
cCRNFmtDXT5_AGBR, // Swizzled 4-component
|
|
|
|
// ATI 3DC and X360 DXN
|
|
cCRNFmtDXN_XY,
|
|
cCRNFmtDXN_YX,
|
|
|
|
// DXT5 alpha blocks only
|
|
cCRNFmtDXT5A,
|
|
|
|
cCRNFmtETC1,
|
|
cCRNFmtETC2,
|
|
cCRNFmtETC2A,
|
|
cCRNFmtETC1S,
|
|
cCRNFmtETC2AS,
|
|
|
|
cCRNFmtTotal,
|
|
|
|
cCRNFmtForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
// Various library/file format limits.
|
|
enum crn_limits {
|
|
// Max. mipmap level resolution on any axis.
|
|
cCRNMaxLevelResolution = 4096,
|
|
|
|
cCRNMinPaletteSize = 8,
|
|
cCRNMaxPaletteSize = 8192,
|
|
|
|
cCRNMaxFaces = 6,
|
|
cCRNMaxLevels = 16,
|
|
|
|
cCRNMaxHelperThreads = 15,
|
|
|
|
cCRNMinQualityLevel = 0,
|
|
cCRNMaxQualityLevel = 255
|
|
};
|
|
|
|
// CRN/DDS compression flags.
|
|
// See the m_flags member in the crn_comp_params struct, below.
|
|
enum crn_comp_flags {
|
|
// Enables perceptual colorspace distance metrics if set.
|
|
// Important: Be sure to disable this when compressing non-sRGB colorspace images, like normal maps!
|
|
// Default: Set
|
|
cCRNCompFlagPerceptual = 1,
|
|
|
|
// Enables (up to) 8x8 macroblock usage if set. If disabled, only 4x4 blocks are allowed.
|
|
// Compression ratio will be lower when disabled, but may cut down on blocky artifacts because the process used to determine
|
|
// where large macroblocks can be used without artifacts isn't perfect.
|
|
// Default: Set.
|
|
cCRNCompFlagHierarchical = 2,
|
|
|
|
// cCRNCompFlagQuick disables several output file optimizations - intended for things like quicker previews.
|
|
// Default: Not set.
|
|
cCRNCompFlagQuick = 4,
|
|
|
|
// DXT1: OK to use DXT1 alpha blocks for better quality or DXT1A transparency.
|
|
// DXT5: OK to use both DXT5 block types.
|
|
// Currently only used when writing to .DDS files, as .CRN uses only a subset of the possible DXTn block types.
|
|
// Default: Set.
|
|
cCRNCompFlagUseBothBlockTypes = 8,
|
|
|
|
// OK to use DXT1A transparent indices to encode black (assumes pixel shader ignores fetched alpha).
|
|
// Currently only used when writing to .DDS files, .CRN never uses alpha blocks.
|
|
// Default: Not set.
|
|
cCRNCompFlagUseTransparentIndicesForBlack = 16,
|
|
|
|
// Disables endpoint caching, for more deterministic output.
|
|
// Currently only used when writing to .DDS files.
|
|
// Default: Not set.
|
|
cCRNCompFlagDisableEndpointCaching = 32,
|
|
|
|
// If enabled, use the cCRNColorEndpointPaletteSize, etc. params to control the CRN palette sizes. Only useful when writing to .CRN files.
|
|
// Default: Not set.
|
|
cCRNCompFlagManualPaletteSizes = 64,
|
|
|
|
// If enabled, DXT1A alpha blocks are used to encode single bit transparency.
|
|
// Default: Not set.
|
|
cCRNCompFlagDXT1AForTransparency = 128,
|
|
|
|
// If enabled, the DXT1 compressor's color distance metric assumes the pixel shader will be converting the fetched RGB results to luma (Y part of YCbCr).
|
|
// This increases quality when compressing grayscale images, because the compressor can spread the luma error amoung all three channels (i.e. it can generate blocks
|
|
// with some chroma present if doing so will ultimately lead to lower luma error).
|
|
// Only enable on grayscale source images.
|
|
// Default: Not set.
|
|
cCRNCompFlagGrayscaleSampling = 256,
|
|
|
|
// If enabled, debug information will be output during compression.
|
|
// Default: Not set.
|
|
cCRNCompFlagDebugging = 0x80000000,
|
|
|
|
cCRNCompFlagForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
// Controls DXTn quality vs. speed control - only used when compressing to .DDS.
|
|
enum crn_dxt_quality {
|
|
cCRNDXTQualitySuperFast,
|
|
cCRNDXTQualityFast,
|
|
cCRNDXTQualityNormal,
|
|
cCRNDXTQualityBetter,
|
|
cCRNDXTQualityUber,
|
|
|
|
cCRNDXTQualityTotal,
|
|
|
|
cCRNDXTQualityForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
// Which DXTn compressor to use when compressing to plain (non-clustered) .DDS.
|
|
enum crn_dxt_compressor_type {
|
|
cCRNDXTCompressorCRN, // Use crnlib's ETC1 or DXTc block compressor (default, highest quality, comparable or better than ati_compress or squish, and crnlib's ETC1 is a lot fasterw with similiar quality to Erricson's)
|
|
cCRNDXTCompressorCRNF, // Use crnlib's "fast" DXTc block compressor
|
|
cCRNDXTCompressorRYG, // Use RYG's DXTc block compressor (low quality, but very fast)
|
|
|
|
#if CRNLIB_SUPPORT_ATI_COMPRESS
|
|
cCRNDXTCompressorATI,
|
|
#endif
|
|
|
|
#if CRNLIB_SUPPORT_SQUISH
|
|
cCRNDXTCompressorSquish,
|
|
#endif
|
|
|
|
cCRNTotalDXTCompressors,
|
|
|
|
cCRNDXTCompressorForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
// Progress callback function.
|
|
// Processing will stop prematurely (and fail) if the callback returns false.
|
|
// phase_index, total_phases - high level progress
|
|
// subphase_index, total_subphases - progress within current phase
|
|
typedef crn_bool (*crn_progress_callback_func)(crn_uint32 phase_index, crn_uint32 total_phases, crn_uint32 subphase_index, crn_uint32 total_subphases, void* pUser_data_ptr);
|
|
|
|
// CRN/DDS compression parameters struct.
|
|
struct crn_comp_params {
|
|
inline crn_comp_params() { clear(); }
|
|
|
|
// Clear struct to default parameters.
|
|
inline void clear() {
|
|
m_size_of_obj = sizeof(*this);
|
|
m_file_type = cCRNFileTypeCRN;
|
|
m_faces = 1;
|
|
m_width = 0;
|
|
m_height = 0;
|
|
m_levels = 1;
|
|
m_format = cCRNFmtDXT1;
|
|
m_flags = cCRNCompFlagPerceptual | cCRNCompFlagHierarchical | cCRNCompFlagUseBothBlockTypes;
|
|
|
|
for (crn_uint32 f = 0; f < cCRNMaxFaces; f++)
|
|
for (crn_uint32 l = 0; l < cCRNMaxLevels; l++)
|
|
m_pImages[f][l] = NULL;
|
|
|
|
m_target_bitrate = 0.0f;
|
|
m_quality_level = cCRNMaxQualityLevel;
|
|
m_dxt1a_alpha_threshold = 128;
|
|
m_dxt_quality = cCRNDXTQualityUber;
|
|
m_dxt_compressor_type = cCRNDXTCompressorCRN;
|
|
m_alpha_component = 3;
|
|
|
|
m_crn_adaptive_tile_color_psnr_derating = 2.0f;
|
|
m_crn_adaptive_tile_alpha_psnr_derating = 2.0f;
|
|
m_crn_color_endpoint_palette_size = 0;
|
|
m_crn_color_selector_palette_size = 0;
|
|
m_crn_alpha_endpoint_palette_size = 0;
|
|
m_crn_alpha_selector_palette_size = 0;
|
|
|
|
m_num_helper_threads = 0;
|
|
m_userdata0 = 0;
|
|
m_userdata1 = 0;
|
|
m_pProgress_func = NULL;
|
|
m_pProgress_func_data = NULL;
|
|
}
|
|
|
|
inline bool operator==(const crn_comp_params& rhs) const {
|
|
#define CRNLIB_COMP(x) \
|
|
do { \
|
|
if ((x) != (rhs.x)) \
|
|
return false; \
|
|
} while (0)
|
|
CRNLIB_COMP(m_size_of_obj);
|
|
CRNLIB_COMP(m_file_type);
|
|
CRNLIB_COMP(m_faces);
|
|
CRNLIB_COMP(m_width);
|
|
CRNLIB_COMP(m_height);
|
|
CRNLIB_COMP(m_levels);
|
|
CRNLIB_COMP(m_format);
|
|
CRNLIB_COMP(m_flags);
|
|
CRNLIB_COMP(m_target_bitrate);
|
|
CRNLIB_COMP(m_quality_level);
|
|
CRNLIB_COMP(m_dxt1a_alpha_threshold);
|
|
CRNLIB_COMP(m_dxt_quality);
|
|
CRNLIB_COMP(m_dxt_compressor_type);
|
|
CRNLIB_COMP(m_alpha_component);
|
|
CRNLIB_COMP(m_crn_adaptive_tile_color_psnr_derating);
|
|
CRNLIB_COMP(m_crn_adaptive_tile_alpha_psnr_derating);
|
|
CRNLIB_COMP(m_crn_color_endpoint_palette_size);
|
|
CRNLIB_COMP(m_crn_color_selector_palette_size);
|
|
CRNLIB_COMP(m_crn_alpha_endpoint_palette_size);
|
|
CRNLIB_COMP(m_crn_alpha_selector_palette_size);
|
|
CRNLIB_COMP(m_num_helper_threads);
|
|
CRNLIB_COMP(m_userdata0);
|
|
CRNLIB_COMP(m_userdata1);
|
|
CRNLIB_COMP(m_pProgress_func);
|
|
CRNLIB_COMP(m_pProgress_func_data);
|
|
|
|
for (crn_uint32 f = 0; f < cCRNMaxFaces; f++)
|
|
for (crn_uint32 l = 0; l < cCRNMaxLevels; l++)
|
|
CRNLIB_COMP(m_pImages[f][l]);
|
|
|
|
#undef CRNLIB_COMP
|
|
return true;
|
|
}
|
|
|
|
// Returns true if the input parameters are reasonable.
|
|
inline bool check() const {
|
|
if ((m_file_type > cCRNFileTypeDDS) ||
|
|
(((int)m_quality_level < (int)cCRNMinQualityLevel) || ((int)m_quality_level > (int)cCRNMaxQualityLevel)) ||
|
|
(m_dxt1a_alpha_threshold > 255) ||
|
|
((m_faces != 1) && (m_faces != 6)) ||
|
|
((m_width < 1) || (m_width > cCRNMaxLevelResolution)) ||
|
|
((m_height < 1) || (m_height > cCRNMaxLevelResolution)) ||
|
|
((m_levels < 1) || (m_levels > cCRNMaxLevels)) ||
|
|
((m_format < cCRNFmtDXT1) || (m_format >= cCRNFmtTotal)) ||
|
|
((m_crn_color_endpoint_palette_size) && ((m_crn_color_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_color_endpoint_palette_size > cCRNMaxPaletteSize))) ||
|
|
((m_crn_color_selector_palette_size) && ((m_crn_color_selector_palette_size < cCRNMinPaletteSize) || (m_crn_color_selector_palette_size > cCRNMaxPaletteSize))) ||
|
|
((m_crn_alpha_endpoint_palette_size) && ((m_crn_alpha_endpoint_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_endpoint_palette_size > cCRNMaxPaletteSize))) ||
|
|
((m_crn_alpha_selector_palette_size) && ((m_crn_alpha_selector_palette_size < cCRNMinPaletteSize) || (m_crn_alpha_selector_palette_size > cCRNMaxPaletteSize))) ||
|
|
(m_alpha_component > 3) ||
|
|
(m_num_helper_threads > cCRNMaxHelperThreads) ||
|
|
(m_dxt_quality > cCRNDXTQualityUber) ||
|
|
(m_dxt_compressor_type >= cCRNTotalDXTCompressors)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Helper to set/get flags from m_flags member.
|
|
inline bool get_flag(crn_comp_flags flag) const { return (m_flags & flag) != 0; }
|
|
inline void set_flag(crn_comp_flags flag, bool val) {
|
|
m_flags &= ~flag;
|
|
if (val)
|
|
m_flags |= flag;
|
|
}
|
|
|
|
crn_uint32 m_size_of_obj;
|
|
|
|
crn_file_type m_file_type; // Output file type: cCRNFileTypeCRN or cCRNFileTypeDDS.
|
|
|
|
crn_uint32 m_faces; // 1 (2D map) or 6 (cubemap)
|
|
crn_uint32 m_width; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK
|
|
crn_uint32 m_height; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK
|
|
crn_uint32 m_levels; // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK
|
|
|
|
crn_format m_format; // Output pixel format.
|
|
|
|
crn_uint32 m_flags; // see crn_comp_flags enum
|
|
|
|
// Array of pointers to 32bpp input images.
|
|
const crn_uint32* m_pImages[cCRNMaxFaces][cCRNMaxLevels];
|
|
|
|
// Target bitrate - if non-zero, the compressor will use an interpolative search to find the
|
|
// highest quality level that is <= the target bitrate. If it fails to find a bitrate high enough, it'll
|
|
// try disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and redo the search. This process can be pretty slow.
|
|
float m_target_bitrate;
|
|
|
|
// Desired quality level.
|
|
// Currently, CRN and DDS quality levels are not compatible with eachother from an image quality standpoint.
|
|
crn_uint32 m_quality_level; // [cCRNMinQualityLevel, cCRNMaxQualityLevel]
|
|
|
|
// DXTn compression parameters.
|
|
crn_uint32 m_dxt1a_alpha_threshold;
|
|
crn_dxt_quality m_dxt_quality;
|
|
crn_dxt_compressor_type m_dxt_compressor_type;
|
|
|
|
// Alpha channel's component. Defaults to 3.
|
|
crn_uint32 m_alpha_component;
|
|
|
|
// Various low-level CRN specific parameters.
|
|
float m_crn_adaptive_tile_color_psnr_derating;
|
|
float m_crn_adaptive_tile_alpha_psnr_derating;
|
|
|
|
crn_uint32 m_crn_color_endpoint_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
|
|
crn_uint32 m_crn_color_selector_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
|
|
|
|
crn_uint32 m_crn_alpha_endpoint_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
|
|
crn_uint32 m_crn_alpha_selector_palette_size; // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
|
|
|
|
// Number of helper threads to create during compression. 0=no threading.
|
|
crn_uint32 m_num_helper_threads;
|
|
|
|
// CRN userdata0 and userdata1 members, which are written directly to the header of the output file.
|
|
crn_uint32 m_userdata0;
|
|
crn_uint32 m_userdata1;
|
|
|
|
// User provided progress callback.
|
|
crn_progress_callback_func m_pProgress_func;
|
|
void* m_pProgress_func_data;
|
|
};
|
|
|
|
// Mipmap generator's mode.
|
|
enum crn_mip_mode {
|
|
cCRNMipModeUseSourceOrGenerateMips, // Use source texture's mipmaps if it has any, otherwise generate new mipmaps
|
|
cCRNMipModeUseSourceMips, // Use source texture's mipmaps if it has any, otherwise the output has no mipmaps
|
|
cCRNMipModeGenerateMips, // Always generate new mipmaps
|
|
cCRNMipModeNoMips, // Output texture has no mipmaps
|
|
|
|
cCRNMipModeTotal,
|
|
|
|
cCRNModeForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
const char* crn_get_mip_mode_desc(crn_mip_mode m);
|
|
const char* crn_get_mip_mode_name(crn_mip_mode m);
|
|
|
|
// Mipmap generator's filter kernel.
|
|
enum crn_mip_filter {
|
|
cCRNMipFilterBox,
|
|
cCRNMipFilterTent,
|
|
cCRNMipFilterLanczos4,
|
|
cCRNMipFilterMitchell,
|
|
cCRNMipFilterKaiser, // Kaiser=default mipmap filter
|
|
|
|
cCRNMipFilterTotal,
|
|
|
|
cCRNMipFilterForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
const char* crn_get_mip_filter_name(crn_mip_filter f);
|
|
|
|
// Mipmap generator's scale mode.
|
|
enum crn_scale_mode {
|
|
cCRNSMDisabled,
|
|
cCRNSMAbsolute,
|
|
cCRNSMRelative,
|
|
cCRNSMLowerPow2,
|
|
cCRNSMNearestPow2,
|
|
cCRNSMNextPow2,
|
|
|
|
cCRNSMTotal,
|
|
|
|
cCRNSMForceDWORD = 0xFFFFFFFF
|
|
};
|
|
|
|
const char* crn_get_scale_mode_desc(crn_scale_mode sm);
|
|
|
|
// Mipmap generator parameters.
|
|
struct crn_mipmap_params {
|
|
inline crn_mipmap_params() { clear(); }
|
|
|
|
inline void clear() {
|
|
m_size_of_obj = sizeof(*this);
|
|
m_mode = cCRNMipModeUseSourceOrGenerateMips;
|
|
m_filter = cCRNMipFilterKaiser;
|
|
m_gamma_filtering = true;
|
|
m_gamma = 2.2f;
|
|
// Default "blurriness" factor of .9 actually sharpens the output a little.
|
|
m_blurriness = .9f;
|
|
m_renormalize = false;
|
|
m_tiled = false;
|
|
m_max_levels = cCRNMaxLevels;
|
|
m_min_mip_size = 1;
|
|
|
|
m_scale_mode = cCRNSMDisabled;
|
|
m_scale_x = 1.0f;
|
|
m_scale_y = 1.0f;
|
|
|
|
m_window_left = 0;
|
|
m_window_top = 0;
|
|
m_window_right = 0;
|
|
m_window_bottom = 0;
|
|
|
|
m_clamp_scale = false;
|
|
m_clamp_width = 0;
|
|
m_clamp_height = 0;
|
|
}
|
|
|
|
inline bool check() const { return true; }
|
|
|
|
inline bool operator==(const crn_mipmap_params& rhs) const {
|
|
#define CRNLIB_COMP(x) \
|
|
do { \
|
|
if ((x) != (rhs.x)) \
|
|
return false; \
|
|
} while (0)
|
|
CRNLIB_COMP(m_size_of_obj);
|
|
CRNLIB_COMP(m_mode);
|
|
CRNLIB_COMP(m_filter);
|
|
CRNLIB_COMP(m_gamma_filtering);
|
|
CRNLIB_COMP(m_gamma);
|
|
CRNLIB_COMP(m_blurriness);
|
|
CRNLIB_COMP(m_renormalize);
|
|
CRNLIB_COMP(m_tiled);
|
|
CRNLIB_COMP(m_max_levels);
|
|
CRNLIB_COMP(m_min_mip_size);
|
|
CRNLIB_COMP(m_scale_mode);
|
|
CRNLIB_COMP(m_scale_x);
|
|
CRNLIB_COMP(m_scale_y);
|
|
CRNLIB_COMP(m_window_left);
|
|
CRNLIB_COMP(m_window_top);
|
|
CRNLIB_COMP(m_window_right);
|
|
CRNLIB_COMP(m_window_bottom);
|
|
CRNLIB_COMP(m_clamp_scale);
|
|
CRNLIB_COMP(m_clamp_width);
|
|
CRNLIB_COMP(m_clamp_height);
|
|
return true;
|
|
#undef CRNLIB_COMP
|
|
}
|
|
crn_uint32 m_size_of_obj;
|
|
|
|
crn_mip_mode m_mode;
|
|
crn_mip_filter m_filter;
|
|
|
|
crn_bool m_gamma_filtering;
|
|
float m_gamma;
|
|
|
|
float m_blurriness;
|
|
|
|
crn_uint32 m_max_levels;
|
|
crn_uint32 m_min_mip_size;
|
|
|
|
crn_bool m_renormalize;
|
|
crn_bool m_tiled;
|
|
|
|
crn_scale_mode m_scale_mode;
|
|
float m_scale_x;
|
|
float m_scale_y;
|
|
|
|
crn_uint32 m_window_left;
|
|
crn_uint32 m_window_top;
|
|
crn_uint32 m_window_right;
|
|
crn_uint32 m_window_bottom;
|
|
|
|
crn_bool m_clamp_scale;
|
|
crn_uint32 m_clamp_width;
|
|
crn_uint32 m_clamp_height;
|
|
};
|
|
|
|
// -------- High-level helper function definitions for CDN/DDS compression.
|
|
|
|
#ifndef CRNLIB_MIN_ALLOC_ALIGNMENT
|
|
#define CRNLIB_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2
|
|
#endif
|
|
|
|
// Function to set an optional user provided memory allocation/reallocation/msize routines.
|
|
// By default, crnlib just uses malloc(), free(), etc. for all allocations.
|
|
typedef void* (*crn_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data);
|
|
typedef size_t (*crn_msize_func)(void* p, void* pUser_data);
|
|
void crn_set_memory_callbacks(crn_realloc_func pRealloc, crn_msize_func pMSize, void* pUser_data);
|
|
|
|
// Frees memory blocks allocated by crn_compress(), crn_decompress_crn_to_dds(), or crn_decompress_dds_to_images().
|
|
void crn_free_block(void* pBlock);
|
|
|
|
// Compresses a 32-bit/pixel texture to either: a regular DX9 DDS file, a "clustered" (or reduced entropy) DX9 DDS file, or a CRN file in memory.
|
|
// Input parameters:
|
|
// comp_params is the compression parameters struct, defined above.
|
|
// compressed_size will be set to the size of the returned memory block containing the output file.
|
|
// The returned block must be freed by calling crn_free_block().
|
|
// *pActual_quality_level will be set to the actual quality level used to compress the image. May be NULL.
|
|
// *pActual_bitrate will be set to the output file's effective bitrate, possibly taking into account LZMA compression. May be NULL.
|
|
// Return value:
|
|
// The compressed file data, or NULL on failure.
|
|
// compressed_size will be set to the size of the returned memory buffer.
|
|
// Notes:
|
|
// A "regular" DDS file is compressed using normal DXTn compression at the specified DXT quality level.
|
|
// A "clustered" DDS file is compressed using clustered DXTn compression to either the target bitrate or the specified integer quality factor.
|
|
// The output file is a standard DX9 format DDS file, except the compressor assumes you will be later losslessly compressing the DDS output file using the LZMA algorithm.
|
|
// A texture is defined as an array of 1 or 6 "faces" (6 faces=cubemap), where each "face" consists of between [1,cCRNMaxLevels] mipmap levels.
|
|
// Mipmap levels are simple 32-bit 2D images with a pitch of width*sizeof(uint32), arranged in the usual raster order (top scanline first).
|
|
// The image pixels may be grayscale (YYYX bytes in memory), grayscale/alpha (YYYA in memory), 24-bit (RGBX in memory), or 32-bit (RGBA) colors (where "X"=don't care).
|
|
// RGB color data is generally assumed to be in the sRGB colorspace. If not, be sure to clear the "cCRNCompFlagPerceptual" in the crn_comp_params struct!
|
|
void* crn_compress(const crn_comp_params& comp_params, crn_uint32& compressed_size, crn_uint32* pActual_quality_level = NULL, float* pActual_bitrate = NULL);
|
|
|
|
// Like the above function, except this function can also do things like generate mipmaps, and resize or crop the input texture before compression.
|
|
// The actual operations performed are controlled by the crn_mipmap_params struct members.
|
|
// Be sure to set the "m_gamma_filtering" member of crn_mipmap_params to false if the input texture is not sRGB.
|
|
void* crn_compress(const crn_comp_params& comp_params, const crn_mipmap_params& mip_params, crn_uint32& compressed_size, crn_uint32* pActual_quality_level = NULL, float* pActual_bitrate = NULL);
|
|
|
|
// Transcodes an entire CRN file to DDS using the crn_decomp.h header file library to do most of the heavy lifting.
|
|
// The output DDS file's format is guaranteed to be one of the DXTn formats in the crn_format enum.
|
|
// This is a fast operation, because the CRN format is explicitly designed to be efficiently transcodable to DXTn.
|
|
// For more control over decompression, see the lower-level helper functions in crn_decomp.h, which do not depend at all on crnlib.
|
|
void* crn_decompress_crn_to_dds(const void* pCRN_file_data, crn_uint32& file_size);
|
|
|
|
// Decompresses an entire DDS file in any supported format to uncompressed 32-bit/pixel image(s).
|
|
// See the crnlib::pixel_format enum in inc/dds_defs.h for a list of the supported DDS formats.
|
|
// You are responsible for freeing each image block, either by calling crn_free_all_images() or manually calling crn_free_block() on each image pointer.
|
|
struct crn_texture_desc {
|
|
crn_uint32 m_faces;
|
|
crn_uint32 m_width;
|
|
crn_uint32 m_height;
|
|
crn_uint32 m_levels;
|
|
crn_uint32 m_fmt_fourcc; // Same as crnlib::pixel_format
|
|
};
|
|
bool crn_decompress_dds_to_images(const void* pDDS_file_data, crn_uint32 dds_file_size, crn_uint32** ppImages, crn_texture_desc& tex_desc);
|
|
|
|
// Frees all images allocated by crn_decompress_dds_to_images().
|
|
void crn_free_all_images(crn_uint32** ppImages, const crn_texture_desc& desc);
|
|
|
|
// -------- crn_format related helpers functions.
|
|
|
|
// Returns the FOURCC format equivalent to the specified crn_format.
|
|
crn_uint32 crn_get_format_fourcc(crn_format fmt);
|
|
|
|
// Returns the crn_format's bits per texel.
|
|
crn_uint32 crn_get_format_bits_per_texel(crn_format fmt);
|
|
|
|
// Returns the crn_format's number of bytes per block.
|
|
crn_uint32 crn_get_bytes_per_dxt_block(crn_format fmt);
|
|
|
|
// Returns the non-swizzled, basic DXTn version of the specified crn_format.
|
|
// This is the format you would supply D3D or OpenGL.
|
|
crn_format crn_get_fundamental_dxt_format(crn_format fmt);
|
|
|
|
// -------- String helpers.
|
|
|
|
// Converts a crn_file_type to a string.
|
|
const char* crn_get_file_type_ext(crn_file_type file_type);
|
|
|
|
// Converts a crn_format to a string.
|
|
const char* crn_get_format_string(crn_format fmt);
|
|
|
|
// Converts a crn_dxt_quality to a string.
|
|
const char* crn_get_dxt_quality_string(crn_dxt_quality q);
|
|
|
|
// -------- Low-level DXTn 4x4 block compressor API
|
|
|
|
// crnlib's DXTn endpoint optimizer actually supports any number of source pixels (i.e. from 1 to thousands, not just 16),
|
|
// but for simplicity this API only supports 4x4 texel blocks.
|
|
typedef void* crn_block_compressor_context_t;
|
|
|
|
// Create a DXTn block compressor.
|
|
// This function only supports the basic/nonswizzled "fundamental" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX.
|
|
// Avoid calling this multiple times if you intend on compressing many blocks, because it allocates some memory.
|
|
crn_block_compressor_context_t crn_create_block_compressor(const crn_comp_params& params);
|
|
|
|
// Compresses a block of 16 pixels to the destination DXTn block.
|
|
// pDst_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others).
|
|
// pPixels should be an array of 16 crn_uint32's. Each crn_uint32 must be r,g,b,a (r is always first) in memory.
|
|
void crn_compress_block(crn_block_compressor_context_t pContext, const crn_uint32* pPixels, void* pDst_block);
|
|
|
|
// Frees a DXTn block compressor.
|
|
void crn_free_block_compressor(crn_block_compressor_context_t pContext);
|
|
|
|
// Unpacks a compressed block to pDst_pixels.
|
|
// pSrc_block should be 8 (for DXT1/DXT5A) or 16 bytes (all the others).
|
|
// pDst_pixel should be an array of 16 crn_uint32's. Each uint32 will be r,g,b,a (r is always first) in memory.
|
|
// crn_fmt should be one of the "fundamental" formats: DXT1, DXT3, DXT5, DXT5A, DXN_XY and DXN_YX.
|
|
// The various swizzled DXT5 formats (such as cCRNFmtDXT5_xGBR, etc.) will be unpacked as if they where plain DXT5.
|
|
// Returns false if the crn_fmt is invalid.
|
|
bool crn_decompress_block(const void* pSrc_block, crn_uint32* pDst_pixels, crn_format crn_fmt);
|
|
|
|
#endif // CRNLIB_H
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// crnlib uses the ZLIB license:
|
|
// http://opensource.org/licenses/Zlib
|
|
//
|
|
// Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
//
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
//
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
//
|
|
//------------------------------------------------------------------------------
|