ext/rays/bitmap.cpp in rays-0.2.1 vs ext/rays/bitmap.cpp in rays-0.3

- old
+ new

@@ -5,11 +5,11 @@ #include "rays/ruby/color.h" #include "rays/ruby/font.h" #include "defs.h" -RUCY_DEFINE_VALUE_FROM_TO(Rays::Bitmap) +RUCY_DEFINE_VALUE_FROM_TO(RAYS_EXPORT, Rays::Bitmap) #define THIS to<Rays::Bitmap*>(self) #define CHECK RUCY_CHECK_OBJECT(Rays::Bitmap, self) @@ -321,27 +321,27 @@ default: argument_error(__FILE__, __LINE__); } } -static inline Value -to_rgb_value (uint8_t r, uint8_t g, uint8_t b) +static inline uint32_t +to_rgb (uint8_t r, uint8_t g, uint8_t b) { - return value( - ((uint) r) << 16 | - ((uint) g) << 8 | - ((uint) b)); + return + ((uint32_t) r) << 16 | + ((uint32_t) g) << 8 | + ((uint32_t) b); } -static inline Value -to_argb_value (uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static inline uint32_t +to_argb (uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - return value( - ((uint) a) << 24 | - ((uint) r) << 16 | - ((uint) g) << 8 | - ((uint) b)); + return + ((uint32_t) a) << 24 | + ((uint32_t) r) << 16 | + ((uint32_t) g) << 8 | + ((uint32_t) b); } static void get_pixels (auto* pixels, const Rays::Bitmap& bmp) { @@ -396,60 +396,60 @@ case Rays::RGB_888: for (int y = 0; y < h; ++y) { const auto* p = bmp.at<uint8_t>(0, y); for (int x = 0; x < w; ++x, p += 3) - pixels->push_back(to_rgb_value(p[0], p[1], p[2])); + pixels->push_back(value(to_rgb(p[0], p[1], p[2]))); } break; case Rays::RGBA_8888: case Rays::RGBX_8888: for (int y = 0; y < h; ++y) { const auto* p = bmp.at<uint8_t>(0, y); for (int x = 0; x < w; ++x, p += 4) - pixels->push_back(to_argb_value(p[0], p[1], p[2], p[3])); + pixels->push_back(value(to_argb(p[0], p[1], p[2], p[3]))); } break; case Rays::ARGB_8888: case Rays::XRGB_8888: for (int y = 0; y < h; ++y) { const auto* p = bmp.at<uint8_t>(0, y); for (int x = 0; x < w; ++x, p += 4) - pixels->push_back(to_argb_value(p[1], p[2], p[3], p[0])); + pixels->push_back(value(to_argb(p[1], p[2], p[3], p[0]))); } break; case Rays::BGR_888: for (int y = 0; y < h; ++y) { const auto* p = bmp.at<uint8_t>(0, y); for (int x = 0; x < w; ++x, p += 3) - pixels->push_back(to_rgb_value(p[2], p[1], p[0])); + pixels->push_back(value(to_rgb(p[2], p[1], p[0]))); } break; case Rays::BGRA_8888: case Rays::BGRX_8888: for (int y = 0; y < h; ++y) { const auto* p = bmp.at<uint8_t>(0, y); for (int x = 0; x < w; ++x, p += 4) - pixels->push_back(to_argb_value(p[2], p[1], p[0], p[3])); + pixels->push_back(value(to_argb(p[2], p[1], p[0], p[3]))); } break; case Rays::ABGR_8888: case Rays::XBGR_8888: for (int y = 0; y < h; ++y) { const auto* p = bmp.at<uint8_t>(0, y); for (int x = 0; x < w; ++x, p += 4) - pixels->push_back(to_argb_value(p[3], p[2], p[1], p[0])); + pixels->push_back(value(to_argb(p[3], p[2], p[1], p[0]))); } break; case Rays::RGB_float: for (int y = 0; y < h; ++y) @@ -536,36 +536,103 @@ default: argument_error(__FILE__, __LINE__); } } -static -RUCY_DEF1(set_pixels, pixels) +static Value +get_32bit_pixels_string (const Rays::Bitmap& bmp) { - CHECK; + // avoid SEGV caused by 32bit argb value on 'x64-mingw-ucrt' platform. - if (sizeof(VALUE) <= 4) + const auto& cs = bmp.color_space(); + if (cs.bpp() != 32) return nil(); + + int w = bmp.width(), h = bmp.height(); + + std::vector<uint32_t> pixels; + pixels.reserve(w * h); + + switch (cs.type()) { - not_implemented_error( - __FILE__, __LINE__, "Bitmap#pixels=() does not support 32-bit platforms"); + case Rays::GRAY_32: + case Rays::ALPHA_32: + for (int y = 0; y < h; ++y) + { + const auto* p = bmp.at<uint32_t>(0, y); + for (int x = 0; x < w; ++x, ++p) + pixels.push_back(*p); + } + break; + + case Rays::RGBA_8888: + case Rays::RGBX_8888: + for (int y = 0; y < h; ++y) + { + const auto* p = bmp.at<uint8_t>(0, y); + for (int x = 0; x < w; ++x, p += 4) + pixels.push_back(to_argb(p[0], p[1], p[2], p[3])); + } + break; + + case Rays::ARGB_8888: + case Rays::XRGB_8888: + for (int y = 0; y < h; ++y) + { + const auto* p = bmp.at<uint8_t>(0, y); + for (int x = 0; x < w; ++x, p += 4) + pixels.push_back(to_argb(p[1], p[2], p[3], p[0])); + } + break; + + case Rays::BGRA_8888: + case Rays::BGRX_8888: + for (int y = 0; y < h; ++y) + { + const auto* p = bmp.at<uint8_t>(0, y); + for (int x = 0; x < w; ++x, p += 4) + pixels.push_back(to_argb(p[2], p[1], p[0], p[3])); + } + break; + + case Rays::ABGR_8888: + case Rays::XBGR_8888: + for (int y = 0; y < h; ++y) + { + const auto* p = bmp.at<uint8_t>(0, y); + for (int x = 0; x < w; ++x, p += 4) + pixels.push_back(to_argb(p[3], p[2], p[1], p[0])); + } + break; + + default: + return nil(); } + return value( + (const char*) &pixels[0], pixels.size() * sizeof(uint32_t), + rb_ascii8bit_encoding()); +} + +static +RUCY_DEF1(set_pixels, pixels) +{ + CHECK; + set_pixels(THIS, pixels); return pixels; } RUCY_END static RUCY_DEF0(get_pixels) { CHECK; - if (sizeof(VALUE) <= 4) - { - not_implemented_error( - __FILE__, __LINE__, "Bitmap#pixels() does not support 32-bit platforms"); - } +#ifdef RAYS_32BIT_PIXELS_STRING + Value str = get_32bit_pixels_string(*THIS); + if (str) return str; +#endif std::vector<VALUE> pixels; get_pixels(&pixels, *THIS); return array((const Value*) &pixels[0], pixels.size()); } @@ -611,10 +678,10 @@ cBitmap.define_private_method("initialize_copy", initialize_copy); cBitmap.define_method("width", width); cBitmap.define_method("height", height); cBitmap.define_method("color_space", color_space); cBitmap.define_method("pixels=", set_pixels); - cBitmap.define_method("pixels", get_pixels); + cBitmap.define_method("pixels!", get_pixels); cBitmap.define_method("[]=", set_at); cBitmap.define_method("[]", get_at); }