mikunyan 3.9.1 → 3.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c39b71c73cdf957d6227efcd70aca3813759e15
4
- data.tar.gz: d755c5b99e3dd798f52b8149872e359717470533
3
+ metadata.gz: 0674f5a0c11d5d34d86e845f11aaddbf72256047
4
+ data.tar.gz: 5ebf875cc82f0b2678092aa87171c2fb96a134df
5
5
  SHA512:
6
- metadata.gz: 788e10112ff00680cc19adbd2327c4a7bf80b8a097accdf58c976e2bbcb9f7c4f917abf7bebab54e0454e540b1f65f86dfd277cd13ee4b994cb3279e0d3c8f1a
7
- data.tar.gz: 03ad199057859b6924aeafd8b52c31fe959a6aaeb989b475013972dfd88e79900284b2b4191abe92f1f4f1a0f02ad060d681116012a255fe6753ef6d0ec03f3a
6
+ metadata.gz: f586f5241de8531bd25c27a04e4c8e6b26e50075aba2a816ff41b9b4e3dae1da178f1f4e91d5524d36429f15229b9079f11ed03eb694f632755d4692545c9c08
7
+ data.tar.gz: 39358b3351addc3ea54b93f23712b46184b006e56c8894971839b903620a07b9ae243739ff2f3db614f09e4f36659e12b8ca16a49e00830f44c5460fc3b6fb20
data/README.md CHANGED
@@ -104,7 +104,7 @@ obj.key
104
104
 
105
105
  You can get png file directly from Texture2D asset. Output object's class is `ChunkyPNG::Image`.
106
106
 
107
- Only some basic texture formats (1--5, 7, 9, 13--20, 22, 62, and 63) and ETC_RGB4 (34) are available.
107
+ Some basic texture formats (1--5, 7, 9, 13--20, 22, 62, and 63), ETC_RGB4 (34), ETC2 (45, 47), and ASTC (48--59) are available.
108
108
 
109
109
  ```ruby
110
110
  require 'mikunyan/decoders'
@@ -119,7 +119,7 @@ img = Mikunyan::ImageDecoder.decode_object(obj)
119
119
  img.save('mikunyan.png')
120
120
  ```
121
121
 
122
- Mikunyan cannot decode ASTC files. Use `Mikunyan::ImageDecoder.create_astc_file` instead.
122
+ Mikunyan cannot decode ASTC with HDR data. Use `Mikunyan::ImageDecoder.create_astc_file` instead.
123
123
 
124
124
  ### Json / YAML Outputer
125
125
 
@@ -39,7 +39,7 @@ while i < ARGV.count
39
39
  i += 1
40
40
  end
41
41
 
42
- if option[:pretty] && option[:yaml]
42
+ if opts[:pretty] && opts[:yaml]
43
43
  warn("Option --pretty is ignored if --yaml is specified.")
44
44
  end
45
45
 
@@ -1 +1,7 @@
1
1
  require 'mikunyan/decoders/image_decoder'
2
+
3
+ module Mikunyan
4
+ # Module for helper classes for decoding object
5
+ module DecodeHelper
6
+ end
7
+ end
@@ -0,0 +1,530 @@
1
+ require 'bin_utils'
2
+ require 'fiddle'
3
+
4
+ module Mikunyan
5
+ module DecodeHelper
6
+ # Class for decode ASTC block
7
+ # @attr_reader [String] data decoded data
8
+ class AstcBlockDecoder
9
+ attr_reader :data
10
+
11
+ # Decode block
12
+ # @param [String] bin binary
13
+ # @param [Integer] bw block width
14
+ # @param [Integer] bh block height
15
+ def initialize(bin, bw, bh)
16
+ if bin[0].ord == 0xfc && bin[1].ord % 2 == 1
17
+ @data = (bin[9] + bin[11] + bin[13] + bin[15]) * bw * bh
18
+ else
19
+ @d2 = BinUtils.get_int64_le(bin)
20
+ @d1 = BinUtils.get_int64_le(bin, 8)
21
+ @bw = bw
22
+ @bh = bh
23
+
24
+ decode_block_params
25
+ decode_endpoints
26
+ decode_weights
27
+ select_partition
28
+ applicate_color
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ WeightPrecTableA = [nil, nil, 0, 3, 0, 5, 3, 0, nil, nil, 5, 3, 0, 5, 3, 0]
35
+ WeightPrecTableB = [nil, nil, 1, 0, 2, 0, 1, 3, nil, nil, 1, 2, 4, 2, 3, 5]
36
+
37
+ CemTableA = [0, 0, 3, 0, 5, 3, 0, 5, 3, 0, 5, 3, 0, 5, 3, 0, 5, 3, 0]
38
+ CemTableB = [1, 2, 1, 3, 1, 2, 4, 2, 3, 5, 3, 4, 6, 4, 5, 7, 5, 6, 8]
39
+
40
+ TritsTable = [
41
+ [0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 1, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 1, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 1, 2, 2],
42
+ [0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 0, 0, 0, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1],
43
+ [0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2],
44
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2],
45
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
46
+ ]
47
+
48
+ QuintsTable = [
49
+ [0, 1, 2, 3, 4, 0, 4, 4, 0, 1, 2, 3, 4, 1, 4, 4, 0, 1, 2, 3, 4, 2, 4, 4, 0, 1, 2, 3, 4, 3, 4, 4, 0, 1, 2, 3, 4, 0, 4, 0, 0, 1, 2, 3, 4, 1, 4, 1, 0, 1, 2, 3, 4, 2, 4, 2, 0, 1, 2, 3, 4, 3, 4, 3, 0, 1, 2, 3, 4, 0, 2, 3, 0, 1, 2, 3, 4, 1, 2, 3, 0, 1, 2, 3, 4, 2, 2, 3, 0, 1, 2, 3, 4, 3, 2, 3, 0, 1, 2, 3, 4, 0, 0, 1, 0, 1, 2, 3, 4, 1, 0, 1, 0, 1, 2, 3, 4, 2, 0, 1, 0, 1, 2, 3, 4, 3, 0, 1],
50
+ [0, 0, 0, 0, 0, 4, 4, 4, 1, 1, 1, 1, 1, 4, 4, 4, 2, 2, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 4, 0, 4, 1, 1, 1, 1, 1, 4, 1, 4, 2, 2, 2, 2, 2, 4, 2, 4, 3, 3, 3, 3, 3, 4, 3, 4, 0, 0, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 1, 4, 1, 1, 2, 2, 2, 2, 2, 4, 2, 2, 3, 3, 3, 3, 3, 4, 3, 3, 0, 0, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 1, 4, 1, 1, 2, 2, 2, 2, 2, 4, 2, 2, 3, 3, 3, 3, 3, 4, 3, 3],
51
+ [0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 3, 4, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4]
52
+ ]
53
+
54
+ def [](i, j = 1)
55
+ if j < 1
56
+ 0
57
+ elsif j == 1
58
+ i < 64 ? @d2[i] : @d1[i - 64]
59
+ else
60
+ if i + j <= 64
61
+ @d2 >> i & (1 << j) - 1
62
+ elsif i >= 64
63
+ @d1 >> (i - 64) & (1 << j) - 1
64
+ else
65
+ @d2 >> i | (@d1 & (1 << i + j - 64) - 1) << 64 - i
66
+ end
67
+ end
68
+ end
69
+
70
+ def decode_block_params
71
+ # Block Mode
72
+ @weight_range = @d2 >> 4 & 1 | @d2 >> 6 & 8
73
+ @dual_plane = @d2 & 0x400 == 0x400
74
+ if @d2 & 0x3 != 0
75
+ @weight_range |= @d2 << 1 & 6
76
+ case @d2 & 0xc
77
+ when 0
78
+ @width = (@d2 >> 7 & 3) + 4
79
+ @height = (@d2 >> 5 & 3) + 2
80
+ when 0x4
81
+ @width = (@d2 >> 7 & 3) + 8
82
+ @height = (@d2 >> 5 & 3) + 2
83
+ when 0x8
84
+ @width = (@d2 >> 5 & 3) + 2
85
+ @height = (@d2 >> 7 & 3) + 8
86
+ else # 0xc
87
+ if @d2 & 0x100 == 0
88
+ @width = (@d2 >> 5 & 3) + 2
89
+ @height = @d2[7] + 6
90
+ else
91
+ @width = @d2[7] + 2
92
+ @height = (@d2 >> 5 & 3) + 2
93
+ end
94
+ end
95
+ else
96
+ @weight_range |= @d2 >> 1 & 6
97
+ case @d2 & 0x180
98
+ when 0
99
+ @width = 12
100
+ @height = (@d2 >> 5 & 3) + 2
101
+ when 0x80
102
+ @width = (@d2 >> 5 & 3) + 2
103
+ @height = 12
104
+ when 0x180
105
+ @width = (@d2 & 0x20 == 0) ? 6 : 10
106
+ @height = 16 - @width
107
+ else # 0x100
108
+ @width = (@d2 >> 5 & 3) + 6
109
+ @height = (@d2 >> 9 & 3) + 6
110
+ @dual_plane = false
111
+ @weight_range &= 7
112
+ end
113
+ end
114
+
115
+ # Count Partitions
116
+ @part_num = (@d2 >> 11 & 3) + 1
117
+
118
+ # Count Weight Bits
119
+ @weight_num = @width * @height
120
+ @weight_num *= 2 if @dual_plane
121
+ case WeightPrecTableA[@weight_range]
122
+ when 3
123
+ @weight_bit = @weight_num * WeightPrecTableB[@weight_range] + (@weight_num * 8 + 4) / 5
124
+ when 5
125
+ @weight_bit = @weight_num * WeightPrecTableB[@weight_range] + (@weight_num * 7 + 2) / 3
126
+ else # 0
127
+ @weight_bit = @weight_num * WeightPrecTableB[@weight_range]
128
+ end
129
+
130
+ # CEM
131
+ if @part_num == 1
132
+ @cem = [@d2 >> 13 & 0xf]
133
+ config_bit = 17
134
+ else
135
+ cembase = @d2 >> 23 & 3
136
+ if cembase == 0
137
+ @cem = Array.new(@part_num, @d2 >> 25 & 0xf)
138
+ config_bit = 29
139
+ else
140
+ @cem = (0...@part_num).map{|i| ((@d2 >> (25 + i) & 1) + cembase - 1) << 2}
141
+
142
+ case @part_num
143
+ when 2
144
+ @cem[0] |= @d2 >> 27 & 3
145
+ @cem[1] |= self[126 - @weight_bit, 2]
146
+ when 3
147
+ @cem[0] |= @d2[28]
148
+ @cem[0] |= self[123 - @weight_bit] << 1
149
+ @cem[1] |= self[124 - @weight_bit, 2]
150
+ @cem[2] |= self[126 - @weight_bit, 2]
151
+ else # 4
152
+ 4.times do |i|
153
+ @cem[i] |= self[120 + 2 * i - @weight_bit, 2]
154
+ end
155
+ end
156
+
157
+ config_bit = 25 + @part_num * 3
158
+ end
159
+ end
160
+
161
+ # Count Color Endpoint Bits
162
+ config_bit += 2 if @dual_plane
163
+ remain_bit = 128 - config_bit - @weight_bit
164
+ @cem_num = @cem.map{|i| (i >> 1 & 6) + 2}.inject(:+)
165
+
166
+ CemTableA.count.times do |n|
167
+ i = CemTableA.count - n - 1
168
+ case CemTableA[i]
169
+ when 3
170
+ @cem_bit = @cem_num * CemTableB[i] + (@cem_num * 8 + 4) / 5
171
+ when 5
172
+ @cem_bit = @cem_num * CemTableB[i] + (@cem_num * 7 + 2) / 3
173
+ else # 0
174
+ @cem_bit = @cem_num * CemTableB[i]
175
+ end
176
+
177
+ if @cem_bit <= remain_bit
178
+ @cem_range = i
179
+ break
180
+ end
181
+ end
182
+
183
+ if @dual_plane
184
+ if @part_num == 1 || cembase == 0
185
+ @plane_selector = self[126 - @weight_bit, 2]
186
+ else
187
+ @plane_selector = self[130 - @weight_bit - @part_num * 3, 2]
188
+ end
189
+ end
190
+ end
191
+
192
+ def decode_endpoints
193
+ values = decode_intseq_raw(self[@part_num == 1 ? 17 : 29, @cem_bit], CemTableA[@cem_range], CemTableB[@cem_range], @cem_num).map do |e|
194
+ unquantize_endpoint(CemTableA[@cem_range], CemTableB[@cem_range], e[0], e[1])
195
+ end
196
+
197
+ @endpoint = @cem.map do |cem|
198
+ v = values.slice!(0, (cem >> 1 & 6) + 2)
199
+ case cem
200
+ when 0
201
+ [v[0], v[0], v[0], 255, v[1], v[1], v[1], 255]
202
+ when 1
203
+ l0 = (v[0] >> 2) | (v[1] & 0xc0)
204
+ l1 = (l0 + (v[1] & 0x3f)).clamp(0, 255)
205
+ [l0, l0, l0, 255, l1, l1, l1, 255]
206
+ when 4
207
+ [v[0], v[0], v[0], v[2], v[1], v[1], v[1], v[3]]
208
+ when 5
209
+ v[1], v[0] = bit_transfer_signed(v[1], v[0])
210
+ v[3], v[2] = bit_transfer_signed(v[3], v[2])
211
+ [v[0], v[0], v[0], v[2], v[0] + v[1], v[0] + v[1], v[0] + v[1], v[2] + v[3]].map{|i| i.clamp(0, 255)}
212
+ when 6
213
+ [v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, 255, v[0], v[1], v[2], 255]
214
+ when 8
215
+ if v[0] + v[2] + v[4] <= v[1] + v[3] + v[5]
216
+ [v[0], v[2], v[4], 255, v[1], v[3], v[5], 255]
217
+ else
218
+ blue_contract(v[1], v[3], v[5], 255, v[0], v[2], v[4], 255)
219
+ end
220
+ when 9
221
+ v[1], v[0] = bit_transfer_signed(v[1], v[0])
222
+ v[3], v[2] = bit_transfer_signed(v[3], v[2])
223
+ v[5], v[4] = bit_transfer_signed(v[5], v[4])
224
+ if v[1] + v[3] + v[5] >= 0
225
+ [v[0], v[2], v[4], 255, v[0] + v[1], v[2] + v[3], v[4] + v[5], 255].map{|i| i.clamp(0, 255)}
226
+ else
227
+ blue_contract(v[0] + v[1], v[2] + v[3], v[4] + v[5], 255, v[0], v[2], v[4], 255).map{|i| i.clamp(0, 255)}
228
+ end
229
+ when 10
230
+ [v[0] * v[3] >> 8, v[1] * v[3] >> 8, v[2] * v[3] >> 8, v[4], v[0], v[1], v[2], v[5]]
231
+ when 12
232
+ if v[0] + v[2] + v[4] <= v[1] + v[3] + v[5]
233
+ [v[0], v[2], v[4], v[6], v[1], v[3], v[5], v[7]]
234
+ else
235
+ blue_contract(v[1], v[3], v[5], v[7], v[0], v[2], v[4], v[6])
236
+ end
237
+ when 13
238
+ v[1], v[0] = bit_transfer_signed(v[1], v[0])
239
+ v[3], v[2] = bit_transfer_signed(v[3], v[2])
240
+ v[5], v[4] = bit_transfer_signed(v[5], v[4])
241
+ v[7], v[6] = bit_transfer_signed(v[7], v[6])
242
+ if v[1] + v[3] + v[5] >= 0
243
+ [v[0], v[2], v[4], v[6], v[0] + v[1], v[2] + v[3], v[4] + v[5], v[6] + v[7]].map{|i| i.clamp(0, 255)}
244
+ else
245
+ blue_contract(v[0] + v[1], v[2] + v[3], v[4] + v[5], v[6] + v[7], v[0], v[2], v[4], v[6]).map{|i| i.clamp(0, 255)}
246
+ end
247
+ else
248
+ throw NotImplementedError.new("HDR image is not supported. (CEM: #{cem})")
249
+ end
250
+ end
251
+ end
252
+
253
+ def bit_transfer_signed(a, b)
254
+ b = (b >> 1) | (a & 0x80)
255
+ a = (a >> 1) & 0x3f
256
+ [a[5] == 1 ? a - 0x40 : a, b]
257
+ end
258
+
259
+ def blue_contract(r1, g1, b1, a1, r2, g2, b2, a2)
260
+ [(r1 + b1) >> 1, (g1 + b1) >> 1, b1, a1, (r2 + b2) >> 1, (g2 + b2) >> 1, b2, a2]
261
+ end
262
+
263
+ def decode_weights
264
+ data = (0...(@weight_bit + 7) / 8).map{|i| (((self[120 - i * 8, 8]) * 0x80200802) & 0x0884422110) * 0x0101010101 >> 32 & 0xff}
265
+ .map.with_index{|e, i| e << i * 8}.inject(:|) & (1 << @weight_bit) - 1
266
+
267
+ weight_point = decode_intseq_raw(data, WeightPrecTableA[@weight_range], WeightPrecTableB[@weight_range], @weight_num).map do |e|
268
+ unquantize_weight(WeightPrecTableA[@weight_range], WeightPrecTableB[@weight_range], e[0], e[1])
269
+ end
270
+
271
+ ds = (1024 + @bw / 2) / (@bw - 1)
272
+ dt = (1024 + @bh / 2) / (@bh - 1)
273
+
274
+ if @dual_plane
275
+ @weight0 = Fiddle::Pointer.malloc(@bw * @bh)
276
+ @weight1 = Fiddle::Pointer.malloc(@bw * @bh)
277
+
278
+ for t in 0...@bh
279
+ for s in 0...@bw
280
+ gs = (ds * s * (@width - 1) + 32) >> 6
281
+ gt = (dt * t * (@height - 1) + 32) >> 6
282
+ fs = gs & 0xf
283
+ ft = gt & 0xf
284
+ v = (gs >> 4) + (gt >> 4) * @width
285
+ w11 = (fs * ft + 8) >> 4
286
+ w10 = ft - w11
287
+ w01 = fs - w11
288
+ w00 = 16 - fs - ft + w11
289
+
290
+ p00 = weight_point[v * 2] || 0
291
+ p01 = weight_point[(v + 1) * 2] || 0
292
+ p10 = weight_point[(v + @width) * 2] || 0
293
+ p11 = weight_point[(v + @width + 1) * 2] || 0
294
+ @weight0[s + t * @bw] = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4
295
+
296
+ p00 = weight_point[v * 2 + 1] || 0
297
+ p01 = weight_point[(v + 1) * 2 + 1] || 0
298
+ p10 = weight_point[(v + @width) * 2 + 1] || 0
299
+ p11 = weight_point[(v + @width + 1) * 2 + 1] || 0
300
+ @weight1[s + t * @bw] = (p00 * w00 + p01 * w01 + p10 * w10 + p11 * w11 + 8) >> 4
301
+ end
302
+ end
303
+ else
304
+ @weight = Fiddle::Pointer.malloc(@bw * @bh)
305
+
306
+ for t in 0...@bh
307
+ for s in 0...@bw
308
+ gs = (ds * s * (@width - 1) + 32) >> 6
309
+ gt = (dt * t * (@height - 1) + 32) >> 6
310
+ fs = gs & 0xf
311
+ ft = gt & 0xf
312
+ v = (gs >> 4) + (gt >> 4) * @width
313
+ w11 = (fs * ft + 8) >> 4
314
+
315
+ p00 = weight_point[v] || 0
316
+ p01 = weight_point[v + 1] || 0
317
+ p10 = weight_point[v + @width] || 0
318
+ p11 = weight_point[v + @width + 1] || 0
319
+ @weight[s + t * @bw] = (p00 * (16 - fs - ft + w11) + p01 * (fs - w11) + p10 * (ft - w11) + p11 * w11 + 8) >> 4
320
+ end
321
+ end
322
+ end
323
+ end
324
+
325
+ def select_partition
326
+ if @part_num > 1
327
+ small_block = @bw * @bh < 31
328
+
329
+ seed = (@d2 >> 13 & 0x3ff) | ((@part_num - 1) << 10)
330
+
331
+ rnum = seed
332
+ rnum ^= (rnum >> 15)
333
+ rnum = (rnum - (rnum << 17)) & 0xffffffff
334
+ rnum = (rnum + (rnum << 7)) & 0xffffffff
335
+ rnum = (rnum + (rnum << 4)) & 0xffffffff
336
+ rnum ^= rnum >> 5
337
+ rnum = (rnum + (rnum << 16)) & 0xffffffff
338
+ rnum ^= rnum >> 7
339
+ rnum ^= rnum >> 3
340
+ rnum = (rnum ^ (rnum << 6)) & 0xffffffff
341
+ rnum = rnum ^ (rnum >> 17)
342
+
343
+ seeds = [0, 4, 8, 12, 16, 20, 24, 28].map{|i| (rnum >> i) & 0xf}.map!{|e| e * e}
344
+ sh = [seed & 2 == 2 ? 4 : 5, @part_num == 3 ? 6 : 5]
345
+ sh.reverse! if seed & 1 == 0
346
+ seeds.map!.with_index{|e, i| e >> sh[i % 2]}
347
+
348
+ @partition = Array.new(@bw * @bh)
349
+
350
+ for y in 0...@bh
351
+ for x in 0...@bw
352
+ idx = x + y * @bw
353
+
354
+ if small_block
355
+ x <<= 1
356
+ y <<= 1
357
+ end
358
+
359
+ a = (seeds[0] * x + seeds[1] * y + (rnum >> 14)) & 0x3f
360
+ b = (seeds[2] * x + seeds[3] * y + (rnum >> 10)) & 0x3f
361
+ c = @part_num < 3 ? 0 : (seeds[4] * x + seeds[5] * y + (rnum >> 6)) & 0x3f
362
+ d = @part_num < 4 ? 0 : (seeds[6] * x + seeds[7] * y + (rnum >> 2)) & 0x3f
363
+
364
+ @partition[idx] = 3 - [d, c, b, a].each_with_index.max[1]
365
+ end
366
+ end
367
+ end
368
+ end
369
+
370
+ def applicate_color
371
+ mem = Fiddle::Pointer.malloc(@bw * @bh * 4)
372
+
373
+ if @dual_plane
374
+ plane_arr = [0, 1, 2, 3]
375
+ plane_arr.delete_at(@plane_selector)
376
+
377
+ if @partition
378
+ (@bw * @bh).times do |i|
379
+ part = @partition[i]
380
+ plane_arr.each{|c| mem[i * 4 + c] = select_color(@endpoint[part][c], @endpoint[part][4 + c], @weight0[i])}
381
+ mem[i * 4 + @plane_selector] = select_color(@endpoint[part][@plane_selector], @endpoint[part][4 + @plane_selector], @weight1[i])
382
+ end
383
+ else
384
+ (@bw * @bh).times do |i|
385
+ plane_arr.each{|c| mem[i * 4 + c] = select_color(@endpoint[0][c], @endpoint[0][4 + c], @weight0[i])}
386
+ mem[i * 4 + @plane_selector] = select_color(@endpoint[0][@plane_selector], @endpoint[0][4 + @plane_selector], @weight1[i])
387
+ end
388
+ end
389
+ elsif @partition
390
+ (@bw * @bh).times do |i|
391
+ part = @partition[i]
392
+ 4.times{|c| mem[i * 4 + c] = select_color(@endpoint[part][c], @endpoint[part][4 + c], @weight[i])}
393
+ end
394
+ else
395
+ (@bw * @bh).times do |i|
396
+ 4.times{|c| mem[i * 4 + c] = select_color(@endpoint[0][c], @endpoint[0][4 + c], @weight[i])}
397
+ end
398
+ end
399
+
400
+ @data = mem.to_str
401
+ end
402
+
403
+ def select_color(v0, v1, weight)
404
+ v0 |= v0 << 8
405
+ v1 |= v1 << 8
406
+ v = (v0 * (64 - weight) + v1 * weight + 32) >> 6
407
+ (v * 255 + 32768) / 65536
408
+ end
409
+
410
+ def decode_intseq_raw(data, a, b, count)
411
+ mask = (1 << b) - 1
412
+ case a
413
+ when 3
414
+ rc = (count + 4) / 5
415
+ ret = Array.new(rc * 5)
416
+ m = [0, 2 + b, 4 + b * 2, 5 + b * 3, 7 + b * 4]
417
+ rc.times do |i|
418
+ t = (data >> b & 3) | (data >> b * 2 & 0xc) | (data >> b * 3 & 0x10) | (data >> b * 4 & 0x60) | (data >> b * 5 & 0x80)
419
+ 5.times do |j|
420
+ ret[i * 5 + j] = [data >> m[j] & mask, TritsTable[j][t]]
421
+ end
422
+ data >>= b * 5 + 8
423
+ end
424
+ ret[0, count]
425
+ when 5
426
+ rc = (count + 2) / 3
427
+ ret = Array.new(rc * 3)
428
+ m = [0, 3 + b, 5 + b * 2]
429
+ rc.times do |i|
430
+ q = (data >> b & 7) | (data >> b * 2 & 0x18) | (data >> b * 3 & 0x60)
431
+ 3.times do |j|
432
+ ret[i * 3 + j] = [data >> m[j] & mask, QuintsTable[j][q]]
433
+ end
434
+ data >>= b * 3 + 7
435
+ end
436
+ ret[0, count]
437
+ else # 0
438
+ (0...count).map do |i|
439
+ [data >> b * i & mask, 0]
440
+ end
441
+ end
442
+ end
443
+
444
+ def unquantize_endpoint(a, b, bit, val_d)
445
+ if a == 0
446
+ case b
447
+ when 1
448
+ bit * 0xff
449
+ when 2
450
+ bit * 0x55
451
+ when 3
452
+ bit << 5 | bit << 2 | bit >> 1
453
+ when 4
454
+ bit << 4 | bit
455
+ when 5
456
+ bit << 3 | bit >> 2
457
+ when 6
458
+ bit << 2 | bit >> 4
459
+ when 7
460
+ bit << 1 | bit >> 6
461
+ else # 8
462
+ bit
463
+ end
464
+ else
465
+ val_a = (bit & 1) * 0x1ff
466
+ tmp_b = bit >> 1
467
+ case b
468
+ when 1
469
+ val_b = 0
470
+ val_c = a == 3 ? 204 : 113
471
+ when 2
472
+ val_b = a == 3 ? (0b100010110) * tmp_b : (0b100001100) * tmp_b
473
+ val_c = a == 3 ? 93 : 54
474
+ when 3
475
+ val_b = a == 3 ? tmp_b << 7 | tmp_b << 2 | tmp_b : tmp_b << 7 | tmp_b << 1 | tmp_b >> 1
476
+ val_c = a == 3 ? 44 : 26
477
+ when 4
478
+ val_b = tmp_b << 6 | tmp_b >> (a == 3 ? 0 : 1)
479
+ val_c = a == 3 ? 22 : 13
480
+ when 5
481
+ val_b = tmp_b << 5 | tmp_b >> (a == 3 ? 2 : 3)
482
+ val_c = a == 3 ? 11 : 6
483
+ else # 6
484
+ val_b = tmp_b << 4 | tmp_b >> 4
485
+ val_c = 5
486
+ end
487
+ t = val_d * val_c + val_b
488
+ t ^= val_a
489
+ (val_a & 0x80) | (t >> 2)
490
+ end
491
+ end
492
+
493
+ def unquantize_weight(a, b, bit, val_d)
494
+ if a == 0
495
+ case b
496
+ when 1
497
+ t = bit == 1 ? 63 : 0
498
+ when 2
499
+ t = bit << 4 | bit << 2 | bit
500
+ when 3
501
+ t = bit << 3 | bit
502
+ when 4
503
+ t = bit << 2 | bit >> 2
504
+ else # 5
505
+ t = bit << 1 | bit >> 4
506
+ end
507
+ elsif b == 0
508
+ t = (a == 3 ? [0, 32, 63] : [0, 16, 32, 47, 63])[val_d]
509
+ else
510
+ val_a = (bit & 1) * 0x7f
511
+ case b
512
+ when 1
513
+ val_b = 0
514
+ val_c = a == 3 ? 50 : 28
515
+ when 2
516
+ val_b = (a == 3 ? 0b1000101 : 0b1000010) * bit[1]
517
+ val_c = a == 3 ? 23 : 13
518
+ else # 3
519
+ val_b = (bit << 4 | bit >> 1) & 0b1100011
520
+ val_c = 11
521
+ end
522
+ t = val_d * val_c + val_b
523
+ t ^= val_a
524
+ t = (val_a & 0x20) | (t >> 2)
525
+ end
526
+ t > 32 ? t + 1 : t
527
+ end
528
+ end
529
+ end
530
+ end
@@ -1,6 +1,7 @@
1
1
  begin; require 'oily_png'; rescue LoadError; require 'chunky_png'; end
2
2
  require 'bin_utils'
3
3
  require 'fiddle'
4
+ require 'mikunyan/decoders/astc_block_decoder'
4
5
 
5
6
  module Mikunyan
6
7
  # Class for image decoding tools
@@ -29,11 +30,11 @@ module Mikunyan
29
30
  when 2
30
31
  decode_argb4444(width, height, bin, endian)
31
32
  when 3
32
- decode_rgb888(width, height, bin)
33
+ decode_rgb24(width, height, bin)
33
34
  when 4
34
- decode_rgba8888(width, height, bin)
35
+ decode_rgba32(width, height, bin)
35
36
  when 5
36
- decode_argb8888(width, height, bin)
37
+ decode_argb32(width, height, bin)
37
38
  when 7
38
39
  decode_rgb565(width, height, bin, endian)
39
40
  when 9
@@ -41,7 +42,7 @@ module Mikunyan
41
42
  when 13
42
43
  decode_rgba4444(width, height, bin, endian)
43
44
  when 14
44
- decode_bgra8888(width, height, bin)
45
+ decode_bgra32(width, height, bin)
45
46
  when 15
46
47
  decode_rhalf(width, height, bin, endian)
47
48
  when 16
@@ -58,6 +59,22 @@ module Mikunyan
58
59
  decode_rgb9e5float(width, height, bin, endian)
59
60
  when 34
60
61
  decode_etc1(width, height, bin)
62
+ when 45
63
+ decode_etc2rgb(width, height, bin)
64
+ when 47
65
+ decode_etc2rgba8(width, height, bin)
66
+ when 48, 54
67
+ decode_astc(width, height, 4, bin)
68
+ when 49, 55
69
+ decode_astc(width, height, 5, bin)
70
+ when 50, 56
71
+ decode_astc(width, height, 6, bin)
72
+ when 51, 57
73
+ decode_astc(width, height, 8, bin)
74
+ when 52, 58
75
+ decode_astc(width, height, 10, bin)
76
+ when 53, 59
77
+ decode_astc(width, height, 12, bin)
61
78
  when 62
62
79
  decode_rg16(width, height, bin)
63
80
  when 63
@@ -342,16 +359,72 @@ module Mikunyan
342
359
  def self.decode_etc1(width, height, bin)
343
360
  bw = (width + 3) / 4
344
361
  bh = (height + 3) / 4
345
- mem = Fiddle::Pointer.malloc(bw * bh * 48)
362
+ ret = ChunkyPNG::Image.new(bw * 4, bh * 4)
346
363
  bh.times do |by|
347
364
  bw.times do |bx|
348
365
  block = decode_etc1_block(BinUtils.get_sint64_be(bin, (bx + by * bw) * 8))
366
+ ret.replace!(ChunkyPNG::Image.from_rgb_stream(4, 4, block), bx * 4, by * 4)
367
+ end
368
+ end
369
+ ret.crop(0, 0, width, height)
370
+ end
371
+
372
+ # Decode image from ETC2 compressed binary
373
+ # @param [Integer] width image width
374
+ # @param [Integer] height image height
375
+ # @param [String] bin binary to decode
376
+ # @return [ChunkyPNG::Image] decoded image
377
+ def self.decode_etc2rgb(width, height, bin)
378
+ bw = (width + 3) / 4
379
+ bh = (height + 3) / 4
380
+ ret = ChunkyPNG::Image.new(bw * 4, bh * 4)
381
+ bh.times do |by|
382
+ bw.times do |bx|
383
+ block = decode_etc2_block(BinUtils.get_sint64_be(bin, (bx + by * bw) * 8))
384
+ ret.replace!(ChunkyPNG::Image.from_rgb_stream(4, 4, block), bx * 4, by * 4)
385
+ end
386
+ end
387
+ ret.crop(0, 0, width, height)
388
+ end
389
+
390
+ # Decode image from ETC2 Alpha8 compressed binary
391
+ # @param [Integer] width image width
392
+ # @param [Integer] height image height
393
+ # @param [String] bin binary to decode
394
+ # @return [ChunkyPNG::Image] decoded image
395
+ def self.decode_etc2rgba8(width, height, bin)
396
+ bw = (width + 3) / 4
397
+ bh = (height + 3) / 4
398
+ mem = Fiddle::Pointer.malloc(bw * bh * 64)
399
+ bh.times do |by|
400
+ bw.times do |bx|
401
+ alpha = decode_etc2alpha_block(BinUtils.get_int64_be(bin, (bx + by * bw) * 16))
402
+ block = decode_etc2_block(BinUtils.get_int64_be(bin, (bx + by * bw) * 16 + 8))
349
403
  16.times do |i|
350
- mem[((i / 4 + bx * 4) + (i % 4 + by * 4) * bw * 4) * 3, 3] = block[i]
404
+ mem[((i / 4 + bx * 4) + (i % 4 + by * 4) * bw * 4) * 4, 4] = block[i] + alpha[i]
351
405
  end
352
406
  end
353
407
  end
354
- ChunkyPNG::Image.from_rgb_stream(bw * 4, bh * 4, mem.to_str).crop!(0, 0, width, height)
408
+ ChunkyPNG::Image.from_rgba_stream(bw * 4, bh * 4, mem.to_str).crop(0, 0, width, height)
409
+ end
410
+
411
+ # Decode image from ASTC compressed binary
412
+ # @param [Integer] width image width
413
+ # @param [Integer] height image height
414
+ # @param [Integer] blocksize block size
415
+ # @param [String] bin binary to decode
416
+ # @return [ChunkyPNG::Image] decoded image
417
+ def self.decode_astc(width, height, blocksize, bin)
418
+ bw = (width + blocksize - 1) / blocksize
419
+ bh = (height + blocksize - 1) / blocksize
420
+ ret = ChunkyPNG::Image.new(bw * blocksize, bh * blocksize)
421
+ bh.times do |by|
422
+ bw.times do |bx|
423
+ block = DecodeHelper::AstcBlockDecoder.new(bin.byteslice((by * bw + bx) * 16, 16), blocksize, blocksize).data
424
+ ret.replace!(ChunkyPNG::Image.from_rgba_stream(blocksize, blocksize, block), bx * blocksize, by * blocksize)
425
+ end
426
+ end
427
+ ret.crop(0, 0, width, height).flip
355
428
  end
356
429
 
357
430
  # Create ASTC file data from ObjectValue
@@ -386,6 +459,25 @@ module Mikunyan
386
459
 
387
460
  Etc1ModifierTable = [[2, 8], [5, 17], [9, 29], [13, 42], [18, 60], [24, 80], [33, 106], [47, 183]]
388
461
  Etc1SubblockTable = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1]]
462
+ Etc2DistanceTable = [3, 6, 11, 16, 23, 32, 41, 64]
463
+ Etc2AlphaModTable = [
464
+ [-3, -6, -9, -15, 2, 5, 8, 14],
465
+ [-3, -7, -10, -13, 2, 6, 9, 12],
466
+ [-2, -5, -8, -13, 1, 4, 7, 12],
467
+ [-2, -4, -6, -13, 1, 3, 5, 12],
468
+ [-3, -6, -8, -12, 2, 5, 7, 11],
469
+ [-3, -7, -9, -11, 2, 6, 8, 10],
470
+ [-4, -7, -8, -11, 3, 6, 7, 10],
471
+ [-3, -5, -8, -11, 2, 4, 7, 10],
472
+ [-2, -6, -8, -10, 1, 5, 7, 9],
473
+ [-2, -5, -8, -10, 1, 4, 7, 9],
474
+ [-2, -4, -8, -10, 1, 3, 7, 9],
475
+ [-2, -5, -7, -10, 1, 4, 6, 9],
476
+ [-3, -4, -7, -10, 2, 3, 6, 9],
477
+ [-1, -2, -3, -10, 0, 1, 2, 9],
478
+ [-4, -6, -8, -9, 3, 5, 7, 8],
479
+ [-3, -5, -7, -9, 2, 4, 6, 8]
480
+ ]
389
481
 
390
482
  def self.decode_etc1_block(bin)
391
483
  colors = []
@@ -406,12 +498,10 @@ module Mikunyan
406
498
  colors[1] = colors[1] | (colors[1] >> 5 & 0x70707)
407
499
  end
408
500
 
409
- ret = Array.new(16, 0)
410
- 16.times do |i|
501
+ (0...16).map do |i|
411
502
  modifier = Etc1ModifierTable[codes[subblocks[i]]][bin[i]]
412
- ret[i] = etc1colormod(colors[subblocks[i]], bin[i + 16] == 0 ? modifier : -modifier)
503
+ etc1colormod(colors[subblocks[i]], bin[i + 16] == 0 ? modifier : -modifier)
413
504
  end
414
- ret
415
505
  end
416
506
 
417
507
  def self.etc1colormod(color, modifier)
@@ -421,6 +511,96 @@ module Mikunyan
421
511
  r.clamp(0, 255).chr + g.clamp(0, 255).chr + b.clamp(0, 255).chr
422
512
  end
423
513
 
514
+ def self.decode_etc2_block(bin)
515
+ if bin[33] == 0
516
+ # individual
517
+ colors = [0, 0]
518
+ colors[0] = bin >> 40 & 0xf0f0f0
519
+ colors[0] = colors[0] | colors[0] >> 4
520
+ colors[1] = bin >> 36 & 0xf0f0f0
521
+ colors[1] = colors[1] | colors[1] >> 4
522
+ codes = [bin >> 37 & 7, bin >> 34 & 7]
523
+ subblocks = Etc1SubblockTable[bin[32]]
524
+ (0...16).map do |i|
525
+ modifier = Etc1ModifierTable[codes[subblocks[i]]][bin[i]]
526
+ etc1colormod(colors[subblocks[i]], bin[i + 16] == 0 ? modifier : -modifier)
527
+ end
528
+ else
529
+ r = bin >> 59
530
+ dr = (bin >> 56 & 3) - (bin >> 56 & 4)
531
+ g = bin >> 51 & 0x1f
532
+ dg = (bin >> 48 & 3) - (bin >> 48 & 4)
533
+ b = bin >> 43 & 0x1f
534
+ db = (bin >> 40 & 3) - (bin >> 40 & 4)
535
+ if r + dr < 0 || r + dr > 31
536
+ # T mode
537
+ base1 = (bin >> 49 & 0xc00) | (bin >> 48 & 0x3ff)
538
+ base1 = (base1 & 0xf00) << 8 | (base1 & 0xf0) << 4 | (base1 & 0xf)
539
+ base1 = (base1 << 4) | base1
540
+ base2 = bin >> 36 & 0xfff
541
+ base2 = (base2 & 0xf00) << 8 | (base2 & 0xf0) << 4 | (base2 & 0xf)
542
+ base2 = (base2 << 4) | base2
543
+ d = Etc2DistanceTable[(bin >> 33 & 6) + bin[32]]
544
+ colors = [[base1].pack('N')[1,3], etc1colormod(base2, d), [base2].pack('N')[1,3], etc1colormod(base2, -d)]
545
+ (0...16).map{|i| colors[bin[i] + bin[i + 16] * 2]}
546
+ elsif g + dg < 0 || g + dg > 31
547
+ # H mode
548
+ base1 = (bin >> 51 & 0xfe0) | (bin >> 48 & 0x18) | (bin >> 47 & 7)
549
+ base1 = (base1 & 0xf00) << 8 | (base1 & 0xf0) << 4 | (base1 & 0xf)
550
+ base1 = (base1 << 4) | base1
551
+ base2 = bin >> 35 & 0xfff
552
+ base2 = (base2 & 0xf00) << 8 | (base2 & 0xf0) << 4 | (base2 & 0xf)
553
+ base2 = (base2 << 4) | base2
554
+ d = Etc2DistanceTable[bin[34] * 2 + bin[32]]
555
+ colors = [etc1colormod(base1, d), etc1colormod(base1, -d), etc1colormod(base2, d), etc1colormod(base2, -d)]
556
+ (0...16).map{|i| colors[bin[i] + bin[i + 16] * 2]}
557
+ elsif b + db < 0 || b + db > 31
558
+ # planar mode
559
+ color_or = (bin >> 55 & 0xfc) | (bin >> 61 & 0x03)
560
+ color_og = (bin >> 49 & 0x80) | (bin >> 48 & 0x7e) | bin[56]
561
+ color_ob = (bin >> 41 & 0x80) | (bin >> 38 & 0x60) | (bin >> 37 & 0x1c) | (bin >> 47 & 2) | bin[44]
562
+ color_hr = (bin >> 31 & 0xf8) | (bin >> 30 & 0x04) | (bin >> 37 & 0x03)
563
+ color_hg = (bin >> 24 & 0xfe) | bin[31]
564
+ color_hb = (bin >> 17 & 0xfc) | (bin >> 23 & 0x03)
565
+ color_vr = (bin >> 11 & 0xfc) | (bin >> 17 & 0x03)
566
+ color_vg = (bin >> 5 & 0xfe) | bin[12]
567
+ color_vb = (bin << 2 & 0xfc) | (bin >> 4 & 0x03)
568
+ (0...16).map do |i|
569
+ x = i / 4
570
+ y = i % 4
571
+ r = (x * (color_hr - color_or) + y * (color_vr - color_or) + 4 * color_or + 2) >> 2
572
+ g = (x * (color_hg - color_og) + y * (color_vg - color_og) + 4 * color_og + 2) >> 2
573
+ b = (x * (color_hb - color_ob) + y * (color_vb - color_ob) + 4 * color_ob + 2) >> 2
574
+ r.clamp(0, 255).chr + g.clamp(0, 255).chr + b.clamp(0, 255).chr
575
+ end
576
+ else
577
+ # differential mode
578
+ colors = [0, 0]
579
+ colors[0] = bin >> 40 & 0xf8f8f8
580
+ colors[1] = colors[0] + (dr << 19) + (dg << 11) + (db << 3)
581
+ colors[0] = colors[0] | (colors[0] >> 5 & 0x70707)
582
+ colors[1] = colors[1] | (colors[1] >> 5 & 0x70707)
583
+ codes = [bin >> 37 & 7, bin >> 34 & 7]
584
+ subblocks = Etc1SubblockTable[bin[32]]
585
+ (0...16).map do |i|
586
+ modifier = Etc1ModifierTable[codes[subblocks[i]]][bin[i]]
587
+ etc1colormod(colors[subblocks[i]], bin[i + 16] == 0 ? modifier : -modifier)
588
+ end
589
+ end
590
+ end
591
+ end
592
+
593
+ def self.decode_etc2alpha_block(bin)
594
+ if bin & 0xf0000000000000 == 0
595
+ Array.new(16, (bin >> 56).chr)
596
+ else
597
+ base = bin >> 56
598
+ mult = bin >> 52 & 0xf
599
+ table = Etc2AlphaModTable[bin >> 48 & 0xf]
600
+ (0...16).map{|i| (base + table[bin >> i*3 & 7] * mult).clamp(0, 255).chr}
601
+ end
602
+ end
603
+
424
604
  # convert 16bit float
425
605
  def self.n2f(n)
426
606
  case n
@@ -1,4 +1,4 @@
1
1
  module Mikunyan
2
2
  # version string
3
- VERSION = "3.9.1"
3
+ VERSION = "3.9.2"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mikunyan
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.1
4
+ version: 3.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ishotihadus
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-08-07 00:00:00.000000000 Z
11
+ date: 2018-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: extlz4
@@ -117,6 +117,7 @@ files:
117
117
  - lib/mikunyan/binary_reader.rb
118
118
  - lib/mikunyan/constants.rb
119
119
  - lib/mikunyan/decoders.rb
120
+ - lib/mikunyan/decoders/astc_block_decoder.rb
120
121
  - lib/mikunyan/decoders/image_decoder.rb
121
122
  - lib/mikunyan/object_value.rb
122
123
  - lib/mikunyan/type_tree.rb
@@ -1032,7 +1033,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1032
1033
  version: '0'
1033
1034
  requirements: []
1034
1035
  rubyforge_project:
1035
- rubygems_version: 2.6.12
1036
+ rubygems_version: 2.6.13
1036
1037
  signing_key:
1037
1038
  specification_version: 4
1038
1039
  summary: Unity asset deserializer for Ruby