3197 lines
78 KiB
C++
3197 lines
78 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 = 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;
|
|
}
|
|
|
|
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
|
|
{
|
|
HGUInt type2 = HGBASE_IMGTYPE_BGR;
|
|
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)pImage->GetHorizontalResolution();
|
|
HGUInt yDpi = (HGUInt)pImage->GetVerticalResolution();
|
|
HGBase_SetImageDpi(*image, xDpi, yDpi);
|
|
}
|
|
|
|
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);
|
|
|
|
ULONG_PTR nToken = 0;
|
|
Gdiplus::GdiplusStartupInput input;
|
|
Gdiplus::GdiplusStartupOutput output;
|
|
Gdiplus::GdiplusStartup(&nToken, &input, &output);
|
|
assert(0 != nToken);
|
|
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|