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