code_app/imgfmt/HGPdf.cpp

402 lines
8.4 KiB
C++
Raw Normal View History

2022-05-03 10:25:52 +00:00
#include "HGPdf.h"
#include "../base/HGInc.h"
#include "mupdf/pdf.h"
#include "mupdf/fitz.h"
#include "pdflib.h"
#include "../utility/HGString.h"
#include <string>
struct HGPdfReaderImpl
{
HGPdfReaderImpl()
{
m_pContext = NULL;
m_pDoc = NULL;
}
~HGPdfReaderImpl()
{
if (NULL != m_pDoc)
{
fz_drop_document(m_pContext, m_pDoc);
m_pDoc = NULL;
}
if (NULL != m_pContext)
{
fz_drop_context(m_pContext);
m_pContext = NULL;
}
}
fz_context* m_pContext;
fz_document *m_pDoc;
};
struct HGPdfImageWriterImpl
{
HGPdfImageWriterImpl()
{
m_pPdf = NULL;
}
~HGPdfImageWriterImpl()
{
if (NULL != m_pPdf)
{
PDF_TRY(m_pPdf)
{
PDF_end_document(m_pPdf, "");
}
PDF_CATCH(m_pPdf)
{
}
PDF_delete(m_pPdf);
m_pPdf = NULL;
}
}
PDF* m_pPdf;
};
#if defined(HG_CMP_MSC)
static WCHAR* GetUnicodeStr(const char* text)
{
int len = ::MultiByteToWideChar(CP_ACP, 0, text, -1, NULL, 0);
WCHAR* pUnicode = new WCHAR[len];
::MultiByteToWideChar(CP_ACP, 0, text, -1, pUnicode, len);
return pUnicode;
}
static uint32_t GetUnicodeStrLen(const WCHAR* pUnicode)
{
return (uint32_t)wcslen(pUnicode);
}
#else
static uint16_t* GetUnicodeStr(const char* text)
{
if (0 == *text)
{
uint16_t* pUnicode = new uint16_t[1];
*pUnicode = 0;
return pUnicode;
}
uint16_t* pUnicode = new uint16_t[strlen(text) + 2];
memset(pUnicode, 0, sizeof(uint16_t) * (strlen(text) + 2));
iconv_t cd = iconv_open("UNICODE//IGNORE", "UTF-8");
if ((iconv_t)-1 != cd)
{
char* inbuf = (char*)text;
size_t inbytes = strlen(text);
char* outbuf = (char*)pUnicode;
size_t outsize = sizeof(uint16_t) * (strlen(text) + 1);
iconv(cd, &inbuf, &inbytes, &outbuf, &outsize);
iconv_close(cd);
}
return pUnicode;
}
static uint32_t GetUnicodeStrLen(const uint16_t* pUnicode)
{
uint32_t i = 0;
while (0 != pUnicode[i])
{
++i;
}
return i;
}
#endif
HGResult HGAPI HGImgFmt_CheckPdfFile(const HGChar* fileName, HGBool* isPdf)
{
if (NULL == fileName || NULL == isPdf)
{
return HGBASE_ERR_INVALIDARG;
}
*isPdf = HGFALSE;
HGPdfReader reader = NULL;
HGImgFmt_OpenPdfReader(fileName, &reader);
if (NULL != reader)
{
*isPdf = HGTRUE;
HGImgFmt_ClosePdfReader(reader);
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_OpenPdfReader(const HGChar* fileName, HGPdfReader* reader)
{
if (NULL == fileName || NULL == reader)
{
return HGBASE_ERR_INVALIDARG;
}
HGBool isPdfFile = HGFALSE;
FILE* file = fopen(fileName, "r");
if (NULL != file)
{
HGByte data[4];
size_t len = fread(data, 1, 4, file);
if (4 == len && 0 == memcmp(data, "%PDF", 4))
{
isPdfFile = HGTRUE;
}
fclose(file);
}
if (!isPdfFile)
{
return HGBASE_ERR_FAIL;
}
fz_context* pContext = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
if (NULL == pContext)
{
return HGBASE_ERR_FAIL;
}
HGResult ret = HGBASE_ERR_FAIL;
fz_try(pContext)
{
fz_register_document_handlers(pContext);
fz_document* pDoc = fz_open_document(pContext, StdStringToUtf8(fileName).c_str());
HGPdfReaderImpl* pdfReaderImpl = new HGPdfReaderImpl;
pdfReaderImpl->m_pContext = pContext;
pdfReaderImpl->m_pDoc = pDoc;
*reader = (HGPdfReader)pdfReaderImpl;
ret = HGBASE_ERR_OK;
}
fz_catch(pContext)
{
fz_drop_context(pContext);
pContext = NULL;
}
return ret;
}
HGResult HGAPI HGImgFmt_ClosePdfReader(HGPdfReader reader)
{
if (NULL == reader)
{
return HGBASE_ERR_INVALIDARG;
}
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
delete pdfReaderImpl;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_GetPdfPageCount(HGPdfReader reader, HGUInt* count)
{
if (NULL == reader || NULL == count)
{
return HGBASE_ERR_INVALIDARG;
}
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
HGResult ret = HGBASE_ERR_FAIL;
fz_try(pdfReaderImpl->m_pContext)
{
*count = (uint32_t)fz_count_pages(pdfReaderImpl->m_pContext, pdfReaderImpl->m_pDoc);
ret = HGBASE_ERR_OK;
}
fz_catch(pdfReaderImpl->m_pContext)
{
}
return ret;
}
HGResult HGAPI HGImgFmt_GetPdfPageInfo(HGPdfReader reader, HGUInt page, HGPdfPageInfo* info)
{
if (NULL == reader || NULL == info)
{
return HGBASE_ERR_INVALIDARG;
}
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
HGResult ret = HGBASE_ERR_FAIL;
fz_page* fzpage = NULL;
fz_try(pdfReaderImpl->m_pContext)
{
fzpage = fz_load_page(pdfReaderImpl->m_pContext, pdfReaderImpl->m_pDoc, (int)page);
pdf_page* page = pdf_page_from_fz_page(pdfReaderImpl->m_pContext, fzpage);
if (NULL != page)
{
fz_rect pdfRect = pdf_bound_page(pdfReaderImpl->m_pContext, page);
info->width = ceil(pdfRect.x1);
info->height = ceil(pdfRect.y1);
ret = HGBASE_ERR_OK;
}
}
fz_catch(pdfReaderImpl->m_pContext)
{
}
if (NULL != fzpage)
fz_drop_page(pdfReaderImpl->m_pContext, fzpage);
return ret;
}
HGResult HGAPI HGImgFmt_LoadImageFromPdfReader(HGPdfReader reader, HGUInt page, HGFloat xScale, HGFloat yScale,
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
{
if (NULL == reader || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
HGResult ret = HGBASE_ERR_FAIL;
fz_pixmap* pix = NULL;
fz_try(pdfReaderImpl->m_pContext)
{
fz_matrix ctm = fz_scale(xScale, yScale);
pix = fz_new_pixmap_from_page_number(pdfReaderImpl->m_pContext, pdfReaderImpl->m_pDoc, (int)page,
ctm, fz_device_rgb(pdfReaderImpl->m_pContext), 0);
int width = fz_pixmap_width(pdfReaderImpl->m_pContext, pix);
int height = fz_pixmap_height(pdfReaderImpl->m_pContext, pix);
*image = NULL;
HGImageInfo imgInfo = { (uint32_t)width, (uint32_t)height, HGBASE_IMGTYPE_RGB, (uint32_t)pix->stride, HGBASE_IMGORIGIN_TOP };
HGBase_CreateImageFromData(pix->samples, &imgInfo, NULL, imgType, imgOrigin, image);
if (NULL != *image)
{
ret = HGBASE_ERR_OK;
}
}
fz_catch(pdfReaderImpl->m_pContext)
{
}
if (NULL != pix)
fz_drop_pixmap(pdfReaderImpl->m_pContext, pix);
return ret;
}
HGResult HGAPI HGImgFmt_OpenPdfImageWriter(const HGChar* fileName, HGPdfImageWriter* writer)
{
if (NULL == fileName || NULL == writer)
{
return HGBASE_ERR_INVALIDARG;
}
PDF* p = PDF_new();
if (NULL == p)
{
return HGBASE_ERR_OUTOFMEMORY;
}
#if defined(HG_CMP_MSC)
WCHAR* pUnicode = GetUnicodeStr(fileName);
#else
uint16_t* pUnicode = GetUnicodeStr(fileName);
#endif
PDF_TRY(p)
{
PDF_set_parameter(p, "compatibility", "1.4");
PDF_set_parameter(p, "errorpolicy", "return");
PDF_set_parameter(p, "hypertextencoding", "host");
#if defined(HG_CMP_MSC)
if (-1 == PDF_begin_document(p, (const char*)pUnicode, (int)(GetUnicodeStrLen(pUnicode) * sizeof(WCHAR)), ""))
#else
if (-1 == PDF_begin_document(p, (const char*)pUnicode, (int)(GetUnicodeStrLen(pUnicode) * sizeof(uint16_t)), ""))
#endif
{
delete[] pUnicode;
PDF_delete(p);
return HGBASE_ERR_FAIL;
}
}
PDF_CATCH(p)
{
delete[] pUnicode;
PDF_delete(p);
return HGBASE_ERR_FAIL;
}
delete[] pUnicode;
HGPdfImageWriterImpl* pdfImageWriterImpl = new HGPdfImageWriterImpl;
pdfImageWriterImpl->m_pPdf = p;
*writer = (HGPdfImageWriter)pdfImageWriterImpl;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_ClosePdfImageWriter(HGPdfImageWriter writer)
{
if (NULL == writer)
{
return HGBASE_ERR_INVALIDARG;
}
HGPdfImageWriterImpl* pdfImageWriterImpl = (HGPdfImageWriterImpl*)writer;
delete pdfImageWriterImpl;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_SaveJpegImageToPdfImageWriter(HGPdfImageWriter writer, HGImage image, const HGJpegSaveInfo* info, HGUInt quality)
{
if (NULL == writer || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
HGBuffer buffer = NULL;
HGResult ret = HGImgFmt_SaveJpegImageToBuffer(image, info, quality, &buffer);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
HGByte* imgBuf = NULL;
HGBase_GetBufferData(buffer, &imgBuf);
HGUSize size = 0;
HGBase_GetBufferSize(buffer, &size);
HGPdfImageWriterImpl* pdfImageWriterImpl = (HGPdfImageWriterImpl*)writer;
PDF_TRY(pdfImageWriterImpl->m_pPdf)
{
PDF_create_pvf(pdfImageWriterImpl->m_pPdf, "virtual_file", 0, imgBuf, size, "");
}
PDF_CATCH(pdfImageWriterImpl->m_pPdf)
{
return HGBASE_ERR_OUTOFMEMORY;
}
int img = PDF_load_image(pdfImageWriterImpl->m_pPdf, "auto", "virtual_file", 0, "page 1");
if (-1 != img)
{
PDF_begin_page_ext(pdfImageWriterImpl->m_pPdf, 0.0, 0.0, "");
PDF_fit_image(pdfImageWriterImpl->m_pPdf, img, 0.0, 0.0, "adjustpage");
PDF_end_page_ext(pdfImageWriterImpl->m_pPdf, "");
PDF_close_image(pdfImageWriterImpl->m_pPdf, img);
}
PDF_delete_pvf(pdfImageWriterImpl->m_pPdf, "virtual_file", 0);
HGBase_DestroyBuffer(buffer);
return HGBASE_ERR_OK;
}