mikunyan 3.9.4 → 3.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +35 -41
  4. data/Rakefile +9 -0
  5. data/exe/mikunyan-image +12 -8
  6. data/ext/decoders/native/astc.c +760 -0
  7. data/ext/decoders/native/astc.h +8 -0
  8. data/ext/decoders/native/dxtc.c +104 -0
  9. data/ext/decoders/native/dxtc.h +9 -0
  10. data/ext/decoders/native/etc.c +271 -0
  11. data/ext/decoders/native/etc.h +11 -0
  12. data/ext/decoders/native/extconf.rb +8 -0
  13. data/ext/decoders/native/main.c +167 -0
  14. data/ext/decoders/native/rgb.c +26 -0
  15. data/ext/decoders/native/rgb.h +8 -0
  16. data/lib/mikunyan/asset.rb +13 -7
  17. data/lib/mikunyan/decoders/image_decoder.rb +40 -201
  18. data/lib/mikunyan/typetrees/00ad972a9b8de1baeacb62e297cbb968.dat +0 -0
  19. data/lib/mikunyan/typetrees/01ccfe05c6fbc7ff03dcf8afa8213ff5.dat +0 -0
  20. data/lib/mikunyan/typetrees/086efb68ee41abe4e98e1ae93ae96290.dat +0 -0
  21. data/lib/mikunyan/typetrees/10355709bc95355f57466913ac850d0b.dat +0 -0
  22. data/lib/mikunyan/typetrees/1e87d82d4fd058509a3c7866db0e7356.dat +0 -0
  23. data/lib/mikunyan/typetrees/26165a24a953362edb6a7078f6536c4b.dat +0 -0
  24. data/lib/mikunyan/typetrees/266d53113fa30d2b858f2768f92eaa14.dat +0 -0
  25. data/lib/mikunyan/typetrees/2d2b1d63eb2a68ed94bbf7f50fc21d7b.dat +0 -0
  26. data/lib/mikunyan/typetrees/434b934f757d042e20f52d8c2ae20843.dat +0 -0
  27. data/lib/mikunyan/typetrees/486ba4e15dbd6aea8ac1a064305889c8.dat +0 -0
  28. data/lib/mikunyan/typetrees/49ff511929094ac12ffaa4ab38ed7bd1.dat +0 -0
  29. data/lib/mikunyan/typetrees/4dbfaa1def6adb569b550804b19b4305.dat +0 -0
  30. data/lib/mikunyan/typetrees/5bc42b93159267aabba724a6a7923603.dat +0 -0
  31. data/lib/mikunyan/typetrees/66405447c6973a81e978410c391172fe.dat +0 -0
  32. data/lib/mikunyan/typetrees/6932d6d1d46264c8680a181056f98be2.dat +0 -0
  33. data/lib/mikunyan/typetrees/6974f6c74321933ec4ba7437a55be2c3.dat +0 -0
  34. data/lib/mikunyan/typetrees/69b01db128625aa95f1f92fb890ff045.dat +0 -0
  35. data/lib/mikunyan/typetrees/6f10d8f832d5adde6982d4515b3f0bb3.dat +0 -0
  36. data/lib/mikunyan/typetrees/761ca81f78491542badc37f810ab3455.dat +0 -0
  37. data/lib/mikunyan/typetrees/76ce55d4dbaf38f5c674ea9f0a344951.dat +0 -0
  38. data/lib/mikunyan/typetrees/7e050781d08ca9d10bc74beb7e91c3b5.dat +0 -0
  39. data/lib/mikunyan/typetrees/8198e72b2e2a96b9cfa38636b5565e13.dat +0 -0
  40. data/lib/mikunyan/typetrees/84c6ac46ef89030991cbbb3fd21d2889.dat +0 -0
  41. data/lib/mikunyan/typetrees/852794becbcf95f66992da2b96a69704.dat +0 -0
  42. data/lib/mikunyan/typetrees/961be27d12d60b1b3421191d5256a876.dat +0 -0
  43. data/lib/mikunyan/typetrees/96a47566b4e135078f690a4a69935d58.dat +0 -0
  44. data/lib/mikunyan/typetrees/97da5f4688e45a57c8b42d4f42497297.dat +0 -0
  45. data/lib/mikunyan/typetrees/97ec0712102a3ea3f1cf8c0a4e47c070.dat +0 -0
  46. data/lib/mikunyan/typetrees/9eabac6ec66ffe818e008883728fcc1b.dat +0 -0
  47. data/lib/mikunyan/typetrees/a372646834bcaf26eab1d21b29e39553.dat +0 -0
  48. data/lib/mikunyan/typetrees/a4f194097b08bc4c5019c3a4ea6f5cbd.dat +0 -0
  49. data/lib/mikunyan/typetrees/af863b6969b9b82be9450f0574339f65.dat +0 -0
  50. data/lib/mikunyan/typetrees/b0adafbe24f8148ebf01794ee6679925.dat +0 -0
  51. data/lib/mikunyan/typetrees/b14bcb0865632d1b2d6e215a000e4c0f.dat +0 -0
  52. data/lib/mikunyan/typetrees/b35bf02952f2946208ff6b4deca3a6a9.dat +0 -0
  53. data/lib/mikunyan/typetrees/b6bbd0e88d1feb636d89bd766ea5934f.dat +0 -0
  54. data/lib/mikunyan/typetrees/b78821b6aeb5b79c8961728a9f068024.dat +0 -0
  55. data/lib/mikunyan/typetrees/bea915a8ab3d9b55e80c969a22e692d3.dat +0 -0
  56. data/lib/mikunyan/typetrees/c184743520186f546000de20f4d19736.dat +0 -0
  57. data/lib/mikunyan/typetrees/d50ed13362e98df8096b2f735131fce5.dat +0 -0
  58. data/lib/mikunyan/typetrees/d871346d990bbc294d02f4c366bf1b6d.dat +0 -0
  59. data/lib/mikunyan/typetrees/d8e8eeb43589ccd7019398e56f6c16b0.dat +0 -0
  60. data/lib/mikunyan/typetrees/daea1bb1bba6613afb2cb001ca8fa0d4.dat +0 -0
  61. data/lib/mikunyan/typetrees/db088f9c2f2224da9f488879467856e5.dat +0 -0
  62. data/lib/mikunyan/typetrees/e7c5c01b0369574e9346ce846e1e8e63.dat +0 -0
  63. data/lib/mikunyan/typetrees/f123b055a61dfa7dc679d78cdaecd383.dat +0 -0
  64. data/lib/mikunyan/typetrees/f92d618c5266ea3a8ca770b6eca728c8.dat +0 -0
  65. data/lib/mikunyan/typetrees/fad2d0a58e9174708176102b418facf1.dat +0 -0
  66. data/lib/mikunyan/typetrees/ff001a2e51937aa5add9eaf9cd3d8ae4.dat +0 -0
  67. data/lib/mikunyan/version.rb +1 -1
  68. data/mikunyan.gemspec +1 -0
  69. metadata +63 -4
  70. data/lib/mikunyan/decoders/astc_block_decoder.rb +0 -526
@@ -0,0 +1,26 @@
1
+ #include <stdint.h>
2
+
3
+ static inline int is_system_little() {
4
+ int x = 1;
5
+ return *(char*)&x == 1;
6
+ }
7
+
8
+ void decode_rgb565(const uint16_t* data, const int size, const int is_big_endian, uint8_t* image) {
9
+ const uint16_t *d = data;
10
+ if (is_big_endian == is_system_little()) {
11
+ uint8_t *p = image;
12
+ for (int i = 0; i < size; i++, d++, p += 4) {
13
+ uint_fast8_t r = *d & 0x00f8;
14
+ uint_fast8_t g = (*d & 0x0007) << 5 | (*d & 0xe000) >> 11;
15
+ uint_fast8_t b = (*d & 0x1f00) >> 5;
16
+ p[0] = r | r >> 5;
17
+ p[1] = g | g >> 6;
18
+ p[2] = b | b >> 5;
19
+ p[3] = 255;
20
+ }
21
+ } else {
22
+ uint32_t *p = (uint32_t*)image;
23
+ for (int i = 0; i < size; i++, d++, p++)
24
+ *p = (*d & 0xf800) >> 8 | *d >> 13 | (*d & 0x7e0) << 5 | (*d & 0x60) << 3 | *d << 19 | (*d & 0x1c) << 14 | 0xff000000;
25
+ }
26
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef RGB_H
2
+ #define RGB_H
3
+
4
+ #include <stdint.h>
5
+
6
+ void decode_rgb565(const uint16_t*, const int, const int, uint8_t*);
7
+
8
+ #endif /* end of include guard: RGB_H */
@@ -226,19 +226,25 @@ module Mikunyan
226
226
  children = type_tree[:children]
227
227
 
228
228
  if node.array?
229
- data = []
230
- size = parse_object_private(br, children.find{|e| e[:name] == 'size'})
229
+ data = nil
230
+ size = parse_object_private(br, children.find{|e| e[:name] == 'size'}).value
231
231
  data_type_tree = children.find{|e| e[:name] == 'data'}
232
- size.value.times do |i|
233
- data << parse_object_private(br, data_type_tree)
232
+ if node.type == 'TypelessData'
233
+ data = br.read(size * data_type_tree[:node].size)
234
+ else
235
+ data = size.times.map{ parse_object_private(br, data_type_tree) }
234
236
  end
235
- data = data.map{|e| e.value}.pack('C*') if node.type == 'TypelessData'
236
237
  r = ObjectValue.new(node.name, node.type, br.endian, data)
237
238
  elsif node.size == -1
238
239
  r = ObjectValue.new(node.name, node.type, br.endian)
239
240
  if children.size == 1 && children[0][:name] == 'Array' && children[0][:node].type == 'Array' && children[0][:node].array?
240
- r.value = parse_object_private(br, children[0]).value
241
- r.value = r.value.map{|e| e.value}.pack('C*').force_encoding("utf-8") if node.type == 'string'
241
+ if node.type == 'string'
242
+ size = parse_object_private(br, children[0][:children].find{|e| e[:name] == 'size'}).value
243
+ r.value = br.read(size * children[0][:children].find{|e| e[:name] == 'data'}[:node].size).force_encoding("utf-8")
244
+ br.align(4) if children[0][:node].flags & 0x4000 != 0
245
+ else
246
+ r.value = parse_object_private(br, children[0]).value
247
+ end
242
248
  else
243
249
  children.each do |child|
244
250
  r[child[:name]] = parse_object_private(br, child)
@@ -1,7 +1,6 @@
1
1
  begin; require 'oily_png'; rescue LoadError; require 'chunky_png'; end
2
2
  require 'bin_utils'
3
- require 'fiddle'
4
- require 'mikunyan/decoders/astc_block_decoder'
3
+ require 'mikunyan/decoders/native'
5
4
 
6
5
  module Mikunyan
7
6
  # Class for image decoding tools
@@ -39,6 +38,10 @@ module Mikunyan
39
38
  decode_rgb565(width, height, bin, endian)
40
39
  when 9
41
40
  decode_r16(width, height, bin)
41
+ when 10
42
+ decode_dxt1(width, height, bin)
43
+ when 12
44
+ decode_dxt5(width, height, bin)
42
45
  when 13
43
46
  decode_rgba4444(width, height, bin, endian)
44
47
  when 14
@@ -61,6 +64,8 @@ module Mikunyan
61
64
  decode_etc1(width, height, bin)
62
65
  when 45
63
66
  decode_etc2rgb(width, height, bin)
67
+ when 46
68
+ decode_etc2rgba1(width, height, bin)
64
69
  when 47
65
70
  decode_etc2rgba8(width, height, bin)
66
71
  when 48, 54
@@ -123,15 +128,7 @@ module Mikunyan
123
128
  # @param [Symbol] endian endianness of binary
124
129
  # @return [ChunkyPNG::Image] decoded image
125
130
  def self.decode_rgb565(width, height, bin, endian = :big)
126
- mem = String.new(capacity: width * height * 3)
127
- (width * height).times do |i|
128
- c = endian == :little ? BinUtils.get_int16_le(bin, i*2) : BinUtils.get_int16_be(bin, i*2)
129
- r = (c & 0xf800) >> 8
130
- g = (c & 0x07e0) >> 3
131
- b = (c & 0x001f) << 3
132
- BinUtils.append_int8!(mem, r | r >> 5, g | g >> 6, b | b >> 5)
133
- end
134
- ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
131
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_rgb565(bin, width * height, endian == :big)).flip
135
132
  end
136
133
 
137
134
  # Decode image from A8 binary
@@ -154,7 +151,7 @@ module Mikunyan
154
151
  # @param [String] bin binary to decode
155
152
  # @return [ChunkyPNG::Image] decoded image
156
153
  def self.decode_r8(width, height, bin)
157
- decode_a8(width, height, bin).flip
154
+ decode_a8(width, height, bin)
158
155
  end
159
156
 
160
157
  # Decode image from RG16 binary
@@ -351,22 +348,31 @@ module Mikunyan
351
348
  ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
352
349
  end
353
350
 
351
+ # Decode image from DXT1 compressed binary
352
+ # @param [Integer] width image width
353
+ # @param [Integer] height image height
354
+ # @param [String] bin binary to decode
355
+ # @return [ChunkyPNG::Image] decoded image
356
+ def self.decode_dxt1(width, height, bin)
357
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt1(bin, width, height))
358
+ end
359
+
360
+ # Decode image from DXT5 compressed binary
361
+ # @param [Integer] width image width
362
+ # @param [Integer] height image height
363
+ # @param [String] bin binary to decode
364
+ # @return [ChunkyPNG::Image] decoded image
365
+ def self.decode_dxt5(width, height, bin)
366
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt5(bin, width, height))
367
+ end
368
+
354
369
  # Decode image from ETC1 compressed binary
355
370
  # @param [Integer] width image width
356
371
  # @param [Integer] height image height
357
372
  # @param [String] bin binary to decode
358
373
  # @return [ChunkyPNG::Image] decoded image
359
374
  def self.decode_etc1(width, height, bin)
360
- bw = (width + 3) / 4
361
- bh = (height + 3) / 4
362
- ret = ChunkyPNG::Image.new(bh * 4, bw * 4)
363
- bh.times do |by|
364
- bw.times do |bx|
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), by * 4, bx * 4)
367
- end
368
- end
369
- ret.crop(0, 0, height, width).rotate_left
375
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc1(bin, width, height))
370
376
  end
371
377
 
372
378
  # Decode image from ETC2 compressed binary
@@ -375,16 +381,16 @@ module Mikunyan
375
381
  # @param [String] bin binary to decode
376
382
  # @return [ChunkyPNG::Image] decoded image
377
383
  def self.decode_etc2rgb(width, height, bin)
378
- bw = (width + 3) / 4
379
- bh = (height + 3) / 4
380
- ret = ChunkyPNG::Image.new(bh * 4, bw * 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.join), by * 4, bx * 4)
385
- end
386
- end
387
- ret.crop(0, 0, height, width).rotate_left
384
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2(bin, width, height))
385
+ end
386
+
387
+ # Decode image from ETC2 Alpha1 compressed binary
388
+ # @param [Integer] width image width
389
+ # @param [Integer] height image height
390
+ # @param [String] bin binary to decode
391
+ # @return [ChunkyPNG::Image] decoded image
392
+ def self.decode_etc2rgba1(width, height, bin)
393
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a1(bin, width, height))
388
394
  end
389
395
 
390
396
  # Decode image from ETC2 Alpha8 compressed binary
@@ -393,19 +399,7 @@ module Mikunyan
393
399
  # @param [String] bin binary to decode
394
400
  # @return [ChunkyPNG::Image] decoded image
395
401
  def self.decode_etc2rgba8(width, height, bin)
396
- bw = (width + 3) / 4
397
- bh = (height + 3) / 4
398
- ret = ChunkyPNG::Image.new(bh * 4, bw * 4)
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))
403
- mem = String.new(capacity: 64)
404
- 16.times{|i| mem << block[i] + alpha[i]}
405
- ret.replace!(ChunkyPNG::Image.from_rgba_stream(4, 4, mem), by * 4, bx * 4)
406
- end
407
- end
408
- ret.crop(0, 0, height, width).rotate_left
402
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a8(bin, width, height))
409
403
  end
410
404
 
411
405
  # Decode image from ASTC compressed binary
@@ -415,16 +409,7 @@ module Mikunyan
415
409
  # @param [String] bin binary to decode
416
410
  # @return [ChunkyPNG::Image] decoded image
417
411
  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
412
+ ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_astc(bin, width, height, blocksize, blocksize))
428
413
  end
429
414
 
430
415
  # Create ASTC file data from ObjectValue
@@ -457,152 +442,6 @@ module Mikunyan
457
442
 
458
443
  private
459
444
 
460
- Etc1ModifierTable = [[2, 8], [5, 17], [9, 29], [13, 42], [18, 60], [24, 80], [33, 106], [47, 183]]
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
- ]
481
-
482
- def self.decode_etc1_block(bin)
483
- colors = []
484
- codes = [bin >> 37 & 7, bin >> 34 & 7]
485
- subblocks = Etc1SubblockTable[bin[32]]
486
- if bin[33] == 0
487
- colors[0] = bin >> 40 & 0xf0f0f0
488
- colors[0] = colors[0] | colors[0] >> 4
489
- colors[1] = bin >> 36 & 0xf0f0f0
490
- colors[1] = colors[1] | colors[1] >> 4
491
- else
492
- colors[0] = bin >> 40 & 0xf8f8f8
493
- dr = (bin >> 56 & 3) - (bin >> 56 & 4)
494
- dg = (bin >> 48 & 3) - (bin >> 48 & 4)
495
- db = (bin >> 40 & 3) - (bin >> 40 & 4)
496
- colors[1] = colors[0] + (dr << 19) + (dg << 11) + (db << 3)
497
- colors[0] = colors[0] | (colors[0] >> 5 & 0x70707)
498
- colors[1] = colors[1] | (colors[1] >> 5 & 0x70707)
499
- end
500
-
501
- mem = Fiddle::Pointer.malloc(48)
502
- 16.times do |i|
503
- modifier = Etc1ModifierTable[codes[subblocks[i]]][bin[i]]
504
- mem[i * 3, 3] = etc1colormod(colors[subblocks[i]], bin[i + 16] == 0 ? modifier : -modifier)
505
- end
506
- mem.to_str
507
- end
508
-
509
- def self.etc1colormod(color, modifier)
510
- r = (color >> 16 & 0xff) + modifier
511
- g = (color >> 8 & 0xff) + modifier
512
- b = (color & 0xff) + modifier
513
- r.clamp(0, 255).chr + g.clamp(0, 255).chr + b.clamp(0, 255).chr
514
- end
515
-
516
- def self.decode_etc2_block(bin)
517
- if bin[33] == 0
518
- # individual
519
- colors = [0, 0]
520
- colors[0] = bin >> 40 & 0xf0f0f0
521
- colors[0] = colors[0] | colors[0] >> 4
522
- colors[1] = bin >> 36 & 0xf0f0f0
523
- colors[1] = colors[1] | colors[1] >> 4
524
- codes = [bin >> 37 & 7, bin >> 34 & 7]
525
- subblocks = Etc1SubblockTable[bin[32]]
526
- (0...16).map do |i|
527
- modifier = Etc1ModifierTable[codes[subblocks[i]]][bin[i]]
528
- etc1colormod(colors[subblocks[i]], bin[i + 16] == 0 ? modifier : -modifier)
529
- end
530
- else
531
- r = bin >> 59
532
- dr = (bin >> 56 & 3) - (bin >> 56 & 4)
533
- g = bin >> 51 & 0x1f
534
- dg = (bin >> 48 & 3) - (bin >> 48 & 4)
535
- b = bin >> 43 & 0x1f
536
- db = (bin >> 40 & 3) - (bin >> 40 & 4)
537
- if r + dr < 0 || r + dr > 31
538
- # T mode
539
- base1 = (bin >> 49 & 0xc00) | (bin >> 48 & 0x3ff)
540
- base1 = (base1 & 0xf00) << 8 | (base1 & 0xf0) << 4 | (base1 & 0xf)
541
- base1 = (base1 << 4) | base1
542
- base2 = bin >> 36 & 0xfff
543
- base2 = (base2 & 0xf00) << 8 | (base2 & 0xf0) << 4 | (base2 & 0xf)
544
- base2 = (base2 << 4) | base2
545
- d = Etc2DistanceTable[(bin >> 33 & 6) + bin[32]]
546
- colors = [[base1].pack('N')[1,3], etc1colormod(base2, d), [base2].pack('N')[1,3], etc1colormod(base2, -d)]
547
- (0...16).map{|i| colors[bin[i] + bin[i + 16] * 2]}
548
- elsif g + dg < 0 || g + dg > 31
549
- # H mode
550
- base1 = (bin >> 51 & 0xfe0) | (bin >> 48 & 0x18) | (bin >> 47 & 7)
551
- base1 = (base1 & 0xf00) << 8 | (base1 & 0xf0) << 4 | (base1 & 0xf)
552
- base1 = (base1 << 4) | base1
553
- base2 = bin >> 35 & 0xfff
554
- base2 = (base2 & 0xf00) << 8 | (base2 & 0xf0) << 4 | (base2 & 0xf)
555
- base2 = (base2 << 4) | base2
556
- d = Etc2DistanceTable[bin[34] * 2 + bin[32]]
557
- colors = [etc1colormod(base1, d), etc1colormod(base1, -d), etc1colormod(base2, d), etc1colormod(base2, -d)]
558
- (0...16).map{|i| colors[bin[i] + bin[i + 16] * 2]}
559
- elsif b + db < 0 || b + db > 31
560
- # planar mode
561
- color_or = (bin >> 55 & 0xfc) | (bin >> 61 & 0x03)
562
- color_og = (bin >> 49 & 0x80) | (bin >> 48 & 0x7e) | bin[56]
563
- color_ob = (bin >> 41 & 0x80) | (bin >> 38 & 0x60) | (bin >> 37 & 0x1c) | (bin >> 47 & 2) | bin[44]
564
- color_hr = (bin >> 31 & 0xf8) | (bin >> 30 & 0x04) | (bin >> 37 & 0x03)
565
- color_hg = (bin >> 24 & 0xfe) | bin[31]
566
- color_hb = (bin >> 17 & 0xfc) | (bin >> 23 & 0x03)
567
- color_vr = (bin >> 11 & 0xfc) | (bin >> 17 & 0x03)
568
- color_vg = (bin >> 5 & 0xfe) | bin[12]
569
- color_vb = (bin << 2 & 0xfc) | (bin >> 4 & 0x03)
570
- (0...16).map do |i|
571
- x = i / 4
572
- y = i % 4
573
- r = (x * (color_hr - color_or) + y * (color_vr - color_or) + 4 * color_or + 2) >> 2
574
- g = (x * (color_hg - color_og) + y * (color_vg - color_og) + 4 * color_og + 2) >> 2
575
- b = (x * (color_hb - color_ob) + y * (color_vb - color_ob) + 4 * color_ob + 2) >> 2
576
- r.clamp(0, 255).chr + g.clamp(0, 255).chr + b.clamp(0, 255).chr
577
- end
578
- else
579
- # differential mode
580
- colors = [0, 0]
581
- colors[0] = bin >> 40 & 0xf8f8f8
582
- colors[1] = colors[0] + (dr << 19) + (dg << 11) + (db << 3)
583
- colors[0] = colors[0] | (colors[0] >> 5 & 0x70707)
584
- colors[1] = colors[1] | (colors[1] >> 5 & 0x70707)
585
- codes = [bin >> 37 & 7, bin >> 34 & 7]
586
- subblocks = Etc1SubblockTable[bin[32]]
587
- (0...16).map do |i|
588
- modifier = Etc1ModifierTable[codes[subblocks[i]]][bin[i]]
589
- etc1colormod(colors[subblocks[i]], bin[i + 16] == 0 ? modifier : -modifier)
590
- end
591
- end
592
- end
593
- end
594
-
595
- def self.decode_etc2alpha_block(bin)
596
- if bin & 0xf0000000000000 == 0
597
- Array.new(16, (bin >> 56).chr)
598
- else
599
- base = bin >> 56
600
- mult = bin >> 52 & 0xf
601
- table = Etc2AlphaModTable[bin >> 48 & 0xf]
602
- (0...16).map{|i| (base + table[bin >> i*3 & 7] * mult).clamp(0, 255).chr}
603
- end
604
- end
605
-
606
445
  # convert 16bit float
607
446
  def self.n2f(n)
608
447
  case n