1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
|
// example_capi.c - Plain C API examples
// Compresses a procedurally generated 32bpp 512x512 test image to a XUASTC LDR 8x5 .ktx2 file with mipmaps and writes a .ktx2 file.
// The .ktx2 file is then opened by the transcoder module, examined and unpacked to RGBA 32bpp and ASTC textures which are saved to disk as .tga and .astc files.
// The .tga image files can be viewed by many common image editors/viewers.
// The standard .astc texture files can be unpacked to .PNG using ARM's astcenc tool, using a command line like this: astcenc-avx2.exe -ds transcoded_0_0_0.astc 0.png
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <memory.h>
typedef int BOOL;
#define TRUE (1)
#define FALSE (0)
// Include compressor and transcoder C API definitions
#include "../encoder/basisu_wasm_api.h"
#include "../encoder/basisu_wasm_transcoder_api.h"
// Write a blob of data in memory to a file
int write_blob_to_file(const char* pFilename, const void* pData, size_t len)
{
assert(pFilename != NULL);
assert(pData != NULL);
if (!pFilename || !pData)
return FALSE;
FILE* f = fopen(pFilename, "wb");
if (!f)
return FALSE;
/* Write the data */
size_t written = fwrite(pData, 1, len, f);
if (written != len)
{
fclose(f);
return FALSE;
}
if (fclose(f) != 0)
return FALSE;
return TRUE; /* success */
}
// Writes 24/32bpp .TGA image files
int write_tga_image(const char* pFilename, int w, int h, int has_alpha, const uint8_t* pPixelsRGBA)
{
assert(pFilename != NULL);
assert(pPixelsRGBA != NULL);
assert(w > 0);
assert(h > 0);
assert((has_alpha == 0) || (has_alpha == 1));
/* Runtime argument validation */
if ((!pFilename) || (!pPixelsRGBA) || (w <= 0) || (h <= 0))
return -1; // invalid argument
FILE* pFile = fopen(pFilename, "wb");
if (!pFile)
return -2; // cannot open file
uint8_t header[18] = { 0 };
header[2] = 2; // uncompressed true-color
header[12] = (uint8_t)(w & 0xFF);
header[13] = (uint8_t)((w >> 8) & 0xFF);
header[14] = (uint8_t)(h & 0xFF);
header[15] = (uint8_t)((h >> 8) & 0xFF);
header[16] = has_alpha ? 32 : 24;
/* Classic TGA: bottom-left origin */
header[17] = has_alpha ? 8 : 0;
if (fwrite(header, 1, 18, pFile) != 18)
{
fclose(pFile);
return -3; // header write failed
}
uint64_t bytes_per_pixel = has_alpha ? 4ULL : 3ULL;
uint64_t pixel_bytes_u64 = (uint64_t)w * (uint64_t)h * bytes_per_pixel;
size_t pixel_bytes = (size_t)pixel_bytes_u64;
if ((uint64_t)pixel_bytes != pixel_bytes_u64)
return -6; // overflow bogus dimensions
/* allocate one scanline for BGRA/BGR output */
size_t row_bytes = (size_t)w * bytes_per_pixel;
uint8_t* pRow = (uint8_t*)malloc(row_bytes);
if (!pRow)
{
fclose(pFile);
return -7; // out of memory
}
/* TGA expects rows in bottom-to-top order */
for (int y = 0; y < h; y++)
{
const uint8_t* pSrcRow = pPixelsRGBA + (size_t)(h - 1 - y) * w * bytes_per_pixel;
/* Convert RGBA->BGRA or RGB->BGR for this row */
if (has_alpha)
{
/* 4 bytes per pixel */
for (int x = 0; x < w; x++)
{
const uint8_t* s = &pSrcRow[x * 4];
uint8_t* d = &pRow[x * 4];
d[0] = s[2]; // B
d[1] = s[1]; // G
d[2] = s[0]; // R
d[3] = s[3]; // A
}
}
else
{
/* 3 bytes per pixel */
for (int x = 0; x < w; x++)
{
const uint8_t* s = &pSrcRow[x * 3];
uint8_t* d = &pRow[x * 3];
d[0] = s[2]; // B
d[1] = s[1]; // G
d[2] = s[0]; // R
}
}
if (fwrite(pRow, 1, row_bytes, pFile) != row_bytes)
{
free(pRow);
fclose(pFile);
return -4; // pixel write failed
}
}
free(pRow);
if (fclose(pFile) != 0)
return -5; // close failed
return 0; // success
}
// Write standard ARM .ASTC format texture files
int write_astc_file(const char* pFilename,
const void* pBlocks, // pointer to ASTC blocks
uint32_t block_width, // in texels [4,12]
uint32_t block_height, // in texels [4,12]
uint32_t dim_x, // image actual dimension in texels
uint32_t dim_y) // image actual dimension in texels
{
assert(pFilename != NULL);
assert(pBlocks != NULL);
assert(dim_x > 0);
assert(dim_y > 0);
assert((block_width >= 4) && (block_width <= 12));
assert((block_height >= 4) && (block_height <= 12));
FILE* f = fopen(pFilename, "wb");
if (!f)
return 0;
/* Helper macro for writing single bytes with error check */
#define PUTB(v) do { if (fputc((int)(v), f) == EOF) { fclose(f); return 0; } } while (0)
/* Magic */
PUTB(0x13);
PUTB(0xAB);
PUTB(0xA1);
PUTB(0x5C);
/* Block dimensions: x, y, z = 1 */
PUTB((uint8_t)block_width);
PUTB((uint8_t)block_height);
PUTB(1); /* block depth */
/* dim_x (24-bit little endian) */
PUTB((uint8_t)(dim_x & 0xFF));
PUTB((uint8_t)((dim_x >> 8) & 0xFF));
PUTB((uint8_t)((dim_x >> 16) & 0xFF));
/* dim_y (24-bit little endian) */
PUTB((uint8_t)(dim_y & 0xFF));
PUTB((uint8_t)((dim_y >> 8) & 0xFF));
PUTB((uint8_t)((dim_y >> 16) & 0xFF));
/* dim_z = 1 (24-bit LE) */
PUTB(1);
PUTB(0);
PUTB(0);
/* Compute block count and total bytes */
uint32_t num_blocks_x = (dim_x + block_width - 1) / block_width;
uint32_t num_blocks_y = (dim_y + block_height - 1) / block_height;
uint64_t total_bytes_u64 =
(uint64_t)num_blocks_x * (uint64_t)num_blocks_y * 16ULL;
size_t total_bytes = (size_t)total_bytes_u64;
if ((uint64_t)total_bytes != total_bytes_u64)
{
fclose(f);
return 0; /* overflow → fail */
}
/* Write block data directly */
size_t written = fwrite(pBlocks, 1, total_bytes, f);
if (written != total_bytes)
{
fclose(f); /* still close even if error */
return 0;
}
if (fclose(f) != 0)
return 0;
return 1; /* success */
#undef PUTB
}
// Procedurally create a simple test image in memory
uint8_t* create_pretty_rgba_pattern(int w, int h, float q)
{
if (w <= 0 || h <= 0)
return NULL;
uint8_t* pImage = (uint8_t*)malloc((size_t)w * h * 4);
if (!pImage)
return NULL;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
/* normalized coordinates 0..1 */
float fx = (float)x / (float)w;
float fy = (float)y / (float)h;
/* --- Extra coordinate warping when q != 0 --- */
if (q != 0.0f) {
float warp = sinf((fx + fy) * 10.0f * q);
fx += 0.15f * q * warp;
fy += 0.15f * q * sinf((fx - fy) * 8.0f * q);
}
/* Original plasma formula */
float v = sinf(fx * 12.0f + fy * 4.0f);
v += sinf(fy * 9.0f - fx * 6.0f);
v += sinf((fx + fy) * 7.0f);
/* Extra variation term — contributes only when q != 0 */
if (q != 0.0f)
{
v += q * 0.7f * sinf((fx * fx + fy) * 20.0f);
v += q * 0.4f * cosf((fx - fy) * 18.0f);
}
/* scale to 0..1 */
v = v * 0.25f + 0.5f;
float L = 1.5f;
/* Convert to RGB colors */
int r = (int)roundf(255.0f * sinf(v * 6.28f) * L);
int g = (int)roundf(255.0f * (1.0f - v) * L);
int b = (int)roundf(255.0f * v * L);
/* clamp */
if (r < 0) r = 0; else if (r > 255) r = 255;
if (g < 0) g = 0; else if (g > 255) g = 255;
if (b < 0) b = 0; else if (b > 255) b = 255;
/* write RGBA */
uint8_t* p = &pImage[(y * w + x) * 4];
p[0] = (uint8_t)r;
p[1] = (uint8_t)g;
p[2] = (uint8_t)b;
p[3] = 255;
}
}
return pImage;
}
// Takes a KTX2 file in memory and displays info about it, then transcodes it to RGBA32 and ASTC, writing .tga/.astc files to disk
int transcode_ktx2_file(const void* pKTX2_data, size_t ktx2_data_size, const char *pDesc)
{
printf("------ transcode_ktx2_file(): ktx2 size: %zu, desc: %s\n", ktx2_data_size, pDesc);
if (!pKTX2_data || !ktx2_data_size)
return FALSE;
if ((uint32_t)ktx2_data_size != ktx2_data_size)
return FALSE;
uint64_t ktx2_data_ofs = bt_alloc(ktx2_data_size);
if (!ktx2_data_ofs)
return FALSE;
memcpy((void*)ktx2_data_ofs, pKTX2_data, ktx2_data_size);
uint64_t ktx2_handle = bt_ktx2_open(ktx2_data_ofs, (uint32_t)ktx2_data_size);
if (!ktx2_handle)
{
bt_free(ktx2_data_ofs);
return FALSE;
}
// Just testing LDR here for now
if (!bt_ktx2_is_ldr(ktx2_handle))
{
bt_ktx2_close(ktx2_handle);
bt_free(ktx2_data_ofs);
return FALSE;
}
if (!bt_ktx2_start_transcoding(ktx2_handle))
{
bt_ktx2_close(ktx2_handle);
bt_free(ktx2_data_ofs);
return FALSE;
}
uint32_t width = bt_ktx2_get_width(ktx2_handle), height = bt_ktx2_get_height(ktx2_handle);
uint32_t levels = bt_ktx2_get_levels(ktx2_handle); // number of mipmap levels, must be >= 1
uint32_t faces = bt_ktx2_get_faces(ktx2_handle); // 1 or 6
uint32_t layers = bt_ktx2_get_layers(ktx2_handle); // 0 or array size
uint32_t basis_tex_format = bt_ktx2_get_basis_tex_format(ktx2_handle);
uint32_t block_width = bt_ktx2_get_block_width(ktx2_handle);
uint32_t block_height = bt_ktx2_get_block_height(ktx2_handle);
uint32_t is_srgb = bt_ktx2_is_srgb(ktx2_handle);
uint32_t is_video = bt_ktx2_is_video(ktx2_handle); // only reliably set after calling bt_ktx2_start_transcoding()
printf("KTX2 Dimensions: %ux%u, Levels: %u, Faces: %u, Layers: %u\n", width, height, levels, faces, layers);
printf("basis_tex_format: %u\n", basis_tex_format);
printf("Block dimensions: %ux%u\n", block_width, block_height);
printf("is sRGB: %u\n", is_srgb);
printf("is video: %u\n", is_video);
assert((width >= 1) && (height >= 1));
assert(levels >= 1);
assert((faces == 6) || (faces == 1));
// If layers==0 it's not a texture array
if (layers < 1)
layers = 1;
// Create our transcoding state handle (which contains thread-local state)
// This is actually optional, and only needed for thread-safe transcoding, but we'll test it here.
uint64_t transcode_state_handle = bt_ktx2_create_transcode_state();
for (uint32_t level_index = 0; level_index < levels; level_index++)
{
for (uint32_t layer_index = 0; layer_index < layers; layer_index++)
{
for (uint32_t face_index = 0; face_index < faces; face_index++)
{
printf("- Level: %u, layer: %u, face: %u\n", level_index, layer_index, face_index);
uint32_t orig_width = bt_ktx2_get_level_orig_width(ktx2_handle, level_index, layer_index, face_index);
uint32_t orig_height = bt_ktx2_get_level_orig_height(ktx2_handle, level_index, layer_index, face_index);
printf(" Orig dimensions: %ux%u, actual: %ux%u\n",
orig_width, orig_height,
bt_ktx2_get_level_actual_width(ktx2_handle, level_index, layer_index, face_index), bt_ktx2_get_level_actual_height(ktx2_handle, level_index, layer_index, face_index));
printf(" Block dimensions: %ux%u, total blocks: %u\n",
bt_ktx2_get_level_num_blocks_x(ktx2_handle, level_index, layer_index, face_index),
bt_ktx2_get_level_num_blocks_y(ktx2_handle, level_index, layer_index, face_index),
bt_ktx2_get_level_total_blocks(ktx2_handle, level_index, layer_index, face_index));
printf(" Alpha flag: %u, iframe flag: %u\n",
bt_ktx2_get_level_alpha_flag(ktx2_handle, level_index, layer_index, face_index),
bt_ktx2_get_level_iframe_flag(ktx2_handle, level_index, layer_index, face_index));
// First transcode level to uncompressed RGBA32 and write a .tga file
{
char tga_filename[256];
snprintf(tga_filename, sizeof(tga_filename), "transcoded_%s_L%u_Y%u_F%u.tga", pDesc, level_index, layer_index, face_index);
uint32_t transcode_buf_size = bt_basis_compute_transcoded_image_size_in_bytes(TF_RGBA32, orig_width, orig_height);
assert(transcode_buf_size);
uint64_t transcode_buf_ofs = bt_alloc(transcode_buf_size);
uint32_t decode_flags = 0;
if (!bt_ktx2_transcode_image_level(ktx2_handle, level_index, layer_index, face_index,
transcode_buf_ofs, transcode_buf_size,
TF_RGBA32,
decode_flags,
0, 0, -1, -1, transcode_state_handle))
{
bt_free(transcode_buf_ofs);
bt_ktx2_destroy_transcode_state(transcode_state_handle);
bt_ktx2_close(ktx2_handle);
bt_free(ktx2_data_ofs);
return FALSE;
}
write_tga_image(tga_filename, orig_width, orig_height, TRUE, (uint8_t*)transcode_buf_ofs);
printf("Wrote file %s\n", tga_filename);
bt_free(transcode_buf_ofs);
transcode_buf_ofs = 0;
}
// Now transcode to ASTC and write a .astc file
{
char astc_filename[256];
snprintf(astc_filename, sizeof(astc_filename), "transcoded_%s_L%u_Y%u_F%u.astc", pDesc, level_index, layer_index, face_index);
// Determine the correct ASTC transcode texture format from the ktx2 format
uint32_t target_transcode_fmt = bt_basis_get_transcoder_texture_format_from_basis_tex_format(basis_tex_format);
uint32_t transcode_buf_size = bt_basis_compute_transcoded_image_size_in_bytes(target_transcode_fmt, orig_width, orig_height);
assert(transcode_buf_size);
uint64_t transcode_buf_ofs = bt_alloc(transcode_buf_size);
uint32_t decode_flags = 0;
if (!bt_ktx2_transcode_image_level(ktx2_handle, level_index, layer_index, face_index,
transcode_buf_ofs, transcode_buf_size,
target_transcode_fmt,
decode_flags,
0, 0, -1, -1, transcode_state_handle))
{
bt_free(transcode_buf_ofs);
bt_ktx2_destroy_transcode_state(transcode_state_handle);
bt_ktx2_close(ktx2_handle);
bt_free(ktx2_data_ofs);
return FALSE;
}
write_astc_file(astc_filename, (void*)transcode_buf_ofs, block_width, block_height, orig_width, orig_height);
printf("Wrote .astc file %s\n", astc_filename);
bt_free(transcode_buf_ofs);
transcode_buf_ofs = 0;
}
} // face_index
} // layer_index
} // level_index
bt_ktx2_destroy_transcode_state(transcode_state_handle);
transcode_state_handle = 0;
bt_ktx2_close(ktx2_handle);
ktx2_handle = 0;
bt_free(ktx2_data_ofs);
ktx2_data_ofs = 0;
return TRUE;
}
// Simple 2D test
int test_2D()
{
printf("------ test_2D():\n");
// Generate a test image
int W = 512, H = 512;
uint8_t* pSrc_image = create_pretty_rgba_pattern(W, H, 0.0f);
// Save the test image to a .tga file
write_tga_image("test_image.tga", W, H, TRUE, pSrc_image);
printf("Wrote file test_image.tga\n");
// Compress it to .ktx2
uint64_t comp_params = bu_new_comp_params();
// Allocate memory
uint64_t img_ofs = bu_alloc(W * H * 4);
if (!img_ofs)
{
fprintf(stderr, "bu_alloc() failed\n");
return EXIT_FAILURE;
}
// Copy the test image into the allocated memory
memcpy((void*)img_ofs, pSrc_image, W * H * 4);
// Supply the image to the compressor - it'll immediately make a copy of the data
if (!bu_comp_params_set_image_rgba32(comp_params, 0, img_ofs, W, H, W * 4))
{
fprintf(stderr, "bu_comp_params_set_image_rgba32() failed\n");
return EXIT_FAILURE;
}
bu_free(img_ofs);
img_ofs = 0;
// Now compress it to XUASTC LDR 8x5 with weight grid DCT
uint32_t basis_tex_format = BTF_XUASTC_LDR_8X5;
//uint32_t basis_tex_format = BTF_ASTC_LDR_8X5;
//uint32_t basis_tex_format = BTF_ETC1S;
//uint32_t basis_tex_format = BTF_UASTC_LDR_4X4;
uint32_t quality_level = 85;
uint32_t effort_level = 2;
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_SRGB |
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_GEN_MIPS_CLAMP |
BU_COMP_FLAGS_PRINT_STATS | BU_COMP_FLAGS_PRINT_STATUS;
if (!bu_compress_texture(comp_params, basis_tex_format, quality_level, effort_level, flags, 0.0f))
{
fprintf(stderr, "bu_compress_texture() failed\n");
return EXIT_FAILURE;
}
// Retrieve the compressed .KTX2 file data
uint64_t comp_size = bu_comp_params_get_comp_data_size(comp_params);
if (!comp_size)
{
fprintf(stderr, "bu_comp_params_get_comp_data_size() failed\n");
return EXIT_FAILURE;
}
void* pComp_data = (void*)bu_comp_params_get_comp_data_ofs(comp_params);
if (!pComp_data)
{
fprintf(stderr, "bu_comp_params_get_comp_data_ofs() failed\n");
return EXIT_FAILURE;
}
// Write the data to disk
write_blob_to_file("test.ktx2", pComp_data, comp_size);
printf("Wrote file test.ktx2\n");
// Now inspect and transcode the .KTX2 data to png/astc files
if (!transcode_ktx2_file(pComp_data, comp_size, "2D"))
{
fprintf(stderr, "transcode_ktx2_file() failed\n");
return EXIT_FAILURE;
}
bu_delete_comp_params(comp_params);
free(pSrc_image);
return EXIT_SUCCESS;
}
// 2D array/texture video test
int test_2D_array(BOOL tex_video_flag, int L, BOOL mipmap_flag)
{
printf("------ test_2D_array() %i %i %i:\n", tex_video_flag, L, mipmap_flag);
// Generate a test image
int W = 256, H = 256;
// Compress it to .ktx2
uint64_t comp_params = bu_new_comp_params();
const char* pDesc = tex_video_flag ? "video" : "array";
char filename_buf[256];
for (int layer = 0; layer < L; layer++)
{
uint8_t* pSrc_image = create_pretty_rgba_pattern(W, H, (float)layer * .05f);
// Save the test image to a .tga file
snprintf(filename_buf, sizeof(filename_buf), "test_%s_layer_%u.tga", pDesc, layer);
write_tga_image(filename_buf, W, H, TRUE, pSrc_image);
printf("Wrote file %s\n", filename_buf);
// Allocate memory
uint64_t img_ofs = bu_alloc(W * H * 4);
if (!img_ofs)
{
fprintf(stderr, "bu_alloc() failed\n");
return EXIT_FAILURE;
}
// Copy the test image into the allocated memory
memcpy((void*)img_ofs, pSrc_image, W * H * 4);
// Supply the image to the compressor - it'll immediately make a copy of the data
if (!bu_comp_params_set_image_rgba32(comp_params, layer, img_ofs, W, H, W * 4))
{
fprintf(stderr, "bu_comp_params_set_image_rgba32() failed\n");
return EXIT_FAILURE;
}
bu_free(img_ofs);
img_ofs = 0;
free(pSrc_image);
} // layer
// ETC1S has special optimizations for texture video (basic p-frames with skip blocks).
uint32_t basis_tex_format = tex_video_flag ? BTF_ETC1S : BTF_XUASTC_LDR_4X4;
uint32_t quality_level = 100;
uint32_t effort_level = 4;
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_SRGB |
BU_COMP_FLAGS_THREADED |
BU_COMP_FLAGS_PRINT_STATS | BU_COMP_FLAGS_PRINT_STATUS;
if (tex_video_flag)
flags |= BU_COMP_FLAGS_TEXTURE_TYPE_VIDEO_FRAMES;
else
flags |= BU_COMP_FLAGS_TEXTURE_TYPE_2D_ARRAY;
if (mipmap_flag)
flags |= BU_COMP_FLAGS_GEN_MIPS_CLAMP;
if (!bu_compress_texture(comp_params, basis_tex_format, quality_level, effort_level, flags, 0.0f))
{
fprintf(stderr, "bu_compress_texture() failed\n");
return EXIT_FAILURE;
}
// Retrieve the compressed .KTX2 file data
uint64_t comp_size = bu_comp_params_get_comp_data_size(comp_params);
if (!comp_size)
{
fprintf(stderr, "bu_comp_params_get_comp_data_size() failed\n");
return EXIT_FAILURE;
}
void* pComp_data = (void*)bu_comp_params_get_comp_data_ofs(comp_params);
if (!pComp_data)
{
fprintf(stderr, "bu_comp_params_get_comp_data_ofs() failed\n");
return EXIT_FAILURE;
}
// Write the data to disk
snprintf(filename_buf, sizeof(filename_buf), "test_%s.ktx2", pDesc);
write_blob_to_file(filename_buf, pComp_data, comp_size);
printf("Wrote file %s\n", filename_buf);
// Now inspect and transcode the .KTX2 data to png/astc files
if (!transcode_ktx2_file(pComp_data, comp_size, pDesc))
{
fprintf(stderr, "transcode_ktx2_file() failed\n");
return EXIT_FAILURE;
}
bu_delete_comp_params(comp_params);
return EXIT_SUCCESS;
}
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
printf("example_capi.c:\n");
// Initialize the encoder (which initializers the transcoder for us)
printf("bu_init:\n");
bu_init();
// bu_init() already does this for us, but it's harmless to call again.
printf("bt_init:\n");
bt_init();
// Control debug output from the compressor
bu_enable_debug_printf(FALSE);
// simple 2D
if (test_2D() != EXIT_SUCCESS)
{
fprintf(stderr, "test_2D() failed!\n");
return EXIT_FAILURE;
}
// 2D array
if (test_2D_array(FALSE, 8, FALSE) != EXIT_SUCCESS)
{
fprintf(stderr, "test_2D_array() (array mode) failed!\n");
return EXIT_FAILURE;
}
// texture video
if (test_2D_array(TRUE, 8, TRUE) != EXIT_SUCCESS)
{
fprintf(stderr, "test_2D_array() (texture video mode) failed!\n");
return EXIT_FAILURE;
}
printf("Success\n");
return EXIT_SUCCESS;
}
|