Class: Mikunyan::ImageDecoder

Inherits:
Object
  • Object
show all
Defined in:
lib/mikunyan/decoders/image_decoder.rb

Overview

Class for image decoding tools

Class Method Summary collapse

Class Method Details

.create_astc_file(object) ⇒ String?

Create ASTC file data from ObjectValue

Parameters:

Returns:

  • (String, nil)

    created file



423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
# File 'lib/mikunyan/decoders/image_decoder.rb', line 423

def self.create_astc_file(object)
    astc_list = {
        48 => 4, 49 => 5, 50 => 6, 51 => 8, 52 => 10, 53 => 12,
        54 => 4, 55 => 5, 56 => 6, 57 => 8, 58 => 10, 59 => 12
    }
    width = object['m_Width']
    height = object['m_Height']
    fmt = object['m_TextureFormat']
    bin = object['image data']
    width = width.value if width.class == ObjectValue
    height = height.value if height.class == ObjectValue
    fmt = fmt.value if fmt.class == ObjectValue
    bin = bin.value if bin.class == ObjectValue
    if width && height && fmt && astc_list[fmt]
        header = "\x13\xAB\xA1\x5C".force_encoding('ascii-8bit')
        header << [astc_list[fmt], astc_list[fmt], 1].pack("C*")
        header << [width].pack("V").byteslice(0, 3)
        header << [height].pack("V").byteslice(0, 3)
        header << "\x01\x00\x00"
        header + bin
    else
        nil
    end
end

.decode_a8(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from A8 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



144
145
146
147
148
149
150
151
# File 'lib/mikunyan/decoders/image_decoder.rb', line 144

def self.decode_a8(width, height, bin)
    mem = String.new(capacity: width * height * 3)
    (width * height).times do |i|
        c = BinUtils.get_int8(bin, i)
        BinUtils.append_int8!(mem, c, c, c)
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end

.decode_argb32(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from ARGB32 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



198
199
200
201
202
203
204
205
# File 'lib/mikunyan/decoders/image_decoder.rb', line 198

def self.decode_argb32(width, height, bin)
    mem = String.new(capacity: width * height * 4)
    (width * height).times do |i|
        c = BinUtils.get_int32_be(bin, i*4)
        BinUtils.append_int32_be!(mem, ((c & 0x00ffffff) << 8) | ((c & 0xff000000) >> 24))
    end
    ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
end

.decode_argb4444(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from ARGB4444 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



119
120
121
122
123
124
125
126
127
# File 'lib/mikunyan/decoders/image_decoder.rb', line 119

def self.decode_argb4444(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 4)
    (width * height).times do |i|
        c = endian == :little ? BinUtils.get_int16_le(bin, i*2) : BinUtils.get_int16_be(bin, i*2)
        c = ((c & 0x0f00) << 16) | ((c & 0x00f0) << 12) | ((c & 0x000f) << 8) | ((c & 0xf000) >> 12)
        BinUtils.append_int32_be!(mem, c << 4 | c)
    end
    ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
end

.decode_astc(width, height, blocksize, bin) ⇒ ChunkyPNG::Image

Decode image from ASTC compressed binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • blocksize (Integer)

    block size

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



416
417
418
# File 'lib/mikunyan/decoders/image_decoder.rb', line 416

def self.decode_astc(width, height, blocksize, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_astc(bin, width, height, blocksize, blocksize))
end

.decode_bgra32(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from BGRA32 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



212
213
214
215
216
217
218
219
# File 'lib/mikunyan/decoders/image_decoder.rb', line 212

def self.decode_bgra32(width, height, bin)
    mem = String.new(capacity: width * height * 4)
    (width * height).times do |i|
        c = BinUtils.get_int32_le(bin, i*4)
        BinUtils.append_int32_be!(mem, ((c & 0x00ffffff) << 8) | ((c & 0xff000000) >> 24))
    end
    ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
end

.decode_dxt1(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from DXT1 compressed binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



361
362
363
# File 'lib/mikunyan/decoders/image_decoder.rb', line 361

def self.decode_dxt1(width, height, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt1(bin, width, height))
end

.decode_dxt5(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from DXT5 compressed binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



370
371
372
# File 'lib/mikunyan/decoders/image_decoder.rb', line 370

def self.decode_dxt5(width, height, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt5(bin, width, height))
end

.decode_etc1(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from ETC1 compressed binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



379
380
381
# File 'lib/mikunyan/decoders/image_decoder.rb', line 379

def self.decode_etc1(width, height, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc1(bin, width, height))
end

.decode_etc2rgb(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from ETC2 compressed binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



388
389
390
# File 'lib/mikunyan/decoders/image_decoder.rb', line 388

def self.decode_etc2rgb(width, height, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2(bin, width, height))
end

.decode_etc2rgba1(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from ETC2 Alpha1 compressed binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



397
398
399
# File 'lib/mikunyan/decoders/image_decoder.rb', line 397

def self.decode_etc2rgba1(width, height, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a1(bin, width, height))
end

.decode_etc2rgba8(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from ETC2 Alpha8 compressed binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



406
407
408
# File 'lib/mikunyan/decoders/image_decoder.rb', line 406

def self.decode_etc2rgba8(width, height, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a8(bin, width, height))
end

.decode_object(object) ⇒ ChunkyPNG::Image?

Decode image from Mikunyan::ObjectValue

Parameters:

Returns:

  • (ChunkyPNG::Image, nil)

    decoded image



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/mikunyan/decoders/image_decoder.rb', line 11

def self.decode_object(object)
    return nil unless object.class == ObjectValue

    endian = object.endian
    width = object['m_Width']
    height = object['m_Height']
    bin = object['image data']
    fmt = object['m_TextureFormat']
    return nil unless width && height && bin && fmt

    width = width.value
    height = height.value
    bin = bin.value
    fmt = fmt.value

    if bin.size == 0 && object['m_StreamData']
        bin = object['m_StreamData'].value
        return nil unless bin
    end

    case fmt
    when 1
        decode_a8(width, height, bin)
    when 2
        decode_argb4444(width, height, bin, endian)
    when 3
        decode_rgb24(width, height, bin)
    when 4
        decode_rgba32(width, height, bin)
    when 5
        decode_argb32(width, height, bin)
    when 7
        decode_rgb565(width, height, bin, endian)
    when 9
        decode_r16(width, height, bin)
    when 10
        decode_dxt1(width, height, bin)
    when 12
        decode_dxt5(width, height, bin)
    when 13
        decode_rgba4444(width, height, bin, endian)
    when 14
        decode_bgra32(width, height, bin)
    when 15
        decode_rhalf(width, height, bin, endian)
    when 16
        decode_rghalf(width, height, bin, endian)
    when 17
        decode_rgbahalf(width, height, bin, endian)
    when 18
        decode_rfloat(width, height, bin, endian)
    when 19
        decode_rgfloat(width, height, bin, endian)
    when 20
        decode_rgbafloat(width, height, bin, endian)
    when 22
        decode_rgb9e5float(width, height, bin, endian)
    when 34
        decode_etc1(width, height, bin)
    when 45
        decode_etc2rgb(width, height, bin)
    when 46
        decode_etc2rgba1(width, height, bin)
    when 47
        decode_etc2rgba8(width, height, bin)
    when 48, 54
        decode_astc(width, height, 4, bin)
    when 49, 55
        decode_astc(width, height, 5, bin)
    when 50, 56
        decode_astc(width, height, 6, bin)
    when 51, 57
        decode_astc(width, height, 8, bin)
    when 52, 58
        decode_astc(width, height, 10, bin)
    when 53, 59
        decode_astc(width, height, 12, bin)
    when 62
        decode_rg16(width, height, bin)
    when 63
        decode_r8(width, height, bin)
    else
        nil
    end
end

.decode_r16(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from R16 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



227
228
229
230
231
232
233
234
235
# File 'lib/mikunyan/decoders/image_decoder.rb', line 227

def self.decode_r16(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 3)
    (width * height).times do |i|
        c = endian == :little ? BinUtils.get_int16_le(bin, i*2) : BinUtils.get_int16_be(bin, i*2)
        c = f2i(r / 65535.0)
        BinUtils.append_int8!(mem, c, c, c)
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end

.decode_r8(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from R8 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



158
159
160
# File 'lib/mikunyan/decoders/image_decoder.rb', line 158

def self.decode_r8(width, height, bin)
    decode_a8(width, height, bin)
end

.decode_rfloat(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from R float binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



314
315
316
317
318
319
320
321
322
# File 'lib/mikunyan/decoders/image_decoder.rb', line 314

def self.decode_rfloat(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 3)
    unpackstr = endian == :little ? 'e' : 'g'
    (width * height).times do |i|
        c = f2i(bin.byteslice(i*4, 4).unpack(unpackstr)[0])
        BinUtils.append_int8!(mem, c, c, c)
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end

.decode_rg16(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from RG16 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



167
168
169
170
171
172
173
# File 'lib/mikunyan/decoders/image_decoder.rb', line 167

def self.decode_rg16(width, height, bin)
    mem = String.new(capacity: width * height * 3)
    (width * height).times do |i|
        BinUtils.append_int16_int8_be!(mem, BinUtils.get_int16_be(bin, i*2), 0)
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end

.decode_rgb24(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from RGB24 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



180
181
182
# File 'lib/mikunyan/decoders/image_decoder.rb', line 180

def self.decode_rgb24(width, height, bin)
    ChunkyPNG::Image.from_rgb_stream(width, height, bin).flip
end

.decode_rgb565(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from RGB565 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



135
136
137
# File 'lib/mikunyan/decoders/image_decoder.rb', line 135

def self.decode_rgb565(width, height, bin, endian = :big)
    ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_rgb565(bin, width * height, endian == :big)).flip
end

.decode_rgb9e5float(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from RGB9e5 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/mikunyan/decoders/image_decoder.rb', line 243

def self.decode_rgb9e5float(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 3)
    (width * height).times do |i|
        n = endian == :little ? BinUtils.get_int32_le(bin, i*4) : BinUtils.get_int32_be(bin, i*4)
        e = (n & 0xf8000000) >> 27
        r = (n & 0x7fc0000) >> 9
        g = (n & 0x3fe00) >> 9
        b = n & 0x1ff
        r = (r / 512r + 1) * (2**(e-15))
        g = (g / 512r + 1) * (2**(e-15))
        b = (b / 512r + 1) * (2**(e-15))
        BinUtils.append_int8!(mem, f2i(r), f2i(g), f2i(b))
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end

.decode_rgba32(width, height, bin) ⇒ ChunkyPNG::Image

Decode image from RGBA32 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

Returns:

  • (ChunkyPNG::Image)

    decoded image



189
190
191
# File 'lib/mikunyan/decoders/image_decoder.rb', line 189

def self.decode_rgba32(width, height, bin)
    ChunkyPNG::Image.from_rgba_stream(width, height, bin).flip
end

.decode_rgba4444(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from RGBA4444 binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



103
104
105
106
107
108
109
110
111
# File 'lib/mikunyan/decoders/image_decoder.rb', line 103

def self.decode_rgba4444(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 4)
    (width * height).times do |i|
        c = endian == :little ? BinUtils.get_int16_le(bin, i*2) : BinUtils.get_int16_be(bin, i*2)
        c = ((c & 0xf000) << 12) | ((c & 0x0f00) << 8) | ((c & 0x00f0) << 4) | (c & 0x000f)
        BinUtils.append_int32_be!(mem, c << 4 | c)
    end
    ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
end

.decode_rgbafloat(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from RGBA float binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



346
347
348
349
350
351
352
353
354
# File 'lib/mikunyan/decoders/image_decoder.rb', line 346

def self.decode_rgbafloat(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 4)
    unpackstr = endian == :little ? 'e4' : 'g4'
    (width * height).times do |i|
        r, g, b, a = bin.byteslice(i*16, 16).unpack(unpackstr)
        BinUtils.append_int8!(mem, f2i(r), f2i(g), f2i(b), f2i(a))
    end
    ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
end

.decode_rgbahalf(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from RGBA Half-float binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



296
297
298
299
300
301
302
303
304
305
306
# File 'lib/mikunyan/decoders/image_decoder.rb', line 296

def self.decode_rgbahalf(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 4)
    (width * height).times do |i|
        r = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i*8) : BinUtils.get_int16_be(bin, i*8)))
        g = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i*8+2) : BinUtils.get_int16_be(bin, i*8+2)))
        b = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i*8+4) : BinUtils.get_int16_be(bin, i*8+4)))
        a = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i*8+6) : BinUtils.get_int16_be(bin, i*8+6)))
        BinUtils.append_int8!(mem, r, g, b, a)
    end
    ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
end

.decode_rgfloat(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from RG float binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



330
331
332
333
334
335
336
337
338
# File 'lib/mikunyan/decoders/image_decoder.rb', line 330

def self.decode_rgfloat(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 3)
    unpackstr = endian == :little ? 'e2' : 'g2'
    (width * height).times do |i|
        r, g = bin.byteslice(i*8, 8).unpack(unpackstr)
        BinUtils.append_int8!(mem, f2i(r), f2i(g), 0)
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end

.decode_rghalf(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from RG Half-float binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



280
281
282
283
284
285
286
287
288
# File 'lib/mikunyan/decoders/image_decoder.rb', line 280

def self.decode_rghalf(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 3)
    (width * height).times do |i|
        r = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i*4) : BinUtils.get_int16_be(bin, i*4)))
        g = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i*4+2) : BinUtils.get_int16_be(bin, i*4+2)))
        BinUtils.append_int8!(mem, r, g, 0)
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end

.decode_rhalf(width, height, bin, endian = :big) ⇒ ChunkyPNG::Image

Decode image from R Half-float binary

Parameters:

  • width (Integer)

    image width

  • height (Integer)

    image height

  • bin (String)

    binary to decode

  • endian (Symbol) (defaults to: :big)

    endianness of binary

Returns:

  • (ChunkyPNG::Image)

    decoded image



265
266
267
268
269
270
271
272
# File 'lib/mikunyan/decoders/image_decoder.rb', line 265

def self.decode_rhalf(width, height, bin, endian = :big)
    mem = String.new(capacity: width * height * 3)
    (width * height).times do |i|
        c = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i*2) : BinUtils.get_int16_be(bin, i*2)))
        BinUtils.append_int8!(mem, c, c, c)
    end
    ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
end