485 lines
14 KiB
C++
485 lines
14 KiB
C++
#include "HGImgProc.h"
|
|
#include "./ImageProcess/ImageApplyAdjustColors.h"
|
|
#include "./ImageProcess/ImageApplyAutoCrop.h"
|
|
#include "./ImageProcess/ImageApplyDiscardBlank.h"
|
|
#include "CvxText.hpp"
|
|
#include "../base/HGInc.h"
|
|
#include "../base/HGUtility.h"
|
|
|
|
HGResult HGAPI HGImgProc_ResizeImage(HGImage image, HGImage destImage, HGUInt interp)
|
|
{
|
|
if (NULL == image || NULL == destImage || image == destImage)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (HGIMGPROC_INTERPOTYPE_NN != interp && HGIMGPROC_INTERPOTYPE_LINEAR != interp)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGImageInfo imgInfo;
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
HGImageInfo destImgInfo;
|
|
HGBase_GetImageInfo(destImage, &destImgInfo);
|
|
|
|
uint32_t type = imgInfo.type;
|
|
uint32_t destType = destImgInfo.type;
|
|
if (type != destType)
|
|
{
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
}
|
|
|
|
HGByte* data = NULL;
|
|
HGBase_GetImageData(image, &data);
|
|
HGByte* destData = NULL;
|
|
HGBase_GetImageData(destImage, &destData);
|
|
|
|
HGImageRoi roi;
|
|
HGBase_GetImageROI(image, &roi);
|
|
HGImageRoi destRoi;
|
|
HGBase_GetImageROI(destImage, &destRoi);
|
|
|
|
HGUInt roiWidth = roi.right - roi.left;
|
|
HGUInt roiHeight = roi.bottom - roi.top;
|
|
HGUInt destRoiWidth = destRoi.right - destRoi.left;
|
|
HGUInt destRoiHeight = destRoi.bottom - destRoi.top;
|
|
|
|
if (roiWidth == destRoiWidth && roiHeight == destRoiHeight)
|
|
{
|
|
return HGBase_CopyImage(image, destImage);
|
|
}
|
|
|
|
if (HGBASE_IMGTYPE_BINARY == type)
|
|
{
|
|
HGImage imageTmp1 = NULL;
|
|
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp1);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
HGImage imageTmp2 = NULL;
|
|
ret = HGBase_CreateImage(destRoiWidth, destRoiHeight, HGBASE_IMGTYPE_GRAY, imgInfo.origin, &imageTmp2);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
ret = HGImgProc_ResizeImage(imageTmp1, imageTmp2, interp);
|
|
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;
|
|
|
|
uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
p = data + (imgInfo.height - roi.bottom) * imgInfo.widthStep + roi.left * channels;
|
|
|
|
uint8_t* pDest = destData + destRoi.top * destImgInfo.widthStep + destRoi.left * channels;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == destImgInfo.origin)
|
|
pDest = destData + (destImgInfo.height - destRoi.bottom) * destImgInfo.widthStep + destRoi.left * channels;
|
|
|
|
IplImage* pImg = cvCreateImageHeader(cvSize(roiWidth, roiHeight), IPL_DEPTH_8U, channels);
|
|
IplImage* pImgDest = cvCreateImageHeader(cvSize(destRoiWidth, destRoiHeight), IPL_DEPTH_8U, channels);
|
|
cvSetData(pImg, p, imgInfo.widthStep);
|
|
cvSetData(pImgDest, pDest, destImgInfo.widthStep);
|
|
int interpolation = (HGIMGPROC_INTERPOTYPE_NN == interp) ? CV_INTER_NN : CV_INTER_LINEAR;
|
|
cvResize(pImg, pImgDest, interpolation);
|
|
cvReleaseImageHeader(&pImgDest);
|
|
cvReleaseImageHeader(&pImg);
|
|
|
|
if (imgInfo.origin != destImgInfo.origin)
|
|
{
|
|
HGBase_ImageFlip(destImage, destImage);
|
|
}
|
|
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGAPI HGImgProc_ImageAdjustColors(HGImage image, HGImage destImage,
|
|
HGInt brightness, HGInt contrast, HGFloat gamma)
|
|
{
|
|
if (NULL == image)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGImageInfo imgInfo;
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
HGUInt type = imgInfo.type;
|
|
|
|
HGByte* data = NULL;
|
|
HGBase_GetImageData(image, &data);
|
|
|
|
HGImageRoi roi;
|
|
HGBase_GetImageROI(image, &roi);
|
|
HGUInt roiWidth = roi.right - roi.left;
|
|
HGUInt roiHeight = roi.bottom - roi.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;
|
|
|
|
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 = HGImgProc_ImageAdjustColors(imageTmp, imageTmp, brightness, contrast, gamma);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
ret = HGBase_CopyImage(imageTmp, image);
|
|
}
|
|
|
|
HGBase_DestroyImage(imageTmp);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
p = data + (imgInfo.height - roi.bottom) * imgInfo.widthStep + roi.left * channels;
|
|
|
|
cv::Mat img(roiHeight, roiWidth, CV_8UC(channels), p, imgInfo.widthStep);
|
|
CImageApplyAdjustColors imgApply(brightness, contrast, gamma);
|
|
imgApply.apply(img, 0);
|
|
}
|
|
else
|
|
{
|
|
HGImageInfo destImgInfo;
|
|
HGBase_GetImageInfo(destImage, &destImgInfo);
|
|
HGUInt destType = destImgInfo.type;
|
|
if (type != destType)
|
|
{
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
}
|
|
|
|
HGByte* destData = NULL;
|
|
HGBase_GetImageData(destImage, &destData);
|
|
|
|
HGImageRoi destRoi;
|
|
HGBase_GetImageROI(destImage, &destRoi);
|
|
HGUInt destRoiWidth = destRoi.right - destRoi.left;
|
|
HGUInt destRoiHeight = destRoi.bottom - destRoi.top;
|
|
|
|
if (roiWidth != destRoiWidth || roiHeight != destRoiHeight)
|
|
{
|
|
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 = HGImgProc_ImageAdjustColors(imageTmp, imageTmp, brightness, contrast, gamma);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
ret = HGBase_CopyImage(imageTmp, destImage);
|
|
}
|
|
|
|
HGBase_DestroyImage(imageTmp);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HGBase_CopyImage(image, destImage);
|
|
|
|
uint8_t* pDest = destData + destRoi.top * destImgInfo.widthStep + destRoi.left * channels;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == destImgInfo.origin)
|
|
pDest = destData + (destImgInfo.height - destRoi.bottom) * destImgInfo.widthStep + destRoi.left * channels;
|
|
|
|
cv::Mat destImg(destRoiHeight, destRoiWidth, CV_8UC(channels), pDest, destImgInfo.widthStep);
|
|
CImageApplyAdjustColors imgApply(brightness, contrast, gamma);
|
|
imgApply.apply(destImg, 0);
|
|
}
|
|
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGAPI HGImgProc_ImageAutoCrop(HGImage image, HGBool autoCrop, HGBool deskew, HGBool fillBlank, const HGImgAutoCropParam* param,
|
|
HGUInt destWidth, HGUInt destHeight, HGUInt destType, HGUInt destOrigin, HGImage* destImage)
|
|
{
|
|
if (NULL == image || NULL == destImage)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGImageInfo imgInfo;
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_RGBA == imgInfo.type
|
|
|| HGBASE_IMGTYPE_BGRA == imgInfo.type)
|
|
{
|
|
HGImage imageTmp = NULL;
|
|
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, 0, &imageTmp);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
if (0 == destType)
|
|
destType = imgInfo.type;
|
|
if (0 == destOrigin)
|
|
destOrigin = imgInfo.origin;
|
|
|
|
ret = HGImgProc_ImageAutoCrop(imageTmp, autoCrop, deskew, fillBlank, param,
|
|
destWidth, destHeight, destType, destOrigin, destImage);
|
|
HGBase_DestroyImage(imageTmp);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool convex = true;
|
|
bool fillColor = false;
|
|
double threshold = 40.0;
|
|
int noise = 8;
|
|
int indent = 5;
|
|
bool normalCrop = false;
|
|
bool dispersion = true;
|
|
|
|
if (NULL != param)
|
|
{
|
|
convex = (bool)param->convex;
|
|
fillColor = (bool)param->fillColor;
|
|
threshold = param->threshold;
|
|
noise = param->noise;
|
|
indent = param->indent;
|
|
normalCrop = (bool)param->normalCrop;
|
|
dispersion = (bool)param->dispersion;
|
|
}
|
|
|
|
HGByte* data = NULL;
|
|
HGBase_GetImageData(image, &data);
|
|
|
|
HGImageRoi roi;
|
|
HGBase_GetImageROI(image, &roi);
|
|
HGUInt roiWidth = roi.right - roi.left;
|
|
HGUInt roiHeight = roi.bottom - roi.top;
|
|
|
|
uint32_t channels = 1;
|
|
if (HGBASE_IMGTYPE_RGB == imgInfo.type || HGBASE_IMGTYPE_BGR == imgInfo.type)
|
|
channels = 3;
|
|
|
|
uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
p = data + (imgInfo.height - roi.bottom) * imgInfo.widthStep + roi.left * channels;
|
|
|
|
cv::Mat img(roiHeight, roiWidth, CV_8UC(channels), p, imgInfo.widthStep);
|
|
|
|
cv::Mat destImg;
|
|
autoCrop_desaskew_fillBlank(img, destImg, autoCrop, deskew, fillBlank, destWidth, destHeight,
|
|
convex, fillColor, threshold, noise, indent, normalCrop, dispersion);
|
|
if (destImg.empty())
|
|
{
|
|
return HGIMGPROC_ERR_FAIL;
|
|
}
|
|
|
|
HGImageInfo newImgInfo;
|
|
newImgInfo.width = (HGUInt)destImg.cols;
|
|
newImgInfo.height = (HGUInt)destImg.rows;
|
|
newImgInfo.type = imgInfo.type;
|
|
newImgInfo.widthStep = (HGUInt)destImg.step;
|
|
newImgInfo.origin = imgInfo.origin;
|
|
|
|
if (0 == destType)
|
|
destType = imgInfo.type;
|
|
if (0 == destOrigin)
|
|
destOrigin = imgInfo.origin;
|
|
|
|
return HGBase_CreateImageFromData(destImg.data, &newImgInfo, NULL, destType, destOrigin, destImage);
|
|
}
|
|
|
|
HGResult HGAPI HGImgProc_ImageBlankCheck(HGImage image, const HGImgBlankCheckParam* param, HGBool* blank)
|
|
{
|
|
if (NULL == image || NULL == blank)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGImageInfo imgInfo;
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_RGBA == imgInfo.type
|
|
|| HGBASE_IMGTYPE_BGRA == imgInfo.type)
|
|
{
|
|
HGImage imageTmp = NULL;
|
|
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, 0, &imageTmp);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
ret = HGImgProc_ImageBlankCheck(imageTmp, param, blank);
|
|
HGBase_DestroyImage(imageTmp);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HGDouble threshold = 40.0;
|
|
HGInt edge = 150;
|
|
HGInt blockSize = 10;
|
|
HGDouble devTh = 50.0;
|
|
HGDouble meanTh = 200.0;
|
|
|
|
if (NULL != param)
|
|
{
|
|
threshold = param->threshold;
|
|
edge = param->edge;
|
|
blockSize = param->blockSize;
|
|
devTh = param->devTh;
|
|
meanTh = param->meanTh;
|
|
}
|
|
|
|
HGByte* data = NULL;
|
|
HGBase_GetImageData(image, &data);
|
|
|
|
HGImageRoi roi;
|
|
HGBase_GetImageROI(image, &roi);
|
|
HGUInt roiWidth = roi.right - roi.left;
|
|
HGUInt roiHeight = roi.bottom - roi.top;
|
|
|
|
uint32_t channels = 1;
|
|
if (HGBASE_IMGTYPE_BGR == imgInfo.type || HGBASE_IMGTYPE_RGB == imgInfo.type)
|
|
channels = 3;
|
|
|
|
uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
p = data + (imgInfo.height - roi.bottom) * imgInfo.widthStep + roi.left * channels;
|
|
|
|
cv::Mat img(roiHeight, roiWidth, CV_8UC(channels), p, imgInfo.widthStep);
|
|
|
|
bool ret = CImageApplyDiscardBlank::apply(img, threshold, edge, blockSize, devTh, meanTh);
|
|
*blank = ret ? HGTRUE : HGFALSE;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGAPI HGImgProc_ImageDrawLine(HGImage image, HGInt x1, HGInt y1, HGInt x2, HGInt y2,
|
|
HGColor color, HGUInt width, HGUInt type)
|
|
{
|
|
if (NULL == image || 0 == width || type < HGIMGPROC_LINETYPE_SOLID || type > HGIMGPROC_LINETYPE_DASH)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGImageInfo imgInfo;
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
if (HGBASE_IMGTYPE_BINARY == imgInfo.type || HGBASE_IMGTYPE_GRAY == imgInfo.type)
|
|
{
|
|
HGImage imageTmp = NULL;
|
|
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, 0, &imageTmp);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
ret = HGImgProc_ImageDrawLine(imageTmp, x1, y1, x2, y2, color, width, type);
|
|
if (HGBASE_ERR_OK == ret)
|
|
{
|
|
ret = HGBase_CopyImage(imageTmp, image);
|
|
}
|
|
|
|
HGBase_DestroyImage(imageTmp);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HGByte* data = NULL;
|
|
HGBase_GetImageData(image, &data);
|
|
|
|
HGImageRoi roi;
|
|
HGBase_GetImageROI(image, &roi);
|
|
HGUInt roiWidth = roi.right - roi.left;
|
|
HGUInt roiHeight = roi.bottom - roi.top;
|
|
|
|
uint32_t channels = 3;
|
|
if (HGBASE_IMGTYPE_BGRA == imgInfo.type || HGBASE_IMGTYPE_RGBA == imgInfo.type)
|
|
channels = 4;
|
|
|
|
uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
p = data + (imgInfo.height - roi.bottom) * imgInfo.widthStep + roi.left * channels;
|
|
|
|
IplImage* pImg = cvCreateImageHeader(cvSize(roiWidth, roiHeight), IPL_DEPTH_8U, channels);
|
|
cvSetData(pImg, p, imgInfo.widthStep);
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
{
|
|
y1 = roiHeight - y1 - 1;
|
|
y2 = roiHeight - y2 - 1;
|
|
}
|
|
|
|
HGUInt r = HG_GETCOLOR_R(color);
|
|
HGUInt g = HG_GETCOLOR_G(color);
|
|
HGUInt b = HG_GETCOLOR_B(color);
|
|
if (HGBASE_IMGTYPE_BGR == imgInfo.type || HGBASE_IMGTYPE_BGRA == imgInfo.type)
|
|
{
|
|
r = HG_GETCOLOR_B(color);
|
|
g = HG_GETCOLOR_G(color);
|
|
b = HG_GETCOLOR_R(color);
|
|
}
|
|
|
|
cvLine(pImg, cvPoint(x1, y1), cvPoint(x2, y2), cvScalar(r, g, b), width);
|
|
cvReleaseImageHeader(&pImg);
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGAPI HGImgProc_AddImageWatermark(HGImage image, const HGChar* text, HGColor color, HGUInt posType,
|
|
HGInt locationX, HGInt locationY, const HGImgWatermarkFontParam *fontParam)
|
|
{
|
|
if (NULL == image || NULL == text || '\0' == *text || posType < HGIMGPROC_WMPOSTYPE_LEFT
|
|
|| posType > HGIMGPROC_WMPOSTYPE_LOCATION)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
std::string fontName = "宋体";
|
|
HGUInt fontSize = 20;
|
|
HGBool bold = HGFALSE;
|
|
HGBool underline = HGFALSE;
|
|
HGBool italic = HGFALSE;
|
|
HGBool strikeout = HGFALSE;
|
|
|
|
if (NULL != fontParam)
|
|
{
|
|
if (0 == fontParam->fontSize)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
fontName = fontParam->foneName;
|
|
fontSize = fontParam->fontSize;
|
|
bold = fontParam->bold;
|
|
underline = fontParam->underline;
|
|
italic = fontParam->italic;
|
|
strikeout = fontParam->strikeout;
|
|
}
|
|
|
|
HGChar moduleName[256];
|
|
HGBase_GetModuleName((void *)HGImgProc_AddImageWatermark, moduleName, 256);
|
|
HGChar modulePath[256];
|
|
HGBase_GetFilePath(moduleName, modulePath, 256);
|
|
HGChar fontPath[256];
|
|
sprintf(fontPath, "%s%s.ttf", modulePath, fontName.c_str());
|
|
|
|
CvxText cvxText;
|
|
HGResult ret = cvxText.Create(fontPath);
|
|
if (HGBASE_ERR_OK != ret)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
ret = cvxText.DrawString(image, text, color, posType, locationX, locationY, fontSize, bold, underline, italic, strikeout);
|
|
return ret;
|
|
}
|