diff options
Diffstat (limited to 'kms++util/src/drawing.cpp')
-rw-r--r-- | kms++util/src/drawing.cpp | 318 |
1 files changed, 262 insertions, 56 deletions
diff --git a/kms++util/src/drawing.cpp b/kms++util/src/drawing.cpp index 194daf8..79e0d90 100644 --- a/kms++util/src/drawing.cpp +++ b/kms++util/src/drawing.cpp @@ -15,98 +15,91 @@ void draw_rgb_pixel(IFramebuffer& buf, unsigned x, unsigned y, RGB color) switch (buf.format()) { case PixelFormat::XRGB8888: - case PixelFormat::ARGB8888: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::ARGB8888: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.argb8888(); break; } case PixelFormat::XBGR8888: - case PixelFormat::ABGR8888: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::ABGR8888: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.abgr8888(); break; } case PixelFormat::RGBX8888: - case PixelFormat::RGBA8888: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::RGBA8888: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.rgba8888(); break; } case PixelFormat::BGRX8888: - case PixelFormat::BGRA8888: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::BGRA8888: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.bgra8888(); break; } case PixelFormat::XRGB2101010: - case PixelFormat::ARGB2101010: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::ARGB2101010: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.argb2101010(); break; } case PixelFormat::XBGR2101010: - case PixelFormat::ABGR2101010: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::ABGR2101010: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.abgr2101010(); break; } case PixelFormat::RGBX1010102: - case PixelFormat::RGBA1010102: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::RGBA1010102: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.rgba1010102(); break; } case PixelFormat::BGRX1010102: - case PixelFormat::BGRA1010102: - { - uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); + case PixelFormat::BGRA1010102: { + uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.bgra1010102(); break; } - case PixelFormat::RGB888: - { - uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3; + case PixelFormat::RGB888: { + uint8_t* p = buf.map(0) + buf.stride(0) * y + x * 3; p[0] = color.b; p[1] = color.g; p[2] = color.r; break; } - case PixelFormat::BGR888: - { - uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3; + case PixelFormat::BGR888: { + uint8_t* p = buf.map(0) + buf.stride(0) * y + x * 3; p[0] = color.r; p[1] = color.g; p[2] = color.b; break; } - case PixelFormat::RGB565: - { - uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); + case PixelFormat::RGB332: { + uint8_t* p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x); + *p = color.rgb332(); + break; + } + case PixelFormat::RGB565: { + uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); *p = color.rgb565(); break; } - case PixelFormat::BGR565: - { - uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); + case PixelFormat::BGR565: { + uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); *p = color.bgr565(); break; } - case PixelFormat::ARGB4444: - { - uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); + case PixelFormat::XRGB4444: + case PixelFormat::ARGB4444: { + uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); *p = color.argb4444(); break; } - case PixelFormat::ARGB1555: - { - uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); + case PixelFormat::XRGB1555: + case PixelFormat::ARGB1555: { + uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); *p = color.argb1555(); break; } @@ -115,14 +108,37 @@ void draw_rgb_pixel(IFramebuffer& buf, unsigned x, unsigned y, RGB color) } } -void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2) +void draw_yuv444_pixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv) { - if ((x + 1) >= buf.width() || y >= buf.height()) + if (x >= buf.width() || y >= buf.height()) throw runtime_error("attempt to draw outside the buffer"); - ASSERT((x & 1) == 0); + uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x); + uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x); + uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * y + x); + + switch (buf.format()) { + case PixelFormat::YUV444: + py[0] = yuv.y; + pu[0] = yuv.u; + pv[0] = yuv.v; + break; + + case PixelFormat::YVU444: + py[0] = yuv.y; + pu[0] = yuv.v; + pv[0] = yuv.u; + break; - uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2); + default: + throw std::invalid_argument("invalid pixelformat"); + } +} + +static void draw_yuv422_packed_macropixel(IFramebuffer& buf, unsigned x, unsigned y, + YUV yuv1, YUV yuv2) +{ + uint8_t* p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2); uint8_t y0 = yuv1.y; uint8_t y1 = yuv2.y; @@ -163,19 +179,106 @@ void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, } } -void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y, - YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4) +static void draw_yuv422_semiplanar_macropixel(IFramebuffer& buf, unsigned x, unsigned y, + YUV yuv1, YUV yuv2) { - if ((x + 1) >= buf.width() || (y + 1) >= buf.height()) + uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x); + uint8_t* puv = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x); + + uint8_t y0 = yuv1.y; + uint8_t y1 = yuv2.y; + uint8_t u = (yuv1.u + yuv2.u) / 2; + uint8_t v = (yuv1.v + yuv2.v) / 2; + + switch (buf.format()) { + case PixelFormat::NV16: + py[0] = y0; + py[1] = y1; + puv[0] = u; + puv[1] = v; + break; + + case PixelFormat::NV61: + py[0] = y0; + py[1] = y1; + puv[0] = v; + puv[1] = u; + break; + + default: + throw std::invalid_argument("invalid pixelformat"); + } +} + +static void draw_yuv422_planar_macropixel(IFramebuffer& buf, unsigned x, unsigned y, + YUV yuv1, YUV yuv2) +{ + uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x); + uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x / 2); + uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * y + x / 2); + + uint8_t y0 = yuv1.y; + uint8_t y1 = yuv2.y; + uint8_t u = (yuv1.u + yuv2.u) / 2; + uint8_t v = (yuv1.v + yuv2.v) / 2; + + switch (buf.format()) { + case PixelFormat::YUV422: + py[0] = y0; + py[1] = y1; + pu[0] = u; + pv[0] = v; + break; + + case PixelFormat::YVU422: + py[0] = y0; + py[1] = y1; + pu[0] = v; + pv[0] = u; + break; + + default: + throw std::invalid_argument("invalid pixelformat"); + } +} + +void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2) +{ + if ((x + 1) >= buf.width() || y >= buf.height()) throw runtime_error("attempt to draw outside the buffer"); ASSERT((x & 1) == 0); - ASSERT((y & 1) == 0); - uint8_t *py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x); - uint8_t *py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x); + switch (buf.format()) { + case PixelFormat::UYVY: + case PixelFormat::YUYV: + case PixelFormat::YVYU: + case PixelFormat::VYUY: + draw_yuv422_packed_macropixel(buf, x, y, yuv1, yuv2); + break; + + case PixelFormat::NV16: + case PixelFormat::NV61: + draw_yuv422_semiplanar_macropixel(buf, x, y, yuv1, yuv2); + break; + + case PixelFormat::YUV422: + case PixelFormat::YVU422: + draw_yuv422_planar_macropixel(buf, x, y, yuv1, yuv2); + break; + + default: + throw std::invalid_argument("invalid pixelformat"); + } +} - uint8_t *puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x); +static void draw_yuv420_semiplanar_macropixel(IFramebuffer& buf, unsigned x, unsigned y, + YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4) +{ + uint8_t* py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x); + uint8_t* py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x); + + uint8_t* puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x); uint8_t y0 = yuv1.y; uint8_t y1 = yuv2.y; @@ -208,7 +311,72 @@ void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y, } } -void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color) +static void draw_yuv420_planar_macropixel(IFramebuffer& buf, unsigned x, unsigned y, + YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4) +{ + uint8_t* py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x); + uint8_t* py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x); + + uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x / 2); + uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * (y / 2) + x / 2); + + uint8_t y0 = yuv1.y; + uint8_t y1 = yuv2.y; + uint8_t y2 = yuv3.y; + uint8_t y3 = yuv4.y; + uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4; + uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4; + + switch (buf.format()) { + case PixelFormat::YUV420: + py1[0] = y0; + py1[1] = y1; + py2[0] = y2; + py2[1] = y3; + pu[0] = u; + pv[0] = v; + break; + + case PixelFormat::YVU420: + py1[0] = y0; + py1[1] = y1; + py2[0] = y2; + py2[1] = y3; + pu[0] = v; + pv[0] = u; + break; + + default: + throw std::invalid_argument("invalid pixelformat"); + } +} + +void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y, + YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4) +{ + if ((x + 1) >= buf.width() || (y + 1) >= buf.height()) + throw runtime_error("attempt to draw outside the buffer"); + + ASSERT((x & 1) == 0); + ASSERT((y & 1) == 0); + + switch (buf.format()) { + case PixelFormat::NV12: + case PixelFormat::NV21: + draw_yuv420_semiplanar_macropixel(buf, x, y, yuv1, yuv2, yuv3, yuv4); + break; + + case PixelFormat::YUV420: + case PixelFormat::YVU420: + draw_yuv420_planar_macropixel(buf, x, y, yuv1, yuv2, yuv3, yuv4); + break; + + default: + throw std::invalid_argument("invalid pixelformat"); + } +} + +void draw_rect(IFramebuffer& fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color) { unsigned i, j; YUV yuvcolor = color.yuv(); @@ -222,8 +390,11 @@ void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, case PixelFormat::BGR888: case PixelFormat::RGB565: case PixelFormat::BGR565: + case PixelFormat::XRGB4444: + case PixelFormat::XRGB1555: case PixelFormat::ARGB4444: case PixelFormat::ARGB1555: + case PixelFormat::RGB332: for (j = 0; j < h; j++) { for (i = 0; i < w; i++) { draw_rgb_pixel(fb, x + i, y + j, color); @@ -231,10 +402,23 @@ void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, } break; + case PixelFormat::YUV444: + case PixelFormat::YVU444: + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + draw_yuv444_pixel(fb, x + i, y + j, yuvcolor); + } + } + break; + case PixelFormat::UYVY: case PixelFormat::YUYV: case PixelFormat::YVYU: case PixelFormat::VYUY: + case PixelFormat::NV16: + case PixelFormat::NV61: + case PixelFormat::YUV422: + case PixelFormat::YVU422: for (j = 0; j < h; j++) { for (i = 0; i < w; i += 2) { draw_yuv422_macropixel(fb, x + i, y + j, yuvcolor, yuvcolor); @@ -244,6 +428,8 @@ void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, case PixelFormat::NV12: case PixelFormat::NV21: + case PixelFormat::YUV420: + case PixelFormat::YVU420: for (j = 0; j < h; j += 2) { for (i = 0; i < w; i += 2) { draw_yuv420_macropixel(fb, x + i, y + j, @@ -296,8 +482,11 @@ static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, R case PixelFormat::BGR888: case PixelFormat::RGB565: case PixelFormat::BGR565: + case PixelFormat::XRGB4444: + case PixelFormat::XRGB1555: case PixelFormat::ARGB4444: case PixelFormat::ARGB1555: + case PixelFormat::RGB332: for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { bool b = get_char_pixel(c, x, y); @@ -307,10 +496,25 @@ static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, R } break; + case PixelFormat::YUV444: + case PixelFormat::YVU444: + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + bool b = get_char_pixel(c, x, y); + + draw_yuv444_pixel(buf, xpos + x, ypos + y, b ? yuvcolor : YUV(RGB())); + } + } + break; + case PixelFormat::UYVY: case PixelFormat::YUYV: case PixelFormat::YVYU: case PixelFormat::VYUY: + case PixelFormat::NV16: + case PixelFormat::NV61: + case PixelFormat::YUV422: + case PixelFormat::YVU422: for (y = 0; y < 8; y++) { for (x = 0; x < 8; x += 2) { bool b0 = get_char_pixel(c, x, y); @@ -324,6 +528,8 @@ static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, R case PixelFormat::NV12: case PixelFormat::NV21: + case PixelFormat::YUV420: + case PixelFormat::YVU420: for (y = 0; y < 8; y += 2) { for (x = 0; x < 8; x += 2) { bool b00 = get_char_pixel(c, x, y); @@ -344,8 +550,8 @@ static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, R void draw_text(IFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color) { - for(unsigned i = 0; i < str.size(); i++) + for (unsigned i = 0; i < str.size(); i++) draw_char(buf, (x + 8 * i), y, str[i], color); } -} +} // namespace kms |