269 lines
7.0 KiB
C++
269 lines
7.0 KiB
C++
|
#include "HGImgProc.h"
|
|||
|
#include "hg_imageprocess.hpp"
|
|||
|
#include <opencv2/opencv.hpp>
|
|||
|
#include "../base/HGInc.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);
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
uint8_t* pDest = destData + destRoi.top * 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;
|
|||
|
|
|||
|
brightness = cv::max(-255, cv::min(brightness, 255));
|
|||
|
contrast = cv::max(-127, cv::min(contrast, 127));
|
|||
|
gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
|
|||
|
|
|||
|
cv::Mat lut(1, 256, CV_8UC1);
|
|||
|
|
|||
|
uchar* ptr = lut.data;
|
|||
|
for (int i = 0; i < 256; i++)
|
|||
|
{
|
|||
|
//update brightness
|
|||
|
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(i + brightness, 255)));
|
|||
|
|
|||
|
//update contrast
|
|||
|
if (ptr[i] < 128)
|
|||
|
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(ptr[i] - contrast, 127)));
|
|||
|
else
|
|||
|
ptr[i] = static_cast<unsigned char>(cv::max(127, cv::min(ptr[i] + contrast, 255)));
|
|||
|
}
|
|||
|
|
|||
|
float g = 1.0f / gamma;
|
|||
|
for (int i = 0; i < 256; i++)
|
|||
|
{
|
|||
|
ptr[i] = static_cast<unsigned char>(cv::min(255,
|
|||
|
static_cast<int>(cv::pow(static_cast<float>(ptr[i]) / 255.0f, g) * 255.0f + 0.5f)));
|
|||
|
}
|
|||
|
|
|||
|
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;
|
|||
|
|
|||
|
uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels;
|
|||
|
cv::Mat img(roiHeight, roiWidth, CV_8UC(channels), p, imgInfo.widthStep);
|
|||
|
|
|||
|
if (NULL == destImage || image == destImage)
|
|||
|
{
|
|||
|
if (brightness == 0 && contrast == 0 && gamma > 0.999999f && gamma < 1.000001f)
|
|||
|
{
|
|||
|
// 什么也不做
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
cv::LUT(img, lut, img);
|
|||
|
}
|
|||
|
}
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
uint8_t* pDest = destData + destRoi.top * destImgInfo.widthStep + destRoi.left * channels;
|
|||
|
cv::Mat destImg(destRoiHeight, destRoiWidth, CV_8UC(channels), pDest, destImgInfo.widthStep);
|
|||
|
|
|||
|
if (brightness == 0 && contrast == 0 && gamma > 0.999999f && gamma < 1.000001f)
|
|||
|
{
|
|||
|
HGBase_CopyImage(image, destImage);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
cv::LUT(img, lut, destImg);
|
|||
|
|
|||
|
if (imgInfo.origin != destImgInfo.origin)
|
|||
|
{
|
|||
|
HGBase_ImageFlip(destImage, destImage);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return HGBASE_ERR_OK;
|
|||
|
}
|
|||
|
|
|||
|
HGResult HGAPI HGImgProc_ImageDeskew(HGImage image, HGBool autoCrop, HGBool deskew, const HGImgDeskewParam* 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_GRAY != imgInfo.type && HGBASE_IMGTYPE_RGB != imgInfo.type)
|
|||
|
{
|
|||
|
return HGBASE_ERR_INVALIDDATA;
|
|||
|
}
|
|||
|
|
|||
|
bool fillBlank = false;
|
|||
|
bool convex = true;
|
|||
|
bool colorBlank = false;
|
|||
|
double threshold = 40.0;
|
|||
|
int noise = 8;
|
|||
|
int indent = 5;
|
|||
|
|
|||
|
if (NULL != param)
|
|||
|
{
|
|||
|
if (param->fillBlank)
|
|||
|
{
|
|||
|
fillBlank = true;
|
|||
|
convex = (bool)param->convex;
|
|||
|
colorBlank = (bool)param->colorBlank;
|
|||
|
}
|
|||
|
|
|||
|
if (param->useParam)
|
|||
|
{
|
|||
|
threshold = param->threshold;
|
|||
|
noise = param->noise;
|
|||
|
indent = param->indent;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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)
|
|||
|
channels = 3;
|
|||
|
|
|||
|
uint8_t* p = data + roi.top * imgInfo.widthStep + roi.left * channels;
|
|||
|
HG_Image img(roiWidth, roiHeight, channels * 8, p, false, imgInfo.widthStep);
|
|||
|
HG_Image destImg = img.autoCrop_desaskew_fillBlank(autoCrop, deskew, fillBlank, destWidth, destHeight,
|
|||
|
convex, colorBlank, threshold, noise, indent);
|
|||
|
if (destImg.empty())
|
|||
|
{
|
|||
|
return HGIMGPROC_ERR_FAIL;
|
|||
|
}
|
|||
|
|
|||
|
HGUInt type = 0;
|
|||
|
if (!destImg.isMono())
|
|||
|
{
|
|||
|
if (destImg.depth() == 8)
|
|||
|
type = HGBASE_IMGTYPE_GRAY;
|
|||
|
else if (destImg.depth() == 24)
|
|||
|
type = HGBASE_IMGTYPE_RGB;
|
|||
|
else if (destImg.depth() == 32)
|
|||
|
type = HGBASE_IMGTYPE_RGBA;
|
|||
|
}
|
|||
|
|
|||
|
if (0 == type)
|
|||
|
{
|
|||
|
return HGIMGPROC_ERR_FAIL;
|
|||
|
}
|
|||
|
|
|||
|
HGImageInfo newImgInfo;
|
|||
|
newImgInfo.width = destImg.width();
|
|||
|
newImgInfo.height = destImg.height();
|
|||
|
newImgInfo.type = type;
|
|||
|
newImgInfo.widthStep = (HGUInt)destImg.step();
|
|||
|
newImgInfo.origin = imgInfo.origin;
|
|||
|
return HGBase_CreateImageFromData(destImg.data(), &newImgInfo, NULL, destType, destOrigin, destImage);
|
|||
|
}
|