RGB565 Native Decoding Support

This commit is contained in:
Ishotihadus
2018-05-26 21:42:02 +09:00
parent 363c9b01d4
commit e07f6ae46b
4 changed files with 49 additions and 9 deletions
+10
View File
@@ -2,6 +2,15 @@
#include <stdint.h>
#include <ruby.h>
#include "astc.h"
#include "rgb.h"
static VALUE rb_decode_rgb565(VALUE self, VALUE rb_data, VALUE size, VALUE big) {
uint8_t *image = (uint8_t*)malloc(FIX2LONG(size) * 3);
decode_rgb565((uint16_t*)RSTRING_PTR(rb_data), FIX2INT(size), RTEST(big), image);
VALUE ret = rb_str_new((char*)image, FIX2LONG(size) * 3);
free(image);
return ret;
}
static VALUE rb_decode_astc(VALUE self, VALUE rb_data, VALUE w, VALUE h, VALUE bw, VALUE bh) {
const uint8_t *data = (uint8_t*)RSTRING_PTR(rb_data);
@@ -16,4 +25,5 @@ void Init_native() {
VALUE mMikunyan = rb_define_module("Mikunyan");
VALUE mDecodeHelper = rb_define_module_under(mMikunyan, "DecodeHelper");
rb_define_module_function(mDecodeHelper, "decode_astc", rb_decode_astc, 5);
rb_define_module_function(mDecodeHelper, "decode_rgb565", rb_decode_rgb565, 3);
}
+30
View File
@@ -0,0 +1,30 @@
#include <stdint.h>
static inline int is_system_little() {
int x = 1;
return *(char*)&x == 1;
}
void decode_rgb565(const uint16_t* data, const int size, const int is_big_endian, uint8_t* image) {
const uint16_t *d = data;
uint8_t *p = image;
if (is_big_endian == is_system_little()) {
for (int i = 0; i < size; i++, d++, p += 3) {
uint8_t r = *d & 0x00f8;
uint8_t g = (*d & 0x0007) << 5 | (*d & 0xe000) >> 11;
uint8_t b = (*d & 0x1f00) >> 5;
p[0] = r | r >> 5;
p[1] = g | g >> 6;
p[2] = b | b >> 5;
}
} else {
for (int i = 0; i < size; i++, d++, p += 3) {
uint8_t r = (*d & 0xf800) >> 8;
uint8_t g = (*d & 0x07e0) >> 3;
uint8_t b = (*d & 0x001f) << 3;
p[0] = r | r >> 5;
p[1] = g | g >> 6;
p[2] = b | b >> 5;
}
}
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef RGB_H
#define RGB_H
#include <stdint.h>
void decode_rgb565(const uint16_t*, const int, const int, uint8_t*);
#endif /* end of include guard: RGB_H */
+1 -9
View File
@@ -127,15 +127,7 @@ module Mikunyan
# @param [Symbol] endian endianness of binary
# @return [ChunkyPNG::Image] decoded image
def self.decode_rgb565(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)
r = (c & 0xf800) >> 8
g = (c & 0x07e0) >> 3
b = (c & 0x001f) << 3
BinUtils.append_int8!(mem, r | r >> 5, g | g >> 6, b | b >> 5)
end
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
ChunkyPNG::Image.from_rgb_stream(width, height, DecodeHelper.decode_rgb565(bin, width * height, endian == :big)).flip
end
# Decode image from A8 binary