723 lines
18 KiB
C++
723 lines
18 KiB
C++
#include "HGPng.h"
|
|
#include "../base/HGInc.h"
|
|
#include "png.h"
|
|
#include "pngstruct.h"
|
|
#include "pnginfo.h"
|
|
#include "pngpriv.h"
|
|
|
|
HGResult HGAPI HGImgFmt_CheckPngFile(const HGChar* fileName, HGBool* isPng)
|
|
{
|
|
if (NULL == fileName || NULL == isPng)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
HGPngLoadInfo info;
|
|
HGResult ret = HGImgFmt_LoadPngImage(fileName, &info, 0, 0, NULL);
|
|
*isPng = (HGBASE_ERR_OK == ret ? HGTRUE : HGFALSE);
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGAPI HGImgFmt_LoadPngImage(const HGChar* fileName, HGPngLoadInfo* 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
|
|
{
|
|
if (0 != imgType && HGBASE_IMGTYPE_GRAY != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
&& HGBASE_IMGTYPE_RGBA != imgType && HGBASE_IMGTYPE_BGR != imgType
|
|
&& HGBASE_IMGTYPE_BGRA != imgType)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
FILE* file = fopen(fileName, "rb");
|
|
if (NULL == file)
|
|
{
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
}
|
|
|
|
png_byte buf[8] = { 0 };
|
|
if (fread(buf, 1, 8, file) != 8)
|
|
{
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
if (0 != png_sig_cmp(buf, 0, 8))
|
|
{
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
if (NULL == png_ptr)
|
|
{
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
|
if (NULL == info_ptr)
|
|
{
|
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
HGImage image2 = NULL;
|
|
uint8_t* buffer = NULL;
|
|
uint8_t** rowPointers = NULL;
|
|
|
|
int jmpResult = setjmp(png_jmpbuf(png_ptr));
|
|
if (0 != jmpResult)
|
|
{
|
|
free(rowPointers);
|
|
rowPointers = NULL;
|
|
free(buffer);
|
|
buffer = NULL;
|
|
HGBase_DestroyImage(image2);
|
|
image2 = NULL;
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
fclose(file);
|
|
file = NULL;
|
|
return (HGResult)jmpResult;
|
|
}
|
|
|
|
#if defined(HG_CMP_MSC)
|
|
_fseeki64(file, 0, SEEK_SET);
|
|
#else
|
|
fseeko64(file, 0, SEEK_SET);
|
|
#endif
|
|
png_init_io(png_ptr, file);
|
|
png_read_info(png_ptr, info_ptr);
|
|
|
|
if (NULL != info)
|
|
{
|
|
info->width = info_ptr->width;
|
|
info->height = info_ptr->height;
|
|
info->bitDepth = info_ptr->bit_depth;
|
|
info->colorType = info_ptr->color_type;
|
|
info->channels = info_ptr->channels;
|
|
info->filterType = info_ptr->filter_type;
|
|
info->InterlaceType = info_ptr->interlace_type;
|
|
info->compressionType = info_ptr->compression_type;
|
|
info->pixelDepth = info_ptr->pixel_depth;
|
|
info->physUnitType = info_ptr->phys_unit_type;
|
|
info->xPixelsPerUnit = info_ptr->x_pixels_per_unit;
|
|
info->yPixelsPerUnit = info_ptr->y_pixels_per_unit;
|
|
}
|
|
|
|
if (NULL != image)
|
|
{
|
|
png_set_scale_16(png_ptr);
|
|
png_set_expand(png_ptr);
|
|
|
|
png_set_interlace_handling(png_ptr);
|
|
png_read_update_info(png_ptr, info_ptr);
|
|
|
|
buffer = (uint8_t*)malloc((uintptr_t)info_ptr->rowbytes * (uintptr_t)info_ptr->height);
|
|
if (NULL == buffer)
|
|
{
|
|
longjmp(png_jmpbuf(png_ptr), (int)HGBASE_ERR_FAIL);
|
|
}
|
|
|
|
rowPointers = (uint8_t**)malloc(info_ptr->height * sizeof(png_bytep));
|
|
if (NULL == rowPointers)
|
|
{
|
|
longjmp(png_jmpbuf(png_ptr), (int)HGBASE_ERR_FAIL);
|
|
}
|
|
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; ++i)
|
|
{
|
|
rowPointers[i] = buffer + (uintptr_t)i * (uintptr_t)info_ptr->rowbytes;
|
|
}
|
|
|
|
png_read_image(png_ptr, rowPointers);
|
|
png_read_end(png_ptr, info_ptr);
|
|
|
|
if (0 == imgType)
|
|
{
|
|
if (PNG_COLOR_TYPE_GRAY_ALPHA == info_ptr->color_type || PNG_COLOR_TYPE_RGB_ALPHA == info_ptr->color_type)
|
|
{
|
|
imgType = HGBASE_IMGTYPE_RGBA;
|
|
}
|
|
else if (PNG_COLOR_TYPE_GRAY == info_ptr->color_type)
|
|
{
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
}
|
|
else
|
|
{
|
|
assert(PNG_COLOR_TYPE_RGB == info_ptr->color_type);
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
}
|
|
}
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CreateImage(info_ptr->width, info_ptr->height, imgType, imgOrigin, &image2))
|
|
{
|
|
longjmp(png_jmpbuf(png_ptr), (int)HGBASE_ERR_FAIL);
|
|
}
|
|
|
|
if (1 == info_ptr->phys_unit_type)
|
|
{
|
|
uint32_t xDpi = (uint32_t)((double)info_ptr->x_pixels_per_unit / 39.3700787 + 0.5);
|
|
uint32_t yDpi = (uint32_t)((double)info_ptr->y_pixels_per_unit / 39.3700787 + 0.5);
|
|
HGBase_SetImageDpi(image2, xDpi, yDpi);
|
|
}
|
|
|
|
uint8_t* data;
|
|
HGBase_GetImageData(image2, &data);
|
|
HGImageInfo imgInfo;
|
|
HGBase_GetImageInfo(image2, &imgInfo);
|
|
|
|
HGByte* dest = data;
|
|
HGSize destStep = (HGSize)imgInfo.widthStep;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgOrigin)
|
|
{
|
|
dest = data + (HGUSize)(imgInfo.height - 1) * (HGUSize)imgInfo.widthStep;
|
|
destStep = -(HGSize)imgInfo.widthStep;
|
|
}
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == imgType)
|
|
{
|
|
if (PNG_COLOR_TYPE_GRAY == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
memcpy(pDestEx, pEx, info_ptr->width);
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_RGB == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 3;
|
|
uint8_t* 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 += 3;
|
|
++pDestEx;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_GRAY_ALPHA == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 2;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
*pDestEx = *pEx;
|
|
pEx += 2;
|
|
++pDestEx;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(PNG_COLOR_TYPE_RGB_ALPHA == info_ptr->color_type);
|
|
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 4;
|
|
uint8_t* 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 += 4;
|
|
++pDestEx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (HGBASE_IMGTYPE_RGB == imgType)
|
|
{
|
|
if (PNG_COLOR_TYPE_GRAY == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pDestEx[1] = pDestEx[2] = *pEx;
|
|
++pEx;
|
|
pDestEx += 3;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_RGB == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
memcpy(pDestEx, pEx, info_ptr->width * 3);
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_GRAY_ALPHA == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 2;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pDestEx[1] = pDestEx[2] = *pEx;
|
|
pEx += 2;
|
|
pDestEx += 3;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(PNG_COLOR_TYPE_RGB_ALPHA == info_ptr->color_type);
|
|
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 4;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pEx[0];
|
|
pDestEx[1] = pEx[1];
|
|
pDestEx[2] = pEx[2];
|
|
|
|
pEx += 4;
|
|
pDestEx += 3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (HGBASE_IMGTYPE_BGR == imgType)
|
|
{
|
|
if (PNG_COLOR_TYPE_GRAY == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pDestEx[1] = pDestEx[2] = *pEx;
|
|
++pEx;
|
|
pDestEx += 3;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_RGB == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 3;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pEx[2];
|
|
pDestEx[1] = pEx[1];
|
|
pDestEx[2] = pEx[0];
|
|
|
|
pEx += 3;
|
|
pDestEx += 3;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_GRAY_ALPHA == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 2;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pDestEx[1] = pDestEx[2] = *pEx;
|
|
pEx += 2;
|
|
pDestEx += 3;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(PNG_COLOR_TYPE_RGB_ALPHA == info_ptr->color_type);
|
|
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 4;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pEx[2];
|
|
pDestEx[1] = pEx[1];
|
|
pDestEx[2] = pEx[0];
|
|
|
|
pEx += 4;
|
|
pDestEx += 3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (HGBASE_IMGTYPE_BGRA == imgType)
|
|
{
|
|
if (PNG_COLOR_TYPE_GRAY == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
uint8_t v = *pEx;
|
|
*((uint32_t*)pDestEx) = (v & 0x000000FF) | ((v << 8) & 0x0000FF00) | ((v << 16) & 0x00FF0000) | 0xFF000000;
|
|
|
|
++pEx;
|
|
pDestEx += 4;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_RGB == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 3;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
uint8_t r = pEx[0];
|
|
uint8_t g = pEx[1];
|
|
uint8_t b = pEx[2];
|
|
*((uint32_t*)pDestEx) = (b & 0x000000FF) | ((g << 8) & 0x0000FF00) | ((r << 16) & 0x00FF0000) | 0xFF000000;
|
|
|
|
pEx += 3;
|
|
pDestEx += 4;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_GRAY_ALPHA == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 2;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
uint8_t v = pEx[0];
|
|
uint8_t alpha = pEx[1];
|
|
*((uint32_t*)pDestEx) = (v & 0x000000FF) | ((v << 8) & 0x0000FF00) | ((v << 16) & 0x00FF0000) | ((alpha << 24) & 0xFF000000);
|
|
|
|
pEx += 2;
|
|
pDestEx += 4;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(PNG_COLOR_TYPE_RGB_ALPHA == info_ptr->color_type);
|
|
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 4;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
pDestEx[0] = pEx[2];
|
|
pDestEx[1] = pEx[1];
|
|
pDestEx[2] = pEx[0];
|
|
pDestEx[3] = pEx[3];
|
|
|
|
pEx += 4;
|
|
pDestEx += 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(HGBASE_IMGTYPE_RGBA == imgType);
|
|
|
|
if (PNG_COLOR_TYPE_GRAY == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
uint8_t v = *pEx;
|
|
*((uint32_t*)pDestEx) = (v & 0x000000FF) | ((v << 8) & 0x0000FF00) | ((v << 16) & 0x00FF0000) | 0xFF000000;
|
|
|
|
++pEx;
|
|
pDestEx += 4;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_RGB == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 3;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
uint8_t r = pEx[0];
|
|
uint8_t g = pEx[1];
|
|
uint8_t b = pEx[2];
|
|
*((uint32_t*)pDestEx) = (r & 0x000000FF) | ((g << 8) & 0x0000FF00) | ((b << 16) & 0x00FF0000) | 0xFF000000;
|
|
|
|
pEx += 3;
|
|
pDestEx += 4;
|
|
}
|
|
}
|
|
}
|
|
else if (PNG_COLOR_TYPE_GRAY_ALPHA == info_ptr->color_type)
|
|
{
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pExEnd = pEx + info_ptr->width * 2;
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
while (pEx < pExEnd)
|
|
{
|
|
uint8_t v = pEx[0];
|
|
uint8_t alpha = pEx[1];
|
|
*((uint32_t*)pDestEx) = (v & 0x000000FF) | ((v << 8) & 0x0000FF00) | ((v << 16) & 0x00FF0000) | ((alpha << 24) & 0xFF000000);
|
|
|
|
pEx += 2;
|
|
pDestEx += 4;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(PNG_COLOR_TYPE_RGB_ALPHA == info_ptr->color_type);
|
|
|
|
//#pragma omp parallel for
|
|
for (png_int_32 i = 0; i < (png_int_32)info_ptr->height; i++)
|
|
{
|
|
uint8_t* pEx = rowPointers[i];
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
memcpy(pDestEx, pEx, info_ptr->width * 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
free(rowPointers);
|
|
rowPointers = NULL;
|
|
free(buffer);
|
|
buffer = NULL;
|
|
*image = image2;
|
|
}
|
|
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_OK;
|
|
}
|
|
|
|
HGResult HGAPI HGImgFmt_SavePngImage(HGImage image, const HGPngSaveInfo* info, const HGChar* fileName)
|
|
{
|
|
if (NULL == image || NULL == fileName)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
if (NULL != info)
|
|
{
|
|
// 判断合法性
|
|
}
|
|
|
|
HGImageInfo imgInfo;
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
|
|
uint32_t width = imgInfo.width;
|
|
uint32_t height = imgInfo.height;
|
|
uint32_t widthStep = imgInfo.widthStep;
|
|
uint32_t type = imgInfo.type;
|
|
uint32_t origin = imgInfo.origin;
|
|
|
|
if (HGBASE_IMGTYPE_GRAY != type && HGBASE_IMGTYPE_RGB != type
|
|
&& HGBASE_IMGTYPE_RGBA != type)
|
|
{
|
|
return HGBASE_ERR_INVALIDARG;
|
|
}
|
|
|
|
FILE* file = fopen(fileName, "wb");
|
|
if (NULL == file)
|
|
{
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
}
|
|
|
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
if (NULL == png_ptr)
|
|
{
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
|
if (NULL == info_ptr)
|
|
{
|
|
png_destroy_write_struct(&png_ptr, NULL);
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
uint8_t** rowPointers = NULL;
|
|
|
|
int jmpResult = setjmp(png_jmpbuf(png_ptr));
|
|
if (0 != jmpResult)
|
|
{
|
|
free(rowPointers);
|
|
rowPointers = NULL;
|
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fclose(file);
|
|
file = NULL;
|
|
return (HGResult)jmpResult;
|
|
}
|
|
|
|
png_init_io(png_ptr, file);
|
|
|
|
uint8_t* data;
|
|
HGBase_GetImageData(image, &data);
|
|
|
|
int color_type = -1;
|
|
if (HGBASE_IMGTYPE_GRAY == type)
|
|
color_type = PNG_COLOR_TYPE_GRAY;
|
|
else if (HGBASE_IMGTYPE_RGB == type)
|
|
color_type = PNG_COLOR_TYPE_RGB;
|
|
else if (HGBASE_IMGTYPE_RGBA == type)
|
|
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
|
assert(-1 != color_type);
|
|
|
|
png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
|
|
|
HGUInt xDpi, yDpi;
|
|
HGBase_GetImageDpi(image, &xDpi, &yDpi);
|
|
info_ptr->phys_unit_type = 1;
|
|
info_ptr->x_pixels_per_unit = (uint32_t)((double)xDpi * 39.3700787 + 0.5);
|
|
info_ptr->y_pixels_per_unit = (uint32_t)((double)yDpi * 39.3700787 + 0.5);
|
|
info_ptr->valid |= PNG_INFO_pHYs;
|
|
|
|
if (NULL != info)
|
|
{
|
|
info_ptr->phys_unit_type = info->physUnitType;
|
|
info_ptr->x_pixels_per_unit = info->xPixelsPerUnit;
|
|
info_ptr->y_pixels_per_unit = info->yPixelsPerUnit;
|
|
info_ptr->valid |= PNG_INFO_pHYs;
|
|
}
|
|
|
|
png_write_info(png_ptr, info_ptr);
|
|
|
|
rowPointers = (uint8_t**)malloc(height * sizeof(png_bytep));
|
|
if (NULL == rowPointers)
|
|
{
|
|
longjmp(png_jmpbuf(png_ptr), (int)HGBASE_ERR_FAIL);
|
|
}
|
|
|
|
HGByte* p = data;
|
|
HGSize step = (HGSize)widthStep;
|
|
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
{
|
|
p = data + (HGUSize)(height - 1) * (HGUSize)widthStep;
|
|
step = -(HGSize)widthStep;
|
|
}
|
|
|
|
//#pragma omp parallel for
|
|
for (int32_t i = 0; i < (int32_t)height; ++i)
|
|
{
|
|
rowPointers[i] = p + (HGSize)i * (HGSize)step;
|
|
}
|
|
|
|
png_write_image(png_ptr, rowPointers);
|
|
png_write_end(png_ptr, info_ptr);
|
|
|
|
free(rowPointers);
|
|
rowPointers = NULL;
|
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fclose(file);
|
|
file = NULL;
|
|
return HGBASE_ERR_OK;
|
|
} |