code_app/base/HGImage.cpp

2653 lines
63 KiB
C++

#include "HGImage.h"
#include "HGInc.h"
#if defined(HG_CMP_MSC)
#include <combaseapi.h>
#include <gdiplus.h>
#endif
struct HGImageImpl
{
HGImageImpl()
{
#if defined(HG_CMP_MSC)
m_hBmp = NULL;
#endif
m_data = NULL;
m_size = 0;
m_alloc = HGFALSE;
m_width = 0;
m_height = 0;
m_type = 0;
m_widthStep = 0;
m_origin = 0;
m_left = 0;
m_top = 0;
m_right = 0;
m_bottom = 0;
m_xDpi = 96;
m_yDpi = 96;
}
~HGImageImpl()
{
if (m_alloc)
{
free(m_data);
m_data = NULL;
}
#if defined(HG_CMP_MSC)
if (NULL != m_hBmp)
{
DeleteObject(m_hBmp);
m_hBmp = NULL;
}
#endif
}
#if defined(HG_CMP_MSC)
HBITMAP m_hBmp;
#endif
HGByte* m_data;
HGUSize m_size;
HGBool m_alloc;
HGUInt m_width;
HGUInt m_height;
HGUInt m_type;
HGUInt m_widthStep;
HGUInt m_origin;
HGUInt m_left;
HGUInt m_top;
HGUInt m_right;
HGUInt m_bottom;
HGUInt m_xDpi;
HGUInt m_yDpi;
};
#if defined(HG_CMP_MSC)
static HBITMAP CreateHBITMAP(HGUInt width, HGUInt height, HGUInt type, HGUInt origin,
HGUInt xDpi, HGUInt yDpi, HGByte** data)
{
BYTE bmi[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)] = { 0 };
BITMAPINFOHEADER* pbmihdr = (BITMAPINFOHEADER*)bmi;
pbmihdr->biSize = sizeof(BITMAPINFOHEADER);
pbmihdr->biWidth = (LONG)width;
pbmihdr->biHeight = (HGBASE_IMGORIGIN_BOTTOM == origin) ? (LONG)height : -(LONG)height;
pbmihdr->biPlanes = 1;
pbmihdr->biCompression = BI_RGB;
pbmihdr->biXPelsPerMeter = (LONG)(xDpi * 39.37);
pbmihdr->biYPelsPerMeter = (LONG)(yDpi * 39.37);
if (HGBASE_IMGTYPE_BGR == type)
{
pbmihdr->biBitCount = 24;
}
else if (HGBASE_IMGTYPE_BGRA == type)
{
pbmihdr->biBitCount = 32;
}
else if (HGBASE_IMGTYPE_GRAY == type)
{
pbmihdr->biBitCount = 8;
RGBQUAD* clr = (RGBQUAD*)(pbmihdr + 1);
for (int i = 0; i < 256; ++i)
{
clr[i].rgbRed = i;
clr[i].rgbGreen = i;
clr[i].rgbBlue = i;
}
}
else
{
return NULL;
}
void* pBits = NULL;
HBITMAP hBmp = CreateDIBSection(NULL, (BITMAPINFO*)bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
if (NULL == hBmp)
{
return NULL;
}
*data = (HGByte*)pBits;
return hBmp;
}
#endif
HGResult HGAPI HGBase_CreateImage(HGUInt width, HGUInt height, HGUInt type, HGUInt origin, HGImage* image)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
if (0 == width || 0 == height || origin < HGBASE_IMGORIGIN_TOP || origin > HGBASE_IMGORIGIN_BOTTOM)
{
return HGBASE_ERR_INVALIDARG;
}
HGUInt bpp = 0;
if (HGBASE_IMGTYPE_GRAY == type)
bpp = 8;
else if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
bpp = 24;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
bpp = 32;
if (0 == bpp)
{
return HGBASE_ERR_INVALIDARG;
}
// 每行4字节对齐
HGUInt widthStep = ((width * bpp + 31) & ~31) >> 3;
HGUSize size = (HGUSize)widthStep * (HGUSize)height;
HGByte* data = NULL;
HGBool alloc = HGFALSE;
#if defined(HG_CMP_MSC)
HBITMAP hBmp = CreateHBITMAP(width, height, type, origin, 96, 96, &data);
if (NULL == hBmp)
{
data = (HGByte*)malloc(size);
if (NULL == data)
return HGBASE_ERR_OUTOFMEMORY;
else
alloc = HGTRUE;
}
else
{
assert(NULL != data);
}
#else
data = (HGByte*)malloc(size);
if (NULL == data)
return HGBASE_ERR_OUTOFMEMORY;
else
alloc = HGTRUE;
#endif
HGImageImpl* imageImpl = new HGImageImpl;
#if defined(HG_CMP_MSC)
imageImpl->m_hBmp = hBmp;
#endif
imageImpl->m_data = data;
imageImpl->m_size = size;
imageImpl->m_alloc = alloc;
imageImpl->m_width = width;
imageImpl->m_height = height;
imageImpl->m_type = type;
imageImpl->m_widthStep = widthStep;
imageImpl->m_origin = origin;
imageImpl->m_left = 0;
imageImpl->m_top = 0;
imageImpl->m_right = imageImpl->m_width;
imageImpl->m_bottom = imageImpl->m_height;
imageImpl->m_xDpi = 96;
imageImpl->m_yDpi = 96;
*image = (HGImage)imageImpl;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_CreateImageWithData(HGByte* data, const HGImageInfo* info, const HGImageRoi* roi, HGImage* image)
{
if (NULL == data || NULL == info || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
if (0 == info->width || 0 == info->height || info->origin < HGBASE_IMGORIGIN_TOP
|| info->origin > HGBASE_IMGORIGIN_BOTTOM)
{
return HGBASE_ERR_INVALIDARG;
}
HGUInt bpp = 0;
if (HGBASE_IMGTYPE_GRAY == info->type)
bpp = 8;
else if (HGBASE_IMGTYPE_BGR == info->type || HGBASE_IMGTYPE_RGB == info->type)
bpp = 24;
else if (HGBASE_IMGTYPE_BGRA == info->type || HGBASE_IMGTYPE_RGBA == info->type)
bpp = 32;
if (0 == bpp)
{
return HGBASE_ERR_INVALIDARG;
}
// info->widthStep必须合法
HGUInt lineSize = ((info->width * bpp + 7) & ~7) >> 3;
if (info->widthStep < lineSize)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageRoi roi2 = { 0, 0, info->width, info->height };
if (NULL != roi)
{
if (roi->left >= roi->right || roi->top >= roi->bottom
|| roi->right > info->width || roi->bottom > info->height)
{
return HGBASE_ERR_INVALIDARG;
}
memcpy(&roi2, roi, sizeof(HGImageRoi));
}
HGUInt channels = bpp >> 3;
HGByte* data2 = data + roi2.top * info->widthStep + roi2.left * channels;
if (HGBASE_IMGORIGIN_BOTTOM == info->origin)
data2 = data + (info->height - roi2.bottom) * info->widthStep + roi2.left * channels;
HGImageImpl* imageImpl = new HGImageImpl;
#if defined(HG_CMP_MSC)
imageImpl->m_hBmp = NULL;
#endif
imageImpl->m_data = data2;
imageImpl->m_size = (HGUSize)info->widthStep * (HGUSize)(roi2.bottom - roi2.top);
imageImpl->m_alloc = HGFALSE;
imageImpl->m_width = roi2.right - roi2.left;
imageImpl->m_height = roi2.bottom - roi2.top;
imageImpl->m_type = info->type;
imageImpl->m_widthStep = info->widthStep;
imageImpl->m_origin = info->origin;
imageImpl->m_left = 0;
imageImpl->m_top = 0;
imageImpl->m_right = imageImpl->m_width;
imageImpl->m_bottom = imageImpl->m_height;
imageImpl->m_xDpi = 96;
imageImpl->m_yDpi = 96;
*image = (HGImage)imageImpl;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_CreateImageFromData(HGByte* data, const HGImageInfo* info, const HGImageRoi* roi,
HGUInt type, HGUInt origin, HGImage* image)
{
HGImage srcImage = NULL;
HGResult ret = HGBase_CreateImageWithData(data, info, roi, &srcImage);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
ret = HGBase_CloneImage(srcImage, type, origin, image);
HGBase_DestroyImage(srcImage);
return ret;
}
#if defined(HG_CMP_MSC)
static HGUInt GetType(HBITMAP hBmp)
{
assert(NULL != hBmp);
HGUInt type = HGBASE_IMGTYPE_BGR;
BITMAP bm;
GetObject(hBmp, sizeof(BITMAP), &bm);
if (32 == bm.bmBitsPixel)
{
type = HGBASE_IMGTYPE_BGRA;
}
return type;
}
HGResult HGAPI HGBase_CreateImageFromHBITMAP(HBITMAP hBmp, const HGImageRoi* roi,
HGUInt type, HGUInt origin, HGImage* image)
{
if (NULL == hBmp || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
BITMAP bm;
GetObject(hBmp, sizeof(BITMAP), &bm);
HGImageRoi roi2 = { 0, 0, (HGUInt)bm.bmWidth, (HGUInt)bm.bmHeight };
if (NULL != roi)
{
if (roi->left >= roi->right || roi->top >= roi->bottom
|| roi->right > (HGUInt)bm.bmWidth || roi->bottom > (HGUInt)bm.bmHeight)
{
return HGBASE_ERR_INVALIDARG;
}
memcpy(&roi2, roi, sizeof(HGImageRoi));
}
if (0 == type)
{
type = GetType(hBmp);
}
HGResult ret = HGBase_CreateImage(roi2.right - roi2.left, roi2.bottom - roi2.top, type, origin, image);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
HBITMAP hBmp2 = NULL;
HGBase_GetHBITMAPOfImage(*image, &hBmp2);
if (NULL != hBmp2)
{
HDC hMem = CreateCompatibleDC(NULL);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hMem, hBmp);
HDC hMem2 = CreateCompatibleDC(hMem);
HBITMAP hOldBmp2 = (HBITMAP)SelectObject(hMem2, hBmp2);
BitBlt(hMem2, 0, 0, roi2.right - roi2.left, roi2.bottom - roi2.top, hMem, roi2.left, roi2.top, SRCCOPY);
SelectObject(hMem2, hOldBmp2);
DeleteDC(hMem2);
SelectObject(hMem, hOldBmp);
DeleteDC(hMem);
ret = HGBASE_ERR_OK;
}
else
{
HGImage image2 = NULL;
ret = HGBase_CreateImageFromHBITMAP(hBmp, roi, (HGBASE_IMGTYPE_RGBA == type)
? HGBASE_IMGTYPE_BGRA : HGBASE_IMGTYPE_BGR, origin, &image2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(image2, *image);
HGBase_DestroyImage(image2);
}
if (HGBASE_ERR_OK != ret)
HGBase_DestroyImage(*image);
}
return ret;
}
static HGUInt GetType(Gdiplus::Image* pImage)
{
assert(NULL != pImage);
HGUInt type = HGBASE_IMGTYPE_BGR;
Gdiplus::PixelFormat pixFmt = pImage->GetPixelFormat();
if (Gdiplus::IsIndexedPixelFormat(pixFmt))
{
UINT nPaletteSize = pImage->GetPaletteSize();
Gdiplus::ColorPalette* pPalette = (Gdiplus::ColorPalette*)_alloca(nPaletteSize);
pImage->GetPalette(pPalette, nPaletteSize);
UINT bpp = Gdiplus::GetPixelFormatSize(pixFmt);
if (8 == bpp)
{
if (256 == pPalette->Count)
{
BOOL bGray = TRUE;
for (UINT i = 0; i < pPalette->Count; ++i)
{
Gdiplus::ARGB color = pPalette->Entries[i];
BYTE red = (BYTE)((color >> RED_SHIFT) & 0xFF);
BYTE green = (BYTE)((color >> GREEN_SHIFT) & 0xFF);
BYTE blue = (BYTE)((color >> BLUE_SHIFT) & 0xFF);
if (i != red || i != green || i != blue)
{
bGray = FALSE;
break;
}
}
if (bGray)
{
type = HGBASE_IMGTYPE_GRAY;
}
}
}
else if (1 == bpp)
{
if (2 == pPalette->Count)
{
BOOL bBinary = TRUE;
for (UINT i = 0; i < pPalette->Count; ++i)
{
Gdiplus::ARGB color = pPalette->Entries[i];
BYTE red = (BYTE)((color >> RED_SHIFT) & 0xFF);
BYTE green = (BYTE)((color >> GREEN_SHIFT) & 0xFF);
BYTE blue = (BYTE)((color >> BLUE_SHIFT) & 0xFF);
if (i * 255 != red || i * 255 != green || i * 255 != blue)
{
bBinary = FALSE;
break;
}
}
if (bBinary)
{
type = HGBASE_IMGTYPE_GRAY;
}
}
}
}
else if (Gdiplus::IsAlphaPixelFormat(pixFmt))
{
type = HGBASE_IMGTYPE_BGRA;
}
return type;
}
static HGResult Load(Gdiplus::Image* pImage, const HGImageRoi* roi, HGUInt type, HGUInt origin, HGImage* image)
{
assert(NULL != pImage && NULL != image);
HGImageRoi roi2 = { 0, 0, pImage->GetWidth(), pImage->GetHeight() };
if (NULL != roi)
{
if (roi->left >= roi->right || roi->top >= roi->bottom
|| roi->right > pImage->GetWidth() || roi->bottom > pImage->GetHeight())
{
return HGBASE_ERR_INVALIDARG;
}
memcpy(&roi2, roi, sizeof(HGImageRoi));
}
if (0 == type)
{
type = GetType(pImage);
}
HGResult ret = HGBase_CreateImage(roi2.right - roi2.left, roi2.bottom - roi2.top, type, origin, image);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_BGRA == type)
{
HBITMAP hBmp = NULL;
HGBase_GetHBITMAPOfImage(*image, &hBmp);
assert(NULL != hBmp);
HDC hMem = CreateCompatibleDC(NULL);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hMem, hBmp);
Gdiplus::Graphics graphics(hMem);
graphics.DrawImage(pImage, (INT)roi2.left, (INT)roi2.top,
(INT)(roi2.right - roi2.left), (INT)(roi2.bottom - roi2.top));
SelectObject(hMem, hOldBmp);
DeleteDC(hMem);
ret = HGBASE_ERR_OK;
}
else
{
HGImage image2 = NULL;
ret = Load(pImage, roi, (HGBASE_IMGTYPE_RGBA == type)
? HGBASE_IMGTYPE_BGRA : HGBASE_IMGTYPE_BGR, origin, &image2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(image2, *image);
HGBase_DestroyImage(image2);
}
if (HGBASE_ERR_OK != ret)
HGBase_DestroyImage(*image);
}
if (HGBASE_ERR_OK == ret)
HGBase_SetImageDpi(*image, (HGUInt)pImage->GetHorizontalResolution(), (HGUInt)pImage->GetVerticalResolution());
return ret;
}
HGResult HGAPI HGBase_CreateImageFromDIB(HGLOBAL hMem, const HGImageRoi* roi,
HGUInt type, HGUInt origin, HGImage* image)
{
if (NULL == hMem || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGResult ret = HGBASE_ERR_FAIL;
ULONG size = (ULONG)GlobalSize(hMem);
void* pMem = GlobalLock(hMem);
if (NULL != pMem)
{
IStream* pStream = NULL;
HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
if (SUCCEEDED(hr))
{
ULONG writeSize = 0;
BITMAPINFOHEADER* infoHeader = (BITMAPINFOHEADER*)pMem;
DWORD bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
if (infoHeader->biBitCount <= 8)
bfOffBits += ((HGUInt)(1 << infoHeader->biBitCount) * sizeof(RGBQUAD));
BITMAPFILEHEADER fileHeader = { 0 };
fileHeader.bfType = 0x4D42;
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + size;
fileHeader.bfOffBits = bfOffBits;
pStream->Write(&fileHeader, sizeof(BITMAPFILEHEADER), &writeSize);
pStream->Write(pMem, size, &writeSize);
Gdiplus::Image img(pStream);
Gdiplus::Status status = img.GetLastStatus();
if (Gdiplus::Ok == status)
{
ret = Load(&img, roi, type, origin, image);
}
pStream->Release();
}
GlobalUnlock(hMem);
}
return ret;
}
#endif /* HG_CMP_MSC */
HGResult HGAPI HGBase_CloneImage(HGImage srcImage, HGUInt type, HGUInt origin, HGImage* image)
{
if (NULL == srcImage || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* srcImageImpl = (HGImageImpl*)srcImage;
if (0 == type)
{
type = srcImageImpl->m_type;
}
HGResult ret = HGBase_CreateImage(srcImageImpl->m_right - srcImageImpl->m_left,
srcImageImpl->m_bottom - srcImageImpl->m_top, type, origin, image);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
ret = HGBase_CopyImage(srcImage, *image);
if (HGBASE_ERR_OK != ret)
{
HGBase_DestroyImage(*image);
return ret;
}
HGBase_SetImageDpi(*image, srcImageImpl->m_xDpi, srcImageImpl->m_yDpi);
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_DestroyImage(HGImage image)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
delete imageImpl;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_GetImageData(HGImage image, HGByte** data)
{
if (NULL == image || NULL == data)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
*data = imageImpl->m_data;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_GetImageInfo(HGImage image, HGImageInfo* info)
{
if (NULL == image || NULL == info)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
info->width = imageImpl->m_width;
info->height = imageImpl->m_height;
info->type = imageImpl->m_type;
info->widthStep = imageImpl->m_widthStep;
info->origin = imageImpl->m_origin;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_GetImageROI(HGImage image, HGImageRoi* roi)
{
if (NULL == image || NULL == roi)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
roi->left = imageImpl->m_left;
roi->top = imageImpl->m_top;
roi->right = imageImpl->m_right;
roi->bottom = imageImpl->m_bottom;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_SetImageROI(HGImage image, const HGImageRoi* roi)
{
if (NULL == image || NULL == roi)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
if (roi->right <= roi->left || roi->bottom <= roi->top
|| roi->right > imageImpl->m_width || roi->bottom > imageImpl->m_height)
{
return HGBASE_ERR_INVALIDARG;
}
imageImpl->m_left = roi->left;
imageImpl->m_top = roi->top;
imageImpl->m_right = roi->right;
imageImpl->m_bottom = roi->bottom;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ResetImageROI(HGImage image)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
imageImpl->m_left = 0;
imageImpl->m_top = 0;
imageImpl->m_right = imageImpl->m_width;
imageImpl->m_bottom = imageImpl->m_height;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_GetImageDpi(HGImage image, HGUInt* xDpi, HGUInt* yDpi)
{
if (NULL == image || NULL == xDpi || NULL == yDpi)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
*xDpi = imageImpl->m_xDpi;
*yDpi = imageImpl->m_yDpi;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_SetImageDpi(HGImage image, HGUInt xDpi, HGUInt yDpi)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
imageImpl->m_xDpi = xDpi;
imageImpl->m_yDpi = yDpi;
return HGBASE_ERR_OK;
}
#if defined(HG_CMP_MSC)
HGResult HGAPI HGBase_GetHBITMAPOfImage(HGImage image, HBITMAP* hBmp)
{
if (NULL == image || NULL == hBmp)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
*hBmp = imageImpl->m_hBmp;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_CreateHBITMAPFromImage(HGImage image, HBITMAP* hBmp)
{
return HGBASE_ERR_NOTIMPL;
}
HGResult HGAPI HGBase_CreateDIBFromImage(HGImage image, HGLOBAL* hMem)
{
return HGBASE_ERR_NOTIMPL;
}
#endif /* HG_CMP_MSC */
HGResult HGAPI HGBase_ImageMirror(HGImage image, HGImage destImage)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
if (NULL == destImage || image == destImage)
{
HGByte* p = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step = -(HGInt)widthStep;
}
if (3 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = p + (HGSize)i * (HGSize)step;
HGByte* pEx2 = pEx + dataSize - channels;
while (pEx < pEx2)
{
HGByte temp0 = pEx[0];
pEx[0] = pEx2[0];
pEx2[0] = temp0;
HGByte temp1 = pEx[1];
pEx[1] = pEx2[1];
pEx2[1] = temp1;
HGByte temp2 = pEx[2];
pEx[2] = pEx2[2];
pEx2[2] = temp2;
pEx += 3;
pEx2 -= 3;
}
}
}
else if (4 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = p + (HGSize)i * (HGSize)step;
HGByte* pEx2 = pEx + dataSize - channels;
while (pEx < pEx2)
{
HGUInt tmp = *(HGUInt*)pEx;
*(HGUInt*)pEx = *(HGUInt*)pEx2;
*(HGUInt*)pEx2 = tmp;
pEx += 4;
pEx2 -= 4;
}
}
}
else
{
assert(1 == channels);
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = p + (HGSize)i * (HGSize)step;
HGByte* pEx2 = pEx + dataSize - channels;
while (pEx < pEx2)
{
HGByte tmp = *pEx;
*pEx = *pEx2;
*pEx2 = tmp;
++pEx;
--pEx2;
}
}
}
}
else
{
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destRight - destLeft) || roiHeight != (destBottom - destTop))
{
return HGBASE_ERR_INVALIDDATA;
}
HGByte* src = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt srcStep = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
src = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
srcStep = -(HGInt)widthStep;
}
HGByte* dest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
dest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * channels;
destStep = -(HGInt)destWidthStep;
}
if (3 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep + dataSize - channels;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
pEx += 3;
pDestEx -= 3;
}
}
}
else if (4 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep + dataSize - channels;
while (pEx < pExEnd)
{
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
pEx += 4;
pDestEx -= 4;
}
}
}
else
{
assert(1 == channels);
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep + dataSize - channels;
while (pEx < pExEnd)
{
*pDestEx = *pEx;
++pEx;
--pDestEx;
}
}
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ImageFlip(HGImage image, HGImage destImage)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
if (NULL == destImage || image == destImage)
{
HGByte* p1 = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step1 = (HGInt)widthStep;
HGByte* p2 = data + (HGUSize)(bottom - 1) * (HGUSize)widthStep + left * channels;
HGInt step2 = -(HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p1 = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step1 = -(HGInt)widthStep;
p2 = data + (HGUSize)(height - bottom) * (HGUSize)widthStep + left * channels;
step2 = (HGInt)widthStep;
}
uint32_t loop = roiHeight / 2;
if (4 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)loop; ++i)
{
uint8_t* p1Ex = p1 + (HGSize)i * (HGSize)step1;
uint8_t* p1ExEnd = p1Ex + dataSize;
uint8_t* p2Ex = p2 + (HGSize)i * (HGSize)step2;
while (p1Ex < p1ExEnd)
{
HGUInt tmp = *(HGUInt*)p1Ex;
*(HGUInt*)p1Ex = *(HGUInt*)p2Ex;
*(HGUInt*)p2Ex = tmp;
p1Ex += 4;
p2Ex += 4;
}
}
}
else
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)loop; ++i)
{
uint8_t* p1Ex = p1 + (HGSize)i * (HGSize)step1;
uint8_t* p1ExEnd = p1Ex + dataSize;
uint8_t* p2Ex = p2 + (HGSize)i * (HGSize)step2;
while (p1Ex < p1ExEnd)
{
uint8_t temp = *p1Ex;
*p1Ex = *p2Ex;
*p2Ex = temp;
++p1Ex;
++p2Ex;
}
}
}
}
else
{
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destRight - destLeft) || roiHeight != (destBottom - destTop))
{
return HGBASE_ERR_INVALIDDATA;
}
HGByte* src = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt srcStep = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
src = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
srcStep = -(HGInt)widthStep;
}
HGByte* dest = destData + (HGUSize)(destBottom - 1) * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = -(HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
dest = destData + (HGUSize)(destHeight - destBottom) * (HGUSize)destWidthStep + destLeft * channels;
destStep = (HGInt)destWidthStep;
}
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
memcpy(pDestEx, pEx, dataSize);
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ImageRotateLeft(HGImage image, HGImage destImage)
{
if (NULL == image || NULL == destImage || image == destImage)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destBottom - destTop) || roiHeight != (destRight - destLeft))
{
return HGBASE_ERR_INVALIDDATA;
}
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
HGInt span = (HGInt)channels * 32;
HGInt destSpan = (HGInt)destWidthStep * 32;
uint8_t* p = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step = -(HGInt)widthStep;
}
uint8_t* pEnd = p + dataSize;
uint8_t* pDest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
pDest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * channels;
destStep = -(HGInt)destWidthStep;
destSpan = -(HGInt)destWidthStep * 32;
}
pDest += (HGSize)(roiWidth - 1) * (HGSize)destStep;
if (3 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest + i * 3;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
pEx += 3;
pDestEx -= destStep;
}
}
p += span;
pDest -= destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest + i * 3;
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
}
p += 3;
pDest -= destStep;
}
}
else if (4 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest + i * 4;
while (pEx < pExEnd)
{
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
pEx += 4;
pDestEx -= destStep;
}
}
p += span;
pDest -= destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest + i * 4;
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
}
p += 4;
pDest -= destStep;
}
}
else
{
assert(1 == channels);
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest + i;
while (pEx < pExEnd)
{
*pDestEx = *pEx;
++pEx;
pDestEx -= destStep;
}
}
p += span;
pDest -= destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest + i;
*pDestEx = *pEx;
}
++p;
pDest -= destStep;
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ImageRotateRight(HGImage image, HGImage destImage)
{
if (NULL == image || NULL == destImage || image == destImage)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destBottom - destTop) || roiHeight != (destRight - destLeft))
{
return HGBASE_ERR_INVALIDDATA;
}
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
HGInt span = (HGInt)channels * 32;
HGInt destSpan = (HGInt)destWidthStep * 32;
uint8_t* p = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step = -(HGInt)widthStep;
}
uint8_t* pEnd = p + dataSize;
uint8_t* pDest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
pDest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * channels;
destStep = -(HGInt)destWidthStep;
destSpan = -(HGInt)destWidthStep * 32;
}
pDest += (roiHeight - 1) * channels;
if (3 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest - i * 3;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
pEx += 3;
pDestEx += destStep;
}
}
p += span;
pDest += destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest - i * 3;
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
}
p += 3;
pDest += destStep;
}
}
else if (4 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest - i * 4;
while (pEx < pExEnd)
{
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
pEx += 4;
pDestEx += destStep;
}
}
p += span;
pDest += destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest - i * 4;
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
}
p += 4;
pDest += destStep;
}
}
else
{
assert(1 == channels);
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest - i;
while (pEx < pExEnd)
{
*pDestEx = *pEx;
++pEx;
pDestEx += destStep;
}
}
p += span;
pDest += destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest - i;
*pDestEx = *pEx;
}
++p;
pDest += destStep;
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ImageRotateLeftMirror(HGImage image, HGImage destImage)
{
if (NULL == image || NULL == destImage || image == destImage)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destBottom - destTop) || roiHeight != (destRight - destLeft))
{
return HGBASE_ERR_INVALIDDATA;
}
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
HGInt span = (HGInt)channels * 32;
HGInt destSpan = (HGInt)destWidthStep * 32;
uint8_t* p = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step = -(HGInt)widthStep;
}
uint8_t* pEnd = p + dataSize;
uint8_t* pDest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
pDest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * channels;
destStep = -(HGInt)destWidthStep;
destSpan = -(HGInt)destWidthStep * 32;
}
pDest += (HGSize)(roiWidth - 1) * (HGSize)destStep;
pDest += (roiHeight - 1) * channels;
if (3 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest - i * 3;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
pEx += 3;
pDestEx -= destStep;
}
}
p += span;
pDest -= destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest - i * 3;
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
}
p += 3;
pDest -= destStep;
}
}
else if (4 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest - i * 4;
while (pEx < pExEnd)
{
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
pEx += 4;
pDestEx -= destStep;
}
}
p += span;
pDest -= destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest - i * 4;
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
}
p += 4;
pDest -= destStep;
}
}
else
{
assert(1 == channels);
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest - i;
while (pEx < pExEnd)
{
*pDestEx = *pEx;
++pEx;
pDestEx -= destStep;
}
}
p += span;
pDest -= destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest - i;
*pDestEx = *pEx;
}
++p;
pDest -= destStep;
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ImageRotateRightMirror(HGImage image, HGImage destImage)
{
if (NULL == image || NULL == destImage || image == destImage)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destBottom - destTop) || roiHeight != (destRight - destLeft))
{
return HGBASE_ERR_INVALIDDATA;
}
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
HGInt span = (HGInt)channels * 32;
HGInt destSpan = (HGInt)destWidthStep * 32;
uint8_t* p = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step = -(HGInt)widthStep;
}
uint8_t* pEnd = p + dataSize;
uint8_t* pDest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
pDest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * channels;
destStep = -(HGInt)destWidthStep;
destSpan = -(HGInt)destWidthStep * 32;
}
if (3 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest + i * 3;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
pEx += 3;
pDestEx += destStep;
}
}
p += span;
pDest += destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest + i * 3;
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
}
p += 3;
pDest += destStep;
}
}
else if (4 == channels)
{
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest + i * 4;
while (pEx < pExEnd)
{
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
pEx += 4;
pDestEx += destStep;
}
}
p += span;
pDest += destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest + i * 4;
*(HGUInt*)pDestEx = *(HGUInt*)pEx;
}
p += 4;
pDest += destStep;
}
}
else
{
assert(1 == channels);
while (p + span <= pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + span;
uint8_t* pDestEx = pDest + i;
while (pEx < pExEnd)
{
*pDestEx = *pEx;
++pEx;
pDestEx += destStep;
}
}
p += span;
pDest += destSpan;
}
while (p < pEnd)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pDestEx = pDest + i;
*pDestEx = *pEx;
}
++p;
pDest += destStep;
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ImageRotate180(HGImage image, HGImage destImage)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
if (NULL == destImage || image == destImage)
{
HGByte* p1 = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step1 = (HGInt)widthStep;
HGByte* p2 = data + (HGUSize)(bottom - 1) * (HGUSize)widthStep + left * channels;
HGInt step2 = -(HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p1 = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step1 = -(HGInt)widthStep;
p2 = data + (HGUSize)(height - bottom) * (HGUSize)widthStep + left * channels;
step2 = (HGInt)widthStep;
}
if (3 == channels)
{
HGUInt loop = roiHeight / 2;
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)loop; ++i)
{
HGByte* p1Ex = p1 + (HGSize)i * (HGSize)step1;
HGByte* p1ExEnd = p1Ex + dataSize;
HGByte* p2Ex = p2 + (HGSize)i * (HGSize)step2 + dataSize - channels;
while (p1Ex < p1ExEnd)
{
HGByte temp0 = p1Ex[0];
p1Ex[0] = p2Ex[0];
p2Ex[0] = temp0;
HGByte temp1 = p1Ex[1];
p1Ex[1] = p2Ex[1];
p2Ex[1] = temp1;
HGByte temp2 = p1Ex[2];
p1Ex[2] = p2Ex[2];
p2Ex[2] = temp2;
p1Ex += 3;
p2Ex -= 3;
}
}
if (0 != roiHeight % 2)
{
HGByte* p1Ex = p1 + (HGSize)loop * (HGSize)step1;
HGByte* p2Ex = p2 + (HGSize)loop * (HGSize)step2 + dataSize - channels;
while (p1Ex < p2Ex)
{
HGByte temp0 = p1Ex[0];
p1Ex[0] = p2Ex[0];
p2Ex[0] = temp0;
HGByte temp1 = p1Ex[1];
p1Ex[1] = p2Ex[1];
p2Ex[1] = temp1;
HGByte temp2 = p1Ex[2];
p1Ex[2] = p2Ex[2];
p2Ex[2] = temp2;
p1Ex += 3;
p2Ex -= 3;
}
}
}
else if (4 == channels)
{
HGUInt loop = roiHeight / 2;
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)loop; ++i)
{
HGByte* p1Ex = p1 + (HGSize)i * (HGSize)step1;
HGByte* p1ExEnd = p1Ex + dataSize;
HGByte* p2Ex = p2 + (HGSize)i * (HGSize)step2 + dataSize - channels;
while (p1Ex < p1ExEnd)
{
HGUInt tmp = *(HGUInt*)p1Ex;
*(HGUInt*)p1Ex = *(HGUInt*)p2Ex;
*(HGUInt*)p2Ex = tmp;
p1Ex += 4;
p2Ex -= 4;
}
}
if (0 != roiHeight % 2)
{
HGByte* p1Ex = p1 + (HGSize)loop * (HGSize)step1;
HGByte* p2Ex = p2 + (HGSize)loop * (HGSize)step2 + dataSize - channels;
while (p1Ex < p2Ex)
{
HGUInt tmp = *(HGUInt*)p1Ex;
*(HGUInt*)p1Ex = *(HGUInt*)p2Ex;
*(HGUInt*)p2Ex = tmp;
p1Ex += 4;
p2Ex -= 4;
}
}
}
else
{
assert(1 == channels);
HGUInt loop = roiHeight / 2;
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)loop; ++i)
{
HGByte* p1Ex = p1 + (HGSize)i * (HGSize)step1;
HGByte* p1ExEnd = p1Ex + dataSize;
HGByte* p2Ex = p2 + (HGSize)i * (HGSize)step2 + dataSize - channels;
while (p1Ex < p1ExEnd)
{
HGByte tmp = *p1Ex;
*p1Ex = *p2Ex;
*p2Ex = tmp;
++p1Ex;
--p2Ex;
}
}
if (0 != roiHeight % 2)
{
HGByte* p1Ex = p1 + (HGSize)loop * (HGSize)step1;
HGByte* p2Ex = p2 + (HGSize)loop * (HGSize)step2 + dataSize - channels;
while (p1Ex < p2Ex)
{
HGByte tmp = *p1Ex;
*p1Ex = *p2Ex;
*p2Ex = tmp;
++p1Ex;
--p2Ex;
}
}
}
}
else
{
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destRight - destLeft) || roiHeight != (destBottom - destTop))
{
return HGBASE_ERR_INVALIDDATA;
}
HGByte* src = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt srcStep = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
src = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
srcStep = -(HGInt)widthStep;
}
HGByte* dest = destData + (HGUSize)(destBottom - 1) * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = -(HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
dest = destData + (HGUSize)(destHeight - destBottom) * (HGUSize)destWidthStep + destLeft * channels;
destStep = (HGInt)destWidthStep;
}
if (3 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* p1Ex = src + (HGSize)i * (HGSize)srcStep;
HGByte* p1ExEnd = p1Ex + dataSize;
HGByte* p2Ex = dest + (HGSize)i * (HGSize)destStep + dataSize - channels;
while (p1Ex < p1ExEnd)
{
p2Ex[0] = p1Ex[0];
p2Ex[1] = p1Ex[1];
p2Ex[2] = p1Ex[2];
p1Ex += 3;
p2Ex -= 3;
}
}
}
else if (4 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* p1Ex = src + (HGSize)i * (HGSize)srcStep;
HGByte* p1ExEnd = p1Ex + dataSize;
HGByte* p2Ex = dest + (HGSize)i * (HGSize)destStep + dataSize - channels;
while (p1Ex < p1ExEnd)
{
*(HGUInt*)p2Ex = *(HGUInt*)p1Ex;
p1Ex += 4;
p2Ex -= 4;
}
}
}
else
{
assert(1 == channels);
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* p1Ex = src + (HGSize)i * (HGSize)srcStep;
HGByte* p1ExEnd = p1Ex + dataSize;
HGByte* p2Ex = dest + (HGSize)i * (HGSize)destStep + dataSize - channels;
while (p1Ex < p1ExEnd)
{
*p2Ex = *p1Ex;
++p1Ex;
--p2Ex;
}
}
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ImageGrayscale(HGImage image, HGImage destImage)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
if (NULL == destImage || image == destImage)
{
HGByte* p = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step = -(HGInt)widthStep;
}
if (HGBASE_IMGTYPE_RGB == type || HGBASE_IMGTYPE_RGBA == type)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + dataSize;
while (pEx < pExEnd)
{
uint8_t value = (pEx[0] * 76 + pEx[1] * 150 + pEx[2] * 30) >> 8;
pEx[0] = pEx[1] = pEx[2] = value;
pEx += channels;
}
}
}
else if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_BGRA == type)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + dataSize;
while (pEx < pExEnd)
{
uint8_t value = (pEx[2] * 76 + pEx[1] * 150 + pEx[0] * 30) >> 8;
pEx[0] = pEx[1] = pEx[2] = value;
pEx += channels;
}
}
}
else
{
assert(HGBASE_IMGTYPE_GRAY == type);
}
}
else
{
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destRight - destLeft) || roiHeight != (destBottom - destTop))
{
return HGBASE_ERR_INVALIDDATA;
}
HGByte* src = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt srcStep = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
src = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
srcStep = -(HGInt)widthStep;
}
HGByte* dest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
dest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * channels;
destStep = -(HGInt)destWidthStep;
}
if (HGBASE_IMGTYPE_RGB == type || HGBASE_IMGTYPE_RGBA == type)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
uint8_t value = (pEx[0] * 76 + pEx[1] * 150 + pEx[2] * 30) >> 8;
pDestEx[0] = pDestEx[1] = pDestEx[2] = value;
pEx += channels;
pDestEx += channels;
}
}
}
else if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_BGRA == type)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
uint8_t value = (pEx[2] * 76 + pEx[1] * 150 + pEx[0] * 30) >> 8;
pDestEx[0] = pDestEx[1] = pDestEx[2] = value;
pEx += channels;
pDestEx += channels;
}
}
}
else
{
assert(HGBASE_IMGTYPE_GRAY == type);
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
memcpy(pDestEx, pEx, dataSize);
}
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_ReverseImage(HGImage image, HGImage destImage)
{
if (NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
if (NULL == destImage || image == destImage)
{
HGByte* p = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt step = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
step = -(HGInt)widthStep;
}
if (4 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + dataSize;
while (pEx < pExEnd)
{
HGUInt temp = *(HGUInt*)pEx;
temp = ~temp;
*(HGUInt*)pEx = temp;
pEx += 4;
}
}
}
else
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
uint8_t* pExEnd = pEx + dataSize;
while (pEx < pExEnd)
{
uint8_t temp = *pEx;
temp = ~temp;
*pEx = temp;
++pEx;
}
}
}
}
else
{
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (type != destType)
{
return HGBASE_ERR_INVALIDDATA;
}
if (roiWidth != (destRight - destLeft) || roiHeight != (destBottom - destTop))
{
return HGBASE_ERR_INVALIDDATA;
}
HGByte* src = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt srcStep = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
src = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
srcStep = -(HGInt)widthStep;
}
HGByte* dest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * channels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
dest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * channels;
destStep = -(HGInt)destWidthStep;
}
if (4 == channels)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
HGUInt temp = *(HGUInt*)pEx;
temp = ~temp;
*(HGUInt*)pDestEx = temp;
pEx += 4;
pDestEx += 4;
}
}
}
else
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
uint8_t temp = *pEx;
temp = ~temp;
*pDestEx = temp;
++pEx;
++pDestEx;
}
}
}
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_CopyImage(HGImage image, HGImage destImage)
{
if (NULL == image || NULL == destImage || image == destImage)
{
return HGBASE_ERR_INVALIDARG;
}
HGImageImpl* imageImpl = (HGImageImpl*)image;
HGUInt width = imageImpl->m_width;
HGUInt height = imageImpl->m_height;
HGUInt type = imageImpl->m_type;
HGUInt widthStep = imageImpl->m_widthStep;
HGUInt origin = imageImpl->m_origin;
HGUInt left = imageImpl->m_left;
HGUInt top = imageImpl->m_top;
HGUInt right = imageImpl->m_right;
HGUInt bottom = imageImpl->m_bottom;
HGByte* data = imageImpl->m_data;
HGUInt roiWidth = right - left;
HGUInt roiHeight = bottom - top;
HGImageImpl* destImageImpl = (HGImageImpl*)destImage;
HGUInt destWidth = destImageImpl->m_width;
HGUInt destHeight = destImageImpl->m_height;
HGUInt destType = destImageImpl->m_type;
HGUInt destWidthStep = destImageImpl->m_widthStep;
HGUInt destOrigin = destImageImpl->m_origin;
HGUInt destLeft = destImageImpl->m_left;
HGUInt destTop = destImageImpl->m_top;
HGUInt destRight = destImageImpl->m_right;
HGUInt destBottom = destImageImpl->m_bottom;
uint8_t* destData = destImageImpl->m_data;
if (roiWidth != (destRight - destLeft) || roiHeight != (destBottom - destTop))
{
return HGBASE_ERR_INVALIDDATA;
}
uint32_t channels = 1;
if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
channels = 3;
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
channels = 4;
uint32_t dataSize = roiWidth * channels;
uint32_t destChannels = 1;
if (HGBASE_IMGTYPE_BGR == destType || HGBASE_IMGTYPE_RGB == destType)
destChannels = 3;
else if (HGBASE_IMGTYPE_BGRA == destType || HGBASE_IMGTYPE_RGBA == destType)
destChannels = 4;
HGByte* src = data + (HGUSize)top * (HGUSize)widthStep + left * channels;
HGInt srcStep = (HGInt)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
src = data + (HGUSize)(height - top - 1) * (HGUSize)widthStep + left * channels;
srcStep = -(HGInt)widthStep;
}
HGByte* dest = destData + (HGUSize)destTop * (HGUSize)destWidthStep + destLeft * destChannels;
HGInt destStep = (HGInt)destWidthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destOrigin)
{
dest = destData + (HGUSize)(destHeight - destTop - 1) * (HGUSize)destWidthStep + destLeft * destChannels;
destStep = -(HGInt)destWidthStep;
}
if (type == destType)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
memcpy(pDestEx, pEx, dataSize);
}
}
else
{
if (HGBASE_IMGTYPE_GRAY == type)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
pDestEx[0] = pDestEx[1] = pDestEx[2] = *pEx;
++pEx;
pDestEx += destChannels;
}
}
}
else if (HGBASE_IMGTYPE_GRAY == destType)
{
if (HGBASE_IMGTYPE_RGB == type || HGBASE_IMGTYPE_RGBA == type)
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
uint8_t value = (pEx[0] * 76 + pEx[1] * 150 + pEx[2] * 30) >> 8;
*pDestEx = value;
pEx += channels;
++pDestEx;
}
}
}
else
{
assert(HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_BGRA == type);
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
uint8_t value = (pEx[2] * 76 + pEx[1] * 150 + pEx[0] * 30) >> 8;
*pDestEx = value;
pEx += channels;
++pDestEx;
}
}
}
}
else if ((HGBASE_IMGTYPE_RGB == type && HGBASE_IMGTYPE_RGBA == destType)
|| (HGBASE_IMGTYPE_BGR == type && HGBASE_IMGTYPE_BGRA == destType)
|| (HGBASE_IMGTYPE_RGBA == type && HGBASE_IMGTYPE_RGB == destType)
|| (HGBASE_IMGTYPE_BGRA == type && HGBASE_IMGTYPE_BGR == destType))
{
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
pEx += channels;
pDestEx += destChannels;
}
}
}
else
{
assert((HGBASE_IMGTYPE_RGB == type && HGBASE_IMGTYPE_BGRA == destType)
|| (HGBASE_IMGTYPE_BGR == type && HGBASE_IMGTYPE_RGBA == destType)
|| (HGBASE_IMGTYPE_RGBA == type && HGBASE_IMGTYPE_BGRA == destType)
|| (HGBASE_IMGTYPE_BGRA == type && HGBASE_IMGTYPE_RGBA == destType)
|| (HGBASE_IMGTYPE_RGBA == type && HGBASE_IMGTYPE_BGR == destType)
|| (HGBASE_IMGTYPE_BGRA == type && HGBASE_IMGTYPE_RGB == destType)
|| (HGBASE_IMGTYPE_BGR == type && HGBASE_IMGTYPE_RGB == destType)
|| (HGBASE_IMGTYPE_RGB == type && HGBASE_IMGTYPE_BGR == destType));
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)roiHeight; ++i)
{
HGByte* pEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pExEnd = pEx + dataSize;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
pDestEx[2] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[0] = pEx[2];
pEx += channels;
pDestEx += destChannels;
}
}
}
}
return HGBASE_ERR_OK;
}