v1.03 prerelease - Full Linux port of crnlib/crunch, in progress - still more testing to do, and some cmd line options (such as -timestamp) don't work under linux yet, but the core stuff (compression/decompression/transcoding) should work fine and performance under Linux is comparable to Windows. The 3 examples haven't been ported yet.

This commit is contained in:
richgel99@gmail.com
2012-04-26 07:14:21 +00:00
parent fffd983ffa
commit f63e26aee6
89 changed files with 3547 additions and 3829 deletions
+143 -66
View File
@@ -2,18 +2,25 @@
// Copyright (c) 2010-2012 Rich Geldreich and Tenacious Software LLC
// See copyright notice and license at the end of this file.
//
// This header file contains the public crnlib declarations for DXTn and
// clustered DXTn compression/decompression.
// 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
// The crn_decomp.h header file library contains all the code necessary for
// decompression.
//
#ifndef CRNLIB_H
#define CRNLIB_H
#define CRNLIB_VERSION 101
#ifdef _MSC_VER
#pragma warning (disable: 4127) // conditional expression is constant
#endif
#define CRNLIB_VERSION 103
#define CRNLIB_SUPPORT_ATI_COMPRESS 0
#define CRNLIB_SUPPORT_SQUISH 0
typedef unsigned char crn_uint8;
typedef unsigned short crn_uint16;
@@ -28,7 +35,7 @@ enum crn_file_type
{
// .CRN
cCRNFileTypeCRN = 0,
// .DDS using regular DXT or clustered DXT
cCRNFileTypeDDS,
@@ -36,21 +43,21 @@ enum crn_file_type
};
// Supported compressed pixel formats.
// Basically all the standard DX9 formats, with some swizzled DXT5 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
@@ -58,7 +65,7 @@ enum crn_format
cCRNFmtDXT5_AGBR, // Swizzled 4-component
// ATI 3DC and X360 DXN
cCRNFmtDXN_XY,
cCRNFmtDXN_XY,
cCRNFmtDXN_YX,
// DXT5 alpha blocks only
@@ -72,7 +79,7 @@ enum crn_format
// Various library/file format limits.
enum crn_limits
{
// Max. mipmap level resolution on any axis (will be doubled to 8k in next release).
// Max. mipmap level resolution on any axis.
cCRNMaxLevelResolution = 4096,
cCRNMinPaletteSize = 8,
@@ -91,27 +98,27 @@ enum crn_limits
// See the m_flags member in the crn_comp_params struct, below.
enum crn_comp_flags
{
// Enables perceptual colorspace distance metrics if set.
// 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,
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
// 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,
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.
// 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.
// Currently only used when writing to .DDS files, as .CRN uses only a subset of the possible DXTn block types.
// Default: Set.
cCRNCompFlagUseBothBlockTypes = 8,
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.
@@ -120,12 +127,12 @@ enum crn_comp_flags
// Disables endpoint caching, for more deterministic output.
// Currently only used when writing to .DDS files.
// Default: Not set.
cCRNCompFlagDisableEndpointCaching = 32,
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,
@@ -136,7 +143,7 @@ enum crn_comp_flags
// 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,
@@ -158,19 +165,27 @@ enum crn_dxt_quality
cCRNDXTQualityForceDWORD = 0xFFFFFFFF
};
// Which DXTn compressor to use when compressing to .DDS.
// Which DXTn compressor to use when compressing to plain (non-clustered) .DDS.
enum crn_dxt_compressor_type
{
cCRNDXTCompressorCRN,
cCRNDXTCompressorCRNF,
cCRNDXTCompressorRYG,
cCRNDXTCompressorCRN, // Use crnlib's DXTc block compressor (default, highest quality, comparable or better than ati_compress or squish)
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
};
// Compression will stop prematurely (and fail) if the callback returns false.
// 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);
@@ -180,6 +195,7 @@ struct crn_comp_params
{
inline crn_comp_params() { clear(); }
// Clear struct to default parameters.
inline void clear()
{
m_size_of_obj = sizeof(*this);
@@ -216,6 +232,43 @@ struct crn_comp_params
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
{
@@ -244,16 +297,16 @@ struct crn_comp_params
// 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
@@ -261,20 +314,20 @@ struct crn_comp_params
// 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
// 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
// disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and try again. This process can be pretty slow.
// try disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and redo the search. This process can be pretty slow.
float m_target_bitrate;
// Desired quality level.
// 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;
@@ -288,7 +341,7 @@ struct crn_comp_params
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 to assist the compressor. 0=no threading.
// 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.
@@ -303,18 +356,18 @@ struct crn_comp_params
// Mipmap generator's mode.
enum crn_mip_mode
{
cCRNMipModeUseSourceOrGenerateMips,
cCRNMipModeUseSourceMips,
cCRNMipModeGenerateMips,
cCRNMipModeNoMips,
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 wchar_t* crn_get_mip_mode_desc(crn_mip_mode m);
const wchar_t* crn_get_mip_mode_name(crn_mip_mode m);
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
@@ -323,7 +376,7 @@ enum crn_mip_filter
cCRNMipFilterTent,
cCRNMipFilterLanczos4,
cCRNMipFilterMitchell,
cCRNMipFilterKaiser,
cCRNMipFilterKaiser, // Kaiser=default mipmap filter
cCRNMipFilterTotal,
@@ -347,8 +400,8 @@ enum crn_scale_mode
cCRNSMForceDWORD = 0xFFFFFFFF
};
const wchar_t* crn_get_scale_mode_desc(crn_scale_mode sm);
const char* crn_get_scale_mode_desc(crn_scale_mode sm);
// Mipmap generator parameters.
struct crn_mipmap_params
{
@@ -361,6 +414,7 @@ struct crn_mipmap_params
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;
@@ -383,19 +437,45 @@ struct crn_mipmap_params
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;
@@ -440,11 +520,11 @@ void crn_free_block(void *pBlock);
// 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.
// 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), grayscale/alpha (YYYA), 24-bit RGBX, or 32-bit RGBA colors (where "X"=don't care).
// 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);
@@ -453,15 +533,15 @@ void *crn_compress(const crn_comp_params &comp_params, crn_uint32 &compressed_si
// 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.
// 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 in inc/dds_defs.h for a list of the supported DDS formats.
// You are responsible for freeing each image, either by calling crn_free_all_images() or manually calling crn_free_block() on each image pointer.
// 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;
@@ -493,16 +573,13 @@ crn_format crn_get_fundamental_dxt_format(crn_format fmt);
// -------- String helpers.
// Converts a crn_file_type to a string.
const wchar_t* crn_get_file_type_ext(crn_file_type file_type);
const char* crn_get_file_type_exta(crn_file_type file_type);
const char* crn_get_file_type_ext(crn_file_type file_type);
// Converts a crn_format to a string.
const char* crn_get_format_stringa(crn_format fmt);
const wchar_t* crn_get_format_string(crn_format fmt);
const char* crn_get_format_string(crn_format fmt);
// Converts a crn_dxt_quality to a string.
const wchar_t* crn_get_dxt_quality_string(crn_dxt_quality q);
const char* crn_get_dxt_quality_stringa(crn_dxt_quality q);
const char* crn_get_dxt_quality_string(crn_dxt_quality q);
// -------- Low-level DXTn 4x4 block compressor API
@@ -530,15 +607,15 @@ void crn_free_block_compressor(crn_block_compressor_context_t pContext);
// http://opensource.org/licenses/Zlib
//
// Copyright (c) 2010-2012 Rich Geldreich and Tenacious Software 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