ext/rays/bitmap.cpp in rays-0.1.47 vs ext/rays/bitmap.cpp in rays-0.1.48
- old
+ new
@@ -70,21 +70,272 @@
return value(THIS->color_space());
}
RUCY_END
+static void
+set_pixels (Rays::Bitmap* bmp, Value pixels)
+{
+ int w = bmp->width(), h = bmp->height();
+ const auto& cs = bmp->color_space();
+ if (pixels.size() != (w * h * (cs.is_float() ? cs.Bpp() / cs.Bpc() : 1)))
+ {
+ argument_error(
+ __FILE__, __LINE__,
+ "The size of the pixel array does not match the size of the bitmap");
+ }
+
+ const Value* array = pixels.as_array();
+
+ switch (cs.type())
+ {
+ case Rays::GRAY_8:
+ case Rays::ALPHA_8:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint8_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, ++pb)
+ *pb = to<uint8_t>(*pa);
+ }
+ break;
+
+ case Rays::GRAY_16:
+ case Rays::ALPHA_16:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint16_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, ++pb)
+ *pb = to<uint16_t>(*pa);
+ }
+ break;
+
+ case Rays::GRAY_32:
+ case Rays::ALPHA_32:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint32_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, ++pb)
+ *pb = to<uint32_t>(*pa);
+ }
+ break;
+
+ case Rays::GRAY_float:
+ case Rays::ALPHA_float:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<float>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, ++pb)
+ *pb = to<float>(*pa);
+ }
+ break;
+
+ case Rays::RGB_888:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint8_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, pb += 3)
+ {
+ uint32_t argb = to<uint32_t>(*pa);
+ pb[0] = (uint8_t) (argb >> 16 & 0xff);
+ pb[1] = (uint8_t) (argb >> 8 & 0xff);
+ pb[2] = (uint8_t) (argb >> 0 & 0xff);
+ }
+ }
+ break;
+
+ case Rays::RGBA_8888:
+ case Rays::RGBX_8888:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint8_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, pb += 4)
+ {
+ uint32_t argb = to<uint32_t>(*pa);
+ pb[0] = (uint8_t) (argb >> 16 & 0xff);
+ pb[1] = (uint8_t) (argb >> 8 & 0xff);
+ pb[2] = (uint8_t) (argb >> 0 & 0xff);
+ pb[3] = (uint8_t) (argb >> 24 & 0xff);
+ }
+ }
+ break;
+
+ case Rays::ARGB_8888:
+ case Rays::XRGB_8888:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint8_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, pb += 4)
+ {
+ uint32_t argb = to<uint32_t>(*pa);
+ pb[0] = (uint8_t) (argb >> 24 & 0xff);
+ pb[1] = (uint8_t) (argb >> 16 & 0xff);
+ pb[2] = (uint8_t) (argb >> 8 & 0xff);
+ pb[3] = (uint8_t) (argb >> 0 & 0xff);
+ }
+ }
+ break;
+
+ case Rays::BGR_888:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint8_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, pb += 3)
+ {
+ uint32_t argb = to<uint32_t>(*pa);
+ pb[0] = (uint8_t) (argb >> 0 & 0xff);
+ pb[1] = (uint8_t) (argb >> 8 & 0xff);
+ pb[2] = (uint8_t) (argb >> 16 & 0xff);
+ }
+ }
+ break;
+
+ case Rays::BGRA_8888:
+ case Rays::BGRX_8888:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint8_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, pb += 4)
+ {
+ uint32_t argb = to<uint32_t>(*pa);
+ pb[0] = (uint8_t) (argb >> 0 & 0xff);
+ pb[1] = (uint8_t) (argb >> 8 & 0xff);
+ pb[2] = (uint8_t) (argb >> 16 & 0xff);
+ pb[3] = (uint8_t) (argb >> 24 & 0xff);
+ }
+ }
+ break;
+
+ case Rays::ABGR_8888:
+ case Rays::XBGR_8888:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[w * y];
+ auto* pb = bmp->at<uint8_t>(0, y);
+ for (int x = 0; x < w; ++x, ++pa, pb += 4)
+ {
+ uint32_t argb = to<uint32_t>(*pa);
+ pb[0] = (uint8_t) (argb >> 24 & 0xff);
+ pb[1] = (uint8_t) (argb >> 0 & 0xff);
+ pb[2] = (uint8_t) (argb >> 8 & 0xff);
+ pb[3] = (uint8_t) (argb >> 16 & 0xff);
+ }
+ }
+ break;
+
+ case Rays::RGB_float:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[3 * w * y];
+ auto* pb = bmp->at<float>(0, y);
+ for (int x = 0; x < w; ++x, pa += 3, pb += 3)
+ {
+ pb[0] = to<float>(pa[0]);
+ pb[1] = to<float>(pa[1]);
+ pb[2] = to<float>(pa[2]);
+ }
+ }
+ break;
+
+ case Rays::RGBA_float:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[4 * w * y];
+ auto* pb = bmp->at<float>(0, y);
+ for (int x = 0; x < w; ++x, pa += 4, pb += 4)
+ {
+ pb[0] = to<float>(pa[0]);
+ pb[1] = to<float>(pa[1]);
+ pb[2] = to<float>(pa[2]);
+ pb[3] = to<float>(pa[3]);
+ }
+ }
+ break;
+
+ case Rays::ARGB_float:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[4 * w * y];
+ auto* pb = bmp->at<float>(0, y);
+ for (int x = 0; x < w; ++x, pa += 4, pb += 4)
+ {
+ pb[0] = to<float>(pa[3]);
+ pb[1] = to<float>(pa[0]);
+ pb[2] = to<float>(pa[1]);
+ pb[3] = to<float>(pa[2]);
+ }
+ }
+ break;
+
+ case Rays::BGR_float:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[3 * w * y];
+ auto* pb = bmp->at<float>(0, y);
+ for (int x = 0; x < w; ++x, pa += 3, pb += 3)
+ {
+ pb[0] = to<float>(pa[2]);
+ pb[1] = to<float>(pa[1]);
+ pb[2] = to<float>(pa[0]);
+ }
+ }
+ break;
+
+ case Rays::BGRA_float:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[4 * w * y];
+ auto* pb = bmp->at<float>(0, y);
+ for (int x = 0; x < w; ++x, pa += 4, pb += 4)
+ {
+ pb[0] = to<float>(pa[2]);
+ pb[1] = to<float>(pa[1]);
+ pb[2] = to<float>(pa[0]);
+ pb[3] = to<float>(pa[3]);
+ }
+ }
+ break;
+
+ case Rays::ABGR_float:
+ for (int y = 0; y < h; ++y)
+ {
+ const Value* pa = &array[4 * w * y];
+ auto* pb = bmp->at<float>(0, y);
+ for (int x = 0; x < w; ++x, pa += 4, pb += 4)
+ {
+ pb[0] = to<float>(pa[3]);
+ pb[1] = to<float>(pa[2]);
+ pb[2] = to<float>(pa[1]);
+ pb[3] = to<float>(pa[0]);
+ }
+ }
+ break;
+
+ default:
+ argument_error(__FILE__, __LINE__);
+ }
+}
+
static inline Value
to_rgb_value (uint8_t r, uint8_t g, uint8_t b)
{
return value(
((uint) r) << 16 |
((uint) g) << 8 |
((uint) b));
}
static inline Value
-to_rgba_value (uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+to_argb_value (uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
return value(
((uint) a) << 24 |
((uint) r) << 16 |
((uint) g) << 8 |
@@ -93,12 +344,12 @@
static void
get_pixels (auto* pixels, const Rays::Bitmap& bmp)
{
int w = bmp.width(), h = bmp.height();
-
const auto& cs = bmp.color_space();
+
pixels->clear();
pixels->reserve(w * h * (cs.is_float() ? cs.Bpp() / cs.Bpc() : 1));
switch (cs.type())
{
@@ -150,42 +401,26 @@
pixels->push_back(to_rgb_value(p[0], p[1], p[2]));
}
break;
case Rays::RGBA_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_rgba_value(p[0], p[1], p[2], p[3]));
- }
- break;
-
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_rgb_value(p[0], p[1], p[2]));
+ pixels->push_back(to_argb_value(p[0], p[1], p[2], p[3]));
}
break;
case Rays::ARGB_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_rgba_value(p[1], p[2], p[3], p[0]));
- }
- break;
-
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_rgb_value(p[1], p[2], p[3]));
+ pixels->push_back(to_argb_value(p[1], p[2], p[3], p[0]));
}
break;
case Rays::BGR_888:
for (int y = 0; y < h; ++y)
@@ -195,49 +430,33 @@
pixels->push_back(to_rgb_value(p[2], p[1], p[0]));
}
break;
case Rays::BGRA_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_rgba_value(p[2], p[1], p[0], p[3]));
- }
- break;
-
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_rgb_value(p[2], p[1], p[0]));
+ pixels->push_back(to_argb_value(p[2], p[1], p[0], p[3]));
}
break;
case Rays::ABGR_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_rgba_value(p[3], p[2], p[1], p[0]));
- }
- break;
-
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_rgb_value(p[3], p[2], p[1]));
+ pixels->push_back(to_argb_value(p[3], p[2], p[1], p[0]));
}
break;
case Rays::RGB_float:
for (int y = 0; y < h; ++y)
{
- const auto* p = bmp.at<uint8_t>(0, y);
+ const auto* p = bmp.at<float>(0, y);
for (int x = 0; x < w; ++x, p += 3)
{
pixels->push_back(value(p[0]));
pixels->push_back(value(p[1]));
pixels->push_back(value(p[2]));
@@ -246,11 +465,11 @@
break;
case Rays::RGBA_float:
for (int y = 0; y < h; ++y)
{
- const auto* p = bmp.at<uint8_t>(0, y);
+ const auto* p = bmp.at<float>(0, y);
for (int x = 0; x < w; ++x, p += 4)
{
pixels->push_back(value(p[0]));
pixels->push_back(value(p[1]));
pixels->push_back(value(p[2]));
@@ -260,11 +479,11 @@
break;
case Rays::ARGB_float:
for (int y = 0; y < h; ++y)
{
- const auto* p = bmp.at<uint8_t>(0, y);
+ const auto* p = bmp.at<float>(0, y);
for (int x = 0; x < w; ++x, p += 4)
{
pixels->push_back(value(p[1]));
pixels->push_back(value(p[2]));
pixels->push_back(value(p[3]));
@@ -274,11 +493,11 @@
break;
case Rays::BGR_float:
for (int y = 0; y < h; ++y)
{
- const auto* p = bmp.at<uint8_t>(0, y);
+ const auto* p = bmp.at<float>(0, y);
for (int x = 0; x < w; ++x, p += 3)
{
pixels->push_back(value(p[2]));
pixels->push_back(value(p[1]));
pixels->push_back(value(p[0]));
@@ -287,11 +506,11 @@
break;
case Rays::BGRA_float:
for (int y = 0; y < h; ++y)
{
- const auto* p = bmp.at<uint8_t>(0, y);
+ const auto* p = bmp.at<float>(0, y);
for (int x = 0; x < w; ++x, p += 4)
{
pixels->push_back(value(p[2]));
pixels->push_back(value(p[1]));
pixels->push_back(value(p[0]));
@@ -301,11 +520,11 @@
break;
case Rays::ABGR_float:
for (int y = 0; y < h; ++y)
{
- const auto* p = bmp.at<uint8_t>(0, y);
+ const auto* p = bmp.at<float>(0, y);
for (int x = 0; x < w; ++x, p += 4)
{
pixels->push_back(value(p[3]));
pixels->push_back(value(p[2]));
pixels->push_back(value(p[1]));
@@ -318,14 +537,36 @@
argument_error(__FILE__, __LINE__);
}
}
static
-RUCY_DEF0(pixels)
+RUCY_DEF1(set_pixels, pixels)
{
CHECK;
+ if (sizeof(VALUE) <= 4)
+ {
+ not_implemented_error(
+ __FILE__, __LINE__, "Bitmap#pixels=() does not support 32-bit platforms");
+ }
+
+ 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");
+ }
+
std::vector<VALUE> pixels;
get_pixels(&pixels, *THIS);
return value(pixels.size(), (const Value*) &pixels[0]);
}
RUCY_END
@@ -369,10 +610,11 @@
cBitmap.define_private_method("initialize", initialize);
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", pixels);
+ cBitmap.define_method("pixels=", set_pixels);
+ cBitmap.define_method("pixels", get_pixels);
cBitmap.define_method("[]=", set_at);
cBitmap.define_method("[]", get_at);
}