#include "HGImage.h" #include "HGInc.h" #if defined(HG_CMP_MSC) #include #include #include #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; }