#ifndef __COLORTRANSFORM_H__
#define __COLORTRANSFORM_H__
#ifdef __cplusplus
extern "C" {
#endif
#define PERROR 1
#define IMAGE_MAX_WIDTH (4*1024)
#define IMAGE_MAX_HEIGHT (4*1024)
#define MAX_FILE_NAME_LENGTH 256
#define LOGP printf("FUNCTION:%s,LINE:%d\n",__FUNCTION__,__LINE__);
#define LINE_BYTES(Width) (((long)(Width) * 8 + 31) / 32 * 4)
typedef unsigned char COLOR_BYTE;
typedef unsigned short COLOR_WORD;
typedef unsigned int COLOR_DWORD;
typedef long COLOR_LONG;
//Definition of bitmap header, in which file type info is not included as
//it is determined by the memory layout of bitmap header.
//If added,file info may be wrongly readed.
typedef struct __tag_BIT_MAP_FILE_HEADER{
// COLOR_WORD wType;//file type,must be0x424D(BM)
COLOR_DWORD dwSize;//file size
COLOR_WORD wReserved1;//reserved word
COLOR_WORD wReserved2;//reserved word
COLOR_DWORD dwOffBits;//offsets from header of file
}BITMAPFILEHEADER, *LPBITMAPFILEHEADER;
typedef struct __tag_BIT_MAP_INFO_HEADER{
COLOR_DWORD dwSize;//size of info header
COLOR_LONG lWidth;//width of image
COLOR_LONG lHeight;//height of image
COLOR_WORD wPlanes;//count of bit plane,must be 1
COLOR_WORD wBitCount;//bits for every pix
COLOR_DWORD dwCompression; //compression type
COLOR_DWORD dwSizeImage; //size in byte of compressed file
COLOR_LONG lXPelsPerMeter; //horizontal resolution
COLOR_LONG lYPelsPerMeter; //vertical resolution
COLOR_DWORD dwClrUsed; //count of color actually used by bitmap
COLOR_DWORD dwClrImportant; //count of important color in bitmap
}BITMAPINFOHEADER, *LPBITMAPINFOHEADER; //definition of bitmap info header
typedef struct __tag_RGB_QUAD{
COLOR_BYTE byRGBBlue; //blue component of the color
COLOR_BYTE byRGBGreen; //green component of the color
COLOR_BYTE byRGBRed; //red component of the color
COLOR_BYTE byRGBReserved; //reserverd value
}RGBQUAD, *LPRGBQUAD;//definition of palette
typedef struct __tag_IMAGE_DATA
{
COLOR_BYTE byBlue;
COLOR_BYTE byGreen;
COLOR_BYTE byRed;
}IMAGEDATA, *LPIMAGEDATA;//pixel information
MRESULT SaveBMPFromYUV(const char* pFilePath, const char *pFileName, const MUInt8 * pSource, int iWidth, int iHeight);
MRESULT ReadYUVFromBMP(const char* pFilePath, const char *pFileName, MUInt8 **ppDest, long *pWidth, long *pHeight);
MRESULT ConvertYuv420pToNV21(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight);
MRESULT ConvertYuv420pToNV12(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight);
MRESULT ConvertYuv420pToYUYV(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight);
MRESULT ConvertYuv420pToI422H(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight);
MRESULT ConvertYuv420pToLPI422H(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight);
#ifdef __cplusplus
}
#endif
#endif //__COLORTRANSFORM_H__
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include "turbojpeg.h"
#include "ColorTransform.h"
MRESULT SaveBMPFromYUV(const char* pFilePath, const char *pFileName, const MUInt8 * pSource, int iWidth, int iHeight)
{
if (NULL == pFilePath || NULL == pFileName || NULL == pSource)
{
return PERROR;
}
if (iWidth <= 0 || iHeight <= 0)
{
return PERROR;
}
MRESULT res = MOK;
const COLOR_WORD wType = 0x4d42;
BITMAPFILEHEADER strHead; //head of bitmap
BITMAPINFOHEADER strInfo; //info head of bitmap
IMAGEDATA *pBMPImageData = NULL; //store pixel info of bitmap
FILE *pFileOut = NULL;
memset(&strHead, 0, sizeof(BITMAPFILEHEADER));
memset(&strInfo, 0, sizeof(BITMAPINFOHEADER));
pBMPImageData = (IMAGEDATA*)malloc(iWidth * iHeight * sizeof(IMAGEDATA));
if (NULL == pBMPImageData)
{
printf("failed to allocate %d size of memory for pBMPImageData\n", iWidth * iHeight * sizeof(IMAGEDATA));
res = PERROR;
goto __EXIT;
}
memset(pBMPImageData, 0, iWidth * iHeight * sizeof(IMAGEDATA));
int y;
int r, g, b;
int i, j;
for(i = 0; i < iHeight; i++)
{
for(j = 0; j < iWidth; j++)
{
y = pSource[j + i * iWidth];
/*
yuv<-->rgb
Y'= 0.299*R' + 0.587*G' + 0.114*B'
U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')
V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')
R' = Y' + 1.140*V'
G' = Y' - 0.394*U' - 0.581*V'
B' = Y' + 2.032*U'
yCbCr<-->rgb
Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16
Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128
R' = 1.164*(Y’-16) + 1.596*(Cr'-128)
G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)
B' = 1.164*(Y’-16) + 2.017*(Cb'-128)*/
r = y;
g = y;
b = y;
r = r > 255 ? 255 : r;
g = g > 255 ? 255 : g;
b = b > 255 ? 255 : b;
r = r < 0 ? 0 : r;
g = g < 0 ? 0 : g;
b = b < 0 ? 0 : b;
(*(pBMPImageData + i * iWidth + j)).byBlue = (COLOR_BYTE)b;
(*(pBMPImageData + i * iWidth + j)).byGreen = (COLOR_BYTE)g;
(*(pBMPImageData + i * iWidth + j)).byRed = (COLOR_BYTE)r;
}
}
///save BMP image
char arrFilePathName[MAX_FILE_NAME_LENGTH];
strcpy(arrFilePathName, pFilePath);
strcat(arrFilePathName, pFileName);
sprintf(arrFilePathName, "%s_%dX%d%s" , arrFilePathName, iWidth, iHeight, ".bmp");
if(NULL == (pFileOut = fopen(arrFilePathName, "wb")))
{
printf("create the bmp file:%s failed!\n", arrFilePathName);
res = PERROR;
goto __EXIT;
}
printf("Save bmp file:%s\n", arrFilePathName);
fwrite(&wType, 1, sizeof(COLOR_WORD), pFileOut);
strHead.dwSize = iWidth * iHeight * 3 + 54; //size of bitmap in byte
strHead.wReserved2 = 0;
strHead.dwOffBits = 54; //actual offsets from the header in byte(14 + 40),no palette
fwrite(&strHead, 1, sizeof(BITMAPFILEHEADER), pFileOut);
strInfo.lWidth = iWidth;
strInfo.lHeight = iHeight;
strInfo.wBitCount = 24; //specify the count of bits used in rendering colors,common value are:1(Black and white two-color image), 4(16-color image), 8(256-color image), 24(true-color image)
strInfo.dwClrImportant = 0; //specify the count of important colors,all colors are identified to be important if it is zero.
strInfo.dwClrUsed = 0; //specify the count of colors actually used in image.If it is 0,count of colors used is identified as 2*2*....*2(total count of wBitCount)
strInfo.dwCompression = 0; //specify if the image is compressed
strInfo.wPlanes = 1; ///count of planes and must be 1
strInfo.dwSize = 40; ///length of struct and must be 40
strInfo.dwSizeImage = 3 * iWidth * iHeight;
fwrite(&strInfo, 1, sizeof(BITMAPINFOHEADER), pFileOut);
//save pixel data
for(i = iHeight - 1; i >= 0; --i) //from top the bottom
{
for(j = 0; j < iWidth; ++j)
//for(int j = iWidth;j > 0;--j)
{
fwrite( &((*(pBMPImageData + i * iWidth + j)).byBlue), 1, sizeof(COLOR_BYTE), pFileOut);
fwrite( &((*(pBMPImageData + i * iWidth + j)).byGreen), 1, sizeof(COLOR_BYTE), pFileOut);
fwrite( &((*(pBMPImageData + i * iWidth + j)).byRed), 1, sizeof(COLOR_BYTE), pFileOut);
}
}
__EXIT:
if (pFileOut != NULL)
{
fclose(pFileOut);
pFileOut = NULL;
}
if (pBMPImageData != NULL)
{
free(pBMPImageData);
pBMPImageData = NULL;
}
return res;
}
MRESULT ReadYUVFromBMP(const char* pFilePath, const char *pFileName, MUInt8 **ppDest, long *pWidth, long *pHeight)
{
if (NULL == pFilePath || NULL == pFileName || NULL == ppDest || NULL == pWidth || NULL == pHeight)
{
printf("parameters invalid\n");
return PERROR;
}
MRESULT res = MOK;
MUInt8 *pData = NULL;
FILE *pFile = NULL;
char arrFileNameFull[MAX_FILE_NAME_LENGTH]; //file name
size_t lReadSize = 0; //return value of fread
size_t lWantReadSize = 0; //acutal value want to read
size_t lActualFileSize = 0; //actula file size in byte
COLOR_DWORD dwFileSize = 0; //file size got from file head
COLOR_DWORD dwOffset = 0; // offset of rgb data from header of file
int iHeight = 0; // height of bmp file
int iWidth = 0; // width of bmp file
MUInt8 * pRGBDataLine = NULL;
sprintf(arrFileNameFull, "%s%s", pFilePath, pFileName);
printf("mask bmp file is:%s\n", arrFileNameFull);
pFile = fopen(arrFileNameFull, "rb");
if (NULL == pFile)
{
printf("can not open file %s\n", arrFileNameFull);
res = PERROR;
goto __EXIT;
}
pData = malloc(sizeof(MUInt8) * (sizeof(BITMAPFILEHEADER) > sizeof(BITMAPINFOHEADER) ? sizeof(BITMAPFILEHEADER) : sizeof(BITMAPINFOHEADER)));
if (NULL == pData)
{
res = PERROR;
goto __EXIT;
}
// get file size in byte
fseek(pFile, 0L, SEEK_END);
lActualFileSize = ftell(pFile);
fseek(pFile, 0L, SEEK_SET);
//check file type
lWantReadSize = 2;
lReadSize = fread(pData, 1, lWantReadSize, pFile);
if (lReadSize != lWantReadSize)
{
printf("fread from %s failed and return %u\n", arrFileNameFull, lReadSize);
res = PERROR;
goto __EXIT;
}
if (pData[0] != 0x42 || pData[1] != 0x4d)
{
printf("file type is:%0x%0x,not a bmp file\n", pData[1], pData[0]);
res = PERROR;
goto __EXIT;
}
// get file size from file head
lWantReadSize = sizeof(BITMAPFILEHEADER);
lReadSize = fread(pData, 1, lWantReadSize, pFile);
if (lReadSize != lWantReadSize)
{
printf("read head from %s failed and return %u\n", arrFileNameFull, lReadSize);
res = PERROR;
goto __EXIT;
}
dwFileSize =
(((COLOR_DWORD)pData[3]) << 24) |
(((COLOR_DWORD)pData[2]) << 16) |
(((COLOR_DWORD)pData[1]) << 8) |
(((COLOR_DWORD)pData[0]) << 0);
if ( dwFileSize != lActualFileSize)
{
printf("file is broken,size in head:%u,actual size:%u\n", dwFileSize, lActualFileSize);
res = PERROR;
goto __EXIT;
}
// get rgb offset from file head
dwOffset =
(((COLOR_DWORD)pData[11]) << 24) |
(((COLOR_DWORD)pData[10]) << 16) |
(((COLOR_DWORD)pData[9]) << 8) |
(((COLOR_DWORD)pData[8]) << 0);
// get info head
lWantReadSize = sizeof(BITMAPINFOHEADER);
lReadSize = fread(pData, 1, lWantReadSize, pFile);
if (lReadSize != lWantReadSize)
{
printf("read info head from %s failed and return %u\n", arrFileNameFull, lReadSize);
res = PERROR;
goto __EXIT;
}
iWidth =
(((COLOR_LONG)pData[7]) << 24) |
(((COLOR_LONG)pData[6]) << 16) |
(((COLOR_LONG)pData[5]) << 8) |
(((COLOR_LONG)pData[4]) << 0) ;
iHeight =
(((COLOR_LONG)pData[11]) << 24) |
(((COLOR_LONG)pData[10]) << 16) |
(((COLOR_LONG)pData[9]) << 8) |
(((COLOR_LONG)pData[8]) << 0) ;
*pWidth = iWidth;
*pHeight = iHeight;
// read RGB data and trasform it into YUV Grey format
*ppDest = (MUInt8 *)malloc(sizeof(MUInt8) * iWidth * iHeight * 2);
if (NULL == *ppDest)
{
printf("failed to malloc size of %ld memory for *ppDest\n", (long)(sizeof(MUInt8) * (*pWidth) * (*pHeight)));
res = PERROR;
goto __EXIT;
}
fseek(pFile, dwOffset, SEEK_SET);
int iChannel = 3;
int iStep = iChannel * iWidth;
int iOffSet = iStep % 4;
int i, j;
if (iOffSet != 0)
{
iOffSet = 4 - iOffSet;
}
pRGBDataLine = (MUInt8 *) malloc(sizeof(MUInt8) * (iStep + iOffSet));
if (NULL == pRGBDataLine)
{
printf("failed to allocate size of %d memory for pRGBDataLine\n", sizeof(MUInt8) * (iStep + iOffSet));
res = PERROR;
goto __EXIT;
}
for (i = 0; i < iHeight; i++)
{
fread(pRGBDataLine, 1, iStep + iOffSet, pFile);
for (j = 0; j < iWidth; j++)
{
//if (pRGBDataLine[j * iChannel] != 0 && pRGBDataLine[j * iChannel] != 255)
if (255 == pRGBDataLine[j * iChannel])
{
(*ppDest)[(iHeight - 1 - i) * iWidth + j] = 0;
}
else if (0 == pRGBDataLine[j * iChannel])
{
(*ppDest)[(iHeight - 1 - i) * iWidth + j] = 255;
}
else
{
//printf("pRGBDataLine[%d]:%d invalid\n", j * iChannel, pRGBDataLine[j * iChannel]);
(*ppDest)[(iHeight - 1 - i) * iWidth + j] = 255;
}
}
}
__EXIT:
if (pRGBDataLine != NULL)
{
free(pRGBDataLine);
pRGBDataLine = NULL;
}
if (pFile != NULL)
{
fclose(pFile);
pFile = NULL;
}
if (pData != NULL)
{
free(pData);
pData = NULL;
}
return res;
}
MRESULT ConvertYuv420pToNV21(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight)
{
if (NULL == pDest || NULL == pSource)
{
return PERROR;
}
if (iWidth <= 0 || iHeight <= 0)
{
return PERROR;
}
int iArea = iHeight * iWidth;
int iSqarea = iArea >> 3;
int iQarea = iArea >> 2;
int iCount = iSqarea;
const unsigned short * pU = (const unsigned short *) (pSource + iArea);
const unsigned short * pV = (const unsigned short *) (pSource + iArea + iQarea);
unsigned int * pUV = (unsigned int *)(pDest + iArea);
memcpy(pDest, pSource, iArea);
do
{
unsigned int uiU = *pU++;
unsigned int uiV = *pV++;
*pUV++ = ( ( (uiU & 0x00FF) << 8 ) |
( (uiU & 0xFF00) << 16) |
( (uiV & 0x00FF) ) |
( (uiV & 0xFF00) << 8) );
}
while (--iCount);
return MOK;
}
MRESULT ConvertYuv420pToNV12(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight)
{
if (NULL == pDest || NULL == pSource)
{
return PERROR;
}
if (iWidth <= 0 || iHeight <= 0)
{
return PERROR;
}
int iArea = iHeight * iWidth;
int iSqarea = iArea >> 3;
int iQarea = iArea >> 2;
int iCount = iSqarea;
const unsigned short * pU = (const unsigned short *) (pSource + iArea);
const unsigned short * pV = (const unsigned short *) (pSource + iArea + iQarea);
unsigned int * pUV = (unsigned int *)(pDest + iArea);
memcpy(pDest, pSource, iArea);
do
{
unsigned int uiU = *pU++;
unsigned int uiV = *pV++;
*pUV++ = ( ( (uiV & 0x00FF) << 8 ) |
( (uiV & 0xFF00) << 16) |
( (uiU & 0x00FF) ) |
( (uiU & 0xFF00) << 8) );
}
while (--iCount);
return MOK;
}
MRESULT ConvertYuv420pToYUYV(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight)
{
if (NULL == pDest || NULL == pSource)
{
return PERROR;
}
if (iWidth <= 0 || iHeight <= 0)
{
return PERROR;
}
int iStride = iWidth * iHeight;
unsigned int x, y;
for (y = 0; y < iHeight; ++y)
{
const MUInt8 *pY = pSource + y * iWidth;
const MUInt8 *pU = pSource + iStride + (y / 2) * (iWidth / 2);
const MUInt8 *pV = pSource + (iStride * 5) / 4 + (y / 2) * (iWidth / 2);
for (x = 0; x < iWidth; x += 2)
{
*(pDest + 0) = pY[0];
*(pDest + 1) = pU[0];
*(pDest + 2) = pY[1];
*(pDest + 3) = pV[0];
pDest += 4;
pY += 2;
++pU;
++pV;
}
}
return MOK;
}
MRESULT ConvertYuv420pToI422H(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight)
{
if (NULL == pDest || NULL == pSource)
{
return PERROR;
}
if (iWidth <= 0 || iHeight <= 0)
{
return PERROR;
}
int iStride = iWidth * iHeight;
unsigned int x, y;
MUInt8 * pDestU = pDest + iStride;
MUInt8 * pDestV = pDestU + iStride / 2;
memcpy(pDest, pSource, iStride);
for (y = 0; y < iHeight; ++y)
{
const MUInt8 *pU = pSource + iStride + (y / 2) * (iWidth / 2);
const MUInt8 *pV = pSource + (iStride * 5) / 4 + (y / 2) * (iWidth / 2);
for (x = 0; x < iWidth; x += 2)
{
*pDestU++ = *pU++;
*pDestV++ = *pV++;
}
}
return MOK;
}
MRESULT ConvertYuv420pToLPI422H(MUInt8 * pDest, const MUInt8 * pSource, int iWidth, int iHeight)
{
if (NULL == pDest || NULL == pSource)
{
return PERROR;
}
if (iWidth <= 0 || iHeight <= 0)
{
return PERROR;
}
int iStride = iWidth * iHeight;
unsigned int x, y;
MUInt8 * pDestUV = pDest + iStride;
memcpy(pDest, pSource, iStride);
for (y = 0; y < iHeight; ++y)
{
const MUInt8 *pU = pSource + iStride + (y / 2) * (iWidth / 2);
const MUInt8 *pV = pSource + (iStride * 5) / 4 + (y / 2) * (iWidth / 2);
for (x = 0; x < iWidth; x += 2)
{
*pDestUV++ = *pU++;
*pDestUV++ = *pV++;
}
}
return MOK;
}
//conver yuv422 to yuv420
int i;
for(i = 0; i < iHeight / 2; i++)
{
memcpy(*ppImgData + iStride + i * iWidth / 2, pYuvRaw + iStride + i * iWidth, iWidth / 2);
memcpy(*ppImgData + iStride * 5 / 4 + i * iWidth / 2, pYuvRaw + iStride * 3 / 2 + i * iWidth, iWidth / 2);
}
YUV格式互转
最新推荐文章于 2021-05-14 17:34:03 发布