#include "rays/ruby/bitmap.h" #include #include "rays.h" using namespace Rucy; using Rays::uchar; using Rays::ushort; using Rays::ulong; using Rays::coord; namespace Rays { Class bitmap_class () { static Class c = rays_module().define_class("Bitmap"); return c; } }// Rays namespace Rucy { Value value (const Rays::Bitmap& bitmap) { return new_type( Rays::bitmap_class(), new Rays::Bitmap(bitmap)); } }// Rucy #define this to(self) #define CHECK CHECK_OBJECT(self, Rays::Bitmap, Rays::bitmap_class()) static RUBY_DEF_ALLOC(alloc, klass) { return new_type(klass, new Rays::Bitmap); } RUBY_END static RUBY_DEFN(initialize) { CHECK_OBJ(self, Rays::Bitmap, Rays::bitmap_class()); if (argc != 0 && argc != 2 && argc != 3) arg_count_error("Bitmap#initialize", argc, 0, 2, 3); if (argc == 0) return self; int width = to(argv[0]); int height = to(argv[1]); uint colorspace = (argc == 3) ? to(argv[2]) : (uint) Rays::RGBA; *this = Rays::Bitmap(width, height, (Rays::ColorSpaceType) colorspace); return self; } RUBY_END static RUBY_DEF0(width) { CHECK; return value(this->width()); } RUBY_END static RUBY_DEF0(height) { CHECK; return value(this->height()); } RUBY_END static RUBY_DEF0(color_space) { CHECK; return value(this->color_space().type()); } RUBY_END static RUBY_DEF2(at, x, y) { CHECK; int xx = x.as_i(), yy = y.as_i(); void* pixel = this->at(xx, yy); if (!pixel) error("Bitmap#at(%d, %d) failed.", xx, yy); Value array(this->color_space().Bpp() / this->color_space().Bpc(), NULL); if (this->color_space().is_float()) { float* p = (float*) pixel; switch (this->color_space().type()) { case Rays::GRAY_float: array.push(p[0]); break; case Rays::RGB_float: array.push(p[0]).push(p[1]).push(p[2]); break; case Rays::RGBA_float: array.push(p[0]).push(p[1]).push(p[2]).push(p[3]); break; case Rays::ARGB_float: array.push(p[1]).push(p[2]).push(p[3]).push(p[0]); break; case Rays::BGR_float: array.push(p[2]).push(p[1]).push(p[0]); break; case Rays::BGRA_float: array.push(p[2]).push(p[1]).push(p[0]).push(p[3]); break; case Rays::ABGR_float: array.push(p[3]).push(p[2]).push(p[1]).push(p[0]); break; default: error("Bitmap#at: unknown color space"); } } else { uchar* p = (uchar*) pixel; switch (this->color_space().type()) { case Rays::GRAY_8: array.push(*(uchar*) pixel); break; case Rays::GRAY_16: array.push(*(ushort*) pixel); break; case Rays::GRAY_32: array.push(*(ulong*) pixel); break; case Rays::RGB_888: array.push(p[0]).push(p[1]).push(p[2]); break; case Rays::RGBA_8888: array.push(p[0]).push(p[1]).push(p[2]).push(p[3]); break; case Rays::ARGB_8888: array.push(p[1]).push(p[2]).push(p[3]).push(p[0]); break; case Rays::RGBX_8888: array.push(p[0]).push(p[1]).push(p[2]); break; case Rays::XRGB_8888: array.push(p[1]).push(p[2]).push(p[3]); break; case Rays::BGR_888: array.push(p[2]).push(p[1]).push(p[0]); break; case Rays::BGRA_8888: array.push(p[2]).push(p[1]).push(p[0]).push(p[3]); break; case Rays::ABGR_8888: array.push(p[3]).push(p[2]).push(p[1]).push(p[0]); break; case Rays::BGRX_8888: array.push(p[2]).push(p[1]).push(p[0]); break; case Rays::XBGR_8888: array.push(p[3]).push(p[2]).push(p[1]); break; default: error("Bitmap#at: unknown color space"); } } return array; } RUBY_END static RUBY_DEF3(assign_at, x, y, color) { CHECK; int xx = x.as_i(), yy = y.as_i(); void* pixel = this->at(xx, yy); if (!pixel) error("Bitmap#assign_at(%d, %d) failed.", xx, yy); Value array(this->color_space().Bpp() / this->color_space().Bpc(), NULL); if (this->color_space().is_float()) { float* p = (float*) pixel; switch (this->color_space().type()) { #define C(n) ((float) color[n].as_f()) case Rays::GRAY_float: p[0] = C(0); break; case Rays::RGB_float: p[0] = C(0); p[1] = C(1); p[2] = C(2); break; case Rays::RGBA_float: p[0] = C(0); p[1] = C(1); p[2] = C(2); p[3] = C(3); break; case Rays::ARGB_float: p[0] = C(1); p[1] = C(2); p[2] = C(3); p[3] = C(0); break; case Rays::BGR_float: p[0] = C(2); p[1] = C(1); p[2] = C(0); break; case Rays::BGRA_float: p[0] = C(2); p[1] = C(1); p[2] = C(0); p[3] = C(3); break; case Rays::ABGR_float: p[0] = C(3); p[1] = C(2); p[2] = C(1); p[3] = C(0); break; #undef C default: error("Bitmap#at: unknown color space"); } } else { uchar* p = (uchar*) pixel; switch (this->color_space().type()) { #define C(n) ((uchar) color[n].as_i()) case Rays::GRAY_8: *(uchar*) pixel = C(0); break; case Rays::GRAY_16: *(ushort*) pixel = C(0); break; case Rays::GRAY_32: *(ulong*) pixel = C(0); break; case Rays::RGB_888: p[0] = C(0); p[1] = C(1); p[2] = C(2); break; case Rays::RGBA_8888: p[0] = C(0); p[1] = C(1); p[2] = C(2); p[3] = C(3); break; case Rays::ARGB_8888: p[0] = C(1); p[1] = C(2); p[2] = C(3); p[3] = C(0); break; case Rays::RGBX_8888: p[0] = C(0); p[1] = C(1); p[2] = C(2); break; case Rays::XRGB_8888: p[0] = C(1); p[1] = C(2); p[2] = C(3); break; case Rays::BGR_888: p[0] = C(2); p[1] = C(1); p[2] = C(0); break; case Rays::BGRA_8888: p[0] = C(2); p[1] = C(1); p[2] = C(0); p[3] = C(3); break; case Rays::ABGR_8888: p[0] = C(3); p[1] = C(2); p[2] = C(1); p[3] = C(0); break; case Rays::BGRX_8888: p[0] = C(2); p[1] = C(1); p[2] = C(0); break; case Rays::XBGR_8888: p[0] = C(3); p[1] = C(2); p[2] = C(1); break; #undef C default: error("Bitmap#at: unknown color space"); } } return color; } RUBY_END static RUBY_DEF1(load, path) { Rays::Bitmap bmp; if (!Rays::load_bitmap(&bmp, path.c_str())) error("Bitmap.load('%s') failed.", path.c_str()); return value(bmp); } RUBY_END void Init_bitmap () { Rays::rays_module() .define_const("RGB", Rays::RGB) .define_const("RGBA", Rays::RGBA); Rays::bitmap_class() .define_alloc_func(alloc) .define_method("initialize", initialize) .define_method("width", width) .define_method("height", height) .define_method("color_space", color_space) .define_method("[]", at) .define_method("[]=", assign_at) .define_function("load", load); }