add EAC support

This commit is contained in:
Ishotihadus
2019-12-21 00:08:01 +09:00
parent d3111e1cad
commit af25ef731b
5 changed files with 227 additions and 13 deletions
+1 -1
View File
@@ -108,7 +108,7 @@ obj.key
Mikunyan generates `ChunkyPNG::Image` images directly from Texture2D objects.
Mikunyan can decode images in basic texture formats (15, 7, 9, 1320, 22, 62, and 63), DXT1 (10), DXT5 (12), PVRTC1 (3033), ETC (34), ETC2 (4547), ASTC (4859), HDR ASTC (6671), or Crunched format (28, 29, 64, 65).
Mikunyan can decode images in basic texture formats (15, 7, 9, 1320, 22, 62, 63), DXT1 (10), DXT5 (12), PVRTC1 (3033), ETC (34), EAC (4144), ETC2 (4547), ASTC (4859), HDR ASTC (6671), or Crunched format (28, 29, 64, 65).
```ruby
# get some Texture2D asset
+96 -2
View File
@@ -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;
}
+4
View File
@@ -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 */
+82 -6
View File
@@ -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);
+44 -4
View File
@@ -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