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 +4 -4
- data/README.md +2 -2
- data/exe/mikunyan-json +1 -1
- data/lib/mikunyan/decoders.rb +6 -0
- data/lib/mikunyan/decoders/astc_block_decoder.rb +530 -0
- data/lib/mikunyan/decoders/image_decoder.rb +191 -11
- data/lib/mikunyan/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0674f5a0c11d5d34d86e845f11aaddbf72256047
|
4
|
+
data.tar.gz: 5ebf875cc82f0b2678092aa87171c2fb96a134df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
122
|
+
Mikunyan cannot decode ASTC with HDR data. Use `Mikunyan::ImageDecoder.create_astc_file` instead.
|
123
123
|
|
124
124
|
### Json / YAML Outputer
|
125
125
|
|
data/exe/mikunyan-json
CHANGED
data/lib/mikunyan/decoders.rb
CHANGED
@@ -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
|
-
|
33
|
+
decode_rgb24(width, height, bin)
|
33
34
|
when 4
|
34
|
-
|
35
|
+
decode_rgba32(width, height, bin)
|
35
36
|
when 5
|
36
|
-
|
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
|
-
|
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
|
-
|
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) *
|
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.
|
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
|
-
|
410
|
-
16.times do |i|
|
501
|
+
(0...16).map do |i|
|
411
502
|
modifier = Etc1ModifierTable[codes[subblocks[i]]][bin[i]]
|
412
|
-
|
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
|
data/lib/mikunyan/version.rb
CHANGED
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.
|
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:
|
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.
|
1036
|
+
rubygems_version: 2.6.13
|
1036
1037
|
signing_key:
|
1037
1038
|
specification_version: 4
|
1038
1039
|
summary: Unity asset deserializer for Ruby
|