2022-05-03 10:25:52 +00:00
|
|
|
|
#include "HGJpeg.h"
|
|
|
|
|
#include "../base/HGInc.h"
|
|
|
|
|
#include "../base/HGInfo.h"
|
|
|
|
|
extern "C"
|
|
|
|
|
{
|
|
|
|
|
#include "jpeglib.h"
|
|
|
|
|
#include "jmemsys.h"
|
|
|
|
|
};
|
|
|
|
|
|
2022-10-12 03:35:09 +00:00
|
|
|
|
struct my_error_mgr
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
struct jpeg_error_mgr pub;
|
|
|
|
|
jmp_buf setjmp_buffer;
|
2022-10-12 03:35:09 +00:00
|
|
|
|
};
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
METHODDEF(void) my_error_exit(j_common_ptr cinfo)
|
|
|
|
|
{
|
2022-10-12 03:35:09 +00:00
|
|
|
|
my_error_mgr* myerr = (my_error_mgr*)cinfo->err;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
(*cinfo->err->output_message)(cinfo);
|
|
|
|
|
longjmp(myerr->setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_CheckJpegFile(const HGChar* fileName, HGBool* isJpeg)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == fileName || NULL == isJpeg)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGJpegLoadInfo info;
|
|
|
|
|
HGResult ret = HGImgFmt_LoadJpegImage(fileName, &info, 0, 0, NULL);
|
|
|
|
|
*isJpeg = (HGBASE_ERR_OK == ret ? HGTRUE : HGFALSE);
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_LoadJpegImage(const HGChar* fileName, HGJpegLoadInfo* info,
|
|
|
|
|
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == fileName)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL == image)
|
|
|
|
|
{
|
|
|
|
|
if (0 != imgType || 0 != imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
if (0 != imgType && HGBASE_IMGTYPE_BINARY != imgType && HGBASE_IMGTYPE_GRAY != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_BGR != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_BGRA != imgType && HGBASE_IMGTYPE_RGBA != imgType)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE* file = fopen(fileName, "rb");
|
|
|
|
|
if (NULL == file)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct jpeg_decompress_struct cinfo;
|
|
|
|
|
struct my_error_mgr jerr;
|
|
|
|
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
|
|
|
|
jerr.pub.error_exit = my_error_exit;
|
|
|
|
|
|
|
|
|
|
HGImage image2 = NULL;
|
|
|
|
|
|
|
|
|
|
int jmpResult = setjmp(jerr.setjmp_buffer);
|
|
|
|
|
if (0 != jmpResult)
|
|
|
|
|
{
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return (HGResult)jmpResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
jpeg_stdio_src(&cinfo, file);
|
|
|
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
info->width = cinfo.image_width;
|
|
|
|
|
info->height = cinfo.image_height;
|
|
|
|
|
info->numComponents = cinfo.num_components;
|
|
|
|
|
info->colorSpace = cinfo.jpeg_color_space;
|
|
|
|
|
info->densityUnit = cinfo.density_unit;
|
|
|
|
|
info->xDensity = cinfo.X_density;
|
|
|
|
|
info->yDensity = cinfo.Y_density;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != image)
|
|
|
|
|
{
|
|
|
|
|
if (0 == imgType)
|
|
|
|
|
{
|
|
|
|
|
if (JCS_GRAYSCALE != cinfo.out_color_space)
|
|
|
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
|
|
|
else
|
|
|
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (0 == imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
cinfo.out_color_space = JCS_RGB;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_start_decompress(&cinfo);
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CreateImage(cinfo.output_width, cinfo.output_height,
|
|
|
|
|
HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2))
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (1 == cinfo.density_unit)
|
|
|
|
|
{
|
|
|
|
|
HGBase_SetImageDpi(image2, cinfo.X_density, cinfo.Y_density);
|
|
|
|
|
}
|
2022-05-13 03:56:46 +00:00
|
|
|
|
else if (2 == cinfo.density_unit)
|
|
|
|
|
{
|
|
|
|
|
uint32_t xDpi = (uint32_t)(cinfo.X_density / 0.393700787402 + 0.5);
|
|
|
|
|
uint32_t yDpi = (uint32_t)(cinfo.Y_density / 0.393700787402 + 0.5);
|
|
|
|
|
HGBase_SetImageDpi(image2, xDpi, yDpi);
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image2, &imgInfo);
|
|
|
|
|
uint8_t* data;
|
|
|
|
|
HGBase_GetImageData(image2, &data);
|
|
|
|
|
|
|
|
|
|
while (cinfo.output_scanline < cinfo.output_height)
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
JSAMPROW pEx = data + (HGSize)cinfo.output_scanline * (HGSize)imgInfo.widthStep;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_read_scanlines(&cinfo, &pEx, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jpeg_finish_decompress(&cinfo);
|
2022-05-26 03:16:59 +00:00
|
|
|
|
|
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CloneImage(image2, imgType, imgOrigin, image))
|
|
|
|
|
{
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_LoadJpegImageFromBuffer(HGBuffer buffer, HGJpegLoadInfo* info,
|
|
|
|
|
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == buffer)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL == image)
|
|
|
|
|
{
|
|
|
|
|
if (0 != imgType || 0 != imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
if (0 != imgType && HGBASE_IMGTYPE_BINARY != imgType && HGBASE_IMGTYPE_GRAY != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_BGR != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_BGRA != imgType && HGBASE_IMGTYPE_RGBA != imgType)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct jpeg_decompress_struct cinfo;
|
|
|
|
|
struct my_error_mgr jerr;
|
|
|
|
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
|
|
|
|
jerr.pub.error_exit = my_error_exit;
|
|
|
|
|
|
|
|
|
|
HGImage image2 = NULL;
|
|
|
|
|
|
|
|
|
|
int jmpResult = setjmp(jerr.setjmp_buffer);
|
|
|
|
|
if (0 != jmpResult)
|
|
|
|
|
{
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
|
return (HGResult)jmpResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGByte* memAddr = NULL;
|
|
|
|
|
HGBase_GetBufferData(buffer, &memAddr);
|
|
|
|
|
HGUSize size = 0;
|
|
|
|
|
HGBase_GetBufferSize(buffer, &size);
|
|
|
|
|
|
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
jpeg_mem_src(&cinfo, memAddr, (unsigned long)size);
|
|
|
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
info->width = cinfo.image_width;
|
|
|
|
|
info->height = cinfo.image_height;
|
|
|
|
|
info->numComponents = cinfo.num_components;
|
|
|
|
|
info->colorSpace = cinfo.jpeg_color_space;
|
|
|
|
|
info->densityUnit = cinfo.density_unit;
|
|
|
|
|
info->xDensity = cinfo.X_density;
|
|
|
|
|
info->yDensity = cinfo.Y_density;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != image)
|
|
|
|
|
{
|
|
|
|
|
if (0 == imgType)
|
|
|
|
|
{
|
|
|
|
|
if (JCS_GRAYSCALE != cinfo.out_color_space)
|
|
|
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
|
|
|
else
|
|
|
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (0 == imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
cinfo.out_color_space = JCS_RGB;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_start_decompress(&cinfo);
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CreateImage(cinfo.output_width, cinfo.output_height,
|
|
|
|
|
HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2))
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (1 == cinfo.density_unit)
|
|
|
|
|
{
|
|
|
|
|
HGBase_SetImageDpi(image2, cinfo.X_density, cinfo.Y_density);
|
|
|
|
|
}
|
2022-05-13 03:56:46 +00:00
|
|
|
|
else if (2 == cinfo.density_unit)
|
|
|
|
|
{
|
|
|
|
|
uint32_t xDpi = (uint32_t)(cinfo.X_density / 0.393700787402 + 0.5);
|
|
|
|
|
uint32_t yDpi = (uint32_t)(cinfo.Y_density / 0.393700787402 + 0.5);
|
|
|
|
|
HGBase_SetImageDpi(image2, xDpi, yDpi);
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image2, &imgInfo);
|
|
|
|
|
uint8_t* data;
|
|
|
|
|
HGBase_GetImageData(image2, &data);
|
|
|
|
|
|
|
|
|
|
while (cinfo.output_scanline < cinfo.output_height)
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
JSAMPROW pEx = data + (HGSize)cinfo.output_scanline * (HGSize)imgInfo.widthStep;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_read_scanlines(&cinfo, &pEx, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jpeg_finish_decompress(&cinfo);
|
2022-05-26 03:16:59 +00:00
|
|
|
|
|
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CloneImage(image2, imgType, imgOrigin, image))
|
|
|
|
|
{
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-13 03:56:46 +00:00
|
|
|
|
HGResult HGAPI HGImgFmt_SaveJpegImage(HGImage image, const HGJpegSaveInfo* info, const HGChar* fileName)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
2022-05-13 03:56:46 +00:00
|
|
|
|
if (NULL == image || NULL == fileName)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
// 判断info参数的合法性
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE* file = fopen(fileName, "wb");
|
|
|
|
|
if (NULL == file)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct jpeg_compress_struct cinfo;
|
|
|
|
|
struct my_error_mgr jerr;
|
|
|
|
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
|
|
|
|
jerr.pub.error_exit = my_error_exit;
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGImage image2 = NULL;
|
|
|
|
|
HGImageRoi roi;
|
|
|
|
|
HGBase_GetImageROI(image, &roi);
|
|
|
|
|
|
2022-05-03 10:25:52 +00:00
|
|
|
|
int jmpResult = setjmp(jerr.setjmp_buffer);
|
|
|
|
|
if (0 != jmpResult)
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_SetImageROI(image, &roi);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return (HGResult)jmpResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jpeg_create_compress(&cinfo);
|
|
|
|
|
jpeg_stdio_dest(&cinfo, file);
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_ResetImageROI(image);
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == imgInfo.type || HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
|
|
|
{
|
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2))
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2))
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGBase_GetImageInfo(image2, &imgInfo);
|
2022-05-03 10:25:52 +00:00
|
|
|
|
uint32_t width = imgInfo.width;
|
|
|
|
|
uint32_t height = imgInfo.height;
|
2022-05-26 03:16:59 +00:00
|
|
|
|
uint32_t type = imgInfo.type;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
uint32_t widthStep = imgInfo.widthStep;
|
|
|
|
|
uint8_t* data;
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_GetImageData(image2, &data);
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
cinfo.image_width = width;
|
|
|
|
|
cinfo.image_height = height;
|
|
|
|
|
cinfo.input_components = (HGBASE_IMGTYPE_GRAY != type) ? 3 : 1;
|
|
|
|
|
cinfo.in_color_space = (HGBASE_IMGTYPE_GRAY != type) ? JCS_RGB : JCS_GRAYSCALE;
|
|
|
|
|
jpeg_set_defaults(&cinfo);
|
|
|
|
|
|
2022-05-13 12:38:58 +00:00
|
|
|
|
int quality;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
2022-05-13 03:56:46 +00:00
|
|
|
|
quality = info->quality;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
cinfo.density_unit = info->densityUnit;
|
|
|
|
|
cinfo.X_density = info->xDensity;
|
|
|
|
|
cinfo.Y_density = info->yDensity;
|
|
|
|
|
}
|
2022-05-13 12:38:58 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
HGUInt xDpi, yDpi;
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_GetImageDpi(image2, &xDpi, &yDpi);
|
2022-05-13 12:38:58 +00:00
|
|
|
|
quality = 80;
|
|
|
|
|
cinfo.density_unit = 1;
|
|
|
|
|
cinfo.X_density = xDpi;
|
|
|
|
|
cinfo.Y_density = yDpi;
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
jpeg_set_quality(&cinfo, (int)quality, TRUE);
|
|
|
|
|
jpeg_start_compress(&cinfo, TRUE);
|
|
|
|
|
|
|
|
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
uint8_t* pEx = data + (HGSize)cinfo.next_scanline * (HGSize)imgInfo.widthStep;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_write_scanlines(&cinfo, &pEx, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jpeg_finish_compress(&cinfo);
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_SetImageROI(image, &roi);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-13 03:56:46 +00:00
|
|
|
|
HGResult HGAPI HGImgFmt_SaveJpegImageToBuffer(HGImage image, const HGJpegSaveInfo* info, HGBuffer* buffer)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
2022-05-13 03:56:46 +00:00
|
|
|
|
if (NULL == image || NULL == buffer)
|
2022-05-03 10:25:52 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
// 判断info参数的合法性
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned char* outbuffer = NULL;
|
|
|
|
|
size_t outSize = 0;
|
|
|
|
|
|
|
|
|
|
struct jpeg_compress_struct cinfo;
|
|
|
|
|
struct my_error_mgr jerr;
|
|
|
|
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
|
|
|
|
jerr.pub.error_exit = my_error_exit;
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGImage image2 = NULL;
|
|
|
|
|
HGImageRoi roi;
|
|
|
|
|
HGBase_GetImageROI(image, &roi);
|
|
|
|
|
|
2022-05-03 10:25:52 +00:00
|
|
|
|
int jmpResult = setjmp(jerr.setjmp_buffer);
|
|
|
|
|
if (0 != jmpResult)
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_SetImageROI(image, &roi);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
2022-05-26 03:16:59 +00:00
|
|
|
|
// 只有libjpeg为静态库的时候,才能用free
|
|
|
|
|
// 否则应该使用jpeg_free_large(NULL, outbuffer, 0);
|
|
|
|
|
jpeg_free_large(NULL, outbuffer, 0);
|
2022-05-03 10:25:52 +00:00
|
|
|
|
return (HGResult)jmpResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jpeg_create_compress(&cinfo);
|
|
|
|
|
jpeg_mem_dest(&cinfo, &outbuffer, &outSize);
|
|
|
|
|
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_ResetImageROI(image);
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == imgInfo.type || HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
|
|
|
{
|
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2))
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2))
|
|
|
|
|
longjmp(jerr.setjmp_buffer, (int)HGBASE_ERR_FAIL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGBase_GetImageInfo(image2, &imgInfo);
|
2022-05-03 10:25:52 +00:00
|
|
|
|
uint32_t width = imgInfo.width;
|
|
|
|
|
uint32_t height = imgInfo.height;
|
2022-05-26 03:16:59 +00:00
|
|
|
|
uint32_t type = imgInfo.type;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
uint32_t widthStep = imgInfo.widthStep;
|
|
|
|
|
uint8_t* data;
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_GetImageData(image2, &data);
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
cinfo.image_width = width;
|
|
|
|
|
cinfo.image_height = height;
|
|
|
|
|
cinfo.input_components = (HGBASE_IMGTYPE_GRAY != type) ? 3 : 1;
|
|
|
|
|
cinfo.in_color_space = (HGBASE_IMGTYPE_GRAY != type) ? JCS_RGB : JCS_GRAYSCALE;
|
|
|
|
|
jpeg_set_defaults(&cinfo);
|
|
|
|
|
|
2022-05-13 12:38:58 +00:00
|
|
|
|
int quality;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
2022-05-13 03:56:46 +00:00
|
|
|
|
quality = info->quality;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
cinfo.density_unit = info->densityUnit;
|
|
|
|
|
cinfo.X_density = info->xDensity;
|
|
|
|
|
cinfo.Y_density = info->yDensity;
|
|
|
|
|
}
|
2022-05-13 12:38:58 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
HGUInt xDpi, yDpi;
|
2022-05-26 03:16:59 +00:00
|
|
|
|
HGBase_GetImageDpi(image2, &xDpi, &yDpi);
|
2022-05-13 12:38:58 +00:00
|
|
|
|
quality = 80;
|
|
|
|
|
cinfo.density_unit = 1;
|
|
|
|
|
cinfo.X_density = xDpi;
|
|
|
|
|
cinfo.Y_density = yDpi;
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
jpeg_set_quality(&cinfo, (int)quality, TRUE);
|
|
|
|
|
jpeg_start_compress(&cinfo, TRUE);
|
|
|
|
|
|
|
|
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
|
|
|
{
|
2022-05-26 03:16:59 +00:00
|
|
|
|
uint8_t* pEx = data + (HGSize)cinfo.next_scanline * (HGSize)imgInfo.widthStep;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_write_scanlines(&cinfo, &pEx, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jpeg_finish_compress(&cinfo);
|
2022-05-26 03:16:59 +00:00
|
|
|
|
|
|
|
|
|
HGBase_SetImageROI(image, &roi);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
image2 = NULL;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
|
|
|
|
|
|
HGResult ret = HGBase_CreateBuffer(outSize, buffer);
|
|
|
|
|
if (HGBASE_ERR_OK == ret)
|
|
|
|
|
{
|
|
|
|
|
HGByte* bufferData = NULL;
|
|
|
|
|
HGBase_GetBufferData(*buffer, &bufferData);
|
|
|
|
|
memcpy(bufferData, outbuffer, outSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 只有libjpeg为静态库的时候,才能用free
|
|
|
|
|
// 否则应该使用jpeg_free_large(NULL, outbuffer, 0);
|
|
|
|
|
jpeg_free_large(NULL, outbuffer, 0);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|