mirror of
https://github.com/openharmony/third_party_astc-encoder.git
synced 2026-07-19 18:23:37 -04:00
add stride; add calculate ssd
Signed-off-by: f00849353 <fanghuameng@huawei.com>
This commit is contained in:
@@ -162,6 +162,17 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#define QUALITY_CONTROL (1)
|
||||
#if QUALITY_CONTROL
|
||||
enum ComponentRGBA {
|
||||
R_COM = 0,
|
||||
G_COM,
|
||||
B_COM,
|
||||
A_COM,
|
||||
RGBA_COM
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(ASTCENC_DYNAMIC_LIBRARY)
|
||||
#if defined(_MSC_VER)
|
||||
#define ASTCENC_PUBLIC extern "C" __declspec(dllexport)
|
||||
@@ -213,6 +224,9 @@ enum astcenc_error {
|
||||
/** @brief The call failed due to an issue with diagnostic tracing. */
|
||||
ASTCENC_ERR_DTRACE_FAILURE,
|
||||
#endif
|
||||
#if QUALITY_CONTROL
|
||||
ASTCENC_ERR_BAD_QUALITY_CHECK
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -541,6 +555,9 @@ struct astcenc_config
|
||||
*/
|
||||
struct astcenc_image
|
||||
{
|
||||
/** @brief The stride dimension of the image, in texels. */
|
||||
unsigned int dim_stride;
|
||||
|
||||
/** @brief The X dimension of the image, in texels. */
|
||||
unsigned int dim_x;
|
||||
|
||||
@@ -707,6 +724,10 @@ ASTCENC_PUBLIC astcenc_error astcenc_compress_image(
|
||||
const astcenc_swizzle* swizzle,
|
||||
uint8_t* data_out,
|
||||
size_t data_len,
|
||||
#if QUALITY_CONTROL
|
||||
bool calQualityEnable,
|
||||
int32_t *mse[RGBA_COM],
|
||||
#endif
|
||||
unsigned int thread_index);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1164,7 +1164,14 @@ void compress_block(
|
||||
const astcenc_context& ctx,
|
||||
const image_block& blk,
|
||||
physical_compressed_block& pcb,
|
||||
compression_working_buffers& tmpbuf)
|
||||
#if QUALITY_CONTROL
|
||||
compression_working_buffers& tmpbuf,
|
||||
bool calQualityEnable,
|
||||
int32_t *mseBlock[RGBA_COM]
|
||||
#else
|
||||
compression_working_buffers& tmpbuf
|
||||
#endif
|
||||
)
|
||||
{
|
||||
astcenc_profile decode_mode = ctx.config.profile;
|
||||
symbolic_compressed_block scb;
|
||||
@@ -1230,6 +1237,11 @@ void compress_block(
|
||||
trace_add_data("exit", "quality hit");
|
||||
|
||||
symbolic_to_physical(bsd, scb, pcb);
|
||||
#if QUALITY_CONTROL
|
||||
if (calQualityEnable) {
|
||||
*mseBlock[R_COM] = *mseBlock[G_COM] = *mseBlock[B_COM] = *mseBlock[A_COM];
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1416,6 +1428,23 @@ END_OF_TESTS:
|
||||
|
||||
// Compress to a physical block
|
||||
symbolic_to_physical(bsd, scb, pcb);
|
||||
#if QUALITY_CONTROL
|
||||
if (calQualityEnable) {
|
||||
image_block decBlk = blk;
|
||||
decompress_symbolic_block(ctx.config.profile, bsd, blk.xpos, blk.ypos, blk.zpos, scb, decBlk);
|
||||
vint4 colorSumDiff = vint4::zero();
|
||||
for (size_t ii = 0; ii < bsd.texel_count; ii++) {
|
||||
vint4 colorRef = float_to_int_rtn(blk.texel(ii) * 255.0f / 65535.0f);
|
||||
vint4 colorTest = float_to_int_rtn(min(decBlk.texel(ii), 1.0f) * 255.0f);
|
||||
vint4 colorDiff = colorRef - colorTest;
|
||||
colorSumDiff += colorDiff * colorDiff;
|
||||
}
|
||||
*mseBlock[R_COM] = colorSumDiff.lane<0>();
|
||||
*mseBlock[G_COM] = colorSumDiff.lane<1>();
|
||||
*mseBlock[B_COM] = colorSumDiff.lane<2>();
|
||||
*mseBlock[A_COM] = colorSumDiff.lane<3>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -182,10 +182,10 @@ static void compute_pixel_region_variance(
|
||||
int x_src = (x - 1) + offset_x - kernel_radius_xy;
|
||||
x_src = astc::clamp(x_src, 0, static_cast<int>(img->dim_x - 1));
|
||||
|
||||
data[0] = data8[(4 * img->dim_x * y_src) + (4 * x_src )];
|
||||
data[1] = data8[(4 * img->dim_x * y_src) + (4 * x_src + 1)];
|
||||
data[2] = data8[(4 * img->dim_x * y_src) + (4 * x_src + 2)];
|
||||
data[3] = data8[(4 * img->dim_x * y_src) + (4 * x_src + 3)];
|
||||
data[0] = data8[(4 * img->dim_stride * y_src) + (4 * x_src )];
|
||||
data[1] = data8[(4 * img->dim_stride * y_src) + (4 * x_src + 1)];
|
||||
data[2] = data8[(4 * img->dim_stride * y_src) + (4 * x_src + 2)];
|
||||
data[3] = data8[(4 * img->dim_stride * y_src) + (4 * x_src + 3)];
|
||||
|
||||
uint8_t r = data[swz.r];
|
||||
uint8_t g = data[swz.g];
|
||||
|
||||
@@ -806,7 +806,13 @@ static void compress_image(
|
||||
unsigned int thread_index,
|
||||
const astcenc_image& image,
|
||||
const astcenc_swizzle& swizzle,
|
||||
#if QUALITY_CONTROL
|
||||
uint8_t* buffer,
|
||||
bool calQualityEnable,
|
||||
int32_t *mse[RGBA_COM]
|
||||
#else
|
||||
uint8_t* buffer
|
||||
#endif
|
||||
) {
|
||||
const block_size_descriptor& bsd = *ctx.bsd;
|
||||
astcenc_profile decode_mode = ctx.config.profile;
|
||||
@@ -932,7 +938,19 @@ static void compress_image(
|
||||
int offset = ((z * yblocks + y) * xblocks + x) * 16;
|
||||
uint8_t *bp = buffer + offset;
|
||||
physical_compressed_block* pcb = reinterpret_cast<physical_compressed_block*>(bp);
|
||||
#if QUALITY_CONTROL
|
||||
int32_t *mseBlock[RGBA_COM] = {nullptr, nullptr, nullptr, nullptr};
|
||||
if (calQualityEnable) {
|
||||
int offset = (z * yblocks + y) * xblocks + x;
|
||||
mseBlock[R_COM] = mse[R_COM] + offset;
|
||||
mseBlock[G_COM] = mse[G_COM] + offset;
|
||||
mseBlock[B_COM] = mse[B_COM] + offset;
|
||||
mseBlock[A_COM] = mse[A_COM] + offset;
|
||||
}
|
||||
compress_block(ctx, blk, *pcb, temp_buffers, calQualityEnable, mseBlock);
|
||||
#else
|
||||
compress_block(ctx, blk, *pcb, temp_buffers);
|
||||
#endif
|
||||
}
|
||||
|
||||
ctx.manage_compress.complete_task_assignment(count);
|
||||
@@ -948,6 +966,10 @@ astcenc_error astcenc_compress_image(
|
||||
const astcenc_swizzle* swizzle,
|
||||
uint8_t* data_out,
|
||||
size_t data_len,
|
||||
#if QUALITY_CONTROL
|
||||
bool calQualityEnable,
|
||||
int32_t *mse[RGBA_COM],
|
||||
#endif
|
||||
unsigned int thread_index
|
||||
) {
|
||||
#if defined(ASTCENC_DECOMPRESS_ONLY)
|
||||
@@ -1022,9 +1044,11 @@ astcenc_error astcenc_compress_image(
|
||||
|
||||
// Wait for compute_averages to complete before compressing
|
||||
ctx->manage_avg.wait();
|
||||
|
||||
#if QUALITY_CONTROL
|
||||
compress_image(*ctx, thread_index, image, *swizzle, data_out, calQualityEnable, mse);
|
||||
#else
|
||||
compress_image(*ctx, thread_index, image, *swizzle, data_out);
|
||||
|
||||
#endif
|
||||
// Wait for compress to complete before freeing memory
|
||||
ctx->manage_compress.wait();
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ void fetch_image_block_fast_ldr(
|
||||
|
||||
unsigned int xsize = img.dim_x;
|
||||
unsigned int ysize = img.dim_y;
|
||||
|
||||
unsigned int stride = img.dim_stride;
|
||||
blk.xpos = xpos;
|
||||
blk.ypos = ypos;
|
||||
blk.zpos = zpos;
|
||||
@@ -300,7 +300,7 @@ void fetch_image_block_fast_ldr(
|
||||
{
|
||||
unsigned int xi = astc::min(x, xsize - 1);
|
||||
|
||||
vint4 datavi = vint4(plane + (4 * xsize * yi) + (4 * xi));
|
||||
vint4 datavi = vint4(plane + (4 * stride * yi) + (4 * xi));
|
||||
vfloat4 datav = int_to_float(datavi) * (65535.0f / 255.0f);
|
||||
|
||||
// Compute block metadata
|
||||
|
||||
@@ -1351,6 +1351,9 @@ struct avg_args
|
||||
pixel_region_args arg;
|
||||
|
||||
// The above has a reference to the image altread?
|
||||
/** @brief The image Stride dimensions. */
|
||||
unsigned int img_size_stride;
|
||||
|
||||
/** @brief The image X dimensions. */
|
||||
unsigned int img_size_x;
|
||||
|
||||
@@ -2284,7 +2287,14 @@ void compress_block(
|
||||
const astcenc_context& ctx,
|
||||
const image_block& blk,
|
||||
physical_compressed_block& pcb,
|
||||
compression_working_buffers& tmpbuf);
|
||||
#if QUALITY_CONTROL
|
||||
compression_working_buffers& tmpbuf,
|
||||
bool calQualityEnable,
|
||||
int32_t *mseBlock[RGBA_COM]
|
||||
#else
|
||||
compression_working_buffers& tmpbuf
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Decompress a symbolic block in to an image block.
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
@@ -139,6 +139,10 @@ struct compression_workload
|
||||
uint8_t* data_out;
|
||||
size_t data_len;
|
||||
astcenc_error error;
|
||||
#if QUALITY_CONTROL
|
||||
bool calQualityEnable;
|
||||
int32_t *mse[RGBA_COM];
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -198,7 +202,11 @@ static void compression_workload_runner(
|
||||
compression_workload* work = static_cast<compression_workload*>(payload);
|
||||
astcenc_error error = astcenc_compress_image(
|
||||
work->context, work->image, &work->swizzle,
|
||||
work->data_out, work->data_len, thread_id);
|
||||
work->data_out, work->data_len,
|
||||
#if QUALITY_CONTROL
|
||||
work->calQualityEnable, work->mse,
|
||||
#endif
|
||||
thread_id);
|
||||
|
||||
// This is a racy update, so which error gets returned is a random, but it
|
||||
// will reliably report an error if an error occurs
|
||||
@@ -1329,6 +1337,53 @@ static void image_preprocess_premultiply(
|
||||
}
|
||||
}
|
||||
|
||||
#if QUALITY_CONTROL
|
||||
constexpr double MAX_PSNR = 99.9;
|
||||
constexpr double MAX_VALUE = 255;
|
||||
constexpr double THRESHOLD_R = 30.0;
|
||||
constexpr double THRESHOLD_G = 30.0;
|
||||
constexpr double THRESHOLD_B = 30.0;
|
||||
constexpr double THRESHOLD_A = 30.0;
|
||||
constexpr double THRESHOLD_RGB = 30.0;
|
||||
constexpr double LOG_BASE = 10.0;
|
||||
|
||||
bool CheckQuality(int32_t* mseIn[RGBA_COM], int blockNum, int blockXYZ)
|
||||
{
|
||||
double psnr[RGBA_COM + 1];
|
||||
double threshold[RGBA_COM + 1] = { THRESHOLD_R, THRESHOLD_G, THRESHOLD_B, THRESHOLD_A, THRESHOLD_RGB};
|
||||
uint64_t mseTotal[RGBA_COM + 1] = { 0, 0, 0, 0, 0};
|
||||
for (int i = R_COM; i < RGBA_COM; i++) {
|
||||
int32_t* mse = mseIn[i];
|
||||
for (int j = 0; j < blockNum; j++) {
|
||||
mseTotal[i] += *mse;
|
||||
if(i != A_COM) mseTotal[RGBA_COM] += *mse;
|
||||
mse++;
|
||||
}
|
||||
}
|
||||
for (int i = R_COM; i < RGBA_COM; i++) {
|
||||
if (mseTotal[i] == 0) {
|
||||
psnr[i] = MAX_PSNR;
|
||||
continue;
|
||||
}
|
||||
double mseRgb = (double)mseTotal[i] / (blockNum * blockXYZ);
|
||||
psnr[i] = LOG_BASE * log((double)(MAX_VALUE * MAX_VALUE) / mseRgb) / log(LOG_BASE);
|
||||
}
|
||||
if (mseTotal[RGBA_COM] == 0) {
|
||||
psnr[RGBA_COM] = MAX_PSNR;
|
||||
}
|
||||
else {
|
||||
double mseRgb = (double)mseTotal[RGBA_COM] / (blockNum * blockXYZ * (RGBA_COM - 1));
|
||||
psnr[RGBA_COM] = LOG_BASE * log((double)(MAX_VALUE * MAX_VALUE) / mseRgb) / log(LOG_BASE);
|
||||
}
|
||||
printf("astc psnr r%f g%f b%f a%f rgb%f\n",
|
||||
psnr[R_COM], psnr[G_COM], psnr[B_COM], psnr[A_COM],
|
||||
psnr[RGBA_COM]);
|
||||
return (psnr[R_COM] > threshold[R_COM]) && (psnr[G_COM] > threshold[G_COM])
|
||||
&& (psnr[B_COM] > threshold[B_COM]) && (psnr[A_COM] > threshold[A_COM])
|
||||
&& (psnr[RGBA_COM] > threshold[RGBA_COM]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The main entry point.
|
||||
*
|
||||
@@ -1584,12 +1639,25 @@ int main(
|
||||
|
||||
compression_workload work;
|
||||
work.context = codec_context;
|
||||
image_uncomp_in->dim_stride = image_uncomp_in->dim_x;
|
||||
work.image = image_uncomp_in;
|
||||
work.swizzle = cli_config.swz_encode;
|
||||
work.data_out = buffer;
|
||||
work.data_len = buffer_size;
|
||||
work.error = ASTCENC_SUCCESS;
|
||||
|
||||
#if QUALITY_CONTROL
|
||||
work.calQualityEnable = true;
|
||||
work.mse[R_COM] = work.mse[G_COM] = work.mse[B_COM] = work.mse[A_COM] = nullptr;
|
||||
if (work.calQualityEnable) {
|
||||
for (int i = R_COM; i < RGBA_COM; i++) {
|
||||
work.mse[i] = (int32_t*)calloc(blocks_x * blocks_y, sizeof(int32_t));
|
||||
if (!work.mse[i]) {
|
||||
printf("quality control calloc failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Only launch worker threads for multi-threaded use - it makes basic
|
||||
// single-threaded profiling and debugging a little less convoluted
|
||||
if (cli_config.thread_count > 1)
|
||||
@@ -1600,7 +1668,11 @@ int main(
|
||||
{
|
||||
work.error = astcenc_compress_image(
|
||||
work.context, work.image, &work.swizzle,
|
||||
work.data_out, work.data_len, 0);
|
||||
work.data_out, work.data_len,
|
||||
#if QUALITY_CONTROL
|
||||
work.calQualityEnable, work.mse,
|
||||
#endif
|
||||
0);
|
||||
}
|
||||
|
||||
if (work.error != ASTCENC_SUCCESS)
|
||||
@@ -1608,7 +1680,18 @@ int main(
|
||||
printf("ERROR: Codec compress failed: %s\n", astcenc_get_error_string(work.error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if QUALITY_CONTROL
|
||||
if (work.calQualityEnable && !CheckQuality(work.mse, blocks_x * blocks_y, config.block_x * config.block_y)) {
|
||||
work.error = ASTCENC_ERR_BAD_QUALITY_CHECK;
|
||||
}
|
||||
if (work.calQualityEnable) {
|
||||
for (int i = R_COM; i < RGBA_COM; i++) {
|
||||
if (work.mse[i]) {
|
||||
free(work.mse[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
image_comp.block_x = config.block_x;
|
||||
image_comp.block_y = config.block_y;
|
||||
image_comp.block_z = config.block_z;
|
||||
|
||||
Reference in New Issue
Block a user