mikunyan 3.9.1 → 3.9.2

Sign up to get free protection for your applications and to get access to all the features.
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