├── .editorconfig ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── include └── tiny_imageformat │ ├── tinyimageformat.h │ ├── tinyimageformat_apis.h │ ├── tinyimageformat_base.h │ ├── tinyimageformat_bits.h │ ├── tinyimageformat_decode.h │ ├── tinyimageformat_encode.h │ └── tinyimageformat_query.h ├── src ├── decodehelpers.h ├── doc.h ├── dummy.c ├── encodehelpers.h ├── formatgen.cpp ├── formatgen.h ├── formatgen_apis.cpp ├── formatgen_base.cpp ├── formatgen_decode.cpp ├── formatgen_encode.cpp ├── formatgen_func.h ├── formatgen_macros.h ├── formatgen_query.cpp └── queryhelpers.h └── tests ├── runner.cpp └── test_formatcracker.cpp /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*.{c,cpp,h,hpp}] 5 | indent_style = tab 6 | indent_size = 2 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12.4) 2 | get_directory_property(hasParent PARENT_DIRECTORY) 3 | if(NOT hasParent) 4 | option(unittests "unittests" OFF) 5 | get_filename_component(_PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) 6 | set_property(GLOBAL PROPERTY GLOBAL_FETCHDEPS_BASE ${_PARENT_DIR}/al2o3 ) 7 | include(FetchContent) 8 | FetchContent_Declare( al2o3 GIT_REPOSITORY https://github.com/DeanoC/al2o3 GIT_TAG master ) 9 | FetchContent_GetProperties(al2o3) 10 | if(NOT al2o3_POPULATED) 11 | FetchContent_Populate(al2o3) 12 | add_subdirectory(${al2o3_SOURCE_DIR} ${al2o3_BINARY_DIR}) 13 | endif() 14 | INIT_AL2O3(${CMAKE_CURRENT_SOURCE_DIR}) 15 | endif () 16 | 17 | SET_MIN_VERSIONS() 18 | set(LibName tiny_imageformat) 19 | project(${LibName}) 20 | 21 | set(MAKE_GENERATOR TRUE) 22 | if(MAKE_GENERATOR) 23 | set(GeneratorSrc 24 | src/formatgen.cpp 25 | src/formatgen_base.cpp 26 | src/formatgen_apis.cpp 27 | src/formatgen_query.cpp 28 | src/formatgen_decode.cpp 29 | src/formatgen_encode.cpp 30 | src/formatgen.h 31 | src/formatgen_func.h 32 | src/formatgen_macros.h 33 | 34 | src/queryhelpers.h 35 | src/decodehelpers.h 36 | src/encodehelpers.h 37 | 38 | src/doc.h 39 | ) 40 | 41 | set(GeneratorDeps 42 | al2o3_platform 43 | al2o3_cmath 44 | al2o3_os 45 | al2o3_vfile 46 | ) 47 | ADD_CONSOLE_APP(generate_${LibName} "${GeneratorSrc}" "${GeneratorDeps}") 48 | endif() 49 | 50 | set(Interface 51 | tinyimageformat_base.h 52 | tinyimageformat_apis.h 53 | tinyimageformat_bits.h 54 | tinyimageformat_decode.h 55 | tinyimageformat_encode.h 56 | tinyimageformat_query.h 57 | ) 58 | set(Src 59 | dummy.c) 60 | 61 | set(Deps 62 | ) 63 | ADD_LIB(${LibName} "${Interface}" "${Src}" "${Deps}") 64 | 65 | set( Tests 66 | runner.cpp 67 | test_formatcracker.cpp 68 | ) 69 | set( TestDeps 70 | al2o3_catch2 71 | utils_simple_logmanager 72 | ) 73 | ADD_LIB_TESTS(${LibName} "${Interface}" "${Tests}" "${TestDeps}") 74 | 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 DeanoC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TinyImageFormat 2 | 3 | TinyImageFormat is a library implementing the common image pixel formats that are used in real-time graphics. 4 | Whilst it provides a enumeration style image format, similar to Vulkan, D3D and Metal is also exposes many other useful information about each format. As well as information it provides functions to decode and encode most formats giving a single library capable of handling many image format you might encounter. 5 | 6 | It currently supports image format with up to 4 channels. It has both logical (you ask for Red) or physical (you ask for Channel 0) functions. Most users will want to use logical channels, as it handles all swizzling and constants automatically. Channels are supported up to 64 bit integers and floating point (doubles). It is fixed at Little Endian only, as this is the only machines its currently built for. 7 | 8 | It is available as a single header or as several smaller ones. The functionality is exactly the same its purely your own preference which to use. The files you include are generated by a custom code generator that takes a description of each format, generates a 64 bit descriptor code and then creates the header from that. 9 | 10 | Just copy over include/tinyimageformat/tinyimageformat.h or the multi version of it into you project and thats its. The Source folder in this repo is purely the code generator, you never need it unless you want to add your own formats and functions. 11 | 12 | The multiple header version is split into several related sections, wheres the single header has them all together. The sections are 13 | * Base - basic enumerations and structure 14 | * Query - query infomation about a image format 15 | * Apis - helpers for the main real-time 3D libraries (Vulkan, D3D and metal) 16 | * Decode - Functions to decode pixel data from an image format 17 | * Encode - Functions to encode pixel data from an image format 18 | 19 | ## API Overview 20 | All types and function are prefixed by _TinyImageFormat_ or _TIF_ as a form of namespaces, these will be left off for the API documentation. 21 | 22 | The basic unit is the block, each image format has a 3D size that represents the smallest quantum of data you can work with. For basic image formats this is a 1x1x1 pixel block, meaning you can encode and decode single pixels of the image. However many other image formats have blocks larger than this. The DXBC formats are all 4x4x1 as thats the size of the compressed data. The smallest quantum you can encode or decode is a 4x4 pixel block. 23 | 24 | Another common use of blocks is to pack non machine word aligned image format (like 1 bit per pixel images) and also pixel format with different frequency (I.e 4:2:0 video formats, that store channels at different rates). 25 | 26 | The smallest unit the API uses is an 8 bit byte, smaller formats either have large block size or multiple channels are packed together to 8 or more bits. 27 | 28 | 29 | ## Base 30 | 31 | The base section has the main enumeration simply called _TinyImageFormat_. Here these is _TinyImageFormat_Count_ values, with each being a different image format. Internally image formats are split into ‘namespaces’ which are used to seperate very different types of image format, whilst this doesn’t technically affect the _TinyImageFormat_ naming, its usually possible to see parts of it (I.e. ASTC is a namespace and all ASTC pixel formats have ASTC in the name). 32 | 33 | ## Query Functions 34 | * Code - uint64_t with the internal descriptor code 35 | * Name - Human C string with the name of this fmt 36 | * FromName - lookup the format given the name as a C String (fast) 37 | * IsDepthOnly - true if just a depth channel 38 | * IsStencilOnly - true if just a stencil channel 39 | * IsDepthAndStencil - if has both depth and stencil channel 40 | * IsCompressed - true if its a compressed format (aka block) 41 | * IsCLUT - true if data is index into a CLUT (Colour Look Up Table) 42 | * IsFloat - is the data in floating point 43 | * IsNormalised - return true if data will be within 0 to 1 or -1 to 1 44 | * IsSigned - does the data include negatives 45 | * IsSRGB - is the data encoded using sRGB non linear encoding 46 | * IsHomogenous - is the encoding the same for every channel 47 | * WidthOfBlock - How many pixels in the x dimension for a block 48 | * HeightOfBlock - How many pixels in the y dimension for a block 49 | * DepthOfBlock - How many pixels in the z dimension for a block 50 | * PixelCountOfBlock - How many pixels in total for a block 51 | * BitSizeOfBlock - How big in bits is a single block. 52 | * ChannelCount - How many channels are actually encoded 53 | 54 | ## Decode Functions 55 | X suffix can be F for floats or D for doubles 56 | * CanDecodeLogicalPixelsX - Can DecodeLogicalPixelsX work with this format? 57 | * DecodeLogicalPixelsX( width in blocks, FetchInput, out pixels) 58 | 59 | Pixels should be a pointer to 4 * PixelCounfOfBlack float/doubles does full decode and remapping into logical channels include constants. 60 | 61 | Returned result can be used directly as RGBA floating point data 62 | 63 | Input pointers are updated are used, so can be passed back in for next set of pixel decoding if desired. 64 | 65 | For CLUT formats in.pixel should be the packed pixel data and in.lut is the lookuptable in R8G8B8A8 format of 2^Pbits entries 66 | 67 | For all others in.pixel should be the packed pixel data 68 | 69 | ## Encode Functions 70 | X suffix can be F for floats or D for doubles 71 | * CanEncodeLogicalPixelsX - Can EncodeLogicalPixelsX work with this format? 72 | * EncodeLogicalPixelsX( width in blocks, in pixels, PutOutput) 73 | 74 | Pixels should be a pointer to 4 * PixelCounfOfBlack float/doubles 75 | 76 | It does full encode and remapping into logical channels 77 | 78 | Output pointers are updated are used, so can be passed back in for next set of pixel encoding if desired. 79 | 80 | out.pixel is where colour information should be stored 81 | 82 | ## Pack namespace details 83 | Most image formats come from the Pack namespace which allows pixel ranging from a single bit to 256 bit to be described. Packed formats have 1 to 4 channels, arbitary swizzling and support for constant 0 and 1. Pack enumeration names are read left to right, with the leftmost element being the lowest bits in the pixel, incrementing as you scan right across the name. The following a channel name is the number of bits that channel is encoded with. 84 | 85 | E.g 86 | 87 | _R8G8B8A8_ 88 | 89 | Red channel is 8 bits from the 0 to 7th bits of a 32 bit unsigned integer. Red = (P >> 0) & 0xFF 90 | 91 | Green channel is 8 bits from the 8 to 15th bits of a 32 bit unsigned integer. Green = (P >> 8) & 0xFF 92 | 93 | Blue channel is 8 bits from the 16 to 23rd bits of a 32 bit unsigned integer. Blue = (P >> 16) & 0xFF 94 | 95 | Alpha channel is 8 bits from the 24 to 32nd bits of a 32 bit unsigned integer. Alpha = (P >> 24) & 0xFF 96 | 97 | _A8B8G8R8_ 98 | 99 | Red channel is 8 bits from the 24 to 32nd bits of a 32 bit unsigned integer. Red = (P >> 24) & 0xFF 100 | 101 | Green channel is 8 bits from the 16 to 23rd bits of a 32 bit unsigned integer. Green = (P >> 16) & 0xFF 102 | 103 | Blue channel is 8 bits from the 8 to 16th bits of a 32 bit unsigned integer. Blue = (P >> 8) & 0xFF 104 | 105 | Alpha channel is 8 bits from the 0 to 7th bits of a 32 bit unsigned integer. Alpha = (P >> 0) & 0xFF 106 | 107 | Each packed channel also has a type, in almost every packed image format this is the same for all channels and in the case the type is specified just once at the end of the name, in the multiple type case the name is after the bit size for each channel 108 | Types are 109 | * _UNORM_ - decoded values are between 0 and 1 110 | * _SNORM_ - decoded values are between -1 and 1 111 | * _UINT_ - decoded values are between 0 and 2^bits-1 112 | * _SINT_ - decoded values are between -2^(bits-1) and 2^(bits-1)-1 113 | * _UFLOAT_ - decoded values are positive floating point numbers 114 | * _SFLOAT_ - decoded values are signed float points numbers 115 | * _SBFLOAT_ - decode value is a 32 bit float with lower 16 mantissa bits being 0 (Brain Floats) 116 | 117 | E.g. 118 | 119 | _R8G8B8A8_UNORM_ - each channel is decoded to a normalised 0 to 1 120 | 121 | _R8_UNORM_G8_SNORM_ - would be R channel decoded 0 to 1 and a G channel decoded to -1 to 1 122 | 123 | Pack namespace formats have a block size of 1x1x1 in most cases, exceptions being the formats that are less than 8 bits. For these multiple pixels are packed up to an 8 bit byte. 124 | 125 | E.g. 126 | 127 | _R4G4_ is an 8 bit byte encoding 2 4 bit channels (block size of 1x1x1) 128 | 129 | _R1_ is an 8 bit byte encoding 8 pixels together (block size of 8x1x1) 130 | 131 | ## Examples 132 | 133 | To write a Red and Alpha pixel to an R16G16B16A16_SFLOAT pixel image, the code below would work 134 | ``` 135 | TinyImageFormat_EncodeOutput output { destinationPtr }; 136 | float const redAlphaPixel[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; 137 | TinyImageFormat_EncodeLogicalPixelsF(TinyImageFormat_R16G16B16A16_SFLOAT, redAlphaPixel, 1, &output); 138 | ``` 139 | 140 | The read the pixel back 141 | ``` 142 | TinyImageFormat_DecodeInput input { destinationPtr }; 143 | float result[4]; 144 | TinyImageFormat_DecodeLogicalPixelsF(TinyImageFormat_R16G16B16A16_SFLOAT, &input, 1, result); 145 | ``` 146 | 147 | To query if the format is floating point (it would return true). 148 | ``` 149 | TinyImageFormat_IsFloat(TinyImageFormat_R16G16B16A16_SFLOAT); 150 | ``` 151 | 152 | -------------------------------------------------------------------------------- /include/tiny_imageformat/tinyimageformat_base.h: -------------------------------------------------------------------------------- 1 | // Auto generated by formatgen on Oct 22 2019 2 | #pragma once 3 | #if !defined(TINYIMAGEFORMAT_BASE_H_) && !defined(TINYIMAGEFORMAT_IMAGEFORMAT_H) 4 | #define TINYIMAGEFORMAT_BASE_H_ 1 5 | 6 | /* TinyImageFormat is a library about the encodings of pixels typically 7 | * encountered in real time graphics. 8 | * 9 | * Like modern graphics API it is enumeration based but it also provides an API 10 | * for reasoning about that enumeration programmatically. 11 | * 12 | * Additionally it provide ways of accessing pixels encoded in the specified 13 | * format for most pixel formats. The hope is eventually to get decode to 100% 14 | * but not there yet (119 out of 193 currently). 15 | * This allows you to effectively read/write a large amount of image data. 16 | * 17 | * To assist with working with graphics APIs converters to and from Vulkan, 18 | * D3D12 and Metal. These are self contained and do not require the actual APIs. 19 | * 20 | * Available as either a single header or a version made of 6 headers split into 21 | * functional groups. Use one style or the other but they don't mix. 22 | * 23 | * These files are large due to unrolling and large switches. Functions are 24 | * inlined, allowing the compiler to eliminate and collapse when possible, 25 | * however particularly the Encode/Decode functions aren't near as fast as they 26 | * could be if heavily optimised for specific formats/layouts. 27 | * 28 | * Whilst not optimal due to number of formats it supports, it intends to be 29 | * fast enough that in many cases it will be fine. 30 | * 31 | * Internally every format has a descriptor packed into a 64 bit code word. 32 | * This code word is used to generate the header and it isn't used by the API 33 | * itself, as its been 'burnt' out by the code generator but it can be used at 34 | * runtime if desired and in future its intended to be used for exotic packed 35 | * formats that don't get there own enumeration value but can be expressed 36 | * via a descriptor. 37 | * 38 | * Where possible for C++ users functions are constexpr. 39 | * 40 | * It is MIT licensed and borrows/builds on code/specs including but not 41 | * limited to 42 | * Microsoft's Chris Walbourn DXTextureTool 43 | * Rygerous public domain Half to float (and vice versa) code 44 | * Khronos DFD specifications 45 | * Khronos Vulkan Specification 46 | * Microsoft D3D11/D3D12 Specifications 47 | * Apple Metal documentation 48 | * DDS Loaders from various sources (Humus, Confetti FX, DXTextureTool) 49 | * 50 | * TODO 51 | * ---- 52 | * Test CLUT formats and add encode clause 53 | * Add shared component i.e. G8R8G8B8 4:2:x formats 54 | * Add Multi plane formats 55 | * Add compressed format decoders 56 | * Add Block copy (for updating compressed formats) 57 | * Add functions that work on descriptor codes directly 58 | * Add UFLOAT 6 and 7 bit support 59 | * Optional SIMD decode/encode functions 60 | * More tests 61 | * 62 | * Definitions 63 | * ----------- 64 | * 65 | * Pixel 66 | * We define a pixel as upto 4 channels representing a single 'colour' 67 | * Its may not be addressable directly but as blocks of related pixels. 68 | * When decode/encoding pixels are presented to the API as 4 floats or doubles. 69 | * 70 | * Logical Channels (TinyImageFormat_LogicalChannel) 71 | * Logical channel are the usual way you would ask for a particular channel, 72 | * so asking about LC_Red while get you data for the red channel, however its 73 | * actually physically encoded in the data. 74 | * 75 | * Physical Channels (TinyImageFormat_PhysicalChannel) 76 | * Physical channels are the inverse of logical channels, that have no meaning 77 | * beyond the position in the data itself. 78 | * 79 | * Both Logical and Physical channels support returning constant 0 or 1 80 | * 81 | * Blocks 82 | * A block is the smallest addressable element this format refers to. Blocks 83 | * have up to 3 dimensions (though no format currently uses the 3rd). 84 | * Blocks are always at least byte aligned. 85 | * For single pixel formats this will be 1x1x1. For something like R1 it would 86 | * be 8x1x1 (8 single bits for 8 pixels). 87 | * For block compressed format a common value is 4x4x1. 88 | * A block for shared channels or very tightly packed this is how many pixels 89 | * are combined into one addressable unit. 90 | * 91 | * API 92 | * --- 93 | * The primary enumeration is simply TinyImageFormat, everything else supports 94 | * this enum. 95 | * All functions, enums etc. are prefixed with TinyImageFormat_, All functions 96 | * also take the format as first parameter. These are often removed in the api 97 | * docs to save space. 98 | * 99 | * Defines 100 | * ------- 101 | * TinyImageFormat_Count - how many formats in total 102 | * TinyImageFormat_MaxPixelCountOfBlock - maximum number of pixels in a block 103 | * - for any format (for static decode buffer allocation) 104 | * 105 | * Enums 106 | * ----- 107 | * TinyImageFormat - Count entries, one for each format supported 108 | * LogicalChannel - values for logical channel or constants 109 | * - LC_Red - Red channel is specified 110 | * - LC_Green - Green channel is specified 111 | * - LC_Blue - Blue channel is specified 112 | * - LC_Alpha - Alpha channel is specified 113 | * - LC_Depth - Depth channel is specified 114 | * - LC_Stencil - Stencil channel is specified 115 | * - LC_1 - constant 1 will be returned 116 | * - LC_0 - constant 0 will be return 117 | * PhysicalChannel - values for physical channel or constants 118 | * - PC_0 - Leftmost channel 119 | * - PC_1 - 2nd channel 120 | * - PC_2 - 3rd channel 121 | * - PC_3 - 4th channel 122 | * - PC_CONST_1 - constant 1 will be returned 123 | * - PC_CONST_0 - constant 0 will be return 124 | * 125 | * Structs 126 | * ------- 127 | * TinyImageFormat_DecodeInput 128 | * - pixel or pixelPlane0 - pixel data ptr or pixel data ptr for plane 0 129 | * - lut or pixelPlane1 - Look Up Table ptr for CLUT formats or pixel plane 1 130 | * - pixelPlane2 to pixelPlane 9 - 7 more planes ptrs 131 | * TinyImageFormat_EncodeOutput 132 | * - pixel or pixelPlane0 - pixel data ptr or pixel data ptr for plane 0 133 | * - pixelPlane2 to pixelPlane 9 - 8 more planes ptrs 134 | 135 | * Query Functions 136 | * ----------- 137 | * Code - uint64_t with the internal descriptor code 138 | * Name - Human C string with the name of this fmt 139 | * FromName - lookup the format given the name as a C String (fast) 140 | * IsDepthOnly - true if just a depth channel 141 | * IsStencilOnly - true if just a stencil channel 142 | * IsDepthAndStencil - if has both depth and stencil channel 143 | * IsCompressed - true if its a compressed format (aka block) 144 | * IsCLUT - true if data is index into a CLUT (Colour Look Up Table) 145 | * IsFloat - is the data in floating point 146 | * IsNormalised - return true if data will be within 0 to 1 or -1 to 1 147 | * IsSigned - does the data include negatives 148 | * IsSRGB - is the data encoded using sRGB non linear encoding 149 | * IsHomogenous - is the encoding the same for every channel 150 | * WidthOfBlock - How many pixels in the x dimension for a block 151 | * HeightOfBlock - How many pixels in the y dimension for a block 152 | * DepthOfBlock - How many pixels in the z dimension for a block 153 | * PixelCountOfBlock - How many pixels in total for a block 154 | * BitSizeOfBlock - How big in bits is a single block. 155 | * ChannelCount - How many channels are actually encoded 156 | * 157 | * Logical Channel Functions 158 | * ------------------------- 159 | * ChannelBitWidth( logical channel ) - how wide in bits is the channel 160 | * Min( logical channel ) - minimum possible value for the channel 161 | * Max( logical channel ) - maximum possible value for the channel 162 | * LogicalChannelToPhysical( logical channel ) 163 | * - what physical channel is the logical channel stored in 164 | * - or constant 0 or 1 if its not physically stored 165 | * 166 | * Pixel Decoder Functions (X = F or D version, use F if possible as its faster) 167 | * ----------------------- 168 | * CanDecodeLogicalPixelsX - Can DecodeLogicalPixelsX work with this format? 169 | * DecodeLogicalPixelsX( width in blocks, FetchInput, out pixels) 170 | * - pixels should be a pointer to 4 * PixelCounfOfBlack float/doubles 171 | * - does full decode and remapping into logical channels include constants. 172 | * - Returned result can be used directly as RGBA floating point data 173 | * - Input pointers are updated are used, so can be passed back in for 174 | * - next set of pixel decoding if desired. 175 | * - For CLUT formats in.pixel should be the packed pixel data and in.lut is 176 | * - the lookuptable in R8G8B8A8 format of 2^Pbits entries 177 | * - For all others in.pixel should be the packed pixel data 178 | * Pixel Decoder Helper Functions 179 | * ----------------------- 180 | * UFloat6AsUintToFloat - returns the value stored as a 6 bit UFloat 181 | * UFloat7AsUintToFloat - returns the value stored as a 7 bit UFloat 182 | * UFloat10AsUintToFloat - returns the value stored as a 10 bit UFloat 183 | * UFloat11AsUintToFloat - returns the value stored as a 11 bit UFloat 184 | * SharedE5B9G9R9UFloatToFloats - return the pixel stored in shared 185 | * - shared 5 bit exponent, 9 bit mantissa for RGB 186 | * HalfAsUintToFloat - returns the value stored as a 16 bit SFloat 187 | * BFloatAsUintToFloat - returns the value stored as a 16 bit BFloat 188 | * LookupSRGB - returns the value for an 8 bit sRGB encoded value 189 | * 190 | * Pixel Encoder Functions (X = F or D version, use F if possible as its faster) 191 | * ----------------------- 192 | * CanEncodeLogicalPixelsX - Can EncodeLogicalPixelsX work with this format? 193 | * EncodeLogicalPixelsX( width in blocks, in pixels, PutOutput) 194 | * - pixels should be a pointer to 4 * PixelCounfOfBlack float/doubles 195 | * - does full encode and remapping into logical channels 196 | * - Output pointers are updated are used, so can be passed back in for 197 | * - next set of pixel encoding if desired. 198 | * - out.pixel is where colour information should be stored 199 | * 200 | * Pixel Encoder Helper Functions 201 | * ----------------------- 202 | * FloatToUFloat6AsUint - Encodes float into a 6 bit UFloat 203 | * FloatToUFloat7AsUint - Encodes float into a 7 bit UFloat 204 | * FloatToUFloat10AsUint - Encodes float into a 10 bit UFloat 205 | * FloatToUFloat11AsUint - Encodes float into 11 bit UFloat 206 | * FloatRGBToRGB9E5AsUint32 - Encodes a float RGB into RGB9E5 207 | * FloatToHalfAsUint - Encodes a float into a 16 bit SFloat 208 | * FloatToBFloatAsUint - Encodes a float into a 16 bit BFloat 209 | * FloatToSRGB - encodes a float to sRGB assuming input is 0-1 210 | * 211 | * Physical Channel Functions (in general use the Logical Channels) 212 | * ------------------ 213 | * ChannelBitWidthAtPhysical( phys channel ) - how wide in bits for this channel 214 | * MinAtPhysical( phys channel ) - min possible value for this channel 215 | * MaxAtPhysical( phys channel ) - max possible value for this channel 216 | * PhysicalChannelToLogical(phys channel) 217 | * - what logical channel does a physical channel map to. 218 | * - Or a constant 0 or 1 219 | * 220 | * Graphics API Functions 221 | * ------------------ 222 | * FromVkFormat( VkFormat ) - converts from or UNDEFINED if not possible 223 | * ToVkFormat - converts to or VK_FORMAT_UNDEFINED if not possible 224 | * FromDXGI_FORMAT( DXGI_FORMAT) converts from or UNDEFINED if not possible 225 | * ToDXGI_FORMAT - converts to or DXGI_FORMAT_UNKNOWN if not possible 226 | * DXGI_FORMATToTypeless - returns the DXGI typeless format if possible 227 | * FromMetal( MTLPixelFormat ) - converts from or UNDEFINED if not possible 228 | * ToMetal - converts to or MTLPixelFormatInvalid if not possible 229 | * 230 | * 231 | */ 232 | typedef enum TinyImageFormat { 233 | TinyImageFormat_UNDEFINED = 0, 234 | TinyImageFormat_R1_UNORM = 1, 235 | TinyImageFormat_R2_UNORM = 2, 236 | TinyImageFormat_R4_UNORM = 3, 237 | TinyImageFormat_R4G4_UNORM = 4, 238 | TinyImageFormat_G4R4_UNORM = 5, 239 | TinyImageFormat_A8_UNORM = 6, 240 | TinyImageFormat_R8_UNORM = 7, 241 | TinyImageFormat_R8_SNORM = 8, 242 | TinyImageFormat_R8_UINT = 9, 243 | TinyImageFormat_R8_SINT = 10, 244 | TinyImageFormat_R8_SRGB = 11, 245 | TinyImageFormat_B2G3R3_UNORM = 12, 246 | TinyImageFormat_R4G4B4A4_UNORM = 13, 247 | TinyImageFormat_R4G4B4X4_UNORM = 14, 248 | TinyImageFormat_B4G4R4A4_UNORM = 15, 249 | TinyImageFormat_B4G4R4X4_UNORM = 16, 250 | TinyImageFormat_A4R4G4B4_UNORM = 17, 251 | TinyImageFormat_X4R4G4B4_UNORM = 18, 252 | TinyImageFormat_A4B4G4R4_UNORM = 19, 253 | TinyImageFormat_X4B4G4R4_UNORM = 20, 254 | TinyImageFormat_R5G6B5_UNORM = 21, 255 | TinyImageFormat_B5G6R5_UNORM = 22, 256 | TinyImageFormat_R5G5B5A1_UNORM = 23, 257 | TinyImageFormat_B5G5R5A1_UNORM = 24, 258 | TinyImageFormat_A1B5G5R5_UNORM = 25, 259 | TinyImageFormat_A1R5G5B5_UNORM = 26, 260 | TinyImageFormat_R5G5B5X1_UNORM = 27, 261 | TinyImageFormat_B5G5R5X1_UNORM = 28, 262 | TinyImageFormat_X1R5G5B5_UNORM = 29, 263 | TinyImageFormat_X1B5G5R5_UNORM = 30, 264 | TinyImageFormat_B2G3R3A8_UNORM = 31, 265 | TinyImageFormat_R8G8_UNORM = 32, 266 | TinyImageFormat_R8G8_SNORM = 33, 267 | TinyImageFormat_G8R8_UNORM = 34, 268 | TinyImageFormat_G8R8_SNORM = 35, 269 | TinyImageFormat_R8G8_UINT = 36, 270 | TinyImageFormat_R8G8_SINT = 37, 271 | TinyImageFormat_R8G8_SRGB = 38, 272 | TinyImageFormat_R16_UNORM = 39, 273 | TinyImageFormat_R16_SNORM = 40, 274 | TinyImageFormat_R16_UINT = 41, 275 | TinyImageFormat_R16_SINT = 42, 276 | TinyImageFormat_R16_SFLOAT = 43, 277 | TinyImageFormat_R16_SBFLOAT = 44, 278 | TinyImageFormat_R8G8B8_UNORM = 45, 279 | TinyImageFormat_R8G8B8_SNORM = 46, 280 | TinyImageFormat_R8G8B8_UINT = 47, 281 | TinyImageFormat_R8G8B8_SINT = 48, 282 | TinyImageFormat_R8G8B8_SRGB = 49, 283 | TinyImageFormat_B8G8R8_UNORM = 50, 284 | TinyImageFormat_B8G8R8_SNORM = 51, 285 | TinyImageFormat_B8G8R8_UINT = 52, 286 | TinyImageFormat_B8G8R8_SINT = 53, 287 | TinyImageFormat_B8G8R8_SRGB = 54, 288 | TinyImageFormat_R8G8B8A8_UNORM = 55, 289 | TinyImageFormat_R8G8B8A8_SNORM = 56, 290 | TinyImageFormat_R8G8B8A8_UINT = 57, 291 | TinyImageFormat_R8G8B8A8_SINT = 58, 292 | TinyImageFormat_R8G8B8A8_SRGB = 59, 293 | TinyImageFormat_B8G8R8A8_UNORM = 60, 294 | TinyImageFormat_B8G8R8A8_SNORM = 61, 295 | TinyImageFormat_B8G8R8A8_UINT = 62, 296 | TinyImageFormat_B8G8R8A8_SINT = 63, 297 | TinyImageFormat_B8G8R8A8_SRGB = 64, 298 | TinyImageFormat_R8G8B8X8_UNORM = 65, 299 | TinyImageFormat_B8G8R8X8_UNORM = 66, 300 | TinyImageFormat_R16G16_UNORM = 67, 301 | TinyImageFormat_G16R16_UNORM = 68, 302 | TinyImageFormat_R16G16_SNORM = 69, 303 | TinyImageFormat_G16R16_SNORM = 70, 304 | TinyImageFormat_R16G16_UINT = 71, 305 | TinyImageFormat_R16G16_SINT = 72, 306 | TinyImageFormat_R16G16_SFLOAT = 73, 307 | TinyImageFormat_R16G16_SBFLOAT = 74, 308 | TinyImageFormat_R32_UINT = 75, 309 | TinyImageFormat_R32_SINT = 76, 310 | TinyImageFormat_R32_SFLOAT = 77, 311 | TinyImageFormat_A2R10G10B10_UNORM = 78, 312 | TinyImageFormat_A2R10G10B10_UINT = 79, 313 | TinyImageFormat_A2R10G10B10_SNORM = 80, 314 | TinyImageFormat_A2R10G10B10_SINT = 81, 315 | TinyImageFormat_A2B10G10R10_UNORM = 82, 316 | TinyImageFormat_A2B10G10R10_UINT = 83, 317 | TinyImageFormat_A2B10G10R10_SNORM = 84, 318 | TinyImageFormat_A2B10G10R10_SINT = 85, 319 | TinyImageFormat_R10G10B10A2_UNORM = 86, 320 | TinyImageFormat_R10G10B10A2_UINT = 87, 321 | TinyImageFormat_R10G10B10A2_SNORM = 88, 322 | TinyImageFormat_R10G10B10A2_SINT = 89, 323 | TinyImageFormat_B10G10R10A2_UNORM = 90, 324 | TinyImageFormat_B10G10R10A2_UINT = 91, 325 | TinyImageFormat_B10G10R10A2_SNORM = 92, 326 | TinyImageFormat_B10G10R10A2_SINT = 93, 327 | TinyImageFormat_B10G11R11_UFLOAT = 94, 328 | TinyImageFormat_E5B9G9R9_UFLOAT = 95, 329 | TinyImageFormat_R16G16B16_UNORM = 96, 330 | TinyImageFormat_R16G16B16_SNORM = 97, 331 | TinyImageFormat_R16G16B16_UINT = 98, 332 | TinyImageFormat_R16G16B16_SINT = 99, 333 | TinyImageFormat_R16G16B16_SFLOAT = 100, 334 | TinyImageFormat_R16G16B16_SBFLOAT = 101, 335 | TinyImageFormat_R16G16B16A16_UNORM = 102, 336 | TinyImageFormat_R16G16B16A16_SNORM = 103, 337 | TinyImageFormat_R16G16B16A16_UINT = 104, 338 | TinyImageFormat_R16G16B16A16_SINT = 105, 339 | TinyImageFormat_R16G16B16A16_SFLOAT = 106, 340 | TinyImageFormat_R16G16B16A16_SBFLOAT = 107, 341 | TinyImageFormat_R32G32_UINT = 108, 342 | TinyImageFormat_R32G32_SINT = 109, 343 | TinyImageFormat_R32G32_SFLOAT = 110, 344 | TinyImageFormat_R32G32B32_UINT = 111, 345 | TinyImageFormat_R32G32B32_SINT = 112, 346 | TinyImageFormat_R32G32B32_SFLOAT = 113, 347 | TinyImageFormat_R32G32B32A32_UINT = 114, 348 | TinyImageFormat_R32G32B32A32_SINT = 115, 349 | TinyImageFormat_R32G32B32A32_SFLOAT = 116, 350 | TinyImageFormat_R64_UINT = 117, 351 | TinyImageFormat_R64_SINT = 118, 352 | TinyImageFormat_R64_SFLOAT = 119, 353 | TinyImageFormat_R64G64_UINT = 120, 354 | TinyImageFormat_R64G64_SINT = 121, 355 | TinyImageFormat_R64G64_SFLOAT = 122, 356 | TinyImageFormat_R64G64B64_UINT = 123, 357 | TinyImageFormat_R64G64B64_SINT = 124, 358 | TinyImageFormat_R64G64B64_SFLOAT = 125, 359 | TinyImageFormat_R64G64B64A64_UINT = 126, 360 | TinyImageFormat_R64G64B64A64_SINT = 127, 361 | TinyImageFormat_R64G64B64A64_SFLOAT = 128, 362 | TinyImageFormat_D16_UNORM = 129, 363 | TinyImageFormat_X8_D24_UNORM = 130, 364 | TinyImageFormat_D32_SFLOAT = 131, 365 | TinyImageFormat_S8_UINT = 132, 366 | TinyImageFormat_D16_UNORM_S8_UINT = 133, 367 | TinyImageFormat_D24_UNORM_S8_UINT = 134, 368 | TinyImageFormat_D32_SFLOAT_S8_UINT = 135, 369 | TinyImageFormat_DXBC1_RGB_UNORM = 136, 370 | TinyImageFormat_DXBC1_RGB_SRGB = 137, 371 | TinyImageFormat_DXBC1_RGBA_UNORM = 138, 372 | TinyImageFormat_DXBC1_RGBA_SRGB = 139, 373 | TinyImageFormat_DXBC2_UNORM = 140, 374 | TinyImageFormat_DXBC2_SRGB = 141, 375 | TinyImageFormat_DXBC3_UNORM = 142, 376 | TinyImageFormat_DXBC3_SRGB = 143, 377 | TinyImageFormat_DXBC4_UNORM = 144, 378 | TinyImageFormat_DXBC4_SNORM = 145, 379 | TinyImageFormat_DXBC5_UNORM = 146, 380 | TinyImageFormat_DXBC5_SNORM = 147, 381 | TinyImageFormat_DXBC6H_UFLOAT = 148, 382 | TinyImageFormat_DXBC6H_SFLOAT = 149, 383 | TinyImageFormat_DXBC7_UNORM = 150, 384 | TinyImageFormat_DXBC7_SRGB = 151, 385 | TinyImageFormat_PVRTC1_2BPP_UNORM = 152, 386 | TinyImageFormat_PVRTC1_4BPP_UNORM = 153, 387 | TinyImageFormat_PVRTC2_2BPP_UNORM = 154, 388 | TinyImageFormat_PVRTC2_4BPP_UNORM = 155, 389 | TinyImageFormat_PVRTC1_2BPP_SRGB = 156, 390 | TinyImageFormat_PVRTC1_4BPP_SRGB = 157, 391 | TinyImageFormat_PVRTC2_2BPP_SRGB = 158, 392 | TinyImageFormat_PVRTC2_4BPP_SRGB = 159, 393 | TinyImageFormat_ETC2_R8G8B8_UNORM = 160, 394 | TinyImageFormat_ETC2_R8G8B8_SRGB = 161, 395 | TinyImageFormat_ETC2_R8G8B8A1_UNORM = 162, 396 | TinyImageFormat_ETC2_R8G8B8A1_SRGB = 163, 397 | TinyImageFormat_ETC2_R8G8B8A8_UNORM = 164, 398 | TinyImageFormat_ETC2_R8G8B8A8_SRGB = 165, 399 | TinyImageFormat_ETC2_EAC_R11_UNORM = 166, 400 | TinyImageFormat_ETC2_EAC_R11_SNORM = 167, 401 | TinyImageFormat_ETC2_EAC_R11G11_UNORM = 168, 402 | TinyImageFormat_ETC2_EAC_R11G11_SNORM = 169, 403 | TinyImageFormat_ASTC_4x4_UNORM = 170, 404 | TinyImageFormat_ASTC_4x4_SRGB = 171, 405 | TinyImageFormat_ASTC_5x4_UNORM = 172, 406 | TinyImageFormat_ASTC_5x4_SRGB = 173, 407 | TinyImageFormat_ASTC_5x5_UNORM = 174, 408 | TinyImageFormat_ASTC_5x5_SRGB = 175, 409 | TinyImageFormat_ASTC_6x5_UNORM = 176, 410 | TinyImageFormat_ASTC_6x5_SRGB = 177, 411 | TinyImageFormat_ASTC_6x6_UNORM = 178, 412 | TinyImageFormat_ASTC_6x6_SRGB = 179, 413 | TinyImageFormat_ASTC_8x5_UNORM = 180, 414 | TinyImageFormat_ASTC_8x5_SRGB = 181, 415 | TinyImageFormat_ASTC_8x6_UNORM = 182, 416 | TinyImageFormat_ASTC_8x6_SRGB = 183, 417 | TinyImageFormat_ASTC_8x8_UNORM = 184, 418 | TinyImageFormat_ASTC_8x8_SRGB = 185, 419 | TinyImageFormat_ASTC_10x5_UNORM = 186, 420 | TinyImageFormat_ASTC_10x5_SRGB = 187, 421 | TinyImageFormat_ASTC_10x6_UNORM = 188, 422 | TinyImageFormat_ASTC_10x6_SRGB = 189, 423 | TinyImageFormat_ASTC_10x8_UNORM = 190, 424 | TinyImageFormat_ASTC_10x8_SRGB = 191, 425 | TinyImageFormat_ASTC_10x10_UNORM = 192, 426 | TinyImageFormat_ASTC_10x10_SRGB = 193, 427 | TinyImageFormat_ASTC_12x10_UNORM = 194, 428 | TinyImageFormat_ASTC_12x10_SRGB = 195, 429 | TinyImageFormat_ASTC_12x12_UNORM = 196, 430 | TinyImageFormat_ASTC_12x12_SRGB = 197, 431 | TinyImageFormat_CLUT_P4 = 198, 432 | TinyImageFormat_CLUT_P4A4 = 199, 433 | TinyImageFormat_CLUT_P8 = 200, 434 | TinyImageFormat_CLUT_P8A8 = 201, 435 | } TinyImageFormat; 436 | 437 | typedef enum TinyImageFormat_LogicalChannel { 438 | TinyImageFormat_LC_Red = 0, 439 | TinyImageFormat_LC_Green = 1, 440 | TinyImageFormat_LC_Blue = 2, 441 | TinyImageFormat_LC_Alpha = 3, 442 | TinyImageFormat_LC_Depth = 0, 443 | TinyImageFormat_LC_Stencil = 1, 444 | TinyImageFormat_LC_0 = -1, 445 | TinyImageFormat_LC_1 = -2, 446 | } TinyImageFormat_LogicalChannel; 447 | 448 | typedef enum TinyImageFormat_PhysicalChannel { 449 | TinyImageFormat_PC_0 = 0, 450 | TinyImageFormat_PC_1 = 1, 451 | TinyImageFormat_PC_2 = 2, 452 | TinyImageFormat_PC_3 = 3, 453 | TinyImageFormat_PC_CONST_0 = -1, 454 | TinyImageFormat_PC_CONST_1 = -2, 455 | } TinyImageFormat_PhysicalChannel; 456 | 457 | #define TinyImageFormat_Count 202U 458 | 459 | typedef struct TinyImageFormat_DecodeInput { 460 | union { void const* pixel; void const* pixelPlane0; }; 461 | union { void const* lut; void const* pixelPlane1; }; 462 | void const* pixelPlane2; 463 | void const* pixelPlane3; 464 | void const* pixelPlane4; 465 | void const* pixelPlane5; 466 | void const* pixelPlane6; 467 | void const* pixelPlane7; 468 | void const* pixelPlane8; 469 | void const* pixelPlane9; 470 | } TinyImageFormat_FetchInput; 471 | 472 | typedef struct TinyImageFormat_EncodeOutput { 473 | union { void * pixel; void * pixelPlane0; }; 474 | void * pixelPlane1; 475 | void * pixelPlane2; 476 | void * pixelPlane3; 477 | void * pixelPlane4; 478 | void * pixelPlane5; 479 | void * pixelPlane6; 480 | void * pixelPlane7; 481 | void * pixelPlane8; 482 | void * pixelPlane9; 483 | } TinyImageFormat_EncodeOutput; 484 | 485 | #endif // TINYIMAGEFORMAT_BASE_H_ 486 | 487 | -------------------------------------------------------------------------------- /include/tiny_imageformat/tinyimageformat_bits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef enum TinyImageFormat_Namespace { 4 | TinyImageFormat_NAMESPACE_PACK = 0ULL, 5 | TinyImageFormat_NAMESPACE_DEPTH_STENCIL = 1ULL, 6 | TinyImageFormat_NAMESPACE_DXTC = 2ULL, 7 | TinyImageFormat_NAMESPACE_PVRTC = 3ULL, 8 | TinyImageFormat_NAMESPACE_ETC = 4ULL, 9 | TinyImageFormat_NAMESPACE_ASTC = 5ULL, 10 | TinyImageFormat_NAMESPACE_CLUT = 6ULL, 11 | } TinyImageFormat_Namespace; 12 | 13 | typedef enum TinyImageFormat_Pack_Special { 14 | TinyImageFormat_PACK_SPECIAL_NONE = 0ULL, 15 | TinyImageFormat_PACK_SPECIAL_PACK = 1ULL, 16 | TinyImageFormat_PACK_SPECIAL_MULTI2 = 2ULL, 17 | TinyImageFormat_PACK_SPECIAL_MULTI4 = 3ULL, 18 | TinyImageFormat_PACK_SPECIAL_MULTI8 = 4ULL, 19 | } TinyImageFormat_Pack_Special; 20 | 21 | typedef enum TinyImageFormat_Pack_Bits { 22 | TinyImageFormat_PACK_BITS_0 = 0ULL, 23 | TinyImageFormat_PACK_BITS_1 = 1ULL, 24 | TinyImageFormat_PACK_BITS_2 = 2ULL, 25 | TinyImageFormat_PACK_BITS_3 = 3ULL, 26 | TinyImageFormat_PACK_BITS_4 = 4ULL, 27 | TinyImageFormat_PACK_BITS_5 = 5ULL, 28 | TinyImageFormat_PACK_BITS_6 = 6ULL, 29 | TinyImageFormat_PACK_BITS_7 = 7ULL, 30 | TinyImageFormat_PACK_BITS_8 = 8ULL, 31 | TinyImageFormat_PACK_BITS_9 = 9ULL, 32 | TinyImageFormat_PACK_BITS_10 = 10ULL, 33 | TinyImageFormat_PACK_BITS_11 = 11ULL, 34 | TinyImageFormat_PACK_BITS_12 = 12ULL, 35 | TinyImageFormat_PACK_BITS_16 = 13ULL, 36 | TinyImageFormat_PACK_BITS_24 = 14ULL, 37 | TinyImageFormat_PACK_BITS_32 = 15ULL, 38 | TinyImageFormat_PACK_BITS_64 = 16ULL, 39 | } TinyImageFormat_Pack_Bits; 40 | 41 | typedef enum TinyImageFormat_Pack_Swizzle { 42 | TinyImageFormat_PACK_SWIZZLE_R = 0ULL, 43 | TinyImageFormat_PACK_SWIZZLE_G = 1ULL, 44 | TinyImageFormat_PACK_SWIZZLE_B = 2ULL, 45 | TinyImageFormat_PACK_SWIZZLE_A = 3ULL, 46 | TinyImageFormat_PACK_SWIZZLE_0 = 4ULL, 47 | TinyImageFormat_PACK_SWIZZLE_1 = 5ULL, 48 | } TinyImageFormat_Pack_Swizzle; 49 | 50 | typedef enum TinyImageFormat_Pack_Type { 51 | TinyImageFormat_PACK_TYPE_NONE = 0ULL, 52 | TinyImageFormat_PACK_TYPE_UNORM = 1ULL, 53 | TinyImageFormat_PACK_TYPE_SNORM = 2ULL, 54 | TinyImageFormat_PACK_TYPE_UINT = 3ULL, 55 | TinyImageFormat_PACK_TYPE_SINT = 4ULL, 56 | TinyImageFormat_PACK_TYPE_UFLOAT = 5ULL, 57 | TinyImageFormat_PACK_TYPE_SFLOAT = 6ULL, 58 | TinyImageFormat_PACK_TYPE_SRGB = 7ULL, 59 | TinyImageFormat_PACK_TYPE_SBFLOAT = 8ULL, 60 | } TinyImageFormat_Pack_Type; 61 | 62 | typedef enum TinyImageFormat_DepthStencil_Total_Size { 63 | TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_8 = 0ULL, 64 | TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_16 = 1ULL, 65 | TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_32 = 2ULL, 66 | TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_64 = 3ULL, 67 | } TinyImageFormat_DepthStencil_Total_Size; 68 | 69 | typedef enum TinyImageFormat_DepthStencil_Bits { 70 | TinyImageFormat_DEPTH_STENCIL_BITS_0 = 0ULL, 71 | TinyImageFormat_DEPTH_STENCIL_BITS_8 = 1ULL, 72 | TinyImageFormat_DEPTH_STENCIL_BITS_16 = 2ULL, 73 | TinyImageFormat_DEPTH_STENCIL_BITS_24 = 3ULL, 74 | TinyImageFormat_DEPTH_STENCIL_BITS_32 = 4ULL, 75 | } TinyImageFormat_DepthStencil_Bits; 76 | 77 | typedef enum TinyImageFormat_DepthStencil_Swizzle { 78 | TinyImageFormat_DEPTH_STENCIL_SWIZZLE_D = 0ULL, 79 | TinyImageFormat_DEPTH_STENCIL_SWIZZLE_S = 1ULL, 80 | TinyImageFormat_DEPTH_STENCIL_SWIZZLE_0 = 2ULL, 81 | } TinyImageFormat_DepthStencil_Swizzle; 82 | 83 | typedef enum TinyImageFormat_DepthStencil_Type { 84 | TinyImageFormat_DEPTH_STENCIL_TYPE_NONE = 0ULL, 85 | TinyImageFormat_DEPTH_STENCIL_TYPE_UNORM = 1ULL, 86 | TinyImageFormat_DEPTH_STENCIL_TYPE_UINT = 2ULL, 87 | TinyImageFormat_DEPTH_STENCIL_TYPE_SFLOAT = 3ULL, 88 | } TinyImageFormat_DepthStencil_Type; 89 | 90 | typedef enum TinyImageFormat_DXTC_Alpha { 91 | TinyImageFormat_DXTC_ALPHA_NONE = 0ULL, 92 | TinyImageFormat_DXTC_ALPHA_PUNCHTHROUGH = 1ULL, 93 | TinyImageFormat_DXTC_ALPHA_BLOCK = 2ULL, 94 | TinyImageFormat_DXTC_ALPHA_FULL = 3ULL, 95 | } TinyImageFormat_DXTC_Alpha; 96 | 97 | typedef enum TinyImageFormat_DXTC_Type { 98 | TinyImageFormat_DXTC_TYPE_UNORM = 0ULL, 99 | TinyImageFormat_DXTC_TYPE_SNORM = 1ULL, 100 | TinyImageFormat_DXTC_TYPE_SRGB = 2ULL, 101 | TinyImageFormat_DXTC_TYPE_SFLOAT = 3ULL, 102 | TinyImageFormat_DXTC_TYPE_UFLOAT = 4ULL, 103 | } TinyImageFormat_DXTC_Type; 104 | 105 | typedef enum TinyImageFormat_DXTC_BlockBytes { 106 | TinyImageFormat_DXTC_BLOCKBYTES_8 = 0ULL, 107 | TinyImageFormat_DXTC_BLOCKBYTES_16 = 1ULL, 108 | } TinyImageFormat_DXTC_BlockBytes; 109 | 110 | typedef enum TinyImageFormat_DXTC_ChannelCount { 111 | TinyImageFormat_DXTC_CHANNELCOUNT_1 = 0ULL, 112 | TinyImageFormat_DXTC_CHANNELCOUNT_2 = 1ULL, 113 | TinyImageFormat_DXTC_CHANNELCOUNT_3 = 2ULL, 114 | TinyImageFormat_DXTC_CHANNELCOUNT_4 = 3ULL, 115 | } TinyImageFormat_DXTC_ChannelCount; 116 | 117 | typedef enum TinyImageFormat_DXTC_ModeCount { 118 | TinyImageFormat_DXTC_MODECOUNT_1 = 0ULL, 119 | TinyImageFormat_DXTC_MODECOUNT_8 = 1ULL, 120 | TinyImageFormat_DXTC_MODECOUNT_14 = 2ULL, 121 | } TinyImageFormat_DXTC_ModeCount; 122 | 123 | typedef enum TinyImageFormat_PVRTC_Version { 124 | TinyImageFormat_PVRTC_VERSION_V1 = 0ULL, 125 | TinyImageFormat_PVRTC_VERSION_V2 = 1ULL, 126 | } TinyImageFormat_PVRTC_Version; 127 | 128 | typedef enum TinyImageFormat_PVRTC_Bits { 129 | TinyImageFormat_PVRTC_BITS_2 = 0ULL, 130 | TinyImageFormat_PVRTC_BITS_4 = 1ULL, 131 | } TinyImageFormat_PVRTC_Bits; 132 | 133 | typedef enum TinyImageFormat_PVRTC_Type { 134 | TinyImageFormat_PVRTC_TYPE_UNORM = 0ULL, 135 | TinyImageFormat_PVRTC_TYPE_SRGB = 1ULL, 136 | } TinyImageFormat_PVRTC_Type; 137 | 138 | typedef enum TinyImageFormat_ETC_Bits { 139 | TinyImageFormat_ETC_BITS_8 = 0ULL, 140 | TinyImageFormat_ETC_BITS_11 = 1ULL, 141 | } TinyImageFormat_ETC_Bits; 142 | 143 | typedef enum TinyImageFormat_ETC_Alpha { 144 | TinyImageFormat_ETC_ALPHA_NONE = 0ULL, 145 | TinyImageFormat_ETC_ALPHA_PUNCHTHROUGH = 1ULL, 146 | TinyImageFormat_ETC_ALPHA_BLOCK = 2ULL, 147 | } TinyImageFormat_ETC_Alpha; 148 | 149 | typedef enum TinyImageFormat_ETC_Type { 150 | TinyImageFormat_ETC_TYPE_UNORM = 0ULL, 151 | TinyImageFormat_ETC_TYPE_SNORM = 1ULL, 152 | TinyImageFormat_ETC_TYPE_SRGB = 2ULL, 153 | } TinyImageFormat_ETC_Type; 154 | 155 | typedef enum TinyImageFormat_ETC_ChannelCount { 156 | TinyImageFormat_ETC_CHANNELCOUNT_1 = 0ULL, 157 | TinyImageFormat_ETC_CHANNELCOUNT_2 = 1ULL, 158 | TinyImageFormat_ETC_CHANNELCOUNT_3 = 2ULL, 159 | TinyImageFormat_ETC_CHANNELCOUNT_4 = 3ULL, 160 | } TinyImageFormat_ETC_ChannelCount; 161 | 162 | typedef enum TinyImageFormat_ASTC_Size { 163 | TinyImageFormat_ASTC_SIZE_1 = 0ULL, 164 | TinyImageFormat_ASTC_SIZE_4 = 2ULL, 165 | TinyImageFormat_ASTC_SIZE_5 = 3ULL, 166 | TinyImageFormat_ASTC_SIZE_6 = 4ULL, 167 | TinyImageFormat_ASTC_SIZE_8 = 5ULL, 168 | TinyImageFormat_ASTC_SIZE_10 = 6ULL, 169 | TinyImageFormat_ASTC_SIZE_12 = 7ULL, 170 | } TinyImageFormat_ASTC_Size; 171 | 172 | typedef enum TinyImageFormat_ASTC_Type { 173 | TinyImageFormat_ASTC_TYPE_UNORM = 0ULL, 174 | TinyImageFormat_ASTC_TYPE_SRGB = 1ULL, 175 | } TinyImageFormat_ASTC_Type; 176 | 177 | typedef enum TinyImageFormat_CLUT_BlockSize { 178 | TinyImageFormat_CLUT_BLOCKSIZE_1 = 0ULL, 179 | TinyImageFormat_CLUT_BLOCKSIZE_2 = 1ULL, 180 | TinyImageFormat_CLUT_BLOCKSIZE_4 = 2ULL, 181 | TinyImageFormat_CLUT_BLOCKSIZE_8 = 3ULL, 182 | } TinyImageFormat_CLUT_BlockSize; 183 | 184 | typedef enum TinyImageFormat_CLUT_Bits { 185 | TinyImageFormat_CLUT_BITS_0 = 0ULL, 186 | TinyImageFormat_CLUT_BITS_1 = 1ULL, 187 | TinyImageFormat_CLUT_BITS_2 = 2ULL, 188 | TinyImageFormat_CLUT_BITS_4 = 3ULL, 189 | TinyImageFormat_CLUT_BITS_8 = 4ULL, 190 | } TinyImageFormat_CLUT_Bits; 191 | 192 | typedef enum TinyImageFormat_CLUT_Type { 193 | TinyImageFormat_CLUT_TYPE_NONE = 0ULL, 194 | TinyImageFormat_CLUT_TYPE_RGB = 1ULL, 195 | TinyImageFormat_CLUT_TYPE_SINGLE = 2ULL, 196 | TinyImageFormat_CLUT_TYPE_EXPLICIT_ALPHA = 3ULL, 197 | } TinyImageFormat_CLUT_Type; 198 | 199 | typedef enum TinyImageFormat_Bits { 200 | TinyImageFormat_NAMESPACE_REQUIRED_BITS = 12ULL, 201 | TinyImageFormat_NAMESPACE_MASK = (1 << TinyImageFormat_NAMESPACE_REQUIRED_BITS) - 1, 202 | 203 | TinyImageFormat_PACK_SPECIAL_REQUIRED_BITS = 3ULL, 204 | TinyImageFormat_PACK_BITS_REQUIRED_BITS = 5ULL, 205 | TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS = 3ULL, 206 | 207 | TinyImageFormat_PACK_TYPE_REQUIRED_BITS = 4ULL, 208 | TinyImageFormat_PACK_NUM_CHANNELS = 4ULL, 209 | 210 | TinyImageFormat_PACK_SPECIAL_SHIFT = (TinyImageFormat_NAMESPACE_REQUIRED_BITS), 211 | TinyImageFormat_PACK_BITS_SHIFT = (TinyImageFormat_PACK_SPECIAL_REQUIRED_BITS + TinyImageFormat_PACK_SPECIAL_SHIFT), 212 | TinyImageFormat_PACK_SWIZZLE_SHIFT = 213 | ((TinyImageFormat_PACK_BITS_REQUIRED_BITS * TinyImageFormat_PACK_NUM_CHANNELS) + TinyImageFormat_PACK_BITS_SHIFT), 214 | TinyImageFormat_PACK_TYPE_SHIFT = ((TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS * TinyImageFormat_PACK_NUM_CHANNELS) 215 | + TinyImageFormat_PACK_SWIZZLE_SHIFT), 216 | 217 | TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_REQUIRED_BITS = 2ULL, 218 | TinyImageFormat_DEPTH_STENCIL_BITS_REQUIRED_BITS = 3ULL, 219 | TinyImageFormat_DEPTH_STENCIL_SWIZZLE_REQUIRED_BITS = 2ULL, 220 | TinyImageFormat_DEPTH_STENCIL_TYPE_REQUIRED_BITS = 2ULL, 221 | TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS = 2ULL, 222 | 223 | TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_SHIFT = (TinyImageFormat_NAMESPACE_REQUIRED_BITS), 224 | TinyImageFormat_DEPTH_STENCIL_BITS_SHIFT = 225 | ((TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_SHIFT), 226 | TinyImageFormat_DEPTH_STENCIL_SWIZZLE_SHIFT = 227 | ((TinyImageFormat_DEPTH_STENCIL_BITS_REQUIRED_BITS * TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS) 228 | + TinyImageFormat_DEPTH_STENCIL_BITS_SHIFT), 229 | TinyImageFormat_DEPTH_STENCIL_TYPE_SHIFT = 230 | ((TinyImageFormat_DEPTH_STENCIL_SWIZZLE_REQUIRED_BITS * TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS) 231 | + TinyImageFormat_DEPTH_STENCIL_SWIZZLE_SHIFT), 232 | 233 | TinyImageFormat_DXTC_ALPHA_REQUIRED_BITS = 2ULL, 234 | TinyImageFormat_DXTC_TYPE_REQUIRED_BITS = 3ULL, 235 | TinyImageFormat_DXTC_BLOCKBYTES_REQUIRED_BITS = 2ULL, 236 | TinyImageFormat_DXTC_CHANNELCOUNT_REQUIRED_BITS = 2ULL, 237 | TinyImageFormat_DXTC_MODECOUNT_REQUIRED_BITS = 3ULL, 238 | 239 | TinyImageFormat_DXTC_ALPHA_SHIFT = (TinyImageFormat_NAMESPACE_REQUIRED_BITS), 240 | TinyImageFormat_DXTC_TYPE_SHIFT = (TinyImageFormat_DXTC_ALPHA_REQUIRED_BITS + TinyImageFormat_DXTC_ALPHA_SHIFT), 241 | TinyImageFormat_DXTC_BLOCKBYTES_SHIFT = (TinyImageFormat_DXTC_TYPE_REQUIRED_BITS + TinyImageFormat_DXTC_TYPE_SHIFT), 242 | TinyImageFormat_DXTC_CHANNELCOUNT_SHIFT = 243 | (TinyImageFormat_DXTC_BLOCKBYTES_REQUIRED_BITS + TinyImageFormat_DXTC_BLOCKBYTES_SHIFT), 244 | TinyImageFormat_DXTC_MODECOUNT_SHIFT = 245 | (TinyImageFormat_DXTC_CHANNELCOUNT_REQUIRED_BITS + TinyImageFormat_DXTC_CHANNELCOUNT_SHIFT), 246 | 247 | TinyImageFormat_PVRTC_VERSION_REQUIRED_BITS = 2ULL, 248 | TinyImageFormat_PVRTC_BITS_REQUIRED_BITS = 2ULL, 249 | TinyImageFormat_PVRTC_TYPE_REQUIRED_BITS = 2ULL, 250 | TinyImageFormat_PVRTC_VERSION_SHIFT = (TinyImageFormat_NAMESPACE_REQUIRED_BITS), 251 | TinyImageFormat_PVRTC_BITS_SHIFT = 252 | (TinyImageFormat_PVRTC_VERSION_REQUIRED_BITS + TinyImageFormat_PVRTC_VERSION_SHIFT), 253 | TinyImageFormat_PVRTC_TYPE_SHIFT = (TinyImageFormat_PVRTC_BITS_REQUIRED_BITS + TinyImageFormat_PVRTC_BITS_SHIFT), 254 | 255 | TinyImageFormat_ETC_BITS_REQUIRED_BITS = 2ULL, 256 | TinyImageFormat_ETC_ALPHA_REQUIRED_BITS = 2ULL, 257 | TinyImageFormat_ETC_TYPE_REQUIRED_BITS = 2ULL, 258 | TinyImageFormat_ETC_CHANNELCOUNT_REQUIRED_BITS = 2ULL, 259 | TinyImageFormat_ETC_BITS_SHIFT = (TinyImageFormat_NAMESPACE_REQUIRED_BITS), 260 | TinyImageFormat_ETC_ALPHA_SHIFT = (TinyImageFormat_ETC_BITS_REQUIRED_BITS + TinyImageFormat_ETC_BITS_SHIFT), 261 | TinyImageFormat_ETC_TYPE_SHIFT = (TinyImageFormat_ETC_ALPHA_REQUIRED_BITS + TinyImageFormat_ETC_ALPHA_SHIFT), 262 | TinyImageFormat_ETC_CHANNELCOUNT_SHIFT = (TinyImageFormat_ETC_TYPE_REQUIRED_BITS + TinyImageFormat_ETC_TYPE_SHIFT), 263 | 264 | TinyImageFormat_ASTC_SIZE_REQUIRED_BITS = 3, 265 | TinyImageFormat_ASTC_TYPE_REQUIRED_BITS = 2ULL, 266 | TinyImageFormat_ASTC_NUM_DIMS = 3, 267 | TinyImageFormat_ASTC_SIZE_SHIFT = (TinyImageFormat_NAMESPACE_REQUIRED_BITS), 268 | TinyImageFormat_ASTC_TYPE_SHIFT = 269 | ((TinyImageFormat_ASTC_SIZE_REQUIRED_BITS * TinyImageFormat_ASTC_NUM_DIMS) + TinyImageFormat_ASTC_SIZE_SHIFT), 270 | 271 | TinyImageFormat_CLUT_BLOCKSIZE_REQUIRED_BITS = 2, 272 | TinyImageFormat_CLUT_BITS_REQUIRED_BITS = 3, 273 | TinyImageFormat_CLUT_TYPE_REQUIRED_BITS = 2, 274 | TinyImageFormat_CLUT_NUM_CHANNELS = 2, 275 | 276 | TinyImageFormat_CLUT_BLOCKSIZE_SHIFT = TinyImageFormat_NAMESPACE_REQUIRED_BITS, 277 | TinyImageFormat_CLUT_BITS_SHIFT = TinyImageFormat_CLUT_BLOCKSIZE_REQUIRED_BITS + TinyImageFormat_CLUT_BLOCKSIZE_SHIFT, 278 | TinyImageFormat_CLUT_TYPE_SHIFT = 279 | ((TinyImageFormat_CLUT_BITS_REQUIRED_BITS * TinyImageFormat_CLUT_NUM_CHANNELS) + TinyImageFormat_CLUT_BITS_SHIFT), 280 | 281 | } TinyImageFormat_Bits; 282 | -------------------------------------------------------------------------------- /src/decodehelpers.h: -------------------------------------------------------------------------------- 1 | RAW_INCLUDE_START( R"=====( ) 2 | 3 | 4 | inline void TinyImageFormat_SharedE5B9G9R9UFloatToFloats(uint32_t v, float out[4]) { 5 | // https://github.com/microsoft/DirectXMath/blob/ecfb4754400dac581c2eeb6e849617cf5d210426/Inc/DirectXPackedVector.h 6 | union 7 | { 8 | struct 9 | { 10 | uint32_t rm : 9; 11 | uint32_t gm : 9; 12 | uint32_t bm : 9; 13 | uint32_t e : 5; 14 | }; 15 | uint32_t v; 16 | } ei; 17 | 18 | union { 19 | uint32_t u; 20 | float f; 21 | } t; 22 | 23 | ei.v = v; 24 | t.u = 0x33800000 + (ei.e << 23); 25 | 26 | out[0] = t.f * (float)(ei.rm); 27 | out[1] = t.f * (float)(ei.gm); 28 | out[2] = t.f * (float)(ei.bm); 29 | out[3] = 1.0f; 30 | } 31 | 32 | //HalfToFloat from Rygorous public domain code 33 | inline float TinyImageFormat_HalfAsUintToFloat(uint16_t h_) { 34 | 35 | const uint32_t shifted_exp = 0x7c00 << 13; // exponent mask after shift 36 | union { 37 | uint16_t u; 38 | struct { 39 | uint32_t Mantissa : 10; 40 | uint32_t Exponent : 5; 41 | uint32_t Sign : 1; 42 | }; 43 | } h; 44 | 45 | union { 46 | uint32_t u; 47 | float f; 48 | struct { 49 | uint32_t Mantissa : 23; 50 | uint32_t Exponent : 8; 51 | uint32_t Sign : 1; 52 | }; 53 | } o; 54 | 55 | h.u = h_; 56 | 57 | o.u = (h.u & 0x7fff) << 13; // exponent/mantissa bits 58 | uint32_t exp = shifted_exp & o.u; // just the exponent 59 | o.u += (127 - 15) << 23; // exponent adjust 60 | 61 | // handle exponent special cases 62 | if (exp == shifted_exp) { // Inf/NaN? 63 | o.u += (128 - 16) << 23; // extra exp adjust 64 | } else if (exp == 0) // Zero/Denormal? 65 | { 66 | union { 67 | uint32_t u; 68 | float f; 69 | } magic; 70 | magic.u = 113 << 23; 71 | 72 | o.u += 1 << 23; // extra exp adjust 73 | o.f -= magic.f; // renormalize 74 | } 75 | 76 | o.u |= (h.u & 0x8000) << 16; // sign bit 77 | return o.f; 78 | } 79 | 80 | inline float TinyImageFormat_BFloatAsUintToFloat(uint16_t h_) { 81 | union { 82 | struct { 83 | uint16_t x; 84 | uint16_t u; 85 | }; 86 | float f; 87 | } o; 88 | 89 | o.u = h_; 90 | o.x = 0; 91 | 92 | return o.f; 93 | } 94 | 95 | inline float TinyImageFormat_UFloat6AsUintToFloat(uint16_t Value) 96 | { 97 | // https://github.com/microsoft/DirectXMath/blob/ecfb4754400dac581c2eeb6e849617cf5d210426/Inc/DirectXPackedVector.h 98 | 99 | union { 100 | uint32_t u; 101 | float f; 102 | struct { 103 | uint32_t Mantissa : 23; 104 | uint32_t Exponent : 8; 105 | uint32_t Sign : 1; 106 | }; 107 | } o; 108 | 109 | o.Mantissa = Value & 0x3F; 110 | o.Exponent = Value & 0x3C0; 111 | o.Sign = 0; 112 | 113 | if (o.Exponent != 0) // The value is normalized 114 | { 115 | o.Exponent = (uint32_t)((Value >> 6) & 0xF); 116 | } 117 | else if (o.Mantissa != 0) // The value is denormalized 118 | { 119 | // Normalize the value in the resulting float 120 | o.Exponent = 1; 121 | do 122 | { 123 | o.Exponent--; 124 | o.Mantissa <<= 1; 125 | } while ((o.Mantissa & 0x40) == 0); 126 | o.Mantissa &= 0x3F; 127 | } 128 | else 129 | { 130 | // The value is zero 131 | o.u = 0; 132 | } 133 | 134 | return o.f; 135 | } 136 | 137 | inline float TinyImageFormat_UFloat7AsUintToFloat(uint16_t Value) 138 | { 139 | // https://github.com/microsoft/DirectXMath/blob/ecfb4754400dac581c2eeb6e849617cf5d210426/Inc/DirectXPackedVector.h 140 | 141 | union { 142 | uint32_t u; 143 | float f; 144 | struct { 145 | uint32_t Mantissa : 23; 146 | uint32_t Exponent : 8; 147 | uint32_t Sign : 1; 148 | }; 149 | } o; 150 | 151 | o.Mantissa = Value & 0x7F; 152 | o.Exponent = Value & 0x380; 153 | o.Sign = 0; 154 | 155 | if (o.Exponent != 0) // The value is normalized 156 | { 157 | o.Exponent = (uint32_t)((Value >> 7) & 0x7); 158 | } 159 | else if (o.Mantissa != 0) // The value is denormalized 160 | { 161 | // Normalize the value in the resulting float 162 | o.Exponent = 1; 163 | do 164 | { 165 | o.Exponent--; 166 | o.Mantissa <<= 1; 167 | } while ((o.Mantissa & 0x80) == 0); 168 | o.Mantissa &= 0x7F; 169 | } 170 | else 171 | { 172 | // The value is zero 173 | o.u = 0; 174 | } 175 | 176 | return o.f; 177 | } 178 | 179 | inline float TinyImageFormat_UFloat10AsUintToFloat(uint16_t v) { 180 | // https://github.com/microsoft/DirectXMath/blob/ecfb4754400dac581c2eeb6e849617cf5d210426/Inc/DirectXPackedVector.h 181 | union { 182 | struct { 183 | uint16_t e : 5; 184 | uint16_t m : 5; 185 | uint16_t x : 6; // not used 186 | }; 187 | uint16_t v; 188 | } ei; 189 | 190 | union { 191 | uint32_t u; 192 | float f; 193 | } t; 194 | 195 | ei.v = v; 196 | 197 | double out = 0.0; 198 | if (ei.e == 31) { 199 | if (ei.m == 0) { 200 | t.u = 0xFF100000; // + infinity 201 | } else { 202 | t.u = 0xFF100002; // float qNAN with payload = 1 203 | } 204 | } else if (ei.e == 0) { 205 | if(ei.m == 0) { 206 | t.f = 0.0f; 207 | } else { 208 | // Normalized float 209 | uint32_t exp = 1; 210 | uint32_t man = ei.m; 211 | do 212 | { 213 | exp--; 214 | man <<= 1; 215 | } while ((man & 0x20) == 0); 216 | man &= 0x1F; 217 | t.u = ((exp + 112) << 23) | (man << 18); 218 | } 219 | } else { 220 | t.u = ((ei.e + 112) << 23) | (ei.m << 18); 221 | } 222 | return t.f; 223 | } 224 | 225 | inline float TinyImageFormat_UFloat11AsUintToFloat(uint16_t v) { 226 | // https://github.com/microsoft/DirectXMath/blob/ecfb4754400dac581c2eeb6e849617cf5d210426/Inc/DirectXPackedVector.h 227 | union { 228 | struct { 229 | uint16_t e : 5; 230 | uint16_t m : 6; 231 | uint16_t x : 5; // not used 232 | }; 233 | uint16_t v; 234 | } ei; 235 | 236 | union { 237 | uint32_t u; 238 | float f; 239 | } t; 240 | 241 | ei.v = v; 242 | 243 | if (ei.e == 31) { 244 | if (ei.m == 0) { 245 | t.u = 0xFF100000; // + infinity 246 | } else { 247 | t.u = 0xFF100002; // float qNAN with payload = 1 248 | } 249 | } else if (ei.e == 0) { 250 | if(ei.m == 0) { 251 | t.f = 0.0f; 252 | } else { 253 | // Normalized float 254 | uint32_t exp = 1; 255 | uint32_t man = ei.m; 256 | do 257 | { 258 | exp--; 259 | man <<= 1; 260 | } while ((man & 0x40) == 0); 261 | man &= 0x3F; 262 | t.u = ((exp + 112) << 23) | (man << 17); 263 | } 264 | } else { 265 | t.u = ((ei.e + 112) << 23) | (ei.m << 17); 266 | } 267 | return t.f; 268 | } 269 | 270 | RAW_INCLUDE_END( )=====" ) -------------------------------------------------------------------------------- /src/doc.h: -------------------------------------------------------------------------------- 1 | RAW_INCLUDE_START( R"=====( ) 2 | /* TinyImageFormat is a library about the encodings of pixels typically 3 | * encountered in real time graphics. 4 | * 5 | * Like modern graphics API it is enumeration based but it also provides an API 6 | * for reasoning about that enumeration programmatically. 7 | * 8 | * Additionally it provide ways of accessing pixels encoded in the specified 9 | * format for most pixel formats. The hope is eventually to get decode to 100% 10 | * but not there yet (119 out of 193 currently). 11 | * This allows you to effectively read/write a large amount of image data. 12 | * 13 | * To assist with working with graphics APIs converters to and from Vulkan, 14 | * D3D12 and Metal. These are self contained and do not require the actual APIs. 15 | * 16 | * Available as either a single header or a version made of 6 headers split into 17 | * functional groups. Use one style or the other but they don't mix. 18 | * 19 | * These files are large due to unrolling and large switches. Functions are 20 | * inlined, allowing the compiler to eliminate and collapse when possible, 21 | * however particularly the Encode/Decode functions aren't near as fast as they 22 | * could be if heavily optimised for specific formats/layouts. 23 | * 24 | * Whilst not optimal due to number of formats it supports, it intends to be 25 | * fast enough that in many cases it will be fine. 26 | * 27 | * Internally every format has a descriptor packed into a 64 bit code word. 28 | * This code word is used to generate the header and it isn't used by the API 29 | * itself, as its been 'burnt' out by the code generator but it can be used at 30 | * runtime if desired and in future its intended to be used for exotic packed 31 | * formats that don't get there own enumeration value but can be expressed 32 | * via a descriptor. 33 | * 34 | * Where possible for C++ users functions are constexpr. 35 | * 36 | * It is MIT licensed and borrows/builds on code/specs including but not 37 | * limited to 38 | * Microsoft's Chris Walbourn DXTextureTool 39 | * Rygerous public domain Half to float (and vice versa) code 40 | * Khronos DFD specifications 41 | * Khronos Vulkan Specification 42 | * Microsoft D3D11/D3D12 Specifications 43 | * Apple Metal documentation 44 | * DDS Loaders from various sources (Humus, Confetti FX, DXTextureTool) 45 | * 46 | * TODO 47 | * ---- 48 | * Test CLUT formats and add encode clause 49 | * Add shared component i.e. G8R8G8B8 4:2:x formats 50 | * Add Multi plane formats 51 | * Add compressed format decoders 52 | * Add Block copy (for updating compressed formats) 53 | * Add functions that work on descriptor codes directly 54 | * Add UFLOAT 6 and 7 bit support 55 | * Optional SIMD decode/encode functions 56 | * More tests 57 | * 58 | * Definitions 59 | * ----------- 60 | * 61 | * Pixel 62 | * We define a pixel as upto 4 channels representing a single 'colour' 63 | * Its may not be addressable directly but as blocks of related pixels. 64 | * When decode/encoding pixels are presented to the API as 4 floats or doubles. 65 | * 66 | * Logical Channels (TinyImageFormat_LogicalChannel) 67 | * Logical channel are the usual way you would ask for a particular channel, 68 | * so asking about LC_Red while get you data for the red channel, however its 69 | * actually physically encoded in the data. 70 | * 71 | * Physical Channels (TinyImageFormat_PhysicalChannel) 72 | * Physical channels are the inverse of logical channels, that have no meaning 73 | * beyond the position in the data itself. 74 | * 75 | * Both Logical and Physical channels support returning constant 0 or 1 76 | * 77 | * Blocks 78 | * A block is the smallest addressable element this format refers to. Blocks 79 | * have up to 3 dimensions (though no format currently uses the 3rd). 80 | * Blocks are always at least byte aligned. 81 | * For single pixel formats this will be 1x1x1. For something like R1 it would 82 | * be 8x1x1 (8 single bits for 8 pixels). 83 | * For block compressed format a common value is 4x4x1. 84 | * A block for shared channels or very tightly packed this is how many pixels 85 | * are combined into one addressable unit. 86 | * 87 | * API 88 | * --- 89 | * The primary enumeration is simply TinyImageFormat, everything else supports 90 | * this enum. 91 | * All functions, enums etc. are prefixed with TinyImageFormat_, All functions 92 | * also take the format as first parameter. These are often removed in the api 93 | * docs to save space. 94 | * 95 | * Defines 96 | * ------- 97 | * TinyImageFormat_Count - how many formats in total 98 | * TinyImageFormat_MaxPixelCountOfBlock - maximum number of pixels in a block 99 | * - for any format (for static decode buffer allocation) 100 | * 101 | * Enums 102 | * ----- 103 | * TinyImageFormat - Count entries, one for each format supported 104 | * LogicalChannel - values for logical channel or constants 105 | * - LC_Red - Red channel is specified 106 | * - LC_Green - Green channel is specified 107 | * - LC_Blue - Blue channel is specified 108 | * - LC_Alpha - Alpha channel is specified 109 | * - LC_Depth - Depth channel is specified 110 | * - LC_Stencil - Stencil channel is specified 111 | * - LC_1 - constant 1 will be returned 112 | * - LC_0 - constant 0 will be return 113 | * PhysicalChannel - values for physical channel or constants 114 | * - PC_0 - Leftmost channel 115 | * - PC_1 - 2nd channel 116 | * - PC_2 - 3rd channel 117 | * - PC_3 - 4th channel 118 | * - PC_CONST_1 - constant 1 will be returned 119 | * - PC_CONST_0 - constant 0 will be return 120 | * 121 | * Structs 122 | * ------- 123 | * TinyImageFormat_DecodeInput 124 | * - pixel or pixelPlane0 - pixel data ptr or pixel data ptr for plane 0 125 | * - lut or pixelPlane1 - Look Up Table ptr for CLUT formats or pixel plane 1 126 | * - pixelPlane2 to pixelPlane 9 - 7 more planes ptrs 127 | * TinyImageFormat_EncodeOutput 128 | * - pixel or pixelPlane0 - pixel data ptr or pixel data ptr for plane 0 129 | * - pixelPlane2 to pixelPlane 9 - 8 more planes ptrs 130 | 131 | * Query Functions 132 | * ----------- 133 | * Code - uint64_t with the internal descriptor code 134 | * Name - Human C string with the name of this fmt 135 | * FromName - lookup the format given the name as a C String (fast) 136 | * IsDepthOnly - true if just a depth channel 137 | * IsStencilOnly - true if just a stencil channel 138 | * IsDepthAndStencil - if has both depth and stencil channel 139 | * IsCompressed - true if its a compressed format (aka block) 140 | * IsCLUT - true if data is index into a CLUT (Colour Look Up Table) 141 | * IsFloat - is the data in floating point 142 | * IsNormalised - return true if data will be within 0 to 1 or -1 to 1 143 | * IsSigned - does the data include negatives 144 | * IsSRGB - is the data encoded using sRGB non linear encoding 145 | * IsHomogenous - is the encoding the same for every channel 146 | * WidthOfBlock - How many pixels in the x dimension for a block 147 | * HeightOfBlock - How many pixels in the y dimension for a block 148 | * DepthOfBlock - How many pixels in the z dimension for a block 149 | * PixelCountOfBlock - How many pixels in total for a block 150 | * BitSizeOfBlock - How big in bits is a single block. 151 | * ChannelCount - How many channels are actually encoded 152 | * 153 | * Logical Channel Functions 154 | * ------------------------- 155 | * ChannelBitWidth( logical channel ) - how wide in bits is the channel 156 | * Min( logical channel ) - minimum possible value for the channel 157 | * Max( logical channel ) - maximum possible value for the channel 158 | * LogicalChannelToPhysical( logical channel ) 159 | * - what physical channel is the logical channel stored in 160 | * - or constant 0 or 1 if its not physically stored 161 | * 162 | * Pixel Decoder Functions (X = F or D version, use F if possible as its faster) 163 | * ----------------------- 164 | * CanDecodeLogicalPixelsX - Can DecodeLogicalPixelsX work with this format? 165 | * DecodeLogicalPixelsX( width in blocks, FetchInput, out pixels) 166 | * - pixels should be a pointer to 4 * PixelCounfOfBlack float/doubles 167 | * - does full decode and remapping into logical channels include constants. 168 | * - Returned result can be used directly as RGBA floating point data 169 | * - Input pointers are updated are used, so can be passed back in for 170 | * - next set of pixel decoding if desired. 171 | * - For CLUT formats in.pixel should be the packed pixel data and in.lut is 172 | * - the lookuptable in R8G8B8A8 format of 2^Pbits entries 173 | * - For all others in.pixel should be the packed pixel data 174 | * Pixel Decoder Helper Functions 175 | * ----------------------- 176 | * UFloat6AsUintToFloat - returns the value stored as a 6 bit UFloat 177 | * UFloat7AsUintToFloat - returns the value stored as a 7 bit UFloat 178 | * UFloat10AsUintToFloat - returns the value stored as a 10 bit UFloat 179 | * UFloat11AsUintToFloat - returns the value stored as a 11 bit UFloat 180 | * SharedE5B9G9R9UFloatToFloats - return the pixel stored in shared 181 | * - shared 5 bit exponent, 9 bit mantissa for RGB 182 | * HalfAsUintToFloat - returns the value stored as a 16 bit SFloat 183 | * BFloatAsUintToFloat - returns the value stored as a 16 bit BFloat 184 | * LookupSRGB - returns the value for an 8 bit sRGB encoded value 185 | * 186 | * Pixel Encoder Functions (X = F or D version, use F if possible as its faster) 187 | * ----------------------- 188 | * CanEncodeLogicalPixelsX - Can EncodeLogicalPixelsX work with this format? 189 | * EncodeLogicalPixelsX( width in blocks, in pixels, PutOutput) 190 | * - pixels should be a pointer to 4 * PixelCounfOfBlack float/doubles 191 | * - does full encode and remapping into logical channels 192 | * - Output pointers are updated are used, so can be passed back in for 193 | * - next set of pixel encoding if desired. 194 | * - out.pixel is where colour information should be stored 195 | * 196 | * Pixel Encoder Helper Functions 197 | * ----------------------- 198 | * FloatToUFloat6AsUint - Encodes float into a 6 bit UFloat 199 | * FloatToUFloat7AsUint - Encodes float into a 7 bit UFloat 200 | * FloatToUFloat10AsUint - Encodes float into a 10 bit UFloat 201 | * FloatToUFloat11AsUint - Encodes float into 11 bit UFloat 202 | * FloatRGBToRGB9E5AsUint32 - Encodes a float RGB into RGB9E5 203 | * FloatToHalfAsUint - Encodes a float into a 16 bit SFloat 204 | * FloatToBFloatAsUint - Encodes a float into a 16 bit BFloat 205 | * FloatToSRGB - encodes a float to sRGB assuming input is 0-1 206 | * 207 | * Physical Channel Functions (in general use the Logical Channels) 208 | * ------------------ 209 | * ChannelBitWidthAtPhysical( phys channel ) - how wide in bits for this channel 210 | * MinAtPhysical( phys channel ) - min possible value for this channel 211 | * MaxAtPhysical( phys channel ) - max possible value for this channel 212 | * PhysicalChannelToLogical(phys channel) 213 | * - what logical channel does a physical channel map to. 214 | * - Or a constant 0 or 1 215 | * 216 | * Graphics API Functions 217 | * ------------------ 218 | * FromVkFormat( VkFormat ) - converts from or UNDEFINED if not possible 219 | * ToVkFormat - converts to or VK_FORMAT_UNDEFINED if not possible 220 | * FromDXGI_FORMAT( DXGI_FORMAT) converts from or UNDEFINED if not possible 221 | * ToDXGI_FORMAT - converts to or DXGI_FORMAT_UNKNOWN if not possible 222 | * DXGI_FORMATToTypeless - returns the DXGI typeless format if possible 223 | * FromMetal( MTLPixelFormat ) - converts from or UNDEFINED if not possible 224 | * ToMetal - converts to or MTLPixelFormatInvalid if not possible 225 | * 226 | * 227 | */ 228 | RAW_INCLUDE_END( )=====" ) -------------------------------------------------------------------------------- /src/dummy.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/encodehelpers.h: -------------------------------------------------------------------------------- 1 | RAW_INCLUDE_START( R"=====( ) 2 | 3 | // from D3DX_DXGIFormatConvert.inl 4 | inline uint8_t TinyImageFormat_FloatToSRGB(float v) { 5 | if (v < 0.0031308f) { 6 | v *= 12.92f; 7 | } else { 8 | v = 1.055f * powf(v, 1.0f / 2.4f) - 0.055f; 9 | } 10 | return (uint8_t)v; 11 | } 12 | 13 | //Float2Half from Rygorous public domain code 14 | inline uint16_t TinyImageFormat_FloatToHalfAsUint(float f_) { 15 | union { 16 | uint16_t u; 17 | struct { 18 | uint16_t Mantissa : 10; 19 | uint16_t Exponent : 5; 20 | uint16_t Sign : 1; 21 | }; 22 | } o; 23 | 24 | union { 25 | uint32_t u; 26 | float f; 27 | struct { 28 | uint32_t Mantissa : 23; 29 | uint32_t Exponent : 8; 30 | uint32_t Sign : 1; 31 | }; 32 | } f; 33 | 34 | static uint32_t const f32infty = {255 << 23}; 35 | static uint32_t const f16max = {(127 + 16) << 23}; 36 | static uint32_t const denorm_magicU = {((127 - 15) + (23 - 10) + 1) << 23}; 37 | static uint32_t const sign_mask = 0x80000000u; 38 | 39 | float const denorm_magic = *(float const*)(&denorm_magicU); 40 | 41 | o.u = 0; 42 | f.f = f_; 43 | 44 | uint32_t const sign = f.u & sign_mask; 45 | f.u ^= sign; 46 | 47 | // NOTE all the integer compares in this function can be safely 48 | // compiled into signed compares since all operands are below 49 | // 0x80000000. Important if you want fast straight SSE2 code 50 | // (since there's no unsigned PCMPGTD). 51 | 52 | if (f.u >= f16max) { // result is Inf or NaN (all exponent bits set) 53 | o.u = (f.u > f32infty) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf 54 | } else // (De)normalized number or zero 55 | { 56 | if (f.u < (113 << 23)) // resulting FP16 is subnormal or zero 57 | { 58 | // use a magic value to align our 10 mantissa bits at the bottom of 59 | // the float. as long as FP addition is round-to-nearest-even this 60 | // just works. 61 | f.f += denorm_magic; 62 | 63 | // and one integer subtract of the bias later, we have our final float! 64 | o.u = f.u - denorm_magicU; 65 | } else { 66 | uint32_t mant_odd = (f.u >> 13) & 1; // resulting mantissa is odd 67 | 68 | // update exponent, rounding bias part 1 69 | f.u += 0xc8000fff; 70 | // rounding bias part 2 71 | f.u += mant_odd; 72 | // take the bits! 73 | o.u = f.u >> 13; 74 | } 75 | } 76 | 77 | o.u |= sign >> 16; 78 | return o.u; 79 | } 80 | 81 | inline uint16_t TinyImageFormat_FloatToBFloatAsUint(float v) { 82 | union { 83 | struct { 84 | uint16_t x; 85 | uint16_t u; 86 | }; 87 | float f; 88 | } o; 89 | 90 | o.f = v; 91 | o.x = 0; 92 | 93 | return o.u; 94 | } 95 | 96 | inline void TinyImageFormat_FloatRGBToRGB9E5AsUint32(float const* in, uint32_t* out) { 97 | float const r = in[0]; 98 | float const g = in[1]; 99 | float const b = in[2]; 100 | float const v = r > g ? r > b ? r : b : g > b ? g : b; 101 | 102 | 103 | union 104 | { 105 | struct 106 | { 107 | uint32_t rm : 9; 108 | uint32_t gm : 9; 109 | uint32_t bm : 9; 110 | uint32_t e : 5; 111 | }; 112 | uint32_t v; 113 | } ei; 114 | 115 | if (v < 1.52587890625e-5f) { 116 | *out = 0; 117 | } else if (v < 65536) { 118 | int ex; 119 | float m = frexpf(v, &ex) * 512.0f / v; 120 | 121 | ei.rm = (uint32_t)(m * r); 122 | ei.gm = (uint32_t)(m * g); 123 | ei.bm = (uint32_t)(m * b); 124 | ei.e = (unsigned int) (ex + 15); 125 | *out = ei.v; 126 | } else { 127 | ei.rm = (r < 65536) ? (uint32_t)(r * (1.0f / 128.0f)) : 0x1FF; 128 | ei.gm = (g < 65536) ? (uint32_t)(g * (1.0f / 128.0f)) : 0x1FF; 129 | ei.bm = (b < 65536) ? (uint32_t)(b * (1.0f / 128.0f)) : 0x1FF; 130 | ei.e = 31; 131 | *out = ei.v; 132 | } 133 | } 134 | 135 | inline uint16_t TinyImageFormat_FloatToUFloat6AsUint(float Value) 136 | { 137 | uint32_t IValue = *((uint32_t *)&Value); 138 | 139 | if (IValue & 0x80000000U) 140 | { 141 | // Positive only 142 | return 0; 143 | } 144 | else if (IValue > 0x43FEFFFFU) 145 | { 146 | // The number is too large to be represented as a 6e4. Saturate. 147 | return 0x3FFU; 148 | } 149 | else 150 | { 151 | if (IValue < 0x3C800000U) 152 | { 153 | // The number is too small to be represented as a normalized 6e4. 154 | // Convert it to a denormalized value. 155 | uint32_t Shift = 121U - (IValue >> 23U); 156 | if(Shift < 24U) Shift = 24U; 157 | 158 | IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift; 159 | } 160 | else 161 | { 162 | // Rebias the exponent to represent the value as a normalized 6e4. 163 | IValue += 0xC4000000U; 164 | } 165 | 166 | return (uint16_t)(((IValue + 0xFFFFU + ((IValue >> 17U) & 1U)) >> 17U) & 0x3FFU); 167 | } 168 | } 169 | 170 | inline uint16_t TinyImageFormat_FloatToUFloat7AsUint(float Value) 171 | { 172 | uint32_t IValue = *((uint32_t *)&Value); 173 | 174 | if (IValue & 0x80000000U) 175 | { 176 | // Positive only 177 | return 0; 178 | } 179 | else if (IValue > 0x41FF73FFU) 180 | { 181 | // The number is too large to be represented as a 7e3. Saturate. 182 | return 0x3FFU; 183 | } 184 | else 185 | { 186 | if (IValue < 0x3E800000U) 187 | { 188 | // The number is too small to be represented as a normalized 7e3. 189 | // Convert it to a denormalized value. 190 | uint32_t Shift = 125U - (IValue >> 23U); 191 | if(Shift < 24U) Shift = 24U; 192 | 193 | IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift; 194 | } 195 | else 196 | { 197 | // Rebias the exponent to represent the value as a normalized 7e3. 198 | IValue += 0xC2000000U; 199 | } 200 | 201 | return (uint16_t)(((IValue + 0x7FFFU + ((IValue >> 16U) & 1U)) >> 16U) & 0x3FFU); 202 | } 203 | } 204 | 205 | inline uint16_t TinyImageFormat_FloatToUFloat10AsUint(float v) { 206 | union { 207 | uint32_t u; 208 | float f; 209 | struct { 210 | uint32_t Mantissa : 23; 211 | uint32_t Exponent : 8; 212 | uint32_t Sign : 1; 213 | }; 214 | } o; 215 | union { 216 | struct { 217 | uint16_t e : 5; 218 | uint16_t m : 5; 219 | uint16_t x : 6; // not used 220 | }; 221 | uint16_t v; 222 | } ei; 223 | 224 | o.f = v; 225 | ei.v = 0; 226 | 227 | // positive only, so clamp to zero 228 | if(o.Sign) return 0; 229 | 230 | // 5-bit exponent, 5-bit mantissa 231 | 232 | // INF or NAN 233 | if (o.Exponent == 0xFF) { 234 | if ( o.Mantissa != 0) { 235 | return 0x3e0 | (((o.u>>18)|(o.u>>11)|(o.u>>6)|(o.u))&0x3f); 236 | } else { 237 | return 0x3e0; 238 | } 239 | } else if (o.u > 0x477C0000U) { 240 | // The number is too large to be represented as a float10, set to max 241 | return 0x3df; 242 | } 243 | else if (o.u < 0x38800000U) { 244 | // The number is too small to be represented as a normalized float11 245 | // Convert it to a denormalized value. 246 | ei.e = 0; 247 | ei.m = o.Mantissa >> (113U - o.Exponent); 248 | } else { 249 | // Rebias the exponent to represent the value as a normalized float11 250 | ei.e = o.Exponent + 16; 251 | ei.m = o.Mantissa >> 18; 252 | } 253 | 254 | return ei.v; 255 | } 256 | 257 | inline uint16_t TinyImageFormat_FloatToUFloat11AsUint(float v) { 258 | union { 259 | uint32_t u; 260 | float f; 261 | struct { 262 | uint32_t Mantissa : 23; 263 | uint32_t Exponent : 8; 264 | uint32_t Sign : 1; 265 | }; 266 | } o; 267 | union { 268 | struct { 269 | uint16_t e : 5; 270 | uint16_t m : 6; 271 | uint16_t x : 5; // not used 272 | }; 273 | uint16_t v; 274 | } ei; 275 | 276 | o.f = v; 277 | ei.v = 0; 278 | 279 | // positive only, so clamp to zero 280 | if(o.Sign) return 0; 281 | 282 | // 5-bit exponent, 6-bit mantissa) 283 | 284 | // INF or NAN 285 | if (o.Exponent == 0xFF) { 286 | if ( o.Mantissa != 0) { 287 | return 0x7c0 | (((o.u>>17)|(o.u>>11)|(o.u>>6)|(o.u))&0x3f); 288 | } else { 289 | return 0x7c0; 290 | } 291 | } else if (o.u > 0x477C0000U) { 292 | // The number is too large to be represented as a float11, set to max 293 | return 0x7BF; 294 | } 295 | else if (o.u < 0x38800000U) { 296 | // The number is too small to be represented as a normalized float11 297 | // Convert it to a denormalized value. 298 | ei.e = 0; 299 | ei.m = o.Mantissa >> (113U - o.Exponent); 300 | } else { 301 | // Rebias the exponent to represent the value as a normalized float11 302 | ei.e = o.Exponent + 16; 303 | ei.m = o.Mantissa >> 17; 304 | } 305 | 306 | return ei.v; 307 | } 308 | 309 | RAW_INCLUDE_END( )=====" ) -------------------------------------------------------------------------------- /src/formatgen.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #define __STDC_FORMAT_MACROS 5 | #include 6 | #include "al2o3_vfile/vfile.h" 7 | #include "formatgen.h" 8 | /* 9 | * Implementation Details 10 | * ---------------------- 11 | * Format Namespaces 12 | * Internally formats are split into sets called namespace with completely 13 | * different descriptor encodings. The largest is the PACK namespace which can 14 | * encode a huge range of packed pixel formats. The enumerations are just 15 | * the common cases. 16 | * Each compression family has its own namespace and also colour look up tables. 17 | * Shared component and various video formats are on the list of things TODO. 18 | * 19 | * The namespace size is huge, allowing for many different future formats. 20 | * 21 | * PACK namespace 22 | * The name of the format specifies exactly the channel order with only one 23 | * factor the PACK special bit. 24 | * If a format can be encoded word aligned (8, 16, 32, 64 bit alignment) then 25 | * PACK isn't set and the physical channel is read left to right 26 | * so R8G8B8A8 is R = PC_0, G = PC_1, B = PC_2, A = PC_3 and can would be read 27 | * uint8_t* data = ...; 28 | * R = data[0]; 29 | * G = data[1]; 30 | * B = data[2]; 31 | * A = data[3]; 32 | * If a format can't be simply decoded via word aligned reads then the PACK bit 33 | * is set and then the names leftsmost element is the lowest bit position going 34 | * up as you read across the format name to the right. 35 | * The actual bit size of each channel is read from the descriptor code. 36 | * so R5G5B5A1 is the first lowest 5 bits being R, next 5 is G then B and the last 37 | * bit being A. 38 | * uint16_t data; 39 | * R = (data >> 0) & 0x1f; 40 | * G = (data >> 5) & 0x1f; 41 | * B = (data >> 10) & 0x1f; 42 | * A = (data >> 15) & 0x1; 43 | * Future Note: The pack special bit insn't need anymore I think it may be 44 | * removed in a future version but its an internal details so won't 45 | * affect the API 46 | * 47 | */ 48 | 49 | void GenEnums(VFile_Handle file); 50 | void GenStructs(VFile_Handle file); 51 | void GenCount(VFile_Handle file); 52 | void GenQuerys(VFile_Handle file); 53 | void GenDecode(VFile_Handle file); 54 | void GenEncode(VFile_Handle file); 55 | void GenAPIsEnums(VFile_Handle file); 56 | 57 | void IncludeDocs(VFile_Handle file) { 58 | #define RAW_INCLUDE_START(x) x 59 | char const *otherEnums = 60 | #include "doc.h" 61 | ""; 62 | #undef RAW_INCLUDE_START 63 | 64 | // skip first ) and last line, artifacts of the include system 65 | char const *start = otherEnums; 66 | while (*start != ')') 67 | start++; 68 | 69 | char const *end = otherEnums + strlen(otherEnums); 70 | while (*end != 'R') 71 | end--; 72 | 73 | VFile_Write(file, start + 1, end - start - 1); 74 | } 75 | 76 | 77 | 78 | int main(int argc, char const *argv[]) { 79 | 80 | uint8_t rgbac[4] { 0xF0, 0x0F, 0x0, 0xFF }; 81 | uint32_t* rgba32 = (uint32_t*) rgbac; 82 | uint8_t r = rgbac[0]; 83 | uint8_t r2 = *rgba32 >> 0; 84 | uint8_t a = rgbac[3]; 85 | uint8_t a2 = *rgba32 >> 24; 86 | 87 | if(r != r2 || a != a2) { 88 | LOGERROR("Non Little Endian machine. This currently only generated a header for LE"); 89 | return 10; 90 | } 91 | 92 | char const header[] = 93 | "// Auto generated by formatgen on " __DATE__ "\n" 94 | "#pragma once\n"; 95 | 96 | char const splitguard[] = 97 | "#if !defined(%s) && !defined(TINYIMAGEFORMAT_IMAGEFORMAT_H)\n" 98 | "#define %s 1\n"; 99 | 100 | char const singleguard[] = 101 | "#if !defined(TINYIMAGEFORMAT_IMAGEFORMAT_H)\n" 102 | "#define TINYIMAGEFORMAT_IMAGEFORMAT_H 1\n"; 103 | 104 | char const subguard[] = 105 | "#if !defined(%s)\n" 106 | "#define %s 1\n"; 107 | 108 | 109 | char const header2[] = 110 | "\n" 111 | "#if __cplusplus > 201402L\n" 112 | "#define TIF_CONSTEXPR constexpr extern \"C\"\n" 113 | "#else\n" 114 | "#define TIF_CONSTEXPR\n" 115 | "#endif\n" 116 | "#ifndef TinyImageFormat_HAVE_UINTXX_T\n" 117 | "#include // for uint32_t and int64_t\n" 118 | "#endif\n" 119 | "#ifndef TinyImageFormat_HAVE_BOOL\n" 120 | "#include // for bool\n" 121 | "#endif\n" 122 | "#ifndef TinyImageFormat_HAVE_POWF\n" 123 | "#include // for powf\n" 124 | "#endif\n" 125 | "//TinyImageFormat_ASSERT needs to be constexpr on some platforms\n" 126 | "#ifndef TinyImageFormat_ASSERT\n" 127 | "#define TinyImageFormat_ASSERT(x)\n" 128 | "#endif\n" 129 | "\n"; 130 | char const suffix2[] = 131 | "#undef TIF_CONSTEXPR\n"; 132 | 133 | char const guardclose[] = 134 | "#endif // %s\n" 135 | "\n"; 136 | 137 | // generate single header 138 | { 139 | 140 | VFile_Handle file = VFile_FromFile("tinyimageformat.h", Os_FM_Write); 141 | VFile_Write(file, header, strlen(header)); 142 | VFile_Write(file, singleguard, strlen(singleguard)); 143 | IncludeDocs(file); 144 | VFile_Write(file, header2, strlen(header2)); 145 | 146 | char headerBuffer[2048]; 147 | char guardCloseBuffer[2048]; 148 | sprintf(headerBuffer, subguard, "TINYIMAGEFORMAT_BASE_H_", "TINYIMAGEFORMAT_BASE_H_"); 149 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 150 | GenEnums(file); 151 | GenCount(file); 152 | GenStructs(file); 153 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_BASE_H_"); 154 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 155 | 156 | 157 | sprintf(headerBuffer, subguard, "TINYIMAGEFORMAT_QUERY_H_", "TINYIMAGEFORMAT_QUERY_H_"); 158 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 159 | GenQuerys(file); 160 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGE_QUERY_H_"); 161 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 162 | 163 | sprintf(headerBuffer, subguard, "TINYIMAGEFORMAT_DECODE_H_", "TINYIMAGEFORMAT_DECODE_H_"); 164 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 165 | GenDecode(file); 166 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_DECODE_H_"); 167 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 168 | 169 | sprintf(headerBuffer, subguard, "TINYIMAGEFORMAT_ENCODE_H_", "TINYIMAGEFORMAT_ENCODE_H_"); 170 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 171 | GenEncode(file); 172 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_ENCODE_H_"); 173 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 174 | 175 | sprintf(headerBuffer, subguard, "TINYIMAGEFORMAT_APIS_H_", "TINYIMAGEFORMAT_APIS_H_"); 176 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 177 | GenAPIsEnums(file); 178 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_APIS_H_"); 179 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 180 | 181 | VFile_Write(file, suffix2, strlen(suffix2)); 182 | 183 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_H_"); 184 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 185 | 186 | VFile_Close(file); 187 | } 188 | // generate multi headers 189 | { 190 | { 191 | VFile_Handle file = VFile_FromFile("tinyimageformat_base.h", Os_FM_Write); 192 | VFile_Write(file, header, strlen(header)); 193 | char headerBuffer[2048]; 194 | sprintf(headerBuffer, splitguard, "TINYIMAGEFORMAT_BASE_H_", "TINYIMAGEFORMAT_BASE_H_"); 195 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 196 | IncludeDocs(file); 197 | 198 | GenEnums(file); 199 | GenCount(file); 200 | GenStructs(file); 201 | 202 | char guardCloseBuffer[2048]; 203 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_BASE_H_"); 204 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 205 | 206 | VFile_Close(file); 207 | } 208 | char const multiheader2[] = "\n#include \"tinyimageformat_base.h\"\n"; 209 | { 210 | VFile_Handle file = VFile_FromFile("tinyimageformat_query.h", Os_FM_Write); 211 | VFile_Write(file, header, strlen(header)); 212 | char headerBuffer[2048]; 213 | sprintf(headerBuffer, splitguard, "TINYIMAGEFORMAT_QUERY_H_", "TINYIMAGEFORMAT_QUERY_H_"); 214 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 215 | VFile_Write(file, multiheader2, strlen(multiheader2)); 216 | VFile_Write(file, header2, strlen(header2)); 217 | 218 | GenQuerys(file); 219 | 220 | VFile_Write(file, suffix2, strlen(suffix2)); 221 | char guardCloseBuffer[2048]; 222 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_QUERY_H_"); 223 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 224 | 225 | VFile_Close(file); 226 | } 227 | { 228 | VFile_Handle file = VFile_FromFile("tinyimageformat_decode.h", Os_FM_Write); 229 | VFile_Write(file, header, strlen(header)); 230 | char headerBuffer[2048]; 231 | sprintf(headerBuffer, splitguard, "TINYIMAGEFORMAT_DECODE_H_", "TINYIMAGEFORMAT_DECODE_H_"); 232 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 233 | VFile_Write(file, multiheader2, strlen(multiheader2)); 234 | VFile_Write(file, header2, strlen(header2)); 235 | 236 | GenDecode(file); 237 | 238 | VFile_Write(file, suffix2, strlen(suffix2)); 239 | char guardCloseBuffer[2048]; 240 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_DECODE_H_"); 241 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 242 | VFile_Close(file); 243 | } 244 | 245 | { 246 | VFile_Handle file = VFile_FromFile("tinyimageformat_encode.h", Os_FM_Write); 247 | VFile_Write(file, header, strlen(header)); 248 | char headerBuffer[2048]; 249 | sprintf(headerBuffer, splitguard, "TINYIMAGEFORMAT_ENCODE_H_", "TINYIMAGEFORMAT_ENCODE_H_"); 250 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 251 | VFile_Write(file, multiheader2, strlen(multiheader2)); 252 | VFile_Write(file, header2, strlen(header2)); 253 | 254 | GenEncode(file); 255 | 256 | VFile_Write(file, suffix2, strlen(suffix2)); 257 | char guardCloseBuffer[2048]; 258 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_ENCODE_H_"); 259 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 260 | VFile_Close(file); 261 | } 262 | { 263 | VFile_Handle file = VFile_FromFile("tinyimageformat_apis.h", Os_FM_Write); 264 | VFile_Write(file, header, strlen(header)); 265 | char headerBuffer[2048]; 266 | sprintf(headerBuffer, splitguard, "TINYIMAGEFORMAT_APIS_H_", "TINYIMAGEFORMAT_APIS_H_"); 267 | VFile_Write(file, headerBuffer, strlen(headerBuffer)); 268 | VFile_Write(file, multiheader2, strlen(multiheader2)); 269 | 270 | GenAPIsEnums(file); 271 | VFile_Write(file, suffix2, strlen(suffix2)); 272 | char guardCloseBuffer[2048]; 273 | sprintf(guardCloseBuffer, guardclose, "TINYIMAGEFORMAT_APIS_H_"); 274 | VFile_Write(file, guardCloseBuffer, strlen(guardCloseBuffer)); 275 | VFile_Close(file); 276 | } 277 | 278 | 279 | } 280 | return 0; 281 | } -------------------------------------------------------------------------------- /src/formatgen.h: -------------------------------------------------------------------------------- 1 | #if !defined( GFX_IMAGEFORMAT_FORMAT_H_ ) || defined( TinyImageFormat_START_MACRO ) 2 | 3 | #if !defined TinyImageFormat_START_MACRO 4 | 5 | #define GFX_IMAGEFORMAT_FORMAT_H_ 1 6 | #define TinyImageFormat_START_MACRO typedef enum class TinyImageFormat : uint64_t { 7 | 8 | #else 9 | 10 | #if !defined( TinyImageFormat_MOD_MACRO ) 11 | #error TinyImageFormat_START_MACRO set but not TinyImageFormat_MOD_MACRO 12 | #elif !defined( TinyImageFormat_END_MACRO ) 13 | #error TinyImageFormat_START_MACRO set but not TinyImageFormat_END_MACRO 14 | #endif 15 | 16 | #endif 17 | 18 | #if !defined TinyImageFormat_MOD_MACRO 19 | #define TinyImageFormat_MOD_MACRO(x, y) x = (y), 20 | #endif 21 | 22 | #if !defined TinyImageFormat_END_MACRO 23 | #define TinyImageFormat_END_MACRO } TinyImageFormat; 24 | #endif 25 | 26 | 27 | //--------- 28 | #include "tiny_imageformat/tinyimageformat_bits.h" 29 | #include "formatgen_func.h" 30 | #include "formatgen_macros.h" 31 | 32 | TinyImageFormat_START_MACRO 33 | TinyImageFormat_MOD_MACRO(UNDEFINED,0ULL) 34 | 35 | TinyImageFormat_MOD_MACRO(R1_UNORM, TinyImageFormat_PACK_1(R, 1, UNORM, MULTI8)) 36 | TinyImageFormat_MOD_MACRO(R2_UNORM, TinyImageFormat_PACK_1(R, 2, UNORM, MULTI4)) 37 | TinyImageFormat_MOD_MACRO(R4_UNORM, TinyImageFormat_PACK_1(R, 4, UNORM, MULTI2)) 38 | 39 | TinyImageFormat_MOD_MACRO(R4G4_UNORM, TinyImageFormat_PACK_2_UNORM(R, 4, G, 4, PACK)) 40 | TinyImageFormat_MOD_MACRO(G4R4_UNORM, TinyImageFormat_PACK_2_UNORM(G, 4, R, 4, PACK)) 41 | TinyImageFormat_MOD_MACRO(A8_UNORM, TinyImageFormat_PACK(A, 8, UNORM, _,_, _, _,_,_, _,_,_, NONE)) 42 | TinyImageFormat_MOD_MACRO(R8_UNORM, TinyImageFormat_PACK_1(R, 8, UNORM, NONE)) 43 | TinyImageFormat_MOD_MACRO(R8_SNORM, TinyImageFormat_PACK_1(R, 8, SNORM, NONE)) 44 | TinyImageFormat_MOD_MACRO(R8_UINT, TinyImageFormat_PACK_1(R, 8, UINT, NONE)) 45 | TinyImageFormat_MOD_MACRO(R8_SINT, TinyImageFormat_PACK_1(R, 8, SINT, NONE)) 46 | TinyImageFormat_MOD_MACRO(R8_SRGB, TinyImageFormat_PACK_1(R, 8, SRGB, NONE)) 47 | TinyImageFormat_MOD_MACRO(B2G3R3_UNORM, TinyImageFormat_PACK_3_UNORM(B, 2, G, 3, R, 3, PACK)) 48 | 49 | TinyImageFormat_MOD_MACRO(R4G4B4A4_UNORM, TinyImageFormat_PACK_4_UNORM(R, 4, G, 4, B, 4, A, 4, PACK)) 50 | TinyImageFormat_MOD_MACRO(R4G4B4X4_UNORM, TinyImageFormat_PACK_4_UNORM(R, 4, G, 4, B, 4, 1, 4, PACK)) 51 | TinyImageFormat_MOD_MACRO(B4G4R4A4_UNORM, TinyImageFormat_PACK_4_UNORM(B, 4, G, 4, R, 4, A, 4, PACK)) 52 | TinyImageFormat_MOD_MACRO(B4G4R4X4_UNORM, TinyImageFormat_PACK_4_UNORM(B, 4, G, 4, R, 4, 1, 4, PACK)) 53 | TinyImageFormat_MOD_MACRO(A4R4G4B4_UNORM, TinyImageFormat_PACK_4_UNORM(A, 4, R, 4, G, 4, B, 4, PACK)) 54 | TinyImageFormat_MOD_MACRO(X4R4G4B4_UNORM, TinyImageFormat_PACK(1,4, UINT, R, 4, UNORM, G, 4, UNORM, B, 4, UNORM, PACK)) 55 | TinyImageFormat_MOD_MACRO(A4B4G4R4_UNORM, TinyImageFormat_PACK_4_UNORM(A, 4, B, 4, G, 4, R, 4, PACK)) 56 | TinyImageFormat_MOD_MACRO(X4B4G4R4_UNORM, TinyImageFormat_PACK(1,4, UINT, B, 4, UNORM, G, 4, UNORM, R, 4, UNORM, PACK)) 57 | 58 | TinyImageFormat_MOD_MACRO(R5G6B5_UNORM, TinyImageFormat_PACK_3(R,5, UNORM, G, 6, UNORM, B, 5, UNORM, PACK)) 59 | TinyImageFormat_MOD_MACRO(B5G6R5_UNORM, TinyImageFormat_PACK_3(B,5, UNORM, G, 6, UNORM, R, 5, UNORM, PACK)) 60 | TinyImageFormat_MOD_MACRO(R5G5B5A1_UNORM, TinyImageFormat_PACK_4_UNORM(R,5, G, 5, B, 5, A, 1, PACK)) 61 | TinyImageFormat_MOD_MACRO(B5G5R5A1_UNORM, TinyImageFormat_PACK_4_UNORM(B,5, G, 5, R, 5, A, 1, PACK)) 62 | TinyImageFormat_MOD_MACRO(A1B5G5R5_UNORM, TinyImageFormat_PACK_4_UNORM(A, 1, B, 5, G, 5, R, 5, PACK)) 63 | TinyImageFormat_MOD_MACRO(A1R5G5B5_UNORM, TinyImageFormat_PACK_4_UNORM(A, 1, R, 5, G, 5, B, 5, PACK)) 64 | TinyImageFormat_MOD_MACRO(R5G5B5X1_UNORM, TinyImageFormat_PACK(R,5, UNORM, G, 5, UNORM, B, 5, UNORM, 1, 1, UINT, PACK)) 65 | TinyImageFormat_MOD_MACRO(B5G5R5X1_UNORM, TinyImageFormat_PACK(B,5, UNORM, G, 5, UNORM, R, 5, UNORM, 1, 1, UINT, PACK)) 66 | TinyImageFormat_MOD_MACRO(X1R5G5B5_UNORM, TinyImageFormat_PACK(1, 1, UINT, R, 5, UNORM, G, 5, UNORM, B, 5, UNORM, PACK)) 67 | TinyImageFormat_MOD_MACRO(X1B5G5R5_UNORM, TinyImageFormat_PACK(1, 1, UINT, B, 5, UNORM, G, 5, UNORM, R, 5, UNORM, PACK)) 68 | 69 | TinyImageFormat_MOD_MACRO(B2G3R3A8_UNORM, TinyImageFormat_PACK_4_UNORM(B, 2, G, 3, R, 3, A, 8, PACK)) 70 | 71 | TinyImageFormat_MOD_MACRO(R8G8_UNORM, TinyImageFormat_PACK_2_UNORM(R, 8, G, 8, NONE)) 72 | TinyImageFormat_MOD_MACRO(R8G8_SNORM, TinyImageFormat_PACK_2_SNORM(R, 8, G, 8, NONE)) 73 | TinyImageFormat_MOD_MACRO(G8R8_UNORM, TinyImageFormat_PACK_2_UNORM(G, 8, R, 8, NONE)) 74 | TinyImageFormat_MOD_MACRO(G8R8_SNORM, TinyImageFormat_PACK_2_SNORM(G, 8, R, 8, NONE)) 75 | 76 | TinyImageFormat_MOD_MACRO(R8G8_UINT, TinyImageFormat_PACK_2_UINT(R, 8, G, 8, NONE)) 77 | TinyImageFormat_MOD_MACRO(R8G8_SINT, TinyImageFormat_PACK_2_SINT(R, 8, G, 8, NONE)) 78 | TinyImageFormat_MOD_MACRO(R8G8_SRGB, TinyImageFormat_PACK_2_SRGB(R, 8, G, 8, NONE)) 79 | TinyImageFormat_MOD_MACRO(R16_UNORM, TinyImageFormat_PACK_1(R, 16, UNORM, NONE)) 80 | TinyImageFormat_MOD_MACRO(R16_SNORM, TinyImageFormat_PACK_1(R, 16, SNORM, NONE)) 81 | TinyImageFormat_MOD_MACRO(R16_UINT, TinyImageFormat_PACK_1(R, 16, UINT, NONE)) 82 | TinyImageFormat_MOD_MACRO(R16_SINT, TinyImageFormat_PACK_1(R, 16, SINT, NONE)) 83 | TinyImageFormat_MOD_MACRO(R16_SFLOAT, TinyImageFormat_PACK_1(R, 16, SFLOAT, NONE)) 84 | TinyImageFormat_MOD_MACRO(R16_SBFLOAT, TinyImageFormat_PACK_1(R, 16, SBFLOAT, NONE)) 85 | 86 | TinyImageFormat_MOD_MACRO(R8G8B8_UNORM, TinyImageFormat_PACK_3_UNORM(R, 8, G, 8, B, 8, NONE)) 87 | TinyImageFormat_MOD_MACRO(R8G8B8_SNORM, TinyImageFormat_PACK_3_SNORM(R, 8, G, 8, B, 8, NONE)) 88 | TinyImageFormat_MOD_MACRO(R8G8B8_UINT, TinyImageFormat_PACK_3_UINT(R, 8, G, 8, B, 8, NONE)) 89 | TinyImageFormat_MOD_MACRO(R8G8B8_SINT, TinyImageFormat_PACK_3_SINT(R, 8, G, 8, B, 8, NONE)) 90 | TinyImageFormat_MOD_MACRO(R8G8B8_SRGB, TinyImageFormat_PACK_3_SRGB(R, 8, G, 8, B, 8, NONE)) 91 | 92 | TinyImageFormat_MOD_MACRO(B8G8R8_UNORM, TinyImageFormat_PACK_3_UNORM(B, 8, G, 8, R, 8, NONE)) 93 | TinyImageFormat_MOD_MACRO(B8G8R8_SNORM, TinyImageFormat_PACK_3_SNORM(B, 8, G, 8, R, 8, NONE)) 94 | TinyImageFormat_MOD_MACRO(B8G8R8_UINT, TinyImageFormat_PACK_3_UINT(B, 8, G, 8, R, 8, NONE)) 95 | TinyImageFormat_MOD_MACRO(B8G8R8_SINT, TinyImageFormat_PACK_3_SINT(B, 8, G, 8, R, 8, NONE)) 96 | TinyImageFormat_MOD_MACRO(B8G8R8_SRGB, TinyImageFormat_PACK_3_SRGB(B, 8, G, 8, R, 8, NONE)) 97 | 98 | TinyImageFormat_MOD_MACRO(R8G8B8A8_UNORM, TinyImageFormat_PACK_4_UNORM(R, 8, G, 8, B, 8, A, 8, NONE)) 99 | TinyImageFormat_MOD_MACRO(R8G8B8A8_SNORM, TinyImageFormat_PACK_4_SNORM(R, 8, G, 8, B, 8, A, 8, NONE)) 100 | TinyImageFormat_MOD_MACRO(R8G8B8A8_UINT, TinyImageFormat_PACK_4_UINT(R, 8, G, 8, B, 8, A, 8, NONE)) 101 | TinyImageFormat_MOD_MACRO(R8G8B8A8_SINT, TinyImageFormat_PACK_4_SINT(R, 8, G, 8, B, 8, A, 8, NONE)) 102 | TinyImageFormat_MOD_MACRO(R8G8B8A8_SRGB, TinyImageFormat_PACK_4_SRGB(R, 8, G, 8, B, 8, A, 8, NONE)) 103 | 104 | TinyImageFormat_MOD_MACRO(B8G8R8A8_UNORM, TinyImageFormat_PACK_4_UNORM(B, 8, G, 8, R, 8, A, 8, NONE)) 105 | TinyImageFormat_MOD_MACRO(B8G8R8A8_SNORM, TinyImageFormat_PACK_4_SNORM(B, 8, G, 8, R, 8, A, 8, NONE)) 106 | TinyImageFormat_MOD_MACRO(B8G8R8A8_UINT, TinyImageFormat_PACK_4_UINT(B, 8, G, 8, R, 8, A, 8, NONE)) 107 | TinyImageFormat_MOD_MACRO(B8G8R8A8_SINT, TinyImageFormat_PACK_4_SINT(B, 8, G, 8, R, 8, A, 8, NONE)) 108 | TinyImageFormat_MOD_MACRO(B8G8R8A8_SRGB, TinyImageFormat_PACK_4_SRGB(B, 8, G, 8, R, 8, A, 8, NONE)) 109 | 110 | TinyImageFormat_MOD_MACRO(R8G8B8X8_UNORM, TinyImageFormat_PACK(R, 8, UNORM, G, 8, UNORM, B, 8, UNORM, 1, 8, UNORM, NONE)) 111 | TinyImageFormat_MOD_MACRO(B8G8R8X8_UNORM, TinyImageFormat_PACK(B, 8, UNORM, G, 8, UNORM, R, 8, UNORM, 1, 8, UNORM, NONE)) 112 | 113 | TinyImageFormat_MOD_MACRO(R16G16_UNORM, TinyImageFormat_PACK_2_UNORM(R, 16, G, 16, NONE)) 114 | TinyImageFormat_MOD_MACRO(G16R16_UNORM, TinyImageFormat_PACK_2_UNORM(G, 16, R, 16, NONE)) 115 | 116 | TinyImageFormat_MOD_MACRO(R16G16_SNORM, TinyImageFormat_PACK_2_SNORM(R, 16, G, 16, NONE)) 117 | TinyImageFormat_MOD_MACRO(G16R16_SNORM, TinyImageFormat_PACK_2_SNORM(G, 16, R, 16, NONE)) 118 | 119 | TinyImageFormat_MOD_MACRO(R16G16_UINT, TinyImageFormat_PACK_2_UINT(R, 16, G, 16, NONE)) 120 | TinyImageFormat_MOD_MACRO(R16G16_SINT, TinyImageFormat_PACK_2_SINT(R, 16, G, 16, NONE)) 121 | TinyImageFormat_MOD_MACRO(R16G16_SFLOAT, TinyImageFormat_PACK_2_SFLOAT(R, 16, G, 16, NONE)) 122 | TinyImageFormat_MOD_MACRO(R16G16_SBFLOAT, TinyImageFormat_PACK_2(R, 16, SBFLOAT, G, 16, SBFLOAT, NONE)) 123 | 124 | TinyImageFormat_MOD_MACRO(R32_UINT, TinyImageFormat_PACK_1(R, 32, UINT, NONE)) 125 | TinyImageFormat_MOD_MACRO(R32_SINT, TinyImageFormat_PACK_1(R, 32, SINT, NONE)) 126 | TinyImageFormat_MOD_MACRO(R32_SFLOAT, TinyImageFormat_PACK_1(R, 32, SFLOAT, NONE)) 127 | 128 | TinyImageFormat_MOD_MACRO(A2R10G10B10_UNORM, TinyImageFormat_PACK_4_UNORM(A, 2, R, 10, G, 10, B, 10, PACK)) 129 | TinyImageFormat_MOD_MACRO(A2R10G10B10_UINT, TinyImageFormat_PACK_4_UINT(A, 2, R, 10, G, 10, B, 10, PACK)) 130 | TinyImageFormat_MOD_MACRO(A2R10G10B10_SNORM, TinyImageFormat_PACK_4_SNORM(A, 2, R, 10, G, 10, B, 10, PACK)) 131 | TinyImageFormat_MOD_MACRO(A2R10G10B10_SINT, TinyImageFormat_PACK_4_SINT(A, 2, R, 10, G, 10, B, 10, PACK)) 132 | TinyImageFormat_MOD_MACRO(A2B10G10R10_UNORM, TinyImageFormat_PACK_4_UNORM(A, 2, B, 10, G, 10, R, 10, PACK)) 133 | TinyImageFormat_MOD_MACRO(A2B10G10R10_UINT, TinyImageFormat_PACK_4_UINT(A, 2, B, 10, G, 10, R, 10, PACK)) 134 | TinyImageFormat_MOD_MACRO(A2B10G10R10_SNORM, TinyImageFormat_PACK_4_SNORM(A, 2, B, 10, G, 10, R, 10, PACK)) 135 | TinyImageFormat_MOD_MACRO(A2B10G10R10_SINT, TinyImageFormat_PACK_4_SINT(A, 2, B, 10, G, 10, R, 10, PACK)) 136 | TinyImageFormat_MOD_MACRO(R10G10B10A2_UNORM, TinyImageFormat_PACK_4_UNORM(R, 10, G, 10, B, 10, A, 2, PACK)) 137 | TinyImageFormat_MOD_MACRO(R10G10B10A2_UINT, TinyImageFormat_PACK_4_UINT(R, 10, G, 10, B, 10, A, 2, PACK)) 138 | TinyImageFormat_MOD_MACRO(R10G10B10A2_SNORM, TinyImageFormat_PACK_4_SNORM(R, 10, G, 10, B, 10, A, 2, PACK)) 139 | TinyImageFormat_MOD_MACRO(R10G10B10A2_SINT, TinyImageFormat_PACK_4_SINT(R, 10, G, 10, B, 10, A, 2, PACK)) 140 | TinyImageFormat_MOD_MACRO(B10G10R10A2_UNORM, TinyImageFormat_PACK_4_UNORM(B, 10, G, 10, R, 10, A, 2, PACK)) 141 | TinyImageFormat_MOD_MACRO(B10G10R10A2_UINT, TinyImageFormat_PACK_4_UINT(B, 10, G, 10, R, 10, A, 2, PACK)) 142 | TinyImageFormat_MOD_MACRO(B10G10R10A2_SNORM, TinyImageFormat_PACK_4_SNORM(B, 10, G, 10, R, 10, A, 2, PACK)) 143 | TinyImageFormat_MOD_MACRO(B10G10R10A2_SINT, TinyImageFormat_PACK_4_SINT(B, 10, G, 10, R, 10, A, 2, PACK)) 144 | 145 | TinyImageFormat_MOD_MACRO(B10G11R11_UFLOAT, TinyImageFormat_PACK_3(B, 10, UFLOAT, G, 11, UFLOAT, R, 11, UFLOAT, PACK)) 146 | TinyImageFormat_MOD_MACRO(E5B9G9R9_UFLOAT, TinyImageFormat_PACK(A, 5, UINT, B, 9, UFLOAT, G, 9, UFLOAT, R, 9, UFLOAT, PACK)) 147 | 148 | TinyImageFormat_MOD_MACRO(R16G16B16_UNORM, TinyImageFormat_PACK_3_UNORM(R, 16, G, 16, B, 16, NONE)) 149 | TinyImageFormat_MOD_MACRO(R16G16B16_SNORM, TinyImageFormat_PACK_3_SNORM(R, 16, G, 16, B, 16, NONE)) 150 | TinyImageFormat_MOD_MACRO(R16G16B16_UINT, TinyImageFormat_PACK_3_UINT(R, 16, G, 16, B, 16, NONE)) 151 | TinyImageFormat_MOD_MACRO(R16G16B16_SINT, TinyImageFormat_PACK_3_SINT(R, 16, G, 16, B, 16, NONE)) 152 | TinyImageFormat_MOD_MACRO(R16G16B16_SFLOAT, TinyImageFormat_PACK_3_SFLOAT(R, 16, G, 16, B, 16, NONE)) 153 | TinyImageFormat_MOD_MACRO(R16G16B16_SBFLOAT, TinyImageFormat_PACK_3(R, 16, SBFLOAT, G, 16, SBFLOAT, B, 16, SBFLOAT, NONE)) 154 | 155 | TinyImageFormat_MOD_MACRO(R16G16B16A16_UNORM, TinyImageFormat_PACK_4_UNORM(R, 16, G, 16, B, 16, A, 16, NONE)) 156 | TinyImageFormat_MOD_MACRO(R16G16B16A16_SNORM, TinyImageFormat_PACK_4_SNORM(R, 16, G, 16, B, 16, A, 16, NONE)) 157 | TinyImageFormat_MOD_MACRO(R16G16B16A16_UINT, TinyImageFormat_PACK_4_UINT(R, 16, G, 16, B, 16, A, 16, NONE)) 158 | TinyImageFormat_MOD_MACRO(R16G16B16A16_SINT, TinyImageFormat_PACK_4_SINT(R, 16, G, 16, B, 16, A, 16, NONE)) 159 | TinyImageFormat_MOD_MACRO(R16G16B16A16_SFLOAT, TinyImageFormat_PACK_4_SFLOAT(R, 16, G, 16, B, 16, A, 16, NONE)) 160 | TinyImageFormat_MOD_MACRO(R16G16B16A16_SBFLOAT, TinyImageFormat_PACK(R, 16, SBFLOAT, G, 16, SBFLOAT, B, 16, SBFLOAT, A, 16, SBFLOAT, NONE)) 161 | 162 | TinyImageFormat_MOD_MACRO(R32G32_UINT, TinyImageFormat_PACK_2_UINT(R, 32, G, 32, NONE)) 163 | TinyImageFormat_MOD_MACRO(R32G32_SINT, TinyImageFormat_PACK_2_SINT(R, 32, G, 32, NONE)) 164 | TinyImageFormat_MOD_MACRO(R32G32_SFLOAT, TinyImageFormat_PACK_2_SFLOAT(R, 32, G, 32, NONE)) 165 | 166 | TinyImageFormat_MOD_MACRO(R32G32B32_UINT, TinyImageFormat_PACK_3_UINT(R, 32, G, 32, B, 32, NONE)) 167 | TinyImageFormat_MOD_MACRO(R32G32B32_SINT, TinyImageFormat_PACK_3_SINT(R, 32, G, 32, B, 32, NONE)) 168 | TinyImageFormat_MOD_MACRO(R32G32B32_SFLOAT, TinyImageFormat_PACK_3_SFLOAT(R, 32, G, 32, B, 32, NONE)) 169 | 170 | TinyImageFormat_MOD_MACRO(R32G32B32A32_UINT, TinyImageFormat_PACK_4_UINT(R, 32, G, 32, B, 32, A, 32, NONE)) 171 | TinyImageFormat_MOD_MACRO(R32G32B32A32_SINT, TinyImageFormat_PACK_4_SINT(R, 32, G, 32, B, 32, A, 32, NONE)) 172 | TinyImageFormat_MOD_MACRO(R32G32B32A32_SFLOAT, TinyImageFormat_PACK_4_SFLOAT(R, 32, G, 32, B, 32, A, 32, NONE)) 173 | 174 | TinyImageFormat_MOD_MACRO(R64_UINT, TinyImageFormat_PACK_1(R, 64, UINT, NONE)) 175 | TinyImageFormat_MOD_MACRO(R64_SINT, TinyImageFormat_PACK_1(R, 64, SINT, NONE)) 176 | TinyImageFormat_MOD_MACRO(R64_SFLOAT, TinyImageFormat_PACK_1(R, 64, SFLOAT, NONE)) 177 | 178 | TinyImageFormat_MOD_MACRO(R64G64_UINT, TinyImageFormat_PACK_2_UINT(R, 64, G, 64, NONE)) 179 | TinyImageFormat_MOD_MACRO(R64G64_SINT, TinyImageFormat_PACK_2_SINT(R, 64, G, 64, NONE)) 180 | TinyImageFormat_MOD_MACRO(R64G64_SFLOAT, TinyImageFormat_PACK_2_SFLOAT(R, 64, G, 64, NONE)) 181 | 182 | TinyImageFormat_MOD_MACRO(R64G64B64_UINT, TinyImageFormat_PACK_3_UINT(R, 64, G, 64, B, 64, NONE)) 183 | TinyImageFormat_MOD_MACRO(R64G64B64_SINT, TinyImageFormat_PACK_3_SINT(R, 64, G, 64, B, 64, NONE)) 184 | TinyImageFormat_MOD_MACRO(R64G64B64_SFLOAT, TinyImageFormat_PACK_3_SFLOAT(R, 64, G, 64, B, 64, NONE)) 185 | 186 | TinyImageFormat_MOD_MACRO(R64G64B64A64_UINT, TinyImageFormat_PACK_4_UINT(R, 64, G, 64, B, 64, A, 64, NONE)) 187 | TinyImageFormat_MOD_MACRO(R64G64B64A64_SINT, TinyImageFormat_PACK_4_SINT(R, 64, G, 64, B, 64, A, 64, NONE)) 188 | TinyImageFormat_MOD_MACRO(R64G64B64A64_SFLOAT, TinyImageFormat_PACK_4_SFLOAT(R, 64, G, 64, B, 64, A, 64, NONE)) 189 | 190 | TinyImageFormat_MOD_MACRO(D16_UNORM, TinyImageFormat_DEPTH_STENCIL(D, 16, UNORM, _, _, _, 16)) 191 | TinyImageFormat_MOD_MACRO(X8_D24_UNORM, TinyImageFormat_DEPTH_STENCIL(0, 8, UINT, D, 24, UNORM, 32)) 192 | TinyImageFormat_MOD_MACRO(D32_SFLOAT, TinyImageFormat_DEPTH_STENCIL(D, 32, SFLOAT, _, _, _, 32)) 193 | TinyImageFormat_MOD_MACRO(S8_UINT, TinyImageFormat_DEPTH_STENCIL(S, 8, UINT, _, _, _, 8)) 194 | TinyImageFormat_MOD_MACRO(D16_UNORM_S8_UINT, TinyImageFormat_DEPTH_STENCIL(D, 16, UNORM, S, 8, UINT, 32)) 195 | TinyImageFormat_MOD_MACRO(D24_UNORM_S8_UINT, TinyImageFormat_DEPTH_STENCIL(D, 24, UNORM, S, 8, UINT, 32)) 196 | TinyImageFormat_MOD_MACRO(D32_SFLOAT_S8_UINT, TinyImageFormat_DEPTH_STENCIL(D, 32, SFLOAT, S, 8, UINT, 64)) 197 | 198 | TinyImageFormat_MOD_MACRO(DXBC1_RGB_UNORM, TinyImageFormat_DXTC( NONE, UNORM, 8, 3, 1)) 199 | TinyImageFormat_MOD_MACRO(DXBC1_RGB_SRGB, TinyImageFormat_DXTC(NONE, SRGB, 8, 3, 1)) 200 | TinyImageFormat_MOD_MACRO(DXBC1_RGBA_UNORM, TinyImageFormat_DXTC(PUNCHTHROUGH, UNORM, 8, 4, 1)) 201 | TinyImageFormat_MOD_MACRO(DXBC1_RGBA_SRGB, TinyImageFormat_DXTC(PUNCHTHROUGH, SRGB, 8, 4, 1)) 202 | TinyImageFormat_MOD_MACRO(DXBC2_UNORM, TinyImageFormat_DXTC(FULL, UNORM, 16, 4, 1)) 203 | TinyImageFormat_MOD_MACRO(DXBC2_SRGB, TinyImageFormat_DXTC(FULL, SRGB, 16, 4, 1)) 204 | TinyImageFormat_MOD_MACRO(DXBC3_UNORM, TinyImageFormat_DXTC(BLOCK, UNORM, 16, 4, 1)) 205 | TinyImageFormat_MOD_MACRO(DXBC3_SRGB, TinyImageFormat_DXTC(BLOCK, SRGB, 16, 4, 1)) 206 | TinyImageFormat_MOD_MACRO(DXBC4_UNORM, TinyImageFormat_DXTC(NONE, UNORM, 8, 1, 1)) 207 | TinyImageFormat_MOD_MACRO(DXBC4_SNORM, TinyImageFormat_DXTC(NONE, SNORM, 8, 1, 1)) 208 | TinyImageFormat_MOD_MACRO(DXBC5_UNORM, TinyImageFormat_DXTC(NONE, UNORM, 16, 2, 1)) 209 | TinyImageFormat_MOD_MACRO(DXBC5_SNORM, TinyImageFormat_DXTC(NONE, SNORM, 16, 2, 1)) 210 | TinyImageFormat_MOD_MACRO(DXBC6H_UFLOAT, TinyImageFormat_DXTC(NONE, UFLOAT, 16, 3, 14)) 211 | TinyImageFormat_MOD_MACRO(DXBC6H_SFLOAT, TinyImageFormat_DXTC(NONE, SFLOAT, 16, 3, 14)) 212 | TinyImageFormat_MOD_MACRO(DXBC7_UNORM, TinyImageFormat_DXTC(FULL, UNORM, 16, 4, 8)) 213 | TinyImageFormat_MOD_MACRO(DXBC7_SRGB, TinyImageFormat_DXTC(FULL, SRGB, 16, 4, 8)) 214 | 215 | TinyImageFormat_MOD_MACRO(PVRTC1_2BPP_UNORM, TinyImageFormat_PVRTC(V1, 2, UNORM)) 216 | TinyImageFormat_MOD_MACRO(PVRTC1_4BPP_UNORM, TinyImageFormat_PVRTC(V1, 4, UNORM)) 217 | TinyImageFormat_MOD_MACRO(PVRTC2_2BPP_UNORM, TinyImageFormat_PVRTC(V2, 2, UNORM)) 218 | TinyImageFormat_MOD_MACRO(PVRTC2_4BPP_UNORM, TinyImageFormat_PVRTC(V2, 4, UNORM)) 219 | TinyImageFormat_MOD_MACRO(PVRTC1_2BPP_SRGB, TinyImageFormat_PVRTC(V1, 2, SRGB)) 220 | TinyImageFormat_MOD_MACRO(PVRTC1_4BPP_SRGB, TinyImageFormat_PVRTC(V1, 4, SRGB)) 221 | TinyImageFormat_MOD_MACRO(PVRTC2_2BPP_SRGB, TinyImageFormat_PVRTC(V2, 2, SRGB)) 222 | TinyImageFormat_MOD_MACRO(PVRTC2_4BPP_SRGB, TinyImageFormat_PVRTC(V2, 4, SRGB)) 223 | 224 | TinyImageFormat_MOD_MACRO(ETC2_R8G8B8_UNORM, TinyImageFormat_ETC(8, NONE, UNORM, 3)) 225 | TinyImageFormat_MOD_MACRO(ETC2_R8G8B8_SRGB, TinyImageFormat_ETC(8, NONE, SRGB, 3)) 226 | TinyImageFormat_MOD_MACRO(ETC2_R8G8B8A1_UNORM, TinyImageFormat_ETC(8, PUNCHTHROUGH, UNORM, 4)) 227 | TinyImageFormat_MOD_MACRO(ETC2_R8G8B8A1_SRGB, TinyImageFormat_ETC(8, PUNCHTHROUGH, SRGB, 4)) 228 | TinyImageFormat_MOD_MACRO(ETC2_R8G8B8A8_UNORM, TinyImageFormat_ETC(8, BLOCK, UNORM, 4)) 229 | TinyImageFormat_MOD_MACRO(ETC2_R8G8B8A8_SRGB, TinyImageFormat_ETC(8, BLOCK, SRGB, 4)) 230 | TinyImageFormat_MOD_MACRO(ETC2_EAC_R11_UNORM, TinyImageFormat_ETC(11, NONE, UNORM, 1)) 231 | TinyImageFormat_MOD_MACRO(ETC2_EAC_R11_SNORM, TinyImageFormat_ETC(11, NONE, SNORM, 1)) 232 | TinyImageFormat_MOD_MACRO(ETC2_EAC_R11G11_UNORM, TinyImageFormat_ETC(11, NONE, UNORM, 2)) 233 | TinyImageFormat_MOD_MACRO(ETC2_EAC_R11G11_SNORM, TinyImageFormat_ETC(11, NONE, SNORM, 2)) 234 | 235 | TinyImageFormat_MOD_MACRO(ASTC_4x4_UNORM, TinyImageFormat_ASTC(4, 4, 1, UNORM)) 236 | TinyImageFormat_MOD_MACRO(ASTC_4x4_SRGB, TinyImageFormat_ASTC(4, 4, 1, SRGB)) 237 | TinyImageFormat_MOD_MACRO(ASTC_5x4_UNORM, TinyImageFormat_ASTC(5, 4, 1, UNORM)) 238 | TinyImageFormat_MOD_MACRO(ASTC_5x4_SRGB, TinyImageFormat_ASTC(5, 4, 1, SRGB)) 239 | TinyImageFormat_MOD_MACRO(ASTC_5x5_UNORM, TinyImageFormat_ASTC(5, 5, 1, UNORM)) 240 | TinyImageFormat_MOD_MACRO(ASTC_5x5_SRGB, TinyImageFormat_ASTC(5, 5, 1, SRGB)) 241 | TinyImageFormat_MOD_MACRO(ASTC_6x5_UNORM, TinyImageFormat_ASTC(6, 5, 1, UNORM)) 242 | TinyImageFormat_MOD_MACRO(ASTC_6x5_SRGB, TinyImageFormat_ASTC(6, 5, 1, SRGB)) 243 | TinyImageFormat_MOD_MACRO(ASTC_6x6_UNORM, TinyImageFormat_ASTC(6, 6, 1, UNORM)) 244 | TinyImageFormat_MOD_MACRO(ASTC_6x6_SRGB, TinyImageFormat_ASTC(6, 6, 1, SRGB)) 245 | TinyImageFormat_MOD_MACRO(ASTC_8x5_UNORM, TinyImageFormat_ASTC(8, 5, 1, UNORM)) 246 | TinyImageFormat_MOD_MACRO(ASTC_8x5_SRGB, TinyImageFormat_ASTC(8, 5, 1, SRGB)) 247 | TinyImageFormat_MOD_MACRO(ASTC_8x6_UNORM, TinyImageFormat_ASTC(8, 6, 1, UNORM)) 248 | TinyImageFormat_MOD_MACRO(ASTC_8x6_SRGB, TinyImageFormat_ASTC(8, 6, 1, SRGB)) 249 | TinyImageFormat_MOD_MACRO(ASTC_8x8_UNORM, TinyImageFormat_ASTC(8, 8, 1, UNORM)) 250 | TinyImageFormat_MOD_MACRO(ASTC_8x8_SRGB, TinyImageFormat_ASTC(8, 8, 1, SRGB)) 251 | TinyImageFormat_MOD_MACRO(ASTC_10x5_UNORM, TinyImageFormat_ASTC(10, 5, 1, UNORM)) 252 | TinyImageFormat_MOD_MACRO(ASTC_10x5_SRGB, TinyImageFormat_ASTC(10, 5, 1, SRGB)) 253 | TinyImageFormat_MOD_MACRO(ASTC_10x6_UNORM, TinyImageFormat_ASTC(10, 6, 1, UNORM)) 254 | TinyImageFormat_MOD_MACRO(ASTC_10x6_SRGB, TinyImageFormat_ASTC(10, 6, 1, SRGB)) 255 | TinyImageFormat_MOD_MACRO(ASTC_10x8_UNORM, TinyImageFormat_ASTC(10, 8, 1, UNORM)) 256 | TinyImageFormat_MOD_MACRO(ASTC_10x8_SRGB, TinyImageFormat_ASTC(10, 8, 1, SRGB)) 257 | TinyImageFormat_MOD_MACRO(ASTC_10x10_UNORM, TinyImageFormat_ASTC(10, 10, 1, UNORM)) 258 | TinyImageFormat_MOD_MACRO(ASTC_10x10_SRGB, TinyImageFormat_ASTC(10, 10, 1, SRGB)) 259 | TinyImageFormat_MOD_MACRO(ASTC_12x10_UNORM, TinyImageFormat_ASTC(12, 10, 1, UNORM)) 260 | TinyImageFormat_MOD_MACRO(ASTC_12x10_SRGB, TinyImageFormat_ASTC(12, 10, 1, SRGB)) 261 | TinyImageFormat_MOD_MACRO(ASTC_12x12_UNORM, TinyImageFormat_ASTC(12, 12, 1, UNORM)) 262 | TinyImageFormat_MOD_MACRO(ASTC_12x12_SRGB, TinyImageFormat_ASTC(12, 12, 1, SRGB)) 263 | 264 | TinyImageFormat_MOD_MACRO(CLUT_P4, TinyImageFormat_CLUT(2, 4, RGB, _, _)) 265 | TinyImageFormat_MOD_MACRO(CLUT_P4A4, TinyImageFormat_CLUT(1, 4, RGB, 4, EXPLICIT_ALPHA)) 266 | TinyImageFormat_MOD_MACRO(CLUT_P8, TinyImageFormat_CLUT(1, 8, RGB, _, _)) 267 | TinyImageFormat_MOD_MACRO(CLUT_P8A8, TinyImageFormat_CLUT(1, 8, RGB, 8, EXPLICIT_ALPHA)) 268 | 269 | TinyImageFormat_END_MACRO 270 | #undef TinyImageFormat_START_MACRO 271 | #undef TinyImageFormat_MOD_MACRO 272 | #undef TinyImageFormat_END_MACRO 273 | 274 | #endif //GFX_IMAGEFORMAT_FORMAT_H_ 275 | -------------------------------------------------------------------------------- /src/formatgen_base.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #define __STDC_FORMAT_MACROS 5 | #include 6 | #include 7 | #include 8 | #include "al2o3_vfile/vfile.h" 9 | #include "../include/tiny_imageformat/tinyimageformat_bits.h" 10 | #include "formatgen.h" 11 | 12 | void GenEnums(VFile_Handle file) { 13 | char const ifstartmacro[] = "typedef enum TinyImageFormat {\n"; 14 | char const ifmodmacro[] = "\tTinyImageFormat_%s = %d,\n"; 15 | char const ifendmacro[] = "} TinyImageFormat;\n\n"; 16 | 17 | char buffer[2048]; 18 | #define TinyImageFormat_START_MACRO { VFile_Write(file, ifstartmacro, strlen(ifstartmacro)); uint32_t count = 0; 19 | #define TinyImageFormat_MOD_MACRO(x, y) sprintf(buffer, ifmodmacro, #x, count++); VFile_Write(file, buffer, strlen(buffer)); 20 | #define TinyImageFormat_END_MACRO VFile_Write(file, ifendmacro, strlen(ifendmacro)); } 21 | #include "formatgen.h" 22 | 23 | char const logiEnum[] = 24 | "typedef enum TinyImageFormat_LogicalChannel {\n" 25 | "\tTinyImageFormat_LC_Red = 0,\n" 26 | "\tTinyImageFormat_LC_Green = 1,\n" 27 | "\tTinyImageFormat_LC_Blue = 2,\n" 28 | "\tTinyImageFormat_LC_Alpha = 3,\n" 29 | "\tTinyImageFormat_LC_Depth = 0,\n" 30 | "\tTinyImageFormat_LC_Stencil = 1,\n" 31 | "\tTinyImageFormat_LC_0 = -1,\n" 32 | "\tTinyImageFormat_LC_1 = -2,\n" 33 | "} TinyImageFormat_LogicalChannel;\n\n"; 34 | 35 | VFile_Write(file, logiEnum, strlen(logiEnum)); 36 | 37 | char const physEnum[] = 38 | "typedef enum TinyImageFormat_PhysicalChannel {\n" 39 | "\tTinyImageFormat_PC_0 = 0,\n" 40 | "\tTinyImageFormat_PC_1 = 1,\n" 41 | "\tTinyImageFormat_PC_2 = 2,\n" 42 | "\tTinyImageFormat_PC_3 = 3,\n" 43 | "\tTinyImageFormat_PC_CONST_0 = -1,\n" 44 | "\tTinyImageFormat_PC_CONST_1 = -2,\n" 45 | "} TinyImageFormat_PhysicalChannel;\n\n"; 46 | VFile_Write(file, physEnum, strlen(physEnum)); 47 | 48 | } 49 | 50 | void GenStructs(VFile_Handle file) { 51 | char const fetchInput[] = 52 | "typedef struct TinyImageFormat_DecodeInput {\n" 53 | "\tunion { void const* pixel; void const* pixelPlane0; };\n" 54 | "\tunion { void const* lut; void const* pixelPlane1; };\n" 55 | "\tvoid const* pixelPlane2;\n" 56 | "\tvoid const* pixelPlane3;\n" 57 | "\tvoid const* pixelPlane4;\n" 58 | "\tvoid const* pixelPlane5;\n" 59 | "\tvoid const* pixelPlane6;\n" 60 | "\tvoid const* pixelPlane7;\n" 61 | "\tvoid const* pixelPlane8;\n" 62 | "\tvoid const* pixelPlane9;\n" 63 | "} TinyImageFormat_FetchInput;\n\n"; 64 | VFile_Write(file, fetchInput, strlen(fetchInput)); 65 | 66 | char const putOutput[] = 67 | "typedef struct TinyImageFormat_EncodeOutput {\n" 68 | "\tunion { void * pixel; void * pixelPlane0; };\n" 69 | "\tvoid * pixelPlane1;\n" 70 | "\tvoid * pixelPlane2;\n" 71 | "\tvoid * pixelPlane3;\n" 72 | "\tvoid * pixelPlane4;\n" 73 | "\tvoid * pixelPlane5;\n" 74 | "\tvoid * pixelPlane6;\n" 75 | "\tvoid * pixelPlane7;\n" 76 | "\tvoid * pixelPlane8;\n" 77 | "\tvoid * pixelPlane9;\n" 78 | "} TinyImageFormat_EncodeOutput;\n\n"; 79 | VFile_Write(file, putOutput, strlen(putOutput)); 80 | 81 | } 82 | 83 | void GenCount(VFile_Handle file) { 84 | char buffer[2048]; 85 | // format count 86 | #define TinyImageFormat_START_MACRO uint32_t count = 0; 87 | #define TinyImageFormat_MOD_MACRO(x, y) count++; 88 | #define TinyImageFormat_END_MACRO 89 | #include "formatgen.h" 90 | char const formatCountF[] = "#define TinyImageFormat_Count %uU \n\n"; 91 | 92 | sprintf(buffer, formatCountF, count); 93 | VFile_Write(file, buffer, strlen(buffer)); 94 | } 95 | -------------------------------------------------------------------------------- /src/formatgen_decode.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #define __STDC_FORMAT_MACROS 5 | #include 6 | #include "al2o3_vfile/vfile.h" 7 | #include "../include/tiny_imageformat/tinyimageformat_bits.h" 8 | #include "formatgen.h" 9 | 10 | int8_t PhysicalChannelToLogical(char const *name, uint64_t const v, uint32_t chan); 11 | void LogicalToPhysicalChannels(const char *name, uint64_t v, int8_t out[4]); 12 | double MaxActual(char const *name, uint64_t v, uint32_t const chan, bool ignoreNormFormats); 13 | uint32_t ChannelCount(char const *name, uint64_t v); 14 | 15 | uint32_t ChannelWidth(char const *name, uint64_t const v, uint32_t chan) { 16 | 17 | if(IsInPacked(name, v)) { 18 | uint64_t vbc = v >> TinyImageFormat_PACK_BITS_SHIFT; 19 | vbc = vbc >> (chan * TinyImageFormat_PACK_BITS_REQUIRED_BITS); 20 | 21 | auto bits = (TinyImageFormat_Pack_Bits const) (vbc & Mask(TinyImageFormat_PACK_BITS_REQUIRED_BITS)); 22 | switch (bits) { 23 | case TinyImageFormat_PACK_BITS_0: return 0; 24 | case TinyImageFormat_PACK_BITS_1: return 1; 25 | case TinyImageFormat_PACK_BITS_2: return 2; 26 | case TinyImageFormat_PACK_BITS_3: return 3; 27 | case TinyImageFormat_PACK_BITS_4: return 4; 28 | case TinyImageFormat_PACK_BITS_5: return 5; 29 | case TinyImageFormat_PACK_BITS_6: return 6; 30 | case TinyImageFormat_PACK_BITS_7: return 7; 31 | case TinyImageFormat_PACK_BITS_8: return 8; 32 | case TinyImageFormat_PACK_BITS_9: return 9; 33 | case TinyImageFormat_PACK_BITS_10: return 10; 34 | case TinyImageFormat_PACK_BITS_11: return 11; 35 | case TinyImageFormat_PACK_BITS_12: return 12; 36 | case TinyImageFormat_PACK_BITS_16: return 16; 37 | case TinyImageFormat_PACK_BITS_24: return 24; 38 | case TinyImageFormat_PACK_BITS_32: return 32; 39 | case TinyImageFormat_PACK_BITS_64: return 64; 40 | } 41 | } 42 | 43 | if(IsInDepthStencil(name, v)) { 44 | uint64_t vbc = v >> TinyImageFormat_DEPTH_STENCIL_BITS_SHIFT; 45 | if(chan >= TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS) return 0; 46 | vbc = vbc >> (chan * TinyImageFormat_DEPTH_STENCIL_BITS_REQUIRED_BITS); 47 | auto bits = (TinyImageFormat_DepthStencil_Bits const) (vbc & Mask(TinyImageFormat_DEPTH_STENCIL_BITS_REQUIRED_BITS)); 48 | switch(bits) { 49 | case TinyImageFormat_DEPTH_STENCIL_BITS_0: return 0; 50 | case TinyImageFormat_DEPTH_STENCIL_BITS_8: return 8; 51 | case TinyImageFormat_DEPTH_STENCIL_BITS_16: return 16; 52 | case TinyImageFormat_DEPTH_STENCIL_BITS_24: return 24; 53 | case TinyImageFormat_DEPTH_STENCIL_BITS_32: return 32; 54 | } 55 | } 56 | 57 | if(IsInCLUT(name,v)) { 58 | uint64_t vbc = v >> TinyImageFormat_CLUT_BITS_SHIFT; 59 | 60 | if(chan >= TinyImageFormat_CLUT_NUM_CHANNELS) return 0; 61 | vbc = vbc >> (chan * TinyImageFormat_CLUT_BITS_REQUIRED_BITS); 62 | auto bits = (TinyImageFormat_CLUT_Bits const) (vbc & Mask(TinyImageFormat_CLUT_BITS_REQUIRED_BITS)); 63 | switch(bits) { 64 | 65 | case TinyImageFormat_CLUT_BITS_0: return 0; 66 | case TinyImageFormat_CLUT_BITS_1: return 1; 67 | case TinyImageFormat_CLUT_BITS_2: return 2; 68 | case TinyImageFormat_CLUT_BITS_4: return 4; 69 | case TinyImageFormat_CLUT_BITS_8: return 8; 70 | } 71 | } 72 | if(IsInDXTC(name,v)) { 73 | uint64_t vt = v >> TinyImageFormat_DXTC_TYPE_SHIFT; 74 | uint64_t vcc = v >> TinyImageFormat_DXTC_CHANNELCOUNT_SHIFT; 75 | uint32_t const channelCount = (uint32_t const)(vcc & Mask(TinyImageFormat_DXTC_CHANNELCOUNT_REQUIRED_BITS)) + 1; 76 | if(chan >= channelCount) return 0; 77 | auto type = (TinyImageFormat_DXTC_Type const) (vt & Mask(TinyImageFormat_DXTC_TYPE_REQUIRED_BITS)); 78 | switch(type) { 79 | case TinyImageFormat_DXTC_TYPE_UNORM: 80 | case TinyImageFormat_DXTC_TYPE_SNORM: 81 | case TinyImageFormat_DXTC_TYPE_SRGB: return 8; // this is wrong but good enough imho 82 | case TinyImageFormat_DXTC_TYPE_SFLOAT: 83 | case TinyImageFormat_DXTC_TYPE_UFLOAT:return 16; 84 | } 85 | } 86 | if(IsInETC(name,v)) { 87 | uint64_t vb = v >> TinyImageFormat_ETC_BITS_SHIFT; 88 | uint64_t vcc = v >> TinyImageFormat_ETC_CHANNELCOUNT_SHIFT; 89 | uint32_t const channelCount = (uint32_t const)(vcc & Mask(TinyImageFormat_ETC_CHANNELCOUNT_REQUIRED_BITS)) + 1; 90 | if(chan >= channelCount) return 0; 91 | auto bits = (TinyImageFormat_ETC_Bits const) (vb & Mask(TinyImageFormat_ETC_BITS_REQUIRED_BITS)); 92 | switch(bits) { 93 | case TinyImageFormat_ETC_BITS_8:return 8; 94 | case TinyImageFormat_ETC_BITS_11:return 11; 95 | } 96 | } 97 | 98 | if(IsInPVRTC(name,v)) { 99 | return 8;// very approximate 100 | } 101 | 102 | if(IsInASTC(name,v)) { 103 | return 8;// very approximate 104 | } 105 | 106 | ASSERT(false); 107 | return 0; 108 | } 109 | 110 | bool FetchLogicalPixelsPackedNotSpecial(char const *name, 111 | uint64_t const v, 112 | uint32_t const outputFloatWidth, 113 | char *output) { 114 | char const *const outputCastTable[2] = { 115 | "float", 116 | "double" 117 | }; 118 | char const *outputCast = outputCastTable[0]; 119 | if (outputFloatWidth == 64) 120 | outputCast = outputCastTable[1]; 121 | 122 | // easy not packed formats 123 | uint64_t vt = v >> TinyImageFormat_PACK_TYPE_SHIFT; 124 | uint64_t vs = v >> TinyImageFormat_PACK_SWIZZLE_SHIFT; 125 | 126 | // unpacked are sort of homogenous same bit size per channel, even if 127 | // type varies (not currently do) but this is okay for the pointer increment 128 | char typeStringBuf[2048]; 129 | 130 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 131 | TinyImageFormat_Pack_Swizzle 132 | swiz = (TinyImageFormat_Pack_Swizzle) (vs & Mask(TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS)); 133 | 134 | int32_t swizzle = PhysicalChannelToLogical(name, v, i); 135 | 136 | TinyImageFormat_Pack_Type 137 | type = (TinyImageFormat_Pack_Type) (vt & Mask(TinyImageFormat_PACK_TYPE_REQUIRED_BITS)); 138 | double const maxFactor = MaxActual(name, v, i, true); 139 | double const normalFactor = 1.0 / maxFactor; 140 | 141 | if (swizzle >= 0) { 142 | uint32_t chanBitWidth = ChannelWidth(name, v, i); 143 | switch (chanBitWidth) { 144 | case 0: continue; 145 | case 8: 146 | case 16: 147 | case 32: 148 | case 64: break; 149 | default: LOGERROR("unpacked format can only be 8, 16, 32, 64 bits wide per channel: bits encoded as %d", 150 | chanBitWidth); 151 | continue; 152 | } 153 | 154 | char const *typeStringFmt = "ERROR"; 155 | switch (type) { 156 | case TinyImageFormat_PACK_TYPE_SNORM: 157 | case TinyImageFormat_PACK_TYPE_SINT: 158 | typeStringFmt = "int%d_t"; 159 | break; 160 | case TinyImageFormat_PACK_TYPE_UNORM: 161 | case TinyImageFormat_PACK_TYPE_SRGB: 162 | case TinyImageFormat_PACK_TYPE_UINT: 163 | typeStringFmt = "uint%d_t"; 164 | break; 165 | case TinyImageFormat_PACK_TYPE_UFLOAT: 166 | case TinyImageFormat_PACK_TYPE_SFLOAT: 167 | if (chanBitWidth == 16) { 168 | typeStringFmt = "uint16_t"; // special needs decoder 169 | } else if (chanBitWidth == 32) { 170 | typeStringFmt = "float"; 171 | } else if (chanBitWidth == 64) { 172 | typeStringFmt = "double"; 173 | } else { 174 | ASSERT(false); 175 | } 176 | break; 177 | case TinyImageFormat_PACK_TYPE_SBFLOAT: 178 | if (chanBitWidth == 16) { 179 | typeStringFmt = "uint16_t"; // special needs decoder 180 | } else { 181 | ASSERT(false); 182 | } 183 | break; 184 | case TinyImageFormat_PACK_TYPE_NONE: continue; 185 | } 186 | 187 | sprintf(typeStringBuf, typeStringFmt, chanBitWidth); 188 | switch (type) { 189 | case TinyImageFormat_PACK_TYPE_UNORM: 190 | case TinyImageFormat_PACK_TYPE_SNORM: 191 | sprintf(output, 192 | "%s\t\t\t\tout[%d] = ((%s)((%s const *)in->pixel)[%d]) * (%s)%1.8f;\n", 193 | output, 194 | swizzle, 195 | outputCast, 196 | typeStringBuf, 197 | i, 198 | outputCast, 199 | normalFactor); 200 | break; 201 | case TinyImageFormat_PACK_TYPE_SFLOAT: 202 | if (chanBitWidth == 16) { 203 | sprintf(output, 204 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_HalfAsUintToFloat((((%s const *)in->pixel))[%d]);\n", 205 | output, 206 | swizzle, 207 | outputCast, 208 | typeStringBuf, 209 | i); 210 | 211 | } else { 212 | sprintf(output, 213 | "%s\t\t\t\tout[%d] = (%s) (((%s const *)in->pixel)[%d]);\n", 214 | output, 215 | swizzle, 216 | outputCast, 217 | typeStringBuf, 218 | i); 219 | } 220 | break; 221 | case TinyImageFormat_PACK_TYPE_SBFLOAT: 222 | sprintf(output, 223 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_BFloatAsUintToFloat((((%s const *)in->pixel))[%d]);\n", 224 | output, 225 | swizzle, 226 | outputCast, 227 | typeStringBuf, 228 | i); 229 | break; 230 | case TinyImageFormat_PACK_TYPE_UINT: 231 | case TinyImageFormat_PACK_TYPE_SINT: 232 | sprintf(output, 233 | "%s\t\t\t\tout[%d] = (%s)(((%s const *)in->pixel)[%d]);\n", 234 | output, 235 | swizzle, 236 | outputCast, 237 | typeStringBuf, 238 | i); 239 | break; 240 | case TinyImageFormat_PACK_TYPE_SRGB: 241 | sprintf(output, 242 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_LookupSRGB(((%s const *)in->pixel)[%d]);\n", 243 | output, 244 | swizzle, 245 | outputCast, 246 | typeStringBuf, 247 | i); 248 | break; 249 | case TinyImageFormat_PACK_TYPE_UFLOAT: 250 | case TinyImageFormat_PACK_TYPE_NONE: ASSERT(false); 251 | } 252 | } 253 | vt = vt >> TinyImageFormat_PACK_TYPE_REQUIRED_BITS; 254 | vs = vs >> TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS; 255 | } 256 | 257 | int8_t l2p[4]; 258 | LogicalToPhysicalChannels(name, v, l2p); 259 | 260 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 261 | if (l2p[i] < 0) { 262 | sprintf(output, 263 | "%s\t\t\t\tout[%d] = (%s)%1.8f;\n", 264 | output, 265 | i, 266 | outputCast, 267 | (double) ((-l2p[i]) - 1)); 268 | } 269 | } 270 | sprintf(output, "%s\t\t\t\tout += 4;\n" 271 | "\t\t\t\tin->pixel = (void const*)(((%s const*)in->pixel) + %d);\n", 272 | output, 273 | typeStringBuf, 274 | ChannelCount(name, v)); 275 | 276 | return true; 277 | } 278 | 279 | bool FetchLogicalPixelsPackedSpecial(char const *name, 280 | uint64_t const v, 281 | uint32_t const outputFloatWidth, 282 | char *output, 283 | TinyImageFormat_Pack_Special const special) { 284 | char const *const outputCastTable[2] = { 285 | "float", 286 | "double" 287 | }; 288 | char const *outputCast = outputCastTable[0]; 289 | if (outputFloatWidth == 64) 290 | outputCast = outputCastTable[1]; 291 | 292 | // how wide is the total pixel format we fetch that and then break out each channel 293 | uint32_t bitWidth = 0; 294 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 295 | bitWidth += ChannelWidth(name, v, i); 296 | } 297 | uint32_t repeat = 1; 298 | switch (special) { 299 | case TinyImageFormat_PACK_SPECIAL_NONE:repeat = 1; 300 | break; 301 | case TinyImageFormat_PACK_SPECIAL_PACK:repeat = 1; 302 | break; 303 | case TinyImageFormat_PACK_SPECIAL_MULTI2:repeat = 2; 304 | break; 305 | case TinyImageFormat_PACK_SPECIAL_MULTI4:repeat = 4; 306 | break; 307 | case TinyImageFormat_PACK_SPECIAL_MULTI8:repeat = 8; 308 | break; 309 | } 310 | bitWidth *= repeat; 311 | 312 | char nextPixelBuffer[2048]; 313 | // packed formats are currently limited to 32 bits but we allow 64 bit for future possibilities 314 | switch (bitWidth) { 315 | case 8: sprintf(output, "%s\t\t\t\tuint8_t val = *((uint8_t const*)in->pixel);\n", output); 316 | sprintf(nextPixelBuffer, "\t\t\t\tin->pixel = (void const*)(((uint8_t const*)in->pixel) + 1);\n"); 317 | break; 318 | case 16: sprintf(output, "%s\t\t\t\tuint16_t val = *((uint16_t const*)in->pixel);\n", output); 319 | sprintf(nextPixelBuffer, "\t\t\t\tin->pixel = (void const*)(((uint16_t const*)in->pixel) + 1);\n"); 320 | break; 321 | case 32: sprintf(output, "%s\t\t\t\tuint32_t val = *((uint32_t const*)in->pixel);\n", output); 322 | sprintf(nextPixelBuffer, "\t\t\t\tin->pixel = (void const*)(((uint32_t const*)in->pixel) + 1);\n"); 323 | break; 324 | case 64: sprintf(output, "%s\t\t\t\tuint64_t val = *((uint64_t const*)in->pixel);\n", output); 325 | sprintf(nextPixelBuffer, "\t\t\t\tin->pixel = (void const*)(((uint64_t const*)in->pixel) + 1);\n"); 326 | break; 327 | default: 328 | if (bitWidth < 8 || bitWidth > 64) { 329 | LOGERROR("The total bitwidth of a pack pixel must be between 8 and 64 bits: %s has %d", name, bitWidth); 330 | return false; 331 | } 332 | } 333 | 334 | sprintf(nextPixelBuffer, "%s\t\t\t\tout+=%d;\n", nextPixelBuffer, 4 * repeat); 335 | 336 | uint64_t shifter = 0; 337 | for (uint32_t j = 0; j < repeat; j++) { 338 | uint64_t vt = v >> TinyImageFormat_PACK_TYPE_SHIFT; 339 | uint64_t vs = v >> TinyImageFormat_PACK_SWIZZLE_SHIFT; 340 | 341 | for (int i = TinyImageFormat_PACK_NUM_CHANNELS - 1; i >= 0; --i) { 342 | uint32_t const chanBitWidth = ChannelWidth(name, v, TinyImageFormat_PACK_NUM_CHANNELS - i - 1); 343 | 344 | auto swiz = (TinyImageFormat_Pack_Swizzle const) (vs & Mask(TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS)); 345 | 346 | int32_t swizzle = -1; 347 | switch (swiz) { 348 | case TinyImageFormat_PACK_SWIZZLE_R: swizzle = 0; 349 | break; 350 | case TinyImageFormat_PACK_SWIZZLE_G: swizzle = 1; 351 | break; 352 | case TinyImageFormat_PACK_SWIZZLE_B: swizzle = 2; 353 | break; 354 | case TinyImageFormat_PACK_SWIZZLE_A: swizzle = 3; 355 | break; 356 | case TinyImageFormat_PACK_SWIZZLE_0: swizzle = -1; 357 | break; 358 | case TinyImageFormat_PACK_SWIZZLE_1: swizzle = -2; 359 | break; 360 | } 361 | 362 | double const maxFactor = MaxActual(name, v, TinyImageFormat_PACK_NUM_CHANNELS - i - 1, true); 363 | auto type = (TinyImageFormat_Pack_Type) (vt & Mask(TinyImageFormat_PACK_TYPE_REQUIRED_BITS)); 364 | 365 | if (swizzle >= 0) { 366 | 367 | double normalFactor = 1.0 / maxFactor; 368 | 369 | // pretty up 1 bit channels by removed the 1.0 multiplier 370 | if (type == TinyImageFormat_PACK_TYPE_UNORM && fabs(normalFactor - 1.0) < 1e-10f) 371 | type = TinyImageFormat_PACK_TYPE_UINT; 372 | 373 | switch (type) { 374 | 375 | case TinyImageFormat_PACK_TYPE_UNORM: 376 | case TinyImageFormat_PACK_TYPE_SNORM: 377 | sprintf(output, 378 | "%s\t\t\t\tout[%d] = ((%s)((val >> %lld) & 0x%llx)) * ((%s)%1.8f);\n", 379 | output, 380 | j * 4 + swizzle, 381 | outputCast, 382 | shifter, 383 | Mask(chanBitWidth), 384 | outputCast, 385 | normalFactor); 386 | break; 387 | case TinyImageFormat_PACK_TYPE_UINT: 388 | case TinyImageFormat_PACK_TYPE_SINT: 389 | sprintf(output, 390 | "%s\t\t\t\tout[%d] = (%s)((val >> %lld) & 0x%llx);\n", 391 | output, 392 | j * 4 + swizzle, 393 | outputCast, 394 | shifter, 395 | Mask(chanBitWidth)); 396 | break; 397 | case TinyImageFormat_PACK_TYPE_SRGB: 398 | sprintf(output, 399 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_LookupSRGB((val >> %lld) & 0x%llx);\n", 400 | output, 401 | j * 4 + swizzle, 402 | outputCast, 403 | shifter, 404 | Mask(chanBitWidth)); 405 | break; 406 | case TinyImageFormat_PACK_TYPE_UFLOAT: 407 | if (chanBitWidth == 10) { 408 | sprintf(output, 409 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_UFloat10AsUintToFloat((val >> %lld) & 0x%llx);\n", 410 | output, 411 | j * 4 + swizzle, 412 | outputCast, 413 | shifter, 414 | Mask(chanBitWidth)); 415 | } else if (chanBitWidth == 11) { 416 | sprintf(output, 417 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_UFloat11AsUintToFloat((val >> %lld) & 0x%llx);\n", 418 | output, 419 | j * 4 + swizzle, 420 | outputCast, 421 | shifter, 422 | Mask(chanBitWidth)); 423 | } else { 424 | ASSERT(false); 425 | } 426 | break; 427 | case TinyImageFormat_PACK_TYPE_SFLOAT: 428 | if (chanBitWidth == 16) { 429 | sprintf(output, 430 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_HalfAsUintToFloat((val >> %lld) & 0x%llx);\n", 431 | output, 432 | j * 4 + swizzle, 433 | outputCast, 434 | shifter, 435 | Mask(chanBitWidth)); 436 | } else { 437 | ASSERT(false); 438 | } 439 | break; 440 | case TinyImageFormat_PACK_TYPE_SBFLOAT: 441 | if (chanBitWidth == 16) { 442 | sprintf(output, 443 | "%s\t\t\t\tout[%d] = (%s)TinyImageFormat_BFloatAsUintToFloat((val >> %lld) & 0x%llx);\n", 444 | output, 445 | j * 4 + swizzle, 446 | outputCast, 447 | shifter, 448 | Mask(chanBitWidth)); 449 | } else { 450 | ASSERT(false); 451 | } 452 | break; 453 | case TinyImageFormat_PACK_TYPE_NONE: ASSERT(false); 454 | } 455 | 456 | } 457 | shifter += chanBitWidth; 458 | vt = vt >> TinyImageFormat_PACK_TYPE_REQUIRED_BITS; 459 | vs = vs >> TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS; 460 | } 461 | 462 | int8_t l2p[4]; 463 | LogicalToPhysicalChannels(name, v, l2p); 464 | 465 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 466 | if (l2p[i] < 0) { 467 | sprintf(output, "%s\t\t\t\tout[%d] = (%s)%1.8f;\n", output, j * 4 + i, outputCast, (double) ((-l2p[i]) - 1)); 468 | } 469 | } 470 | } 471 | sprintf(output, "%s%s", output, nextPixelBuffer); 472 | 473 | return true; 474 | } 475 | bool FetchLogicalPixelsPacked(char const *name, uint64_t const v, uint32_t const outputFloatWidth, 476 | char *output) { 477 | 478 | sprintf(output, "\n"); 479 | uint32_t maxChanWidth = 0; 480 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 481 | uint32_t chanWidth = ChannelWidth(name, v, i); 482 | if (chanWidth > maxChanWidth) 483 | maxChanWidth = chanWidth; 484 | } 485 | 486 | if (maxChanWidth > outputFloatWidth) { 487 | return false; 488 | } 489 | 490 | // special case 491 | if (v == (uint64_t)TinyImageFormat::E5B9G9R9_UFLOAT) { 492 | if (outputFloatWidth == 32) { 493 | char const decoder[] = "\n\t\t\t\tTinyImageFormat_SharedE5B9G9R9UFloatToFloats(*(uint32_t*)in->pixel, out);\n" 494 | "\t\t\t\tin->pixel = (void const*)(((uint32_t const*)in->pixel) + 1);\n" 495 | "\t\t\t\tout += 4;\n"; 496 | sprintf(output, decoder); 497 | return true; 498 | } else { 499 | return false; 500 | } 501 | } 502 | 503 | uint64_t vspec = v >> TinyImageFormat_PACK_SPECIAL_SHIFT; 504 | 505 | auto special = (TinyImageFormat_Pack_Special const) (vspec & Mask(TinyImageFormat_PACK_SPECIAL_REQUIRED_BITS)); 506 | if (special == TinyImageFormat_PACK_SPECIAL_NONE) { 507 | return FetchLogicalPixelsPackedNotSpecial(name, v, outputFloatWidth, output); 508 | } else { 509 | return FetchLogicalPixelsPackedSpecial(name, v, outputFloatWidth, output, special); 510 | } 511 | } 512 | bool FetchLogicalPixelsCLUT(char const *name, uint64_t const v, 513 | uint32_t const outputFloatWidth, 514 | char *output) { 515 | char const *const outputCastTable[2] = { 516 | "float", 517 | "double" 518 | }; 519 | char const *outputCast = outputCastTable[0]; 520 | if (outputFloatWidth == 64) 521 | outputCast = outputCastTable[1]; 522 | 523 | uint32_t maxChanWidth = 0; 524 | uint32_t totalChanWidth = 0; 525 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 526 | uint32_t chanWidth = ChannelWidth(name, v, i); 527 | totalChanWidth += chanWidth; 528 | if (chanWidth > maxChanWidth) 529 | maxChanWidth = chanWidth; 530 | } 531 | ASSERT(totalChanWidth <= 64); 532 | 533 | uint64_t vbs = v >> TinyImageFormat_CLUT_BLOCKSIZE_SHIFT; 534 | 535 | auto blockSize = (TinyImageFormat_CLUT_BlockSize const )(vbs & Mask( TinyImageFormat_CLUT_BLOCKSIZE_REQUIRED_BITS)); 536 | uint32_t repeat = 1; 537 | switch(blockSize) { 538 | case TinyImageFormat_CLUT_BLOCKSIZE_1: repeat = 1; break; 539 | case TinyImageFormat_CLUT_BLOCKSIZE_2: repeat = 2; break; 540 | case TinyImageFormat_CLUT_BLOCKSIZE_4: repeat = 4; break; 541 | case TinyImageFormat_CLUT_BLOCKSIZE_8: repeat = 8; break; 542 | } 543 | uint64_t vt; 544 | 545 | if(totalChanWidth <= 8) { 546 | sprintf(output, "\n\t\t\t\tuint8_t val = *((uint8_t const*)in->pixel);\n"); 547 | } else if(totalChanWidth <= 16) { 548 | sprintf(output, "\n\t\t\t\tuint16_t val = *((uint16_t const*)in->pixel);\n"); 549 | } else if(totalChanWidth <= 32) { 550 | sprintf(output, "\n\t\t\t\tuint32_t val = *((uint32_t const*)in->pixel);\n"); 551 | } else if(totalChanWidth <= 64) { 552 | sprintf(output, "\n\t\t\t\tuint64_t val = *((uint64_t const*)in->pixel);\n"); 553 | } 554 | 555 | sprintf(output, "%s\t\t\t\tuint32_t const* lut = (uint32_t const*)in->lut;\n", output); 556 | 557 | uint64_t shifter = 0; 558 | for (uint32_t j = 0; j < repeat; j++) { 559 | vt = v >> TinyImageFormat_CLUT_TYPE_SHIFT; 560 | bool explicitAlpha = false; 561 | for (int i = 0; i < TinyImageFormat_CLUT_NUM_CHANNELS; ++i) { 562 | auto type = (TinyImageFormat_CLUT_Type const)(vt & Mask(TinyImageFormat_CLUT_TYPE_REQUIRED_BITS)); 563 | if(type == TinyImageFormat_CLUT_TYPE_EXPLICIT_ALPHA) { 564 | explicitAlpha = true; 565 | break; 566 | } 567 | vt >>= TinyImageFormat_CLUT_TYPE_REQUIRED_BITS; 568 | } 569 | 570 | vt = v >> TinyImageFormat_CLUT_TYPE_SHIFT; 571 | for (int i = 0; i < TinyImageFormat_CLUT_NUM_CHANNELS; ++i) { 572 | uint32_t const chanBitWidth = ChannelWidth(name, v, i); 573 | auto type = (TinyImageFormat_CLUT_Type const)(vt & Mask(TinyImageFormat_CLUT_TYPE_REQUIRED_BITS)); 574 | 575 | double const normalFactor = 1.0 / MaxActual(name, v, i, true); 576 | 577 | switch(type) { 578 | case TinyImageFormat_CLUT_TYPE_NONE:break; 579 | case TinyImageFormat_CLUT_TYPE_RGB: 580 | sprintf(output, 581 | "%s\t\t\t\tuint32_t v%d = lut[((val >> %lld) & 0x%llx)];\n", 582 | output, 583 | j, 584 | shifter, 585 | Mask(chanBitWidth) 586 | ); 587 | 588 | for(int k =0; k < (explicitAlpha ? 3 : 4);++k) { 589 | sprintf(output, 590 | "%s\t\t\t\tout[%d] = (%s)((lut[v%d] >> %d) & 0xFF) * (%s)%1.8f;\n", 591 | output, 592 | j * 4 + k, 593 | outputCast, 594 | j, 595 | k * 8, 596 | outputCast, 597 | normalFactor); 598 | } 599 | break; 600 | case TinyImageFormat_CLUT_TYPE_SINGLE: ASSERT(false);// TODO 601 | break; 602 | case TinyImageFormat_CLUT_TYPE_EXPLICIT_ALPHA: 603 | sprintf(output, 604 | "%s\t\t\t\tout[3] = ((%s)((val >> %lld) & 0x%llx)) * ((%s)%1.8f);\n", 605 | output, 606 | outputCast, 607 | shifter, 608 | Mask(chanBitWidth), 609 | outputCast, 610 | normalFactor); 611 | break; 612 | } 613 | 614 | shifter += chanBitWidth; 615 | vt >>= TinyImageFormat_CLUT_TYPE_REQUIRED_BITS; 616 | } 617 | } 618 | sprintf(output, "%s\t\t\t\tin->pixel = (void const*)(((uint8_t const*)in->pixel) + 1);\n", output); 619 | return true; 620 | } 621 | 622 | bool DecodeLogicalPixelsD(char const *name, uint64_t const v, char *output) { 623 | if (v == 0) 624 | return false; 625 | 626 | uint32_t maxChanWidth = 0; 627 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 628 | uint32_t chanWidth = ChannelWidth(name, v, i); 629 | if (chanWidth > maxChanWidth) 630 | maxChanWidth = chanWidth; 631 | } 632 | 633 | if (maxChanWidth < 64) { 634 | return false; 635 | } 636 | 637 | if (IsInPacked(name, v)) { 638 | return FetchLogicalPixelsPacked(name, v, 64, output); 639 | 640 | } else if (IsInCLUT(name, v)) { 641 | return FetchLogicalPixelsCLUT(name, v, 64, output); 642 | } 643 | 644 | return false; 645 | } 646 | 647 | bool DecodeLogicalPixelsF(char const *name, uint64_t const v, char *output) { 648 | if (v == 0) 649 | return false; 650 | 651 | if (IsInPacked(name, v)) { 652 | return FetchLogicalPixelsPacked(name, v, 32, output); 653 | } else if (IsInCLUT(name, v)) { 654 | return FetchLogicalPixelsCLUT(name, v, 32, output); 655 | } 656 | 657 | return false; 658 | } 659 | 660 | static void GenCanDecodeLogicalPixelsF(VFile_Handle file) { 661 | char buffer[2048]; 662 | 663 | char const *const isPrefixF = 664 | "TIF_CONSTEXPR inline bool TinyImageFormat_CanDecodeLogicalPixelsF(TinyImageFormat const fmt) {\n" 665 | "\tswitch(fmt) {\n"; 666 | 667 | char const *const body = "\t\tcase %s: return true;\n"; 668 | char const switchPostfixF[] = "\t\tdefault: return false;\n\t\t}\n\t}\n\n"; 669 | 670 | char output[2048]; 671 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 672 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = DecodeLogicalPixelsF(#x, y, output); if(okay) { sprintf(buffer, body, "TinyImageFormat_"#x); VFile_Write(file, buffer, strlen(buffer)); } } 673 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 674 | #include "formatgen.h" 675 | 676 | } 677 | 678 | static void GenCanDecodeLogicalPixelsD(VFile_Handle file) { 679 | char buffer[2048]; 680 | 681 | char const *const isPrefixF = 682 | "TIF_CONSTEXPR inline bool TinyImageFormat_CanDecodeLogicalPixelsD(TinyImageFormat const fmt) {\n" 683 | "\tswitch(fmt) {\n"; 684 | 685 | char const switchPostfixF[] = "\t\tdefault: return TinyImageFormat_CanDecodeLogicalPixelsF(fmt);\n" 686 | "\t}\n}\n\n"; 687 | 688 | char output[2048]; 689 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 690 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = DecodeLogicalPixelsD(#x, y, output); if(okay) { sprintf(buffer, "\t\tcase %s: return true;\n", "TinyImageFormat_"#x); VFile_Write(file, buffer, strlen(buffer)); } } 691 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 692 | #include "formatgen.h" 693 | 694 | } 695 | 696 | void GenDecodeLogicalPixelsF(VFile_Handle file) { 697 | char buffer[2048]; 698 | 699 | char const *const isPrefixF = 700 | "TIF_CONSTEXPR inline bool TinyImageFormat_DecodeLogicalPixelsF(TinyImageFormat const fmt, TinyImageFormat_DecodeInput * in, uint32_t const width, float* out) {\n" 701 | "\tswitch(fmt) {\n"; 702 | char const *const body = "\t\tcase %s:\n\t\t\tfor(uint32_t w = 0; w < width; ++w) {" 703 | "%s" 704 | "\t\t\t}\n\t\t\treturn true;\n"; 705 | 706 | char const switchPostfixF[] = "\t\tdefault: return false;\n\t}\n}\n\n"; 707 | 708 | char output[2048]; 709 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 710 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = DecodeLogicalPixelsF(#x, y, output); if(okay) { sprintf(buffer, body, "TinyImageFormat_"#x, output); VFile_Write(file, buffer, strlen(buffer)); } } 711 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 712 | #include "formatgen.h" 713 | } 714 | 715 | void GenDecodeLogicalPixelsD(VFile_Handle file) { 716 | char buffer[2048]; 717 | 718 | char const *const isPrefixF = 719 | "TIF_CONSTEXPR inline bool TinyImageFormat_DecodeLogicalPixelsD(TinyImageFormat const fmt, TinyImageFormat_DecodeInput * in, uint32_t const width, double* out) {\n" 720 | "\tswitch(fmt) {\n"; 721 | 722 | char const *const body = "\t\tcase %s:\n\t\t\tfor(uint32_t w = 0; w < width; ++w) {" 723 | "%s" 724 | "\t\t\t}\n\t\t\treturn true;\n"; 725 | 726 | char const switchPostfixF[] = "\t\tdefault:\n" 727 | "\t\t{\n\t\t\tfloat outF[4] = {0, 0, 0, 0}; bool ret = true;\n" 728 | "\t\t\tfor(uint32_t w = 0; w < width && ret; ++w) {\n" 729 | "\t\t\t\tret = TinyImageFormat_DecodeLogicalPixelsF(fmt, in, 1, outF);\n" 730 | "\t\t\t\tout[0] = outF[0]; out[1] = outF[1]; out[2] = outF[2]; out[3] = outF[3]; out += 4;\n\t\t\t\t}\n" 731 | "\t\t\treturn ret;\n\t\t}\n\t}\n}\n\n"; 732 | 733 | char output[2048]; 734 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 735 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = DecodeLogicalPixelsD(#x, y, output); if(okay) { sprintf(buffer, body, "TinyImageFormat_"#x, output); VFile_Write(file, buffer, strlen(buffer)); } } 736 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 737 | #include "formatgen.h" 738 | } 739 | 740 | static void GetSRGBTableFuncton(VFile_Handle file) { 741 | char const *const prefix = 742 | "TIF_CONSTEXPR inline float TinyImageFormat_LookupSRGB(uint8_t lookup) {\n" 743 | "\tswitch(lookup) {\n"; 744 | char const *const body = "\t\tcase %d: return %1.8ff;\n"; 745 | char const *const postfix = "\t\tdefault: return 1.0;\n\t}\n}\n\n"; 746 | 747 | static uint32_t const sRGBTable[256] = { 748 | 0x00000000, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61, 0x3aeeb40e, 0x3b0b3e5d, 749 | 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518d, 0x3b70f18d, 0x3b83e1c6, 0x3b8fe616, 0x3b9c87fd, 750 | 0x3ba9c9b7, 0x3bb7ad6f, 0x3bc63549, 0x3bd56361, 0x3be539c1, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152, 751 | 0x3c15a703, 0x3c1f45be, 0x3c293e6b, 0x3c3391f7, 0x3c3e4149, 0x3c494d43, 0x3c54b6c7, 0x3c607eb1, 752 | 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9f, 0x3c9085db, 0x3c978dc5, 0x3c9ec7c2, 0x3ca63433, 753 | 0x3cadd37d, 0x3cb5a601, 0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d5, 0x3cdfd010, 0x3ce8ddb9, 754 | 0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e6, 0x3d11d2af, 0x3d171963, 0x3d1c7c2e, 755 | 0x3d21fb3c, 0x3d2796b2, 0x3d2d4ebb, 0x3d332380, 0x3d39152b, 0x3d3f23e3, 0x3d454fd1, 0x3d4b991c, 756 | 0x3d51ffef, 0x3d58846a, 0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c20f, 0x3d7add29, 0x3d810b67, 757 | 0x3d84b795, 0x3d887330, 0x3d8c3e4a, 0x3d9018f6, 0x3d940345, 0x3d97fd4a, 0x3d9c0716, 0x3da020bb, 758 | 0x3da44a4b, 0x3da883d7, 0x3daccd70, 0x3db12728, 0x3db59112, 0x3dba0b3b, 0x3dbe95b5, 0x3dc33092, 759 | 0x3dc7dbe2, 0x3dcc97b6, 0x3dd1641f, 0x3dd6412c, 0x3ddb2eef, 0x3de02d77, 0x3de53cd5, 0x3dea5d19, 760 | 0x3def8e52, 0x3df4d091, 0x3dfa23e8, 0x3dff8861, 0x3e027f07, 0x3e054280, 0x3e080ea3, 0x3e0ae378, 761 | 0x3e0dc105, 0x3e10a754, 0x3e13966b, 0x3e168e52, 0x3e198f10, 0x3e1c98ad, 0x3e1fab30, 0x3e22c6a3, 762 | 0x3e25eb09, 0x3e29186c, 0x3e2c4ed0, 0x3e2f8e41, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce703, 763 | 0x3e405416, 0x3e43ca5f, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027, 0x3e55a4e6, 0x3e595303, 764 | 0x3e5d0a8b, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf, 0x3e6c4720, 0x3e702e0c, 0x3e741e84, 0x3e781890, 765 | 0x3e7c1c38, 0x3e8014c2, 0x3e82203c, 0x3e84308d, 0x3e8645ba, 0x3e885fc5, 0x3e8a7eb2, 0x3e8ca283, 766 | 0x3e8ecb3d, 0x3e90f8e1, 0x3e932b74, 0x3e9562f8, 0x3e979f71, 0x3e99e0e2, 0x3e9c274e, 0x3e9e72b7, 767 | 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d289, 0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18333, 768 | 0x3eb3fc18, 0x3eb67a18, 0x3eb8fd37, 0x3ebb8579, 0x3ebe12e1, 0x3ec0a571, 0x3ec33d2d, 0x3ec5da17, 769 | 0x3ec87c33, 0x3ecb2383, 0x3ecdd00b, 0x3ed081cd, 0x3ed338cc, 0x3ed5f50b, 0x3ed8b68d, 0x3edb7d54, 770 | 0x3ede4965, 0x3ee11ac1, 0x3ee3f16b, 0x3ee6cd67, 0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 771 | 0x3ef56976, 0x3ef86594, 0x3efb6717, 0x3efe6e02, 0x3f00bd2d, 0x3f02460e, 0x3f03d1a7, 0x3f055ff9, 772 | 0x3f06f106, 0x3f0884cf, 0x3f0a1b56, 0x3f0bb49b, 0x3f0d50a0, 0x3f0eef67, 0x3f1090f1, 0x3f12353e, 773 | 0x3f13dc51, 0x3f15862b, 0x3f1732cd, 0x3f18e239, 0x3f1a946f, 0x3f1c4971, 0x3f1e0141, 0x3f1fbbdf, 774 | 0x3f21794e, 0x3f23398e, 0x3f24fca0, 0x3f26c286, 0x3f288b41, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680, 775 | 0x3f2fca9e, 0x3f31a197, 0x3f337b6c, 0x3f355820, 0x3f3737b3, 0x3f391a26, 0x3f3aff7c, 0x3f3ce7b5, 776 | 0x3f3ed2d2, 0x3f40c0d4, 0x3f42b1be, 0x3f44a590, 0x3f469c4b, 0x3f4895f1, 0x3f4a9282, 0x3f4c9201, 777 | 0x3f4e946e, 0x3f5099cb, 0x3f52a218, 0x3f54ad57, 0x3f56bb8a, 0x3f58ccb0, 0x3f5ae0cd, 0x3f5cf7e0, 778 | 0x3f5f11ec, 0x3f612eee, 0x3f634eef, 0x3f6571e9, 0x3f6797e3, 0x3f69c0d6, 0x3f6beccd, 0x3f6e1bbf, 779 | 0x3f704db8, 0x3f7282af, 0x3f74baae, 0x3f76f5ae, 0x3f7933b9, 0x3f7b74c6, 0x3f7db8e0, 0x3f800000 780 | }; 781 | 782 | VFile_Write(file, prefix, strlen(prefix)); 783 | 784 | char buffer[2048]; 785 | 786 | for (int i = 0; i < 256; ++i) { 787 | sprintf(buffer, body, i, ((float const *) sRGBTable)[i]); 788 | VFile_Write(file, buffer, strlen(buffer)); 789 | } 790 | 791 | VFile_Write(file, postfix, strlen(postfix)); 792 | } 793 | 794 | void IncludeFetchHelpers(VFile_Handle file) { 795 | #define RAW_INCLUDE_START(x) x 796 | char const *otherEnums = 797 | #include "decodehelpers.h" 798 | ""; 799 | #undef RAW_INCLUDE_START 800 | 801 | // skip first ) and last line, artifacts of the include system 802 | char const *start = otherEnums; 803 | while (*start != ')') 804 | start++; 805 | 806 | char const *end = otherEnums + strlen(otherEnums); 807 | while (*end != 'R') 808 | end--; 809 | 810 | VFile_Write(file, start + 1, end - start - 1); 811 | } 812 | 813 | void GenDecode(VFile_Handle file) { 814 | IncludeFetchHelpers(file); 815 | GetSRGBTableFuncton(file); 816 | GenCanDecodeLogicalPixelsF(file); 817 | GenDecodeLogicalPixelsF(file); 818 | GenCanDecodeLogicalPixelsD(file); 819 | GenDecodeLogicalPixelsD(file); 820 | 821 | } -------------------------------------------------------------------------------- /src/formatgen_encode.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #define __STDC_FORMAT_MACROS 5 | #include 6 | #include "al2o3_vfile/vfile.h" 7 | #include "tiny_imageformat/tinyimageformat_bits.h" 8 | #include "formatgen.h" 9 | 10 | int8_t PhysicalChannelToLogical(char const *name, uint64_t const v, uint32_t chan); 11 | void LogicalToPhysicalChannels(const char *name, uint64_t v, int8_t out[4]); 12 | 13 | double MaxActual(char const *name, uint64_t v, uint32_t const chan, bool ignoreNormFormats); 14 | uint32_t ChannelCount(char const *name, uint64_t v); 15 | uint32_t ChannelWidth(char const *name, uint64_t const v, uint32_t chan); 16 | 17 | bool PutLogicalPixelsPacked(char const *name, 18 | uint64_t const v, 19 | uint32_t const inputFloatWidth, 20 | char *output) { 21 | sprintf(output, "\n"); 22 | uint32_t maxChanWidth = 0; 23 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 24 | uint32_t chanWidth = ChannelWidth(name, v, i); 25 | if (chanWidth > maxChanWidth) 26 | maxChanWidth = chanWidth; 27 | } 28 | 29 | if (maxChanWidth > inputFloatWidth) { 30 | return false; 31 | } 32 | 33 | // special case 34 | if (v == (uint64_t)TinyImageFormat::E5B9G9R9_UFLOAT) { 35 | if (inputFloatWidth == 32) { 36 | char const decoder[] = "\n\t\t\t\tTinyImageFormat_FloatRGBToRGB9E5AsUint32( (float const*)in, (uint32_t*)out->pixel);\n" 37 | "\t\t\t\tout->pixel = (void*)(((uint32_t*)out->pixel) + 1);\n" 38 | "\t\t\t\tin += 4;\n"; 39 | sprintf(output, decoder); 40 | return true; 41 | } else { 42 | return false; 43 | } 44 | } 45 | 46 | uint64_t vspec = v >> TinyImageFormat_PACK_SPECIAL_SHIFT; 47 | 48 | auto special = (TinyImageFormat_Pack_Special const) (vspec & Mask(TinyImageFormat_PACK_SPECIAL_REQUIRED_BITS)); 49 | 50 | // how wide is the total pixel format we put to 51 | uint32_t bitWidth = 0; 52 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 53 | bitWidth += ChannelWidth(name, v, i); 54 | } 55 | uint32_t repeat = 1; 56 | switch (special) { 57 | case TinyImageFormat_PACK_SPECIAL_NONE:repeat = 1; 58 | break; 59 | case TinyImageFormat_PACK_SPECIAL_PACK:repeat = 1; 60 | break; 61 | case TinyImageFormat_PACK_SPECIAL_MULTI2:repeat = 2; 62 | break; 63 | case TinyImageFormat_PACK_SPECIAL_MULTI4:repeat = 4; 64 | break; 65 | case TinyImageFormat_PACK_SPECIAL_MULTI8:repeat = 8; 66 | break; 67 | } 68 | bitWidth *= repeat; 69 | 70 | char const UFloatXOp[] = "%s\t\t\t\t*op%d |= (%sTinyImageFormat_FloatToUFloat%dAsUint((float)in[%d])) << %lld;\n"; 71 | 72 | char const *loadOut; 73 | char const *nextPixelBuffer; 74 | char castBuffer[2048]; 75 | char scastBuffer[2048]; 76 | 77 | uint32_t outTypeSize = 0; 78 | switch (bitWidth) { 79 | case 8: 80 | case 24: loadOut = "\t\t\t\tuint8_t* op%d = (uint8_t*)out->pixel; *op%d = 0;\n"; 81 | nextPixelBuffer = "\t\t\t\tout->pixel = (void*)(((uint8_t*)out->pixel) + 1);\n"; 82 | outTypeSize = 8; 83 | break; 84 | case 48: 85 | case 16: loadOut = "\t\t\t\tuint16_t* op%d = (uint16_t*)out->pixel; *op%d = 0;\n"; 86 | nextPixelBuffer = "\t\t\t\tout->pixel = (void*)(((uint16_t*)out->pixel) + 1);\n"; 87 | outTypeSize = 16; 88 | break; 89 | case 96: 90 | case 32: loadOut = "\t\t\t\tuint32_t* op%d = (uint32_t*)out->pixel; *op%d = 0;\n"; 91 | nextPixelBuffer = "\t\t\t\tout->pixel = (void*)(((uint32_t*)out->pixel) + 1);\n"; 92 | outTypeSize = 32; 93 | break; 94 | case 256: 95 | case 192: 96 | case 128: 97 | case 64: loadOut = "\t\t\t\tuint64_t* op%d = (uint64_t*)out->pixel; *op%d = 0;\n"; 98 | nextPixelBuffer = "\t\t\t\tout->pixel = (void*)(((uint64_t*)out->pixel) + 1);\n"; 99 | outTypeSize = 64; 100 | break; 101 | 102 | default: ASSERT(false); 103 | } 104 | 105 | ASSERT(outTypeSize != 0); 106 | sprintf(castBuffer, "(uint%d_t)", outTypeSize); 107 | sprintf(scastBuffer, "(int%d_t)", outTypeSize); 108 | 109 | uint64_t shifter = 0; 110 | bool load = true; 111 | uint32_t loadIndex = 0; 112 | for (uint32_t j = 0; j < repeat; j++) { 113 | uint64_t vt = v >> TinyImageFormat_PACK_TYPE_SHIFT; 114 | uint64_t vs = v >> TinyImageFormat_PACK_SWIZZLE_SHIFT; 115 | 116 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 117 | uint32_t const chanBitWidth = ChannelWidth(name, v, i); 118 | auto swiz = (TinyImageFormat_Pack_Swizzle const) (vs & Mask(TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS)); 119 | 120 | int32_t swizzle = -1; 121 | switch (swiz) { 122 | case TinyImageFormat_PACK_SWIZZLE_R: swizzle = 0; 123 | break; 124 | case TinyImageFormat_PACK_SWIZZLE_G: swizzle = 1; 125 | break; 126 | case TinyImageFormat_PACK_SWIZZLE_B: swizzle = 2; 127 | break; 128 | case TinyImageFormat_PACK_SWIZZLE_A: swizzle = 3; 129 | break; 130 | case TinyImageFormat_PACK_SWIZZLE_0: swizzle = -1; 131 | case TinyImageFormat_PACK_SWIZZLE_1: swizzle = -2; 132 | break; 133 | } 134 | 135 | if (swizzle >= 0 && i < (int)ChannelCount(name, v)) { 136 | if (shifter >= outTypeSize) { 137 | sprintf(output, "%s%s", output, nextPixelBuffer); 138 | shifter -= outTypeSize; 139 | load = true; 140 | } 141 | if (load) { 142 | char tmp[2048]; 143 | loadIndex = (j * TinyImageFormat_PACK_NUM_CHANNELS) + i; 144 | sprintf(tmp, loadOut, loadIndex, loadIndex); 145 | sprintf(output, "%s%s", output, tmp); 146 | load = false; 147 | } 148 | 149 | double const maxFactor = MaxActual(name, v, i, true); 150 | auto type = (TinyImageFormat_Pack_Type) (vt & Mask(TinyImageFormat_PACK_TYPE_REQUIRED_BITS)); 151 | 152 | switch (type) { 153 | case TinyImageFormat_PACK_TYPE_UNORM: 154 | case TinyImageFormat_PACK_TYPE_SNORM: 155 | sprintf(output, 156 | "%s\t\t\t\t*op%d |= (%s(in[%d] * %1.2ff) & 0x%llx) << %lld;\n", 157 | output, 158 | loadIndex, 159 | (type == TinyImageFormat_PACK_TYPE_UNORM) ? castBuffer : scastBuffer, 160 | j * 4 + swizzle, 161 | maxFactor, 162 | Mask(chanBitWidth), 163 | shifter); 164 | break; 165 | case TinyImageFormat_PACK_TYPE_SINT: 166 | case TinyImageFormat_PACK_TYPE_UINT: 167 | sprintf(output, 168 | "%s\t\t\t\t*op%d |= ((%sin[%d]) & 0x%llx) << %lld;\n", 169 | output, 170 | loadIndex, 171 | (type == TinyImageFormat_PACK_TYPE_UINT) ? castBuffer : scastBuffer, 172 | j * 4 + swizzle, 173 | Mask(chanBitWidth), 174 | shifter); 175 | break; 176 | case TinyImageFormat_PACK_TYPE_SRGB: 177 | sprintf(output, 178 | "%s\t\t\t\t*op%d |= (%sTinyImageFormat_FloatToSRGB((float)in[%d])) << %lld;\n", 179 | output, 180 | loadIndex, 181 | castBuffer, 182 | j * 4 + swizzle, 183 | shifter); 184 | break; 185 | case TinyImageFormat_PACK_TYPE_UFLOAT: 186 | sprintf(output, 187 | UFloatXOp, 188 | output, 189 | loadIndex, 190 | castBuffer, 191 | chanBitWidth, 192 | j * 4 + swizzle, 193 | shifter); 194 | break; 195 | case TinyImageFormat_PACK_TYPE_SFLOAT: 196 | if (chanBitWidth == 16) { 197 | sprintf(output, 198 | "%s\t\t\t\t*op%d |= (%sTinyImageFormat_FloatToHalfAsUint((float)in[%d])) << %lld;\n", 199 | output, 200 | loadIndex, 201 | castBuffer, 202 | j * 4 + swizzle, 203 | shifter); 204 | } else if (chanBitWidth == 32) { 205 | sprintf(output, 206 | "%s\t\t\t\tfloat in%d = (float)in[%d];\n" 207 | "\t\t\t\t*op%d |= (%s*((uint32_t*)&in%d)) << %lld;\n", 208 | output, 209 | j * 4 + swizzle, 210 | j * 4 + swizzle, 211 | loadIndex, 212 | castBuffer, 213 | j * 4 + swizzle, 214 | shifter); 215 | } else if (chanBitWidth == 64) { 216 | sprintf(output, 217 | "%s\t\t\t\tdouble in%d = (double)in[%d];\n" 218 | "\t\t\t\t*op%d |= (%s*((uint64_t*)&in%d)) << %lld;\n", 219 | output, 220 | j * 4 + swizzle, 221 | j * 4 + swizzle, 222 | loadIndex, 223 | castBuffer, 224 | j * 4 + swizzle, 225 | shifter); 226 | } 227 | break; 228 | case TinyImageFormat_PACK_TYPE_SBFLOAT: 229 | if (chanBitWidth == 16) { 230 | sprintf(output, 231 | "%s\t\t\t\t*op%d |= (%sTinyImageFormat_FloatToBFloatAsUint((float)in[%d])) << %lld;\n", 232 | output, 233 | loadIndex, 234 | castBuffer, 235 | j * 4 + swizzle, 236 | shifter); 237 | } else { 238 | ASSERT(false); 239 | } 240 | break; 241 | case TinyImageFormat_PACK_TYPE_NONE: ASSERT(false); 242 | } 243 | 244 | } 245 | shifter += chanBitWidth; 246 | vt = vt >> TinyImageFormat_PACK_TYPE_REQUIRED_BITS; 247 | vs = vs >> TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS; 248 | } 249 | } 250 | sprintf(output, "%s%s", output, nextPixelBuffer); 251 | sprintf(output, "%s\t\t\t\tin+=%d;\n", output, 4 * repeat); 252 | 253 | return true; 254 | } 255 | 256 | bool EncodeLogicalPixelsF(char const *name, uint64_t const v, char *output) { 257 | if (v == 0) 258 | return false; 259 | 260 | if (IsInPacked(name, v)) { 261 | return PutLogicalPixelsPacked(name, v, 32, output); 262 | }/* else if (IsInCLUT(name, v)) { 263 | return PutLogicalPixelsCLUT(name, v, 32, output); 264 | }*/ 265 | 266 | return false; 267 | } 268 | 269 | bool EncodeLogicalPixelsD(char const *name, uint64_t const v, char *output) { 270 | if (v == 0) 271 | return false; 272 | 273 | uint32_t maxChanWidth = 0; 274 | for (int i = 0; i < TinyImageFormat_PACK_NUM_CHANNELS; ++i) { 275 | uint32_t chanWidth = ChannelWidth(name, v, i); 276 | if (chanWidth > maxChanWidth) 277 | maxChanWidth = chanWidth; 278 | } 279 | 280 | if (maxChanWidth < 64) { 281 | return false; 282 | } 283 | 284 | if (IsInPacked(name, v)) { 285 | return PutLogicalPixelsPacked(name, v, 64, output); 286 | 287 | } else if (IsInCLUT(name, v)) { 288 | // return PutLogicalPixelsCLUT(name, v, 64, output); 289 | } 290 | return false; 291 | } 292 | 293 | static void GenCanEncodeLogicalPixelsF(VFile_Handle file) { 294 | char buffer[2048]; 295 | 296 | char const *const isPrefixF = 297 | "TIF_CONSTEXPR inline bool TinyImageFormat_CanEncodeLogicalPixelsF(TinyImageFormat const fmt) {\n" 298 | "\tswitch(fmt) {\n"; 299 | 300 | char const *const body = "\t\tcase %s: return true;\n"; 301 | char const switchPostfixF[] = "\t\tdefault: return false;\n\t\t}\n\t}\n\n"; 302 | 303 | char output[2048]; 304 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 305 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = EncodeLogicalPixelsF(#x, y, output); if(okay) { sprintf(buffer, body, "TinyImageFormat_"#x); VFile_Write(file, buffer, strlen(buffer)); } } 306 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 307 | #include "formatgen.h" 308 | 309 | } 310 | 311 | void GenEncodeLogicalPixelsF(VFile_Handle file) { 312 | char buffer[2048]; 313 | 314 | char const *const isPrefixF = 315 | "TIF_CONSTEXPR inline bool TinyImageFormat_EncodeLogicalPixelsF(TinyImageFormat const fmt, float const *in, uint32_t const width, TinyImageFormat_EncodeOutput * out) {\n" 316 | "\tswitch(fmt) {\n"; 317 | char const *const body = "\t\tcase %s:\n\t\t\tfor(uint32_t w = 0; w < width; ++w) {" 318 | "%s" 319 | "\t\t\t}\n\t\t\treturn true;\n"; 320 | 321 | char const switchPostfixF[] = "\t\tdefault: return false;\n\t}\n}\n\n"; 322 | 323 | char output[2048]; 324 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 325 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = EncodeLogicalPixelsF(#x, y, output); if(okay) { sprintf(buffer, body, "TinyImageFormat_"#x, output); VFile_Write(file, buffer, strlen(buffer)); } } 326 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 327 | #include "formatgen.h" 328 | } 329 | 330 | static void GenCanEncodeLogicalPixelsD(VFile_Handle file) { 331 | char buffer[2048]; 332 | 333 | char const *const isPrefixF = 334 | "TIF_CONSTEXPR inline bool TinyImageFormat_CanEncodeLogicalPixelsD(TinyImageFormat const fmt) {\n" 335 | "\tswitch(fmt) {\n"; 336 | 337 | char const *const body = "\t\tcase %s: return true;\n"; 338 | char const switchPostfixF[] = "\t\tdefault: return TinyImageFormat_CanEncodeLogicalPixelsF(fmt);\n" 339 | "\t}\n}\n\n"; 340 | 341 | char output[2048]; 342 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 343 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = EncodeLogicalPixelsD(#x, y, output); if(okay) { sprintf(buffer, body, "TinyImageFormat_"#x); VFile_Write(file, buffer, strlen(buffer)); } } 344 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 345 | #include "formatgen.h" 346 | 347 | } 348 | 349 | void GenEncodeLogicalPixelsD(VFile_Handle file) { 350 | char buffer[2048]; 351 | 352 | char const *const isPrefixF = 353 | "TIF_CONSTEXPR inline bool TinyImageFormat_EncodeLogicalPixelsD(TinyImageFormat const fmt, double const *in, uint32_t const width, TinyImageFormat_EncodeOutput * out) {\n" 354 | "\tswitch(fmt) {\n"; 355 | char const *const body = "\t\tcase %s:\n\t\t\tfor(uint32_t w = 0; w < width; ++w) {" 356 | "%s" 357 | "\t\t\t}\n\t\t\treturn true;\n"; 358 | 359 | char const switchPostfixF[] = "\t\tdefault:\n" 360 | "\t\t{\n" 361 | "\t\t\tbool ret = true;\n" 362 | "\t\t\tfor(uint32_t w = 0; w < width && ret; ++w) {\n" 363 | "\t\t\t\tfloat inF[4] = {(float)in[0], (float)in[1], (float)in[2], (float)in[3]};\n" 364 | "\t\t\t\tret = TinyImageFormat_EncodeLogicalPixelsF(fmt, inF, 1, out);\n" 365 | "\t\t\t\tin += 4;\n" 366 | "\t\t\t}\n" 367 | "\t\t\treturn ret;\n" 368 | "\t\t}\n" 369 | "\t}\n" 370 | "}\n\n"; 371 | 372 | char output[2048]; 373 | #define TinyImageFormat_START_MACRO VFile_Write(file, isPrefixF, strlen(isPrefixF)); 374 | #define TinyImageFormat_MOD_MACRO(x, y) { bool okay = EncodeLogicalPixelsD(#x, y, output); if(okay) { sprintf(buffer, body, "TinyImageFormat_"#x, output); VFile_Write(file, buffer, strlen(buffer)); } } 375 | #define TinyImageFormat_END_MACRO sprintf(buffer, switchPostfixF); VFile_Write(file, buffer, strlen(buffer)); 376 | #include "formatgen.h" 377 | } 378 | 379 | void IncludeEncodeHelpers(VFile_Handle file) { 380 | #define RAW_INCLUDE_START(x) x 381 | char const *otherEnums = 382 | #include "encodehelpers.h" 383 | ""; 384 | #undef RAW_INCLUDE_START 385 | 386 | // skip first ) and last line, artifacts of the include system 387 | char const *start = otherEnums; 388 | while (*start != ')') 389 | start++; 390 | 391 | char const *end = otherEnums + strlen(otherEnums); 392 | while (*end != 'R') 393 | end--; 394 | 395 | VFile_Write(file, start + 1, end - start - 1); 396 | } 397 | 398 | void GenEncode(VFile_Handle file) { 399 | IncludeEncodeHelpers(file); 400 | 401 | // GetSRGBTableFuncton(file); 402 | 403 | GenCanEncodeLogicalPixelsF(file); 404 | GenEncodeLogicalPixelsF(file); 405 | GenCanEncodeLogicalPixelsD(file); 406 | GenEncodeLogicalPixelsD(file); 407 | 408 | } 409 | 410 | -------------------------------------------------------------------------------- /src/formatgen_func.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef enum TinyImageFormat_LogicalChannel { 4 | TinyImageFormat_LC_Red = 0, 5 | TinyImageFormat_LC_Green = 1, 6 | TinyImageFormat_LC_Blue = 2, 7 | TinyImageFormat_LC_Alpha = 3, 8 | TinyImageFormat_LC_Depth = 0, 9 | TinyImageFormat_LC_Stencil = 1, 10 | TinyImageFormat_LC_0 = -1, 11 | TinyImageFormat_LC_1 = -2, 12 | } TinyImageFormat_LogicalChannel; 13 | 14 | typedef enum TinyImageFormat_PhysicalChannel { 15 | TinyImageFormat_PC_0 = 0, 16 | TinyImageFormat_PC_1 = 1, 17 | TinyImageFormat_PC_2 = 2, 18 | TinyImageFormat_PC_3 = 3, 19 | TinyImageFormat_PC_CONST_0 = -1, 20 | TinyImageFormat_PC_CONST_1 = -2, 21 | } TinyImageFormat_PhysicalChannel; 22 | 23 | constexpr uint64_t TinyImageFormat_CONSTEXPR_Pack( 24 | uint64_t rs, uint64_t rb, uint64_t rt, 25 | uint64_t gs, uint64_t gb, uint64_t gt, 26 | uint64_t bs, uint64_t bb, uint64_t bt, 27 | uint64_t as, uint64_t ab, uint64_t at, 28 | uint64_t special ) { 29 | 30 | static_assert((( TinyImageFormat_PACK_NUM_CHANNELS * TinyImageFormat_PACK_BITS_REQUIRED_BITS) + TinyImageFormat_PACK_BITS_SHIFT) == 35); 31 | static_assert((( TinyImageFormat_PACK_NUM_CHANNELS * TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_PACK_SWIZZLE_SHIFT) == 47); 32 | static_assert((( TinyImageFormat_PACK_NUM_CHANNELS * TinyImageFormat_PACK_TYPE_REQUIRED_BITS) + TinyImageFormat_PACK_TYPE_SHIFT) == 63); 33 | 34 | static_assert((( TinyImageFormat_PACK_NUM_CHANNELS * TinyImageFormat_PACK_TYPE_REQUIRED_BITS) + TinyImageFormat_PACK_TYPE_SHIFT) < 64); 35 | 36 | uint64_t packed = TinyImageFormat_NAMESPACE_PACK | 37 | (special << TinyImageFormat_PACK_SPECIAL_SHIFT) | 38 | (rb << (( TinyImageFormat_PC_0 * TinyImageFormat_PACK_BITS_REQUIRED_BITS) + TinyImageFormat_PACK_BITS_SHIFT)) | 39 | (rs << (( TinyImageFormat_PC_0 * TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_PACK_SWIZZLE_SHIFT)) | 40 | (rt << (( TinyImageFormat_PC_0 * TinyImageFormat_PACK_TYPE_REQUIRED_BITS) + TinyImageFormat_PACK_TYPE_SHIFT)) | 41 | 42 | (gb << (( TinyImageFormat_PC_1 * TinyImageFormat_PACK_BITS_REQUIRED_BITS) + TinyImageFormat_PACK_BITS_SHIFT)) | 43 | (gs << (( TinyImageFormat_PC_1 * TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_PACK_SWIZZLE_SHIFT)) | 44 | (gt << (( TinyImageFormat_PC_1 * TinyImageFormat_PACK_TYPE_REQUIRED_BITS) + TinyImageFormat_PACK_TYPE_SHIFT)) | 45 | 46 | (bb << (( TinyImageFormat_PC_2 * TinyImageFormat_PACK_BITS_REQUIRED_BITS) + TinyImageFormat_PACK_BITS_SHIFT)) | 47 | (bs << (( TinyImageFormat_PC_2 * TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_PACK_SWIZZLE_SHIFT)) | 48 | (bt << (( TinyImageFormat_PC_2 * TinyImageFormat_PACK_TYPE_REQUIRED_BITS) + TinyImageFormat_PACK_TYPE_SHIFT)) | 49 | 50 | (ab << (( TinyImageFormat_PC_3 * TinyImageFormat_PACK_BITS_REQUIRED_BITS) + TinyImageFormat_PACK_BITS_SHIFT)) | 51 | (as << (( TinyImageFormat_PC_3 * TinyImageFormat_PACK_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_PACK_SWIZZLE_SHIFT)) | 52 | (at << (( TinyImageFormat_PC_3 * TinyImageFormat_PACK_TYPE_REQUIRED_BITS) + TinyImageFormat_PACK_TYPE_SHIFT)) | 53 | 0; 54 | return packed; 55 | } 56 | 57 | constexpr uint64_t TinyImageFormat_CONSTEXPR_DepthStencil( uint64_t rs, uint64_t rb, uint64_t rt, uint64_t gs, uint64_t gb, uint64_t gt, uint64_t size) { 58 | static_assert((( TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS * TinyImageFormat_DEPTH_STENCIL_BITS_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_BITS_SHIFT) == 20); 59 | static_assert((( TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS * TinyImageFormat_DEPTH_STENCIL_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_SWIZZLE_SHIFT) == 24); 60 | static_assert((( TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS * TinyImageFormat_DEPTH_STENCIL_TYPE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_TYPE_SHIFT) == 28); 61 | 62 | static_assert((( TinyImageFormat_DEPTH_STENCIL_NUM_CHANNELS * TinyImageFormat_DEPTH_STENCIL_TYPE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_TYPE_SHIFT) < 64); 63 | 64 | uint64_t value = TinyImageFormat_NAMESPACE_DEPTH_STENCIL | 65 | (size << TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_SHIFT) | 66 | (rb << (( TinyImageFormat_PC_0 * TinyImageFormat_DEPTH_STENCIL_BITS_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_BITS_SHIFT)) | 67 | (rs << (( TinyImageFormat_PC_0 * TinyImageFormat_DEPTH_STENCIL_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_SWIZZLE_SHIFT)) | 68 | (rt << (( TinyImageFormat_PC_0 * TinyImageFormat_DEPTH_STENCIL_TYPE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_TYPE_SHIFT)) | 69 | 70 | (gb << (( TinyImageFormat_PC_1 * TinyImageFormat_DEPTH_STENCIL_BITS_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_BITS_SHIFT)) | 71 | (gs << (( TinyImageFormat_PC_1 * TinyImageFormat_DEPTH_STENCIL_SWIZZLE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_SWIZZLE_SHIFT)) | 72 | (gt << (( TinyImageFormat_PC_1 * TinyImageFormat_DEPTH_STENCIL_TYPE_REQUIRED_BITS) + TinyImageFormat_DEPTH_STENCIL_TYPE_SHIFT)) | 73 | 0; 74 | return value; 75 | } 76 | 77 | constexpr uint64_t TinyImageFormat_CONSTEXPR_DXTC(uint64_t alpha, uint64_t type, uint64_t blockBytes, uint64_t channelCount, uint64_t modeCount) { 78 | static_assert( TinyImageFormat_DXTC_ALPHA_SHIFT == 12); 79 | static_assert( TinyImageFormat_DXTC_TYPE_SHIFT == 14); 80 | static_assert( TinyImageFormat_DXTC_BLOCKBYTES_SHIFT == 17); 81 | static_assert( TinyImageFormat_DXTC_CHANNELCOUNT_SHIFT == 19); 82 | static_assert( TinyImageFormat_DXTC_MODECOUNT_SHIFT == 21); 83 | 84 | static_assert( TinyImageFormat_DXTC_MODECOUNT_REQUIRED_BITS + TinyImageFormat_DXTC_MODECOUNT_SHIFT < 64); 85 | 86 | uint64_t value = TinyImageFormat_NAMESPACE_DXTC | 87 | (alpha << TinyImageFormat_DXTC_ALPHA_SHIFT) | 88 | (type << TinyImageFormat_DXTC_TYPE_SHIFT) | 89 | (blockBytes << TinyImageFormat_DXTC_BLOCKBYTES_SHIFT) | 90 | (channelCount << TinyImageFormat_DXTC_CHANNELCOUNT_SHIFT) | 91 | (modeCount << TinyImageFormat_DXTC_MODECOUNT_SHIFT) | 92 | 0; 93 | return value; 94 | } 95 | 96 | constexpr uint64_t TinyImageFormat_CONSTEXPR_PVRTC(uint64_t version, uint64_t bits, uint64_t type) { 97 | static_assert( TinyImageFormat_PVRTC_VERSION_SHIFT == 12); 98 | static_assert( TinyImageFormat_PVRTC_BITS_SHIFT == 14); 99 | static_assert( TinyImageFormat_PVRTC_TYPE_SHIFT == 16); 100 | 101 | static_assert( TinyImageFormat_PVRTC_TYPE_REQUIRED_BITS + TinyImageFormat_PVRTC_TYPE_SHIFT < 64); 102 | 103 | uint64_t value = TinyImageFormat_NAMESPACE_PVRTC | 104 | (version << TinyImageFormat_PVRTC_VERSION_SHIFT) | 105 | (bits << TinyImageFormat_PVRTC_BITS_SHIFT) | 106 | (type << TinyImageFormat_PVRTC_TYPE_SHIFT) | 107 | 0; 108 | return value; 109 | } 110 | 111 | constexpr uint64_t TinyImageFormat_CONSTEXPR_ETC(uint64_t bits, uint64_t alpha, uint64_t type, uint64_t channelCount) { 112 | static_assert( TinyImageFormat_ETC_BITS_SHIFT == 12); 113 | static_assert( TinyImageFormat_ETC_ALPHA_SHIFT == 14); 114 | static_assert( TinyImageFormat_ETC_TYPE_SHIFT == 16); 115 | static_assert( TinyImageFormat_ETC_CHANNELCOUNT_SHIFT == 18); 116 | 117 | static_assert( TinyImageFormat_ETC_CHANNELCOUNT_REQUIRED_BITS + TinyImageFormat_ETC_CHANNELCOUNT_SHIFT < 64); 118 | 119 | uint64_t value = TinyImageFormat_NAMESPACE_ETC | 120 | (bits << TinyImageFormat_ETC_BITS_SHIFT) | 121 | (alpha << TinyImageFormat_ETC_ALPHA_SHIFT) | 122 | (type << TinyImageFormat_ETC_TYPE_SHIFT) | 123 | (channelCount << TinyImageFormat_ETC_CHANNELCOUNT_SHIFT) | 124 | 0; 125 | return value; 126 | } 127 | 128 | constexpr uint64_t TinyImageFormat_CONSTEXPR_ASTC(uint64_t w, uint64_t h, uint64_t d, uint64_t type) { 129 | static_assert( TinyImageFormat_ASTC_SIZE_SHIFT == 12); 130 | static_assert( TinyImageFormat_ASTC_TYPE_SHIFT == 21); 131 | 132 | static_assert( (TinyImageFormat_ASTC_NUM_DIMS * TinyImageFormat_ASTC_TYPE_REQUIRED_BITS) + TinyImageFormat_ASTC_TYPE_SHIFT < 64); 133 | 134 | uint64_t value = TinyImageFormat_NAMESPACE_ASTC | 135 | (w << ((0 * TinyImageFormat_ASTC_SIZE_REQUIRED_BITS) + TinyImageFormat_ASTC_SIZE_SHIFT)) | 136 | (h << ((1 * TinyImageFormat_ASTC_SIZE_REQUIRED_BITS) + TinyImageFormat_ASTC_SIZE_SHIFT)) | 137 | (d << ((2 * TinyImageFormat_ASTC_SIZE_REQUIRED_BITS) + TinyImageFormat_ASTC_SIZE_SHIFT)) | 138 | (type << TinyImageFormat_ASTC_TYPE_SHIFT) | 139 | 0; 140 | return value; 141 | } 142 | 143 | constexpr uint64_t TinyImageFormat_CONSTEXPR_CLUT(uint64_t bs, uint64_t c0s, uint64_t c0t, uint64_t c1s, uint64_t c1t) { 144 | static_assert( TinyImageFormat_CLUT_BLOCKSIZE_SHIFT == 12); 145 | static_assert( TinyImageFormat_CLUT_BITS_SHIFT == 14); 146 | static_assert( TinyImageFormat_CLUT_TYPE_SHIFT == 20); 147 | 148 | static_assert( (TinyImageFormat_CLUT_NUM_CHANNELS * TinyImageFormat_CLUT_TYPE_REQUIRED_BITS) + TinyImageFormat_CLUT_TYPE_SHIFT < 64); 149 | 150 | uint64_t value = TinyImageFormat_NAMESPACE_CLUT | 151 | (bs << TinyImageFormat_CLUT_BLOCKSIZE_SHIFT) | 152 | (c0s << ((0 * TinyImageFormat_CLUT_BITS_REQUIRED_BITS) + TinyImageFormat_CLUT_BITS_SHIFT)) | 153 | (c1s << ((1 * TinyImageFormat_CLUT_BITS_REQUIRED_BITS) + TinyImageFormat_CLUT_BITS_SHIFT)) | 154 | (c0t << ((0 * TinyImageFormat_CLUT_TYPE_REQUIRED_BITS) + TinyImageFormat_CLUT_TYPE_SHIFT)) | 155 | (c1t << ((1 * TinyImageFormat_CLUT_TYPE_REQUIRED_BITS) + TinyImageFormat_CLUT_TYPE_SHIFT)) | 156 | 0; 157 | return value; 158 | } 159 | 160 | constexpr bool IsInPacked(char const *name, uint64_t v) { 161 | return (v & TinyImageFormat_NAMESPACE_MASK) == TinyImageFormat_NAMESPACE_PACK; 162 | } 163 | 164 | constexpr bool IsInDepthStencil(char const *name, uint64_t v) { 165 | return (v & TinyImageFormat_NAMESPACE_MASK) == TinyImageFormat_NAMESPACE_DEPTH_STENCIL; 166 | } 167 | 168 | constexpr bool IsInDXTC(char const *name, uint64_t v) { 169 | return (v & TinyImageFormat_NAMESPACE_MASK) == TinyImageFormat_NAMESPACE_DXTC; 170 | } 171 | 172 | constexpr bool IsInPVRTC(char const *name, uint64_t v) { 173 | return (v & TinyImageFormat_NAMESPACE_MASK) == TinyImageFormat_NAMESPACE_PVRTC; 174 | } 175 | 176 | constexpr bool IsInETC(char const *name, uint64_t v) { 177 | return (v & TinyImageFormat_NAMESPACE_MASK) == TinyImageFormat_NAMESPACE_ETC; 178 | } 179 | 180 | constexpr bool IsInASTC(char const *name, uint64_t v) { 181 | return (v & TinyImageFormat_NAMESPACE_MASK) == TinyImageFormat_NAMESPACE_ASTC; 182 | } 183 | 184 | constexpr bool IsInCLUT(char const *name, uint64_t v) { 185 | return (v & TinyImageFormat_NAMESPACE_MASK) == TinyImageFormat_NAMESPACE_CLUT; 186 | } 187 | 188 | constexpr uint64_t Mask(uint64_t v) { 189 | return (1ULL << v) - 1ULL; 190 | } 191 | -------------------------------------------------------------------------------- /src/formatgen_macros.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define TinyImageFormat_PACK( rs, rb, rt, gs, gb, gt, bs, bb, bt, as, ab, at, special) TinyImageFormat_CONSTEXPR_Pack( \ 4 | TinyImageFormat_PACK_SWIZZLE_##rs, TinyImageFormat_PACK_BITS_##rb, TinyImageFormat_PACK_TYPE_##rt, \ 5 | TinyImageFormat_PACK_SWIZZLE_##gs, TinyImageFormat_PACK_BITS_##gb, TinyImageFormat_PACK_TYPE_##gt, \ 6 | TinyImageFormat_PACK_SWIZZLE_##bs, TinyImageFormat_PACK_BITS_##bb, TinyImageFormat_PACK_TYPE_##bt, \ 7 | TinyImageFormat_PACK_SWIZZLE_##as, TinyImageFormat_PACK_BITS_##ab, TinyImageFormat_PACK_TYPE_##at, \ 8 | TinyImageFormat_PACK_SPECIAL_##special) 9 | 10 | #define TinyImageFormat_PACK_3(rs, rb, rt, gs, gb, gt, bs, bb, bt, special)\ 11 | TinyImageFormat_PACK(rs, rb, rt, gs, gb, gt, bs, bb, bt, 1, _, _, special) 12 | #define TinyImageFormat_PACK_2(rs, rb, rt, gs, gb, gt, special) TinyImageFormat_PACK(rs, rb, rt, gs, gb, gt, 0, _, _, 1, _, _, special) 13 | #define TinyImageFormat_PACK_1(rs, rb, rt, special) TinyImageFormat_PACK(rs, rb, rt, 0, _, _, 0, _, _, 1, _, _, special) 14 | 15 | #define TinyImageFormat_PACK_2_UNORM(rs, rb, gs, gb, special) TinyImageFormat_PACK_2(rs, rb, UNORM, gs, gb, UNORM, special) 16 | #define TinyImageFormat_PACK_3_UNORM(rs, rb, gs, gb, bs, bb, special) TinyImageFormat_PACK_3(rs, rb, UNORM, gs, gb, UNORM, bs, bb, UNORM, special) 17 | #define TinyImageFormat_PACK_4_UNORM(rs, rb, gs, gb, bs, bb, as, ab, special) TinyImageFormat_PACK(rs, rb, UNORM, gs, gb, UNORM, bs, bb, UNORM, as, ab, UNORM, special) 18 | #define TinyImageFormat_PACK_2_SNORM(rs, rb, gs, gb, special) TinyImageFormat_PACK_2(rs, rb, SNORM, gs, gb, SNORM, special) 19 | #define TinyImageFormat_PACK_3_SNORM(rs, rb, gs, gb, bs, bb, special) TinyImageFormat_PACK_3(rs, rb, SNORM, gs, gb, SNORM, bs, bb, SNORM, special) 20 | #define TinyImageFormat_PACK_4_SNORM(rs, rb, gs, gb, bs, bb, as, ab, special) TinyImageFormat_PACK(rs, rb, SNORM, gs, gb, SNORM, bs, bb, SNORM, as, ab, SNORM, special) 21 | #define TinyImageFormat_PACK_2_UINT(rs, rb, gs, gb, special) TinyImageFormat_PACK_2(rs, rb, UINT, gs, gb, UINT, special) 22 | #define TinyImageFormat_PACK_3_UINT(rs, rb, gs, gb, bs, bb, special) TinyImageFormat_PACK_3(rs, rb, UINT, gs, gb, UINT, bs, bb, UINT, special) 23 | #define TinyImageFormat_PACK_4_UINT(rs, rb, gs, gb, bs, bb, as, ab, special) TinyImageFormat_PACK(rs, rb, UINT, gs, gb, UINT, bs, bb, UINT, as, ab, UINT, special) 24 | #define TinyImageFormat_PACK_2_SINT(rs, rb, gs, gb, special) TinyImageFormat_PACK_2(rs, rb, SINT, gs, gb, SINT, special) 25 | #define TinyImageFormat_PACK_3_SINT(rs, rb, gs, gb, bs, bb, special) TinyImageFormat_PACK_3(rs, rb, SINT, gs, gb, SINT, bs, bb, SINT, special) 26 | #define TinyImageFormat_PACK_4_SINT(rs, rb, gs, gb, bs, bb, as, ab, special) TinyImageFormat_PACK(rs, rb, SINT, gs, gb, SINT, bs, bb, SINT, as, ab, SINT, special) 27 | #define TinyImageFormat_PACK_2_SFLOAT(rs, rb, gs, gb, special) TinyImageFormat_PACK_2(rs, rb, SFLOAT, gs, gb, SFLOAT, special) 28 | #define TinyImageFormat_PACK_3_SFLOAT(rs, rb, gs, gb, bs, bb, special) TinyImageFormat_PACK_3(rs, rb, SFLOAT, gs, gb, SFLOAT, bs, bb, SFLOAT, special) 29 | #define TinyImageFormat_PACK_4_SFLOAT(rs, rb, gs, gb, bs, bb, as, ab, special) TinyImageFormat_PACK(rs, rb, SFLOAT, gs, gb, SFLOAT, bs, bb, SFLOAT, as, ab, SFLOAT, special) 30 | 31 | #define TinyImageFormat_PACK_2_SRGB(rs, rb, gs, gb, special) TinyImageFormat_PACK_2(rs, rb, SRGB, gs, gb, SRGB, special) 32 | #define TinyImageFormat_PACK_3_SRGB(rs, rb, gs, gb, bs, bb, special) TinyImageFormat_PACK_3(rs, rb, SRGB, gs, gb, SRGB, bs, bb, SRGB, special) 33 | // SRGB never goes in alpha 34 | #define TinyImageFormat_PACK_4_SRGB(rs, rb, gs, gb, bs, bb, as, ab, special) TinyImageFormat_PACK(rs, rb, SRGB, gs, gb, SRGB, bs, bb, SRGB, as, ab, UNORM, special) 35 | 36 | 37 | #define TinyImageFormat_DEPTH_STENCIL( rs, rb, rt, gs, gb, gt, size) TinyImageFormat_CONSTEXPR_DepthStencil( \ 38 | TinyImageFormat_DEPTH_STENCIL_SWIZZLE_##rs, TinyImageFormat_DEPTH_STENCIL_BITS_##rb, TinyImageFormat_DEPTH_STENCIL_TYPE_##rt, \ 39 | TinyImageFormat_DEPTH_STENCIL_SWIZZLE_##gs, TinyImageFormat_DEPTH_STENCIL_BITS_##gb, TinyImageFormat_DEPTH_STENCIL_TYPE_##gt, \ 40 | TinyImageFormat_DEPTH_STENCIL_TOTAL_SIZE_##size) 41 | 42 | #define TinyImageFormat_DXTC(a, t, b, cc, mc) TinyImageFormat_CONSTEXPR_DXTC( TinyImageFormat_DXTC_ALPHA_##a, TinyImageFormat_DXTC_TYPE_##t, TinyImageFormat_DXTC_BLOCKBYTES_##b, TinyImageFormat_DXTC_CHANNELCOUNT_##cc, TinyImageFormat_DXTC_MODECOUNT_##mc) 43 | #define TinyImageFormat_PVRTC(v, b, t) TinyImageFormat_CONSTEXPR_PVRTC( TinyImageFormat_PVRTC_VERSION_##v, TinyImageFormat_PVRTC_BITS_##b, TinyImageFormat_PVRTC_TYPE_##t) 44 | #define TinyImageFormat_ETC(b, a, t, cc) TinyImageFormat_CONSTEXPR_ETC( TinyImageFormat_ETC_BITS_##b, TinyImageFormat_ETC_ALPHA_##a, TinyImageFormat_ETC_TYPE_##t, TinyImageFormat_ETC_CHANNELCOUNT_##cc) 45 | #define TinyImageFormat_ASTC(w, h, d, t) TinyImageFormat_CONSTEXPR_ASTC( TinyImageFormat_ASTC_SIZE_##w, TinyImageFormat_ASTC_SIZE_##h, TinyImageFormat_ASTC_SIZE_##d, TinyImageFormat_ASTC_TYPE_##t) 46 | #define TinyImageFormat_CLUT(bs, c0s, c0t, c1s, c1t) TinyImageFormat_CONSTEXPR_CLUT( TinyImageFormat_CLUT_BLOCKSIZE_##bs, TinyImageFormat_CLUT_BITS_##c0s, TinyImageFormat_CLUT_TYPE_##c0t, TinyImageFormat_CLUT_BITS_##c1s, TinyImageFormat_CLUT_TYPE_##c1t) 47 | 48 | 49 | #define TinyImageFormat_PACK_BITS__ TinyImageFormat_PACK_BITS_0 50 | #define TinyImageFormat_PACK_SWIZZLE__ TinyImageFormat_PACK_SWIZZLE_0 51 | #define TinyImageFormat_PACK_TYPE__ TinyImageFormat_PACK_TYPE_NONE 52 | #define TinyImageFormat_DEPTH_STENCIL_BITS__ TinyImageFormat_DEPTH_STENCIL_BITS_0 53 | #define TinyImageFormat_DEPTH_STENCIL_SWIZZLE__ TinyImageFormat_DEPTH_STENCIL_SWIZZLE_0 54 | #define TinyImageFormat_DEPTH_STENCIL_TYPE__ TinyImageFormat_DEPTH_STENCIL_TYPE_NONE 55 | 56 | #define TinyImageFormat_CLUT_BLOCKSIZE__ TinyImageFormat_CLUT_BLOCKSIZE_1 57 | #define TinyImageFormat_CLUT_BITS__ TinyImageFormat_CLUT_BITS_0 58 | #define TinyImageFormat_CLUT_TYPE__ TinyImageFormat_CLUT_TYPE_NONE 59 | -------------------------------------------------------------------------------- /src/queryhelpers.h: -------------------------------------------------------------------------------- 1 | RAW_INCLUDE_START( R"=====( ) 2 | 3 | // Helpers 4 | TIF_CONSTEXPR inline uint32_t TinyImageFormat_PixelCountOfBlock(TinyImageFormat const fmt) { 5 | return TinyImageFormat_WidthOfBlock(fmt) * TinyImageFormat_HeightOfBlock(fmt) * TinyImageFormat_DepthOfBlock(fmt); 6 | } 7 | 8 | TIF_CONSTEXPR inline double TinyImageFormat_Min(TinyImageFormat const fmt, TinyImageFormat_LogicalChannel const channel) { 9 | return TinyImageFormat_MinAtPhysical(fmt, TinyImageFormat_LogicalChannelToPhysical(fmt, channel)); 10 | } 11 | 12 | TIF_CONSTEXPR inline double TinyImageFormat_Max(TinyImageFormat const fmt, TinyImageFormat_LogicalChannel const channel) { 13 | return TinyImageFormat_MaxAtPhysical(fmt, TinyImageFormat_LogicalChannelToPhysical(fmt, channel)); 14 | } 15 | 16 | TIF_CONSTEXPR inline uint32_t TinyImageFormat_ChannelBitWidth(TinyImageFormat const fmt, TinyImageFormat_LogicalChannel const channel) { 17 | return TinyImageFormat_ChannelBitWidthAtPhysical(fmt, TinyImageFormat_LogicalChannelToPhysical(fmt, channel)); 18 | } 19 | 20 | RAW_INCLUDE_END( )=====" ) -------------------------------------------------------------------------------- /tests/runner.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_RUNNER 2 | #include "al2o3_catch2/catch2.hpp" 3 | #include "al2o3_memory/memory.h" 4 | #include "utils_simple_logmanager/logmanager.h" 5 | 6 | int main(int argc, char const *argv[]) { 7 | auto logger = SimpleLogManager_Alloc(); 8 | 9 | auto ret = Catch::Session().run(argc, (char**)argv); 10 | 11 | SimpleLogManager_Free(logger); 12 | return ret; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /tests/test_formatcracker.cpp: -------------------------------------------------------------------------------- 1 | #include "al2o3_platform/platform.h" 2 | #include "al2o3_catch2/catch2.hpp" 3 | 4 | #include "tiny_imageformat/tinyimageformat_base.h" 5 | #include "tiny_imageformat/tinyimageformat_query.h" 6 | #include 7 | 8 | TEST_CASE("Format Cracker IsDepthOnly (C)", "[Image]") { 9 | 10 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 11 | TinyImageFormat fmt = (TinyImageFormat) i; 12 | char const *name = TinyImageFormat_Name(fmt); 13 | bool shouldBe = strstr(name, "D16") != nullptr; 14 | shouldBe |= strstr(name, "D24") != nullptr; 15 | shouldBe |= strstr(name, "D32") != nullptr; 16 | shouldBe &= (strstr(name, "S8") == nullptr); 17 | 18 | if (TinyImageFormat_IsDepthOnly(fmt) != shouldBe) { 19 | LOGINFO("TinyImageFormat_IsDepthOnly failed %s", name); 20 | } 21 | CHECK(TinyImageFormat_IsDepthOnly(fmt) == shouldBe); 22 | } 23 | } 24 | 25 | TEST_CASE("Format Cracker IsStencilOnly (C)", "[Image]") { 26 | 27 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 28 | TinyImageFormat fmt = (TinyImageFormat) i; 29 | char const *name = TinyImageFormat_Name(fmt); 30 | bool shouldBe = (strstr(name, "S8") != nullptr) && 31 | (strstr(name, "D") == nullptr); 32 | 33 | if (TinyImageFormat_IsStencilOnly(fmt) != shouldBe) { 34 | LOGINFO("TinyImageFormat_IsStencilOnly failed %s", name); 35 | } 36 | CHECK(TinyImageFormat_IsStencilOnly(fmt) == shouldBe); 37 | } 38 | } 39 | 40 | TEST_CASE("Format Cracker IsDepthAndStencil (C)", "[Image]") { 41 | 42 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 43 | TinyImageFormat fmt = (TinyImageFormat) i; 44 | char const *name = TinyImageFormat_Name(fmt); 45 | bool shouldBe = strstr(name, "D16") != nullptr; 46 | shouldBe |= strstr(name, "D24") != nullptr; 47 | shouldBe |= strstr(name, "D32") != nullptr; 48 | shouldBe &= strstr(name, "S8") != nullptr; 49 | 50 | if (TinyImageFormat_IsDepthAndStencil(fmt) != shouldBe) { 51 | LOGINFO("TinyImageFormat_IsDepthAndStencil failed %s", name); 52 | } 53 | CHECK(TinyImageFormat_IsDepthAndStencil(fmt) == shouldBe); 54 | } 55 | } 56 | 57 | TEST_CASE("Format Cracker IsFloat (C)", "[Image]") { 58 | 59 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 60 | TinyImageFormat fmt = (TinyImageFormat) i; 61 | char const *name = TinyImageFormat_Name(fmt); 62 | bool shouldBe = strstr(name, "SFLOAT") != nullptr; 63 | shouldBe |= strstr(name, "UFLOAT") != nullptr; 64 | shouldBe |= strstr(name, "SBFLOAT") != nullptr; 65 | 66 | if (TinyImageFormat_IsFloat(fmt) != shouldBe) { 67 | LOGINFO("TinyImageFormat_IsFloat failed %s", name); 68 | } 69 | CHECK(TinyImageFormat_IsFloat(fmt) == shouldBe); 70 | } 71 | } 72 | 73 | TEST_CASE("Format Cracker IsNormalised (C)", "[Image]") { 74 | 75 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 76 | TinyImageFormat fmt = (TinyImageFormat) i; 77 | char const *name = TinyImageFormat_Name(fmt); 78 | bool shouldBeNormalised = strstr(name, "UNORM") != nullptr; 79 | shouldBeNormalised |= strstr(name, "SNORM") != nullptr; 80 | shouldBeNormalised |= strstr(name, "SRGB") != nullptr; 81 | 82 | if (TinyImageFormat_IsNormalised(fmt) != shouldBeNormalised) { 83 | LOGINFO("TinyImageFormat_IsNormalised failed %s", name); 84 | } 85 | CHECK(TinyImageFormat_IsNormalised(fmt) == shouldBeNormalised); 86 | } 87 | } 88 | 89 | TEST_CASE("Format Cracker IsSigned (C)", "[Image]") { 90 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 91 | TinyImageFormat fmt = (TinyImageFormat) i; 92 | char const *name = TinyImageFormat_Name(fmt); 93 | bool shouldBe = strstr(name, "SNORM") != nullptr; 94 | shouldBe |= strstr(name, "SSCALED") != nullptr; 95 | shouldBe |= strstr(name, "SINT") != nullptr; 96 | shouldBe |= strstr(name, "SFLOAT") != nullptr; 97 | shouldBe |= strstr(name, "SBFLOAT") != nullptr; 98 | 99 | if (TinyImageFormat_IsSigned(fmt) != shouldBe) { 100 | LOGINFO("TinyImageFormat_IsSigned failed %s", name); 101 | } 102 | CHECK(TinyImageFormat_IsSigned(fmt) == shouldBe); 103 | } 104 | } 105 | 106 | TEST_CASE("Format Cracker IsSRGB (C)", "[Image]") { 107 | 108 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 109 | TinyImageFormat fmt = (TinyImageFormat) i; 110 | char const *name = TinyImageFormat_Name(fmt); 111 | bool shouldBe = strstr(name, "SRGB") != nullptr; 112 | 113 | if (TinyImageFormat_IsSRGB(fmt) != shouldBe) { 114 | LOGINFO("TinyImageFormat_IsSRGB failed %s", name); 115 | } 116 | CHECK(TinyImageFormat_IsSRGB(fmt) == shouldBe); 117 | } 118 | } 119 | 120 | TEST_CASE("Format Cracker IsCompressed (C)", "[Image]") { 121 | 122 | for (uint32_t i = 0; i < TinyImageFormat_Count; ++i) { 123 | TinyImageFormat fmt = (TinyImageFormat) i; 124 | char const *name = TinyImageFormat_Name(fmt); 125 | bool shouldBe = false; 126 | shouldBe |= (strstr(name, "DXBC") != nullptr); 127 | shouldBe |= (strstr(name, "ETC") != nullptr); 128 | shouldBe |= (strstr(name, "PVRTC") != nullptr); 129 | shouldBe |= (strstr(name, "ASTC") != nullptr); 130 | 131 | if (TinyImageFormat_IsCompressed(fmt) != shouldBe) { 132 | LOGINFO("TinyImageFormat_IsCompressed failed %s", name); 133 | } 134 | CHECK(TinyImageFormat_IsCompressed(fmt) == shouldBe); 135 | } 136 | } 137 | 138 | TEST_CASE("Format Cracker Min (C)", "[Image]") { 139 | 140 | // random sample a few to check 141 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Red) == Approx(0)); 142 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Green) == Approx(0)); 143 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Blue) == Approx(0)); 144 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Alpha) == Approx(0)); 145 | 146 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Red) == Approx(-128)); 147 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Green) == Approx(-128)); 148 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Blue) == Approx(-128)); 149 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Alpha) == Approx(-128)); 150 | 151 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Red) == Approx(-FLT_MAX)); 152 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Green) == Approx(-FLT_MAX)); 153 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Blue) == Approx(-FLT_MAX)); 154 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Alpha) == Approx(-FLT_MAX)); 155 | 156 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8X8_UNORM, TinyImageFormat_LC_Red) == Approx(0.0)); 157 | REQUIRE(TinyImageFormat_Min(TinyImageFormat_R8G8B8A8_SNORM, TinyImageFormat_LC_Red) == Approx(-1.0)); 158 | 159 | 160 | } 161 | 162 | TEST_CASE("Format Cracker Max (C)", "[Image]") { 163 | 164 | // random sample a few to check 165 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Red) == Approx(255)); 166 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Green) == Approx(255)); 167 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Blue) == Approx(255)); 168 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_UINT, TinyImageFormat_LC_Alpha) == Approx(255)); 169 | 170 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Red) == Approx(127)); 171 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Green) == Approx(127)); 172 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Blue) == Approx(127)); 173 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R8G8B8A8_SINT, TinyImageFormat_LC_Alpha) == Approx(127)); 174 | 175 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Red) == Approx(FLT_MAX)); 176 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Green) == Approx(FLT_MAX)); 177 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Blue) == Approx(FLT_MAX)); 178 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_R32G32B32A32_SFLOAT, TinyImageFormat_LC_Alpha) == Approx(FLT_MAX)); 179 | 180 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_D32_SFLOAT_S8_UINT, TinyImageFormat_LC_Depth) == Approx(FLT_MAX)); 181 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_D32_SFLOAT_S8_UINT, TinyImageFormat_LC_Stencil) == Approx(255)); 182 | 183 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_D32_SFLOAT, TinyImageFormat_LC_Depth) == Approx(FLT_MAX)); 184 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_S8_UINT, TinyImageFormat_LC_Stencil) == Approx(255)); 185 | 186 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_B8G8R8X8_UNORM, TinyImageFormat_LC_Red) == Approx(1.0)); 187 | REQUIRE(TinyImageFormat_Max(TinyImageFormat_B8G8R8A8_SNORM, TinyImageFormat_LC_Red) == Approx(1.0)); 188 | 189 | } --------------------------------------------------------------------------------