Skip to content

Instantly share code, notes, and snippets.

@EvanLyu732
Created November 1, 2023 08:03
Show Gist options
  • Save EvanLyu732/fcc9d1cfb34a1fab0af64e20c164a042 to your computer and use it in GitHub Desktop.
Save EvanLyu732/fcc9d1cfb34a1fab0af64e20c164a042 to your computer and use it in GitHub Desktop.
yuyv2bgr
#pragam once
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Conversion algorithm from: https://en.wikipedia.org/wiki/YUV
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
constexpr int ConvertYUYV_2_BGR(const int nWidth, const int nHeight,
u_char *pPixSrc, u_char *pPixDst) {
if (nullptr == pPixSrc || nullptr == pPixDst) {
std::cerr << "FAIL: Cannot convert YUYV to BGR from/to NULL pixel buffers"
<< std::endl;
return -1;
}
int nStrideSrc = nWidth * 2;
int nStrideDst = nWidth * 3;
u_char *pSrc = pPixSrc;
u_char *pDst = pPixDst;
int nRow = 0;
int nCol = 0;
int nColDst = 0;
int c = 0;
int d = 0;
int e = 0;
for (nRow = 0; nRow < nHeight; ++nRow) {
for (nCol = 0, nColDst = 0; nCol < nStrideSrc; nCol += 4, nColDst += 6) {
d = (int)pSrc[nCol + 1] - 128; // d = u – 128;
e = (int)pSrc[nCol + 3] - 128; // e = v – 128;
// c = y’ – 16 (for first pixel)
c = 298 * ((int)pSrc[nCol] - 16);
// B – Blue
pDst[nColDst] = (u_char)clamp((c + 516 * d + 128) >> 8, 0, 255);
// G -Green
pDst[nColDst + 1] =
(u_char)clamp((c - 100 * d - 208 * e + 128) >> 8, 0, 255);
// R – Red
pDst[nColDst + 2] = (u_char)clamp((c + 409 * e + 128) >> 8, 0, 255);
// c = y’ – 16 (for second pixel)
c = 298 * ((int)pSrc[nCol + 2] - 16);
// B – Blue
pDst[nColDst + 3] = (u_char)clamp((c + 516 * d + 128) >> 8, 0, 255);
// G -Green
pDst[nColDst + 4] =
(u_char)clamp((c - 100 * d - 208 * e + 128) >> 8, 0, 255);
// R – Red
pDst[nColDst + 5] = (u_char)clamp((c + 409 * e + 128) >> 8, 0, 255);
}
pSrc += nStrideSrc;
pDst += nStrideDst;
}
return 0;
}
@EvanLyu732
Copy link
Author

below is a cuda version

/*
 * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <cuda_runtime.h>
#include "yuv2rgb.cuh"

__device__ inline float clamp(float val, float mn, float mx)
{
	return (val >= mn)? ((val <= mx)? val : mx) : mn;
}

__global__ void gpuConvertYUYVtoBGR_kernel(unsigned char *src, unsigned char *dst,
		unsigned int width, unsigned int height)
{
	int idx = blockIdx.x * blockDim.x + threadIdx.x;
	if (idx*2 >= width) {
		return;
	}

	for (int i = 0; i < height; ++i) {
		int y0 = src[i*width*2+idx*4+0];
		int cb = src[i*width*2+idx*4+1];
		int y1 = src[i*width*2+idx*4+2];
		int cr = src[i*width*2+idx*4+3];

		//r0
		dst[i*width*3+idx*6+2] = clamp(1.164f * (y0 - 16) + 1.596f * (cr - 128)                      , 0.0f, 255.0f);
		//g0
		dst[i*width*3+idx*6+1] = clamp(1.164f * (y0 - 16) - 0.813f * (cr - 128) - 0.391f * (cb - 128), 0.0f, 255.0f);
		//b0
		dst[i*width*3+idx*6+0] = clamp(1.164f * (y0 - 16)                       + 2.018f * (cb - 128), 0.0f, 255.0f);

		//r0
		dst[i*width*3+idx*6+5] = clamp(1.164f * (y1 - 16) + 1.596f * (cr - 128)                      , 0.0f, 255.0f);
		//g1
		dst[i*width*3+idx*6+4] = clamp(1.164f * (y1 - 16) - 0.813f * (cr - 128) - 0.391f * (cb - 128), 0.0f, 255.0f);
		//b1
		dst[i*width*3+idx*6+3] = clamp(1.164f * (y1 - 16)                       + 2.018f * (cb - 128), 0.0f, 255.0f);
	}
}


void gpuConvertYUYVtoBGR(unsigned char *src, unsigned char *dst,
		unsigned int width, unsigned int height)
{
	static unsigned int blockSize = 1024;
	static unsigned int numBlocks = (width / 2 + blockSize - 1) / blockSize;
	gpuConvertYUYVtoBGR_kernel<<<numBlocks, blockSize>>>(src, dst, width, height);
	cudaDeviceSynchronize();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment