├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── assets ├── 100kb_quota_color.bmp ├── 140kb_quota_color.bmp ├── 30kb_quota.bmp ├── 50kb_quota.bmp ├── 70kb_quota.bmp ├── 70kb_quota_color.bmp ├── original.bmp └── original_color.bmp ├── boat.512.bmp ├── boatcolor.512.bmp ├── example ├── inc │ ├── color_util.h │ ├── stb_image.h │ ├── stb_image_resize.h │ └── stb_image_write.h └── src │ ├── example_decode.c │ ├── example_decode_color.c │ ├── example_encode.c │ ├── example_encode_color.c │ └── stb_lib.c ├── house.bmp └── lib_icer ├── CMakeLists.txt ├── inc ├── crc.h └── icer.h └── src ├── crc32.c ├── icer_color.c ├── icer_compress.c ├── icer_config.c ├── icer_context_modeller.c ├── icer_decoding.c ├── icer_encoding.c ├── icer_init.c ├── icer_partition.c ├── icer_util.c └── icer_wavelet.c /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | cmake-build-debug 3 | cmake-build-release 4 | *.bmp 5 | ./*.bin -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.23) 2 | project(icer_compression C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | 6 | if(NOT CMAKE_BUILD_TYPE) 7 | set(CMAKE_BUILD_TYPE Release) 8 | endif() 9 | 10 | set(CMAKE_C_FLAGS "-Wall -Wextra") 11 | set(CMAKE_C_FLAGS_DEBUG "-g") 12 | set(CMAKE_C_FLAGS_RELEASE "-O2") 13 | 14 | include_directories(example/inc) 15 | include_directories(lib_icer/inc) 16 | add_subdirectory(lib_icer) 17 | 18 | add_executable(compress example/src/example_encode.c example/src/stb_lib.c example/inc/color_util.h) 19 | add_executable(decompress example/src/example_decode.c example/src/stb_lib.c) 20 | 21 | add_executable(compress_color example/src/example_encode_color.c example/src/stb_lib.c) 22 | add_executable(decompress_color example/src/example_decode_color.c example/src/stb_lib.c) 23 | 24 | target_link_libraries(compress PRIVATE m) 25 | target_link_libraries(compress PUBLIC icer) 26 | 27 | target_link_libraries(decompress PRIVATE m) 28 | target_link_libraries(decompress PUBLIC icer) 29 | 30 | target_link_libraries(compress_color PRIVATE m) 31 | target_link_libraries(compress_color PUBLIC icer) 32 | 33 | target_link_libraries(decompress_color PRIVATE m) 34 | target_link_libraries(decompress_color PUBLIC icer) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ICER Image Compression Algorithm 2 | 3 | The code in this repository implements the NASA ICER image compression algorithm as a C library. Said compression algorithm is a progressive, wavelet-based image compression algorithm designed to be resistant to data loss, making it suitable for use as the image compression algorithm when encoding images to be transmitted over unreliable delivery channels, such as those in satellite radio communications. 4 | 5 | This library was designed with memory-constrained embedded systems in mind, hence the language choice of C, but it should function just as well on normal machines. 6 | 7 | ## Features 8 | 9 | ### Core Capabilities 10 | 11 | - Full color image compression using YUV color space 12 | - Progressive image compression with configurable quality levels 13 | - Wavelet-based compression using various filter types 14 | - Error containment segments to limit data loss effects 15 | - Configurable output size targeting 16 | - Support for both lossless and lossy compression 17 | - Integer-only arithmetic operations for embedded systems 18 | - Memory-conscious implementation with no dynamic allocation 19 | 20 | ## Compression Examples 21 | 22 | Below are sample images of the compression algorithm producing output images of varying quality depending on the space allocated for it. 10 error containment segments are used, and 9 bitplanes were compressed 23 | 24 | ### Color Compression 25 | 26 | | ![original_color](https://github.com/TheRealOrange/icer_compression/blob/master/assets/original_color.bmp?raw=true) | ![140kb_quota_color](https://github.com/TheRealOrange/icer_compression/blob/master/assets/140kb_quota_color.bmp?raw=true) | 27 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 28 | | original color image (512x512, 768 kilobyte) | 140 kilobyte quota | 29 | | ![100kb_quota_color](https://github.com/TheRealOrange/icer_compression/blob/master/assets/100kb_quota_color.bmp?raw=true) | ![70kb_quota_color](https://github.com/TheRealOrange/icer_compression/blob/master/assets/70kb_quota_color.bmp?raw=true) | 30 | | 100 kilobyte quota | 70 kilobyte quota | 31 | 32 | ### Grayscale Compression 33 | 34 | | ![original](https://github.com/TheRealOrange/icer_compression/blob/master/assets/original.bmp?raw=true) | ![70kb_quota](https://github.com/TheRealOrange/icer_compression/blob/master/assets/70kb_quota.bmp?raw=true) | 35 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 36 | | original image (512x512, 262 kilobyte) | 70 kilobyte quota | 37 | | ![50kb_quota](https://github.com/TheRealOrange/icer_compression/blob/master/assets/50kb_quota.bmp?raw=true) | ![30kb_quota](https://github.com/TheRealOrange/icer_compression/blob/master/assets/30kb_quota.bmp?raw=true) | 38 | | 50 kilobyte quota | 30 kilobyte quota | 39 | 40 | The compression effectiveness depends greatly on the number of error containment segments chosen. 41 | 42 | ## What is this? 43 | 44 | This compression algorithm is based on [a document published by NASA](https://ipnpr.jpl.nasa.gov/progress_report/42-155/155J.pdf). This repository implements the algorithm as described by the paper, with additional support for color images. 45 | 46 | This algorithm is best described by the abstract of the document by NASA, which reads as follows: 47 | 48 | > ICER is a progressive, wavelet-based image data compressor designed to meet the specialized needs of deep-space applications while achieving state-of-the-art compression effectiveness. ICER can provide lossless and lossy compression, and incorporates an error-containment scheme to limit the effects of data loss during transmission. The Mars Exploration Rover (MER) mission will rely primarily on a software implementation of ICER for image compression. This article describes ICER and the methods it uses to meet its goals, and explains the rationale behind the choice of methods. Performance results also are presented. 49 | 50 | ## Credits 51 | 52 | This library uses code from: 53 | 54 | - CRC32 checksum library from the [SNIPPETS C Source Code Archive](https://github.com/vonj/snippets.org) 55 | - Image parsing libraries from [STB libraries](https://github.com/nothings/stb) 56 | 57 | ## Key Features 58 | 59 | There are a few key design considerations which were taking into account when writing this library, which are as follows: 60 | 61 | - Designed to only utilise integer arithmetic operations, as designed by NASA 62 | - Avoids dynamic memory allocation in the library, so memory can be better managed in memory-constrained embedded systems 63 | - Optimised for execution on embedded systems 64 | - Error containment features prevent data loss from affecting the quality of the whole image 65 | - Ability to set a output size target and stop compression once the quota is reached 66 | - Able to compress images losslessly (if the output quota permits) 67 | 68 | (again, recommended that you carefully read the NASA document to understand why and how these are significant) 69 | 70 | ## How do I use it? 71 | 72 | The project is designed as a C-library and as such is intended to be used as a part of a larger program, not as a standalone program. 73 | 74 | To include the library, select the appropriate flags for which parts of the library to compile: 75 | 76 | ```c 77 | #define USE_ENCODE_FUNCTIONS // Compile encode functions 78 | #define USE_DECODE_FUNCTIONS // Compile decode functions 79 | 80 | #define USE_UINT16_FUNCTIONS // Compile functions for uint16_t arrays 81 | #define USE_UINT8_FUNCTIONS // Compile functions for uint8_t arrays 82 | 83 | #include "icer.h" 84 | ``` 85 | 86 | Then, somewhere at the start, one must call 87 | 88 | ```c 89 | int icer_init(); 90 | ``` 91 | 92 | in order to initialise the constants and look up tables used in encode and decode functions. 93 | 94 | The main functions which are important for the usage of the library are (here we only show the `uint8_t` functions, but the `uint16_t` versions exists too): 95 | 96 | 1. Compression functions 97 | 98 | ```c 99 | // For grayscale/single channel images 100 | int icer_compress_image_uint8(uint8_t *image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt, uint8_t segments, icer_output_data_buf_typedef *output_data); 101 | 102 | // For colour images 103 | int icer_compress_image_yuv_uint8(uint8_t *y_channel, uint8_t *u_channel, uint8_t *v_channel, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt, uint8_t segments, icer_output_data_buf_typedef *output_data); 104 | ``` 105 | 106 | which is the function which enables the user to specify an image buffer of a specific width and height, as well as the filter coefficients to use, the number of time to perform wavelet decomposition, and the number of error containment segments to subdivide the image into 107 | 108 | 2. Decompression functions 109 | 110 | ```c 111 | // For grayscale/single channel images 112 | int icer_decompress_image_uint8(uint8_t *image, size_t *image_w, size_t *image_h, size_t image_bufsize, uint8_t *datastream, size_t data_length, uint8_t stages, enum icer_filter_types filt, uint8_t segments); 113 | 114 | // For colour images 115 | int icer_decompress_image_yuv_uint8(uint8_t *y_channel, uint8_t *u_channel, uint8_t *v_channel, size_t *image_w, size_t *image_h, size_t image_bufsize, const uint8_t *datastream, size_t data_length, uint8_t stages, enum icer_filter_types filt, uint8_t segments); 116 | ``` 117 | 118 | which is the function which enables the user to decompress a byte stream stored inside `datastream` and fill the image and the dimensions into the buffer specified. 119 | 120 | 3. Utility Functions 121 | 122 | ```c 123 | int icer_get_image_dimensions(const uint8_t *datastream, size_t data_length, size_t *image_w, size_t *image_h); 124 | ``` 125 | 126 | which can be used to get the dimensions of an encoded image (useful for knowing how much space to allocate for the image to decode it). 127 | 128 | ## How do I test it? 129 | 130 | To run the example code, simply build it and place the `boat.512.bmp` (and `boatcolor.512.bmp` for color encode) image as the same folder as the executable to generate the output. 131 | 132 | ## Advanced Configuration 133 | 134 | The library provides several compile-time configuration options through preprocessor definitions that allow you to optimize memory usage and customize functionality for your specific needs. 135 | 136 | ### Memory and Buffer Configuration 137 | 138 | ```c 139 | // Maximum number of error containment segments 140 | #ifndef ICER_MAX_SEGMENTS 141 | #define ICER_MAX_SEGMENTS 32 142 | #endif 143 | 144 | // Maximum number of wavelet decomposition stages 145 | #ifndef ICER_MAX_DECOMP_STAGES 146 | #define ICER_MAX_DECOMP_STAGES 6 147 | #endif 148 | 149 | // Maximum number of packets for 8-bit and 16-bit processing 150 | #ifndef ICER_MAX_PACKETS 151 | #define ICER_MAX_PACKETS 300 152 | #endif 153 | 154 | #ifndef ICER_MAX_PACKETS_16 155 | #define ICER_MAX_PACKETS_16 800 156 | #endif 157 | 158 | // Number of bitplanes to compress for 8-bit and 16-bit modes 159 | #ifndef ICER_BITPLANES_TO_COMPRESS_8 160 | #define ICER_BITPLANES_TO_COMPRESS_8 7 161 | #endif 162 | 163 | #ifndef ICER_BITPLANES_TO_COMPRESS_16 164 | #define ICER_BITPLANES_TO_COMPRESS_16 9 165 | #endif 166 | ``` 167 | 168 | ### Feature Selection Flags 169 | 170 | ```c 171 | // Select which bit depth functions to compile 172 | #if !defined(USE_UINT8_FUNCTIONS) && !defined(USE_UINT16_FUNCTIONS) 173 | #define USE_UINT8_FUNCTIONS 174 | #define USE_UINT16_FUNCTIONS 175 | #endif 176 | 177 | // Select whether to compile encode/decode functions 178 | #if !defined(USE_DECODE_FUNCTIONS) && !defined(USE_ENCODE_FUNCTIONS) 179 | #define USE_DECODE_FUNCTIONS 180 | #define USE_ENCODE_FUNCTIONS 181 | #endif 182 | ``` 183 | 184 | ### Advanced Memory Management 185 | 186 | ```c 187 | // Enable user-provided buffers for fine-grained memory control 188 | //#define USER_PROVIDED_BUFFERS 189 | ``` 190 | 191 | When `USER_PROVIDED_BUFFERS` is defined, you must allocate the following buffers: 192 | 193 | For 8-bit encoding: 194 | 195 | ```c 196 | icer_packet_context icer_packets[ICER_MAX_PACKETS]; 197 | icer_image_segment_typedef *icer_rearrange_segments_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][7][ICER_MAX_SEGMENTS + 1]; 198 | ``` 199 | 200 | For 8-bit decoding: 201 | 202 | ```c 203 | icer_image_segment_typedef *icer_reconstruct_data_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][7]; 204 | ``` 205 | 206 | For 16-bit encoding: 207 | 208 | ```c 209 | icer_packet_context icer_packets_16[ICER_MAX_PACKETS_16]; 210 | icer_image_segment_typedef *icer_rearrange_segments_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][15][ICER_MAX_SEGMENTS + 1]; 211 | ``` 212 | 213 | For 16-bit decoding: 214 | 215 | ```c 216 | icer_image_segment_typedef *icer_reconstruct_data_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][15]; 217 | ``` 218 | 219 | Common encoding buffer: 220 | 221 | ```c 222 | uint16_t icer_encode_circ_buf[ICER_CIRC_BUF_SIZE]; // ICER_CIRC_BUF_SIZE = 2048 223 | ``` 224 | 225 | ### Custom CRC32 Implementation 226 | 227 | ```c 228 | // Define custom CRC32 implementation (e.g., hardware acceleration) 229 | //#define CRC32BUF_FUNCTION(x, y) your_custom_crc32_function 230 | ``` 231 | 232 | When defined, you can provide your own CRC32 implementation with the following signature: 233 | 234 | ```c 235 | uint32_t crc32buf(char *buf, size_t len) 236 | ``` 237 | 238 | ## Note: Work in progress! 239 | 240 | The library now supports: 241 | 242 | - 8-bit and 16-bit image processing 243 | - Full color support using YUV color space 244 | - Multiple wavelet filter types 245 | - Configurable error containment segments 246 | - Progressive compression with size targeting 247 | 248 | Future improvements may include: 249 | 250 | - Additional color space support 251 | - Enhanced compression options for different color channels 252 | 253 | -------------------------------------------------------------------------------- /assets/100kb_quota_color.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/100kb_quota_color.bmp -------------------------------------------------------------------------------- /assets/140kb_quota_color.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/140kb_quota_color.bmp -------------------------------------------------------------------------------- /assets/30kb_quota.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/30kb_quota.bmp -------------------------------------------------------------------------------- /assets/50kb_quota.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/50kb_quota.bmp -------------------------------------------------------------------------------- /assets/70kb_quota.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/70kb_quota.bmp -------------------------------------------------------------------------------- /assets/70kb_quota_color.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/70kb_quota_color.bmp -------------------------------------------------------------------------------- /assets/original.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/original.bmp -------------------------------------------------------------------------------- /assets/original_color.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/assets/original_color.bmp -------------------------------------------------------------------------------- /boat.512.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/boat.512.bmp -------------------------------------------------------------------------------- /boatcolor.512.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/boatcolor.512.bmp -------------------------------------------------------------------------------- /example/inc/color_util.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 28/3/2023. 3 | // 4 | 5 | #ifndef ICER_COMPRESSION_COLOR_UTIL_H 6 | #define ICER_COMPRESSION_COLOR_UTIL_H 7 | 8 | #define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X) 9 | 10 | // taken from https://stackoverflow.com/questions/1737726/how-to-perform-rgb-yuv-conversion-in-c-c 11 | 12 | // RGB -> YUV 13 | #define RGB2Y(R, G, B) CLIP(( ( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16) 14 | #define RGB2U(R, G, B) CLIP(( ( -38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128) 15 | #define RGB2V(R, G, B) CLIP(( ( 112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128) 16 | 17 | // YUV -> RGB 18 | #define C(Y) ( (Y) - 16 ) 19 | #define D(U) ( (U) - 128 ) 20 | #define E(V) ( (V) - 128 ) 21 | 22 | #define YUV2R(Y, U, V) CLIP(( 298 * C(Y) + 409 * E(V) + 128) >> 8) 23 | #define YUV2G(Y, U, V) CLIP(( 298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8) 24 | #define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U) + 128) >> 8) 25 | 26 | // RGB -> YCbCr 27 | #define CRGB2Y(R, G, B) CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16) 28 | #define CRGB2Cb(R, G, B) CLIP((36962 * (B - CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16) ) >> 16) + 128) 29 | #define CRGB2Cr(R, G, B) CLIP((46727 * (R - CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16) ) >> 16) + 128) 30 | 31 | // YCbCr -> RGB 32 | #define CYCbCr2R(Y, Cb, Cr) CLIP( Y + ( 91881 * Cr >> 16 ) - 179 ) 33 | #define CYCbCr2G(Y, Cb, Cr) CLIP( Y - (( 22544 * Cb + 46793 * Cr ) >> 16) + 135) 34 | #define CYCbCr2B(Y, Cb, Cr) CLIP( Y + (116129 * Cb >> 16 ) - 226 ) 35 | 36 | #endif //ICER_COMPRESSION_COLOR_UTIL_H 37 | -------------------------------------------------------------------------------- /example/src/example_decode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "stb_image_resize.h" 8 | #include "stb_image_write.h" 9 | 10 | #define USE_DECODE_FUNCTIONS 11 | #define USE_UINT16_FUNCTIONS 12 | 13 | #include "icer.h" 14 | 15 | const char compressed_filename[] = "./compressed.bin"; 16 | const char filename[] = "./decompress.bmp"; 17 | 18 | int main() { 19 | const size_t out_w = 1000; 20 | const size_t out_h = 1000; 21 | const int stages = 4; 22 | const enum icer_filter_types filt = ICER_FILTER_A; 23 | const int segments = 6; 24 | 25 | uint16_t *decompress = malloc(out_w*out_h*2); 26 | uint8_t *display = malloc(out_w*out_h); 27 | 28 | int res = 0; 29 | clock_t begin, end; 30 | 31 | icer_init(); 32 | 33 | printf("test decompression code\n"); 34 | 35 | FILE *ptr2; 36 | uint8_t *buf = malloc(500); 37 | size_t buf_size = 500; 38 | size_t length = 0; 39 | 40 | ptr2 = fopen(compressed_filename,"rb"); 41 | while (fread(buf+length, sizeof *buf, 1, ptr2) == 1) { 42 | if (length >= buf_size-1) { 43 | buf_size += 500; 44 | buf = (uint8_t*)realloc(buf, buf_size); 45 | } 46 | length++; 47 | } 48 | fclose(ptr2); 49 | 50 | printf("decompress start\n"); 51 | 52 | size_t decomp_w, decomp_h; 53 | begin = clock(); 54 | res = icer_decompress_image_uint16(decompress, &decomp_w, &decomp_h, out_w*out_h, buf, length, stages, filt, segments); 55 | if (res != ICER_RESULT_OK) { 56 | printf("error: %d\n", res); 57 | return 0; 58 | } 59 | end = clock(); 60 | printf("decompress time taken: %lf\n", (float)(end-begin)/CLOCKS_PER_SEC); 61 | 62 | for (size_t i = 0;i < out_w*out_h;i++) { 63 | display[i] = icer_min_int(0xff, decompress[i]); 64 | } 65 | 66 | printf("saving decompressed image to: \"%s\"\n", filename); 67 | res = stbi_write_bmp(filename, decomp_w, decomp_h, 1, display); 68 | if (res == 0) { 69 | printf("save failed\nexiting...\n"); 70 | return 0; 71 | } 72 | 73 | free(decompress); 74 | free(display); 75 | free(buf); 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /example/src/example_decode_color.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "stb_image_resize.h" 8 | #include "stb_image_write.h" 9 | 10 | #define USE_DECODE_FUNCTIONS 11 | #define USE_UINT16_FUNCTIONS 12 | 13 | #include "icer.h" 14 | #include "color_util.h" 15 | 16 | const char compressed_filename[] = "./compressed.bin"; 17 | const char filename[] = "./decompress.bmp"; 18 | 19 | void yuv_to_rgb888_packed(uint16_t *y_channel, uint16_t *u_channel, uint16_t *v_channel, uint8_t *img, size_t image_w, size_t image_h, size_t rowstride) { 20 | int32_t y, u, v; 21 | uint8_t *pixel; 22 | 23 | uint16_t *input_y, *input_u, *input_v; 24 | for (size_t row = 0;row < image_h;row++) { 25 | pixel = img + 3 * rowstride * row; 26 | input_y = y_channel + rowstride * row; 27 | input_u = u_channel + rowstride * row; 28 | input_v = v_channel + rowstride * row; 29 | for (size_t col = 0;col < image_w;col++) { 30 | y = *input_y; 31 | u = *input_u; 32 | v = *input_v; 33 | 34 | pixel[0] = CYCbCr2R(y, u, v); 35 | pixel[1] = CYCbCr2G(y, u, v); 36 | pixel[2] = CYCbCr2B(y, u, v); 37 | 38 | pixel += 3; 39 | input_y++; input_u++; input_v++; 40 | } 41 | } 42 | } 43 | 44 | int main() { 45 | const size_t out_w = 1000; 46 | const size_t out_h = 1000; 47 | const int stages = 4; 48 | const enum icer_filter_types filt = ICER_FILTER_A; 49 | const int segments = 10; 50 | 51 | uint16_t *decompress[3]; 52 | uint8_t *display = malloc(out_w*out_h*3); 53 | 54 | for (int chan = 0;chan <= 2;chan++) { 55 | decompress[chan] = malloc(out_w*out_h*2); 56 | } 57 | 58 | int res = 0; 59 | clock_t begin, end; 60 | 61 | icer_init(); 62 | 63 | printf("test decompression code\n"); 64 | 65 | FILE *ptr2; 66 | uint8_t *buf = malloc(500); 67 | size_t buf_size = 500; 68 | size_t length = 0; 69 | 70 | ptr2 = fopen(compressed_filename,"rb"); 71 | while (fread(buf+length, sizeof *buf, 1, ptr2) == 1) { 72 | if (length >= buf_size-1) { 73 | buf_size += 500; 74 | buf = (uint8_t*)realloc(buf, buf_size); 75 | } 76 | length++; 77 | } 78 | fclose(ptr2); 79 | 80 | printf("decompress start\n"); 81 | 82 | size_t decomp_w, decomp_h; 83 | begin = clock(); 84 | res = icer_decompress_image_yuv_uint16(decompress[0], decompress[1], decompress[2], &decomp_w, &decomp_h, out_w*out_h, buf, length, stages, filt, segments); 85 | if (res != ICER_RESULT_OK) { 86 | printf("error: %d\n", res); 87 | return 0; 88 | } 89 | end = clock(); 90 | printf("decompress time taken: %lf\n", (float)(end-begin)/CLOCKS_PER_SEC); 91 | 92 | printf("converting to rgb\n"); 93 | yuv_to_rgb888_packed(decompress[0], decompress[1], decompress[2], display, decomp_w, decomp_h, decomp_w); 94 | 95 | printf("saving decompressed image to: \"%s\"\n", filename); 96 | res = stbi_write_bmp(filename, decomp_w, decomp_h, 3, display); 97 | if (res == 0) { 98 | printf("save failed\nexiting...\n"); 99 | return 0; 100 | } 101 | 102 | for (int chan = 0;chan <= 2;chan++) free(decompress[chan]); 103 | free(display); 104 | free(buf); 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /example/src/example_encode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "stb_image.h" 8 | #include "stb_image_resize.h" 9 | 10 | #define USE_ENCODE_FUNCTIONS 11 | #define USE_UINT16_FUNCTIONS 12 | 13 | #include "icer.h" 14 | 15 | const char compressed_filename[] = "./compressed.bin"; 16 | const char filename[] = "./boat.512.bmp"; 17 | 18 | int main() { 19 | const size_t out_w = 512; 20 | const size_t out_h = 512; 21 | const int stages = 4; 22 | const enum icer_filter_types filt = ICER_FILTER_A; 23 | const int segments = 6; 24 | 25 | const int datastream_size = 30000; 26 | 27 | int src_w, src_h, n; 28 | uint8_t *data; 29 | 30 | uint8_t *resized = malloc(out_w*out_h); 31 | uint16_t *compress = malloc(out_w*out_h*2); 32 | 33 | int res = 0; 34 | clock_t begin, end; 35 | 36 | icer_init(); 37 | 38 | printf("test compression code\n"); 39 | 40 | printf("loading image: \"%s\"\n", filename); 41 | data = stbi_load(filename, &src_w, &src_h, &n, 1); 42 | if (data == NULL) { 43 | printf("invalid image\nexiting...\n"); 44 | return 0; 45 | } 46 | 47 | printf("loaded image\nwidth : %5d\nheight : %5d\nchannels : %5d\n", src_w, src_h, n); 48 | 49 | printf("resizing image to width: %4llu, height: %4llu\n", out_w, out_h); 50 | res = stbir_resize_uint8(data, src_w, src_h, 0, 51 | resized, out_w, out_h, 0, 52 | 1); 53 | if (res == 0) { 54 | printf("resize failed\nexiting...\n"); 55 | return 0; 56 | } 57 | printf("resize complete\n"); 58 | 59 | printf("converting to int16\n"); 60 | for (size_t i = 0;i < out_h*out_w;i++) { 61 | compress[i] = resized[i]; 62 | } 63 | 64 | uint8_t *datastream = malloc(datastream_size*2+500); 65 | icer_output_data_buf_typedef output; 66 | icer_init_output_struct(&output, datastream, datastream_size*2, datastream_size); 67 | 68 | begin = clock(); 69 | icer_compress_image_uint16(compress, out_w, out_h, stages, filt, segments, &output); 70 | end = clock(); 71 | 72 | printf("compressed size %llu, time taken: %lf\n", output.size_used, (float)(end-begin)/CLOCKS_PER_SEC); 73 | 74 | FILE *ptr1; 75 | 76 | ptr1 = fopen(compressed_filename,"wb"); 77 | size_t written = fwrite(output.rearrange_start, sizeof(output.rearrange_start[0]), output.size_used, ptr1); 78 | printf("written: %llu\n", written); 79 | fflush(ptr1); 80 | fclose(ptr1); 81 | 82 | printf("output saved\n"); 83 | 84 | free(resized); 85 | free(compress); 86 | free(datastream); 87 | stbi_image_free(data); 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /example/src/example_encode_color.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "stb_image.h" 8 | #include "stb_image_resize.h" 9 | 10 | #define USE_ENCODE_FUNCTIONS 11 | #define USE_UINT16_FUNCTIONS 12 | 13 | #include "icer.h" 14 | #include "color_util.h" 15 | 16 | const char compressed_filename[] = "./compressed.bin"; 17 | const char filename[] = "./boatcolor.512.bmp"; 18 | 19 | void rgb888_packed_to_yuv(uint16_t *y_channel, uint16_t *u_channel, uint16_t *v_channel, uint8_t *img, size_t image_w, size_t image_h, size_t rowstride) { 20 | int32_t r, g, b; 21 | uint8_t *pixel; 22 | 23 | uint16_t *output_y, *output_u, *output_v; 24 | for (size_t row = 0;row < image_h;row++) { 25 | pixel = img + 3 * rowstride * row; 26 | output_y = y_channel + rowstride * row; 27 | output_u = u_channel + rowstride * row; 28 | output_v = v_channel + rowstride * row; 29 | for (size_t col = 0;col < image_w;col++) { 30 | r = pixel[0]; 31 | g = pixel[1]; 32 | b = pixel[2]; 33 | 34 | *output_y = CRGB2Y(r, g, b); 35 | *output_u = CRGB2Cb(r, g, b); 36 | *output_v = CRGB2Cr(r, g, b); 37 | pixel += 3; 38 | output_y++; output_u++; output_v++; 39 | } 40 | } 41 | } 42 | 43 | int main() { 44 | const size_t out_w = 512; 45 | const size_t out_h = 512; 46 | const int stages = 4; 47 | const enum icer_filter_types filt = ICER_FILTER_A; 48 | const int segments = 10; 49 | 50 | const int datastream_size = 100000; 51 | 52 | int src_w, src_h, n; 53 | uint8_t *data; 54 | 55 | uint8_t *resized = malloc(out_w*out_h*3); 56 | uint16_t *compress[3]; 57 | 58 | for (int chan = 0;chan <= 2;chan++) { 59 | compress[chan] = malloc(out_w*out_h*2); 60 | } 61 | 62 | int res = 0; 63 | clock_t begin, end; 64 | 65 | icer_init(); 66 | 67 | printf("test compression code\n"); 68 | 69 | printf("loading image: \"%s\"\n", filename); 70 | data = stbi_load(filename, &src_w, &src_h, &n, 3); 71 | if (data == NULL) { 72 | printf("invalid image\nexiting...\n"); 73 | return 0; 74 | } 75 | 76 | printf("loaded image\nwidth : %5d\nheight : %5d\nchannels : %5d\n", src_w, src_h, n); 77 | 78 | printf("resizing image to width: %4llu, height: %4llu\n", out_w, out_h); 79 | res = stbir_resize_uint8(data, src_w, src_h, 0, 80 | resized, out_w, out_h, 0, 81 | 3); 82 | if (res == 0) { 83 | printf("resize failed\nexiting...\n"); 84 | return 0; 85 | } 86 | printf("resize complete\n"); 87 | 88 | printf("converting to yuv\n"); 89 | rgb888_packed_to_yuv(compress[0], compress[1], compress[2], resized, out_w, out_h, out_w); 90 | 91 | uint8_t *datastream = malloc(datastream_size*2+500); 92 | icer_output_data_buf_typedef output; 93 | icer_init_output_struct(&output, datastream, datastream_size*2, datastream_size); 94 | 95 | begin = clock(); 96 | icer_compress_image_yuv_uint16(compress[0], compress[1], compress[2], out_w, out_h, stages, filt, segments, &output); 97 | end = clock(); 98 | 99 | printf("compressed size %llu, time taken: %lf\n", output.size_used, (float)(end-begin)/CLOCKS_PER_SEC); 100 | 101 | FILE *ptr1; 102 | 103 | ptr1 = fopen(compressed_filename,"wb"); 104 | size_t written = fwrite(output.rearrange_start, sizeof(output.rearrange_start[0]), output.size_used, ptr1); 105 | printf("written: %llu\n", written); 106 | fflush(ptr1); 107 | fclose(ptr1); 108 | 109 | printf("output saved\n"); 110 | 111 | free(resized); 112 | free(datastream); 113 | for (int chan = 0;chan <= 2;chan++) free(compress[chan]); 114 | stbi_image_free(data); 115 | 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /example/src/stb_lib.c: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #define STB_IMAGE_RESIZE_IMPLEMENTATION 3 | #define STB_IMAGE_WRITE_IMPLEMENTATION 4 | 5 | #include "stb_image.h" 6 | #include "stb_image_resize.h" 7 | #include "stb_image_write.h" -------------------------------------------------------------------------------- /house.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheRealOrange/icer_compression/1177e2f76860de0022f74a436ab0d65a45b4efb8/house.bmp -------------------------------------------------------------------------------- /lib_icer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.23) 2 | project(icer C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | 6 | include_directories(inc) 7 | 8 | add_library(icer inc/icer.h src/icer_wavelet.c inc/crc.h src/crc32.c src/icer_encoding.c src/icer_decoding.c src/icer_partition.c src/icer_util.c src/icer_context_modeller.c src/icer_init.c src/icer_config.c src/icer_compress.c src/icer_color.c) -------------------------------------------------------------------------------- /lib_icer/inc/crc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** CRC.H - header file for SNIPPETS CRC and checksum functions 3 | */ 4 | 5 | #ifndef CRC__H 6 | #define CRC__H 7 | 8 | #include /* For size_t */ 9 | #include /* For uint8_t, uint16_t, uint32_t */ 10 | #include /* For bool, true, false */ 11 | 12 | /* 13 | ** File: ARCCRC16.C 14 | */ 15 | 16 | void init_crc_table(void); 17 | uint16_t crc_calc(uint16_t crc, char *buf, unsigned nbytes); 18 | void do_file(char *fn); 19 | 20 | /* 21 | ** File: CRC-16.C 22 | */ 23 | 24 | uint16_t crc16(char *data_p, uint16_t length); 25 | 26 | /* 27 | ** File: CRC-16F.C 28 | */ 29 | 30 | uint16_t updcrc(uint16_t icrc, uint8_t *icp, size_t icnt); 31 | 32 | /* 33 | ** File: CRC_32.C 34 | */ 35 | 36 | #define UPDC32(octet,crc) (crc_32_tab[((crc)\ 37 | ^ ((uint8_t)octet)) & 0xff] ^ ((crc) >> 8)) 38 | 39 | uint32_t updateCRC32(unsigned char ch, uint32_t crc); 40 | bool crc32file(char *name, uint32_t *crc, long *charcnt); 41 | uint32_t crc32buf(char *buf, size_t len); 42 | 43 | /* 44 | ** File: CHECKSUM.C 45 | */ 46 | 47 | unsigned checksum(void *buffer, size_t len, unsigned int seed); 48 | 49 | /* 50 | ** File: CHECKEXE.C 51 | */ 52 | 53 | void checkexe(char *fname); 54 | 55 | 56 | 57 | #endif /* CRC__H */ 58 | -------------------------------------------------------------------------------- /lib_icer/inc/icer.h: -------------------------------------------------------------------------------- 1 | #ifndef ICER_COMPRESSION_ICER_H 2 | #define ICER_COMPRESSION_ICER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef _MSC_VER 10 | #include 11 | 12 | #define __builtin_popcount __popcnt 13 | #define __builtin_clz __clz 14 | 15 | uint32_t __inline __clz( uint32_t value ) { 16 | uint32_t leading_zero = 0; 17 | 18 | if ( _BitScanReverse( &leading_zero, value ) ) { 19 | return 31 - leading_zero; 20 | } else { 21 | // Same remarks as above 22 | return 32; 23 | } 24 | } 25 | #endif 26 | 27 | #define ICER_CIRC_BUF_SIZE 2048 28 | #define MAX_K 12 29 | #ifndef ICER_MAX_SEGMENTS 30 | #define ICER_MAX_SEGMENTS 32 31 | #endif 32 | #ifndef ICER_MAX_DECOMP_STAGES 33 | #define ICER_MAX_DECOMP_STAGES 6 34 | #endif 35 | #ifndef ICER_MAX_PACKETS 36 | #define ICER_MAX_PACKETS 300 37 | #endif 38 | #ifndef ICER_MAX_PACKETS_16 39 | #define ICER_MAX_PACKETS_16 800 40 | #endif 41 | #ifndef ICER_BITPLANES_TO_COMPRESS_8 42 | #define ICER_BITPLANES_TO_COMPRESS_8 7 43 | #endif 44 | #ifndef ICER_BITPLANES_TO_COMPRESS_16 45 | #define ICER_BITPLANES_TO_COMPRESS_16 9 46 | #endif 47 | 48 | //#define USER_PROVIDED_BUFFERS 49 | /* 50 | * if the user decides to specify explicitly where to place the buffers used during encoding and 51 | * decoding, the user should define the above line and allocate memory for the buffers listed below 52 | * 53 | * for encoding uint8 54 | * icer_packet_context icer_packets[ICER_MAX_PACKETS]; 55 | * icer_image_segment_typedef *icer_rearrange_segments_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][7][ICER_MAX_SEGMENTS + 1]; 56 | * 57 | * for decoding uint8 58 | * icer_image_segment_typedef *icer_reconstruct_data_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][7]; 59 | * 60 | * for encoding uint16 61 | * icer_packet_context icer_packets_16[ICER_MAX_PACKETS_16]; 62 | * icer_image_segment_typedef *icer_rearrange_segments_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][15][ICER_MAX_SEGMENTS + 1]; 63 | * 64 | * for decoding uint16 65 | * icer_image_segment_typedef *icer_reconstruct_data_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][15]; 66 | * 67 | * common to all encoding 68 | * uint16_t icer_encode_circ_buf[ICER_CIRC_BUF_SIZE]; 69 | */ 70 | 71 | //#define CRC32BUF_FUNCTION(x, y) xxx 72 | /* 73 | * 74 | * if the user decides to use a custom provided crc32 implementation (perhaps in hardware) the 75 | * user should define the above line with the function as specified below 76 | * 77 | * uint32_t crc32buf(char *buf, size_t len) 78 | * 79 | * override function with a custom defined function 80 | */ 81 | 82 | #if !defined(USE_UINT8_FUNCTIONS) && !defined(USE_UINT16_FUNCTIONS) 83 | #define USE_UINT8_FUNCTIONS 84 | #define USE_UINT16_FUNCTIONS 85 | #endif 86 | 87 | #if !defined(USE_DECODE_FUNCTIONS) && !defined(USE_ENCODE_FUNCTIONS) 88 | #define USE_DECODE_FUNCTIONS 89 | #define USE_ENCODE_FUNCTIONS 90 | #endif 91 | 92 | enum icer_status { 93 | ICER_RESULT_OK = 0, 94 | ICER_INTEGER_OVERFLOW = -1, 95 | ICER_OUTPUT_BUF_TOO_SMALL = -2, 96 | ICER_TOO_MANY_SEGMENTS = -3, 97 | ICER_TOO_MANY_STAGES = -4, 98 | ICER_BYTE_QUOTA_EXCEEDED = -5, 99 | ICER_BITPLANE_OUT_OF_RANGE = -6, 100 | ICER_DECODER_OUT_OF_DATA = -7, 101 | ICER_DECODED_INVALID_DATA = -8, 102 | ICER_PACKET_COUNT_EXCEEDED = -9, 103 | ICER_FATAL_ERROR = -10, 104 | ICER_INVALID_INPUT = -11, 105 | }; 106 | 107 | enum icer_filter_types { 108 | ICER_FILTER_A = 0, 109 | ICER_FILTER_B, 110 | ICER_FILTER_C, 111 | ICER_FILTER_D, 112 | ICER_FILTER_E, 113 | ICER_FILTER_F, 114 | ICER_FILTER_Q 115 | }; 116 | 117 | enum icer_filter_params { 118 | ICER_FILTER_COEF_ALPHA_N1 = 0, 119 | ICER_FILTER_COEF_ALPHA_0, 120 | ICER_FILTER_COEF_ALPHA_1, 121 | ICER_FILTER_COEF_BETA 122 | }; 123 | 124 | #define ICER_FILTER_DENOMINATOR 16 125 | 126 | typedef struct { 127 | uint16_t w; 128 | uint16_t h; 129 | uint16_t r; 130 | uint16_t c; 131 | uint16_t r_t; 132 | uint16_t h_t; 133 | uint16_t x_t; 134 | uint16_t c_t0; 135 | uint16_t y_t; 136 | uint16_t r_t0; 137 | uint16_t x_b; 138 | uint16_t c_b0; 139 | uint16_t y_b; 140 | uint16_t r_b0; 141 | uint16_t s; 142 | } partition_param_typdef; 143 | 144 | extern const int16_t icer_wavelet_filter_parameters[][4]; 145 | 146 | #define ICER_CONTEXT_MAX 16 147 | #define ICER_DEFAULT_CONTEXT_ZERO_COUNT 2 148 | #define ICER_DEFAULT_CONTEXT_TOTAL_COUNT 4 149 | #define ICER_CONTEXT_RESCALING_CAP 500 150 | 151 | enum icer_pixel_contexts { 152 | ICER_CONTEXT_0 = 0, 153 | ICER_CONTEXT_1, 154 | ICER_CONTEXT_2, 155 | ICER_CONTEXT_3, 156 | ICER_CONTEXT_4, 157 | ICER_CONTEXT_5, 158 | ICER_CONTEXT_6, 159 | ICER_CONTEXT_7, 160 | ICER_CONTEXT_8, 161 | ICER_CONTEXT_9, 162 | ICER_CONTEXT_10, 163 | ICER_CONTEXT_11, 164 | ICER_CONTEXT_12, 165 | ICER_CONTEXT_13, 166 | ICER_CONTEXT_14, 167 | ICER_CONTEXT_15, 168 | ICER_CONTEXT_16 = ICER_CONTEXT_MAX, 169 | }; 170 | 171 | extern const uint8_t icer_context_table_ll_lh_hl[3][3][5]; 172 | 173 | extern const uint8_t icer_context_table_hh[5][5]; 174 | 175 | extern const uint8_t icer_sign_context_table[5][5]; 176 | 177 | /* 1 is negative, 0 is positive */ 178 | extern const uint8_t icer_sign_prediction_table[5][5]; 179 | 180 | enum icer_pixel_categories { 181 | ICER_CATEGORY_0 = 0, 182 | ICER_CATEGORY_1, 183 | ICER_CATEGORY_2, 184 | ICER_CATEGORY_3 = 3 185 | }; 186 | 187 | #define ICER_SUBBAND_MAX 3 188 | enum icer_subband_types { 189 | ICER_SUBBAND_LL = 0, 190 | ICER_SUBBAND_HL, 191 | ICER_SUBBAND_LH, 192 | ICER_SUBBAND_HH = ICER_SUBBAND_MAX 193 | }; 194 | 195 | typedef struct { 196 | enum icer_subband_types subband_type; 197 | uint32_t zero_count[ICER_CONTEXT_MAX + 1]; 198 | uint32_t total_count[ICER_CONTEXT_MAX + 1]; 199 | } icer_context_model_typedef; 200 | 201 | #define ICER_ENCODER_BIN_MAX 16 202 | 203 | enum icer_encoder_bins { 204 | ICER_ENC_BIN_1 = 0, 205 | ICER_ENC_BIN_2, 206 | ICER_ENC_BIN_3, 207 | ICER_ENC_BIN_4, 208 | ICER_ENC_BIN_5, 209 | ICER_ENC_BIN_6, 210 | ICER_ENC_BIN_7, 211 | ICER_ENC_BIN_8, 212 | ICER_ENC_BIN_9, 213 | ICER_ENC_BIN_10, 214 | ICER_ENC_BIN_11, 215 | ICER_ENC_BIN_12, 216 | ICER_ENC_BIN_13, 217 | ICER_ENC_BIN_14, 218 | ICER_ENC_BIN_15, 219 | ICER_ENC_BIN_16, 220 | ICER_ENC_BIN_17 = ICER_ENCODER_BIN_MAX 221 | }; 222 | 223 | #define ICER_ENC_BUF_BITS_OFFSET 11 224 | #define ICER_ENC_BUF_SHIFTOUT_OFFSET 6 225 | #define ICER_ENC_BUF_DONE_MASK 0b0000010000000000 226 | #define ICER_ENC_BUF_DATA_MASK 0b0000001111111111 227 | #define ICER_ENC_BUF_INFO_MASK 0b1111100000000000 228 | 229 | extern const uint32_t icer_bin_probability_cutoffs[ICER_ENCODER_BIN_MAX+1]; 230 | 231 | #define ICER_BIN_PROBABILITY_DENOMINATOR 65536 232 | 233 | extern const int32_t icer_bin_coding_scheme[ICER_ENCODER_BIN_MAX+1]; 234 | 235 | typedef struct { 236 | uint8_t input_code_bits; 237 | uint8_t output_code_bits; 238 | uint8_t output_code; 239 | } icer_custom_code_typedef; 240 | 241 | typedef struct { 242 | uint8_t flush_bit; 243 | uint8_t flush_bit_numbers; 244 | } icer_custom_flush_typedef; 245 | 246 | #define CUSTOM_CODING_MAX_LOOKUP 32 247 | #ifdef USE_ENCODE_FUNCTIONS 248 | extern icer_custom_code_typedef icer_custom_coding_scheme[ICER_ENCODER_BIN_MAX + 1][CUSTOM_CODING_MAX_LOOKUP]; 249 | #endif 250 | 251 | #ifdef USE_DECODE_FUNCTIONS 252 | extern icer_custom_code_typedef icer_custom_decode_scheme[ICER_ENCODER_BIN_MAX + 1][CUSTOM_CODING_MAX_LOOKUP]; 253 | #endif 254 | 255 | #define CUSTOM_CODE_FLUSH_MAX_LOOKUP 8 256 | #define MAX_NUM_BITS_BEFORE_FLUSH 5 257 | extern icer_custom_flush_typedef icer_custom_code_flush_bits[ICER_ENCODER_BIN_MAX + 1][CUSTOM_CODE_FLUSH_MAX_LOOKUP + 1][MAX_NUM_BITS_BEFORE_FLUSH + 1]; 258 | 259 | typedef struct { 260 | uint16_t m; 261 | uint16_t l; 262 | uint16_t i; 263 | } icer_golomb_code_typedef; 264 | 265 | extern icer_golomb_code_typedef icer_golomb_coders[ICER_ENCODER_BIN_MAX + 1]; 266 | 267 | typedef struct { 268 | uint8_t decomp_level; 269 | uint8_t subband_type; 270 | uint8_t ll_mean_val; 271 | uint8_t lsb; 272 | uint64_t priority; 273 | size_t image_w; 274 | size_t image_h; 275 | uint8_t channel; 276 | } icer_packet_context; 277 | 278 | #ifdef USE_UINT8_FUNCTIONS 279 | extern icer_packet_context icer_packets[ICER_MAX_PACKETS]; 280 | #endif 281 | 282 | #ifdef USE_UINT16_FUNCTIONS 283 | extern icer_packet_context icer_packets_16[ICER_MAX_PACKETS_16]; 284 | #endif 285 | 286 | #define ICER_PACKET_PREAMBLE 0x605B 287 | #define ICER_SEGMENT_LSB_MASK 0x0f 288 | #define ICER_SEGMENT_CHANNEL_MASK 0xf0 289 | #define ICER_GET_LSB_MACRO(x) ((x) & ICER_SEGMENT_LSB_MASK) 290 | #define ICER_GET_CHANNEL_MACRO(x) (((x) & ICER_SEGMENT_CHANNEL_MASK) >> 4) 291 | #define ICER_SET_CHANNEL_MACRO(x) ((x) << 4) 292 | 293 | typedef struct { 294 | uint16_t preamble; 295 | uint16_t ll_mean_val; 296 | uint8_t decomp_level; 297 | uint8_t subband_type; 298 | uint8_t segment_number; 299 | uint8_t lsb_chan; 300 | uint32_t image_w; 301 | uint32_t image_h; 302 | uint32_t data_length; // store data length in bits for the decoder 303 | uint32_t data_crc32; 304 | uint32_t crc32; 305 | } icer_image_segment_typedef; 306 | 307 | typedef struct { 308 | size_t size_used; 309 | size_t size_allocated; 310 | uint8_t *data_start; 311 | uint8_t *rearrange_start; 312 | } icer_output_data_buf_typedef; 313 | 314 | typedef struct { 315 | size_t buffer_length; 316 | size_t head; 317 | size_t tail; 318 | size_t used; 319 | size_t output_ind; 320 | size_t max_output_length; 321 | uint16_t *encode_buffer; 322 | uint8_t output_bit_offset; 323 | uint8_t *output_buffer; 324 | int16_t bin_current_buf[ICER_ENCODER_BIN_MAX+1]; 325 | int16_t bin_current_buf_bits[ICER_ENCODER_BIN_MAX+1]; 326 | } icer_encoder_context_typedef; 327 | 328 | #define ICER_DECODER_BIT_BIN_MAX 30 329 | 330 | typedef struct { 331 | size_t decoded_words; 332 | size_t encode_ind; 333 | uint8_t encode_bit_offset; 334 | uint32_t encoded_bits_total; 335 | uint32_t decoded_bits_total; 336 | uint8_t *encoded_words; 337 | uint32_t bin_buf[ICER_ENCODER_BIN_MAX+1][ICER_DECODER_BIT_BIN_MAX]; 338 | int32_t bin_bits[ICER_ENCODER_BIN_MAX+1]; 339 | size_t bin_decode_index[ICER_ENCODER_BIN_MAX+1]; 340 | } icer_decoder_context_typedef; 341 | 342 | #define ICER_CHANNEL_MIN 0 343 | #define ICER_CHANNEL_MAX 2 344 | enum icer_color_channels { 345 | ICER_CHANNEL_Y = ICER_CHANNEL_MIN, 346 | ICER_CHANNEL_U = 1, 347 | ICER_CHANNEL_V = ICER_CHANNEL_MAX 348 | }; 349 | 350 | #ifdef USE_UINT8_FUNCTIONS 351 | #ifdef USE_DECODE_FUNCTIONS 352 | extern icer_image_segment_typedef *icer_reconstruct_data_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][7]; 353 | #endif 354 | 355 | #ifdef USE_ENCODE_FUNCTIONS 356 | extern icer_image_segment_typedef *icer_rearrange_segments_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][7][ICER_MAX_SEGMENTS + 1]; 357 | #endif 358 | #endif 359 | 360 | #ifdef USE_UINT16_FUNCTIONS 361 | #ifdef USE_DECODE_FUNCTIONS 362 | extern icer_image_segment_typedef *icer_reconstruct_data_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][15]; 363 | #endif 364 | 365 | #ifdef USE_ENCODE_FUNCTIONS 366 | extern icer_image_segment_typedef *icer_rearrange_segments_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][15][ICER_MAX_SEGMENTS + 1]; 367 | #endif 368 | #endif 369 | 370 | int icer_init(void); 371 | 372 | #ifdef USE_DECODE_FUNCTIONS 373 | void icer_init_decodescheme(void); 374 | int icer_get_image_dimensions(const uint8_t *datastream, size_t data_length, size_t *image_w, size_t *image_h); 375 | #endif 376 | 377 | #ifdef USE_ENCODE_FUNCTIONS 378 | void icer_init_codingscheme(void); 379 | #endif 380 | 381 | void icer_init_flushbits(void); 382 | void icer_init_golombcoder(void); 383 | 384 | #ifdef USE_UINT8_FUNCTIONS 385 | #ifdef USE_ENCODE_FUNCTIONS 386 | int icer_compress_image_uint8(uint8_t *image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt, 387 | uint8_t segments, icer_output_data_buf_typedef *output_data); 388 | int icer_compress_image_yuv_uint8(uint8_t *y_channel, uint8_t *u_channel, uint8_t *v_channel, size_t image_w, 389 | size_t image_h, uint8_t stages, enum icer_filter_types filt, 390 | uint8_t segments, icer_output_data_buf_typedef *const output_data); 391 | 392 | int icer_wavelet_transform_stages_uint8(uint8_t *image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt); 393 | 394 | int icer_wavelet_transform_2d_uint8(uint8_t *image, size_t image_w, size_t image_h, size_t rowstride, enum icer_filter_types filt); 395 | int icer_wavelet_transform_1d_uint8(uint8_t *data, size_t N, size_t stride, enum icer_filter_types filt); 396 | 397 | int icer_compress_partition_uint8(const uint8_t *data, partition_param_typdef *params, size_t rowstride, 398 | icer_packet_context *pkt_context, icer_output_data_buf_typedef *output_data, 399 | icer_image_segment_typedef *segments_encoded[]); 400 | int icer_compress_bitplane_uint8(const uint8_t *data, size_t plane_w, size_t plane_h, size_t rowstride, 401 | icer_context_model_typedef *context_model, 402 | icer_encoder_context_typedef *encoder_context, 403 | const icer_packet_context *pkt_context); 404 | #endif 405 | 406 | #ifdef USE_DECODE_FUNCTIONS 407 | int icer_decompress_image_uint8(uint8_t *image, size_t *image_w, size_t *image_h, size_t image_bufsize, const uint8_t *datastream, 408 | size_t data_length, uint8_t stages, enum icer_filter_types filt, uint8_t segments); 409 | int icer_decompress_image_yuv_uint8(uint8_t *y_channel, uint8_t *u_channel, uint8_t *v_channel, size_t *image_w, 410 | size_t *image_h, size_t image_bufsize, const uint8_t *datastream, 411 | size_t data_length, uint8_t stages, enum icer_filter_types filt, 412 | uint8_t segments); 413 | 414 | int icer_inverse_wavelet_transform_stages_uint8(uint8_t *image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt); 415 | 416 | int icer_inverse_wavelet_transform_2d_uint8(uint8_t *image, size_t image_w, size_t image_h, size_t rowstride, enum icer_filter_types filt); 417 | int icer_inverse_wavelet_transform_1d_uint8(uint8_t *data, size_t N, size_t stride, enum icer_filter_types filt); 418 | 419 | int icer_decompress_partition_uint8(uint8_t *const data, const partition_param_typdef *params, size_t rowstride, 420 | icer_image_segment_typedef *seg[][7]); 421 | int icer_decompress_bitplane_uint8(uint8_t *const data, size_t plane_w, size_t plane_h, size_t rowstride, 422 | icer_context_model_typedef *context_model, 423 | icer_decoder_context_typedef *decoder_context, 424 | const icer_packet_context *pkt_context); 425 | void icer_remove_negative_uint8(uint8_t * const image, size_t image_w, size_t image_h); 426 | #endif 427 | 428 | void icer_reverse_uint8(uint8_t *data, size_t start, size_t end, size_t stride); 429 | 430 | void icer_interleave_uint8(uint8_t *data, size_t len, size_t stride); 431 | void icer_deinterleave_uint8(uint8_t *data, size_t len, size_t stride); 432 | 433 | 434 | void icer_to_sign_magnitude_int8(uint8_t *data, size_t len); 435 | void icer_from_sign_magnitude_int8(uint8_t *data, size_t len); 436 | #endif 437 | 438 | #ifdef USE_UINT16_FUNCTIONS 439 | #ifdef USE_ENCODE_FUNCTIONS 440 | int icer_compress_image_uint16(uint16_t *image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt, 441 | uint8_t segments, icer_output_data_buf_typedef *output_data); 442 | int icer_compress_image_yuv_uint16(uint16_t *y_channel, uint16_t *u_channel, uint16_t *v_channel, size_t image_w, 443 | size_t image_h, uint8_t stages, enum icer_filter_types filt, 444 | uint8_t segments, icer_output_data_buf_typedef *output_data); 445 | 446 | int icer_wavelet_transform_stages_uint16(uint16_t *image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt); 447 | 448 | int icer_wavelet_transform_2d_uint16(uint16_t *image, size_t image_w, size_t image_h, size_t rowstride, enum icer_filter_types filt); 449 | int icer_wavelet_transform_1d_uint16(uint16_t *data, size_t N, size_t stride, enum icer_filter_types filt); 450 | 451 | int icer_compress_partition_uint16(const uint16_t *data, const partition_param_typdef *params, size_t rowstride, 452 | const icer_packet_context *pkt_context, icer_output_data_buf_typedef *output_data, 453 | icer_image_segment_typedef *segments_encoded[]); 454 | int icer_compress_bitplane_uint16(const uint16_t *data, size_t plane_w, size_t plane_h, size_t rowstride, 455 | icer_context_model_typedef *context_model, 456 | icer_encoder_context_typedef *encoder_context, 457 | const icer_packet_context *pkt_context); 458 | #endif 459 | 460 | #ifdef USE_DECODE_FUNCTIONS 461 | int icer_decompress_image_uint16(uint16_t *image, size_t *image_w, size_t *image_h, size_t image_bufsize, const uint8_t *datastream, 462 | size_t data_length, uint8_t stages, enum icer_filter_types filt, uint8_t segments); 463 | int icer_decompress_image_yuv_uint16(uint16_t * y_channel, uint16_t * u_channel, uint16_t * v_channel, size_t *image_w, 464 | size_t *image_h, size_t image_bufsize, const uint8_t *datastream, 465 | size_t data_length, uint8_t stages, enum icer_filter_types filt, 466 | uint8_t segments); 467 | 468 | int icer_inverse_wavelet_transform_stages_uint16(uint16_t *image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt); 469 | 470 | int icer_inverse_wavelet_transform_2d_uint16(uint16_t *image, size_t image_w, size_t image_h, size_t rowstride, enum icer_filter_types filt); 471 | int icer_inverse_wavelet_transform_1d_uint16(uint16_t *data, size_t N, size_t stride, enum icer_filter_types filt); 472 | 473 | int icer_decompress_partition_uint16(uint16_t *data, const partition_param_typdef *params, size_t rowstride, 474 | icer_image_segment_typedef *seg[][15]); 475 | int icer_decompress_bitplane_uint16(uint16_t *const data, size_t plane_w, size_t plane_h, size_t rowstride, 476 | icer_context_model_typedef *context_model, 477 | icer_decoder_context_typedef *decoder_context, 478 | const icer_packet_context *pkt_context); 479 | void icer_remove_negative_uint16(uint16_t * const image, size_t image_w, size_t image_h); 480 | #endif 481 | 482 | void icer_reverse_uint16(uint16_t *data, size_t start, size_t end, size_t stride); 483 | 484 | void icer_interleave_uint16(uint16_t *data, size_t len, size_t stride); 485 | void icer_deinterleave_uint16(uint16_t *data, size_t len, size_t stride); 486 | 487 | void icer_to_sign_magnitude_int16(uint16_t *data, size_t len); 488 | void icer_from_sign_magnitude_int16(uint16_t *data, size_t len); 489 | #endif 490 | 491 | #ifdef USE_ENCODE_FUNCTIONS 492 | /* inside encoding.c */ 493 | extern uint16_t icer_encode_circ_buf[ICER_CIRC_BUF_SIZE]; 494 | 495 | void icer_init_entropy_coder_context(icer_encoder_context_typedef *encoder_context, uint16_t *encode_buffer, size_t buffer_length, uint8_t *encoder_out, size_t enc_out_max); 496 | int icer_encode_bit(icer_encoder_context_typedef *encoder_context, uint8_t bit, uint32_t zero_cnt, uint32_t total_cnt); 497 | int icer_popbuf_while_avail(icer_encoder_context_typedef *encoder_context); 498 | int icer_flush_encode(icer_encoder_context_typedef *encoder_context); 499 | int icer_allocate_data_packet(icer_image_segment_typedef **pkt, icer_output_data_buf_typedef * const output_data, uint8_t segment_num, const icer_packet_context *context); 500 | #endif 501 | 502 | #ifdef USE_DECODE_FUNCTIONS 503 | /* inside decoding.c */ 504 | void icer_init_entropy_decoder_context(icer_decoder_context_typedef *decoder_context, uint8_t *encoded_words, size_t encoded_bits); 505 | void icer_push_bin_bits(icer_decoder_context_typedef *decoder_context, uint8_t bin, uint16_t bits, uint16_t num_bits); 506 | int icer_get_bit_from_codeword(icer_decoder_context_typedef *decoder_context, uint8_t bits); 507 | int icer_get_bits_from_codeword(icer_decoder_context_typedef *decoder_context, uint8_t bits); 508 | int icer_pop_bits_from_codeword(icer_decoder_context_typedef *decoder_context, uint8_t bits); 509 | int icer_decode_bit(icer_decoder_context_typedef *decoder_context, uint8_t *bit, uint32_t zero_cnt, uint32_t total_cnt); 510 | #endif 511 | 512 | int icer_find_packet_in_bytestream(icer_image_segment_typedef **seg, const uint8_t *datastream, size_t data_length, size_t * offset); 513 | 514 | uint8_t icer_find_k(size_t len); 515 | size_t icer_get_dim_n_low_stages(size_t dim, uint8_t stages); 516 | size_t icer_get_dim_n_high_stages(size_t dim, uint8_t stages); 517 | 518 | void icer_init_context_model_vals(icer_context_model_typedef* context_model, enum icer_subband_types subband_type); 519 | int icer_generate_partition_parameters(partition_param_typdef *params, size_t ll_w, size_t ll_h, uint16_t segments); 520 | 521 | uint32_t icer_calculate_packet_crc32(icer_image_segment_typedef *pkt); 522 | uint32_t icer_calculate_segment_crc32(icer_image_segment_typedef *pkt); 523 | 524 | int icer_init_output_struct(icer_output_data_buf_typedef *out, uint8_t *data, size_t buf_len, size_t byte_quota); 525 | int icer_compute_bin(uint32_t zero_cnt, uint32_t total_cnt); 526 | 527 | static inline unsigned icer_pow_uint(unsigned base, unsigned exp); 528 | 529 | static inline int16_t icer_floor_div_int16(int16_t a, int16_t b); 530 | static inline int32_t icer_floor_div_int32(int32_t a, int32_t b); 531 | static inline size_t icer_floor_div_size_t(size_t a, size_t b); 532 | static inline int16_t icer_ceil_div_int16(int16_t a, int16_t b); 533 | static inline uint32_t icer_ceil_div_uint32(uint32_t a, uint32_t b); 534 | static inline size_t icer_ceil_div_size_t(size_t a, size_t b); 535 | 536 | static inline int icer_max_int(int a, int b); 537 | static inline unsigned icer_max_uint(unsigned a, unsigned b); 538 | 539 | static inline int icer_min_int(int a, int b); 540 | 541 | static inline void icer_reverse_bits(uint16_t *bits, uint8_t num); 542 | 543 | extern size_t icer_slice_lengths[MAX_K]; 544 | 545 | static inline unsigned icer_pow_uint(unsigned base, unsigned exp) { 546 | unsigned res = 1; 547 | while (exp) { 548 | if (exp & 1) res *= base; 549 | exp /= 2; 550 | base *= base; 551 | } 552 | return res; 553 | } 554 | 555 | /* optimizes into single division, as per https://stackoverflow.com/questions/46265403/fast-floor-of-a-signed-integer-division-in-c-c */ 556 | static inline int16_t icer_floor_div_int16(int16_t a, int16_t b) { 557 | int16_t d = a / b; 558 | int16_t r = a % b; 559 | return r ? (d - ((a < 0) ^ (b < 0))) : d; 560 | } 561 | 562 | static inline int32_t icer_floor_div_int32(int32_t a, int32_t b) { 563 | int32_t d = a / b; 564 | int32_t r = a % b; 565 | return r ? (d - ((a < 0) ^ (b < 0))) : d; 566 | } 567 | 568 | static inline size_t icer_floor_div_size_t(size_t a, size_t b) { 569 | return a / b; 570 | } 571 | 572 | static inline int16_t icer_ceil_div_int16(int16_t a, int16_t b) { 573 | int16_t d = a / b; 574 | int16_t r = a % b; 575 | return r ? d + 1 : d; 576 | } 577 | 578 | static inline uint32_t icer_ceil_div_uint32(uint32_t a, uint32_t b) { 579 | uint32_t d = a / b; 580 | uint32_t r = a % b; 581 | return r ? d + 1 : d; 582 | } 583 | 584 | static inline size_t icer_ceil_div_size_t(size_t a, size_t b) { 585 | size_t d = a / b; 586 | size_t r = a % b; 587 | return r ? d + 1 : d; 588 | } 589 | 590 | static inline int icer_max_int(int a, int b) { 591 | return (a > b) ? a : b; 592 | } 593 | 594 | static inline unsigned icer_max_uint(unsigned a, unsigned b) { 595 | return (a > b) ? a : b; 596 | } 597 | 598 | static inline int icer_min_int(int a, int b) { 599 | return (a < b) ? a : b; 600 | } 601 | 602 | static inline void icer_reverse_bits(uint16_t *bits, uint8_t num) { 603 | uint16_t reversed = 0; 604 | for (int b = 0; b < num;b++) { 605 | reversed <<= 1; 606 | reversed |= (*bits) & 1; 607 | (*bits) >>= 1; 608 | } 609 | (*bits) = reversed; 610 | } 611 | 612 | 613 | #endif //ICER_COMPRESSION_ICER_H 614 | -------------------------------------------------------------------------------- /lib_icer/src/crc32.c: -------------------------------------------------------------------------------- 1 | /* Crc - 32 BIT ANSI X3.66 CRC checksum files */ 2 | 3 | #include 4 | #include "../inc/crc.h" 5 | 6 | #ifdef __TURBOC__ 7 | #pragma warn -cln 8 | #endif 9 | 10 | /**********************************************************************\ 11 | |* Demonstration program to compute the 32-bit CRC used as the frame *| 12 | |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| 13 | |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| 14 | |* protocol). The 32-bit FCS was added via the Federal Register, *| 15 | |* 1 June 1982, p.23798. I presume but don't know for certain that *| 16 | |* this polynomial is or will be included in CCITT V.41, which *| 17 | |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| 18 | |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| 19 | |* errors by a factor of 10^-5 over 16-bit FCS. *| 20 | \**********************************************************************/ 21 | 22 | /* Need an unsigned type capable of holding 32 bits; */ 23 | 24 | typedef uint32_t UNS_32_BITS; 25 | 26 | /* Copyright (C) 1986 Gary S. Brown. You may use this program, or 27 | code or tables extracted from it, as desired without restriction.*/ 28 | 29 | /* First, the polynomial itself and its table of feedback terms. The */ 30 | /* polynomial is */ 31 | /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ 32 | /* Note that we take it "backwards" and put the highest-order term in */ 33 | /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ 34 | /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ 35 | /* the MSB being 1. */ 36 | 37 | /* Note that the usual hardware shift register implementation, which */ 38 | /* is what we're using (we're merely optimizing it by doing eight-bit */ 39 | /* chunks at a time) shifts bits into the lowest-order term. In our */ 40 | /* implementation, that means shifting towards the right. Why do we */ 41 | /* do it this way? Because the calculated CRC must be transmitted in */ 42 | /* order from highest-order term to lowest-order term. UARTs transmit */ 43 | /* characters in order from LSB to MSB. By storing the CRC this way, */ 44 | /* we hand it to the UART in the order low-byte to high-byte; the UART */ 45 | /* sends each low-bit to hight-bit; and the result is transmission bit */ 46 | /* by bit from highest- to lowest-order term without requiring any bit */ 47 | /* shuffling on our part. Reception works similarly. */ 48 | 49 | /* The feedback terms table consists of 256, 32-bit entries. Notes: */ 50 | /* */ 51 | /* 1. The table can be generated at runtime if desired; code to do so */ 52 | /* is shown later. It might not be obvious, but the feedback */ 53 | /* terms simply represent the results of eight shift/xor opera- */ 54 | /* tions for all combinations of data and CRC register values. */ 55 | /* */ 56 | /* 2. The CRC accumulation logic is the same for all CRC polynomials, */ 57 | /* be they sixteen or thirty-two bits wide. You simply choose the */ 58 | /* appropriate table. Alternatively, because the table can be */ 59 | /* generated at runtime, you can start by generating the table for */ 60 | /* the polynomial in question and use exactly the same "updcrc", */ 61 | /* if your application needn't simultaneously handle two CRC */ 62 | /* polynomials. (Note, however, that XMODEM is strange.) */ 63 | /* */ 64 | /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ 65 | /* of course, 32-bit entries work OK if the high 16 bits are zero. */ 66 | /* */ 67 | /* 4. The values must be right-shifted by eight bits by the "updcrc" */ 68 | /* logic; the shift must be unsigned (bring in zeroes). On some */ 69 | /* hardware you could probably optimize the shift in assembler by */ 70 | /* using byte-swap instructions. */ 71 | 72 | static UNS_32_BITS crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 73 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 74 | 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 75 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 76 | 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 77 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 78 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 79 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 80 | 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 81 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 82 | 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 83 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 84 | 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 85 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 86 | 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 87 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 88 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 89 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 90 | 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 91 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 92 | 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 93 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 94 | 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 95 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 96 | 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 97 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 98 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 99 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 100 | 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 101 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 102 | 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 103 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 104 | 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 105 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 106 | 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 107 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 108 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 109 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 110 | 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 111 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 112 | 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 113 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 114 | 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 115 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 116 | }; 117 | 118 | uint32_t updateCRC32(unsigned char ch, uint32_t crc) 119 | { 120 | return UPDC32(ch, crc); 121 | } 122 | 123 | bool crc32file(char *name, uint32_t *crc, long *charcnt) 124 | { 125 | register FILE *fin; 126 | register uint32_t oldcrc32; 127 | register int c; 128 | 129 | oldcrc32 = 0xFFFFFFFF; *charcnt = 0; 130 | #ifdef MSDOS 131 | if ((fin=fopen(name, "rb"))==NULL) 132 | #else 133 | if ((fin=fopen(name, "r"))==NULL) 134 | #endif 135 | { 136 | perror(name); 137 | return false; 138 | } 139 | while ((c=getc(fin))!=EOF) 140 | { 141 | ++*charcnt; 142 | oldcrc32 = UPDC32(c, oldcrc32); 143 | } 144 | 145 | if (ferror(fin)) 146 | { 147 | perror(name); 148 | *charcnt = -1; 149 | } 150 | fclose(fin); 151 | 152 | *crc = oldcrc32 = ~oldcrc32; 153 | 154 | return true; 155 | } 156 | 157 | uint32_t crc32buf(char *buf, size_t len) 158 | { 159 | register uint32_t oldcrc32; 160 | 161 | oldcrc32 = 0xFFFFFFFF; 162 | 163 | for ( ; len; --len, ++buf) 164 | { 165 | oldcrc32 = UPDC32(*buf, oldcrc32); 166 | } 167 | 168 | return ~oldcrc32; 169 | } 170 | 171 | #ifdef TEST 172 | 173 | int main(int argc, char *argv[]) 174 | { 175 | uint32_t crc = 0; 176 | long charcnt = 0; 177 | bool errors = false; 178 | 179 | for (int i = 1; i < argc; ++ i) 180 | { 181 | errors = errors || crc32file(argv[i], &crc, &charcnt); 182 | printf("%08X %7ld %s\n", crc, charcnt, argv[i]); 183 | } 184 | return !errors; 185 | } 186 | 187 | #endif /* TEST */ 188 | -------------------------------------------------------------------------------- /lib_icer/src/icer_compress.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 22/3/2023. 3 | // 4 | 5 | #include "icer.h" 6 | #include 7 | 8 | static inline int comp_packet(const void *a, const void *b) { 9 | if (((icer_packet_context *)a)->priority == ((icer_packet_context *)b)->priority) { 10 | return ((icer_packet_context *)a)->subband_type - ((icer_packet_context *)b)->subband_type; 11 | } 12 | return ((icer_packet_context *)b)->priority - ((icer_packet_context *)a)->priority; 13 | } 14 | 15 | #ifdef USE_UINT8_FUNCTIONS 16 | int icer_compress_image_uint8(uint8_t * const image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt, 17 | uint8_t segments, icer_output_data_buf_typedef * const output_data) { 18 | int res; 19 | int chan = 0; 20 | res = icer_wavelet_transform_stages_uint8(image, image_w, image_h, stages, filt); 21 | if (res != ICER_RESULT_OK) return res; 22 | 23 | size_t ll_w = icer_get_dim_n_low_stages(image_w, stages); 24 | size_t ll_h = icer_get_dim_n_low_stages(image_h, stages); 25 | 26 | uint64_t sum = 0; 27 | uint8_t *pixel; 28 | for (size_t row = 0;row < ll_h;row++) { 29 | pixel = image + image_w * row; 30 | for (size_t col = 0;col < ll_w;col++) { 31 | sum += (*pixel); 32 | pixel++; 33 | } 34 | } 35 | 36 | uint8_t ll_mean = sum / (ll_w * ll_h); 37 | if (ll_mean > INT8_MAX) { 38 | return ICER_INTEGER_OVERFLOW; 39 | } 40 | 41 | int8_t *signed_pixel; 42 | for (size_t row = 0;row < ll_h;row++) { 43 | signed_pixel = (int8_t*)(image + image_w * row); 44 | for (size_t col = 0;col < ll_w;col++) { 45 | (*signed_pixel) -= (int8_t)ll_mean; 46 | signed_pixel++; 47 | } 48 | } 49 | 50 | icer_to_sign_magnitude_int8(image, image_w * image_h); 51 | 52 | uint32_t priority = 0; 53 | uint32_t ind = 0; 54 | for (uint8_t curr_stage = 1;curr_stage <= stages;curr_stage++) { 55 | priority = icer_pow_uint(2, curr_stage); 56 | for (uint8_t lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_8;lsb++) { 57 | icer_packets[ind].subband_type = ICER_SUBBAND_HL; 58 | icer_packets[ind].decomp_level = curr_stage; 59 | icer_packets[ind].ll_mean_val = ll_mean; 60 | icer_packets[ind].lsb = lsb; 61 | icer_packets[ind].priority = priority << lsb; 62 | icer_packets[ind].image_w = image_w; 63 | icer_packets[ind].image_h = image_h; 64 | icer_packets[ind].channel = chan; 65 | ind++; if (ind >= ICER_MAX_PACKETS) return ICER_PACKET_COUNT_EXCEEDED; 66 | 67 | icer_packets[ind].subband_type = ICER_SUBBAND_LH; 68 | icer_packets[ind].decomp_level = curr_stage; 69 | icer_packets[ind].ll_mean_val = ll_mean; 70 | icer_packets[ind].lsb = lsb; 71 | icer_packets[ind].priority = priority << lsb; 72 | icer_packets[ind].image_w = image_w; 73 | icer_packets[ind].image_h = image_h; 74 | icer_packets[ind].channel = chan; 75 | ind++; if (ind >= ICER_MAX_PACKETS) return ICER_PACKET_COUNT_EXCEEDED; 76 | 77 | icer_packets[ind].subband_type = ICER_SUBBAND_HH; 78 | icer_packets[ind].decomp_level = curr_stage; 79 | icer_packets[ind].ll_mean_val = ll_mean; 80 | icer_packets[ind].lsb = lsb; 81 | icer_packets[ind].priority = ((priority / 2) << lsb) + 1; 82 | icer_packets[ind].image_w = image_w; 83 | icer_packets[ind].image_h = image_h; 84 | icer_packets[ind].channel = chan; 85 | ind++; if (ind >= ICER_MAX_PACKETS) return ICER_PACKET_COUNT_EXCEEDED; 86 | } 87 | } 88 | 89 | priority = icer_pow_uint(2, stages); 90 | for (uint8_t lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_8;lsb++) { 91 | icer_packets[ind].subband_type = ICER_SUBBAND_LL; 92 | icer_packets[ind].decomp_level = stages; 93 | icer_packets[ind].ll_mean_val = ll_mean; 94 | icer_packets[ind].lsb = lsb; 95 | icer_packets[ind].priority = (2 * priority) << lsb; 96 | icer_packets[ind].image_w = image_w; 97 | icer_packets[ind].image_h = image_h; 98 | icer_packets[ind].channel = chan; 99 | ind++; if (ind >= ICER_MAX_PACKETS) return ICER_PACKET_COUNT_EXCEEDED; 100 | 101 | } 102 | 103 | qsort(icer_packets, ind, sizeof(icer_packet_context), comp_packet); 104 | 105 | for (int i = 0;i <= ICER_MAX_DECOMP_STAGES;i++) { 106 | for (int j = 0;j <= ICER_SUBBAND_MAX;j++) { 107 | for (int k = 0;k <= ICER_MAX_SEGMENTS;k++) { 108 | for (int lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_8;lsb++) { 109 | icer_rearrange_segments_8[chan][i][j][lsb][k] = NULL; 110 | } 111 | } 112 | } 113 | } 114 | 115 | partition_param_typdef partition_params; 116 | uint8_t *data_start = image; 117 | for (size_t it = 0;it < ind;it++) { 118 | if (icer_packets[it].subband_type == ICER_SUBBAND_LL) { 119 | ll_w = icer_get_dim_n_low_stages(image_w, icer_packets[it].decomp_level); 120 | ll_h = icer_get_dim_n_low_stages(image_h, icer_packets[it].decomp_level); 121 | data_start = image; 122 | } else if (icer_packets[it].subband_type == ICER_SUBBAND_HL) { 123 | ll_w = icer_get_dim_n_high_stages(image_w, icer_packets[it].decomp_level); 124 | ll_h = icer_get_dim_n_low_stages(image_h, icer_packets[it].decomp_level); 125 | data_start = image + icer_get_dim_n_low_stages(image_w, icer_packets[it].decomp_level); 126 | } else if (icer_packets[it].subband_type == ICER_SUBBAND_LH) { 127 | ll_w = icer_get_dim_n_low_stages(image_w, icer_packets[it].decomp_level); 128 | ll_h = icer_get_dim_n_high_stages(image_h, icer_packets[it].decomp_level); 129 | data_start = image + icer_get_dim_n_low_stages(image_h, icer_packets[it].decomp_level) * image_w; 130 | } else if (icer_packets[it].subband_type == ICER_SUBBAND_HH) { 131 | ll_w = icer_get_dim_n_high_stages(image_w, icer_packets[it].decomp_level); 132 | ll_h = icer_get_dim_n_high_stages(image_h, icer_packets[it].decomp_level); 133 | data_start = image + icer_get_dim_n_low_stages(image_h, icer_packets[it].decomp_level) * image_w + 134 | icer_get_dim_n_low_stages(image_w, icer_packets[it].decomp_level); 135 | } else { 136 | return ICER_FATAL_ERROR; 137 | } 138 | 139 | icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 140 | res = icer_compress_partition_uint8(data_start, &partition_params, image_w, &(icer_packets[it]), output_data, 141 | icer_rearrange_segments_8[chan][icer_packets[it].decomp_level][icer_packets[it].subband_type][icer_packets[it].lsb]); 142 | if (res != ICER_RESULT_OK) { 143 | break; 144 | } 145 | } 146 | 147 | size_t rearrange_offset = 0; 148 | size_t len; 149 | for (int k = 0;k <= ICER_MAX_SEGMENTS;k++) { 150 | for (int j = ICER_SUBBAND_MAX;j >= 0;j--) { 151 | for (int i = ICER_MAX_DECOMP_STAGES;i >= 0;i--) { 152 | for (int lsb = ICER_BITPLANES_TO_COMPRESS_8 - 1;lsb >= 0;lsb--) { 153 | if (icer_rearrange_segments_8[chan][i][j][lsb][k] != NULL) { 154 | len = icer_ceil_div_uint32(icer_rearrange_segments_8[chan][i][j][lsb][k]->data_length, 8) + sizeof(icer_image_segment_typedef); 155 | memcpy(output_data->rearrange_start + rearrange_offset, icer_rearrange_segments_8[chan][i][j][lsb][k], len); 156 | rearrange_offset += len; 157 | } 158 | } 159 | } 160 | } 161 | } 162 | 163 | return res; 164 | } 165 | 166 | int icer_decompress_image_uint8(uint8_t * const image, size_t * const image_w, size_t * const image_h, const size_t image_bufsize, const uint8_t *datastream, 167 | const size_t data_length, const uint8_t stages, const enum icer_filter_types filt, const uint8_t segments) { 168 | int chan = 0; 169 | for (int i = 0;i <= ICER_MAX_DECOMP_STAGES;i++) { 170 | for (int j = 0;j <= ICER_SUBBAND_MAX;j++) { 171 | for (int k = 0;k <= ICER_MAX_SEGMENTS;k++) { 172 | for (int lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_8;lsb++) { 173 | icer_reconstruct_data_8[chan][i][j][k][lsb] = NULL; 174 | } 175 | } 176 | } 177 | } 178 | 179 | icer_image_segment_typedef *seg = NULL; 180 | const uint8_t *seg_start; 181 | size_t offset = 0; 182 | size_t pkt_offset; 183 | int res; 184 | uint16_t ll_mean = 0; 185 | while ((data_length - offset) > 0) { 186 | seg_start = datastream + offset; 187 | res = icer_find_packet_in_bytestream(&seg, seg_start, data_length - offset, &pkt_offset); 188 | if (res == ICER_RESULT_OK) { 189 | icer_reconstruct_data_8[chan][seg->decomp_level][seg->subband_type][seg->segment_number][ICER_GET_LSB_MACRO(seg->lsb_chan)] = seg; 190 | *image_w = seg->image_w; 191 | *image_h = seg->image_h; 192 | ll_mean = seg->ll_mean_val; 193 | } 194 | offset += pkt_offset; 195 | } 196 | 197 | if (image_bufsize < (*image_w) * (*image_h)) { 198 | return ICER_BYTE_QUOTA_EXCEEDED; 199 | } 200 | 201 | uint8_t *data_start; 202 | size_t ll_w; 203 | size_t ll_h; 204 | size_t im_w = *image_w; 205 | size_t im_h = *image_h; 206 | memset(image, 0, im_w * im_h * sizeof(image[0])); 207 | partition_param_typdef partition_params; 208 | for (uint8_t curr_stage = 1;curr_stage <= stages;curr_stage++) { 209 | if (curr_stage == stages) { 210 | /* LL subband */ 211 | ll_w = icer_get_dim_n_low_stages(im_w, curr_stage); 212 | ll_h = icer_get_dim_n_low_stages(im_h, curr_stage); 213 | data_start = image; 214 | 215 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 216 | if (res != ICER_RESULT_OK) return res; 217 | res = icer_decompress_partition_uint8(data_start, &partition_params, im_w, 218 | icer_reconstruct_data_8[chan][curr_stage][ICER_SUBBAND_LL]); 219 | if (res != ICER_RESULT_OK) return res; 220 | } 221 | 222 | /* HL subband */ 223 | ll_w = icer_get_dim_n_high_stages(im_w, curr_stage); 224 | ll_h = icer_get_dim_n_low_stages(im_h, curr_stage); 225 | data_start = image + icer_get_dim_n_low_stages(im_w, curr_stage); 226 | 227 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 228 | if (res != ICER_RESULT_OK) return res; 229 | res = icer_decompress_partition_uint8(data_start, &partition_params, im_w, 230 | icer_reconstruct_data_8[chan][curr_stage][ICER_SUBBAND_HL]); 231 | if (res != ICER_RESULT_OK) return res; 232 | 233 | /* LH subband */ 234 | ll_w = icer_get_dim_n_low_stages(im_w, curr_stage); 235 | ll_h = icer_get_dim_n_high_stages(im_h, curr_stage); 236 | data_start = image + icer_get_dim_n_low_stages(im_h, curr_stage) * im_w; 237 | 238 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 239 | if (res != ICER_RESULT_OK) return res; 240 | res = icer_decompress_partition_uint8(data_start, &partition_params, im_w, 241 | icer_reconstruct_data_8[chan][curr_stage][ICER_SUBBAND_LH]); 242 | if (res != ICER_RESULT_OK) return res; 243 | 244 | /* HH subband */ 245 | ll_w = icer_get_dim_n_high_stages(im_w, curr_stage); 246 | ll_h = icer_get_dim_n_high_stages(im_h, curr_stage); 247 | data_start = image + icer_get_dim_n_low_stages(im_h, curr_stage) * im_w + icer_get_dim_n_low_stages(im_w, curr_stage); 248 | 249 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 250 | if (res != ICER_RESULT_OK) return res; 251 | res = icer_decompress_partition_uint8(data_start, &partition_params, im_w, 252 | icer_reconstruct_data_8[chan][curr_stage][ICER_SUBBAND_HH]); 253 | if (res != ICER_RESULT_OK) return res; 254 | } 255 | 256 | icer_from_sign_magnitude_int8(image, im_w * im_h); 257 | 258 | ll_w = icer_get_dim_n_low_stages(im_w, stages); 259 | ll_h = icer_get_dim_n_low_stages(im_h, stages); 260 | int8_t *signed_pixel; 261 | for (size_t row = 0;row < ll_h;row++) { 262 | signed_pixel = (int8_t*)(image + im_w * row); 263 | for (size_t col = 0;col < ll_w;col++) { 264 | (*signed_pixel) += (int8_t)ll_mean; 265 | signed_pixel++; 266 | } 267 | } 268 | 269 | icer_inverse_wavelet_transform_stages_uint8(image, im_w, im_h, stages, filt); 270 | icer_remove_negative_uint8(image, im_w, im_h); 271 | return ICER_RESULT_OK; 272 | } 273 | #endif 274 | 275 | #ifdef USE_UINT16_FUNCTIONS 276 | #ifdef USE_ENCODE_FUNCTIONS 277 | int icer_compress_image_uint16(uint16_t * const image, size_t image_w, size_t image_h, uint8_t stages, enum icer_filter_types filt, 278 | uint8_t segments, icer_output_data_buf_typedef * const output_data) { 279 | int res; 280 | int chan = 0; 281 | res = icer_wavelet_transform_stages_uint16(image, image_w, image_h, stages, filt); 282 | if (res != ICER_RESULT_OK) return res; 283 | 284 | size_t ll_w = icer_get_dim_n_low_stages(image_w, stages); 285 | size_t ll_h = icer_get_dim_n_low_stages(image_h, stages); 286 | 287 | uint64_t sum = 0; 288 | uint16_t *pixel; 289 | for (size_t row = 0;row < ll_h;row++) { 290 | pixel = image + image_w * row; 291 | for (size_t col = 0;col < ll_w;col++) { 292 | sum += (*pixel); 293 | pixel++; 294 | } 295 | } 296 | 297 | uint16_t ll_mean = sum / (ll_w * ll_h); 298 | if (ll_mean > INT16_MAX) { 299 | return ICER_INTEGER_OVERFLOW; 300 | } 301 | 302 | int16_t *signed_pixel; 303 | for (size_t row = 0;row < ll_h;row++) { 304 | signed_pixel = (int16_t*)(image + image_w * row); 305 | for (size_t col = 0;col < ll_w;col++) { 306 | (*signed_pixel) -= (int16_t)ll_mean; 307 | signed_pixel++; 308 | } 309 | } 310 | 311 | icer_to_sign_magnitude_int16(image, image_w * image_h); 312 | 313 | uint64_t priority = 0; 314 | uint32_t ind = 0; 315 | for (uint8_t curr_stage = 1;curr_stage <= stages;curr_stage++) { 316 | priority = icer_pow_uint(2, curr_stage); 317 | for (uint8_t lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_16;lsb++) { 318 | icer_packets_16[ind].subband_type = ICER_SUBBAND_HL; 319 | icer_packets_16[ind].decomp_level = curr_stage; 320 | icer_packets_16[ind].ll_mean_val = ll_mean; 321 | icer_packets_16[ind].lsb = lsb; 322 | icer_packets_16[ind].priority = priority << lsb; 323 | icer_packets_16[ind].image_w = image_w; 324 | icer_packets_16[ind].image_h = image_h; 325 | icer_packets_16[ind].channel = chan; 326 | ind++; if (ind >= ICER_MAX_PACKETS_16) return ICER_PACKET_COUNT_EXCEEDED; 327 | 328 | icer_packets_16[ind].subband_type = ICER_SUBBAND_LH; 329 | icer_packets_16[ind].decomp_level = curr_stage; 330 | icer_packets_16[ind].ll_mean_val = ll_mean; 331 | icer_packets_16[ind].lsb = lsb; 332 | icer_packets_16[ind].priority = priority << lsb; 333 | icer_packets_16[ind].image_w = image_w; 334 | icer_packets_16[ind].image_h = image_h; 335 | icer_packets_16[ind].channel = chan; 336 | ind++; if (ind >= ICER_MAX_PACKETS_16) return ICER_PACKET_COUNT_EXCEEDED; 337 | 338 | icer_packets_16[ind].subband_type = ICER_SUBBAND_HH; 339 | icer_packets_16[ind].decomp_level = curr_stage; 340 | icer_packets_16[ind].ll_mean_val = ll_mean; 341 | icer_packets_16[ind].lsb = lsb; 342 | icer_packets_16[ind].priority = ((priority / 2) << lsb) + 1; 343 | icer_packets_16[ind].image_w = image_w; 344 | icer_packets_16[ind].image_h = image_h; 345 | icer_packets_16[ind].channel = chan; 346 | ind++; if (ind >= ICER_MAX_PACKETS_16) return ICER_PACKET_COUNT_EXCEEDED; 347 | } 348 | } 349 | 350 | priority = icer_pow_uint(2, stages); 351 | for (uint8_t lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_16;lsb++) { 352 | icer_packets_16[ind].subband_type = ICER_SUBBAND_LL; 353 | icer_packets_16[ind].decomp_level = stages; 354 | icer_packets_16[ind].ll_mean_val = ll_mean; 355 | icer_packets_16[ind].lsb = lsb; 356 | icer_packets_16[ind].priority = (2 * priority) << lsb; 357 | icer_packets_16[ind].image_w = image_w; 358 | icer_packets_16[ind].image_h = image_h; 359 | icer_packets_16[ind].channel = chan; 360 | ind++; if (ind >= ICER_MAX_PACKETS_16) return ICER_PACKET_COUNT_EXCEEDED; 361 | } 362 | 363 | qsort(icer_packets_16, ind, sizeof(icer_packet_context), comp_packet); 364 | 365 | for (int i = 0;i <= ICER_MAX_DECOMP_STAGES;i++) { 366 | for (int j = 0;j <= ICER_SUBBAND_MAX;j++) { 367 | for (int k = 0;k <= ICER_MAX_SEGMENTS;k++) { 368 | for (int lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_16;lsb++) { 369 | icer_rearrange_segments_16[chan][i][j][lsb][k] = NULL; 370 | } 371 | } 372 | } 373 | } 374 | 375 | partition_param_typdef partition_params; 376 | uint16_t *data_start = image; 377 | for (size_t it = 0;it < ind;it++) { 378 | if (icer_packets_16[it].subband_type == ICER_SUBBAND_LL) { 379 | ll_w = icer_get_dim_n_low_stages(image_w, icer_packets_16[it].decomp_level); 380 | ll_h = icer_get_dim_n_low_stages(image_h, icer_packets_16[it].decomp_level); 381 | data_start = image; 382 | } else if (icer_packets_16[it].subband_type == ICER_SUBBAND_HL) { 383 | ll_w = icer_get_dim_n_high_stages(image_w, icer_packets_16[it].decomp_level); 384 | ll_h = icer_get_dim_n_low_stages(image_h, icer_packets_16[it].decomp_level); 385 | data_start = image + icer_get_dim_n_low_stages(image_w, icer_packets_16[it].decomp_level); 386 | } else if (icer_packets_16[it].subband_type == ICER_SUBBAND_LH) { 387 | ll_w = icer_get_dim_n_low_stages(image_w, icer_packets_16[it].decomp_level); 388 | ll_h = icer_get_dim_n_high_stages(image_h, icer_packets_16[it].decomp_level); 389 | data_start = image + icer_get_dim_n_low_stages(image_h, icer_packets_16[it].decomp_level) * image_w; 390 | } else if (icer_packets_16[it].subband_type == ICER_SUBBAND_HH) { 391 | ll_w = icer_get_dim_n_high_stages(image_w, icer_packets_16[it].decomp_level); 392 | ll_h = icer_get_dim_n_high_stages(image_h, icer_packets_16[it].decomp_level); 393 | data_start = image + icer_get_dim_n_low_stages(image_h, icer_packets_16[it].decomp_level) * image_w + 394 | icer_get_dim_n_low_stages(image_w, icer_packets_16[it].decomp_level); 395 | } else { 396 | return ICER_FATAL_ERROR; 397 | } 398 | 399 | icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 400 | res = icer_compress_partition_uint16(data_start, &partition_params, image_w, &(icer_packets_16[it]), 401 | output_data, icer_rearrange_segments_16[chan][icer_packets_16[it].decomp_level][icer_packets_16[it].subband_type][icer_packets_16[it].lsb]); 402 | if (res != ICER_RESULT_OK) { 403 | break; 404 | } 405 | } 406 | 407 | size_t rearrange_offset = 0; 408 | size_t len; 409 | for (int k = 0;k <= ICER_MAX_SEGMENTS;k++) { 410 | for (int j = ICER_SUBBAND_MAX;j >= 0;j--) { 411 | for (int i = ICER_MAX_DECOMP_STAGES;i >= 0;i--) { 412 | for (int lsb = ICER_BITPLANES_TO_COMPRESS_16 - 1;lsb >= 0;lsb--) { 413 | if (icer_rearrange_segments_16[chan][i][j][lsb][k] != NULL) { 414 | len = icer_ceil_div_uint32(icer_rearrange_segments_16[chan][i][j][lsb][k]->data_length, 8) + sizeof(icer_image_segment_typedef); 415 | memcpy(output_data->rearrange_start + rearrange_offset, (uint8_t*)icer_rearrange_segments_16[chan][i][j][lsb][k], len); 416 | rearrange_offset += len; 417 | } 418 | } 419 | } 420 | } 421 | } 422 | 423 | return res; 424 | } 425 | #endif 426 | 427 | #ifdef USE_DECODE_FUNCTIONS 428 | int icer_decompress_image_uint16(uint16_t * const image, size_t * const image_w, size_t * const image_h, size_t image_bufsize, const uint8_t *datastream, 429 | size_t data_length, uint8_t stages, enum icer_filter_types filt, uint8_t segments) { 430 | int chan = 0; 431 | for (int i = 0;i <= ICER_MAX_DECOMP_STAGES;i++) { 432 | for (int j = 0;j <= ICER_SUBBAND_MAX;j++) { 433 | for (int k = 0;k <= ICER_MAX_SEGMENTS;k++) { 434 | for (int lsb = 0;lsb < ICER_BITPLANES_TO_COMPRESS_16;lsb++) { 435 | icer_reconstruct_data_16[chan][i][j][k][lsb] = NULL; 436 | } 437 | } 438 | } 439 | } 440 | 441 | icer_image_segment_typedef *seg = NULL; 442 | const uint8_t *seg_start; 443 | size_t offset = 0; 444 | size_t pkt_offset = 0; 445 | int res; 446 | uint16_t ll_mean = 0; 447 | while ((data_length - offset) > 0) { 448 | seg_start = datastream + offset; 449 | res = icer_find_packet_in_bytestream(&seg, seg_start, data_length - offset, &pkt_offset); 450 | if (res == ICER_RESULT_OK) { 451 | icer_reconstruct_data_16[chan][seg->decomp_level][seg->subband_type][seg->segment_number][ICER_GET_LSB_MACRO(seg->lsb_chan)] = seg; 452 | *image_w = seg->image_w; 453 | *image_h = seg->image_h; 454 | ll_mean = seg->ll_mean_val; 455 | } 456 | offset += pkt_offset; 457 | } 458 | 459 | if (image_bufsize < (*image_w) * (*image_h)) { 460 | return ICER_BYTE_QUOTA_EXCEEDED; 461 | } 462 | 463 | uint16_t *data_start; 464 | size_t ll_w; 465 | size_t ll_h; 466 | size_t im_w = *image_w; 467 | size_t im_h = *image_h; 468 | memset(image, 0, im_w * im_h * sizeof(image[0])); 469 | partition_param_typdef partition_params; 470 | for (uint8_t curr_stage = 1;curr_stage <= stages;curr_stage++) { 471 | if (curr_stage == stages) { 472 | /* LL subband */ 473 | ll_w = icer_get_dim_n_low_stages(im_w, curr_stage); 474 | ll_h = icer_get_dim_n_low_stages(im_h, curr_stage); 475 | data_start = image; 476 | 477 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 478 | if (res != ICER_RESULT_OK) return res; 479 | res = icer_decompress_partition_uint16(data_start, &partition_params, im_w, 480 | icer_reconstruct_data_16[chan][curr_stage][ICER_SUBBAND_LL]); 481 | if (res != ICER_RESULT_OK) return res; 482 | } 483 | 484 | /* HL subband */ 485 | ll_w = icer_get_dim_n_high_stages(im_w, curr_stage); 486 | ll_h = icer_get_dim_n_low_stages(im_h, curr_stage); 487 | data_start = image + icer_get_dim_n_low_stages(im_w, curr_stage); 488 | 489 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 490 | if (res != ICER_RESULT_OK) return res; 491 | res = icer_decompress_partition_uint16(data_start, &partition_params, im_w, 492 | icer_reconstruct_data_16[chan][curr_stage][ICER_SUBBAND_HL]); 493 | if (res != ICER_RESULT_OK) return res; 494 | 495 | /* LH subband */ 496 | ll_w = icer_get_dim_n_low_stages(im_w, curr_stage); 497 | ll_h = icer_get_dim_n_high_stages(im_h, curr_stage); 498 | data_start = image + icer_get_dim_n_low_stages(im_h, curr_stage) * im_w; 499 | 500 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 501 | if (res != ICER_RESULT_OK) return res; 502 | res = icer_decompress_partition_uint16(data_start, &partition_params, im_w, 503 | icer_reconstruct_data_16[chan][curr_stage][ICER_SUBBAND_LH]); 504 | if (res != ICER_RESULT_OK) return res; 505 | 506 | /* HH subband */ 507 | ll_w = icer_get_dim_n_high_stages(im_w, curr_stage); 508 | ll_h = icer_get_dim_n_high_stages(im_h, curr_stage); 509 | data_start = image + icer_get_dim_n_low_stages(im_h, curr_stage) * im_w + icer_get_dim_n_low_stages(im_w, curr_stage); 510 | 511 | res = icer_generate_partition_parameters(&partition_params, ll_w, ll_h, segments); 512 | if (res != ICER_RESULT_OK) return res; 513 | res = icer_decompress_partition_uint16(data_start, &partition_params, im_w, 514 | icer_reconstruct_data_16[chan][curr_stage][ICER_SUBBAND_HH]); 515 | if (res != ICER_RESULT_OK) return res; 516 | } 517 | 518 | icer_from_sign_magnitude_int16(image, im_w * im_h); 519 | 520 | ll_w = icer_get_dim_n_low_stages(im_w, stages); 521 | ll_h = icer_get_dim_n_low_stages(im_h, stages); 522 | int16_t *signed_pixel; 523 | for (size_t row = 0;row < ll_h;row++) { 524 | signed_pixel = (int16_t*)(image + im_w * row); 525 | for (size_t col = 0;col < ll_w;col++) { 526 | (*signed_pixel) += (int16_t)ll_mean; 527 | signed_pixel++; 528 | } 529 | } 530 | 531 | icer_inverse_wavelet_transform_stages_uint16(image, im_w, im_h, stages, filt); 532 | icer_remove_negative_uint16(image, im_w, im_h); 533 | return ICER_RESULT_OK; 534 | } 535 | #endif 536 | #endif 537 | 538 | #ifdef USE_DECODE_FUNCTIONS 539 | int icer_get_image_dimensions(const uint8_t *datastream, size_t data_length, size_t *image_w, size_t *image_h) { 540 | if (!datastream || !image_w || !image_h) { 541 | return ICER_INVALID_INPUT; 542 | } 543 | 544 | icer_image_segment_typedef *seg = NULL; 545 | const uint8_t *seg_start; 546 | size_t offset = 0; 547 | size_t pkt_offset = 0; 548 | int res; 549 | 550 | // Loop through segments to find the first segment containing the image dimensions 551 | while ((data_length - offset) > 0) { 552 | seg_start = datastream + offset; 553 | res = icer_find_packet_in_bytestream(&seg, seg_start, data_length - offset, &pkt_offset); 554 | if (res == ICER_RESULT_OK && seg) { 555 | *image_w = seg->image_w; 556 | *image_h = seg->image_h; 557 | return ICER_RESULT_OK; // Successfully retrieved dimensions 558 | } 559 | offset += pkt_offset; 560 | } 561 | 562 | // If no valid segment found or data length is insufficient 563 | return ICER_DECODER_OUT_OF_DATA; 564 | } 565 | #endif 566 | 567 | int icer_find_packet_in_bytestream(icer_image_segment_typedef **seg, const uint8_t *datastream, size_t data_length, size_t * const offset) { 568 | (*offset) = 0; 569 | (*seg) = NULL; 570 | while ((*offset) < data_length) { 571 | (*seg) = (icer_image_segment_typedef*)(datastream + (*offset)); 572 | if ((*seg)->preamble == ICER_PACKET_PREAMBLE) { 573 | if ((*seg)->crc32 == icer_calculate_packet_crc32((*seg))) { 574 | if (icer_ceil_div_uint32((*seg)->data_length, 8) <= (data_length-(*offset)-sizeof(icer_image_segment_typedef))) { 575 | if((*seg)->data_crc32 == icer_calculate_segment_crc32((*seg))) { 576 | (*offset) += icer_ceil_div_uint32((*seg)->data_length, 8) + sizeof(icer_image_segment_typedef); 577 | return ICER_RESULT_OK; 578 | } 579 | } 580 | } 581 | } 582 | (*seg) = NULL; 583 | (*offset)++; 584 | } 585 | return ICER_DECODER_OUT_OF_DATA; 586 | } -------------------------------------------------------------------------------- /lib_icer/src/icer_config.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 19/3/2023. 3 | // 4 | #include "icer.h" 5 | 6 | #ifdef USE_ENCODE_FUNCTIONS 7 | icer_custom_code_typedef icer_custom_coding_scheme[ICER_ENCODER_BIN_MAX + 1][CUSTOM_CODING_MAX_LOOKUP]; 8 | #endif 9 | 10 | #ifdef USE_DECODE_FUNCTIONS 11 | icer_custom_code_typedef icer_custom_decode_scheme[ICER_ENCODER_BIN_MAX + 1][CUSTOM_CODING_MAX_LOOKUP]; 12 | #endif 13 | 14 | icer_custom_flush_typedef icer_custom_code_flush_bits[ICER_ENCODER_BIN_MAX + 1][CUSTOM_CODE_FLUSH_MAX_LOOKUP + 1][MAX_NUM_BITS_BEFORE_FLUSH + 1]; 15 | 16 | icer_golomb_code_typedef icer_golomb_coders[ICER_ENCODER_BIN_MAX + 1]; 17 | 18 | const int16_t icer_wavelet_filter_parameters[][4] = {{0, 4, 4, 0}, 19 | {0, 4, 6, 4}, 20 | {-1, 4, 8, 6}, 21 | {0, 4, 5, 2}, 22 | {0, 3, 8, 6}, 23 | {0, 3, 9, 8}, 24 | {0, 4, 4, 4}}; 25 | 26 | const uint8_t icer_context_table_ll_lh_hl[3][3][5] = { 27 | { 28 | { ICER_CONTEXT_0, ICER_CONTEXT_1, ICER_CONTEXT_2, ICER_CONTEXT_2, ICER_CONTEXT_2}, 29 | { ICER_CONTEXT_3, ICER_CONTEXT_3, ICER_CONTEXT_3, ICER_CONTEXT_3, ICER_CONTEXT_3}, 30 | { ICER_CONTEXT_4, ICER_CONTEXT_4, ICER_CONTEXT_4, ICER_CONTEXT_4, ICER_CONTEXT_4} 31 | }, 32 | { 33 | { ICER_CONTEXT_5, ICER_CONTEXT_6, ICER_CONTEXT_7, ICER_CONTEXT_7, ICER_CONTEXT_7}, 34 | { ICER_CONTEXT_7, ICER_CONTEXT_7, ICER_CONTEXT_7, ICER_CONTEXT_7, ICER_CONTEXT_7}, 35 | { ICER_CONTEXT_7, ICER_CONTEXT_7, ICER_CONTEXT_7, ICER_CONTEXT_7, ICER_CONTEXT_7} 36 | }, 37 | { 38 | { ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8}, 39 | { ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8}, 40 | { ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8, ICER_CONTEXT_8}, 41 | } 42 | }; 43 | 44 | const uint8_t icer_context_table_hh[5][5] = { 45 | { ICER_CONTEXT_0, ICER_CONTEXT_3, ICER_CONTEXT_6, ICER_CONTEXT_8, ICER_CONTEXT_8}, 46 | { ICER_CONTEXT_1, ICER_CONTEXT_4, ICER_CONTEXT_7, ICER_CONTEXT_8, ICER_CONTEXT_8}, 47 | { ICER_CONTEXT_2, ICER_CONTEXT_5, ICER_CONTEXT_7, ICER_CONTEXT_8, ICER_CONTEXT_8}, 48 | { ICER_CONTEXT_2, ICER_CONTEXT_5, ICER_CONTEXT_7, ICER_CONTEXT_8, ICER_CONTEXT_8}, 49 | { ICER_CONTEXT_2, ICER_CONTEXT_5, ICER_CONTEXT_7, ICER_CONTEXT_8, ICER_CONTEXT_8}, 50 | }; 51 | 52 | const uint8_t icer_sign_context_table[5][5] = { 53 | {ICER_CONTEXT_14, ICER_CONTEXT_14, ICER_CONTEXT_15, ICER_CONTEXT_16, ICER_CONTEXT_16}, 54 | {ICER_CONTEXT_14, ICER_CONTEXT_14, ICER_CONTEXT_15, ICER_CONTEXT_16, ICER_CONTEXT_16}, 55 | {ICER_CONTEXT_13, ICER_CONTEXT_13, ICER_CONTEXT_12, ICER_CONTEXT_13, ICER_CONTEXT_13}, 56 | {ICER_CONTEXT_16, ICER_CONTEXT_16, ICER_CONTEXT_15, ICER_CONTEXT_14, ICER_CONTEXT_14}, 57 | {ICER_CONTEXT_16, ICER_CONTEXT_16, ICER_CONTEXT_15, ICER_CONTEXT_14, ICER_CONTEXT_14}, 58 | }; 59 | 60 | /* 1 is negative, 0 is positive */ 61 | const uint8_t icer_sign_prediction_table[5][5] = { 62 | {1, 1, 1, 1, 1}, 63 | {1, 1, 1, 1, 1}, 64 | {0, 0, 0, 1, 1}, 65 | {0, 0, 0, 0, 0}, 66 | {0, 0, 0, 0, 0} 67 | }; 68 | 69 | const uint32_t icer_bin_probability_cutoffs[ICER_ENCODER_BIN_MAX+1] = { 70 | 35298, 71 | 37345, 72 | 40503, 73 | 43591, 74 | 47480, 75 | 50133, 76 | 53645, 77 | 55902, 78 | 57755, 79 | 58894, 80 | 60437, 81 | 62267, 82 | 63613, 83 | 64557, 84 | 65134, 85 | 65392, 86 | 65536 87 | }; 88 | 89 | const int32_t icer_bin_coding_scheme[ICER_ENCODER_BIN_MAX+1] = { 90 | 0, 91 | -1, 92 | -1, 93 | -1, 94 | -1, 95 | -1, 96 | -1, 97 | -1, 98 | 5, 99 | 6, 100 | 7, 101 | 11, 102 | 17, 103 | 31, 104 | 70, 105 | 200, 106 | 512 107 | }; 108 | size_t icer_slice_lengths[MAX_K] = {0}; 109 | -------------------------------------------------------------------------------- /lib_icer/src/icer_context_modeller.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 19/3/2023. 3 | // 4 | 5 | #include "icer.h" 6 | 7 | #ifdef USE_UINT8_FUNCTIONS 8 | static inline uint8_t get_bit_category_uint8(const uint8_t* data, uint8_t lsb); 9 | static inline bool get_bit_significance_uint8(const uint8_t* data, uint8_t lsb); 10 | static inline int8_t get_sign_uint8(const uint8_t* data, uint8_t lsb); 11 | #endif 12 | 13 | #ifdef USE_UINT16_FUNCTIONS 14 | static inline uint8_t get_bit_category_uint16(const uint16_t* data, uint8_t lsb); 15 | static inline bool get_bit_significance_uint16(const uint16_t* data, uint8_t lsb); 16 | static inline int8_t get_sign_uint16(const uint16_t* data, uint8_t lsb); 17 | #endif 18 | 19 | #ifdef USE_UINT8_FUNCTIONS 20 | int icer_compress_bitplane_uint8(const uint8_t *data, size_t plane_w, size_t plane_h, size_t rowstride, 21 | icer_context_model_typedef *context_model, 22 | icer_encoder_context_typedef *encoder_context, 23 | const icer_packet_context *pkt_context) { 24 | int res; 25 | const uint8_t *pos; 26 | const uint8_t *rowstart = data; 27 | int category; 28 | bool bit; 29 | uint8_t lsb = pkt_context->lsb; 30 | uint8_t mask = 0b1 << lsb; 31 | 32 | const uint8_t *h0, *h1, *v0, *v1, *d0, *d1, *d2, *d3; 33 | uint8_t h = 0, v = 0, d = 0, tmp; 34 | int8_t sh0, sh1, sv0, sv1; 35 | uint8_t sh, sv; 36 | uint8_t pred_sign, actual_sign, agreement_bit; 37 | enum icer_pixel_contexts sign_context; 38 | size_t vert_bound = plane_h - 1; 39 | size_t hor_bound = plane_w - 1; 40 | 41 | uint8_t prev_plane = lsb+1; 42 | if (prev_plane >= 8) return ICER_BITPLANE_OUT_OF_RANGE; 43 | 44 | for (size_t row = 0; row < plane_h; row++) { 45 | pos = rowstart; 46 | /* keep track of 8 adjacent pixels */ 47 | h0 = pos - 1; h1 = pos + 1; 48 | v0 = pos - rowstride; v1 = pos + rowstride; 49 | d0 = v0 - 1; d1 = v0 + 1; 50 | d2 = v1 - 1; d3 = v1 + 1; 51 | 52 | enum icer_pixel_contexts cntxt = 0; 53 | 54 | for (size_t col = 0; col < plane_w; col++) { 55 | category = get_bit_category_uint8(pos, lsb); 56 | bit = ((*pos) & mask) != 0; 57 | 58 | if (category == ICER_CATEGORY_3) { 59 | /* pass to uncoded bin */ 60 | res = icer_encode_bit(encoder_context, bit, 1, 2); 61 | if (res != ICER_RESULT_OK) return res; 62 | } else { 63 | if (category == ICER_CATEGORY_0 || category == ICER_CATEGORY_1) { 64 | h = 0; 65 | v = 0; 66 | d = 0; 67 | 68 | /* consider the horizontally adjacent pixels */ 69 | if (col > 0) h += get_bit_significance_uint8(h0, lsb) & 1; 70 | if (col < hor_bound) h += get_bit_significance_uint8(h1, prev_plane) & 1; 71 | 72 | /* consider the vertically adjacent pixels */ 73 | if (row > 0) v += get_bit_significance_uint8(v0, lsb) & 1; 74 | if (row < vert_bound) v += get_bit_significance_uint8(v1, prev_plane) & 1; 75 | 76 | /* consider the diagonally adjacent pixels */ 77 | if (col > 0 && row > 0) d += get_bit_significance_uint8(d0, lsb) & 1; 78 | if (col > 0 && row < vert_bound) d += get_bit_significance_uint8(d2, prev_plane) & 1; 79 | if (col < hor_bound && row > 0) d += get_bit_significance_uint8(d1, lsb) & 1; 80 | if (col < hor_bound && row < vert_bound) d += get_bit_significance_uint8(d3, prev_plane) & 1; 81 | } 82 | 83 | if (category == ICER_CATEGORY_0) { 84 | if (context_model->subband_type == ICER_SUBBAND_HL) { 85 | tmp = h; 86 | h = v; 87 | v = tmp; 88 | } 89 | 90 | if (context_model->subband_type != ICER_SUBBAND_HH) { 91 | cntxt = icer_context_table_ll_lh_hl[h][v][d]; 92 | } else { 93 | cntxt = icer_context_table_hh[h + v][d]; 94 | } 95 | } else if (category == ICER_CATEGORY_1) { 96 | cntxt = (h + v == 0) ? ICER_CONTEXT_9 : ICER_CONTEXT_10; 97 | } else if (category == ICER_CATEGORY_2) { 98 | cntxt = ICER_CONTEXT_11; 99 | } 100 | 101 | res = icer_encode_bit(encoder_context, bit, context_model->zero_count[cntxt], context_model->total_count[cntxt]); 102 | if (res != ICER_RESULT_OK) return res; 103 | 104 | context_model->total_count[cntxt]++; 105 | context_model->zero_count[cntxt] += (uint32_t)(!bit); 106 | if (context_model->total_count[cntxt] >= ICER_CONTEXT_RESCALING_CAP) { 107 | context_model->total_count[cntxt] >>= 1; 108 | if (context_model->zero_count[cntxt] > context_model->total_count[cntxt]) context_model->zero_count[cntxt] >>= 1; 109 | else icer_ceil_div_uint32(context_model->zero_count[cntxt], 2); 110 | } 111 | 112 | if (category == ICER_CATEGORY_0 && bit) { 113 | /* bit is the first magnitude bit to be encoded, thus we will encode the sign bit */ 114 | /* predict sign bit */ 115 | sh0 = 0; sh1 = 0; 116 | sv0 = 0; sv1 = 0; 117 | 118 | /* consider the horizontally adjacent pixels */ 119 | if (col > 0) sh0 = get_sign_uint8(h0, lsb); 120 | if (col < hor_bound) sh1 = get_sign_uint8(h1, prev_plane); 121 | 122 | /* consider the vertically adjacent pixels */ 123 | if (row > 0) sv0 = get_sign_uint8(v0, lsb); 124 | if (row < vert_bound) sv1 = get_sign_uint8(v1, prev_plane); 125 | 126 | sh = sh0 + sh1 + 2; 127 | sv = sv0 + sv1 + 2; 128 | 129 | if (context_model->subband_type == ICER_SUBBAND_HL) { 130 | tmp = sh; 131 | sh = sv; 132 | sv = tmp; 133 | } 134 | 135 | sign_context = icer_sign_context_table[sh][sv]; 136 | pred_sign = icer_sign_prediction_table[sh][sv]; 137 | actual_sign = ((*pos) & 0x80) != 0; 138 | 139 | agreement_bit = (pred_sign ^ actual_sign) & 1; 140 | 141 | res = icer_encode_bit(encoder_context, agreement_bit, context_model->zero_count[sign_context], context_model->total_count[sign_context]); 142 | if (res != ICER_RESULT_OK) return res; 143 | 144 | context_model->total_count[sign_context]++; 145 | context_model->zero_count[sign_context] += (uint32_t)(agreement_bit == 0); 146 | if (context_model->total_count[sign_context] >= ICER_CONTEXT_RESCALING_CAP) { 147 | context_model->total_count[sign_context] >>= 1; 148 | if (context_model->zero_count[sign_context] > context_model->total_count[sign_context]) context_model->zero_count[sign_context] >>= 1; 149 | else icer_ceil_div_uint32(context_model->zero_count[sign_context], 2); 150 | } 151 | } 152 | } 153 | 154 | pos++; 155 | /* increment position pointers of 8 adjacent pixels */ 156 | h0++; h1++; v0++; v1++; d0++; d1++; d2++; d3++; 157 | } 158 | rowstart += rowstride; 159 | } 160 | while (encoder_context->used > 0) { 161 | res = icer_flush_encode(encoder_context); 162 | if (res != ICER_RESULT_OK) return res; 163 | } 164 | return ICER_RESULT_OK; 165 | } 166 | 167 | int icer_decompress_bitplane_uint8(uint8_t * const data, size_t plane_w, size_t plane_h, size_t rowstride, 168 | icer_context_model_typedef *context_model, 169 | icer_decoder_context_typedef *decoder_context, 170 | const icer_packet_context *pkt_context) { 171 | int res; 172 | uint8_t *pos; 173 | uint8_t *rowstart = data; 174 | int category; 175 | uint8_t bit; 176 | uint8_t lsb = pkt_context->lsb; 177 | 178 | uint8_t *h0, *h1, *v0, *v1, *d0, *d1, *d2, *d3; 179 | uint8_t h = 0, v = 0, d = 0, tmp; 180 | int8_t sh0, sh1, sv0, sv1; 181 | uint8_t sh, sv; 182 | uint8_t pred_sign, actual_sign, agreement_bit; 183 | enum icer_pixel_contexts sign_context; 184 | size_t vert_bound = plane_h - 1; 185 | size_t hor_bound = plane_w - 1; 186 | 187 | uint8_t prev_plane = lsb+1; 188 | if (prev_plane >= 8) return ICER_BITPLANE_OUT_OF_RANGE; 189 | 190 | for (size_t row = 0; row < plane_h; row++) { 191 | pos = rowstart; 192 | /* keep track of 8 adjacent pixels */ 193 | h0 = pos - 1; h1 = pos + 1; 194 | v0 = pos - rowstride; v1 = pos + rowstride; 195 | d0 = v0 - 1; d1 = v0 + 1; 196 | d2 = v1 - 1; d3 = v1 + 1; 197 | 198 | enum icer_pixel_contexts cntxt = 0; 199 | 200 | for (size_t col = 0; col < plane_w; col++) { 201 | category = get_bit_category_uint8(pos, lsb); 202 | 203 | if (category == ICER_CATEGORY_3) { 204 | /* pass to uncoded bin */ 205 | res = icer_decode_bit(decoder_context, &bit, 1, 2); 206 | if (res != ICER_RESULT_OK) return res; 207 | (*pos) |= bit << lsb; 208 | } else { 209 | if (category == ICER_CATEGORY_0 || category == ICER_CATEGORY_1) { 210 | h = 0; 211 | v = 0; 212 | d = 0; 213 | 214 | /* consider the horizontally adjacent pixels */ 215 | if (col > 0) h += get_bit_significance_uint8(h0, lsb) & 1; 216 | if (col < hor_bound) h += get_bit_significance_uint8(h1, prev_plane) & 1; 217 | 218 | /* consider the vertically adjacent pixels */ 219 | if (row > 0) v += get_bit_significance_uint8(v0, lsb) & 1; 220 | if (row < vert_bound) v += get_bit_significance_uint8(v1, prev_plane) & 1; 221 | 222 | /* consider the diagonally adjacent pixels */ 223 | if (col > 0 && row > 0) d += get_bit_significance_uint8(d0, lsb) & 1; 224 | if (col > 0 && row < vert_bound) d += get_bit_significance_uint8(d2, prev_plane) & 1; 225 | if (col < hor_bound && row > 0) d += get_bit_significance_uint8(d1, lsb) & 1; 226 | if (col < hor_bound && row < vert_bound) d += get_bit_significance_uint8(d3, prev_plane) & 1; 227 | } 228 | 229 | if (category == ICER_CATEGORY_0) { 230 | if (context_model->subband_type == ICER_SUBBAND_HL) { 231 | tmp = h; 232 | h = v; 233 | v = tmp; 234 | } 235 | 236 | if (context_model->subband_type != ICER_SUBBAND_HH) { 237 | cntxt = icer_context_table_ll_lh_hl[h][v][d]; 238 | } else { 239 | cntxt = icer_context_table_hh[h + v][d]; 240 | } 241 | } else if (category == ICER_CATEGORY_1) { 242 | cntxt = (h + v == 0) ? ICER_CONTEXT_9 : ICER_CONTEXT_10; 243 | } else if (category == ICER_CATEGORY_2) { 244 | cntxt = ICER_CONTEXT_11; 245 | } 246 | 247 | res = icer_decode_bit(decoder_context, &bit, context_model->zero_count[cntxt], context_model->total_count[cntxt]); 248 | if (res != ICER_RESULT_OK) return res; 249 | (*pos) |= bit << lsb; 250 | 251 | context_model->total_count[cntxt]++; 252 | context_model->zero_count[cntxt] += (uint32_t)(!bit); 253 | if (context_model->total_count[cntxt] >= ICER_CONTEXT_RESCALING_CAP) { 254 | context_model->total_count[cntxt] >>= 1; 255 | if (context_model->zero_count[cntxt] > context_model->total_count[cntxt]) context_model->zero_count[cntxt] >>= 1; 256 | else icer_ceil_div_uint32(context_model->zero_count[cntxt], 2); 257 | } 258 | 259 | if (category == ICER_CATEGORY_0 && bit) { 260 | /* bit is the first magnitude bit to be encoded, thus we will encode the sign bit */ 261 | /* predict sign bit */ 262 | sh0 = 0; sh1 = 0; 263 | sv0 = 0; sv1 = 0; 264 | 265 | /* consider the horizontally adjacent pixels */ 266 | if (col > 0) sh0 = get_sign_uint8(h0, lsb); 267 | if (col < hor_bound) sh1 = get_sign_uint8(h1, prev_plane); 268 | 269 | /* consider the vertically adjacent pixels */ 270 | if (row > 0) sv0 = get_sign_uint8(v0, lsb); 271 | if (row < vert_bound) sv1 = get_sign_uint8(v1, prev_plane); 272 | 273 | sh = sh0 + sh1 + 2; 274 | sv = sv0 + sv1 + 2; 275 | 276 | if (context_model->subband_type == ICER_SUBBAND_HL) { 277 | tmp = sh; 278 | sh = sv; 279 | sv = tmp; 280 | } 281 | 282 | sign_context = icer_sign_context_table[sh][sv]; 283 | pred_sign = icer_sign_prediction_table[sh][sv]; 284 | 285 | res = icer_decode_bit(decoder_context, &agreement_bit, context_model->zero_count[sign_context], context_model->total_count[sign_context]); 286 | if (res != ICER_RESULT_OK) return res; 287 | actual_sign = (agreement_bit ^ pred_sign) & 1; 288 | (*pos) |= actual_sign << 7; 289 | 290 | context_model->total_count[sign_context]++; 291 | context_model->zero_count[sign_context] += (uint32_t)(agreement_bit == 0); 292 | if (context_model->total_count[sign_context] >= ICER_CONTEXT_RESCALING_CAP) { 293 | context_model->total_count[sign_context] >>= 1; 294 | if (context_model->zero_count[sign_context] > context_model->total_count[sign_context]) context_model->zero_count[sign_context] >>= 1; 295 | else icer_ceil_div_uint32(context_model->zero_count[sign_context], 2); 296 | } 297 | } 298 | } 299 | 300 | pos++; 301 | /* increment position pointers of 8 adjacent pixels */ 302 | h0++; h1++; v0++; v1++; d0++; d1++; d2++; d3++; 303 | } 304 | rowstart += rowstride; 305 | } 306 | return ICER_RESULT_OK; 307 | } 308 | #endif 309 | 310 | #ifdef USE_UINT16_FUNCTIONS 311 | #ifdef USE_ENCODE_FUNCTIONS 312 | int icer_compress_bitplane_uint16(const uint16_t *data, size_t plane_w, size_t plane_h, size_t rowstride, 313 | icer_context_model_typedef *context_model, 314 | icer_encoder_context_typedef *encoder_context, 315 | const icer_packet_context *pkt_context) { 316 | int res; 317 | const uint16_t *pos; 318 | const uint16_t *rowstart = data; 319 | int category; 320 | bool bit; 321 | uint8_t lsb = pkt_context->lsb; 322 | uint16_t mask = 0b1 << lsb; 323 | 324 | const uint16_t *h0, *h1, *v0, *v1, *d0, *d1, *d2, *d3; 325 | uint8_t h = 0, v = 0, d = 0, tmp; 326 | int8_t sh0, sh1, sv0, sv1; 327 | uint8_t sh, sv; 328 | uint8_t pred_sign, actual_sign, agreement_bit; 329 | enum icer_pixel_contexts sign_context; 330 | size_t vert_bound = plane_h - 1; 331 | size_t hor_bound = plane_w - 1; 332 | 333 | uint8_t prev_plane = lsb+1; 334 | if (prev_plane >= 16) return ICER_BITPLANE_OUT_OF_RANGE; 335 | 336 | for (size_t row = 0; row < plane_h; row++) { 337 | pos = rowstart; 338 | /* keep track of 8 adjacent pixels */ 339 | h0 = pos - 1; h1 = pos + 1; 340 | v0 = pos - rowstride; v1 = pos + rowstride; 341 | d0 = v0 - 1; d1 = v0 + 1; 342 | d2 = v1 - 1; d3 = v1 + 1; 343 | 344 | enum icer_pixel_contexts cntxt = 0; 345 | 346 | for (size_t col = 0; col < plane_w; col++) { 347 | category = get_bit_category_uint16(pos, lsb); 348 | bit = ((*pos) & mask) != 0; 349 | 350 | if (category == ICER_CATEGORY_3) { 351 | /* pass to uncoded bin */ 352 | res = icer_encode_bit(encoder_context, bit, 1, 2); 353 | if (res != ICER_RESULT_OK) return res; 354 | } else { 355 | if (category == ICER_CATEGORY_0 || category == ICER_CATEGORY_1) { 356 | h = 0; 357 | v = 0; 358 | d = 0; 359 | 360 | /* consider the horizontally adjacent pixels */ 361 | if (col > 0) h += get_bit_significance_uint16(h0, lsb) & 1; 362 | if (col < hor_bound) h += get_bit_significance_uint16(h1, prev_plane) & 1; 363 | 364 | /* consider the vertically adjacent pixels */ 365 | if (row > 0) v += get_bit_significance_uint16(v0, lsb) & 1; 366 | if (row < vert_bound) v += get_bit_significance_uint16(v1, prev_plane) & 1; 367 | 368 | /* consider the diagonally adjacent pixels */ 369 | if (col > 0 && row > 0) d += get_bit_significance_uint16(d0, lsb) & 1; 370 | if (col > 0 && row < vert_bound) d += get_bit_significance_uint16(d2, prev_plane) & 1; 371 | if (col < hor_bound && row > 0) d += get_bit_significance_uint16(d1, lsb) & 1; 372 | if (col < hor_bound && row < vert_bound) d += get_bit_significance_uint16(d3, prev_plane) & 1; 373 | } 374 | 375 | if (category == ICER_CATEGORY_0) { 376 | if (context_model->subband_type == ICER_SUBBAND_HL) { 377 | tmp = h; 378 | h = v; 379 | v = tmp; 380 | } 381 | 382 | if (context_model->subband_type != ICER_SUBBAND_HH) { 383 | cntxt = icer_context_table_ll_lh_hl[h][v][d]; 384 | } else { 385 | cntxt = icer_context_table_hh[h + v][d]; 386 | } 387 | } else if (category == ICER_CATEGORY_1) { 388 | cntxt = (h + v == 0) ? ICER_CONTEXT_9 : ICER_CONTEXT_10; 389 | } else if (category == ICER_CATEGORY_2) { 390 | cntxt = ICER_CONTEXT_11; 391 | } 392 | 393 | res = icer_encode_bit(encoder_context, bit, context_model->zero_count[cntxt], context_model->total_count[cntxt]); 394 | if (res != ICER_RESULT_OK) return res; 395 | 396 | context_model->total_count[cntxt]++; 397 | context_model->zero_count[cntxt] += (uint32_t)(!bit); 398 | if (context_model->total_count[cntxt] >= ICER_CONTEXT_RESCALING_CAP) { 399 | context_model->total_count[cntxt] >>= 1; 400 | if (context_model->zero_count[cntxt] > context_model->total_count[cntxt]) context_model->zero_count[cntxt] >>= 1; 401 | else icer_ceil_div_uint32(context_model->zero_count[cntxt], 2); 402 | } 403 | 404 | if (category == ICER_CATEGORY_0 && bit) { 405 | /* bit is the first magnitude bit to be encoded, thus we will encode the sign bit */ 406 | /* predict sign bit */ 407 | sh0 = 0; sh1 = 0; 408 | sv0 = 0; sv1 = 0; 409 | 410 | /* consider the horizontally adjacent pixels */ 411 | if (col > 0) sh0 = get_sign_uint16(h0, lsb); 412 | if (col < hor_bound) sh1 = get_sign_uint16(h1, prev_plane); 413 | 414 | /* consider the vertically adjacent pixels */ 415 | if (row > 0) sv0 = get_sign_uint16(v0, lsb); 416 | if (row < vert_bound) sv1 = get_sign_uint16(v1, prev_plane); 417 | 418 | sh = sh0 + sh1 + 2; 419 | sv = sv0 + sv1 + 2; 420 | 421 | if (context_model->subband_type == ICER_SUBBAND_HL) { 422 | tmp = sh; 423 | sh = sv; 424 | sv = tmp; 425 | } 426 | 427 | sign_context = icer_sign_context_table[sh][sv]; 428 | pred_sign = icer_sign_prediction_table[sh][sv]; 429 | actual_sign = ((*pos) & 0x8000) != 0; 430 | 431 | agreement_bit = (pred_sign ^ actual_sign) & 1; 432 | 433 | res = icer_encode_bit(encoder_context, agreement_bit, context_model->zero_count[sign_context], context_model->total_count[sign_context]); 434 | if (res != ICER_RESULT_OK) return res; 435 | 436 | context_model->total_count[sign_context]++; 437 | context_model->zero_count[sign_context] += (uint32_t)(agreement_bit == 0); 438 | if (context_model->total_count[sign_context] >= ICER_CONTEXT_RESCALING_CAP) { 439 | context_model->total_count[sign_context] >>= 1; 440 | if (context_model->zero_count[sign_context] > context_model->total_count[sign_context]) context_model->zero_count[sign_context] >>= 1; 441 | else icer_ceil_div_uint32(context_model->zero_count[sign_context], 2); 442 | } 443 | } 444 | } 445 | 446 | pos++; 447 | /* increment position pointers of 8 adjacent pixels */ 448 | h0++; h1++; v0++; v1++; d0++; d1++; d2++; d3++; 449 | } 450 | rowstart += rowstride; 451 | } 452 | while (encoder_context->used > 0) { 453 | res = icer_flush_encode(encoder_context); 454 | if (res != ICER_RESULT_OK) return res; 455 | } 456 | return ICER_RESULT_OK; 457 | } 458 | #endif 459 | 460 | #ifdef USE_DECODE_FUNCTIONS 461 | int icer_decompress_bitplane_uint16(uint16_t * const data, size_t plane_w, size_t plane_h, size_t rowstride, 462 | icer_context_model_typedef *context_model, 463 | icer_decoder_context_typedef *decoder_context, 464 | const icer_packet_context *pkt_context) { 465 | int res; 466 | uint16_t *pos; 467 | uint16_t *rowstart = data; 468 | int category; 469 | uint8_t bit; 470 | uint8_t lsb = pkt_context->lsb; 471 | 472 | uint16_t *h0, *h1, *v0, *v1, *d0, *d1, *d2, *d3; 473 | uint8_t h = 0, v = 0, d = 0, tmp; 474 | int8_t sh0, sh1, sv0, sv1; 475 | uint8_t sh, sv; 476 | uint8_t pred_sign, agreement_bit; 477 | uint16_t actual_sign; 478 | enum icer_pixel_contexts sign_context; 479 | size_t vert_bound = plane_h - 1; 480 | size_t hor_bound = plane_w - 1; 481 | 482 | uint8_t prev_plane = lsb+1; 483 | if (prev_plane >= 16) return ICER_BITPLANE_OUT_OF_RANGE; 484 | 485 | for (size_t row = 0; row < plane_h; row++) { 486 | pos = rowstart; 487 | /* keep track of 8 adjacent pixels */ 488 | h0 = pos - 1; h1 = pos + 1; 489 | v0 = pos - rowstride; v1 = pos + rowstride; 490 | d0 = v0 - 1; d1 = v0 + 1; 491 | d2 = v1 - 1; d3 = v1 + 1; 492 | 493 | enum icer_pixel_contexts cntxt = 0; 494 | 495 | for (size_t col = 0; col < plane_w; col++) { 496 | category = get_bit_category_uint16(pos, lsb); 497 | 498 | if (category == ICER_CATEGORY_3) { 499 | /* pass to uncoded bin */ 500 | res = icer_decode_bit(decoder_context, &bit, 1, 2); 501 | if (res != ICER_RESULT_OK) return res; 502 | (*pos) |= (uint16_t)bit << lsb; 503 | } else { 504 | if (category == ICER_CATEGORY_0 || category == ICER_CATEGORY_1) { 505 | h = 0; 506 | v = 0; 507 | d = 0; 508 | 509 | /* consider the horizontally adjacent pixels */ 510 | if (col > 0) h += get_bit_significance_uint16(h0, lsb) & 1; 511 | if (col < hor_bound) h += get_bit_significance_uint16(h1, prev_plane) & 1; 512 | 513 | /* consider the vertically adjacent pixels */ 514 | if (row > 0) v += get_bit_significance_uint16(v0, lsb) & 1; 515 | if (row < vert_bound) v += get_bit_significance_uint16(v1, prev_plane) & 1; 516 | 517 | /* consider the diagonally adjacent pixels */ 518 | if (col > 0 && row > 0) d += get_bit_significance_uint16(d0, lsb) & 1; 519 | if (col > 0 && row < vert_bound) d += get_bit_significance_uint16(d2, prev_plane) & 1; 520 | if (col < hor_bound && row > 0) d += get_bit_significance_uint16(d1, lsb) & 1; 521 | if (col < hor_bound && row < vert_bound) d += get_bit_significance_uint16(d3, prev_plane) & 1; 522 | } 523 | 524 | if (category == ICER_CATEGORY_0) { 525 | if (context_model->subband_type == ICER_SUBBAND_HL) { 526 | tmp = h; 527 | h = v; 528 | v = tmp; 529 | } 530 | 531 | if (context_model->subband_type != ICER_SUBBAND_HH) { 532 | cntxt = icer_context_table_ll_lh_hl[h][v][d]; 533 | } else { 534 | cntxt = icer_context_table_hh[h + v][d]; 535 | } 536 | } else if (category == ICER_CATEGORY_1) { 537 | cntxt = (h + v == 0) ? ICER_CONTEXT_9 : ICER_CONTEXT_10; 538 | } else if (category == ICER_CATEGORY_2) { 539 | cntxt = ICER_CONTEXT_11; 540 | } 541 | 542 | res = icer_decode_bit(decoder_context, &bit, context_model->zero_count[cntxt], context_model->total_count[cntxt]); 543 | if (res != ICER_RESULT_OK) return res; 544 | (*pos) |= (uint16_t)bit << lsb; 545 | 546 | context_model->total_count[cntxt]++; 547 | context_model->zero_count[cntxt] += (uint32_t)(!bit); 548 | if (context_model->total_count[cntxt] >= ICER_CONTEXT_RESCALING_CAP) { 549 | context_model->total_count[cntxt] >>= 1; 550 | if (context_model->zero_count[cntxt] > context_model->total_count[cntxt]) context_model->zero_count[cntxt] >>= 1; 551 | else icer_ceil_div_uint32(context_model->zero_count[cntxt], 2); 552 | } 553 | 554 | if (category == ICER_CATEGORY_0 && bit) { 555 | /* bit is the first magnitude bit to be encoded, thus we will encode the sign bit */ 556 | /* predict sign bit */ 557 | sh0 = 0; sh1 = 0; 558 | sv0 = 0; sv1 = 0; 559 | 560 | /* consider the horizontally adjacent pixels */ 561 | if (col > 0) sh0 = get_sign_uint16(h0, lsb); 562 | if (col < hor_bound) sh1 = get_sign_uint16(h1, prev_plane); 563 | 564 | /* consider the vertically adjacent pixels */ 565 | if (row > 0) sv0 = get_sign_uint16(v0, lsb); 566 | if (row < vert_bound) sv1 = get_sign_uint16(v1, prev_plane); 567 | 568 | sh = sh0 + sh1 + 2; 569 | sv = sv0 + sv1 + 2; 570 | 571 | if (context_model->subband_type == ICER_SUBBAND_HL) { 572 | tmp = sh; 573 | sh = sv; 574 | sv = tmp; 575 | } 576 | 577 | sign_context = icer_sign_context_table[sh][sv]; 578 | pred_sign = icer_sign_prediction_table[sh][sv]; 579 | 580 | res = icer_decode_bit(decoder_context, &agreement_bit, context_model->zero_count[sign_context], context_model->total_count[sign_context]); 581 | if (res != ICER_RESULT_OK) return res; 582 | actual_sign = (agreement_bit ^ pred_sign) & 1; 583 | (*pos) |= actual_sign << 15; 584 | 585 | context_model->total_count[sign_context]++; 586 | context_model->zero_count[sign_context] += (uint32_t)(agreement_bit == 0); 587 | if (context_model->total_count[sign_context] >= ICER_CONTEXT_RESCALING_CAP) { 588 | context_model->total_count[sign_context] >>= 1; 589 | if (context_model->zero_count[sign_context] > context_model->total_count[sign_context]) context_model->zero_count[sign_context] >>= 1; 590 | else icer_ceil_div_uint32(context_model->zero_count[sign_context], 2); 591 | } 592 | } 593 | } 594 | 595 | pos++; 596 | /* increment position pointers of 8 adjacent pixels */ 597 | h0++; h1++; v0++; v1++; d0++; d1++; d2++; d3++; 598 | } 599 | rowstart += rowstride; 600 | } 601 | return ICER_RESULT_OK; 602 | } 603 | #endif 604 | #endif 605 | 606 | 607 | void icer_init_context_model_vals(icer_context_model_typedef* context_model, enum icer_subband_types subband_type) { 608 | context_model->subband_type = subband_type; 609 | for (size_t i = 0;i <= ICER_CONTEXT_MAX;i++) { 610 | context_model->zero_count[i] = ICER_DEFAULT_CONTEXT_ZERO_COUNT; 611 | context_model->total_count[i] = ICER_DEFAULT_CONTEXT_TOTAL_COUNT; 612 | } 613 | } 614 | 615 | #ifdef USE_UINT8_FUNCTIONS 616 | static inline uint8_t get_bit_category_uint8(const uint8_t* data, uint8_t lsb) { 617 | int msb = 32 - (__builtin_clz(((*data) & 0x7f) | 0b1)) - 1; 618 | return icer_min_int((msb < lsb) ? 0 : msb - lsb, 3); 619 | } 620 | 621 | static inline bool get_bit_significance_uint8(const uint8_t* data, uint8_t lsb) { 622 | return __builtin_popcount(((*data) & 0x7f) >> lsb) != 0; 623 | } 624 | 625 | static inline int8_t get_sign_uint8(const uint8_t* data, uint8_t lsb) { 626 | return ((int8_t)(*data) >> 7) * (int8_t)get_bit_significance_uint8(data, lsb); 627 | } 628 | #endif 629 | 630 | #ifdef USE_UINT16_FUNCTIONS 631 | static inline uint8_t get_bit_category_uint16(const uint16_t* data, uint8_t lsb) { 632 | int msb = 32 - (__builtin_clz(((*data) & 0x7fff) | 0b1)) - 1; 633 | return icer_min_int((msb < lsb) ? 0 : msb - lsb, 3); 634 | } 635 | 636 | static inline bool get_bit_significance_uint16(const uint16_t* data, uint8_t lsb) { 637 | return __builtin_popcount(((*data) & 0x7fff) >> lsb) != 0; 638 | } 639 | 640 | static inline int8_t get_sign_uint16(const uint16_t* data, uint8_t lsb) { 641 | return ((int16_t)(*data) >> 15) * (int8_t)get_bit_significance_uint16(data, lsb); 642 | } 643 | #endif 644 | -------------------------------------------------------------------------------- /lib_icer/src/icer_decoding.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 19/3/2023. 3 | // 4 | 5 | #include 6 | #include "icer.h" 7 | 8 | #ifdef USE_DECODE_FUNCTIONS 9 | 10 | #define ICER_BITMASK_MACRO(x) (((unsigned)1 << x) - 1) 11 | 12 | void icer_init_entropy_decoder_context(icer_decoder_context_typedef *decoder_context, uint8_t *encoded_words, size_t encoded_bits) { 13 | decoder_context->encoded_bits_total = encoded_bits; 14 | decoder_context->decoded_bits_total = 0; 15 | decoder_context->decoded_words = 0; 16 | 17 | decoder_context->encoded_words = encoded_words; 18 | decoder_context->encode_bit_offset = 0; 19 | decoder_context->encode_ind = 0; 20 | 21 | for (size_t it = 0;it < ICER_ENCODER_BIN_MAX+1;it++) { 22 | decoder_context->bin_bits[it] = 0; 23 | decoder_context->bin_decode_index[it] = 0; 24 | for (size_t j = 0;j < ICER_DECODER_BIT_BIN_MAX;j++) decoder_context->bin_buf[it][j] = 0; 25 | } 26 | } 27 | 28 | void icer_push_bin_bits(icer_decoder_context_typedef *decoder_context, uint8_t bin, uint16_t bits, uint16_t num_bits) { 29 | int32_t bin_ind, bin_bit_offset; 30 | bin_ind = decoder_context->bin_bits[bin] / 32; 31 | bin_bit_offset = decoder_context->bin_bits[bin] % 32; 32 | decoder_context->bin_bits[bin] += num_bits; 33 | 34 | int bits_to_push; 35 | while (num_bits) { 36 | bits_to_push = icer_min_int(num_bits, 32-bin_bit_offset); 37 | decoder_context->bin_buf[bin][bin_ind] |= ((bits & ICER_BITMASK_MACRO(bits_to_push)) << bin_bit_offset); 38 | num_bits -= bits_to_push; 39 | 40 | bin_bit_offset += bits_to_push; 41 | bin_ind += bin_bit_offset / 32; 42 | bin_bit_offset %= 32; 43 | } 44 | } 45 | 46 | int icer_get_bit_from_codeword(icer_decoder_context_typedef *decoder_context, uint8_t bits) { 47 | uint8_t bitoffset = decoder_context->encode_bit_offset; 48 | size_t ind = decoder_context->encode_ind; 49 | uint16_t d, r; 50 | bitoffset += (bits - 1); 51 | r = bitoffset / 8; 52 | d = bitoffset % 8; 53 | ind += r; 54 | bitoffset = d; 55 | 56 | return (decoder_context->encoded_words[ind] & (1 << bitoffset)) >> bitoffset; 57 | } 58 | 59 | int icer_get_bits_from_codeword(icer_decoder_context_typedef *decoder_context, uint8_t bits) { 60 | int num = 0; 61 | int bits_to_decode, decoded = 0; 62 | uint8_t bitoffset = decoder_context->encode_bit_offset; 63 | size_t ind = decoder_context->encode_ind; 64 | uint16_t d, r; 65 | while (bits) { 66 | bits_to_decode = icer_min_int(8-bitoffset, bits); 67 | if (decoder_context->decoded_bits_total + bits_to_decode > decoder_context->encoded_bits_total) { 68 | return ICER_DECODER_OUT_OF_DATA; 69 | } 70 | num |= (int)((((decoder_context->encoded_words[ind] & (ICER_BITMASK_MACRO(bits_to_decode)) << bitoffset)) >> bitoffset) << decoded); 71 | bits -= bits_to_decode; 72 | decoded += bits_to_decode; 73 | bitoffset += bits_to_decode; 74 | r = bitoffset / 8; 75 | d = bitoffset % 8; 76 | bitoffset = d; 77 | if (r) { 78 | ind++; 79 | } 80 | } 81 | return num; 82 | } 83 | 84 | int icer_pop_bits_from_codeword(icer_decoder_context_typedef *decoder_context, uint8_t bits) { 85 | int num = 0; 86 | int bits_to_decode, decoded = 0; 87 | uint16_t d, r; 88 | while (bits) { 89 | bits_to_decode = icer_min_int(8-decoder_context->encode_bit_offset, bits); 90 | if (decoder_context->decoded_bits_total + bits_to_decode > decoder_context->encoded_bits_total) { 91 | return ICER_DECODER_OUT_OF_DATA; 92 | } 93 | num |= (int)(((decoder_context->encoded_words[decoder_context->encode_ind] & (ICER_BITMASK_MACRO(bits_to_decode) << decoder_context->encode_bit_offset)) >> decoder_context->encode_bit_offset) << decoded); 94 | bits -= bits_to_decode; 95 | decoded += bits_to_decode; 96 | decoder_context->encode_bit_offset += bits_to_decode; 97 | r = decoder_context->encode_bit_offset / 8; 98 | d = decoder_context->encode_bit_offset % 8; 99 | decoder_context->encode_bit_offset = d; 100 | if (r) { 101 | decoder_context->encode_ind++; 102 | } 103 | } 104 | return num; 105 | } 106 | 107 | 108 | int icer_decode_bit(icer_decoder_context_typedef *decoder_context, uint8_t *bit, uint32_t zero_cnt, uint32_t total_cnt) { 109 | bool inv = false, b; 110 | int code_bit; 111 | uint16_t codeword; 112 | uint8_t num_bits; 113 | uint16_t golomb_k; 114 | if (zero_cnt < (total_cnt >> 1)) { 115 | /* 116 | * we may assume that the probability of zero for each bit is contained 117 | * the interval [1/2, 1] 118 | * in the case that the probability of zero < 1/2 119 | * we simple invert the bit, and its associated probability 120 | * this is duplicated in the decoder 121 | */ 122 | zero_cnt = total_cnt - zero_cnt; 123 | inv = true; 124 | } 125 | 126 | int bin = icer_compute_bin(zero_cnt, total_cnt); 127 | 128 | if (decoder_context->bin_bits[bin] <= 0 || decoder_context->decoded_words - decoder_context->bin_decode_index[bin] >= ICER_CIRC_BUF_SIZE) { 129 | /* ran out of bits in the bit, time to process a new codeword */ 130 | decoder_context->bin_bits[bin] = 0; 131 | memset(decoder_context->bin_buf[bin], 0, ICER_DECODER_BIT_BIN_MAX*sizeof(decoder_context->bin_buf[bin][0])); 132 | if (bin > ICER_ENC_BIN_8) { 133 | /* golomb code bins */ 134 | code_bit = icer_get_bit_from_codeword(decoder_context, 1); 135 | if (code_bit == ICER_DECODER_OUT_OF_DATA) return ICER_DECODER_OUT_OF_DATA; //major oops moment 136 | if (code_bit) { 137 | /* if the first bit is one, return m 0s */ 138 | icer_pop_bits_from_codeword(decoder_context, 1); 139 | icer_push_bin_bits(decoder_context, bin, 0b0, icer_golomb_coders[bin].m); 140 | } else { 141 | golomb_k = icer_get_bits_from_codeword(decoder_context, icer_golomb_coders[bin].l); 142 | icer_reverse_bits(&golomb_k, icer_golomb_coders[bin].l); 143 | if (golomb_k < icer_golomb_coders[bin].i) { 144 | icer_pop_bits_from_codeword(decoder_context, icer_golomb_coders[bin].l); 145 | icer_push_bin_bits(decoder_context, bin, 0b1, 1); 146 | icer_push_bin_bits(decoder_context, bin, 0b0, golomb_k); 147 | } else { 148 | golomb_k = icer_pop_bits_from_codeword(decoder_context, icer_golomb_coders[bin].l + 1); 149 | icer_reverse_bits(&golomb_k, icer_golomb_coders[bin].l + 1); 150 | icer_push_bin_bits(decoder_context, bin, 0b1, 1); 151 | icer_push_bin_bits(decoder_context, bin, 0b0, golomb_k - icer_golomb_coders[bin].i); 152 | } 153 | } 154 | } else if (bin != ICER_ENC_BIN_1) { 155 | /* custom non prefix code bins */ 156 | codeword = 0; 157 | num_bits = 0; 158 | do { 159 | if (decoder_context->decoded_bits_total + num_bits + 1 >= decoder_context->encoded_bits_total) return ICER_DECODER_OUT_OF_DATA; 160 | codeword |= icer_get_bit_from_codeword(decoder_context, num_bits+1) << num_bits; 161 | num_bits++; 162 | if (codeword < 32) { 163 | if (icer_custom_decode_scheme[bin][codeword].input_code_bits == num_bits) { 164 | icer_push_bin_bits(decoder_context, bin, icer_custom_decode_scheme[bin][codeword].output_code, icer_custom_decode_scheme[bin][codeword].output_code_bits); 165 | int test = icer_pop_bits_from_codeword(decoder_context, num_bits); 166 | if (codeword != test) { 167 | return ICER_DECODED_INVALID_DATA; 168 | } else { 169 | break; 170 | } 171 | } 172 | } else { 173 | return ICER_DECODED_INVALID_DATA; 174 | } 175 | } while (num_bits < 10); 176 | } else { 177 | /* uncoded bin */ 178 | code_bit = icer_pop_bits_from_codeword(decoder_context, 1); 179 | if (code_bit == ICER_DECODER_OUT_OF_DATA) return ICER_DECODER_OUT_OF_DATA; 180 | icer_push_bin_bits(decoder_context, bin, code_bit != 0, 1); 181 | } 182 | 183 | decoder_context->decoded_words++; 184 | decoder_context->bin_decode_index[bin] = decoder_context->decoded_words; 185 | } 186 | int32_t bin_ind = decoder_context->bin_bits[bin] / 32; 187 | int32_t bit_offset = decoder_context->bin_bits[bin] % 32; 188 | b = (decoder_context->bin_buf[bin][bin_ind] & (1 << (bit_offset-1))) != 0; 189 | decoder_context->bin_buf[bin][bin_ind] &= ~(1 << (bit_offset-1)); 190 | decoder_context->bin_bits[bin]--; 191 | (*bit) = inv == !b; 192 | 193 | return ICER_RESULT_OK; 194 | } 195 | 196 | #endif -------------------------------------------------------------------------------- /lib_icer/src/icer_encoding.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 19/3/2023. 3 | // 4 | 5 | #include "icer.h" 6 | 7 | #ifdef USE_ENCODE_FUNCTIONS 8 | #ifndef USER_PROVIDED_BUFFERS 9 | uint16_t icer_encode_circ_buf[ICER_CIRC_BUF_SIZE]; 10 | #endif 11 | 12 | static inline uint16_t pop_buf(icer_encoder_context_typedef *cntxt); 13 | static inline int16_t alloc_buf(icer_encoder_context_typedef *cntxt); 14 | 15 | void icer_init_entropy_coder_context(icer_encoder_context_typedef *encoder_context, uint16_t *encode_buffer, size_t buffer_length, uint8_t *encoder_out, size_t enc_out_max) { 16 | encoder_context->max_output_length = enc_out_max; 17 | encoder_context->output_buffer = encoder_out; 18 | 19 | encoder_context->buffer_length = buffer_length; 20 | encoder_context->encode_buffer = encode_buffer; 21 | 22 | encoder_context->head = 0; 23 | encoder_context->tail = 0; 24 | encoder_context->used = 0; 25 | 26 | for (size_t it = 0;it < ICER_ENCODER_BIN_MAX+1;it++) { 27 | encoder_context->bin_current_buf[it] = -1; 28 | encoder_context->bin_current_buf_bits[it] = 0; 29 | } 30 | 31 | encoder_context->output_ind = 0; 32 | encoder_context->output_bit_offset = 0; 33 | encoder_context->output_buffer[encoder_context->output_ind] = 0; 34 | } 35 | 36 | 37 | int icer_encode_bit(icer_encoder_context_typedef *encoder_context, uint8_t bit, uint32_t zero_cnt, uint32_t total_cnt) { 38 | 39 | uint16_t *curr_bin; 40 | if (zero_cnt < (total_cnt >> 1)) { 41 | /* 42 | * we may assume that the probability of zero for each bit is contained 43 | * the interval [1/2, 1] 44 | * in the case that the probability of zero < 1/2 45 | * we simple invert the bit, and its associated probability 46 | * this is duplicated in the decoder 47 | */ 48 | zero_cnt = total_cnt - zero_cnt; 49 | bit = bit ^ 0b1; 50 | } 51 | 52 | int bin = icer_compute_bin(zero_cnt, total_cnt); 53 | uint16_t prefix; 54 | uint16_t golomb_k; 55 | uint16_t golomb_out_code; 56 | uint8_t golomb_out_bits; 57 | uint16_t bit16 = (bit != 0); 58 | 59 | if (encoder_context->bin_current_buf[bin] == -1) { 60 | encoder_context->bin_current_buf[bin] = alloc_buf(encoder_context); 61 | if (encoder_context->bin_current_buf[bin] == -1) { 62 | if (icer_flush_encode(encoder_context) == ICER_BYTE_QUOTA_EXCEEDED) return ICER_BYTE_QUOTA_EXCEEDED; 63 | else encoder_context->bin_current_buf[bin] = alloc_buf(encoder_context); 64 | } 65 | curr_bin = encoder_context->encode_buffer + encoder_context->bin_current_buf[bin]; 66 | (*curr_bin) = bin << ICER_ENC_BUF_BITS_OFFSET; 67 | } else curr_bin = encoder_context->encode_buffer + encoder_context->bin_current_buf[bin]; 68 | 69 | if (bin > ICER_ENC_BIN_8) { 70 | /* golomb code bins */ 71 | if (!bit16) (*curr_bin)++; 72 | if (bit16) { 73 | golomb_k = (*curr_bin) & ICER_ENC_BUF_DATA_MASK; 74 | golomb_out_code = golomb_k + ((golomb_k < icer_golomb_coders[bin].i) ? 0 : icer_golomb_coders[bin].i); 75 | golomb_out_bits = icer_golomb_coders[bin].l + (golomb_k >= icer_golomb_coders[bin].i); 76 | icer_reverse_bits(&golomb_out_code, golomb_out_bits); 77 | (*curr_bin) = (golomb_out_bits << ICER_ENC_BUF_BITS_OFFSET); 78 | (*curr_bin) |= (golomb_out_code & ICER_ENC_BUF_DATA_MASK); 79 | (*curr_bin) |= ICER_ENC_BUF_DONE_MASK; 80 | encoder_context->bin_current_buf[bin] = -1; 81 | } else if (((*curr_bin) & ICER_ENC_BUF_DATA_MASK) >= icer_golomb_coders[bin].m) { 82 | (*curr_bin) = 1 << ICER_ENC_BUF_BITS_OFFSET; 83 | (*curr_bin) |= 1; 84 | (*curr_bin) |= ICER_ENC_BUF_DONE_MASK; 85 | encoder_context->bin_current_buf[bin] = -1; 86 | } 87 | } else if (bin != ICER_ENC_BIN_1) { 88 | /* custom non prefix code bins */ 89 | (*curr_bin) |= (bit16 << encoder_context->bin_current_buf_bits[bin]); 90 | encoder_context->bin_current_buf_bits[bin]++; 91 | prefix = (*curr_bin) & ICER_ENC_BUF_DATA_MASK; 92 | if (icer_custom_coding_scheme[bin][prefix].input_code_bits == encoder_context->bin_current_buf_bits[bin]) { 93 | (*curr_bin) = icer_custom_coding_scheme[bin][prefix].output_code_bits << ICER_ENC_BUF_BITS_OFFSET; 94 | (*curr_bin) |= icer_custom_coding_scheme[bin][prefix].output_code & ICER_ENC_BUF_DATA_MASK; 95 | (*curr_bin) |= ICER_ENC_BUF_DONE_MASK; 96 | encoder_context->bin_current_buf[bin] = -1; 97 | encoder_context->bin_current_buf_bits[bin] = 0; 98 | } 99 | 100 | } else { 101 | /* uncoded bin */ 102 | (*curr_bin) = bit16 & 0b1; 103 | (*curr_bin) |= (1 << ICER_ENC_BUF_BITS_OFFSET); 104 | (*curr_bin) |= ICER_ENC_BUF_DONE_MASK; 105 | encoder_context->bin_current_buf[bin] = -1; 106 | } 107 | 108 | if (icer_popbuf_while_avail(encoder_context) == ICER_BYTE_QUOTA_EXCEEDED) { 109 | return ICER_BYTE_QUOTA_EXCEEDED; 110 | } 111 | return ICER_RESULT_OK; 112 | } 113 | 114 | int icer_popbuf_while_avail(icer_encoder_context_typedef *encoder_context) { 115 | uint16_t out, bits; 116 | uint16_t d, r; 117 | int bits_to_encode; 118 | while (encoder_context->used > 0 && (encoder_context->encode_buffer[encoder_context->head] & ICER_ENC_BUF_DONE_MASK)) { 119 | out = pop_buf(encoder_context); 120 | bits = out >> ICER_ENC_BUF_BITS_OFFSET; 121 | while (bits) { 122 | bits_to_encode = icer_min_int(8-encoder_context->output_bit_offset, bits); 123 | encoder_context->output_buffer[encoder_context->output_ind] |= (out & ((1 << bits_to_encode) - 1)) << (encoder_context->output_bit_offset); 124 | out >>= bits_to_encode; 125 | bits -= bits_to_encode; 126 | r = (encoder_context->output_bit_offset + bits_to_encode) / 8; 127 | d = (encoder_context->output_bit_offset + bits_to_encode) % 8; 128 | encoder_context->output_bit_offset = d; 129 | if (r) { 130 | encoder_context->output_ind += r; 131 | encoder_context->output_buffer[encoder_context->output_ind] = 0; 132 | } 133 | if (encoder_context->output_ind == encoder_context->max_output_length) { 134 | return ICER_BYTE_QUOTA_EXCEEDED; 135 | } 136 | } 137 | } 138 | return ICER_RESULT_OK; 139 | } 140 | 141 | int icer_flush_encode(icer_encoder_context_typedef *encoder_context) { 142 | uint16_t *first = encoder_context->encode_buffer + encoder_context->head; 143 | icer_custom_flush_typedef *flush; 144 | uint16_t prefix; 145 | if (((*first) & ICER_ENC_BUF_DONE_MASK) == 0) { 146 | uint8_t bin = (*first) >> ICER_ENC_BUF_BITS_OFFSET; 147 | 148 | uint16_t golomb_k; 149 | uint16_t golomb_out_code; 150 | uint8_t golomb_out_bits; 151 | 152 | if (bin > ICER_ENC_BIN_8) { 153 | /* golomb code bins */ 154 | golomb_k = (*first) & ICER_ENC_BUF_DATA_MASK; 155 | if (golomb_k == icer_golomb_coders[bin].m - 1) { 156 | *first = 1 << ICER_ENC_BUF_BITS_OFFSET; 157 | *first |= 1; 158 | *first |= ICER_ENC_BUF_DONE_MASK; 159 | } else { 160 | golomb_out_code = golomb_k + ((golomb_k < icer_golomb_coders[bin].i) ? 0 : icer_golomb_coders[bin].i); 161 | golomb_out_bits = icer_golomb_coders[bin].l + (golomb_k >= icer_golomb_coders[bin].i); 162 | icer_reverse_bits(&golomb_out_code, golomb_out_bits); 163 | *first = (golomb_out_bits << ICER_ENC_BUF_BITS_OFFSET); 164 | *first |= (golomb_out_code & ICER_ENC_BUF_DATA_MASK); 165 | *first |= ICER_ENC_BUF_DONE_MASK; 166 | } 167 | encoder_context->bin_current_buf[bin] = -1; 168 | } else if (bin != ICER_ENC_BIN_1) { 169 | /* custom non prefix code bins */ 170 | flush = &(icer_custom_code_flush_bits[bin][(*first) & ICER_ENC_BUF_DATA_MASK][encoder_context->bin_current_buf_bits[bin]]); 171 | (*first) |= flush->flush_bit << encoder_context->bin_current_buf_bits[bin]; 172 | encoder_context->bin_current_buf_bits[bin] += flush->flush_bit_numbers; 173 | 174 | prefix = (*first) & ICER_ENC_BUF_DATA_MASK; 175 | 176 | (*first) = icer_custom_coding_scheme[bin][prefix].output_code_bits << ICER_ENC_BUF_BITS_OFFSET; 177 | (*first) |= icer_custom_coding_scheme[bin][prefix].output_code & ICER_ENC_BUF_DATA_MASK; 178 | (*first) |= ICER_ENC_BUF_DONE_MASK; 179 | encoder_context->bin_current_buf[bin] = -1; 180 | encoder_context->bin_current_buf_bits[bin] = 0; 181 | } else { 182 | /* uncoded bin */ 183 | // this should never happen? 184 | } 185 | } 186 | 187 | if (icer_popbuf_while_avail(encoder_context) == ICER_BYTE_QUOTA_EXCEEDED) return ICER_BYTE_QUOTA_EXCEEDED; 188 | return ICER_RESULT_OK; 189 | } 190 | 191 | /* circular buffer helper functions */ 192 | 193 | static inline uint16_t pop_buf(icer_encoder_context_typedef *cntxt) { 194 | if (cntxt->used > 0) cntxt->used--; 195 | uint16_t res = cntxt->encode_buffer[cntxt->head]; 196 | cntxt->head = (cntxt->head + 1) % cntxt->buffer_length; 197 | return res; 198 | } 199 | 200 | static inline int16_t alloc_buf(icer_encoder_context_typedef *cntxt) { 201 | if (cntxt->used >= cntxt->buffer_length) return -1; 202 | cntxt->used++; 203 | int16_t ind = (int16_t)cntxt->tail; 204 | cntxt->tail = (cntxt->tail+1) % cntxt->buffer_length; 205 | return ind; 206 | } 207 | 208 | /* data packet functions */ 209 | 210 | int icer_allocate_data_packet(icer_image_segment_typedef **pkt, icer_output_data_buf_typedef * const output_data, uint8_t segment_num, const icer_packet_context *context) { 211 | size_t buf_len = output_data->size_allocated - output_data->size_used; 212 | if (buf_len < sizeof(icer_image_segment_typedef)) { 213 | return ICER_BYTE_QUOTA_EXCEEDED; 214 | } 215 | (*pkt) = (icer_image_segment_typedef *) (output_data->data_start + output_data->size_used); 216 | (*pkt)->preamble = ICER_PACKET_PREAMBLE; 217 | (*pkt)->decomp_level = context->decomp_level; 218 | (*pkt)->subband_type = context->subband_type; 219 | (*pkt)->segment_number = segment_num; 220 | (*pkt)->lsb_chan = context->lsb | ICER_SET_CHANNEL_MACRO(context->channel); 221 | (*pkt)->ll_mean_val = context->ll_mean_val; 222 | (*pkt)->image_w = context->image_w; 223 | (*pkt)->image_h = context->image_h; 224 | (*pkt)->data_crc32 = 0; 225 | (*pkt)->crc32 = 0; 226 | 227 | output_data->size_used += sizeof(icer_image_segment_typedef); 228 | buf_len -= sizeof(icer_image_segment_typedef); 229 | 230 | // store max data length first 231 | (*pkt)->data_length = buf_len; 232 | 233 | return ICER_RESULT_OK; 234 | } 235 | 236 | #endif -------------------------------------------------------------------------------- /lib_icer/src/icer_init.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 19/3/2023. 3 | // 4 | 5 | #include "icer.h" 6 | 7 | #define INIT_CODING_SCHEME(bin, inp, inp_bits, out, out_bits) { \ 8 | icer_custom_coding_scheme[bin][inp].input_code_bits = inp_bits; \ 9 | icer_custom_coding_scheme[bin][inp].output_code = out; \ 10 | icer_custom_coding_scheme[bin][inp].output_code_bits = out_bits; \ 11 | } 12 | 13 | #define INIT_FLUSH_BITS(bin, inp, inp_bits, out, out_bits) { \ 14 | icer_custom_code_flush_bits[bin][inp][inp_bits].flush_bit = out; \ 15 | icer_custom_code_flush_bits[bin][inp][inp_bits].flush_bit_numbers = out_bits; \ 16 | } 17 | 18 | #define INIT_DECODE_SCHEME(bin, out, out_bits, inp, inp_bits) { \ 19 | icer_custom_decode_scheme[bin][inp].input_code_bits = inp_bits; \ 20 | icer_custom_decode_scheme[bin][inp].output_code = out; \ 21 | icer_custom_decode_scheme[bin][inp].output_code_bits = out_bits; \ 22 | } 23 | 24 | int icer_init() { 25 | icer_init_golombcoder(); 26 | #ifdef USE_ENCODE_FUNCTIONS 27 | icer_init_codingscheme(); 28 | #endif 29 | #ifdef USE_DECODE_FUNCTIONS 30 | icer_init_decodescheme(); 31 | #endif 32 | icer_init_flushbits(); 33 | 34 | return ICER_RESULT_OK; 35 | } 36 | 37 | #ifdef USE_DECODE_FUNCTIONS 38 | void icer_init_decodescheme() { 39 | for (int it = 0; it <= ICER_ENCODER_BIN_MAX; it++) { 40 | for (int j = 0; j < CUSTOM_CODING_MAX_LOOKUP; j++) { 41 | icer_custom_decode_scheme[it][j].input_code_bits = 0; 42 | icer_custom_decode_scheme[it][j].output_code_bits = 0; 43 | } 44 | } 45 | 46 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b01, 2, 0b10, 2); 47 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b011, 3, 0b011, 3); 48 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b0111, 4, 0b1111, 4); 49 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b1111, 4, 0b10000, 5); 50 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b10, 2, 0b01, 2); 51 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b100, 3, 0b100, 3); 52 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b1000, 4, 0b1000, 4); 53 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b10000, 5, 0b00000, 5); 54 | INIT_DECODE_SCHEME(ICER_ENC_BIN_2, 0b00000, 5, 0b0111, 4); 55 | 56 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b10, 2, 0b01, 2); 57 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b100, 3, 0b00, 2); 58 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b0000, 4, 0b011, 3); 59 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b11000, 5, 0b10010, 5); 60 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b01000, 5, 0b1111, 4); 61 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b01, 2, 0b110, 3); 62 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b0011, 4, 0b0111, 4); 63 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b1011, 4, 0b00010, 5); 64 | INIT_DECODE_SCHEME(ICER_ENC_BIN_3, 0b111, 3, 0b1010, 4); 65 | 66 | INIT_DECODE_SCHEME(ICER_ENC_BIN_4, 0b10, 2, 0b10, 2); 67 | INIT_DECODE_SCHEME(ICER_ENC_BIN_4, 0b100, 3, 0b011, 3); 68 | INIT_DECODE_SCHEME(ICER_ENC_BIN_4, 0b000, 3, 0b00, 2); 69 | INIT_DECODE_SCHEME(ICER_ENC_BIN_4, 0b01, 2, 0b01, 2); 70 | INIT_DECODE_SCHEME(ICER_ENC_BIN_4, 0b11, 2, 0b111, 3); 71 | 72 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b00, 2, 0b1, 1); 73 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b010, 3, 0b000, 3); 74 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b110, 3, 0b1010, 4); 75 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b101, 3, 0b0010, 4); 76 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b1001, 4, 0b1110, 4); 77 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b00001, 5, 0b0100, 4); 78 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b10001, 5, 0b00110, 5); 79 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b011, 3, 0b1100, 4); 80 | INIT_DECODE_SCHEME(ICER_ENC_BIN_5, 0b111, 3, 0b10110, 5); 81 | 82 | INIT_DECODE_SCHEME(ICER_ENC_BIN_6, 0b1, 1, 0b10, 2); 83 | INIT_DECODE_SCHEME(ICER_ENC_BIN_6, 0b010, 3, 0b011, 3); 84 | INIT_DECODE_SCHEME(ICER_ENC_BIN_6, 0b110, 3, 0b1111, 4); 85 | INIT_DECODE_SCHEME(ICER_ENC_BIN_6, 0b100, 3, 0b101, 3); 86 | INIT_DECODE_SCHEME(ICER_ENC_BIN_6, 0b1000, 4, 0b001, 3); 87 | INIT_DECODE_SCHEME(ICER_ENC_BIN_6, 0b10000, 5, 0b0111, 4); 88 | INIT_DECODE_SCHEME(ICER_ENC_BIN_6, 0b00000, 5, 0b00, 2); 89 | 90 | INIT_DECODE_SCHEME(ICER_ENC_BIN_7, 0b000, 3, 0b0, 1); 91 | INIT_DECODE_SCHEME(ICER_ENC_BIN_7, 0b100, 3, 0b001, 3); 92 | INIT_DECODE_SCHEME(ICER_ENC_BIN_7, 0b010, 3, 0b101, 3); 93 | INIT_DECODE_SCHEME(ICER_ENC_BIN_7, 0b110, 3, 0b01111, 5); 94 | INIT_DECODE_SCHEME(ICER_ENC_BIN_7, 0b11, 2, 0b0111, 4); 95 | INIT_DECODE_SCHEME(ICER_ENC_BIN_7, 0b001, 3, 0b011, 3); 96 | INIT_DECODE_SCHEME(ICER_ENC_BIN_7, 0b101, 3, 0b11111, 5); 97 | 98 | INIT_DECODE_SCHEME(ICER_ENC_BIN_8, 0b10, 2, 0b101, 3); 99 | INIT_DECODE_SCHEME(ICER_ENC_BIN_8, 0b100, 3, 0b001, 3); 100 | INIT_DECODE_SCHEME(ICER_ENC_BIN_8, 0b0000, 4, 0b0, 1); 101 | INIT_DECODE_SCHEME(ICER_ENC_BIN_8, 0b01000, 5, 0b0111, 4); 102 | INIT_DECODE_SCHEME(ICER_ENC_BIN_8, 0b11000, 5, 0b01111, 5); 103 | INIT_DECODE_SCHEME(ICER_ENC_BIN_8, 0b01, 2, 0b011, 3); 104 | INIT_DECODE_SCHEME(ICER_ENC_BIN_8, 0b11, 2, 0b11111, 5); 105 | 106 | 107 | for (int it = 0; it <= ICER_ENCODER_BIN_MAX; it++) { 108 | for (int j = 0; j < CUSTOM_CODING_MAX_LOOKUP; j++) { 109 | if (icer_custom_decode_scheme[it][j].output_code_bits != 0) { 110 | uint8_t reversed = 0; 111 | for (int b = 0; b < icer_custom_decode_scheme[it][j].output_code_bits; b++) { 112 | reversed <<= 1; 113 | reversed |= icer_custom_decode_scheme[it][j].output_code & 1; 114 | icer_custom_decode_scheme[it][j].output_code >>= 1; 115 | } 116 | icer_custom_decode_scheme[it][j].output_code = reversed; 117 | } 118 | } 119 | } 120 | } 121 | #endif 122 | 123 | #ifdef USE_ENCODE_FUNCTIONS 124 | void icer_init_codingscheme() { 125 | for (int it = 0; it <= ICER_ENCODER_BIN_MAX; it++) { 126 | for (int j = 0; j < CUSTOM_CODING_MAX_LOOKUP; j++) icer_custom_coding_scheme[it][j].input_code_bits = 0; 127 | } 128 | 129 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b01, 2, 0b10, 2); 130 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b011, 3, 0b011, 3); 131 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b0111, 4, 0b1111, 4); 132 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b1111, 4, 0b10000, 5); 133 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b10, 2, 0b01, 2); 134 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b100, 3, 0b100, 3); 135 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b1000, 4, 0b1000, 4); 136 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b10000, 5, 0b00000, 5); 137 | INIT_CODING_SCHEME(ICER_ENC_BIN_2, 0b00000, 5, 0b0111, 4); 138 | 139 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b10, 2, 0b01, 2); 140 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b100, 3, 0b00, 2); 141 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b0000, 4, 0b011, 3); 142 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b11000, 5, 0b10010, 5); 143 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b01000, 5, 0b1111, 4); 144 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b01, 2, 0b110, 3); 145 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b0011, 4, 0b0111, 4); 146 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b1011, 4, 0b00010, 5); 147 | INIT_CODING_SCHEME(ICER_ENC_BIN_3, 0b111, 3, 0b1010, 4); 148 | 149 | INIT_CODING_SCHEME(ICER_ENC_BIN_4, 0b10, 2, 0b10, 2); 150 | INIT_CODING_SCHEME(ICER_ENC_BIN_4, 0b100, 3, 0b011, 3); 151 | INIT_CODING_SCHEME(ICER_ENC_BIN_4, 0b000, 3, 0b00, 2); 152 | INIT_CODING_SCHEME(ICER_ENC_BIN_4, 0b01, 2, 0b01, 2); 153 | INIT_CODING_SCHEME(ICER_ENC_BIN_4, 0b11, 2, 0b111, 3); 154 | 155 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b00, 2, 0b1, 1); 156 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b010, 3, 0b000, 3); 157 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b110, 3, 0b1010, 4); 158 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b101, 3, 0b0010, 4); 159 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b1001, 4, 0b1110, 4); 160 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b00001, 5, 0b0100, 4); 161 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b10001, 5, 0b00110, 5); 162 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b011, 3, 0b1100, 4); 163 | INIT_CODING_SCHEME(ICER_ENC_BIN_5, 0b111, 3, 0b10110, 5); 164 | 165 | INIT_CODING_SCHEME(ICER_ENC_BIN_6, 0b1, 1, 0b10, 2); 166 | INIT_CODING_SCHEME(ICER_ENC_BIN_6, 0b010, 3, 0b011, 3); 167 | INIT_CODING_SCHEME(ICER_ENC_BIN_6, 0b110, 3, 0b1111, 4); 168 | INIT_CODING_SCHEME(ICER_ENC_BIN_6, 0b100, 3, 0b101, 3); 169 | INIT_CODING_SCHEME(ICER_ENC_BIN_6, 0b1000, 4, 0b001, 3); 170 | INIT_CODING_SCHEME(ICER_ENC_BIN_6, 0b10000, 5, 0b0111, 4); 171 | INIT_CODING_SCHEME(ICER_ENC_BIN_6, 0b00000, 5, 0b00, 2); 172 | 173 | INIT_CODING_SCHEME(ICER_ENC_BIN_7, 0b000, 3, 0b0, 1); 174 | INIT_CODING_SCHEME(ICER_ENC_BIN_7, 0b100, 3, 0b001, 3); 175 | INIT_CODING_SCHEME(ICER_ENC_BIN_7, 0b010, 3, 0b101, 3); 176 | INIT_CODING_SCHEME(ICER_ENC_BIN_7, 0b110, 3, 0b01111, 5); 177 | INIT_CODING_SCHEME(ICER_ENC_BIN_7, 0b11, 2, 0b0111, 4); 178 | INIT_CODING_SCHEME(ICER_ENC_BIN_7, 0b001, 3, 0b011, 3); 179 | INIT_CODING_SCHEME(ICER_ENC_BIN_7, 0b101, 3, 0b11111, 5); 180 | 181 | INIT_CODING_SCHEME(ICER_ENC_BIN_8, 0b10, 2, 0b101, 3); 182 | INIT_CODING_SCHEME(ICER_ENC_BIN_8, 0b100, 3, 0b001, 3); 183 | INIT_CODING_SCHEME(ICER_ENC_BIN_8, 0b0000, 4, 0b0, 1); 184 | INIT_CODING_SCHEME(ICER_ENC_BIN_8, 0b01000, 5, 0b0111, 4); 185 | INIT_CODING_SCHEME(ICER_ENC_BIN_8, 0b11000, 5, 0b01111, 5); 186 | INIT_CODING_SCHEME(ICER_ENC_BIN_8, 0b01, 2, 0b011, 3); 187 | INIT_CODING_SCHEME(ICER_ENC_BIN_8, 0b11, 2, 0b11111, 5); 188 | } 189 | #endif 190 | 191 | void icer_init_flushbits() { 192 | INIT_FLUSH_BITS(ICER_ENC_BIN_2, 0b1, 1, 0, 1); 193 | INIT_FLUSH_BITS(ICER_ENC_BIN_2, 0b11, 2, 0, 1); 194 | INIT_FLUSH_BITS(ICER_ENC_BIN_2, 0b111, 3, 0, 1); 195 | INIT_FLUSH_BITS(ICER_ENC_BIN_2, 0b0, 1, 1, 1); 196 | INIT_FLUSH_BITS(ICER_ENC_BIN_2, 0b00, 2, 1, 1); 197 | INIT_FLUSH_BITS(ICER_ENC_BIN_2, 0b000, 3, 1, 1); 198 | INIT_FLUSH_BITS(ICER_ENC_BIN_2, 0b0000, 4, 0, 1); 199 | 200 | INIT_FLUSH_BITS(ICER_ENC_BIN_3, 0b0, 1, 1, 1); 201 | INIT_FLUSH_BITS(ICER_ENC_BIN_3, 0b00, 2, 1, 1); 202 | INIT_FLUSH_BITS(ICER_ENC_BIN_3, 0b000, 3, 0, 1); 203 | INIT_FLUSH_BITS(ICER_ENC_BIN_3, 0b1000, 4, 0, 1); 204 | INIT_FLUSH_BITS(ICER_ENC_BIN_3, 0b1, 1, 0, 1); 205 | INIT_FLUSH_BITS(ICER_ENC_BIN_3, 0b11, 2, 1, 1); 206 | INIT_FLUSH_BITS(ICER_ENC_BIN_3, 0b011, 3, 0, 1); 207 | 208 | INIT_FLUSH_BITS(ICER_ENC_BIN_4, 0b0, 1, 1, 1); 209 | INIT_FLUSH_BITS(ICER_ENC_BIN_4, 0b00, 2, 0, 1); 210 | INIT_FLUSH_BITS(ICER_ENC_BIN_4, 0b1, 1, 0, 1); 211 | 212 | INIT_FLUSH_BITS(ICER_ENC_BIN_5, 0b0, 1, 0, 1); 213 | INIT_FLUSH_BITS(ICER_ENC_BIN_5, 0b10, 2, 0, 1); 214 | INIT_FLUSH_BITS(ICER_ENC_BIN_5, 0b01, 2, 1, 1); 215 | INIT_FLUSH_BITS(ICER_ENC_BIN_5, 0b001, 3, 1, 1); 216 | INIT_FLUSH_BITS(ICER_ENC_BIN_5, 0b0001, 4, 0, 1); 217 | INIT_FLUSH_BITS(ICER_ENC_BIN_5, 0b1, 1, 0b01, 2); 218 | INIT_FLUSH_BITS(ICER_ENC_BIN_5, 0b11, 2, 0, 1); 219 | 220 | INIT_FLUSH_BITS(ICER_ENC_BIN_6, 0b0, 1, 0b01, 2); 221 | INIT_FLUSH_BITS(ICER_ENC_BIN_6, 0b01, 2, 0, 1); 222 | INIT_FLUSH_BITS(ICER_ENC_BIN_6, 0b00, 2, 1, 1); 223 | INIT_FLUSH_BITS(ICER_ENC_BIN_6, 0b000, 3, 1, 1); 224 | INIT_FLUSH_BITS(ICER_ENC_BIN_6, 0b0000, 4, 0, 1); 225 | 226 | INIT_FLUSH_BITS(ICER_ENC_BIN_7, 0b0, 1, 0b00, 2); 227 | INIT_FLUSH_BITS(ICER_ENC_BIN_7, 0b00, 2, 0, 1); 228 | INIT_FLUSH_BITS(ICER_ENC_BIN_7, 0b10, 2, 0, 1); 229 | INIT_FLUSH_BITS(ICER_ENC_BIN_7, 0b1, 1, 1, 1); 230 | INIT_FLUSH_BITS(ICER_ENC_BIN_7, 0b01, 2, 0, 1); 231 | 232 | INIT_FLUSH_BITS(ICER_ENC_BIN_8, 0b0, 1, 1, 1); 233 | INIT_FLUSH_BITS(ICER_ENC_BIN_8, 0b00, 2, 1, 1); 234 | INIT_FLUSH_BITS(ICER_ENC_BIN_8, 0b000, 3, 0, 1); 235 | INIT_FLUSH_BITS(ICER_ENC_BIN_8, 0b1000, 4, 0, 1); 236 | INIT_FLUSH_BITS(ICER_ENC_BIN_8, 0b1, 1, 0, 1); 237 | } 238 | 239 | void icer_init_golombcoder() { 240 | for (int it = 0; it <= ICER_ENCODER_BIN_MAX; it++) { 241 | if (icer_bin_coding_scheme[it] > 0) { 242 | unsigned int m = icer_bin_coding_scheme[it]; 243 | icer_golomb_coders[it].m = m; 244 | 245 | // compute ceil( log2( m ) ) 246 | unsigned int l = 31 - __builtin_clz(m); 247 | l += ((m ^ (1 << l)) != 0); 248 | 249 | // compute 2^l - m 250 | unsigned int i = icer_pow_uint(2, l) - m; 251 | 252 | icer_golomb_coders[it].i = i; 253 | icer_golomb_coders[it].l = l; 254 | } 255 | } 256 | } -------------------------------------------------------------------------------- /lib_icer/src/icer_partition.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 19/3/2023. 3 | // 4 | 5 | #include "icer.h" 6 | 7 | int icer_generate_partition_parameters(partition_param_typdef *params, size_t ll_w, size_t ll_h, uint16_t segments) { 8 | uint16_t r, c, r_t, h_t, x_t, c_t0, y_t, r_t0; 9 | uint16_t x_b = 0, c_b0 = 0, y_b = 0, r_b0 = 0; 10 | 11 | if (segments > (ll_w * ll_h) || segments > ICER_MAX_SEGMENTS) { 12 | return ICER_TOO_MANY_SEGMENTS; 13 | } 14 | 15 | if (ll_h > (segments - 1) * ll_w) { 16 | r = segments; 17 | } else { 18 | for (r = 1; r < segments && (r + 1) * r * ll_w < ll_h * segments; r++); 19 | } 20 | c = segments / r; 21 | r_t = (c + 1) * r - segments; 22 | h_t = icer_max_uint(r_t, ((2 * ll_h * c * r_t + segments) / 2) / segments); 23 | x_t = ll_w / c; 24 | c_t0 = (x_t + 1) * c - ll_w; 25 | y_t = h_t / r_t; 26 | r_t0 = (y_t + 1) * r_t - h_t; 27 | 28 | if (r_t < r) { 29 | x_b = ll_w / (c + 1); 30 | c_b0 = (x_b + 1) * (c + 1) - ll_w; 31 | y_b = (ll_h - h_t) / (r - r_t); 32 | r_b0 = (y_b + 1) * (r - r_t) - (ll_h - h_t); 33 | } 34 | 35 | params->w = ll_w; 36 | params->h = ll_h; 37 | params->s = segments; 38 | 39 | params->r = r; 40 | params->c = c; 41 | params->r_t = r_t; 42 | params->h_t = h_t; 43 | params->x_t = x_t; 44 | params->c_t0 = c_t0; 45 | params->y_t = y_t; 46 | params->r_t0 = r_t0; 47 | 48 | params->x_b = x_b; 49 | params->c_b0 = c_b0; 50 | params->y_b = y_b; 51 | params->r_b0 = r_b0; 52 | 53 | return ICER_RESULT_OK; 54 | } 55 | 56 | #ifdef USE_UINT8_FUNCTIONS 57 | 58 | #ifdef USE_ENCODE_FUNCTIONS 59 | int icer_compress_partition_uint8(const uint8_t *data, partition_param_typdef *params, size_t rowstride, icer_packet_context *pkt_context, 60 | icer_output_data_buf_typedef * const output_data,icer_image_segment_typedef *segments_encoded[]) { 61 | int res; 62 | size_t segment_w, segment_h; 63 | const uint8_t *segment_start; 64 | uint16_t segment_num = 0; 65 | 66 | size_t partition_col_ind; 67 | size_t partition_row_ind = 0; 68 | 69 | icer_context_model_typedef context_model; 70 | icer_encoder_context_typedef context; 71 | icer_image_segment_typedef *seg; 72 | 73 | uint32_t data_in_bytes; 74 | /* 75 | * process top region which consists of c columns 76 | * height of top region is h_t and it contains r_t rows 77 | */ 78 | for (uint16_t row = 0; row < params->r_t; row++) { 79 | /* 80 | * the first r_t0 rows have height y_t 81 | * the remainder have height y_t + 1 82 | */ 83 | segment_h = params->y_t + ((row >= params->r_t0) ? 1 : 0); 84 | partition_col_ind = 0; 85 | 86 | for (uint16_t col = 0; col < params->c; col++) { 87 | /* the first c_t0 columns have width x_t 88 | * the remainder have width x_t + 1 89 | */ 90 | segment_w = params->x_t + ((col >= params->c_t0) ? 1 : 0); 91 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 92 | partition_col_ind += segment_w; 93 | 94 | icer_init_context_model_vals(&context_model, pkt_context->subband_type); 95 | res = icer_allocate_data_packet(&seg, output_data, segment_num, pkt_context); 96 | if (res != ICER_RESULT_OK) return res; 97 | 98 | icer_init_entropy_coder_context(&context, icer_encode_circ_buf, ICER_CIRC_BUF_SIZE, 99 | (uint8_t *) seg + sizeof(icer_image_segment_typedef), seg->data_length); 100 | res = icer_compress_bitplane_uint8(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 101 | pkt_context); 102 | if (res != ICER_RESULT_OK) { 103 | output_data->size_used -= sizeof(icer_image_segment_typedef); 104 | return res; 105 | } 106 | 107 | data_in_bytes = context.output_ind + (context.output_bit_offset > 0); 108 | seg->data_length = context.output_ind * 8 + context.output_bit_offset; 109 | seg->data_crc32 = icer_calculate_segment_crc32(seg); 110 | seg->crc32 = icer_calculate_packet_crc32(seg); 111 | output_data->size_used += data_in_bytes; 112 | 113 | segments_encoded[segment_num] = seg; 114 | 115 | segment_num++; 116 | } 117 | partition_row_ind += segment_h; 118 | } 119 | 120 | /* 121 | * if the bottom region exists, process bottom region 122 | * which consists of c+1 columns 123 | */ 124 | for (uint16_t row = 0; row < (params->r - params->r_t); row++) { 125 | /* 126 | * the first r_b0 rows have height y_b 127 | * the remainder have height y_b + 1 128 | */ 129 | segment_h = params->y_b + ((row >= params->r_b0) ? 1 : 0); 130 | partition_col_ind = 0; 131 | 132 | for (uint16_t col = 0; col < (params->c + 1); col++) { 133 | /* the first c_b0 columns have width x_b 134 | * the remainder have width x_b + 1 135 | */ 136 | segment_w = params->x_b + ((col >= params->c_b0) ? 1 : 0); 137 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 138 | partition_col_ind += segment_w; 139 | 140 | icer_init_context_model_vals(&context_model, pkt_context->subband_type); 141 | res = icer_allocate_data_packet(&seg, output_data, segment_num, pkt_context); 142 | if (res != ICER_RESULT_OK) return res; 143 | 144 | icer_init_entropy_coder_context(&context, icer_encode_circ_buf, ICER_CIRC_BUF_SIZE, 145 | (uint8_t *) seg + sizeof(icer_image_segment_typedef), seg->data_length); 146 | res = icer_compress_bitplane_uint8(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 147 | pkt_context); 148 | if (res != ICER_RESULT_OK) { 149 | output_data->size_used -= sizeof(icer_image_segment_typedef); 150 | return res; 151 | } 152 | 153 | data_in_bytes = context.output_ind + (context.output_bit_offset > 0); 154 | seg->data_length = context.output_ind * 8 + context.output_bit_offset; 155 | seg->data_crc32 = icer_calculate_segment_crc32(seg); 156 | seg->crc32 = icer_calculate_packet_crc32(seg); 157 | output_data->size_used += data_in_bytes; 158 | 159 | segments_encoded[segment_num] = seg; 160 | 161 | segment_num++; 162 | } 163 | partition_row_ind += segment_h; 164 | } 165 | 166 | return ICER_RESULT_OK; 167 | } 168 | #endif 169 | 170 | #ifdef USE_DECODE_FUNCTIONS 171 | int icer_decompress_partition_uint8(uint8_t * const data, const partition_param_typdef *params, size_t rowstride, 172 | icer_image_segment_typedef *seg[][7]) { 173 | int res; 174 | size_t segment_w, segment_h; 175 | uint8_t *segment_start; 176 | uint16_t segment_num = 0; 177 | 178 | size_t partition_col_ind; 179 | size_t partition_row_ind = 0; 180 | 181 | icer_context_model_typedef context_model; 182 | icer_decoder_context_typedef context; 183 | icer_packet_context pkt_context; 184 | int lsb; 185 | /* 186 | * process top region which consists of c columns 187 | * height of top region is h_t and it contains r_t rows 188 | */ 189 | for (uint16_t row = 0; row < params->r_t; row++) { 190 | /* 191 | * the first r_t0 rows have height y_t 192 | * the remainder have height y_t + 1 193 | */ 194 | segment_h = params->y_t + ((row >= params->r_t0) ? 1 : 0); 195 | partition_col_ind = 0; 196 | 197 | for (uint16_t col = 0; col < params->c; col++) { 198 | /* the first c_t0 columns have width x_t 199 | * the remainder have width x_t + 1 200 | */ 201 | segment_w = params->x_t + ((col >= params->c_t0) ? 1 : 0); 202 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 203 | partition_col_ind += segment_w; 204 | 205 | lsb = ICER_BITPLANES_TO_COMPRESS_8 - 1; 206 | /* decompress starting from the msb, and stop whenever there is a missing bitplane */ 207 | /* it is impossible to decompress subsequent bit planes if there is a missing bit plane, due to how the context 208 | * modeller works; it relies on the previously decoded bbitplanes to determine a bit's context */ 209 | while (seg[segment_num][lsb] != NULL && lsb >= 0) { 210 | pkt_context.subband_type = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_8 - 1]->subband_type; 211 | pkt_context.lsb = lsb; 212 | pkt_context.decomp_level = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_8 - 1]->decomp_level; 213 | icer_init_context_model_vals(&context_model, pkt_context.subband_type); 214 | icer_init_entropy_decoder_context(&context, (uint8_t *) seg[segment_num][lsb] + 215 | sizeof(icer_image_segment_typedef), 216 | seg[segment_num][lsb]->data_length); 217 | res = icer_decompress_bitplane_uint8(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 218 | &pkt_context); 219 | if (res != ICER_RESULT_OK) break; 220 | lsb--; 221 | } 222 | 223 | segment_num++; 224 | } 225 | partition_row_ind += segment_h; 226 | } 227 | 228 | /* 229 | * if the bottom region exists, process bottom region 230 | * which consists of c+1 columns 231 | */ 232 | for (uint16_t row = 0; row < (params->r - params->r_t); row++) { 233 | /* 234 | * the first r_b0 rows have height y_b 235 | * the remainder have height y_b + 1 236 | */ 237 | segment_h = params->y_b + ((row >= params->r_b0) ? 1 : 0); 238 | partition_col_ind = 0; 239 | 240 | for (uint16_t col = 0; col < (params->c + 1); col++) { 241 | /* the first c_b0 columns have width x_b 242 | * the remainder have width x_b + 1 243 | */ 244 | segment_w = params->x_b + ((col >= params->c_b0) ? 1 : 0); 245 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 246 | partition_col_ind += segment_w; 247 | 248 | lsb = ICER_BITPLANES_TO_COMPRESS_8 - 1; 249 | /* decompress starting from the msb, and stop whenever there is a missing bitplane */ 250 | /* it is impossible to decompress subsequent bit planes if there is a missing bit plane, due to how the context 251 | * modeller works; it relies on the previously decoded bbitplanes to determine a bit's context */ 252 | while (seg[segment_num][lsb] != NULL && lsb >= 0) { 253 | pkt_context.subband_type = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_8 - 1]->subband_type; 254 | pkt_context.lsb = lsb; 255 | pkt_context.decomp_level = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_8 - 1]->decomp_level; 256 | icer_init_context_model_vals(&context_model, pkt_context.subband_type); 257 | icer_init_entropy_decoder_context(&context, (uint8_t *) seg[segment_num][lsb] + 258 | sizeof(icer_image_segment_typedef), 259 | seg[segment_num][lsb]->data_length); 260 | res = icer_decompress_bitplane_uint8(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 261 | &pkt_context); 262 | if (res != ICER_RESULT_OK) break; 263 | lsb--; 264 | } 265 | 266 | segment_num++; 267 | } 268 | partition_row_ind += segment_h; 269 | } 270 | 271 | return ICER_RESULT_OK; 272 | } 273 | #endif 274 | #endif 275 | 276 | #ifdef USE_UINT16_FUNCTIONS 277 | 278 | #ifdef USE_ENCODE_FUNCTIONS 279 | int icer_compress_partition_uint16(const uint16_t *data, const partition_param_typdef *params, size_t rowstride, 280 | const icer_packet_context *pkt_context, icer_output_data_buf_typedef *output_data, 281 | icer_image_segment_typedef *segments_encoded[]) { 282 | int res; 283 | size_t segment_w, segment_h; 284 | const uint16_t *segment_start; 285 | uint16_t segment_num = 0; 286 | 287 | size_t partition_col_ind; 288 | size_t partition_row_ind = 0; 289 | 290 | icer_context_model_typedef context_model; 291 | icer_encoder_context_typedef context; 292 | icer_image_segment_typedef *seg; 293 | 294 | uint32_t data_in_bytes; 295 | /* 296 | * process top region which consists of c columns 297 | * height of top region is h_t and it contains r_t rows 298 | */ 299 | for (uint16_t row = 0; row < params->r_t; row++) { 300 | /* 301 | * the first r_t0 rows have height y_t 302 | * the remainder have height y_t + 1 303 | */ 304 | segment_h = params->y_t + ((row >= params->r_t0) ? 1 : 0); 305 | partition_col_ind = 0; 306 | 307 | for (uint16_t col = 0; col < params->c; col++) { 308 | /* the first c_t0 columns have width x_t 309 | * the remainder have width x_t + 1 310 | */ 311 | segment_w = params->x_t + ((col >= params->c_t0) ? 1 : 0); 312 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 313 | partition_col_ind += segment_w; 314 | 315 | icer_init_context_model_vals(&context_model, pkt_context->subband_type); 316 | res = icer_allocate_data_packet(&seg, output_data, segment_num, pkt_context); 317 | if (res != ICER_RESULT_OK) return res; 318 | 319 | icer_init_entropy_coder_context(&context, icer_encode_circ_buf, ICER_CIRC_BUF_SIZE, 320 | (uint8_t *) seg + sizeof(icer_image_segment_typedef), seg->data_length); 321 | res = icer_compress_bitplane_uint16(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 322 | pkt_context); 323 | if (res != ICER_RESULT_OK) { 324 | output_data->size_used -= sizeof(icer_image_segment_typedef); 325 | return res; 326 | } 327 | 328 | data_in_bytes = context.output_ind + (context.output_bit_offset > 0); 329 | seg->data_length = context.output_ind * 8 + context.output_bit_offset; 330 | seg->data_crc32 = icer_calculate_segment_crc32(seg); 331 | seg->crc32 = icer_calculate_packet_crc32(seg); 332 | output_data->size_used += data_in_bytes; 333 | 334 | segments_encoded[segment_num] = seg; 335 | 336 | segment_num++; 337 | } 338 | partition_row_ind += segment_h; 339 | } 340 | 341 | /* 342 | * if the bottom region exists, process bottom region 343 | * which consists of c+1 columns 344 | */ 345 | for (uint16_t row = 0; row < (params->r - params->r_t); row++) { 346 | /* 347 | * the first r_b0 rows have height y_b 348 | * the remainder have height y_b + 1 349 | */ 350 | segment_h = params->y_b + ((row >= params->r_b0) ? 1 : 0); 351 | partition_col_ind = 0; 352 | 353 | for (uint16_t col = 0; col < (params->c + 1); col++) { 354 | /* the first c_b0 columns have width x_b 355 | * the remainder have width x_b + 1 356 | */ 357 | segment_w = params->x_b + ((col >= params->c_b0) ? 1 : 0); 358 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 359 | partition_col_ind += segment_w; 360 | 361 | icer_init_context_model_vals(&context_model, pkt_context->subband_type); 362 | res = icer_allocate_data_packet(&seg, output_data, segment_num, pkt_context); 363 | if (res != ICER_RESULT_OK) return res; 364 | 365 | icer_init_entropy_coder_context(&context, icer_encode_circ_buf, ICER_CIRC_BUF_SIZE, 366 | (uint8_t *) seg + sizeof(icer_image_segment_typedef), seg->data_length); 367 | res = icer_compress_bitplane_uint16(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 368 | pkt_context); 369 | if (res != ICER_RESULT_OK) { 370 | output_data->size_used -= sizeof(icer_image_segment_typedef); 371 | return res; 372 | } 373 | 374 | data_in_bytes = context.output_ind + (context.output_bit_offset > 0); 375 | seg->data_length = context.output_ind * 8 + context.output_bit_offset; 376 | seg->data_crc32 = icer_calculate_segment_crc32(seg); 377 | seg->crc32 = icer_calculate_packet_crc32(seg); 378 | output_data->size_used += data_in_bytes; 379 | 380 | segments_encoded[segment_num] = seg; 381 | 382 | segment_num++; 383 | } 384 | partition_row_ind += segment_h; 385 | } 386 | 387 | return ICER_RESULT_OK; 388 | } 389 | #endif 390 | 391 | 392 | #ifdef USE_DECODE_FUNCTIONS 393 | int icer_decompress_partition_uint16(uint16_t * const data, const partition_param_typdef * params, size_t rowstride, 394 | icer_image_segment_typedef *seg[][15]) { 395 | int res; 396 | size_t segment_w, segment_h; 397 | uint16_t *segment_start; 398 | uint16_t segment_num = 0; 399 | 400 | size_t partition_col_ind; 401 | size_t partition_row_ind = 0; 402 | 403 | icer_context_model_typedef context_model; 404 | icer_decoder_context_typedef context; 405 | icer_packet_context pkt_context; 406 | int lsb; 407 | /* 408 | * process top region which consists of c columns 409 | * height of top region is h_t and it contains r_t rows 410 | */ 411 | for (uint16_t row = 0; row < params->r_t; row++) { 412 | /* 413 | * the first r_t0 rows have height y_t 414 | * the remainder have height y_t + 1 415 | */ 416 | segment_h = params->y_t + ((row >= params->r_t0) ? 1 : 0); 417 | partition_col_ind = 0; 418 | 419 | for (uint16_t col = 0; col < params->c; col++) { 420 | /* the first c_t0 columns have width x_t 421 | * the remainder have width x_t + 1 422 | */ 423 | segment_w = params->x_t + ((col >= params->c_t0) ? 1 : 0); 424 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 425 | partition_col_ind += segment_w; 426 | 427 | lsb = ICER_BITPLANES_TO_COMPRESS_16 - 1; 428 | /* decompress starting from the msb, and stop whenever there is a missing bitplane */ 429 | /* it is impossible to decompress subsequent bit planes if there is a missing bit plane, due to how the context 430 | * modeller works; it relies on the previously decoded bbitplanes to determine a bit's context */ 431 | while (seg[segment_num][lsb] != NULL && lsb >= 0) { 432 | pkt_context.subband_type = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_16 - 1]->subband_type; 433 | pkt_context.lsb = lsb; 434 | pkt_context.decomp_level = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_16 - 1]->decomp_level; 435 | icer_init_context_model_vals(&context_model, pkt_context.subband_type); 436 | icer_init_entropy_decoder_context(&context, (uint8_t *) seg[segment_num][lsb] + 437 | sizeof(icer_image_segment_typedef), 438 | seg[segment_num][lsb]->data_length); 439 | res = icer_decompress_bitplane_uint16(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 440 | &pkt_context); 441 | if (res != ICER_RESULT_OK) break; 442 | lsb--; 443 | } 444 | 445 | segment_num++; 446 | } 447 | partition_row_ind += segment_h; 448 | } 449 | 450 | /* 451 | * if the bottom region exists, process bottom region 452 | * which consists of c+1 columns 453 | */ 454 | for (uint16_t row = 0; row < (params->r - params->r_t); row++) { 455 | /* 456 | * the first r_b0 rows have height y_b 457 | * the remainder have height y_b + 1 458 | */ 459 | segment_h = params->y_b + ((row >= params->r_b0) ? 1 : 0); 460 | partition_col_ind = 0; 461 | 462 | for (uint16_t col = 0; col < (params->c + 1); col++) { 463 | /* the first c_b0 columns have width x_b 464 | * the remainder have width x_b + 1 465 | */ 466 | segment_w = params->x_b + ((col >= params->c_b0) ? 1 : 0); 467 | segment_start = data + partition_row_ind * rowstride + partition_col_ind; 468 | partition_col_ind += segment_w; 469 | 470 | lsb = ICER_BITPLANES_TO_COMPRESS_16 - 1; 471 | /* decompress starting from the msb, and stop whenever there is a missing bitplane */ 472 | /* it is impossible to decompress subsequent bit planes if there is a missing bit plane, due to how the context 473 | * modeller works; it relies on the previously decoded bbitplanes to determine a bit's context */ 474 | while (seg[segment_num][lsb] != NULL && lsb >= 0) { 475 | pkt_context.subband_type = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_16 - 1]->subband_type; 476 | pkt_context.lsb = lsb; 477 | pkt_context.decomp_level = seg[segment_num][ICER_BITPLANES_TO_COMPRESS_16 - 1]->decomp_level; 478 | icer_init_context_model_vals(&context_model, pkt_context.subband_type); 479 | icer_init_entropy_decoder_context(&context, (uint8_t *) seg[segment_num][lsb] + 480 | sizeof(icer_image_segment_typedef), 481 | seg[segment_num][lsb]->data_length); 482 | res = icer_decompress_bitplane_uint16(segment_start, segment_w, segment_h, rowstride, &context_model, &context, 483 | &pkt_context); 484 | if (res != ICER_RESULT_OK) break; 485 | lsb--; 486 | } 487 | 488 | segment_num++; 489 | } 490 | partition_row_ind += segment_h; 491 | } 492 | 493 | return ICER_RESULT_OK; 494 | } 495 | #endif 496 | #endif 497 | 498 | -------------------------------------------------------------------------------- /lib_icer/src/icer_util.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 19/3/2023. 3 | // 4 | 5 | #include "icer.h" 6 | 7 | #ifndef CRC32BUF_FUNCTION 8 | #include "crc.h" 9 | #define CRC32BUF_FUNCTION(x, y) crc32buf(x, y) 10 | #endif 11 | 12 | #ifndef USER_PROVIDED_BUFFERS 13 | 14 | #ifdef USE_UINT8_FUNCTIONS 15 | #ifdef USE_ENCODE_FUNCTIONS 16 | icer_packet_context icer_packets[ICER_MAX_PACKETS]; 17 | icer_image_segment_typedef *icer_rearrange_segments_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][7][ICER_MAX_SEGMENTS + 1]; 18 | #endif 19 | 20 | #ifdef USE_DECODE_FUNCTIONS 21 | icer_image_segment_typedef *icer_reconstruct_data_8[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][7]; 22 | #endif 23 | #endif 24 | 25 | #ifdef USE_UINT16_FUNCTIONS 26 | #ifdef USE_ENCODE_FUNCTIONS 27 | icer_packet_context icer_packets_16[ICER_MAX_PACKETS_16]; 28 | icer_image_segment_typedef *icer_rearrange_segments_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][15][ICER_MAX_SEGMENTS + 1]; 29 | #endif 30 | 31 | #ifdef USE_DECODE_FUNCTIONS 32 | icer_image_segment_typedef *icer_reconstruct_data_16[ICER_CHANNEL_MAX + 1][ICER_MAX_DECOMP_STAGES + 1][ICER_SUBBAND_MAX + 1][ICER_MAX_SEGMENTS + 1][15]; 33 | #endif 34 | #endif 35 | 36 | #endif 37 | 38 | int icer_init_output_struct(icer_output_data_buf_typedef *out, uint8_t *data, size_t buf_len, size_t byte_quota) { 39 | if (byte_quota * 2 > buf_len) return ICER_OUTPUT_BUF_TOO_SMALL; 40 | out->size_used = 0; 41 | out->data_start = data; 42 | out->size_allocated = byte_quota; 43 | out->rearrange_start = data + byte_quota; 44 | return ICER_RESULT_OK; 45 | } 46 | 47 | /* compute which bin of the interleaved entropy coder to place a bit to be encoded based of the probability cutoffs of each bin */ 48 | int icer_compute_bin(uint32_t zero_cnt, uint32_t total_cnt) { 49 | uint32_t comp = zero_cnt * ICER_BIN_PROBABILITY_DENOMINATOR; 50 | for (int16_t bin = ICER_ENCODER_BIN_MAX;bin > ICER_ENC_BIN_1;bin--) { 51 | if (comp >= total_cnt * icer_bin_probability_cutoffs[bin-1]) { 52 | return bin; 53 | } 54 | } 55 | return ICER_ENC_BIN_1; 56 | } 57 | 58 | /* calculates the crc32 for the header of each segment of the image */ 59 | uint32_t icer_calculate_packet_crc32(icer_image_segment_typedef *pkt) { 60 | return crc32buf((char*)pkt, sizeof(icer_image_segment_typedef) - 4); 61 | } 62 | 63 | /* calculates the crc32 for the data portion of each segment of the image */ 64 | uint32_t icer_calculate_segment_crc32(icer_image_segment_typedef *pkt) { 65 | return crc32buf((char*)pkt + sizeof(icer_image_segment_typedef), icer_ceil_div_uint32(pkt->data_length, 8)); 66 | } 67 | 68 | #ifdef USE_DECODE_FUNCTIONS 69 | #ifdef USE_UINT8_FUNCTIONS 70 | void icer_remove_negative_uint8(uint8_t * const image, size_t image_w, size_t image_h) { 71 | size_t data_length = image_w * image_h; 72 | int8_t *data_end = (int8_t *)(image + data_length); 73 | for (int8_t *pixel = (int8_t *)image;pixel < data_end;pixel++) { 74 | if (*pixel < 0) { 75 | *pixel = 0; 76 | } 77 | } 78 | } 79 | #endif 80 | 81 | #ifdef USE_UINT16_FUNCTIONS 82 | void icer_remove_negative_uint16(uint16_t * const image, size_t image_w, size_t image_h) { 83 | size_t data_length = image_w * image_h; 84 | int16_t *data_end = (int16_t *)(image + data_length); 85 | for (int16_t *pixel = (int16_t *)image;pixel < data_end;pixel++) { 86 | if (*pixel < 0) { 87 | *pixel = 0; 88 | } 89 | } 90 | } 91 | #endif 92 | #endif -------------------------------------------------------------------------------- /lib_icer/src/icer_wavelet.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by linyi on 14/3/2023. 3 | // 4 | 5 | #include "icer.h" 6 | 7 | #ifdef USE_UINT8_FUNCTIONS 8 | int icer_wavelet_transform_stages_uint8(uint8_t * const image, size_t image_w, size_t image_h, uint8_t stages, 9 | enum icer_filter_types filt) { 10 | bool overflow = false; 11 | size_t low_w = image_w; 12 | size_t low_h = image_h; 13 | 14 | size_t smallest_w = icer_get_dim_n_low_stages(image_w, stages); 15 | size_t smallest_h = icer_get_dim_n_low_stages(image_h, stages); 16 | 17 | if (smallest_w < 3 || smallest_h < 3) { 18 | return ICER_TOO_MANY_STAGES; 19 | } 20 | 21 | for (uint8_t it = 0; it < stages; it++) { 22 | overflow |= icer_wavelet_transform_2d_uint8(image, low_w, low_h, image_w, filt); 23 | low_w = low_w / 2 + low_w % 2; 24 | low_h = low_h / 2 + low_h % 2; 25 | } 26 | 27 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 28 | } 29 | 30 | int icer_inverse_wavelet_transform_stages_uint8(uint8_t * const image, size_t image_w, size_t image_h, uint8_t stages, 31 | enum icer_filter_types filt) { 32 | bool overflow = false; 33 | size_t low_w; 34 | size_t low_h; 35 | uint8_t decomps; 36 | 37 | size_t smallest_w = icer_get_dim_n_low_stages(image_w, stages); 38 | size_t smallest_h = icer_get_dim_n_low_stages(image_h, stages); 39 | 40 | if (smallest_w < 3 || smallest_h < 3) { 41 | return ICER_TOO_MANY_STAGES; 42 | } 43 | 44 | //icer_from_sign_magnitude_int8(image, image_w * image_h); 45 | for (uint8_t it = 1; it <= stages; it++) { 46 | decomps = stages - it; 47 | low_w = icer_get_dim_n_low_stages(image_w, decomps); 48 | low_h = icer_get_dim_n_low_stages(image_h, decomps); 49 | overflow |= icer_inverse_wavelet_transform_2d_uint8(image, low_w, low_h, image_w, filt); 50 | } 51 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 52 | } 53 | #endif 54 | 55 | #ifdef USE_UINT16_FUNCTIONS 56 | #ifdef USE_ENCODE_FUNCTIONS 57 | int icer_wavelet_transform_stages_uint16(uint16_t * const image, size_t image_w, size_t image_h, uint8_t stages, 58 | enum icer_filter_types filt) { 59 | bool overflow = false; 60 | size_t low_w = image_w; 61 | size_t low_h = image_h; 62 | 63 | size_t smallest_w = icer_get_dim_n_low_stages(image_w, stages); 64 | size_t smallest_h = icer_get_dim_n_low_stages(image_h, stages); 65 | 66 | if (smallest_w < 3 || smallest_h < 3) { 67 | return ICER_TOO_MANY_STAGES; 68 | } 69 | 70 | for (uint8_t it = 0; it < stages; it++) { 71 | overflow |= icer_wavelet_transform_2d_uint16(image, low_w, low_h, image_w, filt); 72 | low_w = low_w / 2 + low_w % 2; 73 | low_h = low_h / 2 + low_h % 2; 74 | } 75 | 76 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 77 | } 78 | #endif 79 | 80 | #ifdef USE_DECODE_FUNCTIONS 81 | int icer_inverse_wavelet_transform_stages_uint16(uint16_t * const image, size_t image_w, size_t image_h, uint8_t stages, 82 | enum icer_filter_types filt) { 83 | bool overflow = false; 84 | size_t low_w; 85 | size_t low_h; 86 | uint8_t decomps; 87 | 88 | size_t smallest_w = icer_get_dim_n_low_stages(image_w, stages); 89 | size_t smallest_h = icer_get_dim_n_low_stages(image_h, stages); 90 | 91 | if (smallest_w < 3 || smallest_h < 3) { 92 | return ICER_TOO_MANY_STAGES; 93 | } 94 | 95 | //icer_from_sign_magnitude_int8(image, image_w * image_h); 96 | for (uint8_t it = 1; it <= stages; it++) { 97 | decomps = stages - it; 98 | low_w = icer_get_dim_n_low_stages(image_w, decomps); 99 | low_h = icer_get_dim_n_low_stages(image_h, decomps); 100 | overflow |= icer_inverse_wavelet_transform_2d_uint16(image, low_w, low_h, image_w, filt); 101 | } 102 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 103 | } 104 | #endif 105 | #endif 106 | 107 | size_t icer_get_dim_n_low_stages(size_t dim, uint8_t stages) { 108 | return icer_ceil_div_size_t(dim, icer_pow_uint(2, stages)); 109 | } 110 | 111 | size_t icer_get_dim_n_high_stages(size_t dim, uint8_t stages) { 112 | return icer_floor_div_size_t(icer_ceil_div_size_t(dim, icer_pow_uint(2, stages-1)), 2); 113 | } 114 | 115 | #ifdef USE_UINT8_FUNCTIONS 116 | int icer_wavelet_transform_2d_uint8(uint8_t * const image, size_t image_w, size_t image_h, size_t rowstride, 117 | enum icer_filter_types filt) { 118 | bool overflow = false; 119 | uint8_t *rowstart = image; 120 | for (size_t r = 0; r < image_h; r++) { 121 | overflow |= icer_wavelet_transform_1d_uint8(rowstart, image_w, 1, filt); 122 | rowstart += rowstride; 123 | } 124 | 125 | uint8_t *colstart = image; 126 | for (size_t c = 0; c < image_w; c++) { 127 | overflow |= icer_wavelet_transform_1d_uint8(colstart, image_h, rowstride, filt); 128 | colstart += 1; 129 | } 130 | 131 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 132 | } 133 | 134 | int icer_inverse_wavelet_transform_2d_uint8(uint8_t * const image, size_t image_w, size_t image_h, size_t rowstride, 135 | enum icer_filter_types filt) { 136 | bool overflow = false; 137 | uint8_t *colstart = image; 138 | for (size_t c = 0; c < image_w; c++) { 139 | overflow |= icer_inverse_wavelet_transform_1d_uint8(colstart, image_h, rowstride, filt); 140 | colstart += 1; 141 | } 142 | 143 | uint8_t *rowstart = image; 144 | for (size_t r = 0; r < image_h; r++) { 145 | overflow |= icer_inverse_wavelet_transform_1d_uint8(rowstart, image_w, 1, filt); 146 | rowstart += rowstride; 147 | } 148 | 149 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 150 | } 151 | #endif 152 | 153 | #ifdef USE_UINT16_FUNCTIONS 154 | #ifdef USE_ENCODE_FUNCTIONS 155 | int icer_wavelet_transform_2d_uint16(uint16_t * const image, size_t image_w, size_t image_h, size_t rowstride, 156 | enum icer_filter_types filt) { 157 | bool overflow = false; 158 | uint16_t *rowstart = image; 159 | for (size_t r = 0; r < image_h; r++) { 160 | overflow |= icer_wavelet_transform_1d_uint16(rowstart, image_w, 1, filt); 161 | rowstart += rowstride; 162 | } 163 | 164 | uint16_t *colstart = image; 165 | for (size_t c = 0; c < image_w; c++) { 166 | overflow |= icer_wavelet_transform_1d_uint16(colstart, image_h, rowstride, filt); 167 | colstart += 1; 168 | } 169 | 170 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 171 | } 172 | #endif 173 | 174 | #ifdef USE_DECODE_FUNCTIONS 175 | int icer_inverse_wavelet_transform_2d_uint16(uint16_t * const image, size_t image_w, size_t image_h, size_t rowstride, 176 | enum icer_filter_types filt) { 177 | bool overflow = false; 178 | uint16_t *colstart = image; 179 | for (size_t c = 0; c < image_w; c++) { 180 | overflow |= icer_inverse_wavelet_transform_1d_uint16(colstart, image_h, rowstride, filt); 181 | colstart += 1; 182 | } 183 | 184 | uint16_t *rowstart = image; 185 | for (size_t r = 0; r < image_h; r++) { 186 | overflow |= icer_inverse_wavelet_transform_1d_uint16(rowstart, image_w, 1, filt); 187 | rowstart += rowstride; 188 | } 189 | 190 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 191 | } 192 | #endif 193 | #endif 194 | 195 | #ifdef USE_UINT8_FUNCTIONS 196 | static inline int16_t get_r_int8(const int8_t *data, size_t n, size_t stride) { 197 | return (n > 0) ? (int16_t) data[(n - 1) * stride] - (int16_t) data[n * stride] : 1; 198 | } 199 | 200 | static inline int16_t get_d_int8(const int8_t *data, size_t n, size_t stride, size_t offset, size_t max, bool isodd) { 201 | return (isodd && n == max) ? 0 : (int16_t) data[(offset + n) * stride]; 202 | } 203 | #endif 204 | 205 | #ifdef USE_UINT16_FUNCTIONS 206 | static inline int16_t get_r_int16(const int16_t *data, size_t n, size_t stride) { 207 | return (n > 0) ? data[(n - 1) * stride] - data[n * stride] : 1; 208 | } 209 | 210 | static inline int16_t get_d_int16(const int16_t *data, size_t n, size_t stride, size_t offset, size_t max, bool isodd) { 211 | return (isodd && n == max) ? 0 : data[(offset + n) * stride]; 212 | } 213 | #endif 214 | 215 | #ifdef USE_UINT8_FUNCTIONS 216 | int icer_wavelet_transform_1d_uint8(uint8_t * const data, size_t N, size_t stride, enum icer_filter_types filt) { 217 | size_t low_N, high_N; 218 | bool is_odd = false; 219 | bool overflow = false; 220 | low_N = N / 2 - 1; 221 | high_N = N / 2 - 1; 222 | 223 | if (N & 1) { 224 | low_N += 1; 225 | is_odd = true; 226 | } 227 | 228 | size_t n1, n2; 229 | int16_t data1, data2; 230 | int16_t low, high; 231 | 232 | int8_t *signed_data = (int8_t *) data; 233 | for (size_t n = 0; n <= low_N; n++) { 234 | if (!(is_odd && n == low_N)) { 235 | n1 = (2 * n) * stride; 236 | n2 = (2 * n + 1) * stride; 237 | data1 = (int16_t) signed_data[n1]; 238 | data2 = (int16_t) signed_data[n2]; 239 | 240 | low = icer_floor_div_int16(data1 + data2, 2); 241 | high = data1 - data2; 242 | 243 | if (low > INT8_MAX || high > INT8_MAX || low < INT8_MIN || high < INT8_MIN) overflow = true; 244 | 245 | signed_data[n1] = (int8_t) low; 246 | signed_data[n2] = (int8_t) high; 247 | } else { 248 | n1 = (N - 1) * stride; 249 | data1 = (int16_t) signed_data[n1]; 250 | low = data1; 251 | high = 0; 252 | 253 | if (low > INT8_MAX || low < INT8_MIN) overflow = true; 254 | 255 | signed_data[n1] = (int8_t) low; 256 | } 257 | } 258 | 259 | icer_deinterleave_uint8(data, N, stride); 260 | 261 | int16_t subtract, h; 262 | size_t offset = low_N + 1; 263 | bool is_zero = icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] != 0; 264 | for (size_t n = 0; n <= high_N; n++) { 265 | if (n == 0) { 266 | subtract = icer_floor_div_int16(get_r_int8(signed_data, 1, stride), 4); 267 | } else if (n == 1 && is_zero) { 268 | subtract = icer_floor_div_int16(2 * get_r_int8(signed_data, 1, stride) 269 | + 3 * get_r_int8(signed_data, 2, stride) 270 | - 2 * get_d_int8(signed_data, 2, stride, low_N, low_N, is_odd) 271 | + 4, 8); 272 | } else if (!is_odd && n == N / 2 - 1) { 273 | subtract = icer_floor_div_int16(get_r_int8(signed_data, N / 2 - 1, stride), 4); 274 | } else { 275 | subtract = icer_floor_div_int16( 276 | icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] * 277 | get_r_int8(signed_data, n - 1, stride) 278 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_0] * 279 | get_r_int8(signed_data, n, stride) 280 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_1] * 281 | get_r_int8(signed_data, n + 1, stride) 282 | - icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_BETA] * 283 | get_d_int8(signed_data, 284 | n + 1, stride, 285 | offset, low_N, 286 | is_odd) 287 | + 8, ICER_FILTER_DENOMINATOR); 288 | } 289 | n1 = (offset + n) * stride; 290 | h = get_d_int8(signed_data, n, stride, offset, low_N, is_odd) - subtract; 291 | if (h > INT8_MAX || h < INT8_MIN) overflow = true; 292 | signed_data[n1] = (int8_t) h; 293 | } 294 | 295 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 296 | } 297 | 298 | int icer_inverse_wavelet_transform_1d_uint8(uint8_t * const data, size_t N, size_t stride, enum icer_filter_types filt) { 299 | size_t low_N, high_N; 300 | bool is_odd = false; 301 | bool overflow = false; 302 | low_N = N / 2 - 1; 303 | high_N = N / 2 - 1; 304 | 305 | if (N & 1) { 306 | low_N += 1; 307 | is_odd = true; 308 | } 309 | int8_t *signed_data = (int8_t *) data; 310 | 311 | size_t n1; 312 | int16_t add, d; 313 | size_t offset = low_N + 1; 314 | bool is_zero = icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] != 0; 315 | for (size_t n, it = 0; it <= high_N; it++) { 316 | n = high_N - it; 317 | if (n == 0) { 318 | add = icer_floor_div_int16(get_r_int8(signed_data, 1, stride), 4); 319 | } else if (n == 1 && is_zero) { 320 | add = icer_floor_div_int16(2 * get_r_int8(signed_data, 1, stride) 321 | + 3 * get_r_int8(signed_data, 2, stride) 322 | - 2 * get_d_int8(signed_data, 2, stride, low_N, low_N, is_odd) 323 | + 4, 8); 324 | } else if (!is_odd && n == N / 2 - 1) { 325 | add = icer_floor_div_int16(get_r_int8(signed_data, N / 2 - 1, stride), 4); 326 | } else { 327 | add = icer_floor_div_int16( 328 | icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] * 329 | get_r_int8(signed_data, n - 1, stride) 330 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_0] * 331 | get_r_int8(signed_data, n, stride) 332 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_1] * 333 | get_r_int8(signed_data, n + 1, stride) 334 | - icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_BETA] * 335 | get_d_int8(signed_data, 336 | n + 1, stride, 337 | offset, low_N, 338 | is_odd) 339 | + 8, ICER_FILTER_DENOMINATOR); 340 | } 341 | n1 = (offset + n) * stride; 342 | d = get_d_int8(signed_data, n, stride, offset, low_N, is_odd) + add; 343 | if (d > INT8_MAX || d < INT8_MIN) overflow = true; 344 | 345 | signed_data[n1] = (int8_t) d; 346 | } 347 | 348 | size_t n2; 349 | int16_t low, high, tmp; 350 | for (size_t n = 0; n <= low_N; n++) { 351 | if (!(is_odd && n == low_N)) { 352 | n1 = n * stride; 353 | n2 = (offset + n) * stride; 354 | 355 | low = (int16_t) signed_data[n1]; 356 | high = (int16_t) signed_data[n2]; 357 | 358 | tmp = low + icer_floor_div_int16(high + 1, 2); 359 | 360 | if (tmp > INT8_MAX || (tmp - high) > INT8_MAX || tmp < INT8_MIN || (tmp - high) < INT8_MIN) overflow = true; 361 | 362 | signed_data[n1] = (int8_t) tmp; 363 | signed_data[n2] = (int8_t) (tmp - high); 364 | } else { 365 | n1 = n * stride; 366 | 367 | low = (int16_t) signed_data[n1]; 368 | high = 0; 369 | 370 | tmp = low + icer_floor_div_int16(high + 1, 2); 371 | 372 | if (tmp > INT8_MAX || tmp < INT8_MIN) overflow = true; 373 | 374 | signed_data[n1] = (int8_t) tmp; 375 | } 376 | } 377 | 378 | icer_interleave_uint8(data, N, stride); 379 | 380 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 381 | } 382 | #endif 383 | 384 | #ifdef USE_UINT16_FUNCTIONS 385 | int icer_wavelet_transform_1d_uint16(uint16_t * const data, size_t N, size_t stride, enum icer_filter_types filt) { 386 | size_t low_N, high_N; 387 | bool is_odd = false; 388 | bool overflow = false; 389 | low_N = N / 2 - 1; 390 | high_N = N / 2 - 1; 391 | 392 | if (N & 1) { 393 | low_N += 1; 394 | is_odd = true; 395 | } 396 | 397 | size_t n1, n2; 398 | int32_t data1, data2; 399 | int32_t low, high; 400 | 401 | int16_t *signed_data = (int16_t *) data; 402 | for (size_t n = 0; n <= low_N; n++) { 403 | if (!(is_odd && n == low_N)) { 404 | n1 = (2 * n) * stride; 405 | n2 = (2 * n + 1) * stride; 406 | data1 = (int32_t) signed_data[n1]; 407 | data2 = (int32_t) signed_data[n2]; 408 | 409 | low = icer_floor_div_int32(data1 + data2, 2); 410 | high = data1 - data2; 411 | 412 | if (low > INT16_MAX || high > INT16_MAX || low < INT16_MIN || high < INT16_MIN) overflow = true; 413 | 414 | signed_data[n1] = (int16_t) low; 415 | signed_data[n2] = (int16_t) high; 416 | } else { 417 | n1 = (N - 1) * stride; 418 | data1 = (int32_t) signed_data[n1]; 419 | low = data1; 420 | high = 0; 421 | 422 | if (low > INT16_MAX || low < INT16_MIN) overflow = true; 423 | 424 | signed_data[n1] = (int16_t) low; 425 | } 426 | } 427 | 428 | icer_deinterleave_uint16(data, N, stride); 429 | 430 | int32_t subtract, h; 431 | size_t offset = low_N + 1; 432 | bool is_zero = icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] != 0; 433 | for (size_t n = 0; n <= high_N; n++) { 434 | if (n == 0) { 435 | subtract = icer_floor_div_int32(get_r_int16(signed_data, 1, stride), 4); 436 | } else if (n == 1 && is_zero) { 437 | subtract = icer_floor_div_int32(2 * get_r_int16(signed_data, 1, stride) 438 | + 3 * get_r_int16(signed_data, 2, stride) 439 | - 2 * get_d_int16(signed_data, 2, stride, low_N, low_N, is_odd) 440 | + 4, 8); 441 | } else if (!is_odd && n == N / 2 - 1) { 442 | subtract = icer_floor_div_int32(get_r_int16(signed_data, N / 2 - 1, stride), 4); 443 | } else { 444 | subtract = icer_floor_div_int32( 445 | icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] * 446 | get_r_int16(signed_data, n - 1, stride) 447 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_0] * 448 | get_r_int16(signed_data, n, stride) 449 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_1] * 450 | get_r_int16(signed_data, n + 1, stride) 451 | - icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_BETA] * 452 | get_d_int16(signed_data, 453 | n + 1, stride, 454 | offset, low_N, 455 | is_odd) 456 | + 8, ICER_FILTER_DENOMINATOR); 457 | } 458 | n1 = (offset + n) * stride; 459 | h = get_d_int16(signed_data, n, stride, offset, low_N, is_odd) - subtract; 460 | if (h > INT16_MAX || h < INT16_MIN) overflow = true; 461 | signed_data[n1] = (int16_t) h; 462 | } 463 | 464 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 465 | } 466 | 467 | int icer_inverse_wavelet_transform_1d_uint16(uint16_t * const data, size_t N, size_t stride, enum icer_filter_types filt) { 468 | size_t low_N, high_N; 469 | bool is_odd = false; 470 | bool overflow = false; 471 | low_N = N / 2 - 1; 472 | high_N = N / 2 - 1; 473 | 474 | if (N & 1) { 475 | low_N += 1; 476 | is_odd = true; 477 | } 478 | int16_t *signed_data = (int16_t *) data; 479 | 480 | size_t n1; 481 | int32_t add, d; 482 | size_t offset = low_N + 1; 483 | bool is_zero = icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] != 0; 484 | for (size_t n, it = 0; it <= high_N; it++) { 485 | n = high_N - it; 486 | if (n == 0) { 487 | add = icer_floor_div_int32(get_r_int16(signed_data, 1, stride), 4); 488 | } else if (n == 1 && is_zero) { 489 | add = icer_floor_div_int32(2 * get_r_int16(signed_data, 1, stride) 490 | + 3 * get_r_int16(signed_data, 2, stride) 491 | - 2 * get_d_int16(signed_data, 2, stride, low_N, low_N, is_odd) 492 | + 4, 8); 493 | } else if (!is_odd && n == N / 2 - 1) { 494 | add = icer_floor_div_int32(get_r_int16(signed_data, N / 2 - 1, stride), 4); 495 | } else { 496 | add = icer_floor_div_int32( 497 | icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_N1] * 498 | get_r_int16(signed_data, n - 1, stride) 499 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_0] * 500 | get_r_int16(signed_data, n, stride) 501 | + icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_ALPHA_1] * 502 | get_r_int16(signed_data, n + 1, stride) 503 | - icer_wavelet_filter_parameters[filt][ICER_FILTER_COEF_BETA] * 504 | get_d_int16(signed_data, 505 | n + 1, stride, 506 | offset, low_N, 507 | is_odd) 508 | + 8, ICER_FILTER_DENOMINATOR); 509 | } 510 | n1 = (offset + n) * stride; 511 | d = get_d_int16(signed_data, n, stride, offset, low_N, is_odd) + add; 512 | if (d > INT16_MAX || d < INT16_MIN) overflow = true; 513 | 514 | signed_data[n1] = (int16_t) d; 515 | } 516 | 517 | size_t n2; 518 | int32_t low, high, tmp; 519 | for (size_t n = 0; n <= low_N; n++) { 520 | if (!(is_odd && n == low_N)) { 521 | n1 = n * stride; 522 | n2 = (offset + n) * stride; 523 | 524 | low = (int32_t) signed_data[n1]; 525 | high = (int32_t) signed_data[n2]; 526 | 527 | tmp = low + icer_floor_div_int32(high + 1, 2); 528 | 529 | if (tmp > INT16_MAX || (tmp - high) > INT16_MAX || tmp < INT16_MIN || (tmp - high) < INT16_MIN) overflow = true; 530 | 531 | signed_data[n1] = (int16_t) tmp; 532 | signed_data[n2] = (int16_t) (tmp - high); 533 | } else { 534 | n1 = n * stride; 535 | 536 | low = (int16_t) signed_data[n1]; 537 | high = 0; 538 | 539 | tmp = low + icer_floor_div_int32(high + 1, 2); 540 | 541 | if (tmp > INT16_MAX || tmp < INT16_MIN) overflow = true; 542 | 543 | signed_data[n1] = (int16_t) tmp; 544 | } 545 | } 546 | 547 | icer_interleave_uint16(data, N, stride); 548 | 549 | return overflow ? ICER_INTEGER_OVERFLOW : ICER_RESULT_OK; 550 | } 551 | #endif 552 | 553 | #ifdef USE_UINT8_FUNCTIONS 554 | /* interleaving and deinterleaving helper functions */ 555 | void icer_reverse_uint8(uint8_t * const data, size_t start, size_t end, size_t stride) { 556 | size_t n1, n2; 557 | uint8_t swap; 558 | while (start < end) { 559 | n1 = start * stride; 560 | n2 = end * stride; 561 | swap = data[n1]; 562 | data[n1] = data[n2]; 563 | data[n2] = swap; 564 | 565 | start++; 566 | end--; 567 | } 568 | } 569 | 570 | void icer_interleave_uint8(uint8_t * const data, size_t len, size_t stride) { 571 | size_t n = len; 572 | size_t processed = 0, left, halfleft; 573 | size_t segment, halfseg; 574 | uint8_t k; 575 | 576 | size_t j, n1; 577 | uint8_t swap, num; 578 | 579 | bool is_odd = len & 1; 580 | // in-shuffle algorithm only works for even length arrays 581 | // odd length handled separately 582 | if (is_odd) n -= 1; 583 | 584 | // place the element at the end of the first half at the end 585 | if (is_odd) { 586 | swap = data[(n / 2) * stride]; 587 | for (size_t i = n / 2; i < n; i++) { 588 | data[i * stride] = data[(i + 1) * stride]; 589 | } 590 | data[(len - 1) * stride] = swap; 591 | } 592 | 593 | while (processed < n) { 594 | k = icer_find_k(n - processed); 595 | segment = icer_slice_lengths[k]; 596 | halfseg = segment / 2; 597 | 598 | left = n - processed; 599 | halfleft = left / 2 - (is_odd ? 0 : 1); 600 | 601 | if (left > 0) { 602 | icer_reverse_uint8(data, processed + halfseg, processed + halfleft + halfseg, stride); 603 | icer_reverse_uint8(data, processed + halfseg, processed + segment - 1, stride); 604 | icer_reverse_uint8(data, processed + segment, processed + halfleft + halfseg, stride); 605 | } 606 | 607 | for (size_t i = 1; i < segment; i *= 3) { 608 | j = i; 609 | n1 = (j + processed) * stride; 610 | num = data[n1]; 611 | do { 612 | if (j < halfseg) { 613 | j *= 2; 614 | } else { 615 | j = (j - halfseg) * 2 + 1; 616 | } 617 | 618 | n1 = (j + processed) * stride; 619 | 620 | swap = data[n1]; 621 | data[n1] = num; 622 | num = swap; 623 | } while (j != i); 624 | } 625 | 626 | processed += segment; 627 | } 628 | } 629 | 630 | void icer_deinterleave_uint8(uint8_t * const data, size_t len, size_t stride) { 631 | size_t n = len; 632 | size_t processed = 0; 633 | size_t segment, halfseg; 634 | uint8_t k; 635 | 636 | size_t j, n1; 637 | uint8_t swap, num; 638 | 639 | bool is_odd = len & 1; 640 | // in-shuffle algorithm only works for even length arrays 641 | // odd length handled separately 642 | if (is_odd) n -= 1; 643 | 644 | while (processed < n) { 645 | k = icer_find_k(n - processed); 646 | segment = icer_slice_lengths[k]; 647 | halfseg = segment / 2; 648 | 649 | for (size_t i = 1; i < segment; i *= 3) { 650 | j = i; 651 | n1 = (j + processed) * stride; 652 | num = data[n1]; 653 | do { 654 | if (j & 1) { 655 | j = halfseg + j / 2; 656 | } else { 657 | j /= 2; 658 | } 659 | 660 | n1 = (j + processed) * stride; 661 | 662 | swap = data[n1]; 663 | data[n1] = num; 664 | num = swap; 665 | } while (j != i); 666 | } 667 | 668 | if (processed > 0) { 669 | icer_reverse_uint8(data, processed / 2, processed - 1, stride); 670 | icer_reverse_uint8(data, processed, processed + halfseg - 1, stride); 671 | icer_reverse_uint8(data, processed / 2, processed + halfseg - 1, stride); 672 | } 673 | 674 | processed += segment; 675 | } 676 | 677 | // place the last element at the end of the first half if array is odd 678 | if (is_odd) { 679 | swap = data[(len - 1) * stride]; 680 | for (size_t i = len - 1; i > n / 2; i--) { 681 | data[i * stride] = data[(i - 1) * stride]; 682 | } 683 | data[(n / 2) * stride] = swap; 684 | } 685 | } 686 | #endif 687 | 688 | #ifdef USE_UINT16_FUNCTIONS 689 | /* interleaving and deinterleaving helper functions */ 690 | void icer_reverse_uint16(uint16_t * const data, size_t start, size_t end, size_t stride) { 691 | size_t n1, n2; 692 | uint16_t swap; 693 | while (start < end) { 694 | n1 = start * stride; 695 | n2 = end * stride; 696 | swap = data[n1]; 697 | data[n1] = data[n2]; 698 | data[n2] = swap; 699 | 700 | start++; 701 | end--; 702 | } 703 | } 704 | 705 | void icer_interleave_uint16(uint16_t * const data, size_t len, size_t stride) { 706 | size_t n = len; 707 | size_t processed = 0, left, halfleft; 708 | size_t segment, halfseg; 709 | uint8_t k; 710 | 711 | size_t j, n1; 712 | uint16_t swap, num; 713 | 714 | bool is_odd = len & 1; 715 | // in-shuffle algorithm only works for even length arrays 716 | // odd length handled separately 717 | if (is_odd) n -= 1; 718 | 719 | // place the element at the end of the first half at the end 720 | if (is_odd) { 721 | swap = data[(n / 2) * stride]; 722 | for (size_t i = n / 2; i < n; i++) { 723 | data[i * stride] = data[(i + 1) * stride]; 724 | } 725 | data[(len - 1) * stride] = swap; 726 | } 727 | 728 | while (processed < n) { 729 | k = icer_find_k(n - processed); 730 | segment = icer_slice_lengths[k]; 731 | halfseg = segment / 2; 732 | 733 | left = n - processed; 734 | halfleft = left / 2 - 1; 735 | 736 | if (left > 0) { 737 | icer_reverse_uint16(data, processed + halfseg, processed + halfleft + halfseg, stride); 738 | icer_reverse_uint16(data, processed + halfseg, processed + segment - 1, stride); 739 | icer_reverse_uint16(data, processed + segment, processed + halfleft + halfseg, stride); 740 | } 741 | 742 | for (size_t i = 1; i < segment; i *= 3) { 743 | j = i; 744 | n1 = (j + processed) * stride; 745 | num = data[n1]; 746 | do { 747 | if (j < halfseg) { 748 | j *= 2; 749 | } else { 750 | j = (j - halfseg) * 2 + 1; 751 | } 752 | 753 | n1 = (j + processed) * stride; 754 | 755 | swap = data[n1]; 756 | data[n1] = num; 757 | num = swap; 758 | } while (j != i); 759 | } 760 | 761 | processed += segment; 762 | } 763 | } 764 | 765 | void icer_deinterleave_uint16(uint16_t * const data, size_t len, size_t stride) { 766 | size_t n = len; 767 | size_t processed = 0; 768 | size_t segment, halfseg; 769 | uint8_t k; 770 | 771 | size_t j, n1; 772 | uint16_t swap, num; 773 | 774 | bool is_odd = len & 1; 775 | // in-shuffle algorithm only works for even length arrays 776 | // odd length handled separately 777 | if (is_odd) n -= 1; 778 | 779 | while (processed < n) { 780 | k = icer_find_k(n - processed); 781 | segment = icer_slice_lengths[k]; 782 | halfseg = segment / 2; 783 | 784 | for (size_t i = 1; i < segment; i *= 3) { 785 | j = i; 786 | n1 = (j + processed) * stride; 787 | num = data[n1]; 788 | do { 789 | if (j & 1) { 790 | j = halfseg + j / 2; 791 | } else { 792 | j /= 2; 793 | } 794 | 795 | n1 = (j + processed) * stride; 796 | 797 | swap = data[n1]; 798 | data[n1] = num; 799 | num = swap; 800 | } while (j != i); 801 | } 802 | 803 | if (processed > 0) { 804 | icer_reverse_uint16(data, processed / 2, processed - 1, stride); 805 | icer_reverse_uint16(data, processed, processed + halfseg - 1, stride); 806 | icer_reverse_uint16(data, processed / 2, processed + halfseg - 1, stride); 807 | } 808 | 809 | processed += segment; 810 | } 811 | 812 | // place the last element at the end of the first half if array is odd 813 | if (is_odd) { 814 | swap = data[(len - 1) * stride]; 815 | for (size_t i = len - 1; i > n / 2; i--) { 816 | data[i * stride] = data[(i - 1) * stride]; 817 | } 818 | data[(n / 2) * stride] = swap; 819 | } 820 | } 821 | #endif 822 | 823 | uint8_t icer_find_k(size_t len) { 824 | uint8_t max_k = MAX_K - 1; 825 | uint8_t min_k = 0; 826 | 827 | if (icer_slice_lengths[min_k] == 0) icer_slice_lengths[min_k] = icer_pow_uint(3, min_k) + 1; 828 | if (icer_slice_lengths[max_k] == 0) icer_slice_lengths[max_k] = icer_pow_uint(3, max_k) + 1; 829 | 830 | uint8_t mid; 831 | uint8_t res = 0; 832 | while (min_k < max_k) { 833 | mid = (max_k + min_k) / 2; 834 | if (icer_slice_lengths[mid] == 0) icer_slice_lengths[mid] = icer_pow_uint(3, mid) + 1; 835 | 836 | if (len > icer_slice_lengths[mid]) { 837 | min_k = mid + 1; 838 | res = mid; 839 | } else if (len < icer_slice_lengths[mid]) { 840 | max_k = mid - 1; 841 | } else { 842 | break; 843 | } 844 | } 845 | 846 | return res; 847 | } 848 | 849 | #ifdef USE_UINT8_FUNCTIONS 850 | /* this assumes that the platform you are running the code on stores numbers as 2's complement */ 851 | void icer_to_sign_magnitude_int8(uint8_t * const data, size_t len) { 852 | uint8_t mask; 853 | for (uint8_t *it = data; it < data + len; it++) { 854 | mask = (int8_t) (*it) >> 7; 855 | (*it) = (((int8_t) (*it) + (int8_t) mask) ^ mask) | ((*it) & 0b10000000); 856 | } 857 | } 858 | 859 | /* this assumes that the platform you are running the code on stores numbers as 2's complement */ 860 | void icer_from_sign_magnitude_int8(uint8_t * const data, size_t len) { 861 | uint8_t mask; 862 | for (uint8_t *it = data; it < data + len; it++) { 863 | mask = (int8_t) (*it) >> 7; 864 | (*it) = (~mask & (*it)) | (((int8_t) ((*it) & 0b10000000) - (int8_t) (*it)) & mask); 865 | } 866 | } 867 | #endif 868 | 869 | #ifdef USE_UINT16_FUNCTIONS 870 | /* this assumes that the platform you are running the code on stores numbers as 2's complement */ 871 | void icer_to_sign_magnitude_int16(uint16_t * const data, size_t len) { 872 | uint16_t mask; 873 | for (uint16_t *it = data; it < data + len; it++) { 874 | mask = (int16_t) (*it) >> 15; 875 | (*it) = (((int16_t) (*it) + (int16_t) mask) ^ mask) | ((*it) & 0x8000); 876 | } 877 | } 878 | 879 | /* this assumes that the platform you are running the code on stores numbers as 2's complement */ 880 | void icer_from_sign_magnitude_int16(uint16_t * const data, size_t len) { 881 | uint16_t mask; 882 | for (uint16_t *it = data; it < data + len; it++) { 883 | mask = (int16_t) (*it) >> 15; 884 | (*it) = (~mask & (*it)) | (((int16_t) ((*it) & 0x8000) - (int16_t) (*it)) & mask); 885 | } 886 | } 887 | #endif --------------------------------------------------------------------------------