• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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