1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2021 Arm Limited
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 // use this file except in compliance with the License. You may obtain a copy
7 // of the License at:
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 // License for the specific language governing permissions and limitations
15 // under the License.
16 // ----------------------------------------------------------------------------
17
18 // This is a minimal example of using the astcenc library.
19 //
20 // This sample shows how to include the astcenc library in your CMake project
21 // as an external dependency, and how to compress and decompress images using
22 // the C library API.
23 //
24 // For sake of clarity the command line exposed by the sample is minimalistic,
25 // and the compression uses a fixed set of options, but the code is commented
26 // to indicate where extension would be possible. Errors handling points are
27 // detected and logged, but resources are not cleaned up on error paths to keep
28 // the sample control path simple, so resources will leak on error.
29
30 #include <stdio.h>
31
32 #include "astcenc.h"
33
34 #define STB_IMAGE_IMPLEMENTATION
35 #include "stb_image.h"
36
37 #define STB_IMAGE_WRITE_IMPLEMENTATION
38 #include "stb_image_write.h"
39
main(int argc,char ** argv)40 int main(int argc, char **argv)
41 {
42 // Parse command line
43 if (argc != 3)
44 {
45 printf("Usage:\n"
46 " %s <source> <dest>\n\n"
47 " <source> : Uncompressed LDR source image.\n"
48 " <dest> : Uncompressed LDR destination image (png).\n"
49 , argv[0]);
50 return 1;
51 }
52
53 // ------------------------------------------------------------------------
54 // For the purposes of this sample we hard-code the compressor settings
55 static const unsigned int thread_count = 1;
56 static const unsigned int block_x = 6;
57 static const unsigned int block_y = 6;
58 static const unsigned int block_z = 1;
59 static const astcenc_profile profile = ASTCENC_PRF_LDR;
60 static const float quality = ASTCENC_PRE_MEDIUM;
61 static const astcenc_swizzle swizzle {
62 ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A
63 };
64
65 // ------------------------------------------------------------------------
66 // Load input image, forcing 4 components
67 int image_x, image_y, image_c;
68 uint8_t *image_data = (uint8_t*)stbi_load(argv[1], &image_x, &image_y, &image_c, 4);
69 if (!image_data)
70 {
71 printf("Failed to load image \"%s\"\n", argv[1]);
72 return 1;
73 }
74
75 // Compute the number of ASTC blocks in each dimension
76 unsigned int block_count_x = (image_x + block_x - 1) / block_x;
77 unsigned int block_count_y = (image_y + block_y - 1) / block_y;
78
79 // ------------------------------------------------------------------------
80 // Initialize the default configuration for the block size and quality
81 astcenc_config config;
82 config.block_x = block_x;
83 config.block_y = block_y;
84 config.profile = profile;
85
86 astcenc_error status;
87 status = astcenc_config_init(profile, block_x, block_y, block_z, quality, 0, &config);
88 if (status != ASTCENC_SUCCESS)
89 {
90 printf("ERROR: Codec config init failed: %s\n", astcenc_get_error_string(status));
91 return 1;
92 }
93
94 // ... power users can customize any config settings after calling
95 // config_init() and before calling context alloc().
96
97 // ------------------------------------------------------------------------
98 // Create a context based on the configuration
99 astcenc_context* context;
100 status = astcenc_context_alloc(&config, thread_count, &context);
101 if (status != ASTCENC_SUCCESS)
102 {
103 printf("ERROR: Codec context alloc failed: %s\n", astcenc_get_error_string(status));
104 return 1;
105 }
106
107 // ------------------------------------------------------------------------
108 // Compress the image
109 astcenc_image image;
110 image.dim_x = image_x;
111 image.dim_y = image_y;
112 image.dim_z = 1;
113 image.data_type = ASTCENC_TYPE_U8;
114 uint8_t* slices = image_data;
115 image.data = reinterpret_cast<void**>(&slices);
116
117 // Space needed for 16 bytes of output per compressed block
118 size_t comp_len = block_count_x * block_count_y * 16;
119 uint8_t* comp_data = new uint8_t[comp_len];
120
121 status = astcenc_compress_image(context, &image, &swizzle, comp_data, comp_len, 0);
122 if (status != ASTCENC_SUCCESS)
123 {
124 printf("ERROR: Codec compress failed: %s\n", astcenc_get_error_string(status));
125 return 1;
126 }
127
128 // ... the comp_data array contains the raw compressed data you would pass
129 // to the graphics API, or pack into a wrapper format such as a KTX file.
130
131 // If using multithreaded compression to sequentially compress multiple
132 // images you should reuse the same context, calling the function
133 // astcenc_compress_reset() between each image in the series.
134
135 // ------------------------------------------------------------------------
136 // Decompress the image
137 // Note we just reuse the image structure to store the output here ...
138 status = astcenc_decompress_image(context, comp_data, comp_len, &image, &swizzle, 0);
139 if (status != ASTCENC_SUCCESS)
140 {
141 printf("ERROR: Codec decompress failed: %s\n", astcenc_get_error_string(status));
142 return 1;
143 }
144
145 // If using multithreaded decompression to sequentially decompress multiple
146 // images you should reuse the same context, calling the function
147 // astcenc_decompress_reset() between each image in the series.
148
149 // ------------------------------------------------------------------------
150 // Store the result back to disk
151 stbi_write_png(argv[2], image_x, image_y, 4, image_data, 4 * image_x);
152
153 // ------------------------------------------------------------------------
154 // Cleanup library resources
155 stbi_image_free(image_data);
156 astcenc_context_free(context);
157 delete[] comp_data;
158
159 return 0;
160 }
161