1cc1dc7a3Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0
2cc1dc7a3Sopenharmony_ci// ----------------------------------------------------------------------------
3cc1dc7a3Sopenharmony_ci// Copyright 2011-2022 Arm Limited
4cc1dc7a3Sopenharmony_ci//
5cc1dc7a3Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); you may not
6cc1dc7a3Sopenharmony_ci// use this file except in compliance with the License. You may obtain a copy
7cc1dc7a3Sopenharmony_ci// of the License at:
8cc1dc7a3Sopenharmony_ci//
9cc1dc7a3Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
10cc1dc7a3Sopenharmony_ci//
11cc1dc7a3Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
12cc1dc7a3Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13cc1dc7a3Sopenharmony_ci// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14cc1dc7a3Sopenharmony_ci// License for the specific language governing permissions and limitations
15cc1dc7a3Sopenharmony_ci// under the License.
16cc1dc7a3Sopenharmony_ci// ----------------------------------------------------------------------------
17cc1dc7a3Sopenharmony_ci
18cc1dc7a3Sopenharmony_ci/**
19cc1dc7a3Sopenharmony_ci * @brief Functions for creating in-memory ASTC image structures.
20cc1dc7a3Sopenharmony_ci */
21cc1dc7a3Sopenharmony_ci
22cc1dc7a3Sopenharmony_ci#include <cassert>
23cc1dc7a3Sopenharmony_ci#include <cstring>
24cc1dc7a3Sopenharmony_ci
25cc1dc7a3Sopenharmony_ci#include "astcenccli_internal.h"
26cc1dc7a3Sopenharmony_ci
27cc1dc7a3Sopenharmony_ci/* See header for documentation. */
28cc1dc7a3Sopenharmony_ciastcenc_image *alloc_image(
29cc1dc7a3Sopenharmony_ci	unsigned int bitness,
30cc1dc7a3Sopenharmony_ci	unsigned int dim_x,
31cc1dc7a3Sopenharmony_ci	unsigned int dim_y,
32cc1dc7a3Sopenharmony_ci	unsigned int dim_z
33cc1dc7a3Sopenharmony_ci) {
34cc1dc7a3Sopenharmony_ci	astcenc_image *img = new astcenc_image;
35cc1dc7a3Sopenharmony_ci	img->dim_x = dim_x;
36cc1dc7a3Sopenharmony_ci	img->dim_y = dim_y;
37cc1dc7a3Sopenharmony_ci	img->dim_z = dim_z;
38cc1dc7a3Sopenharmony_ci
39cc1dc7a3Sopenharmony_ci	void** data = new void*[dim_z];
40cc1dc7a3Sopenharmony_ci	img->data = data;
41cc1dc7a3Sopenharmony_ci
42cc1dc7a3Sopenharmony_ci	if (bitness == 8)
43cc1dc7a3Sopenharmony_ci	{
44cc1dc7a3Sopenharmony_ci		img->data_type = ASTCENC_TYPE_U8;
45cc1dc7a3Sopenharmony_ci		for (unsigned int z = 0; z < dim_z; z++)
46cc1dc7a3Sopenharmony_ci		{
47cc1dc7a3Sopenharmony_ci			data[z] = new uint8_t[dim_x * dim_y * 4];
48cc1dc7a3Sopenharmony_ci		}
49cc1dc7a3Sopenharmony_ci	}
50cc1dc7a3Sopenharmony_ci	else if (bitness == 16)
51cc1dc7a3Sopenharmony_ci	{
52cc1dc7a3Sopenharmony_ci		img->data_type = ASTCENC_TYPE_F16;
53cc1dc7a3Sopenharmony_ci		for (unsigned int z = 0; z < dim_z; z++)
54cc1dc7a3Sopenharmony_ci		{
55cc1dc7a3Sopenharmony_ci			data[z] = new uint16_t[dim_x * dim_y * 4];
56cc1dc7a3Sopenharmony_ci		}
57cc1dc7a3Sopenharmony_ci	}
58cc1dc7a3Sopenharmony_ci	else // if (bitness == 32)
59cc1dc7a3Sopenharmony_ci	{
60cc1dc7a3Sopenharmony_ci		assert(bitness == 32);
61cc1dc7a3Sopenharmony_ci		img->data_type = ASTCENC_TYPE_F32;
62cc1dc7a3Sopenharmony_ci		for (unsigned int z = 0; z < dim_z; z++)
63cc1dc7a3Sopenharmony_ci		{
64cc1dc7a3Sopenharmony_ci			data[z] = new float[dim_x * dim_y * 4];
65cc1dc7a3Sopenharmony_ci		}
66cc1dc7a3Sopenharmony_ci	}
67cc1dc7a3Sopenharmony_ci
68cc1dc7a3Sopenharmony_ci	return img;
69cc1dc7a3Sopenharmony_ci}
70cc1dc7a3Sopenharmony_ci
71cc1dc7a3Sopenharmony_ci/* See header for documentation. */
72cc1dc7a3Sopenharmony_civoid free_image(astcenc_image * img)
73cc1dc7a3Sopenharmony_ci{
74cc1dc7a3Sopenharmony_ci	if (img == nullptr)
75cc1dc7a3Sopenharmony_ci	{
76cc1dc7a3Sopenharmony_ci		return;
77cc1dc7a3Sopenharmony_ci	}
78cc1dc7a3Sopenharmony_ci
79cc1dc7a3Sopenharmony_ci	for (unsigned int z = 0; z < img->dim_z; z++)
80cc1dc7a3Sopenharmony_ci	{
81cc1dc7a3Sopenharmony_ci		delete[] reinterpret_cast<char*>(img->data[z]);
82cc1dc7a3Sopenharmony_ci	}
83cc1dc7a3Sopenharmony_ci
84cc1dc7a3Sopenharmony_ci	delete[] img->data;
85cc1dc7a3Sopenharmony_ci	delete img;
86cc1dc7a3Sopenharmony_ci}
87cc1dc7a3Sopenharmony_ci
88cc1dc7a3Sopenharmony_ci/* See header for documentation. */
89cc1dc7a3Sopenharmony_ciint determine_image_components(const astcenc_image * img)
90cc1dc7a3Sopenharmony_ci{
91cc1dc7a3Sopenharmony_ci	unsigned int dim_x = img->dim_x;
92cc1dc7a3Sopenharmony_ci	unsigned int dim_y = img->dim_y;
93cc1dc7a3Sopenharmony_ci	unsigned int dim_z = img->dim_z;
94cc1dc7a3Sopenharmony_ci
95cc1dc7a3Sopenharmony_ci	// Scan through the image data to determine how many color components the image has
96cc1dc7a3Sopenharmony_ci	bool is_luma = true;
97cc1dc7a3Sopenharmony_ci	bool has_alpha = false;
98cc1dc7a3Sopenharmony_ci
99cc1dc7a3Sopenharmony_ci	if (img->data_type == ASTCENC_TYPE_U8)
100cc1dc7a3Sopenharmony_ci	{
101cc1dc7a3Sopenharmony_ci		for (unsigned int z = 0; z < dim_z; z++)
102cc1dc7a3Sopenharmony_ci		{
103cc1dc7a3Sopenharmony_ci			uint8_t* data8 = static_cast<uint8_t*>(img->data[z]);
104cc1dc7a3Sopenharmony_ci
105cc1dc7a3Sopenharmony_ci			for (unsigned int y = 0; y < dim_y; y++)
106cc1dc7a3Sopenharmony_ci			{
107cc1dc7a3Sopenharmony_ci				for (unsigned int x = 0; x < dim_x; x++)
108cc1dc7a3Sopenharmony_ci				{
109cc1dc7a3Sopenharmony_ci					int r = data8[(4 * dim_x * y) + (4 * x    )];
110cc1dc7a3Sopenharmony_ci					int g = data8[(4 * dim_x * y) + (4 * x + 1)];
111cc1dc7a3Sopenharmony_ci					int b = data8[(4 * dim_x * y) + (4 * x + 2)];
112cc1dc7a3Sopenharmony_ci					int a = data8[(4 * dim_x * y) + (4 * x + 3)];
113cc1dc7a3Sopenharmony_ci
114cc1dc7a3Sopenharmony_ci					is_luma = is_luma && (r == g) && (r == b);
115cc1dc7a3Sopenharmony_ci					has_alpha = has_alpha || (a != 0xFF);
116cc1dc7a3Sopenharmony_ci				}
117cc1dc7a3Sopenharmony_ci			}
118cc1dc7a3Sopenharmony_ci		}
119cc1dc7a3Sopenharmony_ci	}
120cc1dc7a3Sopenharmony_ci	else if (img->data_type == ASTCENC_TYPE_F16)
121cc1dc7a3Sopenharmony_ci	{
122cc1dc7a3Sopenharmony_ci		for (unsigned int z = 0; z < dim_z; z++)
123cc1dc7a3Sopenharmony_ci		{
124cc1dc7a3Sopenharmony_ci			uint16_t* data16 = static_cast<uint16_t*>(img->data[z]);
125cc1dc7a3Sopenharmony_ci
126cc1dc7a3Sopenharmony_ci			for (unsigned int y = 0; y < dim_y; y++)
127cc1dc7a3Sopenharmony_ci			{
128cc1dc7a3Sopenharmony_ci				for (unsigned int x = 0; x < dim_x; x++)
129cc1dc7a3Sopenharmony_ci				{
130cc1dc7a3Sopenharmony_ci					int r = data16[(4 * dim_x * y) + (4 * x    )];
131cc1dc7a3Sopenharmony_ci					int g = data16[(4 * dim_x * y) + (4 * x + 1)];
132cc1dc7a3Sopenharmony_ci					int b = data16[(4 * dim_x * y) + (4 * x + 2)];
133cc1dc7a3Sopenharmony_ci					int a = data16[(4 * dim_x * y) + (4 * x + 3)];
134cc1dc7a3Sopenharmony_ci
135cc1dc7a3Sopenharmony_ci					is_luma = is_luma && (r == g) && (r == b);
136cc1dc7a3Sopenharmony_ci					has_alpha = has_alpha || ((a ^ 0xC3FF) != 0xFFFF);
137cc1dc7a3Sopenharmony_ci					// a ^ 0xC3FF returns FFFF if and only if the input is 1.0
138cc1dc7a3Sopenharmony_ci				}
139cc1dc7a3Sopenharmony_ci			}
140cc1dc7a3Sopenharmony_ci		}
141cc1dc7a3Sopenharmony_ci	}
142cc1dc7a3Sopenharmony_ci	else // if (img->data_type == ASTCENC_TYPE_F32)
143cc1dc7a3Sopenharmony_ci	{
144cc1dc7a3Sopenharmony_ci		assert(img->data_type == ASTCENC_TYPE_F32);
145cc1dc7a3Sopenharmony_ci
146cc1dc7a3Sopenharmony_ci		for (unsigned int z = 0; z < dim_z; z++)
147cc1dc7a3Sopenharmony_ci		{
148cc1dc7a3Sopenharmony_ci			float* data32 = static_cast<float*>(img->data[z]);
149cc1dc7a3Sopenharmony_ci
150cc1dc7a3Sopenharmony_ci			for (unsigned int y = 0; y < dim_y; y++)
151cc1dc7a3Sopenharmony_ci			{
152cc1dc7a3Sopenharmony_ci				for (unsigned int x = 0; x < dim_x; x++)
153cc1dc7a3Sopenharmony_ci				{
154cc1dc7a3Sopenharmony_ci					float r = data32[(4 * dim_x * y) + (4 * x    )];
155cc1dc7a3Sopenharmony_ci					float g = data32[(4 * dim_x * y) + (4 * x + 1)];
156cc1dc7a3Sopenharmony_ci					float b = data32[(4 * dim_x * y) + (4 * x + 2)];
157cc1dc7a3Sopenharmony_ci					float a = data32[(4 * dim_x * y) + (4 * x + 3)];
158cc1dc7a3Sopenharmony_ci
159cc1dc7a3Sopenharmony_ci					is_luma = is_luma && (r == g) && (r == b);
160cc1dc7a3Sopenharmony_ci					has_alpha = has_alpha || (a != 1.0f);
161cc1dc7a3Sopenharmony_ci				}
162cc1dc7a3Sopenharmony_ci			}
163cc1dc7a3Sopenharmony_ci		}
164cc1dc7a3Sopenharmony_ci	}
165cc1dc7a3Sopenharmony_ci
166cc1dc7a3Sopenharmony_ci	int image_components = 1 + (is_luma == 0 ? 2 : 0) + (has_alpha ? 1 : 0);
167cc1dc7a3Sopenharmony_ci	return image_components;
168cc1dc7a3Sopenharmony_ci}
169cc1dc7a3Sopenharmony_ci
170cc1dc7a3Sopenharmony_ci/* See header for documentation. */
171cc1dc7a3Sopenharmony_ciastcenc_image* astc_img_from_floatx4_array(
172cc1dc7a3Sopenharmony_ci	const float* data,
173cc1dc7a3Sopenharmony_ci	unsigned int dim_x,
174cc1dc7a3Sopenharmony_ci	unsigned int dim_y,
175cc1dc7a3Sopenharmony_ci	bool y_flip
176cc1dc7a3Sopenharmony_ci) {
177cc1dc7a3Sopenharmony_ci	astcenc_image* img = alloc_image(16, dim_x, dim_y, 1);
178cc1dc7a3Sopenharmony_ci
179cc1dc7a3Sopenharmony_ci	for (unsigned int y = 0; y < dim_y; y++)
180cc1dc7a3Sopenharmony_ci	{
181cc1dc7a3Sopenharmony_ci		uint16_t* data16 = static_cast<uint16_t*>(img->data[0]);
182cc1dc7a3Sopenharmony_ci		unsigned int y_src = y_flip ? (dim_y - y - 1) : y;
183cc1dc7a3Sopenharmony_ci		const float* src = data + 4 * dim_x * y_src;
184cc1dc7a3Sopenharmony_ci
185cc1dc7a3Sopenharmony_ci		for (unsigned int x = 0; x < dim_x; x++)
186cc1dc7a3Sopenharmony_ci		{
187cc1dc7a3Sopenharmony_ci			vint4 colorf16 = float_to_float16(vfloat4(
188cc1dc7a3Sopenharmony_ci				src[4 * x    ],
189cc1dc7a3Sopenharmony_ci				src[4 * x + 1],
190cc1dc7a3Sopenharmony_ci				src[4 * x + 2],
191cc1dc7a3Sopenharmony_ci				src[4 * x + 3]
192cc1dc7a3Sopenharmony_ci			));
193cc1dc7a3Sopenharmony_ci
194cc1dc7a3Sopenharmony_ci			data16[(4 * dim_x * y) + (4 * x    )] = static_cast<uint16_t>(colorf16.lane<0>());
195cc1dc7a3Sopenharmony_ci			data16[(4 * dim_x * y) + (4 * x + 1)] = static_cast<uint16_t>(colorf16.lane<1>());
196cc1dc7a3Sopenharmony_ci			data16[(4 * dim_x * y) + (4 * x + 2)] = static_cast<uint16_t>(colorf16.lane<2>());
197cc1dc7a3Sopenharmony_ci			data16[(4 * dim_x * y) + (4 * x + 3)] = static_cast<uint16_t>(colorf16.lane<3>());
198cc1dc7a3Sopenharmony_ci		}
199cc1dc7a3Sopenharmony_ci	}
200cc1dc7a3Sopenharmony_ci
201cc1dc7a3Sopenharmony_ci	return img;
202cc1dc7a3Sopenharmony_ci}
203cc1dc7a3Sopenharmony_ci
204cc1dc7a3Sopenharmony_ci/* See header for documentation. */
205cc1dc7a3Sopenharmony_ciastcenc_image* astc_img_from_unorm8x4_array(
206cc1dc7a3Sopenharmony_ci	const uint8_t* data,
207cc1dc7a3Sopenharmony_ci	unsigned int dim_x,
208cc1dc7a3Sopenharmony_ci	unsigned int dim_y,
209cc1dc7a3Sopenharmony_ci	bool y_flip
210cc1dc7a3Sopenharmony_ci) {
211cc1dc7a3Sopenharmony_ci	astcenc_image* img = alloc_image(8, dim_x, dim_y, 1);
212cc1dc7a3Sopenharmony_ci
213cc1dc7a3Sopenharmony_ci	for (unsigned int y = 0; y < dim_y; y++)
214cc1dc7a3Sopenharmony_ci	{
215cc1dc7a3Sopenharmony_ci		uint8_t* data8 = static_cast<uint8_t*>(img->data[0]);
216cc1dc7a3Sopenharmony_ci		unsigned int y_src = y_flip ? (dim_y - y - 1) : y;
217cc1dc7a3Sopenharmony_ci		const uint8_t* src = data + 4 * dim_x * y_src;
218cc1dc7a3Sopenharmony_ci
219cc1dc7a3Sopenharmony_ci		for (unsigned int x = 0; x < dim_x; x++)
220cc1dc7a3Sopenharmony_ci		{
221cc1dc7a3Sopenharmony_ci			data8[(4 * dim_x * y) + (4 * x    )] = src[4 * x    ];
222cc1dc7a3Sopenharmony_ci			data8[(4 * dim_x * y) + (4 * x + 1)] = src[4 * x + 1];
223cc1dc7a3Sopenharmony_ci			data8[(4 * dim_x * y) + (4 * x + 2)] = src[4 * x + 2];
224cc1dc7a3Sopenharmony_ci			data8[(4 * dim_x * y) + (4 * x + 3)] = src[4 * x + 3];
225cc1dc7a3Sopenharmony_ci		}
226cc1dc7a3Sopenharmony_ci	}
227cc1dc7a3Sopenharmony_ci
228cc1dc7a3Sopenharmony_ci	return img;
229cc1dc7a3Sopenharmony_ci}
230cc1dc7a3Sopenharmony_ci
231cc1dc7a3Sopenharmony_ci// initialize a flattened array of float values from an ASTC codec image
232cc1dc7a3Sopenharmony_ci// The returned array is allocated with new[] and must be deleted with delete[].
233cc1dc7a3Sopenharmony_ci/* See header for documentation. */
234cc1dc7a3Sopenharmony_cifloat* floatx4_array_from_astc_img(
235cc1dc7a3Sopenharmony_ci	const astcenc_image* img,
236cc1dc7a3Sopenharmony_ci	bool y_flip,
237cc1dc7a3Sopenharmony_ci	unsigned int z_index
238cc1dc7a3Sopenharmony_ci) {
239cc1dc7a3Sopenharmony_ci	unsigned int dim_x = img->dim_x;
240cc1dc7a3Sopenharmony_ci	unsigned int dim_y = img->dim_y;
241cc1dc7a3Sopenharmony_ci	float *buf = new float[4 * dim_x * dim_y];
242cc1dc7a3Sopenharmony_ci
243cc1dc7a3Sopenharmony_ci	assert(z_index < img->dim_z);
244cc1dc7a3Sopenharmony_ci
245cc1dc7a3Sopenharmony_ci	if (img->data_type == ASTCENC_TYPE_U8)
246cc1dc7a3Sopenharmony_ci	{
247cc1dc7a3Sopenharmony_ci		uint8_t* data8 = static_cast<uint8_t*>(img->data[z_index]);
248cc1dc7a3Sopenharmony_ci		for (unsigned int y = 0; y < dim_y; y++)
249cc1dc7a3Sopenharmony_ci		{
250cc1dc7a3Sopenharmony_ci			unsigned int ymod = y_flip ? dim_y - y - 1 : y;
251cc1dc7a3Sopenharmony_ci			float* dst = buf + y * dim_x * 4;
252cc1dc7a3Sopenharmony_ci
253cc1dc7a3Sopenharmony_ci			for (unsigned int x = 0; x < dim_x; x++)
254cc1dc7a3Sopenharmony_ci			{
255cc1dc7a3Sopenharmony_ci				dst[4 * x    ] = data8[(4 * dim_x * ymod) + (4 * x    )] * (1.0f / 255.0f);
256cc1dc7a3Sopenharmony_ci				dst[4 * x + 1] = data8[(4 * dim_x * ymod) + (4 * x + 1)] * (1.0f / 255.0f);
257cc1dc7a3Sopenharmony_ci				dst[4 * x + 2] = data8[(4 * dim_x * ymod) + (4 * x + 2)] * (1.0f / 255.0f);
258cc1dc7a3Sopenharmony_ci				dst[4 * x + 3] = data8[(4 * dim_x * ymod) + (4 * x + 3)] * (1.0f / 255.0f);
259cc1dc7a3Sopenharmony_ci			}
260cc1dc7a3Sopenharmony_ci		}
261cc1dc7a3Sopenharmony_ci	}
262cc1dc7a3Sopenharmony_ci	else if (img->data_type == ASTCENC_TYPE_F16)
263cc1dc7a3Sopenharmony_ci	{
264cc1dc7a3Sopenharmony_ci		uint16_t* data16 = static_cast<uint16_t*>(img->data[z_index]);
265cc1dc7a3Sopenharmony_ci		for (unsigned int y = 0; y < dim_y; y++)
266cc1dc7a3Sopenharmony_ci		{
267cc1dc7a3Sopenharmony_ci			unsigned int ymod = y_flip ? dim_y - y - 1 : y;
268cc1dc7a3Sopenharmony_ci			float *dst = buf + y * dim_x * 4;
269cc1dc7a3Sopenharmony_ci
270cc1dc7a3Sopenharmony_ci			for (unsigned int x = 0; x < dim_x; x++)
271cc1dc7a3Sopenharmony_ci			{
272cc1dc7a3Sopenharmony_ci				vint4 colori(
273cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x    )],
274cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x + 1)],
275cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x + 2)],
276cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x + 3)]
277cc1dc7a3Sopenharmony_ci				);
278cc1dc7a3Sopenharmony_ci
279cc1dc7a3Sopenharmony_ci				vfloat4 color = float16_to_float(colori);
280cc1dc7a3Sopenharmony_ci				store(color, dst + 4 * x);
281cc1dc7a3Sopenharmony_ci			}
282cc1dc7a3Sopenharmony_ci		}
283cc1dc7a3Sopenharmony_ci	}
284cc1dc7a3Sopenharmony_ci	else // if (img->data_type == ASTCENC_TYPE_F32)
285cc1dc7a3Sopenharmony_ci	{
286cc1dc7a3Sopenharmony_ci		assert(img->data_type == ASTCENC_TYPE_F32);
287cc1dc7a3Sopenharmony_ci		float* data32 = static_cast<float*>(img->data[z_index]);
288cc1dc7a3Sopenharmony_ci		for (unsigned int y = 0; y < dim_y; y++)
289cc1dc7a3Sopenharmony_ci		{
290cc1dc7a3Sopenharmony_ci			unsigned int ymod = y_flip ? dim_y - y - 1 : y;
291cc1dc7a3Sopenharmony_ci			float *dst = buf + y * dim_x * 4;
292cc1dc7a3Sopenharmony_ci
293cc1dc7a3Sopenharmony_ci			for (unsigned int x = 0; x < dim_x; x++)
294cc1dc7a3Sopenharmony_ci			{
295cc1dc7a3Sopenharmony_ci				dst[4 * x    ] = data32[(4 * dim_x * ymod) + (4 * x    )];
296cc1dc7a3Sopenharmony_ci				dst[4 * x + 1] = data32[(4 * dim_x * ymod) + (4 * x + 1)];
297cc1dc7a3Sopenharmony_ci				dst[4 * x + 2] = data32[(4 * dim_x * ymod) + (4 * x + 2)];
298cc1dc7a3Sopenharmony_ci				dst[4 * x + 3] = data32[(4 * dim_x * ymod) + (4 * x + 3)];
299cc1dc7a3Sopenharmony_ci			}
300cc1dc7a3Sopenharmony_ci		}
301cc1dc7a3Sopenharmony_ci	}
302cc1dc7a3Sopenharmony_ci
303cc1dc7a3Sopenharmony_ci	return buf;
304cc1dc7a3Sopenharmony_ci}
305cc1dc7a3Sopenharmony_ci
306cc1dc7a3Sopenharmony_ci/* See header for documentation. */
307cc1dc7a3Sopenharmony_ciuint8_t* unorm8x4_array_from_astc_img(
308cc1dc7a3Sopenharmony_ci	const astcenc_image* img,
309cc1dc7a3Sopenharmony_ci	bool y_flip
310cc1dc7a3Sopenharmony_ci) {
311cc1dc7a3Sopenharmony_ci	unsigned int dim_x = img->dim_x;
312cc1dc7a3Sopenharmony_ci	unsigned int dim_y = img->dim_y;
313cc1dc7a3Sopenharmony_ci	uint8_t* buf = new uint8_t[4 * dim_x * dim_y];
314cc1dc7a3Sopenharmony_ci
315cc1dc7a3Sopenharmony_ci	if (img->data_type == ASTCENC_TYPE_U8)
316cc1dc7a3Sopenharmony_ci	{
317cc1dc7a3Sopenharmony_ci		uint8_t* data8 = static_cast<uint8_t*>(img->data[0]);
318cc1dc7a3Sopenharmony_ci		for (unsigned int y = 0; y < dim_y; y++)
319cc1dc7a3Sopenharmony_ci		{
320cc1dc7a3Sopenharmony_ci			unsigned int ymod = y_flip ? dim_y - y - 1 : y;
321cc1dc7a3Sopenharmony_ci			uint8_t* dst = buf + y * dim_x * 4;
322cc1dc7a3Sopenharmony_ci
323cc1dc7a3Sopenharmony_ci			for (unsigned int x = 0; x < dim_x; x++)
324cc1dc7a3Sopenharmony_ci			{
325cc1dc7a3Sopenharmony_ci				dst[4 * x    ] = data8[(4 * dim_x * ymod) + (4 * x    )];
326cc1dc7a3Sopenharmony_ci				dst[4 * x + 1] = data8[(4 * dim_x * ymod) + (4 * x + 1)];
327cc1dc7a3Sopenharmony_ci				dst[4 * x + 2] = data8[(4 * dim_x * ymod) + (4 * x + 2)];
328cc1dc7a3Sopenharmony_ci				dst[4 * x + 3] = data8[(4 * dim_x * ymod) + (4 * x + 3)];
329cc1dc7a3Sopenharmony_ci			}
330cc1dc7a3Sopenharmony_ci		}
331cc1dc7a3Sopenharmony_ci	}
332cc1dc7a3Sopenharmony_ci	else if (img->data_type == ASTCENC_TYPE_F16)
333cc1dc7a3Sopenharmony_ci	{
334cc1dc7a3Sopenharmony_ci		uint16_t* data16 = static_cast<uint16_t*>(img->data[0]);
335cc1dc7a3Sopenharmony_ci		for (unsigned int y = 0; y < dim_y; y++)
336cc1dc7a3Sopenharmony_ci		{
337cc1dc7a3Sopenharmony_ci			unsigned int ymod = y_flip ? dim_y - y - 1 : y;
338cc1dc7a3Sopenharmony_ci			uint8_t* dst = buf + y * dim_x * 4;
339cc1dc7a3Sopenharmony_ci
340cc1dc7a3Sopenharmony_ci			for (unsigned int x = 0; x < dim_x; x++)
341cc1dc7a3Sopenharmony_ci			{
342cc1dc7a3Sopenharmony_ci				vint4 colori(
343cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x    )],
344cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x + 1)],
345cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x + 2)],
346cc1dc7a3Sopenharmony_ci					data16[(4 * dim_x * ymod) + (4 * x + 3)]
347cc1dc7a3Sopenharmony_ci				);
348cc1dc7a3Sopenharmony_ci
349cc1dc7a3Sopenharmony_ci				vfloat4 color = float16_to_float(colori);
350cc1dc7a3Sopenharmony_ci				color = clamp(0.0f, 1.0f, color) * 255.0f;
351cc1dc7a3Sopenharmony_ci
352cc1dc7a3Sopenharmony_ci				colori = float_to_int_rtn(color);
353cc1dc7a3Sopenharmony_ci				pack_low_bytes(colori);
354cc1dc7a3Sopenharmony_ci				store_nbytes(colori, dst + 4 * x);
355cc1dc7a3Sopenharmony_ci			}
356cc1dc7a3Sopenharmony_ci		}
357cc1dc7a3Sopenharmony_ci	}
358cc1dc7a3Sopenharmony_ci	else // if (img->data_type == ASTCENC_TYPE_F32)
359cc1dc7a3Sopenharmony_ci	{
360cc1dc7a3Sopenharmony_ci		assert(img->data_type == ASTCENC_TYPE_F32);
361cc1dc7a3Sopenharmony_ci		float* data32 = static_cast<float*>(img->data[0]);
362cc1dc7a3Sopenharmony_ci		for (unsigned int y = 0; y < dim_y; y++)
363cc1dc7a3Sopenharmony_ci		{
364cc1dc7a3Sopenharmony_ci			unsigned int ymod = y_flip ? dim_y - y - 1 : y;
365cc1dc7a3Sopenharmony_ci			uint8_t* dst = buf + y * dim_x * 4;
366cc1dc7a3Sopenharmony_ci
367cc1dc7a3Sopenharmony_ci			for (unsigned int x = 0; x < dim_x; x++)
368cc1dc7a3Sopenharmony_ci			{
369cc1dc7a3Sopenharmony_ci				dst[4 * x    ] = static_cast<uint8_t>(astc::flt2int_rtn(astc::clamp1f(data32[(4 * dim_x * ymod) + (4 * x    )]) * 255.0f));
370cc1dc7a3Sopenharmony_ci				dst[4 * x + 1] = static_cast<uint8_t>(astc::flt2int_rtn(astc::clamp1f(data32[(4 * dim_x * ymod) + (4 * x + 1)]) * 255.0f));
371cc1dc7a3Sopenharmony_ci				dst[4 * x + 2] = static_cast<uint8_t>(astc::flt2int_rtn(astc::clamp1f(data32[(4 * dim_x * ymod) + (4 * x + 2)]) * 255.0f));
372cc1dc7a3Sopenharmony_ci				dst[4 * x + 3] = static_cast<uint8_t>(astc::flt2int_rtn(astc::clamp1f(data32[(4 * dim_x * ymod) + (4 * x + 3)]) * 255.0f));
373cc1dc7a3Sopenharmony_ci			}
374cc1dc7a3Sopenharmony_ci		}
375cc1dc7a3Sopenharmony_ci	}
376cc1dc7a3Sopenharmony_ci
377cc1dc7a3Sopenharmony_ci	return buf;
378cc1dc7a3Sopenharmony_ci}
379