code_app/modules/base/HGImage.cpp

3293 lines
80 KiB
C++

#include "HGImage.h"
#include "HGInc.h"
#if defined(HG_CMP_MSC)
#include <combaseapi.h>
#include <atlstr.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 = 0;
m_yDpi = 0;
}
~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 if (HGBASE_IMGTYPE_BINARY == type)
{
pbmihdr->biBitCount = 1;
RGBQUAD* clr = (RGBQUAD*)(pbmihdr + 1);
for (int i = 0; i < 2; ++i)
{
clr[i].rgbRed = i * 255;
clr[i].rgbGreen = i * 255;
clr[i].rgbBlue = i * 255;
}
}
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_BINARY == type)
bpp = 1;
else 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 = NULL;
if (HGBASE_IMGTYPE_RGB == type || HGBASE_IMGTYPE_RGBA == type)
{
data = (HGByte*)malloc(size);
if (NULL == data)
return HGBASE_ERR_OUTOFMEMORY;
else
alloc = HGTRUE;
}
else
{
hBmp = CreateHBITMAP(width, height, type, origin, 0, 0, &data);
if (NULL == hBmp)
return HGBASE_ERR_OUTOFMEMORY;
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 = 0;
imageImpl->m_yDpi = 0;
*image = (HGImage)imageImpl;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_CreateImageWithData(HGByte* data, const HGImageInfo* info, 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_BINARY == info->type)
bpp = 1;
else 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;
}
HGImageImpl* imageImpl = new HGImageImpl;
#if defined(HG_CMP_MSC)
imageImpl->m_hBmp = NULL;
#endif
imageImpl->m_data = data;
imageImpl->m_size = (HGUSize)info->widthStep * (HGUSize)info->height;
imageImpl->m_alloc = HGFALSE;
imageImpl->m_width = info->width;
imageImpl->m_height = info->height;
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 = 0;
imageImpl->m_yDpi = 0;
*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, &srcImage);
if (HGBASE_ERR_OK != ret)
return ret;
if (NULL != roi)
{
ret = HGBase_SetImageROI(srcImage, roi);
if (HGBASE_ERR_OK != ret)
{
HGBase_DestroyImage(srcImage);
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;
DIBSECTION dib;
int ret = GetObject(hBmp, sizeof(DIBSECTION), &dib);
assert(sizeof(DIBSECTION) == ret);
RGBQUAD colorTable[256];
HDC hMem = CreateCompatibleDC(NULL);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hMem, hBmp);
UINT colorCount = GetDIBColorTable(hMem, 0, 256, colorTable);
SelectObject(hMem, hOldBmp);
DeleteDC(hMem);
if (1 == dib.dsBmih.biBitCount || 4 == dib.dsBmih.biBitCount
|| 8 == dib.dsBmih.biBitCount)
{
assert(colorCount > 0);
BOOL bGray = TRUE;
BOOL bBinary = TRUE;
for (UINT i = 0; i < colorCount; ++i)
{
BYTE red = colorTable[i].rgbRed;
BYTE green = colorTable[i].rgbGreen;
BYTE blue = colorTable[i].rgbBlue;
if (red != green || red != blue || green != blue)
{
bGray = FALSE;
bBinary = FALSE;
break;
}
if (red != 0 && red != 255)
{
bBinary = FALSE;
}
}
if (bBinary)
type = HGBASE_IMGTYPE_BINARY;
else if (bGray)
type = HGBASE_IMGTYPE_GRAY;
}
else if (32 == dib.dsBmih.biBitCount)
{
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;
}
DIBSECTION dib;
if (sizeof(DIBSECTION) != GetObject(hBmp, sizeof(DIBSECTION), &dib))
{
return HGBASE_ERR_INVALIDDATA;
}
HGImageRoi roi2 = { 0, 0, (HGUInt)dib.dsBm.bmWidth, (HGUInt)dib.dsBm.bmHeight };
if (NULL != roi)
{
if (roi->left >= roi->right || roi->top >= roi->bottom
|| roi->right > (HGUInt)dib.dsBm.bmWidth || roi->bottom > (HGUInt)dib.dsBm.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
{
HGUInt type2 = type;
if (HGBASE_IMGTYPE_RGB == type)
type2 = HGBASE_IMGTYPE_BGR;
else if (HGBASE_IMGTYPE_RGBA == type)
type2 = HGBASE_IMGTYPE_BGRA;
HGImage image2 = NULL;
ret = HGBase_CreateImageFromHBITMAP(hBmp, roi, type2, 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)
{
HGUInt xDpi = (HGUInt)(dib.dsBmih.biXPelsPerMeter / 39.37);
HGUInt yDpi = (HGUInt)(dib.dsBmih.biYPelsPerMeter / 39.37);
HGBase_SetImageDpi(*image, xDpi, yDpi);
}
return ret;
}
static HGUInt GetType(Gdiplus::Image* pImage)
{
assert(NULL != pImage);
HGUInt type = HGBASE_IMGTYPE_BGR;
Gdiplus::PixelFormat pixFmt = pImage->GetPixelFormat();
if (PixelFormat16bppGrayScale == pixFmt)
{
type = HGBASE_IMGTYPE_GRAY;
}
else if (Gdiplus::IsIndexedPixelFormat(pixFmt))
{
UINT nPaletteSize = pImage->GetPaletteSize();
Gdiplus::ColorPalette* pPalette = (Gdiplus::ColorPalette*)malloc(nPaletteSize);
if (NULL != pPalette)
{
pImage->GetPalette(pPalette, nPaletteSize);
BOOL bGray = TRUE;
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 (red != green || red != blue || green != blue)
{
bGray = FALSE;
bBinary = FALSE;
break;
}
if (red != 0 && red != 255)
{
bBinary = FALSE;
}
}
if (bBinary)
type = HGBASE_IMGTYPE_BINARY;
else if (bGray)
type = HGBASE_IMGTYPE_GRAY;
free(pPalette);
}
}
else if (Gdiplus::IsAlphaPixelFormat(pixFmt))
{
type = HGBASE_IMGTYPE_BGRA;
}
return type;
}
static HGResult LoadGdiImage(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);
}
if (0 == origin)
{
origin = HGBASE_IMGORIGIN_TOP;
}
HGResult ret = HGBase_CreateImage(roi2.right - roi2.left, roi2.bottom - roi2.top, type, origin, image);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
HBITMAP hBmp = NULL;
HGBase_GetHBITMAPOfImage(*image, &hBmp);
if (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
{
HGUInt type2 = type;
if (HGBASE_IMGTYPE_RGB == type)
type2 = HGBASE_IMGTYPE_BGR;
else if (HGBASE_IMGTYPE_RGBA == type)
type2 = HGBASE_IMGTYPE_BGRA;
HGImage image2 = NULL;
ret = LoadGdiImage(pImage, roi, type2, 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)
{
HGUInt xDpi = (HGUInt)((double)pImage->GetHorizontalResolution() + 0.5);
HGUInt yDpi = (HGUInt)((double)pImage->GetVerticalResolution() + 0.5);
HGBase_SetImageDpi(*image, xDpi, yDpi);
}
return ret;
}
HGResult HGAPI HGBase_CreateDIBFile(HGLOBAL hMem, const HGChar *fileName)
{
if (NULL == hMem || NULL == fileName)
{
return HGBASE_ERR_INVALIDARG;
}
HGResult ret = HGBASE_ERR_FAIL;
ULONG size = (ULONG)GlobalSize(hMem);
void* pMem = GlobalLock(hMem);
if (NULL != pMem)
{
FILE *file = fopen(fileName, "wb");
if (NULL != file)
{
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;
fwrite(&fileHeader, 1, sizeof(BITMAPFILEHEADER), file);
fwrite(pMem, 1, size, file);
fclose(file);
ret = HGBASE_ERR_OK;
}
GlobalUnlock(hMem);
}
return ret;
}
HGResult HGAPI HGBase_CreateImageFromFile(const HGChar *fileName, const HGImageRoi* roi,
HGUInt type, HGUInt origin, HGImage* image)
{
if (NULL == fileName || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGResult ret = HGBASE_ERR_FAIL;
ULONG_PTR nToken = 0;
Gdiplus::GdiplusStartupInput input;
Gdiplus::GdiplusStartupOutput output;
Gdiplus::GdiplusStartup(&nToken, &input, &output);
assert(0 != nToken);
CStringW fileName2(fileName);
Gdiplus::Image *img = new Gdiplus::Image(fileName2);
Gdiplus::Status status = img->GetLastStatus();
if (Gdiplus::Ok == status)
{
ret = LoadGdiImage(img, roi, type, origin, image);
}
delete img;
Gdiplus::GdiplusShutdown(nToken);
nToken = 0;
return ret;
}
HGResult HGAPI HGBase_CreateDIBStream(HGLOBAL hMem, HGStream *stream)
{
if (NULL == hMem || NULL == stream)
{
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);
*stream = (HGStream)pStream;
ret = HGBASE_ERR_OK;
}
GlobalUnlock(hMem);
}
return ret;
}
HGResult HGAPI HGBase_DestroyStream(HGStream stream)
{
if (NULL == stream)
{
return HGBASE_ERR_INVALIDARG;
}
IStream* pStream = (IStream*)stream;
pStream->Release();
return HGBASE_ERR_OK;
}
HGResult HGAPI HGBase_CreateImageFromStream(HGStream stream, const HGImageRoi* roi,
HGUInt type, HGUInt origin, HGImage* image)
{
if (NULL == stream || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGResult ret = HGBASE_ERR_FAIL;
ULONG_PTR nToken = 0;
Gdiplus::GdiplusStartupInput input;
Gdiplus::GdiplusStartupOutput output;
Gdiplus::GdiplusStartup(&nToken, &input, &output);
assert(0 != nToken);
IStream* pStream = (IStream*)stream;
Gdiplus::Image *img = new Gdiplus::Image(pStream);
Gdiplus::Status status = img->GetLastStatus();
if (Gdiplus::Ok == status)
{
ret = LoadGdiImage(img, roi, type, origin, image);
}
delete img;
Gdiplus::GdiplusShutdown(nToken);
nToken = 0;
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;
}
if (0 == origin)
{
origin = srcImageImpl->m_origin;
}
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)
{
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageMirror(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, image);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageMirror(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, destImage);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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)
{
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageFlip(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, image);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageFlip(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, destImage);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp1 = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp1);
if (HGBASE_ERR_OK == ret)
{
HGImageInfo imgInfo;
HGBase_GetImageInfo(imageTmp1, &imgInfo);
HGImage imageTmp2 = NULL;
ret = HGBase_CreateImage(imgInfo.height, imgInfo.width, imgInfo.type, imgInfo.origin, &imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageRotateLeft(imageTmp1, imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp2, destImage);
}
HGBase_DestroyImage(imageTmp2);
}
HGBase_DestroyImage(imageTmp1);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp1 = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp1);
if (HGBASE_ERR_OK == ret)
{
HGImageInfo imgInfo;
HGBase_GetImageInfo(imageTmp1, &imgInfo);
HGImage imageTmp2 = NULL;
ret = HGBase_CreateImage(imgInfo.height, imgInfo.width, imgInfo.type, imgInfo.origin, &imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageRotateRight(imageTmp1, imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp2, destImage);
}
HGBase_DestroyImage(imageTmp2);
}
HGBase_DestroyImage(imageTmp1);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp1 = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp1);
if (HGBASE_ERR_OK == ret)
{
HGImageInfo imgInfo;
HGBase_GetImageInfo(imageTmp1, &imgInfo);
HGImage imageTmp2 = NULL;
ret = HGBase_CreateImage(imgInfo.height, imgInfo.width, imgInfo.type, imgInfo.origin, &imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageRotateLeftMirror(imageTmp1, imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp2, destImage);
}
HGBase_DestroyImage(imageTmp2);
}
HGBase_DestroyImage(imageTmp1);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp1 = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp1);
if (HGBASE_ERR_OK == ret)
{
HGImageInfo imgInfo;
HGBase_GetImageInfo(imageTmp1, &imgInfo);
HGImage imageTmp2 = NULL;
ret = HGBase_CreateImage(imgInfo.height, imgInfo.width, imgInfo.type, imgInfo.origin, &imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageRotateRightMirror(imageTmp1, imageTmp2);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp2, destImage);
}
HGBase_DestroyImage(imageTmp2);
}
HGBase_DestroyImage(imageTmp1);
}
return ret;
}
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)
{
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageRotate180(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, image);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ImageRotate180(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, destImage);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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)
{
if (HGBASE_IMGTYPE_BINARY == type)
{
return HGBASE_ERR_OK;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
return HGBase_CopyImage(image, destImage);
}
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)
{
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ReverseImage(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, image);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type)
{
HGImage imageTmp = NULL;
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_ReverseImage(imageTmp, imageTmp);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, destImage);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
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;
}
static inline HGByte GetBit(const HGByte* data, HGUInt index)
{
HGUInt byteIndex = index / 8;
HGUInt bitIndex = index % 8;
return (data[byteIndex] >> (7 - bitIndex)) & 0x01;
}
static inline void SetBit(HGByte* data, HGUInt index, HGByte value)
{
assert(0 == value || 1 == value);
HGUInt byteIndex = index / 8;
HGUInt bitIndex = index % 8;
if (1 == value)
data[byteIndex] |= (1 << (7 - bitIndex));
else
data[byteIndex] &= ~(1 << (7 - bitIndex));
}
static HGResult CopyImageWithBinary(HGImageImpl *srcImageImpl, HGImageImpl *destImageImpl)
{
assert(HGBASE_IMGTYPE_BINARY == srcImageImpl->m_type
|| HGBASE_IMGTYPE_BINARY == destImageImpl->m_type);
HGByte* src = srcImageImpl->m_data + (HGUSize)srcImageImpl->m_top * (HGUSize)srcImageImpl->m_widthStep;
HGInt srcStep = (HGInt)srcImageImpl->m_widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == srcImageImpl->m_origin)
{
src = srcImageImpl->m_data + (HGUSize)(srcImageImpl->m_height - srcImageImpl->m_top - 1) * (HGUSize)srcImageImpl->m_widthStep;
srcStep = -(HGInt)srcImageImpl->m_widthStep;
}
HGByte* dest = destImageImpl->m_data + (HGUSize)destImageImpl->m_top * (HGUSize)destImageImpl->m_widthStep;
HGInt destStep = (HGInt)destImageImpl->m_widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == destImageImpl->m_origin)
{
dest = destImageImpl->m_data + (HGUSize)(destImageImpl->m_height - destImageImpl->m_top - 1) * (HGUSize)destImageImpl->m_widthStep;
destStep = -(HGInt)destImageImpl->m_widthStep;
}
if (HGBASE_IMGTYPE_BINARY == srcImageImpl->m_type)
{
if (HGBASE_IMGTYPE_BINARY == destImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGByte value = GetBit(pSrcEx, srcImageImpl->m_left + j);
SetBit(pDestEx, destImageImpl->m_left + j, value);
}
}
}
else if (HGBASE_IMGTYPE_GRAY == destImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGByte value = GetBit(pSrcEx, srcImageImpl->m_left + j);
pDestEx[destImageImpl->m_left + j] = (0 == value) ? 0 : 255;
}
}
}
else if (HGBASE_IMGTYPE_BGR == destImageImpl->m_type || HGBASE_IMGTYPE_RGB == destImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGByte value = GetBit(pSrcEx, srcImageImpl->m_left + j);
pDestEx[(destImageImpl->m_left + j) * 3] = (0 == value) ? 0 : 255;
pDestEx[(destImageImpl->m_left + j) * 3 + 1] = (0 == value) ? 0 : 255;
pDestEx[(destImageImpl->m_left + j) * 3 + 2] = (0 == value) ? 0 : 255;
}
}
}
else
{
assert(HGBASE_IMGTYPE_BGRA == destImageImpl->m_type || HGBASE_IMGTYPE_RGBA == destImageImpl->m_type);
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGByte value = GetBit(pSrcEx, srcImageImpl->m_left + j);
pDestEx[(destImageImpl->m_left + j) * 4] = (0 == value) ? 0 : 255;
pDestEx[(destImageImpl->m_left + j) * 4 + 1] = (0 == value) ? 0 : 255;
pDestEx[(destImageImpl->m_left + j) * 4 + 2] = (0 == value) ? 0 : 255;
}
}
}
}
else
{
assert(HGBASE_IMGTYPE_BINARY == destImageImpl->m_type);
if (HGBASE_IMGTYPE_GRAY == srcImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGByte v = pSrcEx[srcImageImpl->m_left + j];
SetBit(pDestEx, destImageImpl->m_left + j, (v >= 128 ? 1 : 0));
}
}
}
else if (HGBASE_IMGTYPE_BGR == srcImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGInt b = pSrcEx[(srcImageImpl->m_left + j) * 3];
HGInt g = pSrcEx[(srcImageImpl->m_left + j) * 3 + 1];
HGInt r = pSrcEx[(srcImageImpl->m_left + j) * 3 + 2];
HGByte v = (r * 76 + g * 150 + b * 30) >> 8;
SetBit(pDestEx, destImageImpl->m_left + j, (v >= 128 ? 1 : 0));
}
}
}
else if (HGBASE_IMGTYPE_RGB == srcImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGInt r = pSrcEx[(srcImageImpl->m_left + j) * 3];
HGInt g = pSrcEx[(srcImageImpl->m_left + j) * 3 + 1];
HGInt b = pSrcEx[(srcImageImpl->m_left + j) * 3 + 2];
HGByte v = (r * 76 + g * 150 + b * 30) >> 8;
SetBit(pDestEx, destImageImpl->m_left + j, (v >= 128 ? 1 : 0));
}
}
}
else if (HGBASE_IMGTYPE_BGRA == srcImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGInt b = pSrcEx[(srcImageImpl->m_left + j) * 4];
HGInt g = pSrcEx[(srcImageImpl->m_left + j) * 4 + 1];
HGInt r = pSrcEx[(srcImageImpl->m_left + j) * 4 + 2];
HGByte v = (r * 76 + g * 150 + b * 30) >> 8;
SetBit(pDestEx, destImageImpl->m_left + j, (v >= 128 ? 1 : 0));
}
}
}
else if (HGBASE_IMGTYPE_RGBA == srcImageImpl->m_type)
{
for (int32_t i = 0; i < (int32_t)(srcImageImpl->m_bottom - srcImageImpl->m_top); ++i)
{
HGByte* pSrcEx = src + (HGSize)i * (HGSize)srcStep;
HGByte* pDestEx = dest + (HGSize)i * (HGSize)destStep;
for (int32_t j = 0; j < (int32_t)(srcImageImpl->m_right - srcImageImpl->m_left); ++j)
{
HGInt r = pSrcEx[(srcImageImpl->m_left + j) * 4];
HGInt g = pSrcEx[(srcImageImpl->m_left + j) * 4 + 1];
HGInt b = pSrcEx[(srcImageImpl->m_left + j) * 4 + 2];
HGByte v = (r * 76 + g * 150 + b * 30) >> 8;
SetBit(pDestEx, destImageImpl->m_left + j, (v >= 128 ? 1 : 0));
}
}
}
}
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;
}
if (HGBASE_IMGTYPE_BINARY == type || HGBASE_IMGTYPE_BINARY == destType)
{
return CopyImageWithBinary(imageImpl, destImageImpl);
}
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;
}