add EAC support
This commit is contained in:
@@ -108,7 +108,7 @@ obj.key
|
||||
|
||||
Mikunyan generates `ChunkyPNG::Image` images directly from Texture2D objects.
|
||||
|
||||
Mikunyan can decode images in basic texture formats (1–5, 7, 9, 13–20, 22, 62, and 63), DXT1 (10), DXT5 (12), PVRTC1 (30–33), ETC (34), ETC2 (45–47), ASTC (48–59), HDR ASTC (66–71), or Crunched format (28, 29, 64, 65).
|
||||
Mikunyan can decode images in basic texture formats (1–5, 7, 9, 13–20, 22, 62, 63), DXT1 (10), DXT5 (12), PVRTC1 (30–33), ETC (34), EAC (41–44), ETC2 (45–47), ASTC (48–59), HDR ASTC (66–71), or Crunched format (28, 29, 64, 65).
|
||||
|
||||
```ruby
|
||||
# get some Texture2D asset
|
||||
|
||||
@@ -284,8 +284,7 @@ static void decode_etc2a8_block(const uint8_t *data, uint32_t *outbuf) {
|
||||
// multiplier != 0
|
||||
const uint_fast8_t multiplier = data[1] >> 4;
|
||||
const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf];
|
||||
uint_fast64_t l = data[7] | (uint_fast16_t)data[6] << 8 | (uint_fast32_t)data[5] << 16 |
|
||||
(uint_fast32_t)data[4] << 24 | (uint_fast64_t)data[3] << 32 | (uint_fast64_t)data[2] << 40;
|
||||
uint_fast64_t l = bton64(*(uint64_t*)data);
|
||||
for (int i = 0; i < 16; i++, l >>= 3)
|
||||
((uint8_t *)(outbuf + WriteOrderTableRev[i]))[3] = clamp(data[0] + multiplier * table[l & 7]);
|
||||
} else {
|
||||
@@ -295,6 +294,31 @@ static void decode_etc2a8_block(const uint8_t *data, uint32_t *outbuf) {
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_eac_block(const uint8_t *data, int color, uint32_t *outbuf) {
|
||||
uint_fast8_t multiplier = data[1] >> 1 & 0x78;
|
||||
if (multiplier == 0)
|
||||
multiplier = 1;
|
||||
const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf];
|
||||
uint_fast64_t l = bton64(*(uint64_t*)data);
|
||||
for (int i = 0; i < 16; i++, l >>= 3) {
|
||||
int_fast16_t val = data[0] * 8 + multiplier * table[l & 7] + 4;
|
||||
((uint8_t *)(outbuf + WriteOrderTableRev[i]))[color] = val < 0 ? 0 : val >= 2048 ? 0xff : val >> 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_eac_signed_block(const uint8_t *data, int color, uint32_t *outbuf) {
|
||||
int8_t base = (int8_t)data[0];
|
||||
uint_fast8_t multiplier = data[1] >> 1 & 0x78;
|
||||
if (multiplier == 0)
|
||||
multiplier = 1;
|
||||
const int_fast8_t *table = Etc2AlphaModTable[data[1] & 0xf];
|
||||
uint_fast64_t l = bton64(*(uint64_t*)data);
|
||||
for (int i = 0; i < 16; i++, l >>= 3) {
|
||||
int_fast16_t val = base * 8 + multiplier * table[l & 7] + 1023;
|
||||
((uint8_t *)(outbuf + WriteOrderTableRev[i]))[color] = val < 0 ? 0 : val >= 2048 ? 0xff : val >> 3;
|
||||
}
|
||||
}
|
||||
|
||||
int decode_etc1(const uint8_t *data, const long w, const long h, uint32_t *image) {
|
||||
long num_blocks_x = (w + 3) / 4;
|
||||
long num_blocks_y = (h + 3) / 4;
|
||||
@@ -347,3 +371,73 @@ int decode_etc2a8(const uint8_t *data, const long w, const long h, uint32_t *ima
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int decode_eacr(const uint8_t *data, const long w, const long h, uint32_t *image) {
|
||||
long num_blocks_x = (w + 3) / 4;
|
||||
long num_blocks_y = (h + 3) / 4;
|
||||
uint32_t buffer[16];
|
||||
uint32_t base_buffer[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
base_buffer[i] = color(0, 0, 0, 255);
|
||||
for (long by = 0; by < num_blocks_y; by++) {
|
||||
for (long bx = 0; bx < num_blocks_x; bx++, data += 8) {
|
||||
memcpy(buffer, base_buffer, sizeof(buffer));
|
||||
decode_eac_block(data, 0, buffer);
|
||||
copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int decode_eacr_signed(const uint8_t *data, const long w, const long h, uint32_t *image) {
|
||||
long num_blocks_x = (w + 3) / 4;
|
||||
long num_blocks_y = (h + 3) / 4;
|
||||
uint32_t buffer[16];
|
||||
uint32_t base_buffer[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
base_buffer[i] = color(0, 0, 0, 255);
|
||||
for (long by = 0; by < num_blocks_y; by++) {
|
||||
for (long bx = 0; bx < num_blocks_x; bx++, data += 8) {
|
||||
memcpy(buffer, base_buffer, sizeof(buffer));
|
||||
decode_eac_signed_block(data, 0, buffer);
|
||||
copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int decode_eacrg(const uint8_t *data, const long w, const long h, uint32_t *image) {
|
||||
long num_blocks_x = (w + 3) / 4;
|
||||
long num_blocks_y = (h + 3) / 4;
|
||||
uint32_t buffer[16];
|
||||
uint32_t base_buffer[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
base_buffer[i] = color(0, 0, 0, 255);
|
||||
for (long by = 0; by < num_blocks_y; by++) {
|
||||
for (long bx = 0; bx < num_blocks_x; bx++, data += 16) {
|
||||
memcpy(buffer, base_buffer, sizeof(buffer));
|
||||
decode_eac_block(data, 0, buffer);
|
||||
decode_eac_block(data + 8, 1, buffer);
|
||||
copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int decode_eacrg_signed(const uint8_t *data, const long w, const long h, uint32_t *image) {
|
||||
long num_blocks_x = (w + 3) / 4;
|
||||
long num_blocks_y = (h + 3) / 4;
|
||||
uint32_t buffer[16];
|
||||
uint32_t base_buffer[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
base_buffer[i] = color(0, 0, 0, 255);
|
||||
for (long by = 0; by < num_blocks_y; by++) {
|
||||
for (long bx = 0; bx < num_blocks_x; bx++, data += 16) {
|
||||
memcpy(buffer, base_buffer, sizeof(buffer));
|
||||
decode_eac_signed_block(data, 0, buffer);
|
||||
decode_eac_signed_block(data + 8, 1, buffer);
|
||||
copy_block_buffer(bx, by, w, h, 4, 4, buffer, image);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -7,5 +7,9 @@ int decode_etc1(const uint8_t *, const long, const long, uint32_t *);
|
||||
int decode_etc2(const uint8_t *, const long, const long, uint32_t *);
|
||||
int decode_etc2a1(const uint8_t *, const long, const long, uint32_t *);
|
||||
int decode_etc2a8(const uint8_t *, const long, const long, uint32_t *);
|
||||
int decode_eacr(const uint8_t *, const long, const long, uint32_t *);
|
||||
int decode_eacr_signed(const uint8_t *, const long, const long, uint32_t *);
|
||||
int decode_eacrg(const uint8_t *, const long, const long, uint32_t *);
|
||||
int decode_eacrg_signed(const uint8_t *, const long, const long, uint32_t *);
|
||||
|
||||
#endif /* end of include guard: ETC_H */
|
||||
|
||||
@@ -194,8 +194,8 @@ static VALUE rb_decode_etc1(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
* Decode image from ETC2 compressed binary
|
||||
*
|
||||
* @param [String] rb_data binary to decode
|
||||
* @param [Integer] w image width
|
||||
* @param [Integer] h image height
|
||||
* @param [Integer] rb_w image width
|
||||
* @param [Integer] rb_h image height
|
||||
* @return [String] decoded rgba binary
|
||||
*/
|
||||
static VALUE rb_decode_etc2(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
@@ -212,8 +212,8 @@ static VALUE rb_decode_etc2(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
* Decode image from ETC2 Alpha1 compressed binary
|
||||
*
|
||||
* @param [String] rb_data binary to decode
|
||||
* @param [Integer] w image width
|
||||
* @param [Integer] h image height
|
||||
* @param [Integer] rb_w image width
|
||||
* @param [Integer] rb_h image height
|
||||
* @return [String] decoded rgba binary
|
||||
*/
|
||||
static VALUE rb_decode_etc2a1(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
@@ -230,8 +230,8 @@ static VALUE rb_decode_etc2a1(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h)
|
||||
* Decode image from ETC2 Alpha8 compressed binary
|
||||
*
|
||||
* @param [String] rb_data binary to decode
|
||||
* @param [Integer] w image width
|
||||
* @param [Integer] h image height
|
||||
* @param [Integer] rb_w image width
|
||||
* @param [Integer] rb_h image height
|
||||
* @return [String] decoded rgba binary
|
||||
*/
|
||||
static VALUE rb_decode_etc2a8(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
@@ -244,6 +244,78 @@ static VALUE rb_decode_etc2a8(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode image from EAC R11 compressed binary
|
||||
*
|
||||
* @param [String] rb_data binary to decode
|
||||
* @param [Integer] rb_w image width
|
||||
* @param [Integer] rb_h image height
|
||||
* @return [String] decoded rgba binary
|
||||
*/
|
||||
static VALUE rb_decode_eacr(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
long w = FIX2LONG(rb_w), h = FIX2LONG(rb_h);
|
||||
if (!check_str_len_block(rb_data, w, h, 4, 4, 8))
|
||||
return Qnil;
|
||||
VALUE ret = rb_alloc_rgba(w * h);
|
||||
if (!decode_eacr((uint8_t *)RSTRING_PTR(rb_data), w, h, (uint32_t *)RSTRING_PTR(ret)))
|
||||
return Qnil;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode image from EAC Signed R11 compressed binary
|
||||
*
|
||||
* @param [String] rb_data binary to decode
|
||||
* @param [Integer] rb_w image width
|
||||
* @param [Integer] rb_h image height
|
||||
* @return [String] decoded rgba binary
|
||||
*/
|
||||
static VALUE rb_decode_eacsr(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
long w = FIX2LONG(rb_w), h = FIX2LONG(rb_h);
|
||||
if (!check_str_len_block(rb_data, w, h, 4, 4, 8))
|
||||
return Qnil;
|
||||
VALUE ret = rb_alloc_rgba(w * h);
|
||||
if (!decode_eacr_signed((uint8_t *)RSTRING_PTR(rb_data), w, h, (uint32_t *)RSTRING_PTR(ret)))
|
||||
return Qnil;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode image from EAC RG11 compressed binary
|
||||
*
|
||||
* @param [String] rb_data binary to decode
|
||||
* @param [Integer] rb_w image width
|
||||
* @param [Integer] rb_h image height
|
||||
* @return [String] decoded rgba binary
|
||||
*/
|
||||
static VALUE rb_decode_eacrg(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
long w = FIX2LONG(rb_w), h = FIX2LONG(rb_h);
|
||||
if (!check_str_len_block(rb_data, w, h, 4, 4, 16))
|
||||
return Qnil;
|
||||
VALUE ret = rb_alloc_rgba(w * h);
|
||||
if (!decode_eacrg((uint8_t *)RSTRING_PTR(rb_data), w, h, (uint32_t *)RSTRING_PTR(ret)))
|
||||
return Qnil;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode image from EAC RG11 compressed binary
|
||||
*
|
||||
* @param [String] rb_data binary to decode
|
||||
* @param [Integer] rb_w image width
|
||||
* @param [Integer] rb_h image height
|
||||
* @return [String] decoded rgba binary
|
||||
*/
|
||||
static VALUE rb_decode_eacsrg(VALUE self, VALUE rb_data, VALUE rb_w, VALUE rb_h) {
|
||||
long w = FIX2LONG(rb_w), h = FIX2LONG(rb_h);
|
||||
if (!check_str_len_block(rb_data, w, h, 4, 4, 16))
|
||||
return Qnil;
|
||||
VALUE ret = rb_alloc_rgba(w * h);
|
||||
if (!decode_eacrg_signed((uint8_t *)RSTRING_PTR(rb_data), w, h, (uint32_t *)RSTRING_PTR(ret)))
|
||||
return Qnil;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode image from ASTC compressed binary
|
||||
*
|
||||
@@ -336,6 +408,10 @@ void Init_native() {
|
||||
rb_define_module_function(mDecodeHelper, "decode_etc2", rb_decode_etc2, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_etc2a1", rb_decode_etc2a1, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_etc2a8", rb_decode_etc2a8, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_eacr", rb_decode_eacr, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_eacsr", rb_decode_eacsr, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_eacrg", rb_decode_eacrg, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_eacsrg", rb_decode_eacsrg, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_astc", rb_decode_astc, 5);
|
||||
rb_define_module_function(mDecodeHelper, "decode_dxt1", rb_decode_dxt1, 3);
|
||||
rb_define_module_function(mDecodeHelper, "decode_dxt5", rb_decode_dxt5, 3);
|
||||
|
||||
@@ -79,10 +79,14 @@ module Mikunyan
|
||||
decode_pvrtc1(width, height, bin, 4)
|
||||
when 34 # ETC_RGB4
|
||||
decode_etc1(width, height, bin)
|
||||
# when 41 # EAC_R
|
||||
# when 42 # EAC_R_SIGNED
|
||||
# when 43 # EAC_RG
|
||||
# when 44 # EAC_RG_SIGNED
|
||||
when 41 # EAC_R
|
||||
decode_eacr(width, height, bin)
|
||||
when 42 # EAC_R_SIGNED
|
||||
decode_eacsr(width, height, bin)
|
||||
when 43 # EAC_RG
|
||||
decode_eacrg(width, height, bin)
|
||||
when 44 # EAC_RG_SIGNED
|
||||
decode_eacsrg(width, height, bin)
|
||||
when 45 # ETC2_RGB
|
||||
decode_etc2rgb(width, height, bin)
|
||||
when 46 # ETC2_RGBA1
|
||||
@@ -375,6 +379,42 @@ module Mikunyan
|
||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc1(bin, width, height))
|
||||
end
|
||||
|
||||
# Decode image from EAC R11 compressed binary
|
||||
# @param [Integer] width image width
|
||||
# @param [Integer] height image height
|
||||
# @param [String] bin binary to decode
|
||||
# @return [ChunkyPNG::Image] decoded image
|
||||
def self.decode_eacr(width, height, bin)
|
||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_eacr(bin, width, height))
|
||||
end
|
||||
|
||||
# Decode image from EAC Signed R11 compressed binary
|
||||
# @param [Integer] width image width
|
||||
# @param [Integer] height image height
|
||||
# @param [String] bin binary to decode
|
||||
# @return [ChunkyPNG::Image] decoded image
|
||||
def self.decode_eacsr(width, height, bin)
|
||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_eacsr(bin, width, height))
|
||||
end
|
||||
|
||||
# Decode image from EAC RG11 compressed binary
|
||||
# @param [Integer] width image width
|
||||
# @param [Integer] height image height
|
||||
# @param [String] bin binary to decode
|
||||
# @return [ChunkyPNG::Image] decoded image
|
||||
def self.decode_eacrg(width, height, bin)
|
||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_eacrg(bin, width, height))
|
||||
end
|
||||
|
||||
# Decode image from EAC Signed RG11 compressed binary
|
||||
# @param [Integer] width image width
|
||||
# @param [Integer] height image height
|
||||
# @param [String] bin binary to decode
|
||||
# @return [ChunkyPNG::Image] decoded image
|
||||
def self.decode_eacsrg(width, height, bin)
|
||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_eacsrg(bin, width, height))
|
||||
end
|
||||
|
||||
# Decode image from ETC2 compressed binary
|
||||
# @param [Integer] width image width
|
||||
# @param [Integer] height image height
|
||||
|
||||
Reference in New Issue
Block a user