Picture *Picture::yuv8_to_uyvy8(void) { int i, j; uint16_t u, v; uint8_t y1, y2; Picture *out = Picture::alloc(this->w, this->h, 2*this->w, UYVY8); uint8_t *in_ptr, *out_ptr; for (i = 0; i < this->h; i++) { in_ptr = this->scanline(i); out_ptr = out->scanline(i); for (j = 0; j < this->w; j += 2) { y1 = *in_ptr++; u = *in_ptr++; v = *in_ptr++; y2 = *in_ptr++; u += *in_ptr++; v += *in_ptr++; u /= 2; v /= 2; *out_ptr++ = u; *out_ptr++ = y1; *out_ptr++ = v; *out_ptr++ = y2; } } return out; }
Picture *Picture::from_png(const char *filename) { cairo_surface_t *pngs = cairo_image_surface_create_from_png(filename); if (cairo_surface_status(pngs) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy(pngs); throw std::runtime_error("Failed to load PNG to Cairo surface"); } cairo_format_t nf = cairo_image_surface_get_format(pngs); if (nf != CAIRO_FORMAT_ARGB32 && nf != CAIRO_FORMAT_RGB24) { cairo_surface_destroy(pngs); throw std::runtime_error("PNG uses unsupported pixel format"); } Picture *ret = Picture::alloc( cairo_image_surface_get_width(pngs), cairo_image_surface_get_height(pngs), 4*cairo_image_surface_get_width(pngs), BGRA8 ); int xcopy = 4*ret->w; int stride = cairo_image_surface_get_stride(pngs); uint8_t *data = (uint8_t *)cairo_image_surface_get_data(pngs); /* copy data */ for (int ycopy = 0; ycopy < ret->h; ++ycopy) { memcpy(ret->scanline(ycopy), data + stride * ycopy, xcopy); } cairo_surface_destroy(pngs); return ret; }
Picture *Picture::uyvy8_to_yuv8(void) { int i, j; uint8_t u, y1, v, y2; Picture *out = Picture::alloc(this->w, this->h, 3*this->w, YUV8); uint8_t *in_ptr, *out_ptr; for (i = 0; i < this->h; i++) { in_ptr = this->scanline(i); out_ptr = out->scanline(i); for (j = 0; j < this->w; j+=2) { u = *in_ptr++; y1 = *in_ptr++; v = *in_ptr++; y2 = *in_ptr++; *out_ptr++ = y1; *out_ptr++ = u; *out_ptr++ = v; *out_ptr++ = y2; *out_ptr++ = u; *out_ptr++ = v; } } return out; }
Picture *Picture::bgra8_to_yuva8(void) { int i, j; uint8_t r, g, b, a; uint16_t y, u, v; Picture *out = Picture::alloc(this->w, this->h, 4*this->w, YUVA8); uint8_t *pix_ptr, *out_ptr; for (i = 0; i < this->h; i++) { pix_ptr = this->scanline(i); out_ptr = out->scanline(i); for (j = 0; j < this->w; j++) { b = *pix_ptr++; g = *pix_ptr++; r = *pix_ptr++; a = *pix_ptr++; y = 16 + (r * 66 + g * 129 + b * 25) / 256; u = 128 + (b * 112 - g * 74 - r * 37) / 256; v = 128 + (r * 112 - g * 94 - b * 18) / 256; *out_ptr++ = y; *out_ptr++ = u; *out_ptr++ = v; *out_ptr++ = a; } } return out; }
Picture *Picture::bgra8_to_rgb8(void) { int i, j; uint8_t r, g, b, a; Picture *out = Picture::alloc(this->w, this->h, 3*this->w, RGB8); uint8_t *pix_ptr, *out_ptr; for (i = 0; i < this->h; i++) { pix_ptr = this->scanline(i); out_ptr = out->scanline(i); for (j = 0; j < this->w; j++) { b = *pix_ptr++; g = *pix_ptr++; r = *pix_ptr++; a = *pix_ptr++; *out_ptr++ = r; *out_ptr++ = g; *out_ptr++ = b; } } return out; }
Picture *Picture::rgb8_to_uyvy8(void) { int i, j; uint8_t r, g, b; uint16_t y1, y2, u, v; /* UYVY8 = 4 bytes/2 pixels (w must be even) */ assert(this->w % 2 == 0); Picture *out = Picture::alloc(this->w, this->h, 2*this->w, UYVY8); uint8_t *pix_ptr, *out_ptr; for (i = 0; i < this->h; i++) { pix_ptr = this->scanline(i); out_ptr = out->scanline(i); for (j = 0; j < this->w; j += 2) { r = *pix_ptr++; g = *pix_ptr++; b = *pix_ptr++; y1 = 16 + (r * 66 + g * 129 + b * 25) / 256; u = 128 + (b * 112 - g * 74 - r * 37) / 256; v = 128 + (r * 112 - g * 94 - b * 18) / 256; r = *pix_ptr++; g = *pix_ptr++; b = *pix_ptr++; y2 = 16 + (r * 66 + g * 129 + b * 25) / 256; u += 128 + (b * 112 - g * 74 - r * 37) / 256; v += 128 + (r * 112 - g * 94 - b * 18) / 256; u >>= 1; v >>= 1; *out_ptr++ = u; *out_ptr++ = y1; *out_ptr++ = v; *out_ptr++ = y2; } } return out; }
/* (maybe not anymore??) */ Picture *Picture::uyvy8_to_rgb8(void) { int i, j; int16_t r, g, b; uint8_t u, y1, v, y2; Picture *out = Picture::alloc(this->w, this->h, 3*this->w, RGB8); uint8_t *in_ptr, *out_ptr; for (i = 0; i < this->h; i++) { in_ptr = this->scanline(i); out_ptr = out->scanline(i); for (j = 0; j < this->w; j += 2) { u = *in_ptr++; y1 = *in_ptr++; v = *in_ptr++; y2 = *in_ptr++; r = (298 * y1 + 409 * v) / 256 - 223; g = (298 * y1 - 100 * u - 208 * v) / 256 + 135; b = (298 * y1 + 516 * u) / 256 - 277; *out_ptr++ = SCLAMP(r); *out_ptr++ = SCLAMP(g); *out_ptr++ = SCLAMP(b); r = (298 * y2 + 409 * v) / 256 - 223; g = (298 * y2 - 100 * u - 208 * v) / 256 + 135; b = (298 * y2 + 516 * u) / 256 - 277; *out_ptr++ = SCLAMP(r); *out_ptr++ = SCLAMP(g); *out_ptr++ = SCLAMP(b); } } return out; }