Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/d8cc664db15339d09fff25e364454ef6 to your computer and use it in GitHub Desktop.
Save Sup3rc4l1fr4g1l1571c3xp14l1d0c10u5/d8cc664db15339d09fff25e364454ef6 to your computer and use it in GitHub Desktop.
// for For image to be given to FreeH264.
class yuv420_planar {
private:
static void yuv_to_bgr(unsigned char bgr[], const unsigned char y, const unsigned char u, const unsigned char v) {
auto c = static_cast<int>(y) - 16;
auto d = static_cast<int>(u) - 128;
auto e = static_cast<int>(v) - 128;
auto _r = (298 * c + 409 * e + 128) >> 8;
auto _g = (298 * c - 100 * d - 208 * e + 128) >> 8;
auto _b = (298 * c + 516 * d + 128) >> 8;
if (_r < 0) { _r = 0; } else if (_r > 255) { _r = 255; }
if (_g < 0) { _g = 0; } else if (_g > 255) { _g = 255; }
if (_b < 0) { _b = 0; } else if (_b > 255) { _b = 255; }
bgr[0] = static_cast<unsigned char>(_b);
bgr[1] = static_cast<unsigned char>(_g);
bgr[2] = static_cast<unsigned char>(_r);
}
static unsigned char bgr_to_y(const unsigned char b, const unsigned char g, const unsigned char r)
{
return static_cast<unsigned char>((66 * static_cast<short>(r) + 129 * static_cast<short>(g) + 25 * static_cast<short>(b) + 128) >> 8) + 16;
}
static unsigned char bgr_to_u(const unsigned char b, const unsigned char g, const unsigned char r)
{
return static_cast<unsigned char>((-38 * static_cast<short>(r) - 74 * static_cast<short>(g) + 112 * static_cast<short>(b) + 128) >> 8) + 128;
}
static unsigned char bgr_to_v(const unsigned char b, const unsigned char g, const unsigned char r)
{
return static_cast<unsigned char>((112 * static_cast<short>(r) - 94 * static_cast<short>(g) - 18 * static_cast<short>(b) + 128) >> 8) + 128;
}
public:
static int yuv420_to_bgr24(int width, int height, unsigned char * planarYUV[], int strideU, int strideV, unsigned char * bmpBuffer, int bmpStride)
{
auto planarY = planarYUV[0];
auto planarU = planarYUV[1];
auto planarV = planarYUV[2];
auto bmpScaline = bmpBuffer;
for (int _y = 0; _y < height; _y++) {
auto pPixel = bmpScaline;
auto pY = planarY;
auto pU = planarU;
auto pV = planarV;
for (int _x = 0; _x < width; _x += 2) {
yuv_to_bgr(pPixel, *pY++, *pU, *pV);
pPixel += 3;
yuv_to_bgr(pPixel, *pY++, *pU++, *pV++);
pPixel += 3;
}
bmpScaline += bmpStride;
planarY += strideU;
if (_y % 2 == 1) {
planarU += strideV;
planarV += strideV;
}
}
return 0;
}
public:
static int bgr32_to_yuv420(
unsigned char * yuvBuffer,
const int width,
const int height,
const unsigned char * bgrBuffer,
bool isOddFrame)
{
auto planarU = yuvBuffer + width * height;
auto planarV = planarU + ((width * height) / 4);
for (auto i = 0; i < height / 2; ++i) {
auto bgrScanLineEven = bgrBuffer;
auto bgrScanLineOdd = bgrBuffer + width * 4;
auto planarYeven = yuvBuffer;
auto planarYodd = yuvBuffer + width;
short r, g, b;
for (auto j = 0; j < width / 2; ++j) {
b = *bgrScanLineEven++;
g = *bgrScanLineEven++;
r = *bgrScanLineEven++;
++bgrScanLineEven; // skip alpha
*planarYeven++ = bgr_to_y(b, g, r);
if (!isOddFrame)
{
*planarU++ = bgr_to_u(b, g, r);
}
b = *bgrScanLineEven++;
g = *bgrScanLineEven++;
r = *bgrScanLineEven++;
++bgrScanLineEven; // skip alpha
*planarYeven++ = bgr_to_y(b, g, r);
if (isOddFrame)
{
*planarU++ = bgr_to_u(b, g, r);
}
b = *bgrScanLineOdd++;
g = *bgrScanLineOdd++;
r = *bgrScanLineOdd++;
++bgrScanLineOdd; // skip alpha
*planarYodd++ = bgr_to_y(b, g, r);
if (!isOddFrame)
{
*planarV++ = bgr_to_v(b, g, r);
}
b = *bgrScanLineOdd++;
g = *bgrScanLineOdd++;
r = *bgrScanLineOdd++;
++bgrScanLineOdd; // skip alpha
*planarYodd++ = bgr_to_y(b, g, r);
if (isOddFrame)
{
*planarV++ = bgr_to_v(b, g, r);
}
}
yuvBuffer += width * 2;
bgrBuffer += width * 4 * 2;
}
return 0;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment