From eec5647b4bb8461f34c203f7d13e6ed10e15eecb Mon Sep 17 00:00:00 2001 From: Ishotihadus Date: Sat, 3 Mar 2018 16:29:10 +0900 Subject: [PATCH] Add DXT1 Support --- lib/mikunyan/decoders/dxtc_block_decoder.rb | 37 +++++++++++++++++++++ lib/mikunyan/decoders/image_decoder.rb | 16 +++++++++ 2 files changed, 53 insertions(+) create mode 100644 lib/mikunyan/decoders/dxtc_block_decoder.rb diff --git a/lib/mikunyan/decoders/dxtc_block_decoder.rb b/lib/mikunyan/decoders/dxtc_block_decoder.rb new file mode 100644 index 0000000..4ea7090 --- /dev/null +++ b/lib/mikunyan/decoders/dxtc_block_decoder.rb @@ -0,0 +1,37 @@ +require 'bin_utils' +require 'fiddle' + +module Mikunyan + module DecodeHelper + # Module for decoding DXTC block + module DxtcBlockDecoder + def self.decode_dxt1_block(bin) + c0 = BinUtils.get_int16_le(bin, 0) + c1 = BinUtils.get_int16_le(bin, 2) + color = [get_rgb565(c0), get_rgb565(c1), nil, nil] + if c0 > c1 + color[2] = [(color[0][0] * 2 + color[1][0]) / 3, (color[0][1] * 2 + color[1][1]) / 3, (color[0][2] * 2 + color[1][2]) / 3, 255] + color[3] = [(color[0][0] + color[1][0] * 2) / 3, (color[0][1] + color[1][1] * 2) / 3, (color[0][2] + color[1][2] * 2) / 3, 255] + else + color[2] = [(color[0][0] + color[1][0]) / 2, (color[0][1] + color[1][1]) / 2, (color[0][2] + color[1][2]) / 2, 255] + color[3] = [0, 0, 0, 0] + end + color.map!{|e| e.pack('C4')} + code = BinUtils.get_int32_le(bin, 4) + mem = String.new(capacity: 64) + 16.times do + mem << color[code & 3] + code >>= 2 + end + mem + end + + def self.get_rgb565(c) + r = (c & 0xf800) >> 8 + g = (c & 0x07e0) >> 3 + b = (c & 0x001f) << 3 + [r | r >> 5, g | g >> 6, b | b >> 5, 255] + end + end + end +end diff --git a/lib/mikunyan/decoders/image_decoder.rb b/lib/mikunyan/decoders/image_decoder.rb index 79223a7..a29dac7 100644 --- a/lib/mikunyan/decoders/image_decoder.rb +++ b/lib/mikunyan/decoders/image_decoder.rb @@ -1,6 +1,7 @@ begin; require 'oily_png'; rescue LoadError; require 'chunky_png'; end require 'bin_utils' require 'mikunyan/decoders/astc_block_decoder' +require 'mikunyan/decoders/dxtc_block_decoder' module Mikunyan # Class for image decoding tools @@ -38,6 +39,8 @@ module Mikunyan decode_rgb565(width, height, bin, endian) when 9 decode_r16(width, height, bin) + when 10 + decode_dxt1(width, height, bin) when 13 decode_rgba4444(width, height, bin, endian) when 14 @@ -350,6 +353,19 @@ module Mikunyan ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip end + def self.decode_dxt1(width, height, bin) + bw = (width + 3) / 4 + bh = (height + 3) / 4 + ret = ChunkyPNG::Image.new(bh * 4, bw * 4) + bh.times do |by| + bw.times do |bx| + block = DecodeHelper::DxtcBlockDecoder::decode_dxt1_block(bin.byteslice((bx + by * bw) * 8, 8)) + ret.replace!(ChunkyPNG::Image.from_rgba_stream(4, 4, block), bx * 4, by * 4) + end + end + ret.crop(0, 0, height, width).flip + end + # Decode image from ETC1 compressed binary # @param [Integer] width image width # @param [Integer] height image height