调整app编译路径
This commit is contained in:
parent
2fed123ed0
commit
4fa2231a8b
|
@ -24,19 +24,19 @@ win32 {
|
||||||
|
|
||||||
contains(QT_ARCH, i386) {
|
contains(QT_ARCH, i386) {
|
||||||
LIBS += -L../sdk/lib/x86/Release -lHGBase -lHGImgFmt -lHGImgProc -lsane
|
LIBS += -L../sdk/lib/x86/Release -lHGBase -lHGImgFmt -lHGImgProc -lsane
|
||||||
LIBS += -L../../db/Debug -lHGPdtToolDb
|
|
||||||
CONFIG(release, debug|release) {
|
CONFIG(release, debug|release) {
|
||||||
DESTDIR = ../release/x86/
|
LIBS += -L../../db/Release -lHGPdtToolDb
|
||||||
|
DESTDIR = ../../../release/win/x86/Release
|
||||||
}
|
}
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
|
LIBS += -L../../db/Debug -lHGPdtToolDb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contains(QT_ARCH, x86_64){
|
contains(QT_ARCH, x86_64){
|
||||||
LIBS += -L../sdk/lib/x64/Release -lHGBase -lHGImgFmt -lHGImgProc -lsane
|
LIBS += -L../sdk/lib/x64/Release -lHGBase -lHGImgFmt -lHGImgProc -lsane
|
||||||
LIBS += -L../../db/Debug -lHGPdtToolDb
|
LIBS += -L../../db/Debug -lHGPdtToolDb
|
||||||
CONFIG(release, debug|release) {
|
CONFIG(release, debug|release) {
|
||||||
DESTDIR = ../release/x64/
|
DESTDIR = ../../../release/win/x64/Release
|
||||||
}
|
}
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
|
|
||||||
|
@ -44,8 +44,6 @@ win32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/../utility/
|
|
||||||
INCLUDEPATH += $$PWD/../modules/
|
|
||||||
INCLUDEPATH += $$PWD/../sdk/include/
|
INCLUDEPATH += $$PWD/../sdk/include/
|
||||||
INCLUDEPATH += $$PWD/../../db/HGPdtToolDb/
|
INCLUDEPATH += $$PWD/../../db/HGPdtToolDb/
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef __HGBASE_H__
|
|
||||||
#define __HGBASE_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
#include "HGBase64.h"
|
|
||||||
#include "HGDes.h"
|
|
||||||
#include "HGMd5.h"
|
|
||||||
#include "HGLock.h"
|
|
||||||
#include "HGEvent.h"
|
|
||||||
#include "HGDll.h"
|
|
||||||
#include "HGLog.h"
|
|
||||||
#include "HGConsole.h"
|
|
||||||
#include "HGBuffer.h"
|
|
||||||
#include "HGImage.h"
|
|
||||||
#include "HGThread.h"
|
|
||||||
#include "HGUtility.h"
|
|
||||||
#include "HGInfo.h"
|
|
||||||
#include "HGIni.h"
|
|
||||||
#include "HGMsgPump.h"
|
|
||||||
#include "HGTime.h"
|
|
||||||
#include "HGNamedPipe.h"
|
|
||||||
|
|
||||||
#endif /* __HGBASE_H__ */
|
|
|
@ -1,255 +0,0 @@
|
||||||
#include "HGBase64.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_Base64Encode(const HGByte* originalData, HGSize originalSize,
|
|
||||||
HGByte* base64Data, HGSize* base64Size)
|
|
||||||
{
|
|
||||||
if (NULL == originalData || 0 == originalSize)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != base64Data)
|
|
||||||
{
|
|
||||||
static const HGByte base64Table[] =
|
|
||||||
{
|
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
|
||||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
|
||||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
|
||||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
|
||||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
|
||||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
|
||||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
|
||||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
|
||||||
};
|
|
||||||
|
|
||||||
HGSize numberOfCycles = originalSize / 3;
|
|
||||||
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (HGSize i = 0; i < numberOfCycles; ++i)
|
|
||||||
{
|
|
||||||
const HGByte* originalDataEx = originalData + i * 3;
|
|
||||||
HGByte* base64DataEx = base64Data + i * 4;
|
|
||||||
|
|
||||||
HGUInt temp = (((HGUInt)originalDataEx[0] << 16) | ((HGUInt)originalDataEx[1] << 8)
|
|
||||||
| ((HGUInt)originalDataEx[2])) & 0x00FFFFFF;
|
|
||||||
base64DataEx[0] = base64Table[(temp >> 18) & 0x3F];
|
|
||||||
base64DataEx[1] = base64Table[(temp >> 12) & 0x3F];
|
|
||||||
base64DataEx[2] = base64Table[(temp >> 6) & 0x3F];
|
|
||||||
base64DataEx[3] = base64Table[temp & 0x3F];
|
|
||||||
}
|
|
||||||
|
|
||||||
const HGByte* originalDataEx = originalData + numberOfCycles * 3;
|
|
||||||
HGByte* base64DataEx = base64Data + numberOfCycles * 4;
|
|
||||||
|
|
||||||
HGSize sizeOfRemaining = originalSize - numberOfCycles * 3;
|
|
||||||
if (1 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
HGUInt temp = ((HGUInt)originalDataEx[0] << 16) & 0x00FF0000;
|
|
||||||
base64DataEx[0] = base64Table[(temp >> 18) & 0x3F];
|
|
||||||
base64DataEx[1] = base64Table[(temp >> 12) & 0x3F];
|
|
||||||
base64DataEx[2] = '=';
|
|
||||||
base64DataEx[3] = '=';
|
|
||||||
}
|
|
||||||
else if (2 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
HGUInt temp = (((HGUInt)originalDataEx[0] << 16) | ((HGUInt)originalDataEx[1] << 8)) & 0x00FFFF00;
|
|
||||||
base64DataEx[0] = base64Table[(temp >> 18) & 0x3F];
|
|
||||||
base64DataEx[1] = base64Table[(temp >> 12) & 0x3F];
|
|
||||||
base64DataEx[2] = base64Table[(temp >> 6) & 0x3F];
|
|
||||||
base64DataEx[3] = '=';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != base64Size)
|
|
||||||
{
|
|
||||||
HGSize newSize = (originalSize / 3) * 4;
|
|
||||||
if (0 != originalSize % 3)
|
|
||||||
{
|
|
||||||
newSize += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
*base64Size = newSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_Base64Decode(const HGByte* base64Data, HGSize base64Size,
|
|
||||||
HGByte* originalData, HGSize* originalSize)
|
|
||||||
{
|
|
||||||
if (NULL == base64Data || 0 == base64Size)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != originalData)
|
|
||||||
{
|
|
||||||
static const HGByte base64Table_1[] =
|
|
||||||
{
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 62, 64, 64, 64, 63,
|
|
||||||
52, 53, 54, 55, 56, 57, 58, 59,
|
|
||||||
60, 61, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 0, 1, 2, 3, 4, 5, 6,
|
|
||||||
7, 8, 9, 10, 11, 12, 13, 14,
|
|
||||||
15, 16, 17, 18, 19, 20, 21, 22,
|
|
||||||
23, 24, 25, 64, 64, 64, 64, 64,
|
|
||||||
64, 26, 27, 28, 29, 30, 31, 32,
|
|
||||||
33, 34, 35, 36, 37, 38, 39, 40,
|
|
||||||
41, 42, 43, 44, 45, 46, 47, 48,
|
|
||||||
49, 50, 51, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64
|
|
||||||
};
|
|
||||||
|
|
||||||
HGSize numberOfCycles = (base64Size - 1) / 4;
|
|
||||||
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (HGSize i = 0; i < numberOfCycles; ++i)
|
|
||||||
{
|
|
||||||
const HGByte* base64DataEx = base64Data + i * 4;
|
|
||||||
HGByte* originalDataEx = originalData + i * 3;
|
|
||||||
|
|
||||||
HGUInt t0 = base64Table_1[base64DataEx[0]];
|
|
||||||
HGUInt t1 = base64Table_1[base64DataEx[1]];
|
|
||||||
HGUInt t2 = base64Table_1[base64DataEx[2]];
|
|
||||||
HGUInt t3 = base64Table_1[base64DataEx[3]];
|
|
||||||
|
|
||||||
originalDataEx[0] = ((t0 << 2) | (t1 >> 4)) & 0xFF;
|
|
||||||
originalDataEx[1] = ((t1 << 4) | (t2 >> 2)) & 0xFF;
|
|
||||||
originalDataEx[2] = ((t2 << 6) | t3) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
const HGByte* base64DataEx = base64Data + numberOfCycles * 4;
|
|
||||||
HGByte* originalDataEx = originalData + numberOfCycles * 3;
|
|
||||||
|
|
||||||
HGSize sizeOfRemaining = base64Size - numberOfCycles * 4;
|
|
||||||
if (2 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
if ('=' != base64DataEx[0] && '=' != base64DataEx[1])
|
|
||||||
{
|
|
||||||
HGUInt t0 = base64Table_1[base64DataEx[0]];
|
|
||||||
HGUInt t1 = base64Table_1[base64DataEx[1]];
|
|
||||||
|
|
||||||
originalDataEx[0] = ((t0 << 2) | (t1 >> 4)) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (3 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
if ('=' != base64DataEx[0] && '=' != base64DataEx[1])
|
|
||||||
{
|
|
||||||
HGUInt t0 = base64Table_1[base64DataEx[0]];
|
|
||||||
HGUInt t1 = base64Table_1[base64DataEx[1]];
|
|
||||||
HGUInt t2 = base64Table_1[base64DataEx[2]];
|
|
||||||
|
|
||||||
if ('=' == base64DataEx[2])
|
|
||||||
{
|
|
||||||
originalDataEx[0] = ((t0 << 2) | (t1 >> 4)) & 0xFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
originalDataEx[0] = ((t0 << 2) | (t1 >> 4)) & 0xFF;
|
|
||||||
originalDataEx[1] = ((t1 << 4) | (t2 >> 2)) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (4 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
if ('=' != base64DataEx[0] && '=' != base64DataEx[1])
|
|
||||||
{
|
|
||||||
HGUInt t0 = base64Table_1[base64DataEx[0]];
|
|
||||||
HGUInt t1 = base64Table_1[base64DataEx[1]];
|
|
||||||
HGUInt t2 = base64Table_1[base64DataEx[2]];
|
|
||||||
HGUInt t3 = base64Table_1[base64DataEx[3]];
|
|
||||||
|
|
||||||
if ('=' == base64DataEx[2] && '=' == base64DataEx[3])
|
|
||||||
{
|
|
||||||
originalDataEx[0] = ((t0 << 2) | (t1 >> 4)) & 0xFF;
|
|
||||||
}
|
|
||||||
else if ('=' != base64DataEx[2] && '=' == base64DataEx[3])
|
|
||||||
{
|
|
||||||
originalDataEx[0] = ((t0 << 2) | (t1 >> 4)) & 0xFF;
|
|
||||||
originalDataEx[1] = ((t1 << 4) | (t2 >> 2)) & 0xFF;
|
|
||||||
}
|
|
||||||
else if ('=' != base64DataEx[2] && '=' != base64DataEx[3])
|
|
||||||
{
|
|
||||||
originalDataEx[0] = ((t0 << 2) | (t1 >> 4)) & 0xFF;
|
|
||||||
originalDataEx[1] = ((t1 << 4) | (t2 >> 2)) & 0xFF;
|
|
||||||
originalDataEx[2] = ((t2 << 6) | t3) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != originalSize)
|
|
||||||
{
|
|
||||||
HGSize numberOfCycles = (base64Size - 1) / 4;
|
|
||||||
const HGByte* base64DataEx = base64Data + numberOfCycles * 4;
|
|
||||||
|
|
||||||
HGSize newSize = numberOfCycles * 3;
|
|
||||||
|
|
||||||
HGSize sizeOfRemaining = base64Size - numberOfCycles * 4;
|
|
||||||
if (2 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
if ('=' != base64DataEx[0] && '=' != base64DataEx[1])
|
|
||||||
{
|
|
||||||
newSize += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (3 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
if ('=' != base64DataEx[0] && '=' != base64DataEx[1])
|
|
||||||
{
|
|
||||||
if ('=' == base64DataEx[2])
|
|
||||||
{
|
|
||||||
newSize += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newSize += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (4 == sizeOfRemaining)
|
|
||||||
{
|
|
||||||
if ('=' != base64DataEx[0] && '=' != base64DataEx[1])
|
|
||||||
{
|
|
||||||
if ('=' == base64DataEx[2] && '=' == base64DataEx[3])
|
|
||||||
{
|
|
||||||
newSize += 1;
|
|
||||||
}
|
|
||||||
else if ('=' != base64DataEx[2] && '=' == base64DataEx[3])
|
|
||||||
{
|
|
||||||
newSize += 2;
|
|
||||||
}
|
|
||||||
else if ('=' != base64DataEx[2] && '=' != base64DataEx[3])
|
|
||||||
{
|
|
||||||
newSize += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*originalSize = newSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef __HGBASE64_H__
|
|
||||||
#define __HGBASE64_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
/* Base64编码
|
|
||||||
* 参数:
|
|
||||||
* 1) originalData: in, 原始数据地址
|
|
||||||
* 2) originalSize: in, 原始数据长度
|
|
||||||
* 3) base64Data: out, base64地址
|
|
||||||
* 4) base64Size: out, 编码后base64长度
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数的调用需要分两次,第一次base64Data为NULL,base64Size不为NULL, 获取编码后base64长度
|
|
||||||
* 2) 分配足够的内存后,然后调用第二次,此时base64Data为分配的地址
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_Base64Encode(const HGByte* originalData, HGSize originalSize,
|
|
||||||
HGByte* base64Data, HGSize* base64Size);
|
|
||||||
|
|
||||||
/* Base64解码
|
|
||||||
* 参数:
|
|
||||||
* 1) base64Data: in, base64地址
|
|
||||||
* 2) base64Size: in, base64长度
|
|
||||||
* 3) originalData: out, 原始数据地址
|
|
||||||
* 4) originalSize: out, 解码后原始数据长度
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数的调用需要分两次,第一次originalData为NULL,originalSize不为NULL, 获取解码后原始数据长度
|
|
||||||
* 2) 分配足够的内存后,然后调用第二次,此时originalData为分配的地址
|
|
||||||
* 3) base64Data中的数据必须是标准Base64字符, 不能有其他字符,比如\r或\n等
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_Base64Decode(const HGByte* base64Data, HGSize base64Size,
|
|
||||||
HGByte* originalData, HGSize* originalSize);
|
|
||||||
|
|
||||||
#endif /* __HGBASE64_H__ */
|
|
|
@ -1,40 +0,0 @@
|
||||||
#ifndef __HGBASEERR_H__
|
|
||||||
#define __HGBASEERR_H__
|
|
||||||
|
|
||||||
/* 无错误 */
|
|
||||||
#define HGBASE_ERR_OK 0x00000000L
|
|
||||||
|
|
||||||
/* 一般错误 */
|
|
||||||
#define HGBASE_ERR_FAIL 0x00000001L
|
|
||||||
|
|
||||||
/* 内存不足 */
|
|
||||||
#define HGBASE_ERR_OUTOFMEMORY 0x00000002L
|
|
||||||
|
|
||||||
/* 参数非法 */
|
|
||||||
#define HGBASE_ERR_INVALIDARG 0x00000003L
|
|
||||||
|
|
||||||
/* 无访问权限 */
|
|
||||||
#define HGBASE_ERR_ACCESSDENIED 0x00000004L
|
|
||||||
|
|
||||||
/* 数据非法 */
|
|
||||||
#define HGBASE_ERR_INVALIDDATA 0x00000005L
|
|
||||||
|
|
||||||
/* 未实现 */
|
|
||||||
#define HGBASE_ERR_NOTIMPL 0x00000006L
|
|
||||||
|
|
||||||
/* 不支持该功能 */
|
|
||||||
#define HGBASE_ERR_NOTSUPPORT 0x00000007L
|
|
||||||
|
|
||||||
/* 超时 */
|
|
||||||
#define HGBASE_ERR_TIMEOUT 0x00000008L
|
|
||||||
|
|
||||||
/* 文件不存在 */
|
|
||||||
#define HGBASE_ERR_FILENOTEXIST 0x00000009L
|
|
||||||
|
|
||||||
/* 加载动态库失败 */
|
|
||||||
#define HGBASE_ERR_LOADLIBRARY 0x0000000AL
|
|
||||||
|
|
||||||
/* 文件错误 */
|
|
||||||
#define HGBASE_ERR_FILEERROR 0x0000000BL
|
|
||||||
|
|
||||||
#endif /* __HGBASEERR_H__ */
|
|
|
@ -1,149 +0,0 @@
|
||||||
#include "HGBuffer.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
struct HGBufferImpl
|
|
||||||
{
|
|
||||||
HGBufferImpl()
|
|
||||||
{
|
|
||||||
m_data = NULL;
|
|
||||||
m_size = 0;
|
|
||||||
m_alloc = HGFALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
~HGBufferImpl()
|
|
||||||
{
|
|
||||||
if (m_alloc)
|
|
||||||
{
|
|
||||||
free(m_data);
|
|
||||||
m_data = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte* m_data;
|
|
||||||
HGUSize m_size;
|
|
||||||
HGBool m_alloc;
|
|
||||||
};
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateBuffer(HGUSize size, HGBuffer* buffer)
|
|
||||||
{
|
|
||||||
if (0 == size || NULL == buffer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte* data = (HGByte*)malloc(size);
|
|
||||||
if (NULL == data)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBufferImpl* bufferImpl = new HGBufferImpl;
|
|
||||||
bufferImpl->m_data = data;
|
|
||||||
bufferImpl->m_size = size;
|
|
||||||
bufferImpl->m_alloc = HGTRUE;
|
|
||||||
|
|
||||||
*buffer = (HGBuffer)bufferImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateBufferFromData(const HGByte* data, HGUSize size, HGBuffer* buffer)
|
|
||||||
{
|
|
||||||
if (NULL == data || 0 == size || NULL == buffer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte* data2 = (HGByte*)malloc(size);
|
|
||||||
if (NULL == data2)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data2, data, size);
|
|
||||||
|
|
||||||
HGBufferImpl* bufferImpl = new HGBufferImpl;
|
|
||||||
bufferImpl->m_data = data2;
|
|
||||||
bufferImpl->m_size = size;
|
|
||||||
bufferImpl->m_alloc = HGTRUE;
|
|
||||||
|
|
||||||
*buffer = (HGBuffer)bufferImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateBufferWithData(HGByte* data, HGUSize size, HGBuffer* buffer)
|
|
||||||
{
|
|
||||||
if (NULL == data || 0 == size || NULL == buffer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBufferImpl* bufferImpl = new HGBufferImpl;
|
|
||||||
bufferImpl->m_data = data;
|
|
||||||
bufferImpl->m_size = size;
|
|
||||||
bufferImpl->m_alloc = HGFALSE;
|
|
||||||
|
|
||||||
*buffer = (HGBuffer)bufferImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CloneBuffer(HGBuffer srcBuffer, HGBuffer* buffer)
|
|
||||||
{
|
|
||||||
if (NULL == srcBuffer || NULL == buffer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBufferImpl* srcBufferImpl = (HGBufferImpl*)srcBuffer;
|
|
||||||
|
|
||||||
HGByte* data = (HGByte*)malloc(srcBufferImpl->m_size);
|
|
||||||
if (NULL == data)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data, srcBufferImpl->m_data, srcBufferImpl->m_size);
|
|
||||||
|
|
||||||
HGBufferImpl* bufferImpl = new HGBufferImpl;
|
|
||||||
bufferImpl->m_data = data;
|
|
||||||
bufferImpl->m_size = srcBufferImpl->m_size;
|
|
||||||
bufferImpl->m_alloc = HGTRUE;
|
|
||||||
|
|
||||||
*buffer = (HGBuffer)bufferImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DestroyBuffer(HGBuffer buffer)
|
|
||||||
{
|
|
||||||
if (NULL == buffer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBufferImpl* bufferImpl = (HGBufferImpl*)buffer;
|
|
||||||
delete bufferImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetBufferData(HGBuffer buffer, HGByte** data)
|
|
||||||
{
|
|
||||||
if (NULL == buffer || NULL == data)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBufferImpl* bufferImpl = (HGBufferImpl*)buffer;
|
|
||||||
*data = bufferImpl->m_data;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetBufferSize(HGBuffer buffer, HGUSize* size)
|
|
||||||
{
|
|
||||||
if (NULL == buffer || NULL == size)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBufferImpl* bufferImpl = (HGBufferImpl*)buffer;
|
|
||||||
*size = bufferImpl->m_size;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
#ifndef __HGBUFFER_H__
|
|
||||||
#define __HGBUFFER_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGBuffer);
|
|
||||||
|
|
||||||
/* 创建新的缓冲区
|
|
||||||
* 参数:
|
|
||||||
* 1) size: in, 缓冲区大小, 单位字节
|
|
||||||
* 2) buffer: out, 新缓冲区句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 内部会分配size字节大小的内存
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateBuffer(HGUSize size, HGBuffer* buffer);
|
|
||||||
|
|
||||||
/* 通过已有数据创建新的缓冲区
|
|
||||||
* 参数:
|
|
||||||
* 1) data: in, 已有的数据地址
|
|
||||||
* 2) size: in, 已有的数据大小, 单位字节
|
|
||||||
* 3) buffer: out, 新缓冲区句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 内部会分配size字节大小的内存, 新的缓冲区创建完成时, 会将data中的数据拷贝过去
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateBufferFromData(const HGByte* data, HGUSize size, HGBuffer* buffer);
|
|
||||||
|
|
||||||
/* 通过已有数据创建新的缓冲区(不分配内存, 不拷贝数据)
|
|
||||||
* 参数:
|
|
||||||
* 1) data: in, 已有的数据地址
|
|
||||||
* 2) size: in, 已有的数据大小, 单位字节
|
|
||||||
* 3) buffer: out, 新缓冲区句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 内部不会分配内存, 将直接使用原始数据
|
|
||||||
* 2) 需保证缓冲区销毁前原始数据一直有效
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateBufferWithData(HGByte* data, HGUSize size, HGBuffer* buffer);
|
|
||||||
|
|
||||||
/* 通过现有缓冲区创建新的缓冲区
|
|
||||||
* 参数:
|
|
||||||
* 1) srcBuffer: in, 已有缓冲区
|
|
||||||
* 2) buffer: out, 新缓冲区句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 内部会分配现有缓冲区的size字节大小的内存, 新缓冲区创建完成时, 会将现有缓冲区中的数据拷贝过去
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CloneBuffer(HGBuffer srcBuffer, HGBuffer* buffer);
|
|
||||||
|
|
||||||
/* 销毁缓冲区
|
|
||||||
* 参数:
|
|
||||||
* 1) buffer: in, 缓冲区句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 如果内部分配了内存, 销毁的时候会自动释放该内存
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DestroyBuffer(HGBuffer buffer);
|
|
||||||
|
|
||||||
/* 获取缓冲区数据地址
|
|
||||||
* 参数:
|
|
||||||
* 1) buffer: in, 缓冲区句柄
|
|
||||||
* 2) data: out, 数据地址
|
|
||||||
* 说明:
|
|
||||||
* 1) 如果内部分配了内存, 返回的是分配的内存地址
|
|
||||||
* 2) 如果内部没有分配内存, 返回的则是原始数据的地址
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetBufferData(HGBuffer buffer, HGByte** data);
|
|
||||||
|
|
||||||
/* 获取缓冲区数据大小
|
|
||||||
* 参数:
|
|
||||||
* 1) buffer: in, 缓冲区句柄
|
|
||||||
* 2) size: out, 数据长度
|
|
||||||
* 说明:
|
|
||||||
* 1) 如果内部分配了内存, 返回的是分配的内存大小
|
|
||||||
* 2) 如果内部没有分配内存, 返回的则是原始数据的大小
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetBufferSize(HGBuffer buffer, HGUSize* size);
|
|
||||||
|
|
||||||
#endif /* __HGBUFFER_H__ */
|
|
|
@ -1,78 +0,0 @@
|
||||||
#include "HGConsole.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
struct HGConsoleImpl
|
|
||||||
{
|
|
||||||
HGConsoleImpl()
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
m_bAllocConsole = FALSE;
|
|
||||||
m_hConsole = INVALID_HANDLE_VALUE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
~HGConsoleImpl()
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (INVALID_HANDLE_VALUE != m_hConsole)
|
|
||||||
m_hConsole = INVALID_HANDLE_VALUE;
|
|
||||||
if (m_bAllocConsole)
|
|
||||||
{
|
|
||||||
FreeConsole();
|
|
||||||
m_bAllocConsole = FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
BOOL m_bAllocConsole;
|
|
||||||
HANDLE m_hConsole;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_OpenConsole(HGConsole* console)
|
|
||||||
{
|
|
||||||
if (NULL == console)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGConsoleImpl* consoleImpl = new HGConsoleImpl;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
consoleImpl->m_bAllocConsole = AllocConsole();
|
|
||||||
consoleImpl->m_hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
#endif
|
|
||||||
*console = (HGConsole)consoleImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CloseConsole(HGConsole console)
|
|
||||||
{
|
|
||||||
if (NULL == console)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGConsoleImpl* consoleImpl = (HGConsoleImpl*)console;
|
|
||||||
delete consoleImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_WriteConsole(HGConsole console, const HGChar* info)
|
|
||||||
{
|
|
||||||
if (NULL == console || NULL == info || '\0' == *info)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGConsoleImpl* consoleImpl = (HGConsoleImpl*)console;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
DWORD dwNumberOfCharsWritten;
|
|
||||||
WriteConsoleA(consoleImpl->m_hConsole, info, (DWORD)strlen(info), &dwNumberOfCharsWritten, NULL);
|
|
||||||
WriteConsoleA(consoleImpl->m_hConsole, "\r\n", (DWORD)strlen("\r\n"), &dwNumberOfCharsWritten, NULL);
|
|
||||||
#else
|
|
||||||
printf(info);
|
|
||||||
printf("\n");
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#ifndef __HGCONSOLE_H__
|
|
||||||
#define __HGCONSOLE_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGConsole);
|
|
||||||
|
|
||||||
/* 开启控制台
|
|
||||||
* 参数:
|
|
||||||
* 1) log: out, 控制台句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_OpenConsole(HGConsole *console);
|
|
||||||
|
|
||||||
/* 关闭控制台
|
|
||||||
* 参数:
|
|
||||||
* 1) log: in, 控制台句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CloseConsole(HGConsole console);
|
|
||||||
|
|
||||||
/* 写控制台信息
|
|
||||||
* 参数:
|
|
||||||
* 1) log: in, 控制台句柄
|
|
||||||
* 2) info: in, 信息, 一次一行, info无需加换行符
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数不是线程安全的, 在不同线程调用的时候, 需要加锁
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_WriteConsole(HGConsole console, const HGChar* info);
|
|
||||||
|
|
||||||
#endif /* __HGCONSOLE_H__ */
|
|
|
@ -1,66 +0,0 @@
|
||||||
#include "HGCrash.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
#include <Dbghelp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static HGCrashFunc g_crashFunc = NULL;
|
|
||||||
static HGPointer g_crashParam = NULL;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
static _EXCEPTION_POINTERS* g_exceptionInfo = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
static LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS* exceptionInfo)
|
|
||||||
{
|
|
||||||
g_exceptionInfo = exceptionInfo;
|
|
||||||
if (NULL != g_crashFunc)
|
|
||||||
g_crashFunc(exceptionInfo->ExceptionRecord->ExceptionAddress, g_crashParam);
|
|
||||||
g_exceptionInfo = NULL;
|
|
||||||
|
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_RegisterCrashFunc(HGCrashFunc func, HGPointer param)
|
|
||||||
{
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
g_crashFunc = func;
|
|
||||||
g_crashParam = param;
|
|
||||||
SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
#else
|
|
||||||
return HGBASE_ERR_NOTIMPL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_MakeCrashFile(const HGChar* filePath)
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL == g_exceptionInfo)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE hFile = CreateFileA(filePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (INVALID_HANDLE_VALUE == hFile)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
MINIDUMP_EXCEPTION_INFORMATION mdei;
|
|
||||||
mdei.ThreadId = GetCurrentThreadId();
|
|
||||||
mdei.ExceptionPointers = g_exceptionInfo;
|
|
||||||
mdei.ClientPointers = TRUE;
|
|
||||||
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, NULL, NULL);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
#else
|
|
||||||
return HGBASE_ERR_NOTIMPL;
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#ifndef __HGCRASH_H__
|
|
||||||
#define __HGCRASH_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
typedef void (HGAPI *HGCrashFunc)(HGPointer crashAddr, HGPointer param);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_RegisterCrashFunc(HGCrashFunc func, HGPointer param);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_MakeCrashFile(const HGChar *filePath);
|
|
||||||
|
|
||||||
#endif /* __HGCRASH_H__ */
|
|
|
@ -1,146 +0,0 @@
|
||||||
#ifndef __HGDEF_H__
|
|
||||||
#define __HGDEF_H__
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Platform Dependent Definitions and Typedefs *
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* Microsoft C/C++ Compiler */
|
|
||||||
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) || defined (_WINDOWS)
|
|
||||||
|
|
||||||
#define HG_CMP_MSC
|
|
||||||
#if defined(_WIN64) || defined(WIN64)
|
|
||||||
#define HG_64BIT
|
|
||||||
#elif defined(_WIN32) || defined(WIN32)
|
|
||||||
#define HG_32BIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Apple Compiler (which is GNU now) */
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
|
|
||||||
#define HG_CMP_XCODE
|
|
||||||
#define HG_64BIT
|
|
||||||
|
|
||||||
/* GNU C/C++ Compiler */
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
|
|
||||||
#define HG_CMP_GNU
|
|
||||||
#if defined(__alpha__) || defined(__ia64__) || defined(__ppc64__) || defined(__s390x__) || defined(__x86_64__)
|
|
||||||
#define HG_64BIT
|
|
||||||
#else
|
|
||||||
#define HG_32BIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Unrecognized */
|
|
||||||
#else
|
|
||||||
|
|
||||||
#error Unrecognized compiler
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* type defines */
|
|
||||||
typedef void HGVoid;
|
|
||||||
typedef char HGChar;
|
|
||||||
typedef unsigned char HGByte;
|
|
||||||
typedef short HGShort;
|
|
||||||
typedef unsigned short HGUShort;
|
|
||||||
typedef int HGInt;
|
|
||||||
typedef unsigned int HGUInt;
|
|
||||||
typedef long long HGLonglong;
|
|
||||||
typedef unsigned long long HGULonglong;
|
|
||||||
typedef void* HGPointer;
|
|
||||||
typedef HGInt HGBool;
|
|
||||||
typedef float HGFloat;
|
|
||||||
typedef double HGDouble;
|
|
||||||
#ifdef HG_64BIT
|
|
||||||
typedef HGLonglong HGSize;
|
|
||||||
typedef HGULonglong HGUSize;
|
|
||||||
#else
|
|
||||||
typedef HGInt HGSize;
|
|
||||||
typedef HGUInt HGUSize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef HGUInt HGColor;
|
|
||||||
|
|
||||||
#define HG_MAKECOLOR(r, g, b, a) (HGColor)(((HGUInt)a << 24) | ((HGUInt)b << 16) | ((HGUInt)g << 8) | (HGUInt)r)
|
|
||||||
#define HG_GETCOLOR_R(color) (HGUInt)((HGColor)color & 0xFF)
|
|
||||||
#define HG_GETCOLOR_G(color) (HGUInt)(((HGColor)color >> 8) & 0xFF)
|
|
||||||
#define HG_GETCOLOR_B(color) (HGUInt)(((HGColor)color >> 16) & 0xFF)
|
|
||||||
#define HG_GETCOLOR_A(color) (HGUInt)(((HGColor)color >> 24) & 0xFF)
|
|
||||||
|
|
||||||
/* error code */
|
|
||||||
typedef HGUInt HGResult;
|
|
||||||
|
|
||||||
#define HGTRUE 1
|
|
||||||
#define HGFALSE 0
|
|
||||||
|
|
||||||
#ifndef HGMAX
|
|
||||||
#define HGMAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
#ifndef HGMIN
|
|
||||||
#define HGMIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define HGEXPORT extern "C"
|
|
||||||
#else
|
|
||||||
#define HGEXPORT
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
#define HGAPI __stdcall
|
|
||||||
#define HGAPIV __cdecl
|
|
||||||
#else
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define HGEXPORT extern "C" __attribute ((visibility("default")))
|
|
||||||
#else
|
|
||||||
#define HGEXPORT __attribute ((visibility("default")))
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
#define HGAPI
|
|
||||||
#define HGAPIV
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define HG_DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGInt left;
|
|
||||||
HGInt top;
|
|
||||||
HGInt right;
|
|
||||||
HGInt bottom;
|
|
||||||
}HGRect;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGFloat left;
|
|
||||||
HGFloat top;
|
|
||||||
HGFloat right;
|
|
||||||
HGFloat bottom;
|
|
||||||
}HGRectF;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGInt x;
|
|
||||||
HGInt y;
|
|
||||||
}HGPoint;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGFloat x;
|
|
||||||
HGFloat y;
|
|
||||||
}HGPointF;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#endif /* __HGDEF_H__ */
|
|
|
@ -1,472 +0,0 @@
|
||||||
#include "HGDes.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
/* 初始置换表IP */
|
|
||||||
static HGByte IP_Table[64] =
|
|
||||||
{
|
|
||||||
57, 49, 41, 33, 25, 17, 9, 1,
|
|
||||||
59, 51, 43, 35, 27, 19, 11, 3,
|
|
||||||
61, 53, 45, 37, 29, 21, 13, 5,
|
|
||||||
63, 55, 47, 39, 31, 23, 15, 7,
|
|
||||||
56, 48, 40, 32, 24, 16, 8, 0,
|
|
||||||
58, 50, 42, 34, 26, 18, 10, 2,
|
|
||||||
60, 52, 44, 36, 28, 20, 12, 4,
|
|
||||||
62, 54, 46, 38, 30, 22, 14, 6
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 逆初始置换表IP^-1 */
|
|
||||||
static HGByte IP_1_Table[64] =
|
|
||||||
{
|
|
||||||
39, 7, 47, 15, 55, 23, 63, 31,
|
|
||||||
38, 6, 46, 14, 54, 22, 62, 30,
|
|
||||||
37, 5, 45, 13, 53, 21, 61, 29,
|
|
||||||
36, 4, 44, 12, 52, 20, 60, 28,
|
|
||||||
35, 3, 43, 11, 51, 19, 59, 27,
|
|
||||||
34, 2, 42, 10, 50, 18, 58, 26,
|
|
||||||
33, 1, 41, 9, 49, 17, 57, 25,
|
|
||||||
32, 0, 40, 8, 48, 16, 56, 24
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 扩充置换表E */
|
|
||||||
static HGByte E_Table[48] =
|
|
||||||
{
|
|
||||||
31, 0, 1, 2, 3, 4,
|
|
||||||
3, 4, 5, 6, 7, 8,
|
|
||||||
7, 8, 9,10, 11, 12,
|
|
||||||
11, 12, 13, 14, 15, 16,
|
|
||||||
15, 16, 17, 18, 19, 20,
|
|
||||||
19, 20, 21, 22, 23, 24,
|
|
||||||
23, 24, 25, 26, 27, 28,
|
|
||||||
27, 28, 29, 30, 31, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 置换函数P */
|
|
||||||
static HGByte P_Table[32] =
|
|
||||||
{
|
|
||||||
15, 6, 19, 20, 28, 11, 27, 16,
|
|
||||||
0, 14, 22, 25, 4, 17, 30, 9,
|
|
||||||
1, 7, 23, 13, 31, 26, 2, 8,
|
|
||||||
18, 12, 29, 5, 21, 10, 3, 24
|
|
||||||
};
|
|
||||||
|
|
||||||
/* S盒 */
|
|
||||||
static HGByte S[8][4][16] =
|
|
||||||
{
|
|
||||||
/* S1 */
|
|
||||||
14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,
|
|
||||||
0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
|
|
||||||
4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
|
|
||||||
15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13,
|
|
||||||
|
|
||||||
/* S2 */
|
|
||||||
15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,
|
|
||||||
3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,
|
|
||||||
0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,
|
|
||||||
13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9,
|
|
||||||
|
|
||||||
/* S3 */
|
|
||||||
10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,
|
|
||||||
13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,
|
|
||||||
13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,
|
|
||||||
1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12,
|
|
||||||
|
|
||||||
/* S4 */
|
|
||||||
7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,
|
|
||||||
13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,
|
|
||||||
10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,
|
|
||||||
3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14,
|
|
||||||
|
|
||||||
/* S5 */
|
|
||||||
2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,
|
|
||||||
14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,
|
|
||||||
4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,
|
|
||||||
11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3,
|
|
||||||
|
|
||||||
/* S6 */
|
|
||||||
12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,
|
|
||||||
10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,
|
|
||||||
9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,
|
|
||||||
4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13,
|
|
||||||
|
|
||||||
/* S7 */
|
|
||||||
4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,
|
|
||||||
13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,
|
|
||||||
1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,
|
|
||||||
6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12,
|
|
||||||
|
|
||||||
/* S8 */
|
|
||||||
13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,
|
|
||||||
1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,
|
|
||||||
7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,
|
|
||||||
2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 置换选择1 */
|
|
||||||
static HGByte PC_1[56] =
|
|
||||||
{
|
|
||||||
56,48,40,32,24,16,8,
|
|
||||||
0,57,49,41,33,25,17,
|
|
||||||
9,1,58,50,42,34,26,
|
|
||||||
18,10,2,59,51,43,35,
|
|
||||||
62,54,46,38,30,22,14,
|
|
||||||
6,61,53,45,37,29,21,
|
|
||||||
13,5,60,52,44,36,28,
|
|
||||||
20,12,4,27,19,11,3
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 置换选择2 */
|
|
||||||
static HGByte PC_2[48] =
|
|
||||||
{
|
|
||||||
13,16,10,23,0,4,2,27,
|
|
||||||
14,5,20,9,22,18,11,3,
|
|
||||||
25,7,15,6,26,19,12,1,
|
|
||||||
40,51,30,36,46,54,29,39,
|
|
||||||
50,44,32,46,43,48,38,55,
|
|
||||||
33,52,45,41,49,35,28,31
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 对左移次数的规定 */
|
|
||||||
static HGByte MOVE_TIMES[16] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };
|
|
||||||
|
|
||||||
|
|
||||||
static int ByteToBit8(HGByte ch, HGByte bit[8])
|
|
||||||
{
|
|
||||||
for (int cnt = 0; cnt < 8; cnt++)
|
|
||||||
{
|
|
||||||
*(bit + cnt) = (ch >> cnt) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int Bit8ToByte(const HGByte bit[8], HGByte* ch)
|
|
||||||
{
|
|
||||||
if (NULL == ch)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
*ch = 0;
|
|
||||||
for (int cnt = 0; cnt < 8; cnt++)
|
|
||||||
{
|
|
||||||
*ch |= *(bit + cnt) << cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int Byte8ToBit64(const HGByte ch[8], HGByte bit[64])
|
|
||||||
{
|
|
||||||
for (int cnt = 0; cnt < 8; cnt++)
|
|
||||||
{
|
|
||||||
ByteToBit8(*(ch + cnt), bit + (cnt << 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int Bit64ToByte8(HGByte bit[64], HGByte ch[8])
|
|
||||||
{
|
|
||||||
memset(ch, 0, 8);
|
|
||||||
for (int cnt = 0; cnt < 8; cnt++)
|
|
||||||
{
|
|
||||||
Bit8ToByte(bit + (cnt << 3), ch + cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 密钥置换1 */
|
|
||||||
static int DES_PC1_Transform(HGByte key[64], HGByte tempbts[56])
|
|
||||||
{
|
|
||||||
for (int cnt = 0; cnt < 56; cnt++)
|
|
||||||
{
|
|
||||||
tempbts[cnt] = key[PC_1[cnt]];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 密钥置换2 */
|
|
||||||
static int DES_PC2_Transform(HGByte key[56], HGByte tempbts[48])
|
|
||||||
{
|
|
||||||
for (int cnt = 0; cnt < 48; cnt++)
|
|
||||||
{
|
|
||||||
tempbts[cnt] = key[PC_2[cnt]];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 循环左移 */
|
|
||||||
static int DES_ROL(HGByte data[56], int time)
|
|
||||||
{
|
|
||||||
HGByte temp[56];
|
|
||||||
HGByte temp2[28];
|
|
||||||
|
|
||||||
/* 保存将要循环移动到右边的位 */
|
|
||||||
memcpy(temp, data, time);
|
|
||||||
memcpy(temp + time, data + 28, time);
|
|
||||||
|
|
||||||
/* 前28位移动 */
|
|
||||||
//memcpy(data, data + time, 28 - time);
|
|
||||||
memcpy(temp2, data + time, 28 - time);
|
|
||||||
memcpy(data, temp2, 28 - time);
|
|
||||||
memcpy(data + 28 - time, temp, time);
|
|
||||||
|
|
||||||
/* 后28位移动 */
|
|
||||||
//memcpy(data + 28, data + 28 + time, 28 - time);
|
|
||||||
memcpy(temp2, data + 28 + time, 28 - time);
|
|
||||||
memcpy(data + 28, temp2, 28 - time);
|
|
||||||
memcpy(data + 56 - time, temp + time, time);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 生成子密钥 */
|
|
||||||
static int DES_MakeSubKeys(HGByte key[64], HGByte subKeys[16][48])
|
|
||||||
{
|
|
||||||
HGByte temp[56];
|
|
||||||
DES_PC1_Transform(key, temp); /* PC1置换 */
|
|
||||||
|
|
||||||
for (int cnt = 0; cnt < 16; cnt++)
|
|
||||||
{
|
|
||||||
/* 16轮跌代,产生16个子密钥 */
|
|
||||||
DES_ROL(temp, MOVE_TIMES[cnt]); /* 循环左移 */
|
|
||||||
DES_PC2_Transform(temp, subKeys[cnt]); /* PC2置换,产生子密钥 */
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IP置换 */
|
|
||||||
static int DES_IP_Transform(HGByte data[64])
|
|
||||||
{
|
|
||||||
HGByte temp[64];
|
|
||||||
for (int cnt = 0; cnt < 64; cnt++)
|
|
||||||
{
|
|
||||||
temp[cnt] = data[IP_Table[cnt]];
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data, temp, 64);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IP逆置换 */
|
|
||||||
static int DES_IP_1_Transform(HGByte data[64])
|
|
||||||
{
|
|
||||||
HGByte temp[64];
|
|
||||||
for (int cnt = 0; cnt < 64; cnt++)
|
|
||||||
{
|
|
||||||
temp[cnt] = data[IP_1_Table[cnt]];
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data, temp, 64);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 扩展置换 */
|
|
||||||
static int DES_E_Transform(HGByte data[48])
|
|
||||||
{
|
|
||||||
HGByte temp[48];
|
|
||||||
for (int cnt = 0; cnt < 48; cnt++)
|
|
||||||
{
|
|
||||||
temp[cnt] = data[E_Table[cnt]];
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data, temp, 48);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* P置换 */
|
|
||||||
static int DES_P_Transform(HGByte data[32])
|
|
||||||
{
|
|
||||||
HGByte temp[32];
|
|
||||||
for (int cnt = 0; cnt < 32; cnt++)
|
|
||||||
{
|
|
||||||
temp[cnt] = data[P_Table[cnt]];
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data, temp, 32);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 异或 */
|
|
||||||
static int DES_XOR(HGByte R[48], HGByte L[48], int count)
|
|
||||||
{
|
|
||||||
for (int cnt = 0; cnt < count; cnt++)
|
|
||||||
{
|
|
||||||
R[cnt] ^= L[cnt];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* S盒置换 */
|
|
||||||
static int DES_SBOX(HGByte data[48])
|
|
||||||
{
|
|
||||||
for (int cnt = 0; cnt < 8; cnt++)
|
|
||||||
{
|
|
||||||
int cur1 = cnt * 6;
|
|
||||||
int cur2 = cnt << 2;
|
|
||||||
|
|
||||||
/* 计算在S盒中的行与列 */
|
|
||||||
int line = (data[cur1] << 1) + data[cur1 + 5];
|
|
||||||
int row = (data[cur1 + 1] << 3) + (data[cur1 + 2] << 2) + (data[cur1 + 3] << 1) + data[cur1 + 4];
|
|
||||||
int output = S[cnt][line][row];
|
|
||||||
|
|
||||||
/* 化为2进制 */
|
|
||||||
data[cur2] = (output & 0X08) >> 3;
|
|
||||||
data[cur2 + 1] = (output & 0X04) >> 2;
|
|
||||||
data[cur2 + 2] = (output & 0X02) >> 1;
|
|
||||||
data[cur2 + 3] = output & 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 交换 */
|
|
||||||
static int DES_Swap(HGByte left[32], HGByte right[32])
|
|
||||||
{
|
|
||||||
HGByte temp[32];
|
|
||||||
memcpy(temp, left, 32);
|
|
||||||
memcpy(left, right, 32);
|
|
||||||
memcpy(right, temp, 32);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 加密单个分组 */
|
|
||||||
static int DES_EncryptBlock(HGByte plainBlock[8], HGByte subKeys[16][48], HGByte cipherBlock[8])
|
|
||||||
{
|
|
||||||
HGByte plainBits[64];
|
|
||||||
HGByte copyRight[48];
|
|
||||||
|
|
||||||
Byte8ToBit64(plainBlock, plainBits);
|
|
||||||
/* 初始置换(IP置换) */
|
|
||||||
DES_IP_Transform(plainBits);
|
|
||||||
|
|
||||||
/* 16轮迭代 */
|
|
||||||
for (int cnt = 0; cnt < 16; cnt++)
|
|
||||||
{
|
|
||||||
memcpy(copyRight, plainBits + 32, 32);
|
|
||||||
|
|
||||||
/* 将右半部分进行扩展置换,从32位扩展到48位 */
|
|
||||||
DES_E_Transform(copyRight);
|
|
||||||
/* 将右半部分与子密钥进行异或操作 */
|
|
||||||
DES_XOR(copyRight, subKeys[cnt], 48);
|
|
||||||
/* 异或结果进入S盒,输出32位结果 */
|
|
||||||
DES_SBOX(copyRight);
|
|
||||||
/* P置换 */
|
|
||||||
DES_P_Transform(copyRight);
|
|
||||||
/* 将明文左半部分与右半部分进行异或 */
|
|
||||||
DES_XOR(plainBits, copyRight, 32);
|
|
||||||
|
|
||||||
if (cnt != 15)
|
|
||||||
{
|
|
||||||
/* 最终完成左右部的交换 */
|
|
||||||
DES_Swap(plainBits, plainBits + 32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 逆初始置换(IP^1置换) */
|
|
||||||
DES_IP_1_Transform(plainBits);
|
|
||||||
Bit64ToByte8(plainBits, cipherBlock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 解密单个分组 */
|
|
||||||
|
|
||||||
static int DES_DecryptBlock(HGByte cipherBlock[8], HGByte subKeys[16][48], HGByte plainBlock[8])
|
|
||||||
{
|
|
||||||
HGByte cipherBits[64];
|
|
||||||
HGByte copyRight[48];
|
|
||||||
|
|
||||||
Byte8ToBit64(cipherBlock, cipherBits);
|
|
||||||
/* 初始置换(IP置换) */
|
|
||||||
DES_IP_Transform(cipherBits);
|
|
||||||
|
|
||||||
/* 16轮迭代 */
|
|
||||||
for (int cnt = 15; cnt >= 0; cnt--)
|
|
||||||
{
|
|
||||||
memcpy(copyRight, cipherBits + 32, 32);
|
|
||||||
|
|
||||||
/* 将右半部分进行扩展置换,从32位扩展到48位 */
|
|
||||||
DES_E_Transform(copyRight);
|
|
||||||
/* 将右半部分与子密钥进行异或操作 */
|
|
||||||
DES_XOR(copyRight, subKeys[cnt], 48);
|
|
||||||
/* 异或结果进入S盒,输出32位结果 */
|
|
||||||
DES_SBOX(copyRight);
|
|
||||||
/* P置换 */
|
|
||||||
DES_P_Transform(copyRight);
|
|
||||||
/* 将明文左半部分与右半部分进行异或 */
|
|
||||||
DES_XOR(cipherBits, copyRight, 32);
|
|
||||||
|
|
||||||
if (cnt != 0)
|
|
||||||
{
|
|
||||||
/* 最终完成左右部的交换 */
|
|
||||||
DES_Swap(cipherBits, cipherBits + 32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 逆初始置换(IP^1置换) */
|
|
||||||
DES_IP_1_Transform(cipherBits);
|
|
||||||
Bit64ToByte8(cipherBits, plainBlock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DesEncrypt(HGByte* data, HGUInt size, const HGByte* key)
|
|
||||||
{
|
|
||||||
if (NULL == data || 0 == size || 0 != size % 8 || NULL == key)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte bKey[64];
|
|
||||||
HGByte subKeys[16][48];
|
|
||||||
HGByte plainBlock[8];
|
|
||||||
|
|
||||||
/* 将密钥转换为二进制流 */
|
|
||||||
Byte8ToBit64(key, bKey);
|
|
||||||
/* 生成子密钥 */
|
|
||||||
DES_MakeSubKeys(bKey, subKeys);
|
|
||||||
|
|
||||||
HGByte* p = data;
|
|
||||||
HGByte* pe = data + size;
|
|
||||||
while (p < pe)
|
|
||||||
{
|
|
||||||
memcpy(plainBlock, p, 8);
|
|
||||||
DES_EncryptBlock(plainBlock, subKeys, p);
|
|
||||||
p += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DesDecrypt(HGByte* data, HGUInt size, const HGByte* key)
|
|
||||||
{
|
|
||||||
if (NULL == data || 0 == size || 0 != size % 8 || NULL == key)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte bKey[64];
|
|
||||||
HGByte subKeys[16][48];
|
|
||||||
HGByte cipherBlock[8];
|
|
||||||
|
|
||||||
/* 将密钥转换为二进制流 */
|
|
||||||
Byte8ToBit64(key, bKey);
|
|
||||||
/* 生成子密钥 */
|
|
||||||
DES_MakeSubKeys(bKey, subKeys);
|
|
||||||
|
|
||||||
HGByte* p = data;
|
|
||||||
HGByte* pe = data + size;
|
|
||||||
while (p < pe)
|
|
||||||
{
|
|
||||||
memcpy(cipherBlock, p, 8);
|
|
||||||
DES_DecryptBlock(cipherBlock, subKeys, p);
|
|
||||||
p += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
#ifndef __HGDES_H__
|
|
||||||
#define __HGDES_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
/* DES加密
|
|
||||||
* 参数:
|
|
||||||
* 1) data: in, out, 明文
|
|
||||||
* 2) size: in, 明文尺寸, 必须是8的倍数
|
|
||||||
* 3) key: in, 加密密钥, 为8字节数组
|
|
||||||
* 说明:
|
|
||||||
* 1) 加密后的密文会覆盖明文,如果需要保留明文,需要提前保存
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DesEncrypt(HGByte* data, HGUInt size, const HGByte* key);
|
|
||||||
|
|
||||||
/* DES解密
|
|
||||||
* 参数:
|
|
||||||
* 1) data: in, out, 密文
|
|
||||||
* 2) size: in, 密文尺寸, 必须是8的倍数
|
|
||||||
* 3) key: in, 解密密钥, 为8字节数组
|
|
||||||
* 说明:
|
|
||||||
* 1) 解密后的明文会覆盖密文,如果需要保留密文,需要提前保存
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DesDecrypt(HGByte* data, HGUInt size, const HGByte* key);
|
|
||||||
|
|
||||||
#endif /* __HGDES_H__ */
|
|
|
@ -1,94 +0,0 @@
|
||||||
#include "HGDll.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
#include "HGInfo.h"
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct HGDllImpl
|
|
||||||
{
|
|
||||||
HGDllImpl()
|
|
||||||
{
|
|
||||||
m_hDll = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
~HGDllImpl()
|
|
||||||
{
|
|
||||||
if (NULL != m_hDll)
|
|
||||||
{
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
dlclose(m_hDll);
|
|
||||||
#else
|
|
||||||
FreeLibrary(m_hDll);
|
|
||||||
#endif
|
|
||||||
m_hDll = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
void* m_hDll;
|
|
||||||
#else
|
|
||||||
HMODULE m_hDll;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateDll(const HGChar* fileName, HGDll* dll)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == dll)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
void* hDll = dlopen(fileName, RTLD_LAZY);
|
|
||||||
if (NULL == hDll)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGBase_CreateDll: dlopen fail, %s dlerror=%s", fileName, dlerror());
|
|
||||||
return HGBASE_ERR_LOADLIBRARY;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
HMODULE hDll = LoadLibraryExA((const char *)fileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
|
||||||
if (NULL == hDll)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGBase_CreateDll: LoadLibraryExA fail, %s GetLastError=%u", fileName, GetLastError());
|
|
||||||
return HGBASE_ERR_LOADLIBRARY;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
HGDllImpl* dllImpl = new HGDllImpl;
|
|
||||||
dllImpl->m_hDll = hDll;
|
|
||||||
*dll = (HGDll)dllImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DestroyDll(HGDll dll)
|
|
||||||
{
|
|
||||||
if (NULL == dll)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGDllImpl* dllImpl = (HGDllImpl*)dll;
|
|
||||||
delete dllImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetDllProcAddress(HGDll dll, const HGChar* symbol, HGPointer* func)
|
|
||||||
{
|
|
||||||
if (NULL == dll || NULL == symbol || NULL == func)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGDllImpl* dllImpl = (HGDllImpl*)dll;
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
*func = dlsym(dllImpl->m_hDll, symbol);
|
|
||||||
#else
|
|
||||||
* func = GetProcAddress(dllImpl->m_hDll, (const char *)symbol);
|
|
||||||
#endif
|
|
||||||
if (NULL == *func)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
#ifndef __HGDLL_H__
|
|
||||||
#define __HGDLL_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGDll);
|
|
||||||
|
|
||||||
/* 加载DLL
|
|
||||||
* 参数:
|
|
||||||
* 1) fileName: in, dll/so文件路径, 可以是绝对路径或相对路径
|
|
||||||
* 2) dll: out, DLL句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 在windows系统上, fileName需要是GBK编码
|
|
||||||
* 2) 在linux系统上, fileName需要是UTF8编码
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateDll(const HGChar* fileName, HGDll* dll);
|
|
||||||
|
|
||||||
/* 销毁DLL
|
|
||||||
* 参数:
|
|
||||||
* 1) dll: in, DLL句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DestroyDll(HGDll dll);
|
|
||||||
|
|
||||||
/* 查找函数地址
|
|
||||||
* 参数:
|
|
||||||
* 1) dll: in, DLL句柄
|
|
||||||
* 2) symbol: in, 函数名
|
|
||||||
* 3) func: out, 函数地址
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetDllProcAddress(HGDll dll, const HGChar* symbol, HGPointer* func);
|
|
||||||
|
|
||||||
#endif /* __HGDLL_H__ */
|
|
|
@ -1,238 +0,0 @@
|
||||||
#include "HGEvent.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
struct event_t
|
|
||||||
{
|
|
||||||
HGBool state;
|
|
||||||
HGBool manual_reset;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_cond_t cond;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateEvent(HGBool manualReset, HGBool initState, HGEvent* event)
|
|
||||||
{
|
|
||||||
if (NULL == event)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
event_t* hEvent = new event_t;
|
|
||||||
|
|
||||||
hEvent->state = initState;
|
|
||||||
hEvent->manual_reset = manualReset;
|
|
||||||
if (0 != pthread_mutex_init(&hEvent->mutex, NULL))
|
|
||||||
{
|
|
||||||
delete hEvent;
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
if (0 != pthread_cond_init(&hEvent->cond, NULL))
|
|
||||||
{
|
|
||||||
pthread_mutex_destroy(&hEvent->mutex);
|
|
||||||
delete hEvent;
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
*event = (HGEvent)hEvent;
|
|
||||||
#else
|
|
||||||
HANDLE hEvent = CreateEventW(NULL, (BOOL)manualReset, (BOOL)initState, NULL);
|
|
||||||
*event = (HGEvent)hEvent;
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DestroyEvent(HGEvent event)
|
|
||||||
{
|
|
||||||
if (NULL == event)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
event_t* hEvent = (event_t*)event;
|
|
||||||
pthread_cond_destroy(&hEvent->cond);
|
|
||||||
pthread_mutex_destroy(&hEvent->mutex);
|
|
||||||
delete hEvent;
|
|
||||||
#else
|
|
||||||
HANDLE hEvent = (HANDLE)event;
|
|
||||||
CloseHandle(hEvent);
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_WaitEvent(HGEvent event)
|
|
||||||
{
|
|
||||||
if (NULL == event)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
event_t* hEvent = (event_t*)event;
|
|
||||||
if (0 != pthread_mutex_lock(&hEvent->mutex))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
while (!hEvent->state)
|
|
||||||
{
|
|
||||||
if (0 != pthread_cond_wait(&hEvent->cond, &hEvent->mutex))
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&hEvent->mutex);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hEvent->manual_reset)
|
|
||||||
{
|
|
||||||
hEvent->state = HGFALSE;
|
|
||||||
}
|
|
||||||
if (0 != pthread_mutex_unlock(&hEvent->mutex))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
HANDLE hEvent = (HANDLE)event;
|
|
||||||
DWORD ret = WaitForSingleObject(hEvent, INFINITE);
|
|
||||||
if (WAIT_OBJECT_0 != ret)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_WaitEventTimeout(HGEvent event, HGUInt milliseconds)
|
|
||||||
{
|
|
||||||
if (NULL == event)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
struct timespec abstime;
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
abstime.tv_sec = tv.tv_sec + milliseconds / 1000;
|
|
||||||
abstime.tv_nsec = tv.tv_usec * 1000 + (milliseconds % 1000) * 1000000;
|
|
||||||
if (abstime.tv_nsec >= 1000000000)
|
|
||||||
{
|
|
||||||
abstime.tv_nsec -= 1000000000;
|
|
||||||
abstime.tv_sec++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc = 0;
|
|
||||||
event_t* hEvent = (event_t*)event;
|
|
||||||
if (pthread_mutex_lock(&hEvent->mutex) != 0)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
while (!hEvent->state)
|
|
||||||
{
|
|
||||||
rc = pthread_cond_timedwait(&hEvent->cond, &hEvent->mutex, &abstime);
|
|
||||||
if (0 != rc)
|
|
||||||
{
|
|
||||||
if (rc == ETIMEDOUT)
|
|
||||||
break;
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&hEvent->mutex);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rc == 0 && !hEvent->manual_reset)
|
|
||||||
{
|
|
||||||
hEvent->state = HGFALSE;
|
|
||||||
}
|
|
||||||
if (pthread_mutex_unlock(&hEvent->mutex) != 0)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
if (rc == ETIMEDOUT)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
#else
|
|
||||||
HANDLE hEvent = (HANDLE)event;
|
|
||||||
DWORD ret = WaitForSingleObject(hEvent, milliseconds);
|
|
||||||
if (WAIT_OBJECT_0 == ret)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
else if (WAIT_TIMEOUT == ret)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_SetEvent(HGEvent event)
|
|
||||||
{
|
|
||||||
if (NULL == event)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
event_t* hEvent = (event_t*)event;
|
|
||||||
if (0 != pthread_mutex_lock(&hEvent->mutex))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hEvent->state = HGTRUE;
|
|
||||||
if (hEvent->manual_reset)
|
|
||||||
{
|
|
||||||
if (0 != pthread_cond_broadcast(&hEvent->cond))
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&hEvent->mutex);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (0 != pthread_cond_signal(&hEvent->cond))
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&hEvent->mutex);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != pthread_mutex_unlock(&hEvent->mutex))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
#else
|
|
||||||
HANDLE hEvent = (HANDLE)event;
|
|
||||||
SetEvent(hEvent);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_ResetEvent(HGEvent event)
|
|
||||||
{
|
|
||||||
if (NULL == event)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
event_t* hEvent = (event_t*)event;
|
|
||||||
if (0 != pthread_mutex_lock(&hEvent->mutex))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hEvent->state = HGFALSE;
|
|
||||||
if (0 != pthread_mutex_unlock(&hEvent->mutex))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
#else
|
|
||||||
HANDLE hEvent = (HANDLE)event;
|
|
||||||
ResetEvent(hEvent);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
#ifndef __HGEVENT_H__
|
|
||||||
#define __HGEVENT_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGEvent);
|
|
||||||
|
|
||||||
/* 创建事件
|
|
||||||
* 参数:
|
|
||||||
* 1) manualReset: in, 是否手动设置
|
|
||||||
* 2) initState: in, 初始化时是否有信号
|
|
||||||
* 3) event: out, 事件句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 当manualReset为HGTRUE时, HGBase_WaitEvent和HGBase_WaitEventTimeout调用后, 事件仍然为有信号
|
|
||||||
* 2) 当manualReset为HGFALSE时, HGBase_WaitEvent和HGBase_WaitEventTimeout调用后, 事件为无信号
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateEvent(HGBool manualReset, HGBool initState, HGEvent* event);
|
|
||||||
|
|
||||||
/* 销毁事件
|
|
||||||
* 参数:
|
|
||||||
* 1) event: in, 事件句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DestroyEvent(HGEvent event);
|
|
||||||
|
|
||||||
/* 无限等待事件
|
|
||||||
* 参数:
|
|
||||||
* 1) event: in, 事件句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 如果创建时的manualReset为HGTRUE, 返回前不会将事件置为无信号;否则,返回前会将事件置为无信号
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_WaitEvent(HGEvent event);
|
|
||||||
|
|
||||||
/* 等待事件, 带超时时间
|
|
||||||
* 参数:
|
|
||||||
* 1) event: in, 事件句柄
|
|
||||||
* 2) milliseconds: in, 超时时间, 毫秒
|
|
||||||
* 说明:
|
|
||||||
* 1) 在milliseconds时间内如果事件有信号,立即返回
|
|
||||||
* 2) 如果一直无信号, 在milliseconds毫秒后也立即返回, 返回值为HGBASE_ERR_WAIT_TIMEOUT
|
|
||||||
* 3) 如果创建时的manualReset为HGTRUE, 返回前不会将事件置为无信号;否则,返回前会将事件置为无信号
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_WaitEventTimeout(HGEvent event, HGUInt milliseconds);
|
|
||||||
|
|
||||||
/* 使事件有信号
|
|
||||||
* 参数:
|
|
||||||
* 1) event: in, 事件句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_SetEvent(HGEvent event);
|
|
||||||
|
|
||||||
/* 使事件无信号
|
|
||||||
* 参数:
|
|
||||||
* 1) event: in, 事件句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ResetEvent(HGEvent event);
|
|
||||||
|
|
||||||
#endif /* __HGEVENT_H__ */
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,391 +0,0 @@
|
||||||
#ifndef __HGIMAGE_H__
|
|
||||||
#define __HGIMAGE_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGImage);
|
|
||||||
|
|
||||||
/* 1位黑白图 */
|
|
||||||
#define HGBASE_IMGTYPE_BINARY 1L
|
|
||||||
/* 8位灰度图 */
|
|
||||||
#define HGBASE_IMGTYPE_GRAY 2L
|
|
||||||
/* 24位真彩色,B8G8R8格式 */
|
|
||||||
#define HGBASE_IMGTYPE_BGR 3L
|
|
||||||
/* 24位真彩色,R8G8B8格式 */
|
|
||||||
#define HGBASE_IMGTYPE_RGB 4L
|
|
||||||
/* 32位真彩色,带Alpha通道,B8G8R8A8格式 */
|
|
||||||
#define HGBASE_IMGTYPE_BGRA 5L
|
|
||||||
/* 32位真彩色,带Alpha通道,R8G8B8A8格式 */
|
|
||||||
#define HGBASE_IMGTYPE_RGBA 6L
|
|
||||||
|
|
||||||
/* 顶左结构 */
|
|
||||||
#define HGBASE_IMGORIGIN_TOP 1L
|
|
||||||
/* 底左结构 */
|
|
||||||
#define HGBASE_IMGORIGIN_BOTTOM 2L
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
/* 图像信息 */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 宽(像素),列数 */
|
|
||||||
HGUInt height; /* 高(像素),行数 */
|
|
||||||
HGUInt type; /* 类型,参见HGBASE_IMGTYPE_* */
|
|
||||||
HGUInt widthStep; /* 每行的字节数 */
|
|
||||||
HGUInt origin; /* 数据排列方式,参见HGBASE_IMGORIGIN_* */
|
|
||||||
}HGImageInfo;
|
|
||||||
|
|
||||||
/* 图像感兴趣区域 */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt left;
|
|
||||||
HGUInt top;
|
|
||||||
HGUInt right;
|
|
||||||
HGUInt bottom;
|
|
||||||
}HGImageRoi;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
/* 创建空白的新图像
|
|
||||||
* 参数:
|
|
||||||
* 1) width: in, 新图像宽度
|
|
||||||
* 2) height: in, 新图像高度
|
|
||||||
* 3) type: in, 新图像类型
|
|
||||||
* 4) origin: in, 新图像的数据排列方式
|
|
||||||
* 5) image: out,新图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1)在windows系统上,当type为HGBASE_IMGTYPE_BINARY、HGBASE_IMGTYPE_GRAY、HGBASE_IMGTYPE_BGR或HGBASE_IMGTYPE_BGRA时,新图像内部实际创建DIB位图(有HBITMAP),
|
|
||||||
* 否则内部分配普通内存(无HBITMAP); 在linux系统上,新图像内部分配普通内存(无HBITMAP)
|
|
||||||
* 2) 新图像的width=width; 新图像的height=height; 新图像的type=type; 新图像的widthStep为4字节对齐; 新图像的origin=origin
|
|
||||||
* 3) 新图像的roi为{0, 0, width, height}
|
|
||||||
* 4) 新图像的xdpi=96, ydpi=96
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateImage(HGUInt width, HGUInt height, HGUInt type, HGUInt origin, HGImage* image);
|
|
||||||
|
|
||||||
/* 从源数据创建新图像(不分配内存, 也不拷贝数据)
|
|
||||||
* 参数:
|
|
||||||
* 1) data: in, 源数据的地址
|
|
||||||
* 2) info: in, 源数据的图像信息
|
|
||||||
* 3) image: out,新图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 新图像内部不会分配普通像素内存,也不会创建DIB位图(windows系统上, 无HBITMAP),而是直接使用源数据, 在该图像销毁之前需要保证源数据一直有效
|
|
||||||
* 2) 新图像的width=info->width; 新图像的height=info->height; 新图像的type=info->type; 新图像的widthStep=info->widthStep;
|
|
||||||
* 新图像的origin=info->origin
|
|
||||||
* 3) 新图像的roi为{0, 0, width, height}
|
|
||||||
* 4) 新图像的xdpi=96, ydpi=96
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateImageWithData(HGByte* data, const HGImageInfo* info, HGImage* image);
|
|
||||||
|
|
||||||
/* 从源数据创建新图像
|
|
||||||
* 参数:
|
|
||||||
* 1) data: in, 源数据的地址
|
|
||||||
* 2) info: in, 源数据的图像信息
|
|
||||||
* 3) roi: in, 源数据的感兴趣区域, NULL表示整个图像区域
|
|
||||||
* 4) type: in, 新图像的类型, 0表示和源数据一样
|
|
||||||
* 5) origin: in, 新图像的数据排列方式, 0表示和源数据一样
|
|
||||||
* 6) image: out,新图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1)在windows系统上,当type为HGBASE_IMGTYPE_BINARY、HGBASE_IMGTYPE_GRAY、HGBASE_IMGTYPE_BGR或HGBASE_IMGTYPE_BGRA时,新图像内部实际创建DIB位图(有HBITMAP),
|
|
||||||
* 否则内部分配普通内存(无HBITMAP); 在linux系统上,新图像内部分配普通内存(无HBITMAP)
|
|
||||||
* 2) 新图像的width=roi->right-roi->left; 新图像的height=roi->bottom-roi->top; 新图像的type=type; 新图像的widthStep为4字节对齐;
|
|
||||||
* 新图像的origin=origin, 如果origin和info->origin不一致,拷贝时像素会进行上下翻转
|
|
||||||
* 3) 新图像的roi为{0, 0, width, height}
|
|
||||||
* 4) 新图像的xdpi=96, ydpi=96
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateImageFromData(HGByte* data, const HGImageInfo *info, const HGImageRoi *roi,
|
|
||||||
HGUInt type, HGUInt origin, HGImage* image);
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
|
|
||||||
/* 从DIB位图创建新图像
|
|
||||||
* 参数:
|
|
||||||
* 1) hBmp: in, DIB位图句柄
|
|
||||||
* 2) roi: DIB位图的感兴趣区域, NULL表示整个图像区域
|
|
||||||
* 3) type: in, 新图像的类型, 0表示自动生成和DIB位图最接近的type
|
|
||||||
* 4) origin: in, 新图像的数据排列方式, 必须指定
|
|
||||||
* 5) image: out,新图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1)当type为HGBASE_IMGTYPE_BINARY、HGBASE_IMGTYPE_GRAY、HGBASE_IMGTYPE_BGR或HGBASE_IMGTYPE_BGRA时,新图像内部实际创建DIB位图(有HBITMAP),
|
|
||||||
* 否则内部分配普通内存(无HBITMAP)
|
|
||||||
* 2) 新图像的width=roi->right-roi->left; 新图像的height=roi->bottom-roi->top; 新图像的type=type; 新图像的widthStep为4字节对齐;
|
|
||||||
* 新图像的origin=origin
|
|
||||||
* 3) 新图像的roi为{0, 0, width, height}
|
|
||||||
* 4) 新图像的xdpi=hBmp的xDPI, ydpi=hBmp的yDPI
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateImageFromHBITMAP(HBITMAP hBmp, const HGImageRoi* roi,
|
|
||||||
HGUInt type, HGUInt origin, HGImage* image);
|
|
||||||
|
|
||||||
/* 从DIB内存创建新图像
|
|
||||||
* 参数:
|
|
||||||
* 1) hMem: in, DIB内存句柄
|
|
||||||
* 2) roi: DIB内存的感兴趣区域, NULL表示整个图像区域
|
|
||||||
* 3) type: in, 新图像的类型, 0表示自动生成和DIB内存最接近的type
|
|
||||||
* 4) origin: in, 新图像的数据排列方式, 必须指定
|
|
||||||
* 5) image: out,新图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1)当type为HGBASE_IMGTYPE_BINARY、HGBASE_IMGTYPE_GRAY、HGBASE_IMGTYPE_BGR或HGBASE_IMGTYPE_BGRA时,新图像内部实际创建DIB位图(有HBITMAP),
|
|
||||||
* 否则内部分配普通内存(无HBITMAP)
|
|
||||||
* 2) 新图像的width=roi->right-roi->left; 新图像的height=roi->bottom-roi->top; 新图像的type=type; 新图像的widthStep为4字节对齐;
|
|
||||||
* 新图像的origin=origin
|
|
||||||
* 3) 新图像的roi为{0, 0, width, height}
|
|
||||||
* 4) 新图像的xdpi=DIB的xDPI, ydpi=DIB的yDPI
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateImageFromDIB(HGLOBAL hMem, const HGImageRoi* roi,
|
|
||||||
HGUInt type, HGUInt origin, HGImage* image);
|
|
||||||
|
|
||||||
#endif /* HG_CMP_MSC */
|
|
||||||
|
|
||||||
/* 从源图像创建新图像
|
|
||||||
* 参数:
|
|
||||||
* 1) srcImage: in, 源图像
|
|
||||||
* 2) type: in, 新图像的类型, 0表示和源图像一样
|
|
||||||
* 3) origin: in, 新图像的数据排列方式, 0表示和源图像一样
|
|
||||||
* 4) image: out,新图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1)在windows系统上,当type为HGBASE_IMGTYPE_BINARY、HGBASE_IMGTYPE_GRAY、HGBASE_IMGTYPE_BGR或HGBASE_IMGTYPE_BGRA时,新图像内部实际创建DIB位图(有HBITMAP),
|
|
||||||
* 否则内部分配普通内存(无HBITMAP); 在linux系统上,新图像内部分配普通内存(无HBITMAP)
|
|
||||||
* 2) 新图像的width=srcImage->roi.right-srcImage->roi.left; 新图像的height=srcImage->roi.bottom-srcImage->roi.top;
|
|
||||||
* 新图像的type=type; 新图像的widthStep为4字节对齐; 新图像的origin=origin, 如果origin和srcImage->origin不一致,拷贝时像素会进行上下翻转
|
|
||||||
* 3) 新图像的roi为{0, 0, width, height}
|
|
||||||
* 4) 新图像的xdpi=srcImage->xdpi, ydpi=srcImage->ydpi
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CloneImage(HGImage srcImage, HGUInt type, HGUInt origin, HGImage* image);
|
|
||||||
|
|
||||||
/* 销毁图像
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 如果图像内部分配了像素内存, 销毁图像的同时会自动释放
|
|
||||||
* 2) 如果图像内部创建了DIB位图(windows上), 销毁图像的同时会自动调用DeleteObject进行销毁
|
|
||||||
* 3) 如果图像内存没有分配内存,也没有创建DIB位图,而是直接使用源数据,销毁图像后源数据才可以释放
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DestroyImage(HGImage image);
|
|
||||||
|
|
||||||
/* 获取图像数据地址
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) data: out, 数据地址
|
|
||||||
* 说明:
|
|
||||||
* 1) 如果图像内部分配了内存, 返回的是分配的内存地址
|
|
||||||
* 2) 如果图像内部创建了DIB位图,返回的是DIB位图像素数据的内存地址
|
|
||||||
* 3) 否则,返回的是源数据地址
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetImageData(HGImage image, HGByte** data);
|
|
||||||
|
|
||||||
/* 获取图像信息
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) info: out, 图像信息
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetImageInfo(HGImage image, HGImageInfo* info);
|
|
||||||
|
|
||||||
/* 获取图像感兴趣区域
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) roi: out, 图像感兴趣区域
|
|
||||||
* 说明:
|
|
||||||
* 1) 默认的感兴趣区域整张图, 即left=0,top=0,right=width,bottom=height
|
|
||||||
* 2) 图像算法模块可以仅处理感兴趣区域
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetImageROI(HGImage image, HGImageRoi* roi);
|
|
||||||
|
|
||||||
/* 设置图像感兴趣区域
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) roi: in, 图像感兴趣区域
|
|
||||||
* 说明:
|
|
||||||
* 1) roi所指定的区域必须是整个图像幅面的子集
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_SetImageROI(HGImage image, const HGImageRoi* roi);
|
|
||||||
|
|
||||||
/* 重置图像感兴趣区域
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 默认的感兴趣区域整张图, 即left=0,top=0,right=width,bottom=height
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ResetImageROI(HGImage image);
|
|
||||||
|
|
||||||
/* 获取图像DPI
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) xDpi: out, xdpi
|
|
||||||
* 3) yDpi: out, ydpi
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetImageDpi(HGImage image, HGUInt *xDpi, HGUInt* yDpi);
|
|
||||||
|
|
||||||
/* 设置图像DPI
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) xDpi: in, xdpi
|
|
||||||
* 3) yDpi: in, ydpi
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_SetImageDpi(HGImage image, HGUInt xDpi, HGUInt yDpi);
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
|
|
||||||
/* 获取图像内部的DIB位图句柄
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) hBmp: out, DIB位图句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数只对windows平台有效
|
|
||||||
* 2) 返回的HBITMAP不能用DeleteObject销毁
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetHBITMAPOfImage(HGImage image, HBITMAP *hBmp);
|
|
||||||
|
|
||||||
/* 创建DIB位图
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) hBmp: out, DIB位图句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数只对windows平台有效
|
|
||||||
* 2) 返回的hBmp必须用DeleteObject销毁
|
|
||||||
* 3) 操作的只是图像的ROI区域
|
|
||||||
* 4) HGBASE_IMGTYPE_RGB会自动转为BGR排列, HGBASE_IMGTYPE_RGBA会自动转为BGRA排列
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateHBITMAPFromImage(HGImage image, HBITMAP* hBmp);
|
|
||||||
|
|
||||||
/* 创建DIB内存
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) hMem: out, DIB内存句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数只对windows平台有效
|
|
||||||
* 2) 返回的hMem必须用GlobalFree销毁
|
|
||||||
* 3) 操作的只是图像的ROI区域
|
|
||||||
* 4) HGBASE_IMGTYPE_RGB会自动转为BGR排列, HGBASE_IMGTYPE_RGBA会自动转为BGRA排列
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateDIBFromImage(HGImage image, HGLOBAL* hMem);
|
|
||||||
|
|
||||||
#endif /* HG_CMP_MSC */
|
|
||||||
|
|
||||||
/* 图像左右镜像
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须一样
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageMirror(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像上下镜像
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须一样
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageFlip(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像左转
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须宽高互反
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage不能是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageRotateLeft(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像右转
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须宽高互反
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage不能是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageRotateRight(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像左转后再左右镜像
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须宽高互反
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage不能是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageRotateLeftMirror(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像右转后再左右镜像
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须宽高互反
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage不能是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageRotateRightMirror(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像旋转180度
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须一样
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageRotate180(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像灰度化
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须一样
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ImageGrayscale(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 图像反色
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须一样
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ReverseImage(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
/* 拷贝图像
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, 源图像和目标图像的ROI大小必须一样
|
|
||||||
* 2) 拷贝的时候会自动处理type不一致的情况
|
|
||||||
* 3) 拷贝的时候自动处理origin不一致的情况
|
|
||||||
* 4) image和destImage不能是同一个图像句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CopyImage(HGImage image, HGImage destImage);
|
|
||||||
|
|
||||||
#endif /* __HGIMAGE_H__ */
|
|
|
@ -1,39 +0,0 @@
|
||||||
#ifndef __HGINC_H__
|
|
||||||
#define __HGINC_H__
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
#include <windows.h>
|
|
||||||
#include <WinSock2.h>
|
|
||||||
#include <io.h>
|
|
||||||
#else
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <iconv.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __HGINC_H__ */
|
|
|
@ -1,35 +0,0 @@
|
||||||
#include "HGInfo.h"
|
|
||||||
#include "HGInfoImpl.hpp"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
HGInfoImpl* g_infoImpl = NULL;
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_EnableInfo()
|
|
||||||
{
|
|
||||||
if (NULL == g_infoImpl)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
|
|
||||||
return g_infoImpl->Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DisableInfo()
|
|
||||||
{
|
|
||||||
if (NULL == g_infoImpl)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
|
|
||||||
return g_infoImpl->Disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPIV HGBase_WriteInfo(HGUInt type, const HGChar* format, ...)
|
|
||||||
{
|
|
||||||
if (NULL == g_infoImpl)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
|
|
||||||
char buf[1024] = { 0 };
|
|
||||||
va_list va;
|
|
||||||
va_start(va, format);
|
|
||||||
vsnprintf(buf, 1024, format, va);
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
return g_infoImpl->Write(type, buf);
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef __HGINFO_H__
|
|
||||||
#define __HGINFO_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
/* 致命错误 */
|
|
||||||
#define HGBASE_INFOTYPE_FATAL 1L
|
|
||||||
/* 一般错误 */
|
|
||||||
#define HGBASE_INFOTYPE_ERROR 2L
|
|
||||||
/* 警告 */
|
|
||||||
#define HGBASE_INFOTYPE_WARNING 4L
|
|
||||||
/* 一般描述信息 */
|
|
||||||
#define HGBASE_INFOTYPE_DESC 8L
|
|
||||||
/* 调试信息 */
|
|
||||||
#define HGBASE_INFOTYPE_DEBUG 16L
|
|
||||||
|
|
||||||
/* 启用日志/控制台信息
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_EnableInfo();
|
|
||||||
|
|
||||||
/* 禁用日志/控制台信息
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DisableInfo();
|
|
||||||
|
|
||||||
/* 写日志/控制台信息
|
|
||||||
* 参数:
|
|
||||||
* 1) type: in, 信息类型, 参见HGBASE_INFOTYPE_*
|
|
||||||
* 2) format: in, 信息格式
|
|
||||||
* 说明:
|
|
||||||
* 1) 信息的完整输出行: [日期-时间] [进程号/线程号] [信息类型] [信息]
|
|
||||||
* 2) 信息的实际输出行取决于config.ini的配置
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPIV HGBase_WriteInfo(HGUInt type, const HGChar* format, ...);
|
|
||||||
|
|
||||||
#endif /* __HGINFO_H__ */
|
|
|
@ -1,171 +0,0 @@
|
||||||
#include "HGInfoImpl.hpp"
|
|
||||||
#include "HGInfo.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
#include "HGUtility.h"
|
|
||||||
#include "HGIni.h"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
HGInfoImpl::HGInfoImpl()
|
|
||||||
{
|
|
||||||
HGBase_CreateLock(&m_lock);
|
|
||||||
m_enabled = HGFALSE;
|
|
||||||
m_log = NULL;
|
|
||||||
m_console = NULL;
|
|
||||||
m_type = 0;
|
|
||||||
m_showTime = HGFALSE;
|
|
||||||
m_showId = HGFALSE;
|
|
||||||
m_showType = HGFALSE;
|
|
||||||
|
|
||||||
Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
HGInfoImpl::~HGInfoImpl()
|
|
||||||
{
|
|
||||||
Disable();
|
|
||||||
|
|
||||||
HGBase_DestroyLock(m_lock);
|
|
||||||
m_lock = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGInfoImpl::Enable()
|
|
||||||
{
|
|
||||||
if (m_enabled)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar cfgPath[256] = { 0 };
|
|
||||||
HGBase_GetConfigPath(cfgPath, 256);
|
|
||||||
strcat(cfgPath, "config.ini");
|
|
||||||
|
|
||||||
HGBool writeLog;
|
|
||||||
HGBase_GetProfileInt(cfgPath, "info", "writeLog", 1, &writeLog);
|
|
||||||
HGBool writeConsole;
|
|
||||||
HGBase_GetProfileInt(cfgPath, "info", "writeConsole", 0, &writeConsole);
|
|
||||||
HGUInt defType = HGBASE_INFOTYPE_FATAL | HGBASE_INFOTYPE_ERROR | HGBASE_INFOTYPE_WARNING;
|
|
||||||
HGBase_GetProfileInt(cfgPath, "info", "type", (HGInt)defType, (HGInt*)&m_type);
|
|
||||||
HGBase_GetProfileInt(cfgPath, "info", "showTime", 1, &m_showTime);
|
|
||||||
HGBase_GetProfileInt(cfgPath, "info", "showId", 0, &m_showId);
|
|
||||||
HGBase_GetProfileInt(cfgPath, "info", "showType", 1, &m_showType);
|
|
||||||
|
|
||||||
if (writeLog)
|
|
||||||
{
|
|
||||||
HGChar logPath[256];
|
|
||||||
HGBase_GetLogFilePath(logPath, 256);
|
|
||||||
HGBase_CreateDir(logPath);
|
|
||||||
|
|
||||||
timeb tb;
|
|
||||||
ftime(&tb);
|
|
||||||
struct tm* p = localtime(&tb.time);
|
|
||||||
|
|
||||||
char fileName[256];
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
sprintf(fileName, "\\%04d%02d%02d.log", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday);
|
|
||||||
#else
|
|
||||||
sprintf(fileName, "/%04d%02d%02d.log", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday);
|
|
||||||
#endif
|
|
||||||
strcat(logPath, fileName);
|
|
||||||
HGBase_OpenLog(logPath, &m_log);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writeConsole)
|
|
||||||
{
|
|
||||||
HGBase_OpenConsole(&m_console);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_enabled = HGTRUE;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGInfoImpl::Disable()
|
|
||||||
{
|
|
||||||
if (!m_enabled)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_CloseConsole(m_console);
|
|
||||||
m_console = NULL;
|
|
||||||
HGBase_CloseLog(m_log);
|
|
||||||
m_log = NULL;
|
|
||||||
|
|
||||||
m_enabled = HGFALSE;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGInfoImpl::Write(HGUInt type, const HGChar* info)
|
|
||||||
{
|
|
||||||
if (!m_enabled)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HGBASE_INFOTYPE_FATAL != type && HGBASE_INFOTYPE_ERROR != type
|
|
||||||
&& HGBASE_INFOTYPE_WARNING != type && HGBASE_INFOTYPE_DESC != type
|
|
||||||
&& HGBASE_INFOTYPE_DEBUG != type)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == info || '\0' == *info)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == (type & m_type))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char writeInfo[2048] = { 0 };
|
|
||||||
|
|
||||||
if (m_showTime)
|
|
||||||
{
|
|
||||||
timeb tb;
|
|
||||||
ftime(&tb);
|
|
||||||
struct tm* p = localtime(&tb.time);
|
|
||||||
char timeStr[64] = { 0 };
|
|
||||||
sprintf(timeStr, "[%04d/%02d/%02d-%02d:%02d:%02d.%03d]", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday,
|
|
||||||
p->tm_hour, p->tm_min, p->tm_sec, tb.millitm);
|
|
||||||
strcat(writeInfo, timeStr);
|
|
||||||
strcat(writeInfo, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_showId)
|
|
||||||
{
|
|
||||||
char idStr[32] = { 0 };
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
sprintf(idStr, "[0x%08X/0x%08X]", GetCurrentProcessId(), GetCurrentThreadId());
|
|
||||||
#else
|
|
||||||
sprintf(idStr, "[0x%08X/0x%08X]", (HGUInt)getpid(), (HGUInt)syscall(SYS_gettid));
|
|
||||||
#endif
|
|
||||||
strcat(writeInfo, idStr);
|
|
||||||
strcat(writeInfo, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_showType)
|
|
||||||
{
|
|
||||||
char typeStr[24] = { 0 };
|
|
||||||
if (HGBASE_INFOTYPE_FATAL == type)
|
|
||||||
sprintf(typeStr, "[%s]", "FAT");
|
|
||||||
else if (HGBASE_INFOTYPE_ERROR == type)
|
|
||||||
sprintf(typeStr, "[%s]", "ERR");
|
|
||||||
else if (HGBASE_INFOTYPE_WARNING == type)
|
|
||||||
sprintf(typeStr, "[%s]", "WAR");
|
|
||||||
else if (HGBASE_INFOTYPE_DESC == type)
|
|
||||||
sprintf(typeStr, "[%s]", "DES");
|
|
||||||
else
|
|
||||||
sprintf(typeStr, "[%s]", "DEB");
|
|
||||||
strcat(writeInfo, typeStr);
|
|
||||||
strcat(writeInfo, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(writeInfo, info);
|
|
||||||
|
|
||||||
HGBase_EnterLock(m_lock);
|
|
||||||
HGBase_WriteLog(m_log, writeInfo);
|
|
||||||
HGBase_WriteConsole(m_console, writeInfo);
|
|
||||||
HGBase_LeaveLock(m_lock);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef __HGINFOIMPL_HPP__
|
|
||||||
#define __HGINFOIMPL_HPP__
|
|
||||||
|
|
||||||
#include "HGLog.h"
|
|
||||||
#include "HGConsole.h"
|
|
||||||
#include "HGLock.h"
|
|
||||||
|
|
||||||
class HGInfoImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGInfoImpl();
|
|
||||||
~HGInfoImpl();
|
|
||||||
|
|
||||||
HGResult Enable();
|
|
||||||
HGResult Disable();
|
|
||||||
HGResult Write(HGUInt type, const HGChar* info);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HGLock m_lock;
|
|
||||||
HGBool m_enabled;
|
|
||||||
HGLog m_log;
|
|
||||||
HGConsole m_console;
|
|
||||||
HGUInt m_type;
|
|
||||||
HGBool m_showTime;
|
|
||||||
HGBool m_showId;
|
|
||||||
HGBool m_showType;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGINFOIMPL_HPP__ */
|
|
|
@ -1,339 +0,0 @@
|
||||||
#include "HGIni.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
#include "HGInfo.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
static HGUInt IniWriteValue(const char* section, const char* key, const char* val, const char* file)
|
|
||||||
{
|
|
||||||
typedef std::vector<std::pair<std::string, std::string> > KeyList;
|
|
||||||
typedef std::vector<std::pair<std::string, KeyList> > SectionList;
|
|
||||||
|
|
||||||
SectionList sectList;
|
|
||||||
|
|
||||||
FILE* fp = fopen(file, "r");
|
|
||||||
if (fp != NULL)
|
|
||||||
{
|
|
||||||
KeyList* pCurKeyList = NULL;
|
|
||||||
|
|
||||||
while (feof(fp) == 0)
|
|
||||||
{
|
|
||||||
char lineContent[256] = { 0 };
|
|
||||||
if (NULL == fgets(lineContent, 256, fp))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lineContent[0] == ';') || (lineContent[0] == '\0') || (lineContent[0] == '\r') || (lineContent[0] == '\n'))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < strlen(lineContent); ++i)
|
|
||||||
{
|
|
||||||
if (lineContent[i] == '\r' || lineContent[i] == '\n')
|
|
||||||
{
|
|
||||||
lineContent[i] = '\0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lineContent[0] == '[')
|
|
||||||
{
|
|
||||||
std::pair<std::string, KeyList> pr;
|
|
||||||
pr.first = lineContent;
|
|
||||||
sectList.push_back(pr);
|
|
||||||
pCurKeyList = §List[sectList.size() - 1].second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int pos = -1;
|
|
||||||
for (int i = 0; i < (int)strlen(lineContent); ++i)
|
|
||||||
{
|
|
||||||
if (lineContent[i] == '=')
|
|
||||||
{
|
|
||||||
pos = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != pCurKeyList)
|
|
||||||
{
|
|
||||||
std::pair<std::string, std::string> pr;
|
|
||||||
if (-1 != pos)
|
|
||||||
{
|
|
||||||
pr.first.assign(lineContent, pos);
|
|
||||||
pr.second.assign(lineContent + pos + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pr.first = lineContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCurKeyList->push_back(pr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bFindSect = false;
|
|
||||||
for (size_t i = 0; i < sectList.size(); ++i)
|
|
||||||
{
|
|
||||||
if (strcmp(sectList[i].first.c_str(), section) == 0)
|
|
||||||
{
|
|
||||||
bool bFindKey = false;
|
|
||||||
for (size_t j = 0; j < sectList[i].second.size(); ++j)
|
|
||||||
{
|
|
||||||
if (strcmp(sectList[i].second[j].first.c_str(), key) == 0)
|
|
||||||
{
|
|
||||||
sectList[i].second[j].second = val;
|
|
||||||
bFindKey = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bFindKey)
|
|
||||||
{
|
|
||||||
std::pair<std::string, std::string> pr;
|
|
||||||
pr.first = key;
|
|
||||||
pr.second = val;
|
|
||||||
sectList[i].second.push_back(pr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bFindSect = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bFindSect)
|
|
||||||
{
|
|
||||||
std::pair<std::string, KeyList> pr;
|
|
||||||
pr.first = section;
|
|
||||||
std::pair<std::string, std::string> pr2;
|
|
||||||
pr2.first = key;
|
|
||||||
pr2.second = val;
|
|
||||||
pr.second.push_back(pr2);
|
|
||||||
sectList.push_back(pr);
|
|
||||||
}
|
|
||||||
|
|
||||||
fp = fopen(file, "w");
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "IniWriteValue: fopen fail %s errno=%d", file, errno);
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sectList.size(); ++i)
|
|
||||||
{
|
|
||||||
fputs(sectList[i].first.c_str(), fp);
|
|
||||||
fputs("\n", fp);
|
|
||||||
|
|
||||||
for (size_t j = 0; j < sectList[i].second.size(); ++j)
|
|
||||||
{
|
|
||||||
fputs(sectList[i].second[j].first.c_str(), fp);
|
|
||||||
fputs("=", fp);
|
|
||||||
fputs(sectList[i].second[j].second.c_str(), fp);
|
|
||||||
fputs("\n", fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HGResult writeStringValue(const char* section, const char* key, const char* val, const char* file)
|
|
||||||
{
|
|
||||||
if (section == NULL || key == NULL || val == NULL || file == NULL)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
char sect[256];
|
|
||||||
sprintf(sect, "[%s]", section);
|
|
||||||
return IniWriteValue(sect, key, val, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_SetProfileInt(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, HGInt value)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == appName || NULL == keyName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
char str[8];
|
|
||||||
sprintf(str, "%d", value);
|
|
||||||
return writeStringValue(appName, keyName, str, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_SetProfileString(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, const HGChar* value)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == appName || NULL == keyName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return writeStringValue(appName, keyName, value, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HGResult IniReadValue(const char* section, const char* key, char* val, const char* def, const char* file)
|
|
||||||
{
|
|
||||||
typedef std::vector<std::pair<std::string, std::string> > KeyList;
|
|
||||||
typedef std::vector<std::pair<std::string, KeyList> > SectionList;
|
|
||||||
|
|
||||||
SectionList sectList;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(file, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(file, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* fp = fopen(file, "r");
|
|
||||||
if (fp != NULL)
|
|
||||||
{
|
|
||||||
KeyList* pCurKeyList = NULL;
|
|
||||||
|
|
||||||
while (feof(fp) == 0)
|
|
||||||
{
|
|
||||||
char lineContent[256] = { 0 };
|
|
||||||
if (NULL == fgets(lineContent, 256, fp))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lineContent[0] == ';') || (lineContent[0] == '\0') || (lineContent[0] == '\r') || (lineContent[0] == '\n'))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < strlen(lineContent); ++i)
|
|
||||||
{
|
|
||||||
if (lineContent[i] == '\r' || lineContent[i] == '\n')
|
|
||||||
{
|
|
||||||
lineContent[i] = '\0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lineContent[0] == '[')
|
|
||||||
{
|
|
||||||
std::pair<std::string, KeyList> pr;
|
|
||||||
pr.first = lineContent;
|
|
||||||
sectList.push_back(pr);
|
|
||||||
pCurKeyList = §List[sectList.size() - 1].second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int pos = -1;
|
|
||||||
for (int i = 0; i < (int)strlen(lineContent); ++i)
|
|
||||||
{
|
|
||||||
if (lineContent[i] == '=')
|
|
||||||
{
|
|
||||||
pos = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != pCurKeyList)
|
|
||||||
{
|
|
||||||
std::pair<std::string, std::string> pr;
|
|
||||||
if (-1 != pos)
|
|
||||||
{
|
|
||||||
pr.first.assign(lineContent, pos);
|
|
||||||
pr.second.assign(lineContent + pos + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pr.first = lineContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCurKeyList->push_back(pr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcpy(val, def);
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bGetVal = false;
|
|
||||||
for (size_t i = 0; i < sectList.size(); ++i)
|
|
||||||
{
|
|
||||||
if (strcmp(sectList[i].first.c_str(), section) == 0)
|
|
||||||
{
|
|
||||||
for (size_t j = 0; j < sectList[i].second.size(); ++j)
|
|
||||||
{
|
|
||||||
if (strcmp(sectList[i].second[j].first.c_str(), key) == 0)
|
|
||||||
{
|
|
||||||
strcpy(val, sectList[i].second[j].second.c_str());
|
|
||||||
bGetVal = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bGetVal)
|
|
||||||
{
|
|
||||||
strcpy(val, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HGResult readStringValue(const char* section, const char* key, char* val, const char* def, const char* file)
|
|
||||||
{
|
|
||||||
if (section == NULL || key == NULL || val == NULL || def == NULL || file == NULL)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
char sect[256];
|
|
||||||
sprintf(sect, "[%s]", section);
|
|
||||||
return IniReadValue(sect, key, val, def, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetProfileInt(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, HGInt def, HGInt* value)
|
|
||||||
{
|
|
||||||
if (NULL == appName || NULL == keyName || NULL == value)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
char strRet[256] = { 0 };
|
|
||||||
char strDef[32];
|
|
||||||
sprintf(strDef, "%d", def);
|
|
||||||
HGResult ret = readStringValue(appName, keyName, strRet, strDef, fileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
*value = def;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*value = atoi(strRet);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetProfileString(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, const HGChar* def, HGChar* value, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == appName || NULL == keyName || NULL == value)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return readStringValue(appName, keyName, value, def, fileName);
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
#ifndef __HGINI_H__
|
|
||||||
#define __HGINI_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
/* 设置ini文件的值
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_SetProfileInt(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, HGInt value);
|
|
||||||
|
|
||||||
/* 设置ini文件的值
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_SetProfileString(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, const HGChar* value);
|
|
||||||
|
|
||||||
/* 获取ini文件的值
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetProfileInt(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, HGInt def, HGInt* value);
|
|
||||||
|
|
||||||
/* 获取ini文件的值
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetProfileString(const HGChar* fileName, const HGChar* appName,
|
|
||||||
const HGChar* keyName, const HGChar* def, HGChar* value, HGUInt maxLen);
|
|
||||||
|
|
||||||
#endif /* __HGINI_H__ */
|
|
|
@ -1,78 +0,0 @@
|
||||||
#include "HGLock.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateLock(HGLock* lock)
|
|
||||||
{
|
|
||||||
if (NULL == lock)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
pthread_mutex_t* hLock = new pthread_mutex_t;
|
|
||||||
if (0 != pthread_mutex_init(hLock, NULL))
|
|
||||||
{
|
|
||||||
delete hLock;
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
*lock = (HGLock)hLock;
|
|
||||||
#else
|
|
||||||
CRITICAL_SECTION* hLock = new CRITICAL_SECTION;
|
|
||||||
InitializeCriticalSection(hLock);
|
|
||||||
*lock = (HGLock)hLock;
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DestroyLock(HGLock lock)
|
|
||||||
{
|
|
||||||
if (NULL == lock)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
pthread_mutex_t* hLock = (pthread_mutex_t*)lock;
|
|
||||||
pthread_mutex_destroy(hLock);
|
|
||||||
delete hLock;
|
|
||||||
#else
|
|
||||||
CRITICAL_SECTION* hLock = (CRITICAL_SECTION*)lock;
|
|
||||||
DeleteCriticalSection(hLock);
|
|
||||||
delete hLock;
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_EnterLock(HGLock lock)
|
|
||||||
{
|
|
||||||
if (NULL == lock)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
pthread_mutex_t* hLock = (pthread_mutex_t*)lock;
|
|
||||||
pthread_mutex_lock(hLock);
|
|
||||||
#else
|
|
||||||
CRITICAL_SECTION* hLock = (CRITICAL_SECTION*)lock;
|
|
||||||
EnterCriticalSection(hLock);
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_LeaveLock(HGLock lock)
|
|
||||||
{
|
|
||||||
if (NULL == lock)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
pthread_mutex_t* hLock = (pthread_mutex_t*)lock;
|
|
||||||
pthread_mutex_unlock(hLock);
|
|
||||||
#else
|
|
||||||
CRITICAL_SECTION* hLock = (CRITICAL_SECTION*)lock;
|
|
||||||
LeaveCriticalSection(hLock);
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
#ifndef __HGLOCK_H__
|
|
||||||
#define __HGLOCK_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGLock);
|
|
||||||
|
|
||||||
/* 创建互斥锁
|
|
||||||
* 参数:
|
|
||||||
* 1) lock: out, 互斥锁句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateLock(HGLock* lock);
|
|
||||||
|
|
||||||
/* 销毁互斥锁
|
|
||||||
* 参数:
|
|
||||||
* 1) lock: in, 互斥锁句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DestroyLock(HGLock lock);
|
|
||||||
|
|
||||||
/* 加锁
|
|
||||||
* 参数:
|
|
||||||
* 1) lock: in, 互斥锁句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_EnterLock(HGLock lock);
|
|
||||||
|
|
||||||
/* 解锁
|
|
||||||
* 参数:
|
|
||||||
* 1) lock: in, 互斥锁句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_LeaveLock(HGLock lock);
|
|
||||||
|
|
||||||
#endif /* __HGLOCK_H__ */
|
|
|
@ -1,89 +0,0 @@
|
||||||
#include "HGLog.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
struct HGLogImpl
|
|
||||||
{
|
|
||||||
HGLogImpl()
|
|
||||||
{
|
|
||||||
m_file = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
~HGLogImpl()
|
|
||||||
{
|
|
||||||
if (NULL != m_file)
|
|
||||||
{
|
|
||||||
fclose(m_file);
|
|
||||||
m_file = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* m_file;
|
|
||||||
};
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_OpenLog(const HGChar* fileName, HGLog* log)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == log)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *file = fopen(fileName, "a+");
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGLogImpl* logImpl = new HGLogImpl;
|
|
||||||
logImpl->m_file = file;
|
|
||||||
*log = (HGLog)logImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CloseLog(HGLog log)
|
|
||||||
{
|
|
||||||
if (NULL == log)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGLogImpl* logImpl = (HGLogImpl*)log;
|
|
||||||
delete logImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetLogFileSize(HGLog log, HGLonglong* size)
|
|
||||||
{
|
|
||||||
if (NULL == log || NULL == size)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGLogImpl* logImpl = (HGLogImpl*)log;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
_fseeki64(logImpl->m_file, 0, SEEK_END);
|
|
||||||
*size = _ftelli64(logImpl->m_file);
|
|
||||||
#else
|
|
||||||
fseeko64(logImpl->m_file, 0, SEEK_END);
|
|
||||||
*size = ftello64(logImpl->m_file);
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_WriteLog(HGLog log, const HGChar* info)
|
|
||||||
{
|
|
||||||
if (NULL == log || NULL == info || '\0' == *info)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGLogImpl* logImpl = (HGLogImpl*)log;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
_fseeki64(logImpl->m_file, 0, SEEK_END);
|
|
||||||
#else
|
|
||||||
fseeko64(logImpl->m_file, 0, SEEK_END);
|
|
||||||
#endif
|
|
||||||
fwrite(info, 1, strlen(info), logImpl->m_file);
|
|
||||||
fwrite("\n", 1, strlen("\n"), logImpl->m_file);
|
|
||||||
fflush(logImpl->m_file);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
#ifndef __HGLOG_H__
|
|
||||||
#define __HGLOG_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGLog);
|
|
||||||
|
|
||||||
/* 开启日志
|
|
||||||
* 参数:
|
|
||||||
* 1) fileName: in, 文件名
|
|
||||||
* 2) log: out, 日志句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_OpenLog(const HGChar* fileName, HGLog* log);
|
|
||||||
|
|
||||||
/* 关闭日志
|
|
||||||
* 参数:
|
|
||||||
* 1) log: in, 日志句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CloseLog(HGLog log);
|
|
||||||
|
|
||||||
/* 获取日志文件大小
|
|
||||||
* 参数:
|
|
||||||
* 1) log: in, 日志句柄
|
|
||||||
* 2) size: out, 日志文件大小
|
|
||||||
* 说明:
|
|
||||||
* 1) 每次写入日志信息后,可以用该函数检查日志文件的大小,当日志文件足够大时,可以关闭该日志句柄,在新的日志文件上重新打开
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetLogFileSize(HGLog log, HGLonglong* size);
|
|
||||||
|
|
||||||
/* 写日志信息
|
|
||||||
* 参数:
|
|
||||||
* 1) log: in, 日志句柄
|
|
||||||
* 2) info: in, 信息, 一次一行, info无需加换行符
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数不是线程安全的, 在不同进程或不同线程调用的时候, 需要加锁
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_WriteLog(HGLog log, const HGChar* info);
|
|
||||||
|
|
||||||
#endif /* __HGLOG_H__ */
|
|
|
@ -1,314 +0,0 @@
|
||||||
#include "HGMd5.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
/* Constants for MD5Transform routine. */
|
|
||||||
/* md5转换用到的常量,算法本身规定的 */
|
|
||||||
#define S11 7
|
|
||||||
#define S12 12
|
|
||||||
#define S13 17
|
|
||||||
#define S14 22
|
|
||||||
#define S21 5
|
|
||||||
#define S22 9
|
|
||||||
#define S23 14
|
|
||||||
#define S24 20
|
|
||||||
#define S31 4
|
|
||||||
#define S32 11
|
|
||||||
#define S33 16
|
|
||||||
#define S34 23
|
|
||||||
#define S41 6
|
|
||||||
#define S42 10
|
|
||||||
#define S43 15
|
|
||||||
#define S44 21
|
|
||||||
|
|
||||||
/*
|
|
||||||
接下来的这几个宏定义是md5算法规定的,就是对信息进行md5加密都要做的运算。
|
|
||||||
据说有经验的高手跟踪程序时根据这几个特殊的操作就可以断定是不是用的md5
|
|
||||||
F, G, H and I are basic MD5 functions.
|
|
||||||
*/
|
|
||||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
|
||||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
|
||||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
|
||||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
|
||||||
|
|
||||||
/*
|
|
||||||
ROTATE_LEFT rotates x left n bits.
|
|
||||||
*/
|
|
||||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
|
||||||
|
|
||||||
/*
|
|
||||||
FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
|
||||||
Rotation is separate from addition to prevent recomputation.
|
|
||||||
*/
|
|
||||||
#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
|
||||||
#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
|
||||||
#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
|
||||||
#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (HGUInt)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
|
||||||
|
|
||||||
/* MD5 context. */
|
|
||||||
struct MD5_CTX
|
|
||||||
{
|
|
||||||
/* state (ABCD) */
|
|
||||||
/*四个32bits数,用于存放最终计算得到的消息摘要。当消息长度〉512bits时,也用于存放每个512bits的中间结果*/
|
|
||||||
HGUInt state[4];
|
|
||||||
/* number of bits, modulo 2^64 (lsb first) */
|
|
||||||
/*存储原始信息的bits数长度,不包括填充的bits,最长为 2^64 bits,因为2^64是一个64位数的最大值*/
|
|
||||||
HGUInt count[2];
|
|
||||||
/* input buffer */
|
|
||||||
/*存放输入的信息的缓冲区,512bits*/
|
|
||||||
HGByte buffer[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* MD5 initialization. Begins an MD5 operation, writing a new context. */
|
|
||||||
/*初始化md5的结构*/
|
|
||||||
static void MD5Init(MD5_CTX* ctx)
|
|
||||||
{
|
|
||||||
/*将当前的有效信息的长度设成0,这个很简单,还没有有效信息,长度当然是0了*/
|
|
||||||
ctx->count[0] = 0;
|
|
||||||
ctx->count[1] = 0;
|
|
||||||
|
|
||||||
/* Load magic initialization constants.*/
|
|
||||||
/*初始化链接变量,算法要求这样,这个没法解释了*/
|
|
||||||
ctx->state[0] = 0x67452301;
|
|
||||||
ctx->state[1] = 0xefcdab89;
|
|
||||||
ctx->state[2] = 0x98badcfe;
|
|
||||||
ctx->state[3] = 0x10325476;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
将4字节的整数copy到字符形式的缓冲区中
|
|
||||||
output:用于输出的字符缓冲区
|
|
||||||
input:欲转换的四字节的整数形式的数组
|
|
||||||
len:output缓冲区的长度,要求是4的整数倍
|
|
||||||
*/
|
|
||||||
static void MD5Encode(HGByte* output, const HGUInt* input, HGUInt len)
|
|
||||||
{
|
|
||||||
for (HGUInt i = 0, j = 0; j < len; i++, j += 4)
|
|
||||||
{
|
|
||||||
output[j] = (HGByte)(input[i] & 0xFF);
|
|
||||||
output[j + 1] = (HGByte)((input[i] >> 8) & 0xFF);
|
|
||||||
output[j + 2] = (HGByte)((input[i] >> 16) & 0xFF);
|
|
||||||
output[j + 3] = (HGByte)((input[i] >> 24) & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
与上面的函数正好相反,这一个把字符形式的缓冲区中的数据copy到4字节的整数中(即以整数形式保存)
|
|
||||||
output:保存转换出的整数
|
|
||||||
input:欲转换的字符缓冲区
|
|
||||||
len:输入的字符缓冲区的长度,要求是4的整数倍
|
|
||||||
*/
|
|
||||||
static void MD5Decode(HGUInt* output, const HGByte* input, HGUInt len)
|
|
||||||
{
|
|
||||||
for (HGUInt i = 0, j = 0; j < len; i++, j += 4)
|
|
||||||
{
|
|
||||||
output[i] = ((HGUInt)input[j]) | (((HGUInt)input[j + 1]) << 8) | (((HGUInt)input[j + 2]) << 16) | (((HGUInt)input[j + 3]) << 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
对512bits信息(即block缓冲区)进行一次处理,每次处理包括四轮
|
|
||||||
state[4]:md5结构中的state[4],用于保存对512bits信息加密的中间结果或者最终结果
|
|
||||||
block[64]:欲加密的512bits信息
|
|
||||||
*/
|
|
||||||
static void MD5Transform(HGUInt* state, const HGByte* block)
|
|
||||||
{
|
|
||||||
HGUInt a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
|
||||||
|
|
||||||
MD5Decode(x, block, 64);
|
|
||||||
|
|
||||||
/* Round 1 */
|
|
||||||
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
|
|
||||||
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
|
|
||||||
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
|
|
||||||
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
|
|
||||||
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
|
|
||||||
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
|
|
||||||
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
|
|
||||||
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
|
|
||||||
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
|
|
||||||
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
|
|
||||||
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
|
||||||
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
|
||||||
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
|
||||||
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
|
||||||
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
|
||||||
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
|
||||||
|
|
||||||
/* Round 2 */
|
|
||||||
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
|
|
||||||
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
|
|
||||||
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
|
||||||
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
|
|
||||||
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
|
|
||||||
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
|
||||||
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
|
||||||
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
|
|
||||||
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
|
|
||||||
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
|
||||||
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
|
|
||||||
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
|
|
||||||
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
|
||||||
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
|
|
||||||
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
|
|
||||||
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
|
||||||
|
|
||||||
/* Round 3 */
|
|
||||||
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
|
|
||||||
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
|
|
||||||
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
|
||||||
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
|
||||||
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
|
|
||||||
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
|
|
||||||
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
|
|
||||||
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
|
||||||
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
|
||||||
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
|
|
||||||
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
|
|
||||||
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
|
|
||||||
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
|
|
||||||
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
|
||||||
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
|
||||||
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
|
|
||||||
|
|
||||||
/* Round 4 */
|
|
||||||
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
|
|
||||||
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
|
|
||||||
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
|
||||||
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
|
|
||||||
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
|
||||||
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
|
|
||||||
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
|
||||||
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
|
|
||||||
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
|
|
||||||
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
|
||||||
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
|
|
||||||
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
|
||||||
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
|
|
||||||
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
|
||||||
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
|
|
||||||
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
|
|
||||||
|
|
||||||
state[0] += a;
|
|
||||||
state[1] += b;
|
|
||||||
state[2] += c;
|
|
||||||
state[3] += d;
|
|
||||||
|
|
||||||
/* Zeroize sensitive information. */
|
|
||||||
memset(x, 0, sizeof(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
MD5 block update operation. Continues an MD5 message-digest
|
|
||||||
operation, processing another message block, and updating the
|
|
||||||
context.
|
|
||||||
将与加密的信息传递给md5结构,可以多次调用
|
|
||||||
context:初始化过了的md5结构
|
|
||||||
input:欲加密的信息,可以任意长
|
|
||||||
inputLen:指定input的长度
|
|
||||||
*/
|
|
||||||
static void MD5Update(MD5_CTX* ctx, const HGByte* data, HGUInt size)
|
|
||||||
{
|
|
||||||
HGUInt i, index, partLen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
计算已有信息的bits长度的字节数的模64, 64bytes=512bits。
|
|
||||||
用于判断已有信息加上当前传过来的信息的总长度能不能达到512bits,
|
|
||||||
如果能够达到则对凑够的512bits进行一次处理
|
|
||||||
*/
|
|
||||||
index = (HGUInt)((ctx->count[0] >> 3) & 0x3F);
|
|
||||||
|
|
||||||
/* Update number of bits *//*更新已有信息的bits长度 */
|
|
||||||
if ((ctx->count[0] += ((HGUInt)size << 3)) < ((HGUInt)size << 3))
|
|
||||||
ctx->count[1]++;
|
|
||||||
ctx->count[1] += ((HGUInt)size >> 29);
|
|
||||||
|
|
||||||
/* 计算已有的字节数长度还差多少字节可以 凑成64的整倍数 */
|
|
||||||
partLen = 64 - index;
|
|
||||||
|
|
||||||
/* 如果当前输入的字节数 大于 已有字节数长度补足64字节整倍数所差的字节数 */
|
|
||||||
if (size >= partLen)
|
|
||||||
{
|
|
||||||
/* 用当前输入的内容把ctx->buffer的内容补足512bits */
|
|
||||||
memcpy(&ctx->buffer[index], data, partLen);
|
|
||||||
/* 用基本函数对填充满的512bits(已经保存到ctx->buffer中) 做一次转换,转换结果保存到ctx->state中 */
|
|
||||||
MD5Transform(ctx->state, ctx->buffer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
对当前输入的剩余字节做转换(如果剩余的字节<在输入的data缓冲区中>大于512bits的话),
|
|
||||||
转换结果保存到ctx->state中
|
|
||||||
*/
|
|
||||||
for (i = partLen; i + 63 < size; i += 64) /* 把i+63<size改为i+64<=size更容易理解 */
|
|
||||||
MD5Transform(ctx->state, &data[i]);
|
|
||||||
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 将输入缓冲区中的不足填充满512bits的剩余内容填充到ctx->buffer中,留待以后再作处理 */
|
|
||||||
memcpy(&ctx->buffer[index], &data[i], size - i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
MD5 finalization. Ends an MD5 message-digest operation, writing the
|
|
||||||
the message digest and zeroizing the context.
|
|
||||||
获取加密 的最终结果
|
|
||||||
digest:保存最终的加密串
|
|
||||||
context:你前面初始化并填入了信息的md5结构
|
|
||||||
*/
|
|
||||||
static void MD5Final(MD5_CTX* ctx, HGByte* md5)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
用于bits填充的缓冲区,为什么要64个字节呢?因为当欲加密的信息的bits数被512除其余数为448时,
|
|
||||||
需要填充的bits的最大值为512=64*8 。
|
|
||||||
*/
|
|
||||||
static const HGByte MD5_PADDING[64] =
|
|
||||||
{
|
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
HGByte bits[8];
|
|
||||||
HGUInt index, padLen;
|
|
||||||
|
|
||||||
/* 将要被转换的信息(所有的)的bits长度拷贝到bits中 */
|
|
||||||
MD5Encode(bits, ctx->count, 8);
|
|
||||||
|
|
||||||
/* 计算所有的bits长度的字节数的模64, 64bytes=512bits */
|
|
||||||
index = (HGUInt)((ctx->count[0] >> 3) & 0x3F);
|
|
||||||
|
|
||||||
/* 计算需要填充的字节数,padLen的取值范围在1-64之间 */
|
|
||||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
|
||||||
|
|
||||||
/* 这一次函数调用绝对不会再导致MD5Transform的被调用,因为这一次不会填满512bits */
|
|
||||||
MD5Update(ctx, MD5_PADDING, padLen);
|
|
||||||
/* 补上原始信息的bits长度(bits长度固定的用64bits表示),这一次能够恰巧凑够512bits,不会多也不会少 */
|
|
||||||
MD5Update(ctx, bits, 8);
|
|
||||||
|
|
||||||
/* Store state in digest */
|
|
||||||
MD5Encode(md5, ctx->state, 16);
|
|
||||||
memset(ctx, 0, sizeof(MD5_CTX));
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_MakeMd5(const HGByte* data, HGUInt size, HGByte* md5)
|
|
||||||
{
|
|
||||||
if (NULL == data || 0 == size || NULL == md5)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
MD5_CTX ctx;
|
|
||||||
MD5Init(&ctx);
|
|
||||||
MD5Update(&ctx, data, size);
|
|
||||||
MD5Final(&ctx, md5);
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef __HGMD5_H__
|
|
||||||
#define __HGMD5_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
/* 生成MD5值
|
|
||||||
* 参数:
|
|
||||||
* 1) data: in, 数据地址
|
|
||||||
* 2) size: in, 数据长度
|
|
||||||
* 3) md5: out, md5值, 必须至少分配16字节
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_MakeMd5(const HGByte* data, HGUInt size, HGByte* md5);
|
|
||||||
|
|
||||||
#endif /* __HGMD5_H__ */
|
|
|
@ -1,59 +0,0 @@
|
||||||
#include "HGMsgPump.h"
|
|
||||||
#include "HGMsgPumpImpl.hpp"
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateMsgPump(HGMsgPump* msgPump)
|
|
||||||
{
|
|
||||||
if (NULL == msgPump)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGMsgPumpImpl* msgPumpImpl = new HGMsgPumpImpl;
|
|
||||||
*msgPump = (HGMsgPump)msgPumpImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DestroyMsgPump(HGMsgPump msgPump)
|
|
||||||
{
|
|
||||||
if (NULL == msgPump)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGMsgPumpImpl* msgPumpImpl = (HGMsgPumpImpl*)msgPump;
|
|
||||||
delete msgPumpImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_RunMsgPump(HGMsgPump msgPump, HGMsgPumpFunc func, HGPointer param)
|
|
||||||
{
|
|
||||||
if (NULL == msgPump)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGMsgPumpImpl* msgPumpImpl = (HGMsgPumpImpl*)msgPump;
|
|
||||||
return msgPumpImpl->Run(func, param);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_PostPumpMessage(HGMsgPump msgPump, const HGMsg* msg)
|
|
||||||
{
|
|
||||||
if (NULL == msgPump)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGMsgPumpImpl* msgPumpImpl = (HGMsgPumpImpl*)msgPump;
|
|
||||||
return msgPumpImpl->PostMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_ExitMsgPump(HGMsgPump msgPump)
|
|
||||||
{
|
|
||||||
if (NULL == msgPump)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGMsgPumpImpl* msgPumpImpl = (HGMsgPumpImpl*)msgPump;
|
|
||||||
return msgPumpImpl->Exit();
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef __HGMSGPUMP_H__
|
|
||||||
#define __HGMSGPUMP_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGMsgPump);
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
/* 消息结构体, 可以自定义 */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt id; /* 消息ID, 不能为0 */
|
|
||||||
HGPointer data; /* 携带的数据 */
|
|
||||||
}HGMsg;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
typedef void (HGAPI *HGMsgPumpFunc)(HGMsgPump msgPump, const HGMsg* msg, HGPointer param);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateMsgPump(HGMsgPump *msgPump);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DestroyMsgPump(HGMsgPump msgPump);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_RunMsgPump(HGMsgPump msgPump, HGMsgPumpFunc func, HGPointer param);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_PostPumpMessage(HGMsgPump msgPump, const HGMsg *msg);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_ExitMsgPump(HGMsgPump msgPump);
|
|
||||||
|
|
||||||
#endif /* __HGMSGPUMP_H__ */
|
|
|
@ -1,102 +0,0 @@
|
||||||
#include "HGMsgPumpImpl.hpp"
|
|
||||||
|
|
||||||
HGMsgPumpImpl::HGMsgPumpImpl()
|
|
||||||
{
|
|
||||||
HGBase_CreateEvent(HGTRUE, HGFALSE, &m_msgEvent);
|
|
||||||
HGBase_CreateLock(&m_msgLock);
|
|
||||||
m_bRecvMsg = HGTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGMsgPumpImpl::~HGMsgPumpImpl()
|
|
||||||
{
|
|
||||||
HGBase_DestroyLock(m_msgLock);
|
|
||||||
m_msgLock = NULL;
|
|
||||||
HGBase_DestroyEvent(m_msgEvent);
|
|
||||||
m_msgEvent = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGMsgPumpImpl::Run(HGMsgPumpFunc func, HGPointer param)
|
|
||||||
{
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
HGBase_WaitEvent(m_msgEvent);
|
|
||||||
|
|
||||||
HGMsg msg = { 0 };
|
|
||||||
bool getMsg = false;
|
|
||||||
|
|
||||||
HGBase_EnterLock(m_msgLock);
|
|
||||||
if (!m_listMsg.empty())
|
|
||||||
{
|
|
||||||
msg = m_listMsg.front();
|
|
||||||
m_listMsg.pop_front();
|
|
||||||
getMsg = true;
|
|
||||||
}
|
|
||||||
if (m_listMsg.empty())
|
|
||||||
{
|
|
||||||
HGBase_ResetEvent(m_msgEvent);
|
|
||||||
}
|
|
||||||
HGBase_LeaveLock(m_msgLock);
|
|
||||||
|
|
||||||
if (!getMsg)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == msg.id)
|
|
||||||
{
|
|
||||||
assert(NULL == msg.data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
func((HGMsgPump)this, &msg, param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGMsgPumpImpl::PostMessage(const HGMsg* msg)
|
|
||||||
{
|
|
||||||
if (NULL == msg || 0 == msg->id)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult ret = HGBASE_ERR_FAIL;
|
|
||||||
HGBase_EnterLock(m_msgLock);
|
|
||||||
if (m_bRecvMsg)
|
|
||||||
{
|
|
||||||
m_listMsg.push_back(*msg);
|
|
||||||
HGBase_SetEvent(m_msgEvent);
|
|
||||||
ret = HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
HGBase_LeaveLock(m_msgLock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGMsgPumpImpl::Exit()
|
|
||||||
{
|
|
||||||
HGMsg msg;
|
|
||||||
msg.id = 0;
|
|
||||||
msg.data = NULL;
|
|
||||||
|
|
||||||
HGResult ret = HGBASE_ERR_FAIL;
|
|
||||||
HGBase_EnterLock(m_msgLock);
|
|
||||||
if (m_bRecvMsg)
|
|
||||||
{
|
|
||||||
m_listMsg.push_back(msg);
|
|
||||||
HGBase_SetEvent(m_msgEvent);
|
|
||||||
m_bRecvMsg = HGFALSE;
|
|
||||||
ret = HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
HGBase_LeaveLock(m_msgLock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef __HGMSGPUMPIMPL_H__
|
|
||||||
#define __HGMSGPUMPIMPL_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
#include "HGEvent.h"
|
|
||||||
#include "HGLock.h"
|
|
||||||
#include "HGMsgPump.h"
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
class HGMsgPumpImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGMsgPumpImpl();
|
|
||||||
~HGMsgPumpImpl();
|
|
||||||
|
|
||||||
HGResult Run(HGMsgPumpFunc func, HGPointer param);
|
|
||||||
HGResult PostMessage(const HGMsg* msg);
|
|
||||||
HGResult Exit();
|
|
||||||
|
|
||||||
private:
|
|
||||||
HGEvent m_msgEvent;
|
|
||||||
HGLock m_msgLock;
|
|
||||||
HGBool m_bRecvMsg;
|
|
||||||
std::list<HGMsg> m_listMsg;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGMSGPUMPIMPL_H__ */
|
|
|
@ -1,621 +0,0 @@
|
||||||
#include "HGNamedPipe.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
#include "HGThread.h"
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct HGNamedPipeServerImpl
|
|
||||||
{
|
|
||||||
HGNamedPipeServerImpl()
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
m_hConnectEvent = NULL;
|
|
||||||
m_hWriteEvent = NULL;
|
|
||||||
m_hReadEvent = NULL;
|
|
||||||
m_hProcessEvent = NULL;
|
|
||||||
m_hPipe = INVALID_HANDLE_VALUE;
|
|
||||||
m_clientPid = 0;
|
|
||||||
m_thread = NULL;
|
|
||||||
m_error = HGFALSE;
|
|
||||||
m_break = HGFALSE;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
~HGNamedPipeServerImpl()
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HGBase_CloseThread(m_thread);
|
|
||||||
m_thread = NULL;
|
|
||||||
CloseHandle(m_hPipe);
|
|
||||||
m_hPipe = INVALID_HANDLE_VALUE;
|
|
||||||
CloseHandle(m_hProcessEvent);
|
|
||||||
m_hProcessEvent = NULL;
|
|
||||||
CloseHandle(m_hReadEvent);
|
|
||||||
m_hReadEvent = NULL;
|
|
||||||
CloseHandle(m_hWriteEvent);
|
|
||||||
m_hWriteEvent = NULL;
|
|
||||||
CloseHandle(m_hConnectEvent);
|
|
||||||
m_hConnectEvent = NULL;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HANDLE m_hConnectEvent;
|
|
||||||
HANDLE m_hWriteEvent;
|
|
||||||
HANDLE m_hReadEvent;
|
|
||||||
HANDLE m_hProcessEvent;
|
|
||||||
HANDLE m_hPipe;
|
|
||||||
DWORD m_clientPid;
|
|
||||||
HGThread m_thread;
|
|
||||||
HGBool m_error;
|
|
||||||
HGBool m_break;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HGNamedPipeClientImpl
|
|
||||||
{
|
|
||||||
HGNamedPipeClientImpl()
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
m_hWriteEvent = NULL;
|
|
||||||
m_hReadEvent = NULL;
|
|
||||||
m_hProcessEvent = NULL;
|
|
||||||
m_hPipe = INVALID_HANDLE_VALUE;
|
|
||||||
m_serverPid = 0;
|
|
||||||
m_thread = NULL;
|
|
||||||
m_error = HGFALSE;
|
|
||||||
m_break = HGFALSE;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
~HGNamedPipeClientImpl()
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HGBase_CloseThread(m_thread);
|
|
||||||
m_thread = NULL;
|
|
||||||
CloseHandle(m_hPipe);
|
|
||||||
m_hPipe = INVALID_HANDLE_VALUE;
|
|
||||||
CloseHandle(m_hProcessEvent);
|
|
||||||
m_hProcessEvent = NULL;
|
|
||||||
CloseHandle(m_hReadEvent);
|
|
||||||
m_hReadEvent = NULL;
|
|
||||||
CloseHandle(m_hWriteEvent);
|
|
||||||
m_hWriteEvent = NULL;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HANDLE m_hWriteEvent;
|
|
||||||
HANDLE m_hReadEvent;
|
|
||||||
HANDLE m_hProcessEvent;
|
|
||||||
HANDLE m_hPipe;
|
|
||||||
DWORD m_serverPid;
|
|
||||||
HGThread m_thread;
|
|
||||||
HGBool m_error;
|
|
||||||
HGBool m_break;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static void HGAPI NamedPipeServerFunc(HGThread thread, HGPointer param)
|
|
||||||
{
|
|
||||||
HGNamedPipeServerImpl* p = (HGNamedPipeServerImpl*)param;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HANDLE handles[2];
|
|
||||||
handles[0] = OpenProcess(SYNCHRONIZE, FALSE, p->m_clientPid);
|
|
||||||
handles[1] = p->m_hProcessEvent;
|
|
||||||
if (WAIT_OBJECT_0 == WaitForMultipleObjects(2, handles, FALSE, INFINITE))
|
|
||||||
{
|
|
||||||
p->m_error = HGTRUE;
|
|
||||||
SetEvent(p->m_hWriteEvent);
|
|
||||||
SetEvent(p->m_hReadEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(handles[0]);
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void NamedPipeClientFunc(HGThread thread, HGPointer param)
|
|
||||||
{
|
|
||||||
HGNamedPipeClientImpl* p = (HGNamedPipeClientImpl*)param;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HANDLE handles[2];
|
|
||||||
handles[0] = OpenProcess(SYNCHRONIZE, FALSE, p->m_serverPid);
|
|
||||||
handles[1] = p->m_hProcessEvent;
|
|
||||||
if (WAIT_OBJECT_0 == WaitForMultipleObjects(2, handles, FALSE, INFINITE))
|
|
||||||
{
|
|
||||||
p->m_error = HGTRUE;
|
|
||||||
SetEvent(p->m_hWriteEvent);
|
|
||||||
SetEvent(p->m_hReadEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(handles[0]);
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_OpenNamedPipeServer(const HGChar* pipeName, HGNamedPipeServer* server)
|
|
||||||
{
|
|
||||||
if (NULL == pipeName || NULL == server)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HANDLE hConnectEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
||||||
assert(NULL != hConnectEvent);
|
|
||||||
HANDLE hWriteEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
||||||
assert(NULL != hWriteEvent);
|
|
||||||
HANDLE hReadEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
||||||
assert(NULL != hReadEvent);
|
|
||||||
HANDLE hProcessEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
||||||
assert(NULL != hProcessEvent);
|
|
||||||
|
|
||||||
char name[256];
|
|
||||||
sprintf(name, "\\\\.\\pipe\\%s", pipeName);
|
|
||||||
HANDLE hPipe = CreateNamedPipeA(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
|
|
||||||
0, 1, 1024, 1024, 0, NULL);
|
|
||||||
if (INVALID_HANDLE_VALUE == hPipe)
|
|
||||||
{
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
CloseHandle(hConnectEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeServerImpl* pipeServerImpl = new HGNamedPipeServerImpl;
|
|
||||||
pipeServerImpl->m_hConnectEvent = hConnectEvent;
|
|
||||||
pipeServerImpl->m_hWriteEvent = hWriteEvent;
|
|
||||||
pipeServerImpl->m_hReadEvent = hReadEvent;
|
|
||||||
pipeServerImpl->m_hProcessEvent = hProcessEvent;
|
|
||||||
pipeServerImpl->m_hPipe = hPipe;
|
|
||||||
*server = (HGNamedPipeServer)pipeServerImpl;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CloseNamedPipeServer(HGNamedPipeServer server)
|
|
||||||
{
|
|
||||||
if (NULL == server)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server;
|
|
||||||
delete pipeServerImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_NamedPipeServerWrite(HGNamedPipeServer server, const HGByte* data, HGUInt size, HGUInt* writeSize)
|
|
||||||
{
|
|
||||||
if (NULL == server || NULL == data || 0 == size)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL == pipeServerImpl->m_thread || pipeServerImpl->m_error || pipeServerImpl->m_break)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
OVERLAPPED overlapped = { 0 };
|
|
||||||
overlapped.hEvent = pipeServerImpl->m_hWriteEvent;
|
|
||||||
DWORD dwNumerOfWriteBytes = 0;
|
|
||||||
if (!WriteFile(pipeServerImpl->m_hPipe, data, size, &dwNumerOfWriteBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 写入错误
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(pipeServerImpl->m_hWriteEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != writeSize)
|
|
||||||
*writeSize = dwNumerOfWriteBytes;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_NamedPipeServerRead(HGNamedPipeServer server, HGByte* data, HGUInt size, HGUInt* readSize)
|
|
||||||
{
|
|
||||||
if (NULL == server || NULL == data || 0 == size)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL == pipeServerImpl->m_thread) // 未连接
|
|
||||||
{
|
|
||||||
OVERLAPPED overlapped = { 0 };
|
|
||||||
overlapped.hEvent = pipeServerImpl->m_hConnectEvent;
|
|
||||||
if (!ConnectNamedPipe(pipeServerImpl->m_hPipe, &overlapped))
|
|
||||||
{
|
|
||||||
DWORD err = GetLastError();
|
|
||||||
if (ERROR_IO_PENDING != err && ERROR_PIPE_CONNECTED != err)
|
|
||||||
{
|
|
||||||
// 等待连接出错
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ERROR_IO_PENDING == err)
|
|
||||||
{
|
|
||||||
// 等待连接
|
|
||||||
WaitForSingleObject(pipeServerImpl->m_hConnectEvent, INFINITE);
|
|
||||||
DWORD dwTransferBytes = 0; // 此值无意义
|
|
||||||
if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwTransferBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取对方进程ID
|
|
||||||
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
|
||||||
overlapped.hEvent = pipeServerImpl->m_hReadEvent;
|
|
||||||
DWORD dwNumerOfReadBytes = 0;
|
|
||||||
DWORD clientPid = 0;
|
|
||||||
if (!ReadFile(pipeServerImpl->m_hPipe, &clientPid, sizeof(DWORD), &dwNumerOfReadBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 读取错误
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(pipeServerImpl->m_hReadEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfReadBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sizeof(DWORD) != dwNumerOfReadBytes || 0 == clientPid)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送己方进程ID
|
|
||||||
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
|
||||||
overlapped.hEvent = pipeServerImpl->m_hWriteEvent;
|
|
||||||
DWORD dwNumerOfWriteBytes = 0;
|
|
||||||
DWORD serverPid = GetCurrentProcessId();
|
|
||||||
if (!WriteFile(pipeServerImpl->m_hPipe, &serverPid, sizeof(DWORD), &dwNumerOfWriteBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 写入错误
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(pipeServerImpl->m_hWriteEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sizeof(DWORD) != dwNumerOfWriteBytes)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建线程等待对方进程ID
|
|
||||||
pipeServerImpl->m_clientPid = clientPid;
|
|
||||||
HGBase_OpenThread(NamedPipeServerFunc, pipeServerImpl, &pipeServerImpl->m_thread);
|
|
||||||
assert(NULL != pipeServerImpl->m_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pipeServerImpl->m_error || pipeServerImpl->m_break)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
OVERLAPPED overlapped = { 0 };
|
|
||||||
overlapped.hEvent = pipeServerImpl->m_hReadEvent;
|
|
||||||
DWORD dwNumerOfReadBytes = 0;
|
|
||||||
if (!ReadFile(pipeServerImpl->m_hPipe, data, size, &dwNumerOfReadBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 读取错误
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(pipeServerImpl->m_hReadEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(pipeServerImpl->m_hPipe, &overlapped, &dwNumerOfReadBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != readSize)
|
|
||||||
*readSize = dwNumerOfReadBytes;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_NamedPipeServerStop(HGNamedPipeServer server)
|
|
||||||
{
|
|
||||||
if (NULL == server)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeServerImpl* pipeServerImpl = (HGNamedPipeServerImpl*)server;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
pipeServerImpl->m_break = HGTRUE;
|
|
||||||
SetEvent(pipeServerImpl->m_hConnectEvent);
|
|
||||||
SetEvent(pipeServerImpl->m_hWriteEvent);
|
|
||||||
SetEvent(pipeServerImpl->m_hReadEvent);
|
|
||||||
SetEvent(pipeServerImpl->m_hProcessEvent);
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_OpenNamedPipeClient(const HGChar* pipeName, HGNamedPipeClient* client)
|
|
||||||
{
|
|
||||||
if (NULL == pipeName || NULL == client)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
HANDLE hWriteEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
||||||
assert(NULL != hWriteEvent);
|
|
||||||
HANDLE hReadEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
||||||
assert(NULL != hReadEvent);
|
|
||||||
HANDLE hProcessEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
||||||
assert(NULL != hProcessEvent);
|
|
||||||
|
|
||||||
char name[256];
|
|
||||||
sprintf(name, "\\\\.\\pipe\\%s", pipeName);
|
|
||||||
HANDLE hPipe = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
|
|
||||||
if (INVALID_HANDLE_VALUE == hPipe)
|
|
||||||
{
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送己方进程ID
|
|
||||||
OVERLAPPED overlapped = { 0 };
|
|
||||||
overlapped.hEvent = hWriteEvent;
|
|
||||||
DWORD dwNumerOfWriteBytes = 0;
|
|
||||||
DWORD clientPid = GetCurrentProcessId();
|
|
||||||
if (!WriteFile(hPipe, &clientPid, sizeof(DWORD), &dwNumerOfWriteBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 写入错误
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(hWriteEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sizeof(DWORD) != dwNumerOfWriteBytes)
|
|
||||||
{
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取对方进程ID
|
|
||||||
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
|
||||||
overlapped.hEvent = hReadEvent;
|
|
||||||
DWORD dwNumerOfReadBytes = 0;
|
|
||||||
DWORD serverPid = 0;
|
|
||||||
if (!ReadFile(hPipe, &serverPid, sizeof(DWORD), &dwNumerOfReadBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 读取错误
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(hReadEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(hPipe, &overlapped, &dwNumerOfReadBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sizeof(DWORD) != dwNumerOfReadBytes || 0 == serverPid)
|
|
||||||
{
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
CloseHandle(hProcessEvent);
|
|
||||||
CloseHandle(hReadEvent);
|
|
||||||
CloseHandle(hWriteEvent);
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建线程等待对方进程ID
|
|
||||||
|
|
||||||
HGNamedPipeClientImpl* pipeClientImpl = new HGNamedPipeClientImpl;
|
|
||||||
pipeClientImpl->m_hWriteEvent = hWriteEvent;
|
|
||||||
pipeClientImpl->m_hReadEvent = hReadEvent;
|
|
||||||
pipeClientImpl->m_hProcessEvent = hProcessEvent;
|
|
||||||
pipeClientImpl->m_hPipe = hPipe;
|
|
||||||
pipeClientImpl->m_serverPid = serverPid;
|
|
||||||
HGBase_OpenThread(NamedPipeServerFunc, pipeClientImpl, &pipeClientImpl->m_thread);
|
|
||||||
assert(NULL != pipeClientImpl->m_thread);
|
|
||||||
*client = (HGNamedPipeClient)pipeClientImpl;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CloseNamedPipeClient(HGNamedPipeClient client)
|
|
||||||
{
|
|
||||||
if (NULL == client)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client;
|
|
||||||
delete pipeClientImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_NamedPipeClientWrite(HGNamedPipeClient client, const HGByte* data, HGUInt size, HGUInt* writeSize)
|
|
||||||
{
|
|
||||||
if (NULL == client)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
assert(NULL != pipeClientImpl->m_thread);
|
|
||||||
|
|
||||||
if (pipeClientImpl->m_error || pipeClientImpl->m_break)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
OVERLAPPED overlapped = { 0 };
|
|
||||||
overlapped.hEvent = pipeClientImpl->m_hWriteEvent;
|
|
||||||
DWORD dwNumerOfWriteBytes = 0;
|
|
||||||
if (!WriteFile(pipeClientImpl->m_hPipe, data, size, &dwNumerOfWriteBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 写入错误
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(pipeClientImpl->m_hWriteEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(pipeClientImpl->m_hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (NULL != writeSize)
|
|
||||||
*writeSize = dwNumerOfWriteBytes;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_NamedPipeClientRead(HGNamedPipeClient client, HGByte* data, HGUInt size, HGUInt* readSize)
|
|
||||||
{
|
|
||||||
if (NULL == client)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
assert(NULL != pipeClientImpl->m_thread);
|
|
||||||
|
|
||||||
if (pipeClientImpl->m_error || pipeClientImpl->m_break)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
OVERLAPPED overlapped = { 0 };
|
|
||||||
overlapped.hEvent = pipeClientImpl->m_hReadEvent;
|
|
||||||
DWORD dwNumerOfReadBytes = 0;
|
|
||||||
if (!ReadFile(pipeClientImpl->m_hPipe, data, size, &dwNumerOfReadBytes, &overlapped))
|
|
||||||
{
|
|
||||||
if (ERROR_IO_PENDING != GetLastError())
|
|
||||||
{
|
|
||||||
// 读取错误
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(pipeClientImpl->m_hReadEvent, INFINITE);
|
|
||||||
if (!GetOverlappedResult(pipeClientImpl->m_hPipe, &overlapped, &dwNumerOfReadBytes, TRUE))
|
|
||||||
{
|
|
||||||
// 手动停止
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != readSize)
|
|
||||||
*readSize = dwNumerOfReadBytes;
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_NamedPipeClientStop(HGNamedPipeClient client)
|
|
||||||
{
|
|
||||||
if (NULL == client)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGNamedPipeClientImpl* pipeClientImpl = (HGNamedPipeClientImpl*)client;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
pipeClientImpl->m_break = HGTRUE;
|
|
||||||
SetEvent(pipeClientImpl->m_hWriteEvent);
|
|
||||||
SetEvent(pipeClientImpl->m_hReadEvent);
|
|
||||||
SetEvent(pipeClientImpl->m_hProcessEvent);
|
|
||||||
#else
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#ifndef __HGNAMEDPIPE_H__
|
|
||||||
#define __HGNAMEDPIPE_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGNamedPipeServer);
|
|
||||||
HG_DECLARE_HANDLE(HGNamedPipeClient);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_OpenNamedPipeServer(const HGChar* pipeName, HGNamedPipeServer *server);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CloseNamedPipeServer(HGNamedPipeServer server);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_NamedPipeServerWrite(HGNamedPipeServer server, const HGByte* data, HGUInt size, HGUInt* writeSize);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_NamedPipeServerRead(HGNamedPipeServer server, HGByte* data, HGUInt size, HGUInt* readSize);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_NamedPipeServerStop(HGNamedPipeServer server);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_OpenNamedPipeClient(const HGChar* pipeName, HGNamedPipeClient* client);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CloseNamedPipeClient(HGNamedPipeClient client);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_NamedPipeClientWrite(HGNamedPipeClient client, const HGByte* data, HGUInt size, HGUInt* writeSize);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_NamedPipeClientRead(HGNamedPipeClient client, HGByte* data, HGUInt size, HGUInt* readSize);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_NamedPipeClientStop(HGNamedPipeClient client);
|
|
||||||
|
|
||||||
#endif /* __HGNAMEDPIPE_H__ */
|
|
|
@ -1,102 +0,0 @@
|
||||||
#include "HGThread.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
struct HGThreadImpl
|
|
||||||
{
|
|
||||||
HGThreadImpl()
|
|
||||||
{
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
m_ntid = 0;
|
|
||||||
#else
|
|
||||||
m_thread = NULL;
|
|
||||||
#endif
|
|
||||||
m_func = NULL;
|
|
||||||
m_param = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~HGThreadImpl()
|
|
||||||
{
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
if (0 != m_ntid)
|
|
||||||
{
|
|
||||||
pthread_join(m_ntid, NULL);
|
|
||||||
m_ntid = 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (NULL != m_thread)
|
|
||||||
{
|
|
||||||
WaitForSingleObject(m_thread, INFINITE);
|
|
||||||
CloseHandle(m_thread);
|
|
||||||
m_thread = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
m_param = 0;
|
|
||||||
m_func = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
static void* thread_fun(void* arg)
|
|
||||||
{
|
|
||||||
HGThreadImpl* p = (HGThreadImpl*)arg;
|
|
||||||
p->m_func((HGThread)p, p->m_param);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static DWORD WINAPI ThreadCallback(LPVOID param)
|
|
||||||
{
|
|
||||||
HGThreadImpl* p = (HGThreadImpl*)param;
|
|
||||||
p->m_func((HGThread)p, p->m_param);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
pthread_t m_ntid;
|
|
||||||
#else
|
|
||||||
HANDLE m_thread;
|
|
||||||
#endif
|
|
||||||
HGThreadFunc m_func;
|
|
||||||
HGPointer m_param;
|
|
||||||
};
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_OpenThread(HGThreadFunc func, HGPointer param, HGThread* thread)
|
|
||||||
{
|
|
||||||
if (NULL == func || NULL == thread)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGThreadImpl* threadImpl = new HGThreadImpl;
|
|
||||||
threadImpl->m_func = func;
|
|
||||||
threadImpl->m_param = param;
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
if (0 != pthread_create(&threadImpl->m_ntid, NULL, HGThreadImpl::thread_fun, threadImpl))
|
|
||||||
{
|
|
||||||
delete threadImpl;
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
threadImpl->m_thread = CreateThread(NULL, 0, HGThreadImpl::ThreadCallback, threadImpl, 0, NULL);
|
|
||||||
if (NULL == threadImpl->m_thread)
|
|
||||||
{
|
|
||||||
delete threadImpl;
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
* thread = (HGThread)threadImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CloseThread(HGThread thread)
|
|
||||||
{
|
|
||||||
if (NULL == thread)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGThreadImpl* threadImpl = (HGThreadImpl*)thread;
|
|
||||||
delete threadImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef __HGTHREAD_H__
|
|
||||||
#define __HGTHREAD_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGThread);
|
|
||||||
|
|
||||||
/* 线程回调函数
|
|
||||||
* 参数:
|
|
||||||
* 1) thread: in, 线程句柄
|
|
||||||
* 2) param: in, 回调参数
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
typedef void (HGAPI *HGThreadFunc)(HGThread thread, HGPointer param);
|
|
||||||
|
|
||||||
/* 开启线程
|
|
||||||
* 参数:
|
|
||||||
* 1) func: in, 线程回调函数
|
|
||||||
* 2) param: in, 回调参数
|
|
||||||
* 3) thread: out, 线程句柄
|
|
||||||
* 说明:
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_OpenThread(HGThreadFunc func, HGPointer param, HGThread *thread);
|
|
||||||
|
|
||||||
/* 关闭线程
|
|
||||||
* 参数:
|
|
||||||
* 1) thread: in, 线程句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数会等待线程正常结束, 如果线程阻塞, 该函数也会阻塞
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CloseThread(HGThread thread);
|
|
||||||
|
|
||||||
#endif /* __HGTHREAD_H__ */
|
|
|
@ -1,37 +0,0 @@
|
||||||
#include "HGTime.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetLocalTime(HGTimeInfo* timeInfo)
|
|
||||||
{
|
|
||||||
if (NULL == timeInfo)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
SYSTEMTIME st;
|
|
||||||
GetLocalTime(&st);
|
|
||||||
timeInfo->year = st.wYear;
|
|
||||||
timeInfo->month = st.wMonth;
|
|
||||||
timeInfo->day = st.wDay;
|
|
||||||
timeInfo->dayOfWeek = st.wDayOfWeek;
|
|
||||||
timeInfo->hour = st.wHour;
|
|
||||||
timeInfo->minute = st.wMinute;
|
|
||||||
timeInfo->second = st.wSecond;
|
|
||||||
timeInfo->milliseconds = st.wMilliseconds;
|
|
||||||
#else
|
|
||||||
struct timeval time;
|
|
||||||
gettimeofday(&time, NULL);
|
|
||||||
struct tm* p = localtime(&time.tv_sec);
|
|
||||||
assert(NULL != p);
|
|
||||||
timeInfo->year = p->tm_year + 1900;
|
|
||||||
timeInfo->month = 1 + p->tm_mon;
|
|
||||||
timeInfo->day = p->tm_mday;
|
|
||||||
timeInfo->dayOfWeek = p->tm_wday;
|
|
||||||
timeInfo->hour = p->tm_hour;
|
|
||||||
timeInfo->minute = p->tm_min;
|
|
||||||
timeInfo->second = p->tm_sec;
|
|
||||||
timeInfo->milliseconds = time.tv_usec / 1000;
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef __HGTIME_H__
|
|
||||||
#define __HGTIME_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUShort year;
|
|
||||||
HGUShort month;
|
|
||||||
HGUShort day;
|
|
||||||
HGUShort dayOfWeek; /* 0为星期天, 1-6表示星期一到星期六 */
|
|
||||||
HGUShort hour;
|
|
||||||
HGUShort minute;
|
|
||||||
HGUShort second;
|
|
||||||
HGUShort milliseconds;
|
|
||||||
}HGTimeInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetLocalTime(HGTimeInfo *timeInfo);
|
|
||||||
|
|
||||||
#endif /* __HGTIME_H__ */
|
|
|
@ -1,650 +0,0 @@
|
||||||
#include "HGUtility.h"
|
|
||||||
#include "HGInc.h"
|
|
||||||
#include "HGInfo.h"
|
|
||||||
#include "HGIni.h"
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
#include <shlobj.h>
|
|
||||||
#include <atlstr.h>
|
|
||||||
#else
|
|
||||||
#include "uuid/uuid.h"
|
|
||||||
#endif
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetTmpPath(HGChar* path, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == path || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
char tmpPath[512] = {0};
|
|
||||||
strcpy(tmpPath, "/tmp/");
|
|
||||||
#else
|
|
||||||
CHAR tmpPath[MAX_PATH] = { 0 };
|
|
||||||
DWORD len = GetTempPathA(MAX_PATH, tmpPath);
|
|
||||||
if (0 == len)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (tmpPath[strlen(tmpPath) - 1] != '\\')
|
|
||||||
strcat(tmpPath, "\\");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < strlen(tmpPath) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(path, tmpPath);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetCurrentDir(HGChar* dir, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == dir || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
char buffer[512] = { 0 };
|
|
||||||
char* p = getcwd(buffer, 512);
|
|
||||||
if (NULL == p)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (buffer[strlen(buffer) - 1] != '/')
|
|
||||||
strcat(buffer, "/");
|
|
||||||
#else
|
|
||||||
CHAR buffer[MAX_PATH] = { 0 };
|
|
||||||
DWORD len = GetCurrentDirectoryA(MAX_PATH, buffer);
|
|
||||||
if (0 == len)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (buffer[strlen(buffer) - 1] != '\\')
|
|
||||||
strcat(buffer, "\\");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < strlen(buffer) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(dir, buffer);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_SetCurrentDir(const HGChar* dir)
|
|
||||||
{
|
|
||||||
if (NULL == dir)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
if (0 != chdir(dir))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#else
|
|
||||||
if (!SetCurrentDirectoryA(dir))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_CreateDir(const HGChar* dir)
|
|
||||||
{
|
|
||||||
if (NULL == dir)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
bool ret = true;
|
|
||||||
|
|
||||||
char muldir[512] = { 0 };
|
|
||||||
strcpy(muldir, dir);
|
|
||||||
for (size_t i = 0; i < strlen(muldir); ++i)
|
|
||||||
{
|
|
||||||
if ('/' == muldir[i])
|
|
||||||
{
|
|
||||||
muldir[i] = '\0';
|
|
||||||
if ('\0' != *muldir && 0 != access(muldir, 0))
|
|
||||||
{
|
|
||||||
if (0 != mkdir(muldir, 0777))
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGBase_CreateDir: mkdir fail, %s errno=%d", dir, errno);
|
|
||||||
ret = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
muldir[i] = '/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
if ('\0' != *muldir && 0 != access(muldir, 0))
|
|
||||||
{
|
|
||||||
if (0 != mkdir(muldir, 0777))
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGBase_CreateDir: mkdir fail, %s errno=%d", dir, errno);
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
#else
|
|
||||||
int ret = SHCreateDirectoryExA(NULL, dir, NULL);
|
|
||||||
if (ERROR_SUCCESS != ret && ERROR_ALREADY_EXISTS != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGBase_CreateDir: SHCreateDirectoryExA fail, %s GetLastError=%u", dir, GetLastError());
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DeleteDir(const HGChar* dir)
|
|
||||||
{
|
|
||||||
if (NULL == dir)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
if (0 != rmdir(dir))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#else
|
|
||||||
if (!RemoveDirectoryA(dir))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_DeleteFile(const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL == fileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
if (0 != unlink(fileName))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#else
|
|
||||||
if (!DeleteFileA(fileName))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetModuleName(HGPointer addr, HGChar* name, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == name || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
if (NULL == addr)
|
|
||||||
{
|
|
||||||
char dir[PATH_MAX] = {0};
|
|
||||||
if (0 == readlink("/proc/self/exe", dir, PATH_MAX))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (maxLen < strlen(dir) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(name, dir);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Dl_info dlinfo;
|
|
||||||
if (0 == dladdr(addr, &dlinfo))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (maxLen < strlen(dlinfo.dli_fname) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(name, dlinfo.dli_fname);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
HMODULE hModule = NULL;
|
|
||||||
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
|
||||||
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)addr, &hModule);
|
|
||||||
|
|
||||||
CHAR moduleName[MAX_PATH] = { 0 };
|
|
||||||
DWORD len = GetModuleFileNameA(hModule, moduleName, MAX_PATH);
|
|
||||||
if (0 == len || maxLen < strlen(moduleName) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(name, moduleName);
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetUuid(HGChar* uuid, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == uuid || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(HG_CMP_MSC)
|
|
||||||
uuid_t id;
|
|
||||||
uuid_generate(id);
|
|
||||||
|
|
||||||
char str[128] = {0};
|
|
||||||
uuid_unparse(id, str);
|
|
||||||
if (maxLen < strlen(str) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(uuid, str);
|
|
||||||
#else
|
|
||||||
GUID guid;
|
|
||||||
if (S_OK != CoCreateGuid(&guid))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
|
|
||||||
char str[128] = {0};
|
|
||||||
sprintf(str, "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1],
|
|
||||||
guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
|
||||||
if (maxLen < strlen(str) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(uuid, str);
|
|
||||||
#endif
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetTmpFileName(const HGChar* suffix, HGChar* fileName, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar path[256] = { 0 }, uuid[128] = {0};
|
|
||||||
HGBase_GetTmpPath(path, 256);
|
|
||||||
HGBase_GetUuid(uuid, 128);
|
|
||||||
strcat(path, uuid);
|
|
||||||
if (NULL != suffix && 0 != *suffix)
|
|
||||||
{
|
|
||||||
strcat(path, ".");
|
|
||||||
strcat(path, suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxLen < strlen(path) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(fileName, path);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetConfigPath(HGChar* configPath, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == configPath || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar moduleName[256];
|
|
||||||
HGBase_GetModuleName(NULL, moduleName, 256);
|
|
||||||
HGChar modulePath[256];
|
|
||||||
HGBase_GetFilePath(moduleName, modulePath, 256);
|
|
||||||
strcat(modulePath, "first.cfg");
|
|
||||||
|
|
||||||
HGChar dataPath[256] = {0};
|
|
||||||
HGBase_GetProfileString(modulePath, "constraints", "local_data_path", "", dataPath, 256);
|
|
||||||
if ('\0' != *dataPath)
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (dataPath[strlen(dataPath) - 1] != '\\')
|
|
||||||
strcat(dataPath, "\\");
|
|
||||||
strcat(dataPath, "Cfg\\");
|
|
||||||
#else
|
|
||||||
if (dataPath[strlen(dataPath) - 1] != '/')
|
|
||||||
strcat(dataPath, "/");
|
|
||||||
strcat(dataPath, "Cfg/");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < strlen(dataPath) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(configPath, dataPath);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
CHAR cfgPath[MAX_PATH] = { 0 };
|
|
||||||
BOOL ret = SHGetSpecialFolderPathA(NULL, cfgPath, CSIDL_APPDATA, FALSE);
|
|
||||||
if (!ret)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (cfgPath[strlen(cfgPath) - 1] != '\\')
|
|
||||||
strcat(cfgPath, "\\");
|
|
||||||
|
|
||||||
HGChar procName[64];
|
|
||||||
HGBase_GetProcessName(procName, 64);
|
|
||||||
strcat(cfgPath, procName);
|
|
||||||
strcat(cfgPath, "\\Cfg\\");
|
|
||||||
#else
|
|
||||||
char cfgPath[512] = { 0 };
|
|
||||||
strcpy(cfgPath, getenv("HOME"));
|
|
||||||
if (cfgPath[strlen(cfgPath) - 1] != '/')
|
|
||||||
strcat(cfgPath, "/");
|
|
||||||
|
|
||||||
strcat(cfgPath, ".");
|
|
||||||
HGChar procName[64];
|
|
||||||
HGBase_GetProcessName(procName, 64);
|
|
||||||
strcat(cfgPath, procName);
|
|
||||||
strcat(cfgPath, "/Cfg/");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < strlen(cfgPath) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(configPath, cfgPath);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetLogFilePath(HGChar* logFilePath, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == logFilePath || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar moduleName[256];
|
|
||||||
HGBase_GetModuleName(NULL, moduleName, 256);
|
|
||||||
HGChar modulePath[256];
|
|
||||||
HGBase_GetFilePath(moduleName, modulePath, 256);
|
|
||||||
strcat(modulePath, "first.cfg");
|
|
||||||
|
|
||||||
HGChar dataPath[256] = { 0 };
|
|
||||||
HGBase_GetProfileString(modulePath, "constraints", "local_data_path", "", dataPath, 256);
|
|
||||||
if ('\0' != *dataPath)
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (dataPath[strlen(dataPath) - 1] != '\\')
|
|
||||||
strcat(dataPath, "\\");
|
|
||||||
strcat(dataPath, "Cfg\\");
|
|
||||||
#else
|
|
||||||
if (dataPath[strlen(dataPath) - 1] != '/')
|
|
||||||
strcat(dataPath, "/");
|
|
||||||
strcat(dataPath, "Cfg/");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < strlen(dataPath) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(logFilePath, dataPath);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
CHAR logPath[MAX_PATH] = { 0 };
|
|
||||||
BOOL ret = SHGetSpecialFolderPathA(NULL, logPath, CSIDL_APPDATA, FALSE);
|
|
||||||
if (!ret)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (logPath[strlen(logPath) - 1] != '\\')
|
|
||||||
strcat(logPath, "\\");
|
|
||||||
|
|
||||||
HGChar procName[64];
|
|
||||||
HGBase_GetProcessName(procName, 64);
|
|
||||||
strcat(logPath, procName);
|
|
||||||
strcat(logPath, "\\Log\\");
|
|
||||||
#else
|
|
||||||
char logPath[512] = { 0 };
|
|
||||||
strcpy(logPath, getenv("HOME"));
|
|
||||||
if (logPath[strlen(logPath) - 1] != '/')
|
|
||||||
strcat(logPath, "/");
|
|
||||||
|
|
||||||
strcat(logPath, ".");
|
|
||||||
HGChar procName[64];
|
|
||||||
HGBase_GetProcessName(procName, 64);
|
|
||||||
strcat(logPath, procName);
|
|
||||||
strcat(logPath, "/Log/");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < strlen(logPath) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(logFilePath, logPath);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetDocumentsPath(HGChar* documentsPath, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == documentsPath || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
CHAR docPath[MAX_PATH] = { 0 };
|
|
||||||
BOOL ret = SHGetSpecialFolderPathA(NULL, docPath, CSIDL_MYDOCUMENTS, FALSE);
|
|
||||||
if (!ret)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (docPath[strlen(docPath) - 1] != '\\')
|
|
||||||
strcat(docPath, "\\");
|
|
||||||
#else
|
|
||||||
char docPath[512] = { 0 };
|
|
||||||
strcpy(docPath, getenv("HOME"));
|
|
||||||
if (docPath[strlen(docPath) - 1] != '/')
|
|
||||||
strcat(docPath, "/");
|
|
||||||
strcat(docPath, "Documents/");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < strlen(docPath) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(documentsPath, docPath);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetProcessName(HGChar* name, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == name || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
CHAR moduleName[MAX_PATH] = { 0 };
|
|
||||||
DWORD len = GetModuleFileNameA(NULL, moduleName, MAX_PATH);
|
|
||||||
if (0 == len)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
CStringA strModuleName(moduleName);
|
|
||||||
int pos = strModuleName.ReverseFind('\\');
|
|
||||||
if (-1 == pos)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strModuleName = strModuleName.Right(strModuleName.GetLength() - pos - 1);
|
|
||||||
pos = strModuleName.ReverseFind('.');
|
|
||||||
if (-1 != pos)
|
|
||||||
strModuleName = strModuleName.Left(pos);
|
|
||||||
if (maxLen < (HGUInt)strModuleName.GetLength() + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(name, strModuleName);
|
|
||||||
#else
|
|
||||||
char aucPathBuf[1024] = { 0 };
|
|
||||||
if (readlink("/proc/self/exe", aucPathBuf, 1024) <= 0)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
const char* pcName = strrchr(aucPathBuf, '/');
|
|
||||||
if (NULL == pcName)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
++pcName;
|
|
||||||
std::string procName(pcName);
|
|
||||||
const char* pcSuffix = strrchr(procName.c_str(), '.');
|
|
||||||
if (NULL != pcSuffix)
|
|
||||||
procName = procName.substr(0, pcSuffix - procName.c_str());
|
|
||||||
if (maxLen < (HGUInt)procName.size() + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(name, procName.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetFilePath(const HGChar* fileName, HGChar* path, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == path || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
const char* pcName = strrchr(fileName, '\\');
|
|
||||||
if (NULL == pcName)
|
|
||||||
{
|
|
||||||
pcName = strrchr(fileName, '/');
|
|
||||||
if (NULL == pcName)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
const char* pcName = strrchr(fileName, '/');
|
|
||||||
if (NULL == pcName)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
++pcName;
|
|
||||||
if (maxLen < (HGUInt)(pcName - fileName + 1))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
memcpy(path, fileName, pcName - fileName);
|
|
||||||
path[pcName - fileName] = 0;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetFileName(const HGChar* fileName, HGChar* name, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == name || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
const char* pcName = strrchr(fileName, '\\');
|
|
||||||
if (NULL == pcName)
|
|
||||||
{
|
|
||||||
pcName = strrchr(fileName, '/');
|
|
||||||
if (NULL == pcName)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
const char* pcName = strrchr(fileName, '/');
|
|
||||||
if (NULL == pcName)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
++pcName;
|
|
||||||
if (maxLen < strlen(pcName) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(name, pcName);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetFilePrefix(const HGChar* fileName, HGChar* prefix, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == prefix || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
CStringA strPrefix;
|
|
||||||
CStringA strFileName(fileName);
|
|
||||||
int pos = strFileName.ReverseFind('.');
|
|
||||||
if (-1 == pos)
|
|
||||||
strPrefix = strFileName;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CStringA strSuffix = strFileName.Right(strFileName.GetLength() - pos - 1);
|
|
||||||
if (-1 != strSuffix.Find('\\') || -1 != strSuffix.Find('/'))
|
|
||||||
strPrefix = strFileName;
|
|
||||||
else
|
|
||||||
strPrefix = strFileName.Left(pos);
|
|
||||||
}
|
|
||||||
if (maxLen < (HGUInt)strPrefix.GetLength() + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(prefix, strPrefix);
|
|
||||||
#else
|
|
||||||
std::string strPrefix;
|
|
||||||
const char* pcSuffix = strrchr(fileName, '.');
|
|
||||||
if (NULL == pcSuffix)
|
|
||||||
strPrefix = fileName;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (NULL != strchr(pcSuffix + 1, '/'))
|
|
||||||
strPrefix = fileName;
|
|
||||||
else
|
|
||||||
strPrefix = std::string(fileName, pcSuffix - fileName);
|
|
||||||
}
|
|
||||||
if (maxLen < (HGUInt)strPrefix.size() + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(prefix, strPrefix.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_GetFileSuffix(const HGChar* fileName, HGChar* suffix, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == suffix || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
CStringA strFileName(fileName);
|
|
||||||
int pos = strFileName.ReverseFind('.');
|
|
||||||
if (-1 == pos)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
CStringA strSuffix = strFileName.Right(strFileName.GetLength() - pos - 1);
|
|
||||||
if (-1 != strSuffix.Find('\\') || -1 != strSuffix.Find('/'))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (maxLen < (HGUInt)strSuffix.GetLength() + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(suffix, strSuffix);
|
|
||||||
#else
|
|
||||||
const char* pcSuffix = strrchr(fileName, '.');
|
|
||||||
if (NULL == pcSuffix)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
++pcSuffix;
|
|
||||||
if (NULL != strchr(pcSuffix, '/'))
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
if (maxLen < (HGUInt)strlen(pcSuffix) + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(suffix, pcSuffix);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGBase_StandardiseFileName(const HGChar* fileName, HGChar* result, HGUInt maxLen)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == result || 0 == maxLen)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string stdFileName;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
bool separator = false;
|
|
||||||
for (const HGChar* p = fileName; *p != 0; ++p)
|
|
||||||
{
|
|
||||||
if (*p == '\\' || *p == '/')
|
|
||||||
{
|
|
||||||
if (!separator)
|
|
||||||
{
|
|
||||||
stdFileName.push_back('\\');
|
|
||||||
separator = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stdFileName.push_back(*p);
|
|
||||||
separator = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
bool separator = false;
|
|
||||||
for (const HGChar* p = fileName; *p != 0; ++p)
|
|
||||||
{
|
|
||||||
if (*p == '/')
|
|
||||||
{
|
|
||||||
if (!separator)
|
|
||||||
{
|
|
||||||
stdFileName.push_back('/');
|
|
||||||
separator = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stdFileName.push_back(*p);
|
|
||||||
separator = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (maxLen < (HGUInt)stdFileName.size() + 1)
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
strcpy(result, stdFileName.c_str());
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
#ifndef __HGUTILITY_H__
|
|
||||||
#define __HGUTILITY_H__
|
|
||||||
|
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGBaseErr.h"
|
|
||||||
|
|
||||||
/* 获取系统临时文件目录
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetTmpPath(HGChar* path, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 获取进程的当前工作目录
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetCurrentDir(HGChar* dir, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 设置进程的当前工作目录
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_SetCurrentDir(const HGChar* dir);
|
|
||||||
|
|
||||||
/* 创建目录
|
|
||||||
* 该函数可以创建多级目录
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_CreateDir(const HGChar* dir);
|
|
||||||
|
|
||||||
/* 删除目录
|
|
||||||
* 该函数只能用于删除空目录
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DeleteDir(const HGChar* dir);
|
|
||||||
|
|
||||||
/* 删除文件
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_DeleteFile(const HGChar* fileName);
|
|
||||||
|
|
||||||
/* 获取模块名称
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetModuleName(HGPointer addr, HGChar* name, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 获取UUID
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetUuid(HGChar* uuid, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 获取临时文件名
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetTmpFileName(const HGChar *suffix, HGChar* fileName, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 获取配置文件路径
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetConfigPath(HGChar* configPath, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 获取日志文件路径
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetLogFilePath(HGChar* logFilePath, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 获取文档路径
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetDocumentsPath(HGChar* documentsPath, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 获取进程名
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetProcessName(HGChar* name, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 通过文件全路径获取路径
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetFilePath(const HGChar* fileName, HGChar* path, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 通过文件全路径获取文件名
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetFileName(const HGChar* fileName, HGChar* name, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 通过文件名获取文件前缀
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetFilePrefix(const HGChar* fileName, HGChar* prefix, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 通过文件名获取文件后缀
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_GetFileSuffix(const HGChar *fileName, HGChar* suffix, HGUInt maxLen);
|
|
||||||
|
|
||||||
/* 将文件名标准化 */
|
|
||||||
HGEXPORT HGResult HGAPI HGBase_StandardiseFileName(const HGChar* fileName, HGChar *result, HGUInt maxLen);
|
|
||||||
|
|
||||||
#endif /* __HGUTILITY_H__ */
|
|
|
@ -1,49 +0,0 @@
|
||||||
#include "HGDef.h"
|
|
||||||
#include "HGInfoImpl.hpp"
|
|
||||||
#include "HGInc.h"
|
|
||||||
|
|
||||||
extern HGInfoImpl* g_infoImpl;
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
|
|
||||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
|
||||||
{
|
|
||||||
switch (ul_reason_for_call)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
{
|
|
||||||
g_infoImpl = new HGInfoImpl;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DLL_THREAD_ATTACH:
|
|
||||||
break;
|
|
||||||
case DLL_THREAD_DETACH:
|
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
{
|
|
||||||
delete g_infoImpl;
|
|
||||||
g_infoImpl = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
void __attribute__((constructor)) global_load(void);
|
|
||||||
void __attribute__((destructor)) global_unload(void);
|
|
||||||
|
|
||||||
void global_load(void)
|
|
||||||
{
|
|
||||||
g_infoImpl = new HGInfoImpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void global_unload(void)
|
|
||||||
{
|
|
||||||
delete g_infoImpl;
|
|
||||||
g_infoImpl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,557 +0,0 @@
|
||||||
#include "HGBmp.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "libnsbmp.h"
|
|
||||||
};
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CheckBmpFile(const HGChar* fileName, HGBool* isBmp)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == isBmp)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBmpLoadInfo info;
|
|
||||||
HGResult ret = HGImgFmt_LoadBmpImage(fileName, &info, 0, 0, NULL);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*isBmp = HGTRUE;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* bitmap_create(int width, int height, unsigned int state)
|
|
||||||
{
|
|
||||||
if (width <= 0 || height <= 0)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)state; /* unused */
|
|
||||||
return calloc((intptr_t)width * (intptr_t)height, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned char* bitmap_get_buffer(void* bitmap)
|
|
||||||
{
|
|
||||||
assert(NULL != bitmap);
|
|
||||||
return (unsigned char*)bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t bitmap_get_bpp(void* bitmap)
|
|
||||||
{
|
|
||||||
(void)bitmap; /* unused */
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bitmap_destroy(void* bitmap)
|
|
||||||
{
|
|
||||||
assert(NULL != bitmap);
|
|
||||||
free(bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadBmpImage(const HGChar* fileName, HGBmpLoadInfo* 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_BINARY != imgType && HGBASE_IMGTYPE_GRAY != imgType
|
|
||||||
&& HGBASE_IMGTYPE_BGR != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
||||||
&& HGBASE_IMGTYPE_BGRA != imgType && HGBASE_IMGTYPE_RGBA != imgType)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(fileName, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(fileName, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* file = fopen(fileName, "rb");
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
_fseeki64(file, 0, SEEK_END);
|
|
||||||
uint64_t size = _ftelli64(file);
|
|
||||||
#else
|
|
||||||
fseeko64(file, 0, SEEK_END);
|
|
||||||
uint64_t size = ftello64(file);
|
|
||||||
#endif
|
|
||||||
if (0 == size)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* buffer = (uint8_t*)malloc((size_t)size);
|
|
||||||
if (NULL == buffer)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
_fseeki64(file, 0, SEEK_SET);
|
|
||||||
#else
|
|
||||||
fseeko64(file, 0, SEEK_SET);
|
|
||||||
#endif
|
|
||||||
size_t readSize = fread(buffer, 1, (size_t)size, file);
|
|
||||||
if (readSize != size)
|
|
||||||
{
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bmp_image bmp;
|
|
||||||
bmp_bitmap_callback_vt bitmap_callbacks = { bitmap_create, bitmap_destroy, bitmap_get_buffer, bitmap_get_bpp };
|
|
||||||
bmp_create(&bmp, &bitmap_callbacks);
|
|
||||||
|
|
||||||
if (BMP_OK != bmp_analyse(&bmp, (size_t)size, buffer))
|
|
||||||
{
|
|
||||||
bmp_finalise(&bmp);
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
info->width = bmp.width;
|
|
||||||
info->height = bmp.height;
|
|
||||||
info->bitCount = bmp.bpp;
|
|
||||||
info->compression = (uint32_t)bmp.encoding;
|
|
||||||
info->xPelsPerMeter = bmp.x_pels_per_meter;
|
|
||||||
info->yPelsPerMeter = bmp.y_pels_per_meter;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != image)
|
|
||||||
{
|
|
||||||
if (BMP_OK != bmp_decode(&bmp))
|
|
||||||
{
|
|
||||||
bmp_finalise(&bmp);
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == imgType)
|
|
||||||
{
|
|
||||||
imgType = HGBASE_IMGTYPE_RGB;
|
|
||||||
|
|
||||||
if (1 == bmp.bpp || 4 == bmp.bpp || 8 == bmp.bpp)
|
|
||||||
{
|
|
||||||
bool bGray = true;
|
|
||||||
bool bBinary = true;
|
|
||||||
for (uint32_t i = 0; i < bmp.colours; ++i)
|
|
||||||
{
|
|
||||||
HGByte red = (bmp.colour_table[i] >> 16) & 0xff;
|
|
||||||
HGByte green = (bmp.colour_table[i] >> 8) & 0xff;
|
|
||||||
HGByte blue = (bmp.colour_table[i]) & 0xff;
|
|
||||||
|
|
||||||
if (red != green || red != blue || green != blue)
|
|
||||||
{
|
|
||||||
bGray = false;
|
|
||||||
bBinary = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (red != 0 && red != 255)
|
|
||||||
{
|
|
||||||
bBinary = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bBinary)
|
|
||||||
imgType = HGBASE_IMGTYPE_BINARY;
|
|
||||||
else if (bGray)
|
|
||||||
imgType = HGBASE_IMGTYPE_GRAY;
|
|
||||||
}
|
|
||||||
else if (32 == bmp.bpp)
|
|
||||||
{
|
|
||||||
imgType = HGBASE_IMGTYPE_RGBA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgOrigin == 0)
|
|
||||||
{
|
|
||||||
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageInfo bmpImageInfo;
|
|
||||||
bmpImageInfo.width = bmp.width;
|
|
||||||
bmpImageInfo.height = bmp.height;
|
|
||||||
bmpImageInfo.type = HGBASE_IMGTYPE_RGBA;
|
|
||||||
bmpImageInfo.widthStep = bmp.width * 4;
|
|
||||||
bmpImageInfo.origin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGResult ret = HGBase_CreateImageWithData((HGByte*)bmp.bitmap, &bmpImageInfo, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
bmp_finalise(&bmp);
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t xDpi = (uint32_t)((double)bmp.x_pels_per_meter / 39.3700787 + 0.5);
|
|
||||||
uint32_t yDpi = (uint32_t)((double)bmp.y_pels_per_meter / 39.3700787 + 0.5);
|
|
||||||
HGBase_SetImageDpi(image2, xDpi, yDpi);
|
|
||||||
|
|
||||||
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
bmp_finalise(&bmp);
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bmp_finalise(&bmp);
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveBmpImage(HGImage image, const HGBmpSaveInfo* 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;
|
|
||||||
|
|
||||||
HGUInt bpp = 0;
|
|
||||||
if (HGBASE_IMGTYPE_BINARY == type)
|
|
||||||
bpp = 1;
|
|
||||||
else if (HGBASE_IMGTYPE_GRAY == type)
|
|
||||||
bpp = 8;
|
|
||||||
else if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_RGB == type)
|
|
||||||
bpp = 24;
|
|
||||||
else if (HGBASE_IMGTYPE_BGRA == type || HGBASE_IMGTYPE_RGBA == type)
|
|
||||||
bpp = 32;
|
|
||||||
assert(0 != bpp);
|
|
||||||
HGUInt stdWidthStep = ((width * bpp + 31) & ~31) >> 3;
|
|
||||||
|
|
||||||
if (widthStep != stdWidthStep)
|
|
||||||
{
|
|
||||||
HGImage imgTemp = NULL;
|
|
||||||
|
|
||||||
HGImageRoi imageRoi;
|
|
||||||
HGBase_GetImageROI(image, &imageRoi);
|
|
||||||
HGBase_ResetImageROI(image);
|
|
||||||
HGResult ret = HGBase_CloneImage(image, 0, 0, &imgTemp);
|
|
||||||
HGBase_SetImageROI(image, &imageRoi);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGImgFmt_SaveBmpImage(imgTemp, info, fileName);
|
|
||||||
HGBase_DestroyImage(imgTemp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* file = fopen(fileName, "wb");
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGImgFmt_SaveBmpImage: fopen fail, %s errno=%d", fileName, errno);
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* buffer = (uint8_t*)malloc(widthStep * height);
|
|
||||||
if (NULL == buffer)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t fh[14];
|
|
||||||
*(uint16_t*)fh = 0x4D42;
|
|
||||||
*(uint16_t*)(fh + 6) = 0;
|
|
||||||
*(uint16_t*)(fh + 8) = 0;
|
|
||||||
|
|
||||||
uint8_t ih[40];
|
|
||||||
*(uint32_t*)ih = 40;
|
|
||||||
*(int32_t*)(ih + 4) = (int32_t)width;
|
|
||||||
*(int32_t*)(ih + 8) = (int32_t)height;
|
|
||||||
*(uint16_t*)(ih + 12) = 1;
|
|
||||||
*(uint32_t*)(ih + 16) = 0;
|
|
||||||
*(uint32_t*)(ih + 20) = (widthStep * height);
|
|
||||||
*(int32_t*)(ih + 24) = 0;
|
|
||||||
*(int32_t*)(ih + 28) = 0;
|
|
||||||
*(uint32_t*)(ih + 32) = 0;
|
|
||||||
*(uint32_t*)(ih + 36) = 0;
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
*(int32_t*)(ih + 24) = (int32_t)info->xPelsPerMeter;
|
|
||||||
*(int32_t*)(ih + 28) = (int32_t)info->yPelsPerMeter;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image, &xDpi, &yDpi);
|
|
||||||
*(int32_t*)(ih + 24) = (uint32_t)((double)xDpi * 39.3700787 + 0.5);
|
|
||||||
*(int32_t*)(ih + 28) = (uint32_t)((double)yDpi * 39.3700787 + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image, &data);
|
|
||||||
|
|
||||||
if (HGBASE_IMGTYPE_BINARY == type)
|
|
||||||
{
|
|
||||||
*(uint32_t*)(fh + 2) = 54 + 4 * 2 + widthStep * height;
|
|
||||||
*(uint32_t*)(fh + 10) = 54 + 4 * 2;
|
|
||||||
*(uint16_t*)(ih + 14) = 1;
|
|
||||||
|
|
||||||
uint32_t colorTable[2];
|
|
||||||
colorTable[0] = 0x00000000;
|
|
||||||
colorTable[1] = 0x00FFFFFF;
|
|
||||||
|
|
||||||
fwrite(fh, 14, 1, file);
|
|
||||||
fwrite(ih, 40, 1, file);
|
|
||||||
fwrite(colorTable, 4, 2, file);
|
|
||||||
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
||||||
{
|
|
||||||
fwrite(data, 1, widthStep * height, file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t* dataEx = data + (height - 1) * widthStep;
|
|
||||||
while (dataEx >= data)
|
|
||||||
{
|
|
||||||
fwrite(dataEx, 1, widthStep, file);
|
|
||||||
dataEx -= widthStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_GRAY == type)
|
|
||||||
{
|
|
||||||
*(uint32_t*)(fh + 2) = 54 + 4 * 256 + widthStep * height;
|
|
||||||
*(uint32_t*)(fh + 10) = 54 + 4 * 256;
|
|
||||||
*(uint16_t*)(ih + 14) = 8;
|
|
||||||
|
|
||||||
uint32_t colorTable[256];
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (int32_t i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
uint32_t v = (i & 0x000000FF) | ((i << 8) & 0x0000FF00) | ((i << 16) & 0x00FF0000);
|
|
||||||
colorTable[i] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite(fh, 14, 1, file);
|
|
||||||
fwrite(ih, 40, 1, file);
|
|
||||||
fwrite(colorTable, 4, 256, file);
|
|
||||||
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
||||||
{
|
|
||||||
fwrite(data, 1, widthStep * height, file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t* dataEx = data + (height - 1) * widthStep;
|
|
||||||
while (dataEx >= data)
|
|
||||||
{
|
|
||||||
fwrite(dataEx, 1, widthStep, file);
|
|
||||||
dataEx -= widthStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_RGB == type)
|
|
||||||
{
|
|
||||||
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
||||||
*(uint32_t*)(fh + 10) = 54;
|
|
||||||
*(uint16_t*)(ih + 14) = 24;
|
|
||||||
|
|
||||||
fwrite(fh, 14, 1, file);
|
|
||||||
fwrite(ih, 40, 1, file);
|
|
||||||
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (int32_t i = 0; i < (int32_t)height; ++i)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = data + (uintptr_t)i * (uintptr_t)widthStep;
|
|
||||||
uint8_t* pExEnd = pEx + width * 3;
|
|
||||||
uint8_t* pDestEx = buffer + (uintptr_t)i * (uintptr_t)widthStep;
|
|
||||||
|
|
||||||
while (pEx < pExEnd)
|
|
||||||
{
|
|
||||||
pDestEx[0] = pEx[2];
|
|
||||||
pDestEx[1] = pEx[1];
|
|
||||||
pDestEx[2] = pEx[0];
|
|
||||||
|
|
||||||
pEx += 3;
|
|
||||||
pDestEx += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
||||||
{
|
|
||||||
fwrite(buffer, 1, widthStep * height, file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t* bufferEx = buffer + (height - 1) * widthStep;
|
|
||||||
while (bufferEx >= buffer)
|
|
||||||
{
|
|
||||||
fwrite(bufferEx, 1, widthStep, file);
|
|
||||||
bufferEx -= widthStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_BGR == type)
|
|
||||||
{
|
|
||||||
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
||||||
*(uint32_t*)(fh + 10) = 54;
|
|
||||||
*(uint16_t*)(ih + 14) = 24;
|
|
||||||
|
|
||||||
fwrite(fh, 14, 1, file);
|
|
||||||
fwrite(ih, 40, 1, file);
|
|
||||||
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
||||||
{
|
|
||||||
fwrite(data, 1, widthStep * height, file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t* dataEx = data + (height - 1) * widthStep;
|
|
||||||
while (dataEx >= data)
|
|
||||||
{
|
|
||||||
fwrite(dataEx, 1, widthStep, file);
|
|
||||||
dataEx -= widthStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_BGRA == type)
|
|
||||||
{
|
|
||||||
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
||||||
*(uint32_t*)(fh + 10) = 54;
|
|
||||||
*(uint16_t*)(ih + 14) = 32;
|
|
||||||
|
|
||||||
fwrite(fh, 14, 1, file);
|
|
||||||
fwrite(ih, 40, 1, file);
|
|
||||||
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
||||||
{
|
|
||||||
fwrite(data, 1, widthStep * height, file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t* dataEx = data + (height - 1) * widthStep;
|
|
||||||
while (dataEx >= data)
|
|
||||||
{
|
|
||||||
fwrite(dataEx, 1, widthStep, file);
|
|
||||||
dataEx -= widthStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(HGBASE_IMGTYPE_RGBA == type);
|
|
||||||
|
|
||||||
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
||||||
*(uint32_t*)(fh + 10) = 54;
|
|
||||||
*(uint16_t*)(ih + 14) = 32;
|
|
||||||
|
|
||||||
fwrite(fh, 14, 1, file);
|
|
||||||
fwrite(ih, 40, 1, file);
|
|
||||||
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (int32_t i = 0; i < (int32_t)height; ++i)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = data + (uintptr_t)i * (uintptr_t)widthStep;
|
|
||||||
uint8_t* pExEnd = pEx + width * 4;
|
|
||||||
uint8_t* pDestEx = buffer + (uintptr_t)i * (uintptr_t)widthStep;
|
|
||||||
|
|
||||||
while (pEx < pExEnd)
|
|
||||||
{
|
|
||||||
pDestEx[0] = pEx[2];
|
|
||||||
pDestEx[1] = pEx[1];
|
|
||||||
pDestEx[2] = pEx[0];
|
|
||||||
pDestEx[3] = pEx[3];
|
|
||||||
|
|
||||||
pEx += 4;
|
|
||||||
pDestEx += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
||||||
{
|
|
||||||
fwrite(buffer, 1, widthStep * height, file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t* bufferEx = buffer + (height - 1) * widthStep;
|
|
||||||
while (bufferEx >= buffer)
|
|
||||||
{
|
|
||||||
fwrite(bufferEx, 1, widthStep, file);
|
|
||||||
bufferEx -= widthStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
#ifndef __HGBMP_H__
|
|
||||||
#define __HGBMP_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
|
|
||||||
/* 压缩方式 */
|
|
||||||
#define HGIMGFMT_BMPENCODING_RGB 0L
|
|
||||||
#define HGIMGFMT_BMPENCODING_RLE8 1L
|
|
||||||
#define HGIMGFMT_BMPENCODING_RLE4 2L
|
|
||||||
#define HGIMGFMT_BMPENCODING_BITFIELDS 3L
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 宽 */
|
|
||||||
HGUInt height; /* 高 */
|
|
||||||
HGUShort bitCount; /* 每像素比特数 */
|
|
||||||
HGUInt compression; /* 压缩方式, 见HGIMGFMT_BMPENCODING_ */
|
|
||||||
HGUInt xPelsPerMeter; /* 每米的像素数x */
|
|
||||||
HGUInt yPelsPerMeter; /* 每米的像素数y */
|
|
||||||
}HGBmpLoadInfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt xPelsPerMeter; /* 每米的像素数x */
|
|
||||||
HGUInt yPelsPerMeter; /* 每米的像素数y */
|
|
||||||
}HGBmpSaveInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
/* 检查文件是否是BMP图像
|
|
||||||
* 参数:
|
|
||||||
* 1) fileName: in, 文件名, windows系统上是GBK编码, linux系统上是UTF8编码
|
|
||||||
* 2) isBmp: out, 是否是BMP图像
|
|
||||||
* 说明:
|
|
||||||
* 1) 该函数会打开文件判断文件头,而不是判断文件名后缀
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckBmpFile(const HGChar* fileName, HGBool* isBmp);
|
|
||||||
|
|
||||||
/* 加载BMP图像
|
|
||||||
* 参数:
|
|
||||||
* 1) fileName: in, 文件名, windows系统上是GBK编码, linux系统上是UTF8编码
|
|
||||||
* 2) info: out, BMP图像加载信息, 如果不需要该信息可传NULL
|
|
||||||
* 3) imgType: in, 要生成的图像类型, 参见HGBASE_IMGTYPE_*, 传0表示自动获取
|
|
||||||
* 4) imgOrigin: in, 要生成的图像数据排列方式, 参见HGBASE_IMGORIGIN_*, 传0表示自动获取
|
|
||||||
* 5) image: out, 要生成的图像句柄
|
|
||||||
* 说明:
|
|
||||||
* 1) 生成的图像不使用时需要调用HGBase_DestroyImage销毁
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadBmpImage(const HGChar* fileName, HGBmpLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
/* 保存BMP图像
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 要保存的图像句柄
|
|
||||||
* 2) info: in, BMP图像保存信息, 如果没有则传NULL
|
|
||||||
* 3) fileName: in, 文件名, windows系统上是GBK编码, linux系统上是UTF8编码
|
|
||||||
* 说明:
|
|
||||||
* 1) 忽略fileName的文件扩展名
|
|
||||||
* 2) 如果info不为NULL, 保存的DPI使用info指定的; 否则使用image自带的
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveBmpImage(HGImage image, const HGBmpSaveInfo* info, const HGChar* fileName);
|
|
||||||
|
|
||||||
#endif /* __HGBMP_H__ */
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,55 +0,0 @@
|
||||||
#ifndef __HGGIF_H__
|
|
||||||
#define __HGGIF_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGGifReader);
|
|
||||||
HG_DECLARE_HANDLE(HGGifWriter);
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 图像宽 */
|
|
||||||
HGUInt height; /* 图像高 */
|
|
||||||
HGUInt colorResolution; /* 位深 */
|
|
||||||
HGUInt imageCount; /* 图像数量 */
|
|
||||||
}HGGifLoadInfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 图像宽 */
|
|
||||||
HGUInt height; /* 图像高 */
|
|
||||||
}HGGifSaveInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckGifFile(const HGChar* fileName, HGBool* isGif);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenGifReader(const HGChar* fileName, HGGifLoadInfo* info, HGGifReader* reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseGifReader(HGGifReader reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_RetrieveImageFromGifReader(HGGifReader reader, HGUInt *index, HGUInt *interval,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadImageFromGifReader(HGGifReader reader, HGUInt index, HGUInt* interval,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadGifImage(const HGChar* fileName, HGGifLoadInfo* info, HGUInt* interval,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenGifWriter(const HGChar* fileName, const HGGifSaveInfo* info, HGGifWriter* writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseGifWriter(HGGifWriter writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveImageToGifWriter(HGGifWriter writer, HGUInt interval, HGColor bkColor, HGImage image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveGifImage(HGImage image, const HGGifSaveInfo* info,
|
|
||||||
HGUInt interval, HGColor bkColor, const HGChar* fileName);
|
|
||||||
|
|
||||||
#endif /* __HGGIF_H__ */
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,77 +0,0 @@
|
||||||
#ifndef __HGIMGFMT_H__
|
|
||||||
#define __HGIMGFMT_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
#include "HGTiff.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGImgFmtReader);
|
|
||||||
HG_DECLARE_HANDLE(HGImgFmtWriter);
|
|
||||||
|
|
||||||
/* JPEG */
|
|
||||||
#define HGIMGFMT_TYPE_JPEG 1L
|
|
||||||
/* BMP */
|
|
||||||
#define HGIMGFMT_TYPE_BMP 2L
|
|
||||||
/* PNG */
|
|
||||||
#define HGIMGFMT_TYPE_PNG 3L
|
|
||||||
/* TIFF */
|
|
||||||
#define HGIMGFMT_TYPE_TIFF 4L
|
|
||||||
/* PDF */
|
|
||||||
#define HGIMGFMT_TYPE_PDF 5L
|
|
||||||
/* OFD */
|
|
||||||
#define HGIMGFMT_TYPE_OFD 6L
|
|
||||||
/* GIF */
|
|
||||||
#define HGIMGFMT_TYPE_GIF 7L
|
|
||||||
/* PNM */
|
|
||||||
#define HGIMGFMT_TYPE_PNM 8L
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 图像宽 */
|
|
||||||
HGUInt height; /* 图像高 */
|
|
||||||
HGUInt bpp; /* 每像素比特数 */
|
|
||||||
HGUInt xDpi; /* x-DPI */
|
|
||||||
HGUInt yDpi; /* y-DPI */
|
|
||||||
}HGImgFmtLoadInfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt jpegQuality; /* jpeg质量 */
|
|
||||||
HGUInt tiffCompression; /* tiff压缩方式, 见HGIMGFMT_TIFFCOMP_* */
|
|
||||||
HGUInt tiffJpegQuality; /* tiff-jpeg质量 */
|
|
||||||
}HGImgFmtSaveInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetImgFmtType(const HGChar* fileName, HGUInt* fmtType);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetImgFmtTypeFromFileName(const HGChar* fileName, HGUInt* fmtType);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_IsMultiImgFmtType(HGUInt fmtType, HGBool *isMulti);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadImage(const HGChar *fileName, HGUInt fmtType, HGImgFmtLoadInfo *info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage *image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveImage(HGImage image, HGUInt fmtType, const HGImgFmtSaveInfo *info, const HGChar *fileName);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenImageReader(const HGChar *fileName, HGUInt fmtType, HGImgFmtReader *reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseImageReader(HGImgFmtReader reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetImagePageCount(HGImgFmtReader reader, HGUInt *count);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadImageFromReader(HGImgFmtReader reader, HGUInt index, HGImgFmtLoadInfo *info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage *image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenImageWriter(const HGChar *fileName, HGUInt fmtType, HGImgFmtWriter *writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseImageWriter(HGImgFmtWriter writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveImageToWriter(HGImgFmtWriter writer, HGImage image, const HGImgFmtSaveInfo *info);
|
|
||||||
|
|
||||||
#endif /* __HGIMGFMT_H__ */
|
|
|
@ -1,7 +0,0 @@
|
||||||
#ifndef __HGIMGFMTERR_H__
|
|
||||||
#define __HGIMGFMTERR_H__
|
|
||||||
|
|
||||||
/* 一般错误 */
|
|
||||||
#define HGIMGFMT_ERR_FAIL 0x00002001L
|
|
||||||
|
|
||||||
#endif /* __HGIMGFMTERR_H__ */
|
|
|
@ -1,538 +0,0 @@
|
||||||
#include "HGJpeg.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "jpeglib.h"
|
|
||||||
#include "jmemsys.h"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct my_error_mgr
|
|
||||||
{
|
|
||||||
struct jpeg_error_mgr pub;
|
|
||||||
jmp_buf setjmp_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
METHODDEF(void) my_error_exit(j_common_ptr cinfo)
|
|
||||||
{
|
|
||||||
my_error_mgr* myerr = (my_error_mgr*)cinfo->err;
|
|
||||||
(*cinfo->err->output_message)(cinfo);
|
|
||||||
longjmp(myerr->setjmp_buffer, (int)HGIMGFMT_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);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*isJpeg = HGTRUE;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(fileName, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(fileName, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == imgOrigin)
|
|
||||||
{
|
|
||||||
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
cinfo.out_color_space = JCS_RGB;
|
|
||||||
jpeg_start_decompress(&cinfo);
|
|
||||||
|
|
||||||
HGResult ret = HGBase_CreateImage(cinfo.output_width, cinfo.output_height,
|
|
||||||
HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (1 == cinfo.density_unit)
|
|
||||||
{
|
|
||||||
HGBase_SetImageDpi(image2, cinfo.X_density, cinfo.Y_density);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image2, &imgInfo);
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image2, &data);
|
|
||||||
|
|
||||||
while (cinfo.output_scanline < cinfo.output_height)
|
|
||||||
{
|
|
||||||
JSAMPROW pEx = data + (HGSize)cinfo.output_scanline * (HGSize)imgInfo.widthStep;
|
|
||||||
jpeg_read_scanlines(&cinfo, &pEx, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_finish_decompress(&cinfo);
|
|
||||||
|
|
||||||
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
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
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == imgOrigin)
|
|
||||||
{
|
|
||||||
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
cinfo.out_color_space = JCS_RGB;
|
|
||||||
jpeg_start_decompress(&cinfo);
|
|
||||||
|
|
||||||
HGResult ret = HGBase_CreateImage(cinfo.output_width, cinfo.output_height,
|
|
||||||
HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (1 == cinfo.density_unit)
|
|
||||||
{
|
|
||||||
HGBase_SetImageDpi(image2, cinfo.X_density, cinfo.Y_density);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image2, &imgInfo);
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image2, &data);
|
|
||||||
|
|
||||||
while (cinfo.output_scanline < cinfo.output_height)
|
|
||||||
{
|
|
||||||
JSAMPROW pEx = data + (HGSize)cinfo.output_scanline * (HGSize)imgInfo.widthStep;
|
|
||||||
jpeg_read_scanlines(&cinfo, &pEx, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_finish_decompress(&cinfo);
|
|
||||||
|
|
||||||
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
jpeg_destroy_decompress(&cinfo);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveJpegImage(HGImage image, const HGJpegSaveInfo* info, const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL == image || NULL == fileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
// 判断info参数的合法性
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* file = fopen(fileName, "wb");
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGImgFmt_SaveJpegImage: fopen fail, %s errno=%d", fileName, errno);
|
|
||||||
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;
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGImageRoi roi;
|
|
||||||
HGBase_GetImageROI(image, &roi);
|
|
||||||
|
|
||||||
int jmpResult = setjmp(jerr.setjmp_buffer);
|
|
||||||
if (0 != jmpResult)
|
|
||||||
{
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
jpeg_destroy_compress(&cinfo);
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return (HGResult)jmpResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_create_compress(&cinfo);
|
|
||||||
jpeg_stdio_dest(&cinfo, file);
|
|
||||||
|
|
||||||
HGBase_ResetImageROI(image);
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
if (HGBASE_IMGTYPE_GRAY == imgInfo.type || HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_GetImageInfo(image2, &imgInfo);
|
|
||||||
uint32_t width = imgInfo.width;
|
|
||||||
uint32_t height = imgInfo.height;
|
|
||||||
uint32_t type = imgInfo.type;
|
|
||||||
uint32_t widthStep = imgInfo.widthStep;
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image2, &data);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
int quality;
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
quality = info->quality;
|
|
||||||
cinfo.density_unit = info->densityUnit;
|
|
||||||
cinfo.X_density = info->xDensity;
|
|
||||||
cinfo.Y_density = info->yDensity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image2, &xDpi, &yDpi);
|
|
||||||
quality = 80;
|
|
||||||
cinfo.density_unit = 1;
|
|
||||||
cinfo.X_density = xDpi;
|
|
||||||
cinfo.Y_density = yDpi;
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_set_quality(&cinfo, (int)quality, TRUE);
|
|
||||||
jpeg_start_compress(&cinfo, TRUE);
|
|
||||||
|
|
||||||
while (cinfo.next_scanline < cinfo.image_height)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = data + (HGSize)cinfo.next_scanline * (HGSize)imgInfo.widthStep;
|
|
||||||
jpeg_write_scanlines(&cinfo, &pEx, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_finish_compress(&cinfo);
|
|
||||||
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
jpeg_destroy_compress(&cinfo);
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveJpegImageToBuffer(HGImage image, const HGJpegSaveInfo* info, HGBuffer* buffer)
|
|
||||||
{
|
|
||||||
if (NULL == image || NULL == buffer)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGImageRoi roi;
|
|
||||||
HGBase_GetImageROI(image, &roi);
|
|
||||||
|
|
||||||
int jmpResult = setjmp(jerr.setjmp_buffer);
|
|
||||||
if (0 != jmpResult)
|
|
||||||
{
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
jpeg_destroy_compress(&cinfo);
|
|
||||||
// 只有libjpeg为静态库的时候,才能用free
|
|
||||||
// 否则应该使用jpeg_free_large(NULL, outbuffer, 0);
|
|
||||||
jpeg_free_large(NULL, outbuffer, 0);
|
|
||||||
return (HGResult)jmpResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_create_compress(&cinfo);
|
|
||||||
jpeg_mem_dest(&cinfo, &outbuffer, &outSize);
|
|
||||||
|
|
||||||
HGBase_ResetImageROI(image);
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
if (HGBASE_IMGTYPE_GRAY == imgInfo.type || HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
longjmp(jerr.setjmp_buffer, (int)ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_GetImageInfo(image2, &imgInfo);
|
|
||||||
uint32_t width = imgInfo.width;
|
|
||||||
uint32_t height = imgInfo.height;
|
|
||||||
uint32_t type = imgInfo.type;
|
|
||||||
uint32_t widthStep = imgInfo.widthStep;
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image2, &data);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
int quality;
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
quality = info->quality;
|
|
||||||
cinfo.density_unit = info->densityUnit;
|
|
||||||
cinfo.X_density = info->xDensity;
|
|
||||||
cinfo.Y_density = info->yDensity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image2, &xDpi, &yDpi);
|
|
||||||
quality = 80;
|
|
||||||
cinfo.density_unit = 1;
|
|
||||||
cinfo.X_density = xDpi;
|
|
||||||
cinfo.Y_density = yDpi;
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_set_quality(&cinfo, (int)quality, TRUE);
|
|
||||||
jpeg_start_compress(&cinfo, TRUE);
|
|
||||||
|
|
||||||
while (cinfo.next_scanline < cinfo.image_height)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = data + (HGSize)cinfo.next_scanline * (HGSize)imgInfo.widthStep;
|
|
||||||
jpeg_write_scanlines(&cinfo, &pEx, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
jpeg_finish_compress(&cinfo);
|
|
||||||
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
#ifndef __HGJPEG_H__
|
|
||||||
#define __HGJPEG_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
#include "../base/HGBuffer.h"
|
|
||||||
|
|
||||||
/* 颜色空间 */
|
|
||||||
#define HGIMGFMT_JPEGCLRSPACE_UNKNOWN 0L
|
|
||||||
#define HGIMGFMT_JPEGCLRSPACE_GRAYSCALE 1L
|
|
||||||
#define HGIMGFMT_JPEGCLRSPACE_RGB 2L
|
|
||||||
|
|
||||||
/* 分辨率单位 */
|
|
||||||
#define HGIMGFMT_JPEGDENUNIT_INCH 1L /* 英寸 */
|
|
||||||
#define HGIMGFMT_JPEGDENUNIT_CENTIMETER 2L /* 厘米 */
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 图像宽 */
|
|
||||||
HGUInt height; /* 图像高 */
|
|
||||||
HGUInt numComponents; /* 颜色数量 */
|
|
||||||
HGUInt colorSpace; /* 颜色空间, 见HGIMGFMT_JPEGCLRSPACE_* */
|
|
||||||
HGByte densityUnit; /* 分辨率单位, 见HGIMGFMT_JPEGDENUNIT_* */
|
|
||||||
HGUShort xDensity; /* 分辨率x值 */
|
|
||||||
HGUShort yDensity; /* 分辨率y值 */
|
|
||||||
}HGJpegLoadInfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt quality; /* 压缩质量, 0-100 */
|
|
||||||
HGByte densityUnit; /* 分辨率单位, 见HGIMGFMT_JPEGDENUNIT_* */
|
|
||||||
HGUShort xDensity; /* 分辨率x值 */
|
|
||||||
HGUShort yDensity; /* 分辨率y值 */
|
|
||||||
}HGJpegSaveInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckJpegFile(const HGChar* fileName, HGBool *isJpeg);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadJpegImage(const HGChar* fileName, HGJpegLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadJpegImageFromBuffer(HGBuffer buffer, HGJpegLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveJpegImage(HGImage image, const HGJpegSaveInfo* info, const HGChar* fileName);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveJpegImageToBuffer(HGImage image, const HGJpegSaveInfo* info, HGBuffer *buffer);
|
|
||||||
|
|
||||||
#endif /* __HGJPEG_H__ */
|
|
|
@ -1,173 +0,0 @@
|
||||||
#include "HGOfd.h"
|
|
||||||
#include "HGOfdImpl.hpp"
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CheckOfdFile(const HGChar* fileName, HGBool* isOfd)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == isOfd)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdReader reader = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenOfdReader(fileName, &reader);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*isOfd = HGTRUE;
|
|
||||||
HGImgFmt_CloseOfdReader(reader);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_OpenOfdReader(const HGChar* fileName, HGOfdReader* reader)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdReaderImpl* ofdReaderImpl = new HGOfdReaderImpl;
|
|
||||||
HGResult ret = ofdReaderImpl->Open(fileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete ofdReaderImpl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*reader = (HGOfdReader)ofdReaderImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CloseOfdReader(HGOfdReader reader)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdReaderImpl* ofdReaderImpl = (HGOfdReaderImpl *)reader;
|
|
||||||
HGResult ret = ofdReaderImpl->Close();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete ofdReaderImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_GetOfdPageCount(HGOfdReader reader, HGUInt* count)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdReaderImpl* ofdReaderImpl = (HGOfdReaderImpl*)reader;
|
|
||||||
return ofdReaderImpl->GetPageCount(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_GetOfdPageInfo(HGOfdReader reader, HGUInt page, HGOfdPageInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdReaderImpl* ofdReaderImpl = (HGOfdReaderImpl*)reader;
|
|
||||||
return ofdReaderImpl->GetPageInfo(page, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadImageFromOfdReader(HGOfdReader reader, HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdReaderImpl* ofdReaderImpl = (HGOfdReaderImpl*)reader;
|
|
||||||
return ofdReaderImpl->LoadImage(page, xScale, yScale, imgType, imgOrigin, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadOfdImage(const HGChar* fileName, HGOfdPageInfo* info, HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
HGOfdReader reader = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenOfdReader(fileName, &reader);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HGBASE_ERR_OK == ret && NULL != info)
|
|
||||||
ret = HGImgFmt_GetOfdPageInfo(reader, 0, info);
|
|
||||||
|
|
||||||
if (HGBASE_ERR_OK == ret && NULL != image)
|
|
||||||
ret = HGImgFmt_LoadImageFromOfdReader(reader, 0, 1.0f, 1.0f, imgType, imgOrigin, image);
|
|
||||||
|
|
||||||
HGImgFmt_CloseOfdReader(reader);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_OpenOfdImageWriter(const HGChar* fileName, HGOfdImageWriter* writer)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdImageWriterImpl* ofdImageWriterImpl = new HGOfdImageWriterImpl;
|
|
||||||
HGResult ret = ofdImageWriterImpl->Open(fileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete ofdImageWriterImpl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*writer = (HGOfdImageWriter)ofdImageWriterImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CloseOfdImageWriter(HGOfdImageWriter writer)
|
|
||||||
{
|
|
||||||
if (NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdImageWriterImpl* ofdImageWriterImpl = (HGOfdImageWriterImpl*)writer;
|
|
||||||
HGResult ret = ofdImageWriterImpl->Close();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete ofdImageWriterImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveJpegImageToOfdImageWriter(HGOfdImageWriter writer, HGImage image, const HGJpegSaveInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdImageWriterImpl* ofdImageWriterImpl = (HGOfdImageWriterImpl*)writer;
|
|
||||||
return ofdImageWriterImpl->SaveJpegImage(image, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveOfdJpegImage(HGImage image, const HGJpegSaveInfo* info, const HGChar* fileName)
|
|
||||||
{
|
|
||||||
HGOfdImageWriter writer = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenOfdImageWriter(fileName, &writer);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGImgFmt_SaveJpegImageToOfdImageWriter(writer, image, info);
|
|
||||||
HGImgFmt_CloseOfdImageWriter(writer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
#ifndef __HGOFD_H__
|
|
||||||
#define __HGOFD_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
#include "HGJpeg.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGOfdReader);
|
|
||||||
HG_DECLARE_HANDLE(HGOfdImageWriter);
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width;
|
|
||||||
HGUInt height;
|
|
||||||
HGUInt bpp;
|
|
||||||
}HGOfdPageInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckOfdFile(const HGChar* fileName, HGBool* isOfd);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenOfdReader(const HGChar* fileName, HGOfdReader* reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseOfdReader(HGOfdReader reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetOfdPageCount(HGOfdReader reader, HGUInt* count);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetOfdPageInfo(HGOfdReader reader, HGUInt page, HGOfdPageInfo* info);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadImageFromOfdReader(HGOfdReader reader, HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadOfdImage(const HGChar* fileName, HGOfdPageInfo* info, HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenOfdImageWriter(const HGChar* fileName, HGOfdImageWriter* writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseOfdImageWriter(HGOfdImageWriter writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveJpegImageToOfdImageWriter(HGOfdImageWriter writer, HGImage image, const HGJpegSaveInfo* info);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveOfdJpegImage(HGImage image, const HGJpegSaveInfo* info, const HGChar* fileName);
|
|
||||||
|
|
||||||
#endif /* __HGOFD_H__ */
|
|
|
@ -1,914 +0,0 @@
|
||||||
#include "HGOfdImpl.hpp"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
#include "../base/HGUtility.h"
|
|
||||||
#include "HGString.h"
|
|
||||||
|
|
||||||
#define A4page_page_PhysicalBox_Width 210.000000
|
|
||||||
#define A4page_page_PhysicalBox_Height 297.000000
|
|
||||||
|
|
||||||
HGOfdReaderImpl::HGOfdReaderImpl()
|
|
||||||
{
|
|
||||||
m_zip = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdReaderImpl::~HGOfdReaderImpl()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdReaderImpl::Open(const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL != m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(fileName, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(fileName, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
int error = 0;
|
|
||||||
m_zip = zip_open(StdStringToUtf8(fileName).c_str(), 0, &error);
|
|
||||||
if (NULL == m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string content;
|
|
||||||
HGResult ret = ReadXml("Doc_0/Document.xml", content);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
zip_close(m_zip);
|
|
||||||
m_zip = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
if (tinyxml2::XML_SUCCESS == xmlDoc.Parse(content.c_str()))
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.RootElement();
|
|
||||||
if (NULL != root)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* pages = root->FirstChildElement("ofd:Pages");
|
|
||||||
if (NULL != pages)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* page = pages->FirstChildElement("ofd:Page");
|
|
||||||
if (NULL != page)
|
|
||||||
{
|
|
||||||
const char* attr = page->Attribute("BaseLoc");
|
|
||||||
if (NULL != attr)
|
|
||||||
m_contentNames.push_back(attr);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* p = page->NextSiblingElement("ofd:Page");
|
|
||||||
while (NULL != p)
|
|
||||||
{
|
|
||||||
const char* attr = p->Attribute("BaseLoc");
|
|
||||||
if (NULL != attr)
|
|
||||||
m_contentNames.push_back(attr);
|
|
||||||
|
|
||||||
p = p->NextSiblingElement("ofd:Page");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdReaderImpl::Close()
|
|
||||||
{
|
|
||||||
if (NULL == m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_contentNames.clear();
|
|
||||||
zip_close(m_zip);
|
|
||||||
m_zip = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdReaderImpl::GetPageCount(HGUInt* count)
|
|
||||||
{
|
|
||||||
if (NULL == m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == count)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*count = (HGUInt)m_contentNames.size();
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool GetRect(const char *text, double data[4])
|
|
||||||
{
|
|
||||||
bool ret = false;
|
|
||||||
if (NULL == text)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
char str[256];
|
|
||||||
strcpy(str, text);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
char* pStr = strtok(str, " ");
|
|
||||||
if (NULL != pStr)
|
|
||||||
{
|
|
||||||
data[i] = atof(pStr);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
while (i < 4)
|
|
||||||
{
|
|
||||||
pStr = strtok(NULL, " ");
|
|
||||||
if (NULL == pStr)
|
|
||||||
break;
|
|
||||||
data[i] = atof(pStr);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (4 == i);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdReaderImpl::GetPageInfo(HGUInt page, HGOfdPageInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page >= (HGUInt)m_contentNames.size() || NULL == info)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
char name[128];
|
|
||||||
sprintf(name, "Doc_0/%s", m_contentNames[page].c_str());
|
|
||||||
|
|
||||||
std::string content;
|
|
||||||
HGResult ret = ReadXml(name, content);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
|
|
||||||
std::string resId;
|
|
||||||
if (tinyxml2::XML_SUCCESS == xmlDoc.Parse(content.c_str()))
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.RootElement();
|
|
||||||
if (NULL != root)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* content = root->FirstChildElement("ofd:Content");
|
|
||||||
if (NULL != content)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* layer = content->FirstChildElement("ofd:Layer");
|
|
||||||
if (NULL != layer)
|
|
||||||
{
|
|
||||||
const char* attr = layer->Attribute("Type");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL == attr || 0 != _stricmp("Background", attr))
|
|
||||||
#else
|
|
||||||
if (NULL == attr || 0 != strcasecmp("Background", attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* p = layer->NextSiblingElement("ofd:Layer");
|
|
||||||
while (NULL != p)
|
|
||||||
{
|
|
||||||
const char* attr = p->Attribute("Type");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL != attr && 0 == _stricmp("Background", attr))
|
|
||||||
#else
|
|
||||||
if (NULL != attr && 0 == strcasecmp("Background", attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p->NextSiblingElement("ofd:Layer");
|
|
||||||
}
|
|
||||||
|
|
||||||
layer = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != layer)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* imgObject = layer->FirstChildElement("ofd:ImageObject");
|
|
||||||
if (NULL != imgObject)
|
|
||||||
{
|
|
||||||
resId = imgObject->Attribute("ResourceID");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resId.empty())
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ReadXml("Doc_0/DocumentRes.xml", content);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string imgName;
|
|
||||||
if (tinyxml2::XML_SUCCESS == xmlDoc.Parse(content.c_str()))
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.RootElement();
|
|
||||||
if (NULL != root)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* multiMedias = root->FirstChildElement("ofd:MultiMedias");
|
|
||||||
if (NULL != multiMedias)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* multiMedia = multiMedias->FirstChildElement("ofd:MultiMedia");
|
|
||||||
if (NULL != multiMedia)
|
|
||||||
{
|
|
||||||
const char* attr = multiMedia->Attribute("ID");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL == attr || 0 != _stricmp(resId.c_str(), attr))
|
|
||||||
#else
|
|
||||||
if (NULL == attr || 0 != strcasecmp(resId.c_str(), attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* p = multiMedia->NextSiblingElement("ofd:MultiMedia");
|
|
||||||
while (NULL != p)
|
|
||||||
{
|
|
||||||
const char* attr = p->Attribute("ID");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL != attr && 0 == _stricmp(resId.c_str(), attr))
|
|
||||||
#else
|
|
||||||
if (NULL != attr && 0 == strcasecmp(resId.c_str(), attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p->NextSiblingElement("ofd:MultiMedia");
|
|
||||||
}
|
|
||||||
|
|
||||||
multiMedia = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != multiMedia)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* mediaFile = multiMedia->FirstChildElement("ofd:MediaFile");
|
|
||||||
if (NULL != mediaFile)
|
|
||||||
{
|
|
||||||
imgName = mediaFile->GetText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgName.empty())
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char img_name[128];
|
|
||||||
sprintf(img_name, "Doc_0/Res/%s", imgName.c_str());
|
|
||||||
|
|
||||||
HGJpegLoadInfo jpegInfo;
|
|
||||||
ret = ReadJpeg(img_name, &jpegInfo, 0, 0, 0, 0, NULL);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
info->width = jpegInfo.width;
|
|
||||||
info->height = jpegInfo.height;
|
|
||||||
info->bpp = jpegInfo.numComponents * 8;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdReaderImpl::LoadImage(HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
if (NULL == m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page >= (HGUInt)m_contentNames.size() || NULL == image)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
char name[128];
|
|
||||||
sprintf(name, "Doc_0/%s", m_contentNames[page].c_str());
|
|
||||||
|
|
||||||
std::string content;
|
|
||||||
HGResult ret = ReadXml(name, content);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
|
|
||||||
std::string resId;
|
|
||||||
if (tinyxml2::XML_SUCCESS == xmlDoc.Parse(content.c_str()))
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.RootElement();
|
|
||||||
if (NULL != root)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* content = root->FirstChildElement("ofd:Content");
|
|
||||||
if (NULL != content)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* layer = content->FirstChildElement("ofd:Layer");
|
|
||||||
if (NULL != layer)
|
|
||||||
{
|
|
||||||
const char* attr = layer->Attribute("Type");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL == attr || 0 != _stricmp("Background", attr))
|
|
||||||
#else
|
|
||||||
if (NULL == attr || 0 != strcasecmp("Background", attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* p = layer->NextSiblingElement("ofd:Layer");
|
|
||||||
while (NULL != p)
|
|
||||||
{
|
|
||||||
const char* attr = p->Attribute("Type");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL != attr && 0 == _stricmp("Background", attr))
|
|
||||||
#else
|
|
||||||
if (NULL != attr && 0 == strcasecmp("Background", attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p->NextSiblingElement("ofd:Layer");
|
|
||||||
}
|
|
||||||
|
|
||||||
layer = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != layer)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* imgObject = layer->FirstChildElement("ofd:ImageObject");
|
|
||||||
if (NULL != imgObject)
|
|
||||||
{
|
|
||||||
resId = imgObject->Attribute("ResourceID");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resId.empty())
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ReadXml("Doc_0/DocumentRes.xml", content);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string imgName;
|
|
||||||
if (tinyxml2::XML_SUCCESS == xmlDoc.Parse(content.c_str()))
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.RootElement();
|
|
||||||
if (NULL != root)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* multiMedias = root->FirstChildElement("ofd:MultiMedias");
|
|
||||||
if (NULL != multiMedias)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* multiMedia = multiMedias->FirstChildElement("ofd:MultiMedia");
|
|
||||||
if (NULL != multiMedia)
|
|
||||||
{
|
|
||||||
const char* attr = multiMedia->Attribute("ID");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL == attr || 0 != _stricmp(resId.c_str(), attr))
|
|
||||||
#else
|
|
||||||
if (NULL == attr || 0 != strcasecmp(resId.c_str(), attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* p = multiMedia->NextSiblingElement("ofd:MultiMedia");
|
|
||||||
while (NULL != p)
|
|
||||||
{
|
|
||||||
const char* attr = p->Attribute("ID");
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (NULL != attr && 0 == _stricmp(resId.c_str(), attr))
|
|
||||||
#else
|
|
||||||
if (NULL != attr && 0 == strcasecmp(resId.c_str(), attr))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p->NextSiblingElement("ofd:MultiMedia");
|
|
||||||
}
|
|
||||||
|
|
||||||
multiMedia = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != multiMedia)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* mediaFile = multiMedia->FirstChildElement("ofd:MediaFile");
|
|
||||||
if (NULL != mediaFile)
|
|
||||||
{
|
|
||||||
imgName = mediaFile->GetText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgName.empty())
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char img_name[128];
|
|
||||||
sprintf(img_name, "Doc_0/Res/%s", imgName.c_str());
|
|
||||||
ret = ReadJpeg(img_name, NULL, xScale, yScale, imgType, imgOrigin, image);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdReaderImpl::ReadXml(const char* name, std::string& content)
|
|
||||||
{
|
|
||||||
struct zip_stat st;
|
|
||||||
zip_stat_init(&st);
|
|
||||||
zip_stat(m_zip, name, ZIP_FL_NOCASE, &st);
|
|
||||||
|
|
||||||
zip_int64_t size = st.size;
|
|
||||||
if (0 == size)
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_file* file = zip_fopen(m_zip, name, ZIP_FL_NOCASE);
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* s = (char*)malloc((size_t)size + 1);
|
|
||||||
if (NULL == s)
|
|
||||||
{
|
|
||||||
zip_fclose(file);
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_int64_t did_read = zip_fread(file, s, size);
|
|
||||||
if (did_read != size)
|
|
||||||
{
|
|
||||||
free(s);
|
|
||||||
zip_fclose(file);
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
s[size] = 0;
|
|
||||||
content = s;
|
|
||||||
|
|
||||||
free(s);
|
|
||||||
zip_fclose(file);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdReaderImpl::ReadJpeg(const char* name, HGJpegLoadInfo* info, HGFloat xScale, HGFloat yScale, HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
struct zip_stat st;
|
|
||||||
zip_stat_init(&st);
|
|
||||||
zip_stat(m_zip, name, ZIP_FL_NOCASE, &st);
|
|
||||||
|
|
||||||
zip_int64_t size = st.size;
|
|
||||||
if (0 == size)
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_file* file = zip_fopen(m_zip, name, ZIP_FL_NOCASE);
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char* content = (unsigned char*)malloc((size_t)size);
|
|
||||||
if (NULL == content)
|
|
||||||
{
|
|
||||||
zip_fclose(file);
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_int64_t did_read = zip_fread(file, content, size);
|
|
||||||
if (did_read != size)
|
|
||||||
{
|
|
||||||
free(content);
|
|
||||||
zip_fclose(file);
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBuffer buffer = NULL;
|
|
||||||
HGBase_CreateBufferWithData(content, (size_t)size, &buffer);
|
|
||||||
HGResult ret = HGImgFmt_LoadJpegImageFromBuffer(buffer, info, imgType, imgOrigin, image);
|
|
||||||
HGBase_DestroyBuffer(buffer);
|
|
||||||
|
|
||||||
free(content);
|
|
||||||
zip_fclose(file);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HGOfdImageWriterImpl::HGOfdImageWriterImpl()
|
|
||||||
{
|
|
||||||
m_zip = NULL;
|
|
||||||
m_curImgIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOfdImageWriterImpl::~HGOfdImageWriterImpl()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::Open(const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL != m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int error = 0;
|
|
||||||
m_zip = zip_open(StdStringToUtf8(fileName).c_str(), ZIP_CREATE | ZIP_TRUNCATE, &error);
|
|
||||||
if (NULL == m_zip)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOfdImageWriterImpl::Open: zip_open fail, %s", fileName);
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_add_dir(m_zip, "Doc_0");
|
|
||||||
zip_add_dir(m_zip, "Doc_0/Pages");
|
|
||||||
zip_add_dir(m_zip, "Doc_0/Res");
|
|
||||||
|
|
||||||
HGResult ret = AddOfdXml();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
zip_close(m_zip);
|
|
||||||
m_zip = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = AddPublicResXml();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
zip_close(m_zip);
|
|
||||||
m_zip = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::Close()
|
|
||||||
{
|
|
||||||
if (NULL == m_zip)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddDocXml();
|
|
||||||
AddDocResXml();
|
|
||||||
|
|
||||||
zip_close(m_zip);
|
|
||||||
m_zip = NULL;
|
|
||||||
|
|
||||||
// 清理临时文件
|
|
||||||
std::list<std::string>::const_iterator iter;
|
|
||||||
for (iter = m_tmpFiles.begin(); iter != m_tmpFiles.end(); ++iter)
|
|
||||||
{
|
|
||||||
HGBase_DeleteFile(iter->c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tmpFiles.clear();
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::SaveJpegImage(HGImage image, const HGJpegSaveInfo* info)
|
|
||||||
{
|
|
||||||
HGChar name[128];
|
|
||||||
sprintf(name, "Doc_0/Res/image_%u.jpg", m_curImgIndex);
|
|
||||||
HGResult ret = AddJpegImageFile(image, info, name);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image, &xDpi, &yDpi);
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
if (HGIMGFMT_JPEGDENUNIT_INCH == info->densityUnit)
|
|
||||||
{
|
|
||||||
xDpi = info->xDensity;
|
|
||||||
yDpi = info->yDensity;
|
|
||||||
}
|
|
||||||
else if (HGIMGFMT_JPEGDENUNIT_CENTIMETER == info->densityUnit)
|
|
||||||
{
|
|
||||||
xDpi = (uint32_t)((double)info->xDensity / 0.393700787 + 0.5);
|
|
||||||
yDpi = (uint32_t)((double)info->yDensity / 0.393700787 + 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
HGFloat physicalWidth = 25.4f * (HGFloat)imgInfo.width / (HGFloat)xDpi;
|
|
||||||
HGFloat physicalHeight = 25.4f * (HGFloat)imgInfo.height / (HGFloat)yDpi;
|
|
||||||
|
|
||||||
AddContentXmlFile(m_curImgIndex, physicalWidth, physicalHeight);
|
|
||||||
++m_curImgIndex;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::AddOfdXml()
|
|
||||||
{
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
|
|
||||||
HGChar uuid[128];
|
|
||||||
HGBase_GetUuid(uuid, 128);
|
|
||||||
|
|
||||||
time_t tm = time(NULL);
|
|
||||||
struct tm *local_tm = localtime(&tm);
|
|
||||||
char local_tm_str[256];
|
|
||||||
strftime(local_tm_str, 256, "%c", local_tm);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *root = xmlDoc.NewElement("ofd:OFD");
|
|
||||||
root->SetAttribute("xmlns:ofd", "http://www.ofdspec.org/2016");
|
|
||||||
root->SetAttribute("DocType", "OFD");
|
|
||||||
root->SetAttribute("Version", "1.0");
|
|
||||||
xmlDoc.InsertEndChild(root);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* docBody = xmlDoc.NewElement("ofd:DocBody");
|
|
||||||
root->InsertEndChild(docBody);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* docRoot = xmlDoc.NewElement("ofd:DocRoot");
|
|
||||||
docRoot->SetText("Doc_0/Document.xml");
|
|
||||||
docBody->InsertEndChild(docRoot);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* docInfo = xmlDoc.NewElement("ofd:DocInfo");
|
|
||||||
docBody->InsertEndChild(docInfo);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* docId = xmlDoc.NewElement("ofd:DocID");
|
|
||||||
docId->SetText(uuid);
|
|
||||||
docInfo->InsertEndChild(docId);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* creationDate = xmlDoc.NewElement("ofd:CreationDate");
|
|
||||||
creationDate->SetText(local_tm_str);
|
|
||||||
docInfo->InsertEndChild(creationDate);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* modDate = xmlDoc.NewElement("ofd:ModDate");
|
|
||||||
modDate->SetText(local_tm_str);
|
|
||||||
docInfo->InsertEndChild(modDate);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* creator = xmlDoc.NewElement("ofd:Creator");
|
|
||||||
creator->SetText("ofd");
|
|
||||||
docInfo->InsertEndChild(creator);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* createVersion = xmlDoc.NewElement("ofd:CreatorVersion");
|
|
||||||
createVersion->SetText("1.0.0");
|
|
||||||
docInfo->InsertEndChild(createVersion);
|
|
||||||
|
|
||||||
return AddXmlFile(xmlDoc, "OFD.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::AddDocXml()
|
|
||||||
{
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.NewElement("ofd:Document");
|
|
||||||
root->SetAttribute("xmlns:ofd", "http://www.ofdspec.org/2016");
|
|
||||||
xmlDoc.InsertEndChild(root);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* commonData = xmlDoc.NewElement("ofd:CommonData");
|
|
||||||
root->InsertEndChild(commonData);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* maxUnitID = xmlDoc.NewElement("ofd:MaxUnitID");
|
|
||||||
HGChar maxId[24];
|
|
||||||
sprintf(maxId, "%u", m_curImgIndex * 10 + 2);
|
|
||||||
maxUnitID->SetText(maxId);
|
|
||||||
commonData->InsertEndChild(maxUnitID);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* pageArea = xmlDoc.NewElement("ofd:PageArea");
|
|
||||||
commonData->InsertEndChild(pageArea);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* publicRes = xmlDoc.NewElement("ofd:PublicRes");
|
|
||||||
publicRes->SetText("PublicRes.xml");
|
|
||||||
commonData->InsertEndChild(publicRes);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* documentRes = xmlDoc.NewElement("ofd:DocumentRes");
|
|
||||||
documentRes->SetText("DocumentRes.xml");
|
|
||||||
commonData->InsertEndChild(documentRes);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* physicalBox = xmlDoc.NewElement("ofd:PhysicalBox");
|
|
||||||
char physicalBoxText[512];
|
|
||||||
sprintf(physicalBoxText, "0.000000 0.000000 %f %f", A4page_page_PhysicalBox_Width,
|
|
||||||
A4page_page_PhysicalBox_Height);
|
|
||||||
physicalBox->SetText(physicalBoxText);
|
|
||||||
pageArea->InsertEndChild(physicalBox);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* pages = xmlDoc.NewElement("ofd:Pages");
|
|
||||||
root->InsertEndChild(pages);
|
|
||||||
|
|
||||||
for (HGUInt i = 0; i < m_curImgIndex; ++i)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* page = xmlDoc.NewElement("ofd:Page");
|
|
||||||
|
|
||||||
HGChar id[24];
|
|
||||||
sprintf(id, "%u", i * 10 + 1);
|
|
||||||
page->SetAttribute("ID", id);
|
|
||||||
|
|
||||||
HGChar loc[128];
|
|
||||||
sprintf(loc, "Pages/Page_%u/Content.xml", i);
|
|
||||||
page->SetAttribute("BaseLoc", loc);
|
|
||||||
|
|
||||||
pages->InsertEndChild(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddXmlFile(xmlDoc, "Doc_0/Document.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::AddDocResXml()
|
|
||||||
{
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.NewElement("ofd:Res");
|
|
||||||
root->SetAttribute("xmlns:ofd", "http://www.ofdspec.org/2016");
|
|
||||||
root->SetAttribute("BaseLoc", "Res");
|
|
||||||
xmlDoc.InsertEndChild(root);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* multiMedias = xmlDoc.NewElement("ofd:MultiMedias");
|
|
||||||
root->InsertEndChild(multiMedias);
|
|
||||||
|
|
||||||
for (HGUInt i = 0; i < m_curImgIndex; ++i)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement* multiMedia = xmlDoc.NewElement("ofd:MultiMedia");
|
|
||||||
multiMedia->SetAttribute("Type", "Image");
|
|
||||||
HGChar id[24];
|
|
||||||
sprintf(id, "%u", i * 10 + 2);
|
|
||||||
multiMedia->SetAttribute("ID", id);
|
|
||||||
multiMedias->InsertEndChild(multiMedia);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* mediaFile = xmlDoc.NewElement("ofd:MediaFile");
|
|
||||||
HGChar loc[128];
|
|
||||||
sprintf(loc, "image_%u.jpg", i);
|
|
||||||
mediaFile->SetText(loc);
|
|
||||||
multiMedia->InsertEndChild(mediaFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddXmlFile(xmlDoc, "Doc_0/DocumentRes.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::AddPublicResXml()
|
|
||||||
{
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.NewElement("ofd:Res");
|
|
||||||
root->SetAttribute("xmlns:ofd", "http://www.ofdspec.org/2016");
|
|
||||||
root->SetAttribute("BaseLoc", "Res");
|
|
||||||
xmlDoc.InsertEndChild(root);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* fonts = xmlDoc.NewElement("ofd:Fonts");
|
|
||||||
root->InsertEndChild(fonts);
|
|
||||||
|
|
||||||
return AddXmlFile(xmlDoc, "Doc_0/PublicRes.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::AddXmlFile(tinyxml2::XMLDocument& xmlDoc, const HGChar* name)
|
|
||||||
{
|
|
||||||
HGChar tmpName[256];
|
|
||||||
HGBase_GetTmpFileName(NULL, tmpName, 256);
|
|
||||||
if (tinyxml2::XML_SUCCESS != xmlDoc.SaveFile(tmpName))
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_source_t* s = zip_source_file(m_zip, tmpName, 0, 0);
|
|
||||||
if (NULL == s)
|
|
||||||
{
|
|
||||||
HGBase_DeleteFile(tmpName);
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_int64_t ret = zip_file_add(m_zip, name, s, ZIP_FL_ENC_UTF_8 | ZIP_FL_OVERWRITE);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
zip_source_free(s);
|
|
||||||
HGBase_DeleteFile(tmpName);
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tmpFiles.push_back(tmpName);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::AddJpegImageFile(HGImage image, const HGJpegSaveInfo* info, const HGChar* name)
|
|
||||||
{
|
|
||||||
HGChar tmpName[256];
|
|
||||||
HGBase_GetTmpFileName(NULL, tmpName, 256);
|
|
||||||
HGResult ret = HGImgFmt_SaveJpegImage(image, info, tmpName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_source_t* s = zip_source_file(m_zip, tmpName, 0, 0);
|
|
||||||
if (NULL == s)
|
|
||||||
{
|
|
||||||
HGBase_DeleteFile(tmpName);
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_int64_t rc = zip_file_add(m_zip, name, s, ZIP_FL_OVERWRITE);
|
|
||||||
if (rc < 0)
|
|
||||||
{
|
|
||||||
zip_source_free(s);
|
|
||||||
HGBase_DeleteFile(tmpName);
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tmpFiles.push_back(tmpName);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOfdImageWriterImpl::AddContentXmlFile(HGUInt index, HGFloat physicalWidth, HGFloat physicalHeight)
|
|
||||||
{
|
|
||||||
HGChar dir[128];
|
|
||||||
sprintf(dir, "Doc_0/Pages/Page_%u", index);
|
|
||||||
zip_add_dir(m_zip, dir);
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument xmlDoc;
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* root = xmlDoc.NewElement("ofd:Page");
|
|
||||||
root->SetAttribute("xmlns:ofd", "http://www.ofdspec.org/2016");
|
|
||||||
xmlDoc.InsertEndChild(root);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* area = xmlDoc.NewElement("ofd:Area");
|
|
||||||
root->InsertEndChild(area);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* physicalBox = xmlDoc.NewElement("ofd:PhysicalBox");
|
|
||||||
char physicalBoxText[512];
|
|
||||||
sprintf(physicalBoxText, "0.000000 0.000000 %f %f", physicalWidth, physicalHeight);
|
|
||||||
physicalBox->SetText(physicalBoxText);
|
|
||||||
area->InsertEndChild(physicalBox);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* content = xmlDoc.NewElement("ofd:Content");
|
|
||||||
root->InsertEndChild(content);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* layer = xmlDoc.NewElement("ofd:Layer");
|
|
||||||
HGChar layerId[24];
|
|
||||||
sprintf(layerId, "%u", index * 10 + 3);
|
|
||||||
layer->SetAttribute("ID", layerId);
|
|
||||||
layer->SetAttribute("Type", "Background");
|
|
||||||
content->InsertEndChild(layer);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* imgObject = xmlDoc.NewElement("ofd:ImageObject");
|
|
||||||
HGChar imgObjectId[24];
|
|
||||||
sprintf(imgObjectId, "%u", index * 10 + 4);
|
|
||||||
imgObject->SetAttribute("ID", imgObjectId);
|
|
||||||
char boundaryText[512];
|
|
||||||
sprintf(boundaryText, "0.000000 0.000000 %f %f", physicalWidth, physicalHeight);
|
|
||||||
imgObject->SetAttribute("Boundary", boundaryText);
|
|
||||||
HGChar imgObjectResId[24];
|
|
||||||
sprintf(imgObjectResId, "%u", index * 10 + 2);
|
|
||||||
imgObject->SetAttribute("ResourceID", imgObjectResId);
|
|
||||||
char ctmText[512];
|
|
||||||
sprintf(ctmText, "%f 0 0 %f 0 0", physicalWidth, physicalHeight);
|
|
||||||
imgObject->SetAttribute("CTM", ctmText);
|
|
||||||
layer->InsertEndChild(imgObject);
|
|
||||||
|
|
||||||
HGChar name[256];
|
|
||||||
sprintf(name, "%s/Content.xml", dir);
|
|
||||||
return AddXmlFile(xmlDoc, name);
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
#ifndef __HGOFDIMPL_HPP__
|
|
||||||
#define __HGOFDIMPL_HPP__
|
|
||||||
|
|
||||||
#include "HGOfd.h"
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "zip.h"
|
|
||||||
};
|
|
||||||
#include "tinyxml2.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class HGOfdReaderImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGOfdReaderImpl();
|
|
||||||
~HGOfdReaderImpl();
|
|
||||||
|
|
||||||
HGResult Open(const HGChar* fileName);
|
|
||||||
HGResult Close();
|
|
||||||
HGResult GetPageCount(HGUInt* count);
|
|
||||||
HGResult GetPageInfo(HGUInt page, HGOfdPageInfo* info);
|
|
||||||
HGResult LoadImage(HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HGResult ReadXml(const char *name, std::string &content);
|
|
||||||
HGResult ReadJpeg(const char* name, HGJpegLoadInfo *info, HGFloat xScale, HGFloat yScale, HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
private:
|
|
||||||
zip* m_zip;
|
|
||||||
std::vector<std::string> m_contentNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
class HGOfdImageWriterImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGOfdImageWriterImpl();
|
|
||||||
~HGOfdImageWriterImpl();
|
|
||||||
|
|
||||||
HGResult Open(const HGChar* fileName);
|
|
||||||
HGResult Close();
|
|
||||||
HGResult SaveJpegImage(HGImage image, const HGJpegSaveInfo* info);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HGResult AddOfdXml();
|
|
||||||
HGResult AddDocXml();
|
|
||||||
HGResult AddDocResXml();
|
|
||||||
HGResult AddPublicResXml();
|
|
||||||
HGResult AddXmlFile(tinyxml2::XMLDocument &xmlDoc, const HGChar *name);
|
|
||||||
HGResult AddJpegImageFile(HGImage image, const HGJpegSaveInfo* info, const HGChar* name);
|
|
||||||
HGResult AddContentXmlFile(HGUInt index, HGFloat physicalWidth, HGFloat physicalHeight);
|
|
||||||
|
|
||||||
private:
|
|
||||||
zip* m_zip;
|
|
||||||
std::list<std::string> m_tmpFiles;
|
|
||||||
HGUInt m_curImgIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGOFDIMPL_HPP__ */
|
|
|
@ -1,173 +0,0 @@
|
||||||
#include "HGPdf.h"
|
|
||||||
#include "HGPdfImpl.hpp"
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CheckPdfFile(const HGChar* fileName, HGBool* isPdf)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == isPdf)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfReader reader = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenPdfReader(fileName, &reader);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*isPdf = HGTRUE;
|
|
||||||
HGImgFmt_ClosePdfReader(reader);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_OpenPdfReader(const HGChar* fileName, HGPdfReader* reader)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfReaderImpl* pdfReaderImpl = new HGPdfReaderImpl;
|
|
||||||
HGResult ret = pdfReaderImpl->Open(fileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete pdfReaderImpl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*reader = (HGPdfReader)pdfReaderImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_ClosePdfReader(HGPdfReader reader)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|
||||||
HGResult ret = pdfReaderImpl->Close();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pdfReaderImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_GetPdfPageCount(HGPdfReader reader, HGUInt* count)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|
||||||
return pdfReaderImpl->GetPageCount(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_GetPdfPageInfo(HGPdfReader reader, HGUInt page, HGPdfPageInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|
||||||
return pdfReaderImpl->GetPageInfo(page, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadImageFromPdfReader(HGPdfReader reader, HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfReaderImpl* pdfReaderImpl = (HGPdfReaderImpl*)reader;
|
|
||||||
return pdfReaderImpl->LoadImage(page, xScale, yScale, imgType, imgOrigin, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadPdfImage(const HGChar* fileName, HGPdfPageInfo* info, HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
HGPdfReader reader = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenPdfReader(fileName, &reader);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HGBASE_ERR_OK == ret && NULL != info)
|
|
||||||
ret = HGImgFmt_GetPdfPageInfo(reader, 0, info);
|
|
||||||
|
|
||||||
if (HGBASE_ERR_OK == ret && NULL != image)
|
|
||||||
ret = HGImgFmt_LoadImageFromPdfReader(reader, 0, 1.0f, 1.0f, imgType, imgOrigin, image);
|
|
||||||
|
|
||||||
HGImgFmt_ClosePdfReader(reader);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_OpenPdfImageWriter(const HGChar* fileName, HGPdfImageWriter* writer)
|
|
||||||
{
|
|
||||||
if (NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfImageWriterImpl* pdfImageWriterImpl = new HGPdfImageWriterImpl;
|
|
||||||
HGResult ret = pdfImageWriterImpl->Open(fileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete pdfImageWriterImpl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*writer = (HGPdfImageWriter)pdfImageWriterImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_ClosePdfImageWriter(HGPdfImageWriter writer)
|
|
||||||
{
|
|
||||||
if (NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfImageWriterImpl* pdfImageWriterImpl = (HGPdfImageWriterImpl*)writer;
|
|
||||||
HGResult ret = pdfImageWriterImpl->Close();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pdfImageWriterImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveJpegImageToPdfImageWriter(HGPdfImageWriter writer, HGImage image, const HGJpegSaveInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfImageWriterImpl* pdfImageWriterImpl = (HGPdfImageWriterImpl*)writer;
|
|
||||||
return pdfImageWriterImpl->SaveJpegImage(image, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SavePdfJpegImage(HGImage image, const HGJpegSaveInfo* info, const HGChar* fileName)
|
|
||||||
{
|
|
||||||
HGPdfImageWriter writer = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenPdfImageWriter(fileName, &writer);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGImgFmt_SaveJpegImageToPdfImageWriter(writer, image, info);
|
|
||||||
HGImgFmt_ClosePdfImageWriter(writer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
#ifndef __HGPDF_H__
|
|
||||||
#define __HGPDF_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
#include "HGJpeg.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGPdfReader);
|
|
||||||
HG_DECLARE_HANDLE(HGPdfImageWriter);
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width;
|
|
||||||
HGUInt height;
|
|
||||||
HGUInt bpp;
|
|
||||||
}HGPdfPageInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckPdfFile(const HGChar* fileName, HGBool* isPdf);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenPdfReader(const HGChar* fileName, HGPdfReader* reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_ClosePdfReader(HGPdfReader reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetPdfPageCount(HGPdfReader reader, HGUInt* count);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetPdfPageInfo(HGPdfReader reader, HGUInt page, HGPdfPageInfo *info);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadImageFromPdfReader(HGPdfReader reader, HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadPdfImage(const HGChar* fileName, HGPdfPageInfo *info, HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenPdfImageWriter(const HGChar* fileName, HGPdfImageWriter* writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_ClosePdfImageWriter(HGPdfImageWriter writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveJpegImageToPdfImageWriter(HGPdfImageWriter writer, HGImage image, const HGJpegSaveInfo* info);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SavePdfJpegImage(HGImage image, const HGJpegSaveInfo* info, const HGChar* fileName);
|
|
||||||
|
|
||||||
#endif /* __HGPDF_H__ */
|
|
|
@ -1,890 +0,0 @@
|
||||||
#include "HGPdfImpl.hpp"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGUtility.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
#include "HGString.h"
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
HGPdfReaderImpl::HGPdfReaderImpl()
|
|
||||||
{
|
|
||||||
m_dll = NULL;
|
|
||||||
m_pContext = NULL;
|
|
||||||
m_pDoc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfReaderImpl::~HGPdfReaderImpl()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfReaderImpl::Open(const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL != m_pDoc)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == fileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(fileName, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(fileName, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPdfFile)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(NULL == m_dll);
|
|
||||||
|
|
||||||
HGChar moduleName[256];
|
|
||||||
HGBase_GetModuleName((void *)HGImgFmt_OpenPdfReader, moduleName, 256);
|
|
||||||
HGChar dllPath[256];
|
|
||||||
HGBase_GetFilePath(moduleName, dllPath, 256);
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
strcat(dllPath, "libmupdf.dll");
|
|
||||||
#else
|
|
||||||
strcat(dllPath, "libmupdf.so");
|
|
||||||
#endif
|
|
||||||
HGResult ret = HGBase_CreateDll(dllPath, &m_dll);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_context* pContext = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
|
|
||||||
if (NULL == pContext)
|
|
||||||
{
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGIMGFMT_ERR_FAIL;
|
|
||||||
fz_try(pContext)
|
|
||||||
{
|
|
||||||
fz_register_document_handlers(pContext);
|
|
||||||
fz_document* pDoc = fz_open_document(pContext, StdStringToUtf8(fileName).c_str());
|
|
||||||
|
|
||||||
m_pContext = pContext;
|
|
||||||
m_pDoc = pDoc;
|
|
||||||
ret = HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
fz_catch(pContext)
|
|
||||||
{
|
|
||||||
fz_drop_context(pContext);
|
|
||||||
pContext = NULL;
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfReaderImpl::Close()
|
|
||||||
{
|
|
||||||
if (NULL == m_pDoc)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_drop_document(m_pContext, m_pDoc);
|
|
||||||
m_pDoc = NULL;
|
|
||||||
fz_drop_context(m_pContext);
|
|
||||||
m_pContext = NULL;
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfReaderImpl::GetPageCount(HGUInt* count)
|
|
||||||
{
|
|
||||||
if (NULL == m_pDoc)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == count)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult ret = HGIMGFMT_ERR_FAIL;
|
|
||||||
fz_try(m_pContext)
|
|
||||||
{
|
|
||||||
*count = (uint32_t)fz_count_pages(m_pContext, m_pDoc);
|
|
||||||
ret = HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
fz_catch(m_pContext)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfReaderImpl::GetPageInfo(HGUInt page, HGPdfPageInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == m_pDoc)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == info)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult ret = HGIMGFMT_ERR_FAIL;
|
|
||||||
fz_page* fzpage = NULL;
|
|
||||||
|
|
||||||
fz_try(m_pContext)
|
|
||||||
{
|
|
||||||
fzpage = fz_load_page(m_pContext, m_pDoc, (int)page);
|
|
||||||
pdf_page* page = pdf_page_from_fz_page(m_pContext, fzpage);
|
|
||||||
if (NULL != page)
|
|
||||||
{
|
|
||||||
fz_rect pdfRect = pdf_bound_page(m_pContext, page);
|
|
||||||
info->width = ceil(pdfRect.x1);
|
|
||||||
info->height = ceil(pdfRect.y1);
|
|
||||||
info->bpp = 24;
|
|
||||||
ret = HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fz_catch(m_pContext)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != fzpage)
|
|
||||||
fz_drop_page(m_pContext, fzpage);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfReaderImpl::LoadImage(HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
if (NULL == m_pDoc)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == image)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult ret = HGIMGFMT_ERR_FAIL;
|
|
||||||
fz_pixmap* pix = NULL;
|
|
||||||
|
|
||||||
fz_try(m_pContext)
|
|
||||||
{
|
|
||||||
fz_matrix ctm = fz_scale(xScale, yScale);
|
|
||||||
pix = fz_new_pixmap_from_page_number(m_pContext, m_pDoc, (int)page,
|
|
||||||
ctm, fz_device_rgb(m_pContext), 0);
|
|
||||||
|
|
||||||
int width = fz_pixmap_width(m_pContext, pix);
|
|
||||||
int height = fz_pixmap_height(m_pContext, pix);
|
|
||||||
|
|
||||||
if (0 == imgType)
|
|
||||||
imgType = HGBASE_IMGTYPE_RGB;
|
|
||||||
|
|
||||||
if (imgOrigin == 0)
|
|
||||||
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGImageInfo imgInfo = { (uint32_t)width, (uint32_t)height, HGBASE_IMGTYPE_RGB, (uint32_t)pix->stride, HGBASE_IMGORIGIN_TOP };
|
|
||||||
if (HGBASE_ERR_OK == HGBase_CreateImageWithData(pix->samples, &imgInfo, &image2))
|
|
||||||
{
|
|
||||||
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fz_catch(m_pContext)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != pix)
|
|
||||||
fz_drop_pixmap(m_pContext, pix);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_context* HGPdfReaderImpl::fz_new_context_imp(const fz_alloc_context* alloc, const fz_locks_context* locks, size_t max_store, const char* version)
|
|
||||||
{
|
|
||||||
typedef fz_context* (*Func)(const fz_alloc_context*, const fz_locks_context*, size_t, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_new_context_imp", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(alloc, locks, max_store, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfReaderImpl::fz_register_document_handlers(fz_context* ctx)
|
|
||||||
{
|
|
||||||
typedef void (*Func)(fz_context*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_register_document_handlers", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_document* HGPdfReaderImpl::fz_open_document(fz_context* ctx, const char* filename)
|
|
||||||
{
|
|
||||||
typedef fz_document* (*Func)(fz_context*, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_open_document", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfReaderImpl::fz_drop_context(fz_context* ctx)
|
|
||||||
{
|
|
||||||
typedef void (*Func)(fz_context*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_drop_context", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfReaderImpl::fz_drop_document(fz_context* ctx, fz_document* doc)
|
|
||||||
{
|
|
||||||
typedef void (*Func)(fz_context*, fz_document*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_drop_document", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(ctx, doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfReaderImpl::fz_count_pages(fz_context* ctx, fz_document* doc)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(fz_context*, fz_document*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_count_pages", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_page* HGPdfReaderImpl::fz_load_page(fz_context* ctx, fz_document* doc, int number)
|
|
||||||
{
|
|
||||||
typedef fz_page* (*Func)(fz_context*, fz_document* doc, int);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_load_page", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, doc, number);
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf_page* HGPdfReaderImpl::pdf_page_from_fz_page(fz_context* ctx, fz_page* ptr)
|
|
||||||
{
|
|
||||||
typedef pdf_page* (*Func)(fz_context*, fz_page*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "pdf_page_from_fz_page", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_rect HGPdfReaderImpl::pdf_bound_page(fz_context* ctx, pdf_page* page)
|
|
||||||
{
|
|
||||||
typedef fz_rect (*Func)(fz_context*, pdf_page*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "pdf_bound_page", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
fz_rect rect = {0, 0, 0, 0};
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, page);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfReaderImpl::fz_drop_page(fz_context* ctx, fz_page* page)
|
|
||||||
{
|
|
||||||
typedef void (*Func)(fz_context*, fz_page*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_drop_page", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(ctx, page);
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_matrix HGPdfReaderImpl::fz_scale(float sx, float sy)
|
|
||||||
{
|
|
||||||
typedef fz_matrix (*Func)(float, float);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_scale", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
fz_matrix matrix = { 0, 0, 0, 0, 0, 0 };
|
|
||||||
return matrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(sx, sy);
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_pixmap* HGPdfReaderImpl::fz_new_pixmap_from_page_number(fz_context* ctx, fz_document* doc, int number, fz_matrix ctm, fz_colorspace* cs, int alpha)
|
|
||||||
{
|
|
||||||
typedef fz_pixmap* (*Func)(fz_context*, fz_document*, int, fz_matrix, fz_colorspace*, int);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_new_pixmap_from_page_number", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, doc, number, ctm, cs, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_colorspace* HGPdfReaderImpl::fz_device_rgb(fz_context* ctx)
|
|
||||||
{
|
|
||||||
typedef fz_colorspace* (*Func)(fz_context*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_device_rgb", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfReaderImpl::fz_pixmap_width(fz_context* ctx, const fz_pixmap* pix)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(fz_context*, const fz_pixmap*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_pixmap_width", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfReaderImpl::fz_pixmap_height(fz_context* ctx, const fz_pixmap* pix)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(fz_context*, const fz_pixmap*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_pixmap_height", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx, pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfReaderImpl::fz_drop_pixmap(fz_context* ctx, fz_pixmap* pix)
|
|
||||||
{
|
|
||||||
typedef void (*Func)(fz_context*, fz_pixmap*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_drop_pixmap", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(ctx, pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_jmp_buf* HGPdfReaderImpl::fz_push_try(fz_context* ctx)
|
|
||||||
{
|
|
||||||
typedef fz_jmp_buf* (*Func)(fz_context*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_push_try", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfReaderImpl::fz_do_try(fz_context* ctx)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(fz_context*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_do_try", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfReaderImpl::fz_do_catch(fz_context* ctx)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(fz_context*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "fz_do_catch", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
HGPdfImageWriterImpl::HGPdfImageWriterImpl()
|
|
||||||
{
|
|
||||||
m_dll = NULL;
|
|
||||||
m_pPdf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPdfImageWriterImpl::~HGPdfImageWriterImpl()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfImageWriterImpl::Open(const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL != m_pPdf)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == fileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(NULL == m_dll);
|
|
||||||
|
|
||||||
HGChar moduleName[256];
|
|
||||||
HGBase_GetModuleName((void*)HGImgFmt_OpenPdfImageWriter, moduleName, 256);
|
|
||||||
HGChar dllPath[256];
|
|
||||||
HGBase_GetFilePath(moduleName, dllPath, 256);
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
strcat(dllPath, "pdflib.dll");
|
|
||||||
#else
|
|
||||||
strcat(dllPath, "libpdf.so");
|
|
||||||
#endif
|
|
||||||
HGResult ret = HGBase_CreateDll(dllPath, &m_dll);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
PDF* p = PDF_new();
|
|
||||||
if (NULL == p)
|
|
||||||
{
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGPdfImageWriterImpl::Open: PDF_begin_document fail, %s", fileName);
|
|
||||||
|
|
||||||
delete[] pUnicode;
|
|
||||||
PDF_delete(p);
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PDF_CATCH(p)
|
|
||||||
{
|
|
||||||
delete[] pUnicode;
|
|
||||||
PDF_delete(p);
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] pUnicode;
|
|
||||||
m_pPdf = p;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfImageWriterImpl::Close()
|
|
||||||
{
|
|
||||||
if (NULL == m_pPdf)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PDF_TRY(m_pPdf)
|
|
||||||
{
|
|
||||||
PDF_end_document(m_pPdf, "");
|
|
||||||
}
|
|
||||||
PDF_CATCH(m_pPdf)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
PDF_delete(m_pPdf);
|
|
||||||
m_pPdf = NULL;
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGPdfImageWriterImpl::SaveJpegImage(HGImage image, const HGJpegSaveInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == m_pPdf)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == image)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBuffer buffer = NULL;
|
|
||||||
HGResult ret = HGImgFmt_SaveJpegImageToBuffer(image, info, &buffer);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte* imgBuf = NULL;
|
|
||||||
HGBase_GetBufferData(buffer, &imgBuf);
|
|
||||||
HGUSize size = 0;
|
|
||||||
HGBase_GetBufferSize(buffer, &size);
|
|
||||||
|
|
||||||
PDF_TRY(m_pPdf)
|
|
||||||
{
|
|
||||||
PDF_create_pvf(m_pPdf, "virtual_file", 0, imgBuf, size, "");
|
|
||||||
}
|
|
||||||
PDF_CATCH(m_pPdf)
|
|
||||||
{
|
|
||||||
HGBase_DestroyBuffer(buffer);
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int img = PDF_load_image(m_pPdf, "auto", "virtual_file", 0, "page 1");
|
|
||||||
if (-1 != img)
|
|
||||||
{
|
|
||||||
PDF_begin_page_ext(m_pPdf, 0.0, 0.0, "");
|
|
||||||
PDF_fit_image(m_pPdf, img, 0.0, 0.0, "adjustpage");
|
|
||||||
PDF_end_page_ext(m_pPdf, "");
|
|
||||||
PDF_close_image(m_pPdf, img);
|
|
||||||
}
|
|
||||||
|
|
||||||
PDF_delete_pvf(m_pPdf, "virtual_file", 0);
|
|
||||||
|
|
||||||
HGBase_DestroyBuffer(buffer);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PDF* HGPdfImageWriterImpl::PDF_new(void)
|
|
||||||
{
|
|
||||||
typedef PDF* (PDFLIB_CALL *Func)();
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_new", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_set_parameter(PDF* p, const char* key, const char* value)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*, const char*, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_set_parameter", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfImageWriterImpl::PDF_begin_document(PDF* p, const char* filename, int len, const char* optlist)
|
|
||||||
{
|
|
||||||
typedef int (PDFLIB_CALL* Func)(PDF*, const char*, int, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_begin_document", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(p, filename, len, optlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_delete(PDF* p)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_delete", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_end_document(PDF* p, const char* optlist)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_end_document", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p, optlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_create_pvf(PDF* p, const char* filename, int len, const void* data, size_t size, const char* optlist)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*, const char*, int, const void*, size_t, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_create_pvf", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p, filename, len, data, size, optlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfImageWriterImpl::PDF_load_image(PDF* p, const char* imagetype, const char* filename, int len, const char* optlist)
|
|
||||||
{
|
|
||||||
typedef int (PDFLIB_CALL* Func)(PDF*, const char*, const char*, int, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_load_image", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(p, imagetype, filename, len, optlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_begin_page_ext(PDF* p, double width, double height, const char* optlist)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*, double, double, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_begin_page_ext", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p, width, height, optlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_fit_image(PDF* p, int image, double x, double y, const char* optlist)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*, int, double, double, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_fit_image", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p, image, x, y, optlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_end_page_ext(PDF* p, const char* optlist)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*, const char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_end_page_ext", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p, optlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGPdfImageWriterImpl::PDF_close_image(PDF* p, int image)
|
|
||||||
{
|
|
||||||
typedef void (PDFLIB_CALL* Func)(PDF*, int);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_close_image", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfImageWriterImpl::PDF_delete_pvf(PDF* p, const char* filename, int len)
|
|
||||||
{
|
|
||||||
typedef int (PDFLIB_CALL* Func)(PDF*, const char*, int);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "PDF_delete_pvf", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(p, filename, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf_jmpbuf* HGPdfImageWriterImpl::pdf_jbuf(PDF* p)
|
|
||||||
{
|
|
||||||
typedef pdf_jmpbuf* (PDFLIB_CALL* Func)(PDF*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "pdf_jbuf", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGPdfImageWriterImpl::pdf_catch(PDF* p)
|
|
||||||
{
|
|
||||||
typedef int (PDFLIB_CALL* Func)(PDF*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "pdf_catch", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(p);
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
#ifndef __HGPDFIMPL_HPP__
|
|
||||||
#define __HGPDFIMPL_HPP__
|
|
||||||
|
|
||||||
#include "HGPdf.h"
|
|
||||||
#include "../base/HGDll.h"
|
|
||||||
#include "mupdf/pdf.h"
|
|
||||||
#include "mupdf/fitz.h"
|
|
||||||
#include "pdflib.h"
|
|
||||||
|
|
||||||
class HGPdfReaderImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGPdfReaderImpl();
|
|
||||||
~HGPdfReaderImpl();
|
|
||||||
|
|
||||||
HGResult Open(const HGChar* fileName);
|
|
||||||
HGResult Close();
|
|
||||||
HGResult GetPageCount(HGUInt* count);
|
|
||||||
HGResult GetPageInfo(HGUInt page, HGPdfPageInfo* info);
|
|
||||||
HGResult LoadImage(HGUInt page, HGFloat xScale, HGFloat yScale,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
private:
|
|
||||||
fz_context* fz_new_context_imp(const fz_alloc_context* alloc, const fz_locks_context* locks, size_t max_store, const char* version);
|
|
||||||
void fz_register_document_handlers(fz_context* ctx);
|
|
||||||
fz_document* fz_open_document(fz_context* ctx, const char* filename);
|
|
||||||
void fz_drop_context(fz_context* ctx);
|
|
||||||
void fz_drop_document(fz_context* ctx, fz_document* doc);
|
|
||||||
int fz_count_pages(fz_context* ctx, fz_document* doc);
|
|
||||||
fz_page* fz_load_page(fz_context* ctx, fz_document* doc, int number);
|
|
||||||
pdf_page* pdf_page_from_fz_page(fz_context* ctx, fz_page* ptr);
|
|
||||||
fz_rect pdf_bound_page(fz_context* ctx, pdf_page* page);
|
|
||||||
void fz_drop_page(fz_context* ctx, fz_page* page);
|
|
||||||
fz_matrix fz_scale(float sx, float sy);
|
|
||||||
fz_pixmap* fz_new_pixmap_from_page_number(fz_context* ctx, fz_document* doc, int number, fz_matrix ctm, fz_colorspace* cs, int alpha);
|
|
||||||
fz_colorspace* fz_device_rgb(fz_context* ctx);
|
|
||||||
int fz_pixmap_width(fz_context* ctx, const fz_pixmap* pix);
|
|
||||||
int fz_pixmap_height(fz_context* ctx, const fz_pixmap* pix);
|
|
||||||
void fz_drop_pixmap(fz_context* ctx, fz_pixmap* pix);
|
|
||||||
fz_jmp_buf* fz_push_try(fz_context* ctx);
|
|
||||||
int fz_do_try(fz_context* ctx);
|
|
||||||
int fz_do_catch(fz_context* ctx);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HGDll m_dll;
|
|
||||||
fz_context* m_pContext;
|
|
||||||
fz_document* m_pDoc;
|
|
||||||
};
|
|
||||||
|
|
||||||
class HGPdfImageWriterImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGPdfImageWriterImpl();
|
|
||||||
~HGPdfImageWriterImpl();
|
|
||||||
|
|
||||||
HGResult Open(const HGChar* fileName);
|
|
||||||
HGResult Close();
|
|
||||||
HGResult SaveJpegImage(HGImage image, const HGJpegSaveInfo* info);
|
|
||||||
|
|
||||||
private:
|
|
||||||
PDF* PDF_new(void);
|
|
||||||
void PDF_set_parameter(PDF* p, const char* key, const char* value);
|
|
||||||
int PDF_begin_document(PDF* p, const char* filename, int len, const char* optlist);
|
|
||||||
void PDF_delete(PDF* p);
|
|
||||||
void PDF_end_document(PDF* p, const char* optlist);
|
|
||||||
void PDF_create_pvf(PDF* p, const char* filename, int len, const void* data, size_t size, const char* optlist);
|
|
||||||
int PDF_load_image(PDF* p, const char* imagetype, const char* filename, int len, const char* optlist);
|
|
||||||
void PDF_begin_page_ext(PDF* p, double width, double height, const char* optlist);
|
|
||||||
void PDF_fit_image(PDF* p, int image, double x, double y, const char* optlist);
|
|
||||||
void PDF_end_page_ext(PDF* p, const char* optlist);
|
|
||||||
void PDF_close_image(PDF* p, int image);
|
|
||||||
int PDF_delete_pvf(PDF* p, const char* filename, int len);
|
|
||||||
pdf_jmpbuf* pdf_jbuf(PDF* p);
|
|
||||||
int pdf_catch(PDF* p);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HGDll m_dll;
|
|
||||||
PDF* m_pPdf;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGPDFIMPL_HPP__ */
|
|
|
@ -1,462 +0,0 @@
|
||||||
#include "HGPng.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGInfo.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);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*isPng = HGTRUE;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_BINARY != imgType && HGBASE_IMGTYPE_GRAY != imgType
|
|
||||||
&& HGBASE_IMGTYPE_BGR != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
||||||
&& HGBASE_IMGTYPE_BGRA != imgType && HGBASE_IMGTYPE_RGBA != imgType)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(fileName, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(fileName, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
||||||
if (NULL == png_ptr)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGIMGFMT_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 HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* buffer = NULL;
|
|
||||||
uint8_t** rowPointers = NULL;
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
|
|
||||||
int jmpResult = setjmp(png_jmpbuf(png_ptr));
|
|
||||||
if (0 != jmpResult)
|
|
||||||
{
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
free(rowPointers);
|
|
||||||
rowPointers = NULL;
|
|
||||||
free(buffer);
|
|
||||||
buffer = 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_OUTOFMEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
rowPointers = (uint8_t**)malloc(info_ptr->height * sizeof(png_bytep));
|
|
||||||
if (NULL == rowPointers)
|
|
||||||
{
|
|
||||||
longjmp(png_jmpbuf(png_ptr), (int)HGBASE_ERR_OUTOFMEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#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)
|
|
||||||
{
|
|
||||||
imgType = HGBASE_IMGTYPE_RGB;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgOrigin == 0)
|
|
||||||
{
|
|
||||||
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult ret = HGBase_CreateImage(info_ptr->width, info_ptr->height, HGBASE_IMGTYPE_RGBA, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(png_jmpbuf(png_ptr), (int)ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PNG_RESOLUTION_METER == 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);
|
|
||||||
|
|
||||||
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 = data + (HGSize)i * (HGSize)imgInfo.widthStep;
|
|
||||||
|
|
||||||
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 = data + (HGSize)i * (HGSize)imgInfo.widthStep;
|
|
||||||
|
|
||||||
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 = data + (HGSize)i * (HGSize)imgInfo.widthStep;
|
|
||||||
|
|
||||||
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 = data + (HGSize)i * (HGSize)imgInfo.widthStep;
|
|
||||||
memcpy(pDestEx, pEx, info_ptr->width * 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(png_jmpbuf(png_ptr), (int)ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
free(rowPointers);
|
|
||||||
rowPointers = NULL;
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// 判断合法性
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* file = fopen(fileName, "wb");
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGImgFmt_SavePngImage: fopen fail, %s errno=%d", fileName, errno);
|
|
||||||
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 HGIMGFMT_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 HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t** rowPointers = NULL;
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGImageRoi roi;
|
|
||||||
HGBase_GetImageROI(image, &roi);
|
|
||||||
|
|
||||||
int jmpResult = setjmp(png_jmpbuf(png_ptr));
|
|
||||||
if (0 != jmpResult)
|
|
||||||
{
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
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);
|
|
||||||
|
|
||||||
HGBase_ResetImageROI(image);
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
if (HGBASE_IMGTYPE_BGR == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(png_jmpbuf(png_ptr), (int)ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_BGRA == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGBA, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(png_jmpbuf(png_ptr), (int)ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(png_jmpbuf(png_ptr), (int)ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, imgInfo.type, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
longjmp(png_jmpbuf(png_ptr), (int)ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_GetImageInfo(image2, &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;
|
|
||||||
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image2, &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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image2, &xDpi, &yDpi);
|
|
||||||
info_ptr->phys_unit_type = PNG_RESOLUTION_METER;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_OUTOFMEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (int32_t i = 0; i < (int32_t)height; ++i)
|
|
||||||
{
|
|
||||||
rowPointers[i] = data + (HGSize)i * (HGSize)widthStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_write_image(png_ptr, rowPointers);
|
|
||||||
png_write_end(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
free(rowPointers);
|
|
||||||
rowPointers = NULL;
|
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
||||||
fclose(file);
|
|
||||||
file = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
#ifndef __HGPNG_H__
|
|
||||||
#define __HGPNG_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
|
|
||||||
/* */
|
|
||||||
#define HGIMGFMT_PNGCLRTYPE_GRAY 0L
|
|
||||||
#define HGIMGFMT_PNGCLRTYPE_PALETTE (1L | 2L)
|
|
||||||
#define HGIMGFMT_PNGCLRTYPE_RGB 2L
|
|
||||||
#define HGIMGFMT_PNGCLRTYPE_RGB_ALPHA (2L | 4L)
|
|
||||||
#define HGIMGFMT_PNGCLRTYPE_GRAY_ALPHA 4L
|
|
||||||
|
|
||||||
/* */
|
|
||||||
#define HGIMGFMT_PNGFILTERTYPE_BASE 0L
|
|
||||||
/* */
|
|
||||||
#define HGIMGFMT_PNGINTERLACE_NONE 0L
|
|
||||||
#define HGIMGFMT_PNGINTERLACE_ADAM7 1L
|
|
||||||
#define HGIMGFMT_PNGINTERLACE_LAST 2L
|
|
||||||
/* */
|
|
||||||
#define HGIMGFMT_PNGCOMPTYPE_BASE 0L
|
|
||||||
|
|
||||||
/* 分辨率单位 */
|
|
||||||
#define HGIMGFMT_PNGPHYSUNIT_UNKNOWN 0L
|
|
||||||
#define HGIMGFMT_PNGPHYSUNIT_METER 1L
|
|
||||||
#define HGIMGFMT_PNGPHYSUNIT_LAST 2L
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 图像宽 */
|
|
||||||
HGUInt height; /* 图像高 */
|
|
||||||
HGByte bitDepth; /* 每通道的比特数 */
|
|
||||||
HGByte colorType; /* 色彩类型, 见HGIMGFMT_PNGCLRTYPE_* */
|
|
||||||
HGByte channels; /* 通道数 */
|
|
||||||
HGByte filterType; /* 见HGIMGFMT_PNGFILTERTYPE_* */
|
|
||||||
HGByte InterlaceType; /* 见HGIMGFMT_PNGINTERLACE_* */
|
|
||||||
HGByte compressionType; /* 见HGIMGFMT_PNGCOMPTYPE_* */
|
|
||||||
HGByte pixelDepth; /* 每像素的比特数 */
|
|
||||||
HGByte physUnitType; /* 分辨率单位, 见HGIMGFMT_PNGPHYSUNIT_* */
|
|
||||||
HGUInt xPixelsPerUnit; /* 分辨率x */
|
|
||||||
HGUInt yPixelsPerUnit; /* 分辨率y */
|
|
||||||
}HGPngLoadInfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGByte physUnitType; /* 分辨率单位, 见HGIMGFMT_PNGPHYSUNIT_* */
|
|
||||||
HGUInt xPixelsPerUnit; /* 分辨率x */
|
|
||||||
HGUInt yPixelsPerUnit; /* 分辨率y */
|
|
||||||
}HGPngSaveInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckPngFile(const HGChar* fileName, HGBool* isPng);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadPngImage(const HGChar* fileName, HGPngLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SavePngImage(HGImage image, const HGPngSaveInfo* info, const HGChar* fileName);
|
|
||||||
|
|
||||||
#endif /* __HGPNG_H__ */
|
|
|
@ -1,732 +0,0 @@
|
||||||
#include "HGPnm.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
static inline HGByte GetBit(const HGByte* data, HGUInt index)
|
|
||||||
{
|
|
||||||
HGUInt byteIndex = index / 8;
|
|
||||||
HGUInt bitIndex = index % 8;
|
|
||||||
return (data[byteIndex] >> (7 - bitIndex)) & 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void SetBit(HGByte* data, HGUInt index, HGByte value)
|
|
||||||
{
|
|
||||||
assert(0 == value || 1 == value);
|
|
||||||
HGUInt byteIndex = index / 8;
|
|
||||||
HGUInt bitIndex = index % 8;
|
|
||||||
if (1 == value)
|
|
||||||
data[byteIndex] |= (1 << (7 - bitIndex));
|
|
||||||
else
|
|
||||||
data[byteIndex] &= ~(1 << (7 - bitIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline HGUInt MyAtoi(const HGChar* c)
|
|
||||||
{
|
|
||||||
HGUInt value = 0;
|
|
||||||
|
|
||||||
const HGChar* p = c;
|
|
||||||
while (0 != *p)
|
|
||||||
{
|
|
||||||
value *= 10;
|
|
||||||
value += (HGUInt)(*p - '0');
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CheckPnmFile(const HGChar* fileName, HGBool* isPnm)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == isPnm)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGPnmLoadInfo info;
|
|
||||||
HGResult ret = HGImgFmt_LoadPnmImage(fileName, &info, 0, 0, NULL);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*isPnm = HGTRUE;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_GetPnmTypeFromFileName(const HGChar* fileName, HGUInt* pnmType)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == pnmType)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* p = strrchr(fileName, '.');
|
|
||||||
if (NULL == p)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 == _stricmp(p, ".pbm"))
|
|
||||||
{
|
|
||||||
*pnmType = HGIMGFMT_PNMTYPE_BINARY_BINARY;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == _stricmp(p, ".pgm"))
|
|
||||||
{
|
|
||||||
*pnmType = HGIMGFMT_PNMTYPE_GRAY_BINARY;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == _stricmp(p, ".ppm"))
|
|
||||||
{
|
|
||||||
*pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (0 == strcasecmp(p, ".pbm"))
|
|
||||||
{
|
|
||||||
*pnmType = HGIMGFMT_PNMTYPE_BINARY_BINARY;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == strcasecmp(p, ".pgm"))
|
|
||||||
{
|
|
||||||
*pnmType = HGIMGFMT_PNMTYPE_GRAY_BINARY;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == strcasecmp(p, ".ppm"))
|
|
||||||
{
|
|
||||||
*pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HGResult PnmLoadInfo(FILE* file, HGUInt pnmType, HGUInt *width, HGUInt *height, HGUInt *maxColor)
|
|
||||||
{
|
|
||||||
assert(NULL != file && NULL != width && NULL != height && NULL != maxColor);
|
|
||||||
|
|
||||||
bool getWidth = false;
|
|
||||||
bool getHeight = false;
|
|
||||||
bool getMaxColor = false;
|
|
||||||
char buf[256];
|
|
||||||
int bufLen = 0;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
HGByte c = 0;
|
|
||||||
if (1 != fread(&c, 1, 1, file))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
|
|
||||||
{
|
|
||||||
if (0 != bufLen)
|
|
||||||
{
|
|
||||||
buf[bufLen] = 0;
|
|
||||||
|
|
||||||
if (!getWidth)
|
|
||||||
{
|
|
||||||
*width = MyAtoi(buf);
|
|
||||||
if (*width == 0)
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
getWidth = true;
|
|
||||||
}
|
|
||||||
else if (!getHeight)
|
|
||||||
{
|
|
||||||
*height = MyAtoi(buf);
|
|
||||||
if (*height == 0)
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
getHeight = true;
|
|
||||||
}
|
|
||||||
else if (!getMaxColor)
|
|
||||||
{
|
|
||||||
*maxColor = MyAtoi(buf);
|
|
||||||
if (*maxColor == 0)
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
getMaxColor = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bufLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '#')
|
|
||||||
{
|
|
||||||
while (c != '\n')
|
|
||||||
{
|
|
||||||
if (1 != fread(&c, 1, 1, file))
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c >= '0' && c <= '9')
|
|
||||||
{
|
|
||||||
buf[bufLen] = c;
|
|
||||||
++bufLen;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
||||||
{
|
|
||||||
if (getMaxColor)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (getHeight)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HGResult PnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
HGUInt width = 0, height = 0, maxColor = 0;
|
|
||||||
HGResult ret = PnmLoadInfo(file, pnmType, &width, &height, &maxColor);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
||||||
{
|
|
||||||
if (maxColor != 255)
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
maxColor = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
info->width = width;
|
|
||||||
info->height = height;
|
|
||||||
info->type = pnmType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != image)
|
|
||||||
{
|
|
||||||
if (imgType == 0)
|
|
||||||
{
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
||||||
imgType = HGBASE_IMGTYPE_BINARY;
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
|
||||||
imgType = HGBASE_IMGTYPE_GRAY;
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
|
||||||
imgType = HGBASE_IMGTYPE_RGB;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgOrigin == 0)
|
|
||||||
{
|
|
||||||
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
||||||
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_BINARY, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
|
||||||
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
|
||||||
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image2, &data);
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image2, &imgInfo);
|
|
||||||
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
|
||||||
{
|
|
||||||
HGUInt lineSize = ((width + 7) & ~7) >> 3;
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
|
||||||
lineSize = width;
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
|
||||||
lineSize = width * 3;
|
|
||||||
|
|
||||||
for (HGUInt i = 0; i < height; ++i)
|
|
||||||
{
|
|
||||||
if (lineSize != fread(data + i * imgInfo.widthStep, 1, lineSize, file))
|
|
||||||
{
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
||||||
{
|
|
||||||
HGBase_ReverseImage(image2, image2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII)
|
|
||||||
{
|
|
||||||
HGChar readBuf[2048];
|
|
||||||
HGUInt readBufLen = 0;
|
|
||||||
HGChar* curReadPos = readBuf;
|
|
||||||
HGChar buf[256];
|
|
||||||
HGUInt bufLen = 0;
|
|
||||||
HGByte* p = data;
|
|
||||||
HGUInt idx = 0;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (0 == readBufLen)
|
|
||||||
{
|
|
||||||
readBufLen = (HGUInt)fread(readBuf, 1, 2048, file);
|
|
||||||
curReadPos = readBuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte c = 0;
|
|
||||||
HGBool getChar = HGFALSE;
|
|
||||||
if (0 != readBufLen)
|
|
||||||
{
|
|
||||||
c = *curReadPos;
|
|
||||||
++curReadPos;
|
|
||||||
--readBufLen;
|
|
||||||
getChar = HGTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!getChar || c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
|
|
||||||
{
|
|
||||||
if (0 != bufLen)
|
|
||||||
{
|
|
||||||
buf[bufLen] = 0;
|
|
||||||
HGUInt pixel = MyAtoi(buf);
|
|
||||||
if (pixel < 0 || pixel > maxColor)
|
|
||||||
{
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII)
|
|
||||||
SetBit(p, idx, (pixel == 0) ? 1 : 0);
|
|
||||||
else
|
|
||||||
p[idx] = (HGByte)pixel;
|
|
||||||
|
|
||||||
HGUInt step = width;
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII)
|
|
||||||
step = width * 3;
|
|
||||||
|
|
||||||
++idx;
|
|
||||||
if (idx == step)
|
|
||||||
{
|
|
||||||
p += imgInfo.widthStep;
|
|
||||||
idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bufLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!getChar)
|
|
||||||
{
|
|
||||||
if (p == data + height * imgInfo.widthStep)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == '#')
|
|
||||||
{
|
|
||||||
while (c != '\n')
|
|
||||||
{
|
|
||||||
c = 0;
|
|
||||||
HGBool getChar = HGFALSE;
|
|
||||||
if (0 != readBufLen)
|
|
||||||
{
|
|
||||||
c = *curReadPos;
|
|
||||||
++curReadPos;
|
|
||||||
--readBufLen;
|
|
||||||
getChar = HGTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!getChar)
|
|
||||||
{
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c >= '0' && c <= '9')
|
|
||||||
{
|
|
||||||
buf[bufLen] = c;
|
|
||||||
++bufLen;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == data + height * imgInfo.widthStep)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgInfo.type == imgType && imgInfo.origin == imgOrigin)
|
|
||||||
{
|
|
||||||
*image = image2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadPnmImage(const HGChar* fileName, HGPnmLoadInfo* 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_BINARY != imgType && HGBASE_IMGTYPE_GRAY != imgType
|
|
||||||
&& HGBASE_IMGTYPE_BGR != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
||||||
&& HGBASE_IMGTYPE_BGRA != imgType && HGBASE_IMGTYPE_RGBA != imgType)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(fileName, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(fileName, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* file = fopen(fileName, "rb");
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte magicKey[2] = {0};
|
|
||||||
if (2 != fread(magicKey, 1, 2, file))
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGUInt pnmType = 0;
|
|
||||||
if (magicKey[0] == 'P' && (magicKey[1] == '1'))
|
|
||||||
{
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_BINARY_ASCII;
|
|
||||||
}
|
|
||||||
else if (magicKey[0] == 'P' && (magicKey[1] == '2'))
|
|
||||||
{
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_GRAY_ASCII;
|
|
||||||
}
|
|
||||||
else if (magicKey[0] == 'P' && (magicKey[1] == '3'))
|
|
||||||
{
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_RGB_ASCII;
|
|
||||||
}
|
|
||||||
else if (magicKey[0] == 'P' && (magicKey[1] == '4'))
|
|
||||||
{
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_BINARY_BINARY;
|
|
||||||
}
|
|
||||||
else if (magicKey[0] == 'P' && (magicKey[1] == '5'))
|
|
||||||
{
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_GRAY_BINARY;
|
|
||||||
}
|
|
||||||
else if (magicKey[0] == 'P' && (magicKey[1] == '6'))
|
|
||||||
{
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == pnmType)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult ret = PnmLoadImage(file, pnmType, info, imgType, imgOrigin, image);
|
|
||||||
fclose(file);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HGResult PnmSaveImage(HGImage image, const HGChar* fileName, HGUInt pnmType)
|
|
||||||
{
|
|
||||||
FILE* file = fopen(fileName, "wb");
|
|
||||||
if (NULL == file)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "PnmSaveImage: fopen fail, %s errno=%d", fileName, errno);
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte* data = NULL;
|
|
||||||
HGBase_GetImageData(image, &data);
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
|
|
||||||
char magicKey[4] = {0};
|
|
||||||
if (HGIMGFMT_PNMTYPE_BINARY_ASCII == pnmType)
|
|
||||||
{
|
|
||||||
strcpy(magicKey, "P1\n");
|
|
||||||
}
|
|
||||||
else if (HGIMGFMT_PNMTYPE_GRAY_ASCII == pnmType)
|
|
||||||
{
|
|
||||||
strcpy(magicKey, "P2\n");
|
|
||||||
}
|
|
||||||
else if (HGIMGFMT_PNMTYPE_RGB_ASCII == pnmType)
|
|
||||||
{
|
|
||||||
strcpy(magicKey, "P3\n");
|
|
||||||
}
|
|
||||||
else if (HGIMGFMT_PNMTYPE_BINARY_BINARY == pnmType)
|
|
||||||
{
|
|
||||||
strcpy(magicKey, "P4\n");
|
|
||||||
}
|
|
||||||
else if (HGIMGFMT_PNMTYPE_GRAY_BINARY == pnmType)
|
|
||||||
{
|
|
||||||
strcpy(magicKey, "P5\n");
|
|
||||||
}
|
|
||||||
else if (HGIMGFMT_PNMTYPE_RGB_BINARY == pnmType)
|
|
||||||
{
|
|
||||||
strcpy(magicKey, "P6\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite(magicKey, 1, strlen(magicKey), file);
|
|
||||||
|
|
||||||
char width[20], height[20];
|
|
||||||
sprintf(width, "%u\n", imgInfo.width);
|
|
||||||
sprintf(height, "%u\n", imgInfo.height);
|
|
||||||
fwrite(width, 1, strlen(width), file);
|
|
||||||
fwrite(height, 1, strlen(height), file);
|
|
||||||
|
|
||||||
if (HGIMGFMT_PNMTYPE_BINARY_ASCII != pnmType && HGIMGFMT_PNMTYPE_BINARY_BINARY != pnmType)
|
|
||||||
{
|
|
||||||
char maxColor[] = "255\n";
|
|
||||||
fwrite(maxColor, 1, strlen(maxColor), file);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGByte* p = data;
|
|
||||||
HGInt step = (HGInt)imgInfo.widthStep;
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
||||||
{
|
|
||||||
p = data + (imgInfo.height - 1) * imgInfo.widthStep;
|
|
||||||
step = -(HGInt)imgInfo.widthStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
||||||
{
|
|
||||||
HGUInt lineSize = ((imgInfo.width + 7) & ~7) >> 3;
|
|
||||||
HGByte* buf = (HGByte*)malloc(lineSize);
|
|
||||||
if (NULL == buf)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
||||||
for (HGUInt j = 0; j < lineSize; ++j)
|
|
||||||
{
|
|
||||||
buf[j] = ~pEx[j]; // 黑白反色
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite(buf, 1, lineSize, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
|
||||||
{
|
|
||||||
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
||||||
fwrite(pEx, 1, imgInfo.width, file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
|
||||||
{
|
|
||||||
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
||||||
fwrite(pEx, 1, imgInfo.width * 3, file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII)
|
|
||||||
{
|
|
||||||
HGUInt w = imgInfo.width;
|
|
||||||
if (HGIMGFMT_PNMTYPE_RGB_ASCII == pnmType)
|
|
||||||
w = imgInfo.width * 3;
|
|
||||||
|
|
||||||
char *buf = (char *)malloc(w * 5 + 1);
|
|
||||||
if (NULL == buf)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pixelStr[256];
|
|
||||||
for (int i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
char str[6];
|
|
||||||
sprintf(str, "%d", i);
|
|
||||||
pixelStr[i] = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
||||||
{
|
|
||||||
int bufLen = 0;
|
|
||||||
int lineSize = 0;
|
|
||||||
|
|
||||||
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
||||||
for (HGUInt j = 0; j < w; ++j)
|
|
||||||
{
|
|
||||||
HGUInt idx;
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII)
|
|
||||||
idx = (0 == GetBit(pEx, j) ? 1 : 0);
|
|
||||||
else
|
|
||||||
idx = pEx[j];
|
|
||||||
|
|
||||||
if (0 != lineSize)
|
|
||||||
{
|
|
||||||
if (lineSize + pixelStr[idx].size() + 1 > 70)
|
|
||||||
{
|
|
||||||
buf[bufLen] = '\n';
|
|
||||||
++bufLen;
|
|
||||||
lineSize = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf[bufLen] = ' ';
|
|
||||||
++bufLen;
|
|
||||||
++lineSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(buf + bufLen, pixelStr[idx].c_str());
|
|
||||||
bufLen += (int)pixelStr[idx].size();
|
|
||||||
lineSize += (int)pixelStr[idx].size();
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[bufLen] = '\n';
|
|
||||||
++bufLen;
|
|
||||||
lineSize = 0;
|
|
||||||
|
|
||||||
fwrite(buf, 1, bufLen, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SavePnmImage(HGImage image, const HGPnmSaveInfo* info, const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL == image || NULL == fileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
if (info->type < HGIMGFMT_PNMTYPE_BINARY_ASCII || info->type > HGIMGFMT_PNMTYPE_RGB_BINARY)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
|
|
||||||
HGUInt pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
|
|
||||||
if (HGBASE_IMGTYPE_GRAY == imgInfo.type)
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_GRAY_BINARY;
|
|
||||||
else if (HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
||||||
pnmType = HGIMGFMT_PNMTYPE_BINARY_BINARY;
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
pnmType = info->type;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGUInt pnmType2 = 0;
|
|
||||||
HGImgFmt_GetPnmTypeFromFileName(fileName, &pnmType2);
|
|
||||||
if (0 != pnmType2)
|
|
||||||
{
|
|
||||||
pnmType = pnmType2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGUInt imgType = HGBASE_IMGTYPE_RGB;
|
|
||||||
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
||||||
imgType = HGBASE_IMGTYPE_BINARY;
|
|
||||||
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
|
||||||
imgType = HGBASE_IMGTYPE_GRAY;
|
|
||||||
|
|
||||||
if (imgInfo.type != imgType)
|
|
||||||
{
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGResult ret = HGBase_CloneImage(image, imgType, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (ret != HGBASE_ERR_OK)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = PnmSaveImage(image2, fileName, pnmType);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PnmSaveImage(image, fileName, pnmType);
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#ifndef __HGPNM_H__
|
|
||||||
#define __HGPNM_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
|
|
||||||
#define HGIMGFMT_PNMTYPE_BINARY_ASCII 1L
|
|
||||||
#define HGIMGFMT_PNMTYPE_BINARY_BINARY 2L
|
|
||||||
#define HGIMGFMT_PNMTYPE_GRAY_ASCII 3L
|
|
||||||
#define HGIMGFMT_PNMTYPE_GRAY_BINARY 4L
|
|
||||||
#define HGIMGFMT_PNMTYPE_RGB_ASCII 5L
|
|
||||||
#define HGIMGFMT_PNMTYPE_RGB_BINARY 6L
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 图像宽 */
|
|
||||||
HGUInt height; /* 图像高 */
|
|
||||||
HGUInt type; /* 类型 */
|
|
||||||
}HGPnmLoadInfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt type; /* 类型 */
|
|
||||||
}HGPnmSaveInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckPnmFile(const HGChar* fileName, HGBool* isPnm);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetPnmTypeFromFileName(const HGChar* fileName, HGUInt* pnmType);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadPnmImage(const HGChar* fileName, HGPnmLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SavePnmImage(HGImage image, const HGPnmSaveInfo* info, const HGChar* fileName);
|
|
||||||
|
|
||||||
#endif // __HGPNM_H__
|
|
|
@ -1,414 +0,0 @@
|
||||||
#include "HGTiff.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
#include "tiffio.h"
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CheckTiffFile(const HGChar* fileName, HGBool* isTiff)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == isTiff)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGTiffReader reader = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenTiffReader(fileName, &reader);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*isTiff = HGTRUE;
|
|
||||||
HGImgFmt_CloseTiffReader(reader);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_OpenTiffReader(const HGChar* fileName, HGTiffReader* reader)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 != _access(fileName, 0))
|
|
||||||
#else
|
|
||||||
if (0 != access(fileName, 0))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILENOTEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIFF* tif = TIFFOpen(fileName, "r");
|
|
||||||
if (NULL == tif)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FILEERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*reader = (HGTiffReader)tif;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CloseTiffReader(HGTiffReader reader)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIFF* tif = (TIFF*)reader;
|
|
||||||
TIFFClose(tif);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_GetTiffPageCount(HGTiffReader reader, HGUInt* count)
|
|
||||||
{
|
|
||||||
if (NULL == reader || NULL == count)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIFF* tif = (TIFF*)reader;
|
|
||||||
*count = TIFFNumberOfDirectories(tif);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadImageFromTiffReader(HGTiffReader reader, HGUInt index, HGTiffLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
if (NULL == reader)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == image)
|
|
||||||
{
|
|
||||||
if (0 != imgType || 0 != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TIFF* tif = (TIFF*)reader;
|
|
||||||
if (0 == TIFFSetDirectory(tif, index))
|
|
||||||
{
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 width;
|
|
||||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
|
|
||||||
uint32 height;
|
|
||||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
|
|
||||||
uint16 bitsPerSample;
|
|
||||||
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
|
|
||||||
uint16 samplesPerPixel;
|
|
||||||
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
|
|
||||||
uint16 compression;
|
|
||||||
TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
|
|
||||||
|
|
||||||
uint16 resolutionUnit;
|
|
||||||
TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resolutionUnit);
|
|
||||||
float xResolution;
|
|
||||||
TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xResolution);
|
|
||||||
float yResolution;
|
|
||||||
TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yResolution);
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
info->width = width;
|
|
||||||
info->height = height;
|
|
||||||
info->bitsPerSample = bitsPerSample;
|
|
||||||
info->samplesPerPixel = samplesPerPixel;
|
|
||||||
info->compression = compression;
|
|
||||||
info->resolutionUnit = resolutionUnit;
|
|
||||||
info->xResolution = xResolution;
|
|
||||||
info->yResolution = yResolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != image)
|
|
||||||
{
|
|
||||||
uint32* buffer = (uint32*)malloc(width * height * sizeof(uint32));
|
|
||||||
if (NULL == buffer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == TIFFReadRGBAImageOriented(tif, width, height, buffer, ORIENTATION_TOPLEFT))
|
|
||||||
{
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
return HGIMGFMT_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == imgType)
|
|
||||||
{
|
|
||||||
imgType = HGBASE_IMGTYPE_RGB;
|
|
||||||
if (4 == samplesPerPixel)
|
|
||||||
{
|
|
||||||
imgType = HGBASE_IMGTYPE_RGBA;
|
|
||||||
}
|
|
||||||
else if (1 == samplesPerPixel)
|
|
||||||
{
|
|
||||||
if (1 == bitsPerSample)
|
|
||||||
imgType = HGBASE_IMGTYPE_BINARY;
|
|
||||||
else
|
|
||||||
imgType = HGBASE_IMGTYPE_GRAY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgOrigin == 0)
|
|
||||||
{
|
|
||||||
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageInfo tiffImageInfo;
|
|
||||||
tiffImageInfo.width = width;
|
|
||||||
tiffImageInfo.height = height;
|
|
||||||
tiffImageInfo.type = HGBASE_IMGTYPE_RGBA;
|
|
||||||
tiffImageInfo.widthStep = width * 4;
|
|
||||||
tiffImageInfo.origin = HGBASE_IMGORIGIN_TOP;
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGResult ret = HGBase_CreateImageWithData((HGByte*)buffer, &tiffImageInfo, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RESUNIT_INCH == resolutionUnit)
|
|
||||||
{
|
|
||||||
uint32_t xDpi = (uint32_t)(xResolution + 0.5f);
|
|
||||||
uint32_t yDpi = (uint32_t)(yResolution + 0.5f);
|
|
||||||
HGBase_SetImageDpi(image2, xDpi, yDpi);
|
|
||||||
}
|
|
||||||
else if (RESUNIT_CENTIMETER == resolutionUnit)
|
|
||||||
{
|
|
||||||
uint32_t xDpi = (uint32_t)(xResolution / 0.393700787402 + 0.5);
|
|
||||||
uint32_t yDpi = (uint32_t)(yResolution / 0.393700787402 + 0.5);
|
|
||||||
HGBase_SetImageDpi(image2, xDpi, yDpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_LoadTiffImage(const HGChar* fileName, HGTiffLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
||||||
{
|
|
||||||
HGTiffReader reader = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenTiffReader(fileName, &reader);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGImgFmt_LoadImageFromTiffReader(reader, 0, info, imgType, imgOrigin, image);
|
|
||||||
HGImgFmt_CloseTiffReader(reader);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_OpenTiffWriter(const HGChar* fileName, HGTiffWriter* writer)
|
|
||||||
{
|
|
||||||
if (NULL == fileName || NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIFF* tif = TIFFOpen(fileName, "w");
|
|
||||||
if (NULL == tif)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGImgFmt_OpenTiffWriter: TIFFOpen fail, %s", fileName);
|
|
||||||
return HGBASE_ERR_ACCESSDENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*writer = (HGTiffWriter)tif;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_CloseTiffWriter(HGTiffWriter writer)
|
|
||||||
{
|
|
||||||
if (NULL == writer)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIFF* tif = (TIFF*)writer;
|
|
||||||
TIFFClose(tif);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveImageToTiffWriter(HGTiffWriter writer, HGImage image, const HGTiffSaveInfo* info)
|
|
||||||
{
|
|
||||||
if (NULL == writer || NULL == image)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
// 判断合法性
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
HGImageRoi roi;
|
|
||||||
HGBase_GetImageROI(image, &roi);
|
|
||||||
|
|
||||||
HGBase_ResetImageROI(image);
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
if (HGBASE_IMGTYPE_BGR == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_BGRA == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGBA, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, imgInfo.type, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_GetImageInfo(image2, &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;
|
|
||||||
uint8_t* data;
|
|
||||||
HGBase_GetImageData(image2, &data);
|
|
||||||
|
|
||||||
uint8 samplesPerPixel = 0;
|
|
||||||
uint8 bitsPerSample = 0;
|
|
||||||
if (HGBASE_IMGTYPE_BINARY == type)
|
|
||||||
{
|
|
||||||
samplesPerPixel = 1;
|
|
||||||
bitsPerSample = 1;
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_GRAY == type)
|
|
||||||
{
|
|
||||||
samplesPerPixel = 1;
|
|
||||||
bitsPerSample = 8;
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_RGB == type)
|
|
||||||
{
|
|
||||||
samplesPerPixel = 3;
|
|
||||||
bitsPerSample = 8;
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_RGBA == type)
|
|
||||||
{
|
|
||||||
samplesPerPixel = 4;
|
|
||||||
bitsPerSample = 8;
|
|
||||||
}
|
|
||||||
assert(0 != samplesPerPixel && 0 != bitsPerSample);
|
|
||||||
|
|
||||||
TIFF* tif = (TIFF*)writer;
|
|
||||||
|
|
||||||
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
|
|
||||||
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
|
|
||||||
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
|
|
||||||
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel);
|
|
||||||
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, (1 == samplesPerPixel) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB);
|
|
||||||
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
|
||||||
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, height);
|
|
||||||
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
|
||||||
|
|
||||||
if (NULL != info)
|
|
||||||
{
|
|
||||||
if ((HGBASE_IMGTYPE_BINARY == type && HGIMGFMT_TIFFCOMP_JPEG == info->compression)
|
|
||||||
|| (HGBASE_IMGTYPE_BINARY != type && HGIMGFMT_TIFFCOMP_CCITTFAX4 == info->compression))
|
|
||||||
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
|
|
||||||
else
|
|
||||||
TIFFSetField(tif, TIFFTAG_COMPRESSION, info->compression);
|
|
||||||
|
|
||||||
TIFFSetField(tif, TIFFTAG_JPEGQUALITY, info->jpegQuality);
|
|
||||||
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, info->resolutionUnit);
|
|
||||||
TIFFSetField(tif, TIFFTAG_XRESOLUTION, info->xResolution);
|
|
||||||
TIFFSetField(tif, TIFFTAG_YRESOLUTION, info->yResolution);
|
|
||||||
|
|
||||||
if (HGIMGFMT_TIFFCOMP_JPEG == info->compression && HGBASE_IMGTYPE_RGB == type)
|
|
||||||
{
|
|
||||||
TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
|
||||||
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image, &xDpi, &yDpi);
|
|
||||||
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
|
|
||||||
TIFFSetField(tif, TIFFTAG_JPEGQUALITY, 80);
|
|
||||||
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
|
|
||||||
TIFFSetField(tif, TIFFTAG_XRESOLUTION, xDpi);
|
|
||||||
TIFFSetField(tif, TIFFTAG_YRESOLUTION, yDpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#pragma omp parallel for
|
|
||||||
for (int32_t i = 0; i < (int32_t)height; ++i)
|
|
||||||
{
|
|
||||||
uint8_t* pEx = data + (HGSize)i * (HGSize)widthStep;
|
|
||||||
TIFFWriteScanline(tif, pEx, i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_SetImageROI(image, &roi);
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
image2 = NULL;
|
|
||||||
TIFFWriteDirectory(tif);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgFmt_SaveTiffImage(HGImage image, const HGTiffSaveInfo* info, const HGChar* fileName)
|
|
||||||
{
|
|
||||||
HGTiffWriter writer = NULL;
|
|
||||||
HGResult ret = HGImgFmt_OpenTiffWriter(fileName, &writer);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = HGImgFmt_SaveImageToTiffWriter(writer, image, info);
|
|
||||||
HGImgFmt_CloseTiffWriter(writer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
#ifndef __HGTIFF_H__
|
|
||||||
#define __HGTIFF_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgFmtErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGTiffReader);
|
|
||||||
HG_DECLARE_HANDLE(HGTiffWriter);
|
|
||||||
|
|
||||||
/* 压缩方式 */
|
|
||||||
#define HGIMGFMT_TIFFCOMP_NONE 1L
|
|
||||||
#define HGIMGFMT_TIFFCOMP_CCITTFAX4 4L
|
|
||||||
#define HGIMGFMT_TIFFCOMP_LZW 5L
|
|
||||||
#define HGIMGFMT_TIFFCOMP_JPEG 7L
|
|
||||||
|
|
||||||
/* 分辨率单位 */
|
|
||||||
#define HGIMGFMT_TIFFRESUNIT_NONE 1L
|
|
||||||
#define HGIMGFMT_TIFFRESUNIT_INCH 2L /* 英寸 */
|
|
||||||
#define HGIMGFMT_TIFFRESUNIT_CENTIMETER 3L /* 厘米 */
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt width; /* 图像宽 */
|
|
||||||
HGUInt height; /* 图像高 */
|
|
||||||
HGUShort bitsPerSample; /* 每个采样的比特数 */
|
|
||||||
HGUShort samplesPerPixel; /* 每个像素的采样数 */
|
|
||||||
HGUShort compression; /* 压缩方式, 见HGIMGFMT_TIFFCOMP_* */
|
|
||||||
HGUShort resolutionUnit; /* 分辨率单位, 见HGIMGFMT_TIFFRESUNIT_* */
|
|
||||||
HGFloat xResolution; /* 分辨率x值 */
|
|
||||||
HGFloat yResolution; /* 分辨率y值 */
|
|
||||||
}HGTiffLoadInfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGUInt compression; /* 压缩方式, 见HGIMGFMT_TIFFCOMP_* */
|
|
||||||
HGUInt jpegQuality; /* jpeg压缩质量, 0-100 */
|
|
||||||
HGUShort resolutionUnit; /* 分辨率单位, 见HGIMGFMT_TIFFRESUNIT_* */
|
|
||||||
HGFloat xResolution; /* 分辨率x值 */
|
|
||||||
HGFloat yResolution; /* 分辨率y值 */
|
|
||||||
}HGTiffSaveInfo;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CheckTiffFile(const HGChar* fileName, HGBool* isTiff);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenTiffReader(const HGChar* fileName, HGTiffReader* reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseTiffReader(HGTiffReader reader);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_GetTiffPageCount(HGTiffReader reader, HGUInt* count);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadImageFromTiffReader(HGTiffReader reader, HGUInt index, HGTiffLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_LoadTiffImage(const HGChar* fileName, HGTiffLoadInfo* info,
|
|
||||||
HGUInt imgType, HGUInt imgOrigin, HGImage* image);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_OpenTiffWriter(const HGChar* fileName, HGTiffWriter* writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_CloseTiffWriter(HGTiffWriter writer);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveImageToTiffWriter(HGTiffWriter writer, HGImage image, const HGTiffSaveInfo* info);
|
|
||||||
|
|
||||||
HGEXPORT HGResult HGAPI HGImgFmt_SaveTiffImage(HGImage image, const HGTiffSaveInfo* info, const HGChar* fileName);
|
|
||||||
|
|
||||||
#endif /* __HGTIFF_H__ */
|
|
|
@ -1,463 +0,0 @@
|
||||||
#include "CvxText.hpp"
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
CvxText::CvxText()
|
|
||||||
{
|
|
||||||
m_library = NULL;
|
|
||||||
m_face = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CvxText::~CvxText()
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult CvxText::Create(const HGChar* fontPath)
|
|
||||||
{
|
|
||||||
if (NULL != m_face)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Init_FreeType(&m_library);
|
|
||||||
if (NULL == m_library)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_New_Face(m_library, fontPath, 0, &m_face);
|
|
||||||
if (NULL == m_face)
|
|
||||||
{
|
|
||||||
FT_Done_FreeType(m_library);
|
|
||||||
m_library = NULL;
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult CvxText::Destroy()
|
|
||||||
{
|
|
||||||
if (NULL == m_face)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Done_Face(m_face);
|
|
||||||
m_face = NULL;
|
|
||||||
FT_Done_FreeType(m_library);
|
|
||||||
m_library = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HGResult CvxText::DrawString(HGImage image, const HGChar* text, HGColor color, HGUInt posType, HGInt locationX, HGInt locationY,
|
|
||||||
HGUInt fontSize, HGBool bold, HGBool underline, HGBool italic, HGBool strikeout)
|
|
||||||
{
|
|
||||||
if (NULL == m_face)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(NULL != image);
|
|
||||||
assert(NULL != text && '\0' != *text);
|
|
||||||
assert(posType >= HGIMGPROC_WMPOSTYPE_LEFT && posType <= HGIMGPROC_WMPOSTYPE_LOCATION);
|
|
||||||
assert(0 != fontSize);
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
if (HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
||||||
{
|
|
||||||
HGImage imageTmp = NULL;
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
|
|
||||||
if (HGBASE_ERR_OK == ret)
|
|
||||||
{
|
|
||||||
ret = DrawString(imageTmp, text, color, posType, locationX, locationY, fontSize, bold, underline, italic, strikeout);
|
|
||||||
HGBase_DestroyImage(imageTmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGUInt width, height;
|
|
||||||
std::vector<HGRect> vPos;
|
|
||||||
GetStringLocation(text, fontSize, bold, underline, italic, strikeout, width, height, vPos);
|
|
||||||
|
|
||||||
if (HGIMGPROC_WMPOSTYPE_LOCATION == posType)
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
WCHAR* pUnicode = GetUnicodeStr(text);
|
|
||||||
#else
|
|
||||||
uint16_t* pUnicode = GetUnicodeStr(text);
|
|
||||||
uint16_t* pUnicodeEx = pUnicode + 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
while ('\0' != pUnicode[i])
|
|
||||||
#else
|
|
||||||
while ('\0' != pUnicodeEx[i])
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
DrawChar(image, pUnicode[i], color, locationX + vPos[i].left, locationY + vPos[i].top, fontSize, bold, italic);
|
|
||||||
#else
|
|
||||||
DrawChar(image, pUnicodeEx[i], color, locationX + vPos[i].left, locationY + vPos[i].top, fontSize, bold, italic);
|
|
||||||
#endif
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] pUnicode;
|
|
||||||
|
|
||||||
if (underline)
|
|
||||||
{
|
|
||||||
HGImgProc_ImageDrawLine(image, locationX, locationY + height - 1,
|
|
||||||
locationX + width, locationY + height - 1, color, 1, HGIMGPROC_LINETYPE_SOLID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strikeout)
|
|
||||||
{
|
|
||||||
if (underline)
|
|
||||||
HGImgProc_ImageDrawLine(image, locationX, locationY + (height - 1) / 2,
|
|
||||||
locationX + width, locationY + (height - 1) / 2, color, 1, HGIMGPROC_LINETYPE_SOLID);
|
|
||||||
else
|
|
||||||
HGImgProc_ImageDrawLine(image, locationX, locationY + height / 2,
|
|
||||||
locationX + width, locationY + height / 2, color, 1, HGIMGPROC_LINETYPE_SOLID);
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageRoi imgRoi;
|
|
||||||
HGBase_GetImageROI(image, &imgRoi);
|
|
||||||
HGInt roiWidth = imgRoi.right - imgRoi.left;
|
|
||||||
HGInt roiHeight = imgRoi.bottom - imgRoi.top;
|
|
||||||
|
|
||||||
HGInt x, y;
|
|
||||||
if (HGIMGPROC_WMPOSTYPE_LEFT == posType)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y = (roiHeight - height) / 2;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_WMPOSTYPE_TOP == posType)
|
|
||||||
{
|
|
||||||
x = (roiWidth - width) / 2;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_WMPOSTYPE_RIGHT == posType)
|
|
||||||
{
|
|
||||||
x = roiWidth - width;
|
|
||||||
y = (roiHeight - height) / 2;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_WMPOSTYPE_BOTTOM == posType)
|
|
||||||
{
|
|
||||||
x = (roiWidth - width) / 2;
|
|
||||||
y = roiHeight - height;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_WMPOSTYPE_LEFTTOP == posType)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_WMPOSTYPE_RIGHTTOP == posType)
|
|
||||||
{
|
|
||||||
x = roiWidth - width;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_WMPOSTYPE_LEFTBOTTOM == posType)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y = roiHeight - height;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_WMPOSTYPE_RIGHTBOTTOM == posType)
|
|
||||||
{
|
|
||||||
x = roiWidth - width;
|
|
||||||
y = roiHeight - height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = (roiWidth - width) / 2;
|
|
||||||
y = (roiHeight - height) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DrawString(image, text, color, HGIMGPROC_WMPOSTYPE_LOCATION, x, y, fontSize, bold, underline, italic, strikeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CvxText::MeasureChar(HGUInt wc, HGUInt fontSize, HGBool bold, HGBool italic, FT_BBox& acbox)
|
|
||||||
{
|
|
||||||
assert(NULL != m_face);
|
|
||||||
assert(0 != fontSize);
|
|
||||||
|
|
||||||
FT_Set_Pixel_Sizes(m_face, fontSize, fontSize);
|
|
||||||
FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);
|
|
||||||
FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
|
|
||||||
|
|
||||||
if (bold)
|
|
||||||
{
|
|
||||||
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
||||||
{
|
|
||||||
FT_Outline_Embolden(&m_face->glyph->outline, fontSize * 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (italic)
|
|
||||||
{
|
|
||||||
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
||||||
{
|
|
||||||
FT_Matrix matrix;
|
|
||||||
matrix.xx = 0x10000L;
|
|
||||||
matrix.xy = 0.4f * 0x10000L;
|
|
||||||
matrix.yx = 0;
|
|
||||||
matrix.yy = 0x10000L;
|
|
||||||
FT_Outline_Transform(&m_face->glyph->outline, &matrix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
|
||||||
{
|
|
||||||
FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Glyph glyph;
|
|
||||||
FT_Get_Glyph(m_face->glyph, &glyph);
|
|
||||||
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &acbox);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CvxText::GetStringLocation(const HGChar* text, HGUInt fontSize, HGBool bold, HGBool underline, HGBool italic, HGBool strikeout,
|
|
||||||
HGUInt& width, HGUInt& height, std::vector<HGRect> &vPos)
|
|
||||||
{
|
|
||||||
assert(NULL != text && '\0' != *text);
|
|
||||||
assert(0 != fontSize);
|
|
||||||
|
|
||||||
width = 0;
|
|
||||||
height = 0;
|
|
||||||
vPos.clear();
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
WCHAR* pUnicode = GetUnicodeStr(text);
|
|
||||||
#else
|
|
||||||
uint16_t* pUnicode = GetUnicodeStr(text);
|
|
||||||
uint16_t* pUnicodeEx = pUnicode + 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HGInt origin = 0;
|
|
||||||
HGInt minY = INT_MAX, maxY = INT_MIN;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
while ('\0' != pUnicode[i])
|
|
||||||
#else
|
|
||||||
while ('\0' != pUnicodeEx[i])
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
FT_BBox acbox;
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
MeasureChar(pUnicode[i], fontSize, bold, italic, acbox);
|
|
||||||
#else
|
|
||||||
MeasureChar(pUnicodeEx[i], fontSize, bold, italic, acbox);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HGRect pos;
|
|
||||||
pos.left = origin + acbox.xMin;
|
|
||||||
pos.right = origin + acbox.xMax;
|
|
||||||
pos.top = -acbox.yMax;
|
|
||||||
pos.bottom = -acbox.yMin;
|
|
||||||
vPos.push_back(pos);
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (pUnicode[i] < 255 && (!isprint((int)pUnicode[i]) || isspace((int)pUnicode[i])))
|
|
||||||
#else
|
|
||||||
if (pUnicodeEx[i] < 255 && (!isprint((int)pUnicodeEx[i]) || isspace((int)pUnicodeEx[i])))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
origin += fontSize / 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
origin += (acbox.xMax + acbox.xMin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acbox.yMin < minY)
|
|
||||||
minY = acbox.yMin;
|
|
||||||
if (acbox.yMax > maxY)
|
|
||||||
maxY = acbox.yMax;
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] pUnicode;
|
|
||||||
|
|
||||||
width = origin;
|
|
||||||
height = (maxY - minY);
|
|
||||||
if (underline)
|
|
||||||
++height;
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)vPos.size(); ++i)
|
|
||||||
{
|
|
||||||
vPos[i].top += maxY;
|
|
||||||
vPos[i].bottom += maxY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CvxText::DrawChar(HGImage image, HGUInt wc, HGColor color, HGInt x, HGInt y, HGUInt fontSize, HGBool bold, HGBool italic)
|
|
||||||
{
|
|
||||||
assert(NULL != m_face);
|
|
||||||
assert(NULL != image);
|
|
||||||
assert(0 != fontSize);
|
|
||||||
|
|
||||||
FT_Set_Pixel_Sizes(m_face, fontSize, fontSize);
|
|
||||||
FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);
|
|
||||||
FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
|
|
||||||
|
|
||||||
if (bold)
|
|
||||||
{
|
|
||||||
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
||||||
{
|
|
||||||
FT_Outline_Embolden(&m_face->glyph->outline, fontSize * 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (italic)
|
|
||||||
{
|
|
||||||
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
||||||
{
|
|
||||||
FT_Matrix matrix;
|
|
||||||
matrix.xx = 0x10000L;
|
|
||||||
matrix.xy = 0.4f * 0x10000L;
|
|
||||||
matrix.yx = 0;
|
|
||||||
matrix.yy = 0x10000L;
|
|
||||||
FT_Outline_Transform(&m_face->glyph->outline, &matrix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
|
||||||
{
|
|
||||||
FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
uint32_t imgWidth = imgInfo.width;
|
|
||||||
uint32_t imgHeight = imgInfo.height;
|
|
||||||
uint32_t imgWidthStep = imgInfo.widthStep;
|
|
||||||
uint32_t imgType = imgInfo.type;
|
|
||||||
|
|
||||||
uint8_t *imgData;
|
|
||||||
HGBase_GetImageData(image, &imgData);
|
|
||||||
|
|
||||||
int32_t imgChannel = 0;
|
|
||||||
if (HGBASE_IMGTYPE_GRAY == imgType)
|
|
||||||
imgChannel = 1;
|
|
||||||
else if (HGBASE_IMGTYPE_RGB == imgType || HGBASE_IMGTYPE_BGR == imgType)
|
|
||||||
imgChannel = 3;
|
|
||||||
else if (HGBASE_IMGTYPE_RGBA == imgType || HGBASE_IMGTYPE_BGRA == imgType)
|
|
||||||
imgChannel = 4;
|
|
||||||
assert(0 != imgChannel);
|
|
||||||
|
|
||||||
HGImageRoi imgRoi;
|
|
||||||
HGBase_GetImageROI(image, &imgRoi);
|
|
||||||
uint32_t imgLeft = imgRoi.left;
|
|
||||||
uint32_t imgTop = imgRoi.top;
|
|
||||||
uint32_t imgRight = imgRoi.right;
|
|
||||||
uint32_t imgBottom = imgRoi.bottom;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_face->glyph->bitmap.rows; ++i)
|
|
||||||
{
|
|
||||||
for (unsigned int j = 0; j < m_face->glyph->bitmap.width; ++j)
|
|
||||||
{
|
|
||||||
int32_t xOffset = (int32_t)imgLeft + x + (int32_t)j;
|
|
||||||
int32_t yOffset = (int32_t)imgTop + y + (int32_t)i;
|
|
||||||
|
|
||||||
if (xOffset >= (int32_t)imgLeft && xOffset < (int32_t)imgRight
|
|
||||||
&& yOffset >= (int32_t)imgTop && yOffset < (int32_t)imgBottom)
|
|
||||||
{
|
|
||||||
uint8_t *p = m_face->glyph->bitmap.buffer + m_face->glyph->bitmap.pitch * i + j;
|
|
||||||
int32_t opacity = HG_GETCOLOR_A(color) * (*p) / 255;
|
|
||||||
|
|
||||||
uint8_t *pEx = imgData + yOffset * imgWidthStep + xOffset * imgChannel;
|
|
||||||
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
||||||
pEx = imgData + (imgHeight - yOffset - 1) * imgWidthStep + xOffset * imgChannel;
|
|
||||||
|
|
||||||
if (HGBASE_IMGTYPE_RGB == imgType || HGBASE_IMGTYPE_RGBA == imgType)
|
|
||||||
{
|
|
||||||
int32_t v0 = HG_GETCOLOR_R(color);
|
|
||||||
int32_t vDest0 = pEx[0];
|
|
||||||
int32_t value0 = (v0 - vDest0) * opacity;
|
|
||||||
pEx[0] = (uint8_t)(vDest0 + (((value0 << 8) + value0) >> 16));
|
|
||||||
|
|
||||||
int32_t v1 = HG_GETCOLOR_G(color);
|
|
||||||
int32_t vDest1 = pEx[1];
|
|
||||||
int32_t value1 = (v1 - vDest1) * opacity;
|
|
||||||
pEx[1] = (uint8_t)(vDest1 + (((value1 << 8) + value1) >> 16));
|
|
||||||
|
|
||||||
int32_t v2 = HG_GETCOLOR_B(color);
|
|
||||||
int32_t vDest2 = pEx[2];
|
|
||||||
int32_t value2 = (v2 - vDest2) * opacity;
|
|
||||||
pEx[2] = (uint8_t)(vDest2 + (((value2 << 8) + value2) >> 16));
|
|
||||||
}
|
|
||||||
else if (HGBASE_IMGTYPE_BGR == imgType || HGBASE_IMGTYPE_BGRA == imgType)
|
|
||||||
{
|
|
||||||
int32_t v0 = HG_GETCOLOR_B(color);
|
|
||||||
int32_t vDest0 = pEx[0];
|
|
||||||
int32_t value0 = (v0 - vDest0) * opacity;
|
|
||||||
pEx[0] = (uint8_t)(vDest0 + (((value0 << 8) + value0) >> 16));
|
|
||||||
|
|
||||||
int32_t v1 = HG_GETCOLOR_G(color);
|
|
||||||
int32_t vDest1 = pEx[1];
|
|
||||||
int32_t value1 = (v1 - vDest1) * opacity;
|
|
||||||
pEx[1] = (uint8_t)(vDest1 + (((value1 << 8) + value1) >> 16));
|
|
||||||
|
|
||||||
int32_t v2 = HG_GETCOLOR_R(color);
|
|
||||||
int32_t vDest2 = pEx[2];
|
|
||||||
int32_t value2 = (v2 - vDest2) * opacity;
|
|
||||||
pEx[2] = (uint8_t)(vDest2 + (((value2 << 8) + value2) >> 16));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int32_t v = (HG_GETCOLOR_R(color) * 76 + HG_GETCOLOR_G(color) * 150 + HG_GETCOLOR_B(color) * 30) >> 8;
|
|
||||||
int32_t vDest = *pEx;
|
|
||||||
int32_t value = (v - vDest) * opacity;
|
|
||||||
*pEx = (uint8_t)(vDest + (((value << 8) + value) >> 16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
#ifndef __CVXTEXT_H__
|
|
||||||
#define __CVXTEXT_H__
|
|
||||||
|
|
||||||
#include "HGImgProc.h"
|
|
||||||
#include <ft2build.h>
|
|
||||||
#include <freetype/freetype.h>
|
|
||||||
#include <freetype/ftbitmap.h>
|
|
||||||
#include <freetype/ftoutln.h>
|
|
||||||
#include <freetype/ftglyph.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class CvxText
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CvxText();
|
|
||||||
~CvxText();
|
|
||||||
|
|
||||||
HGResult Create(const HGChar *fontPath);
|
|
||||||
HGResult Destroy();
|
|
||||||
HGResult DrawString(HGImage image, const HGChar* text, HGColor color, HGUInt posType, HGInt locationX, HGInt locationY,
|
|
||||||
HGUInt fontSize, HGBool bold, HGBool underline, HGBool italic, HGBool strikeout);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void MeasureChar(HGUInt wc, HGUInt fontSize, HGBool bold, HGBool italic, FT_BBox& acbox);
|
|
||||||
void GetStringLocation(const HGChar* text, HGUInt fontSize, HGBool bold, HGBool underline, HGBool italic, HGBool strikeout,
|
|
||||||
HGUInt &width, HGUInt &height, std::vector<HGRect> &vPos);
|
|
||||||
void DrawChar(HGImage image, HGUInt wc, HGColor color, HGInt x, HGInt y, HGUInt fontSize, HGBool bold, HGBool italic);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FT_Library m_library;
|
|
||||||
FT_Face m_face;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __CVXTEXT_H__ */
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,205 +0,0 @@
|
||||||
#ifndef __HGIMGPROC_H__
|
|
||||||
#define __HGIMGPROC_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgProcErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
|
|
||||||
/* 最近邻插值 */
|
|
||||||
#define HGIMGPROC_INTERPOTYPE_NN 1L
|
|
||||||
/* 双线性插值 */
|
|
||||||
#define HGIMGPROC_INTERPOTYPE_LINEAR 2L
|
|
||||||
|
|
||||||
/* 线条类型-实线 */
|
|
||||||
#define HGIMGPROC_LINETYPE_SOLID 1L
|
|
||||||
/* 线条类型-虚线 */
|
|
||||||
#define HGIMGPROC_LINETYPE_DASH 2L
|
|
||||||
|
|
||||||
/* 水印位置-左侧 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_LEFT 1L
|
|
||||||
/* 水印位置-上侧 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_TOP 2L
|
|
||||||
/* 水印位置-右侧 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_RIGHT 3L
|
|
||||||
/* 水印位置-下侧 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_BOTTOM 4L
|
|
||||||
/* 水印位置-左上 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_LEFTTOP 5L
|
|
||||||
/* 水印位置-右上 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_RIGHTTOP 6L
|
|
||||||
/* 水印位置-左下 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_LEFTBOTTOM 7L
|
|
||||||
/* 水印位置-右下 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_RIGHTBOTTOM 8L
|
|
||||||
/* 水印位置-中间 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_CENTER 9L
|
|
||||||
/* 水印位置-自定义 */
|
|
||||||
#define HGIMGPROC_WMPOSTYPE_LOCATION 10L
|
|
||||||
|
|
||||||
/* 内部去污 */
|
|
||||||
#define HGIMGPROC_DECOTYPE_INSIDE 1L
|
|
||||||
/* 外部去污 */
|
|
||||||
#define HGIMGPROC_DECOTYPE_OUTSIDE 2L
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(4)
|
|
||||||
|
|
||||||
/* 自动裁剪参数 */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGBool convex; /* 黑底填充时的填充方式, HGTRUE为凸多边形填充,HGFALSE为凹多边形填充,默认HGTRUE */
|
|
||||||
HGBool fillColor; /* 黑底填充时采用自适应色彩填充,HGFALSE为白色填充,HGTRUE为自适应文稿底色填充,默认HGFALSE */
|
|
||||||
HGDouble threshold; /* 二值化阈值,取值范围(0, 255),默认40 */
|
|
||||||
HGInt noise; /* 除噪像素,能够消除noise宽度的背景竖条纹干扰,默认8 */
|
|
||||||
HGInt indent; /* 轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认5 */
|
|
||||||
HGBool normalCrop; /* crop deskew fillBlank失效,固定裁切采用最传统的裁切方式,默认HGFALSE */
|
|
||||||
HGBool dispersion; /* 是否除色散,默认HGTRUE */
|
|
||||||
}HGImgAutoCropParam;
|
|
||||||
|
|
||||||
/* 白底检查参数 */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGDouble threshold; /* 默认40 */
|
|
||||||
HGInt edge; /* 默认150 */
|
|
||||||
HGInt blockSize; /* 默认10 */
|
|
||||||
HGDouble devTh; /* 默认50 */
|
|
||||||
HGDouble meanTh; /* 默认200 */
|
|
||||||
}HGImgBlankCheckParam;
|
|
||||||
|
|
||||||
/* 水印字体参数 */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGChar foneName[64]; /* 字体名, windows上为GBK编码, linux上为UTF8编码, 默认宋体 */
|
|
||||||
HGUInt fontSize; /* 字号, 默认20 */
|
|
||||||
HGBool bold; /* 是否粗体, 默认HGFALSE */
|
|
||||||
HGBool underline; /* 是否有下划线, 默认HGFALSE */
|
|
||||||
HGBool italic; /* 是否斜体, 默认HGFALSE */
|
|
||||||
HGBool strikeout; /* 是否有删除线, 默认HGFALSE */
|
|
||||||
}HGImgWatermarkFontParam;
|
|
||||||
|
|
||||||
/* 去底色参数 */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
HGInt threshold; /* 默认100 */
|
|
||||||
HGInt offset; /* 默认0 */
|
|
||||||
HGInt range; /* 默认40 */
|
|
||||||
}HGImgFaceBkColorParam;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
/* 图像缩放
|
|
||||||
* 参数:
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 3) interpolation: in, 插值方式, 参见HGIMGPROC_INTERPOTYPE_*
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage不能是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ResizeImage(HGImage image, HGImage destImage, HGUInt interp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 图像色彩调整
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 3) brightness: in, 亮度增加值, -255至255之间
|
|
||||||
* 4) contrast: in, 对比度增加值, -127至127之间
|
|
||||||
* 5) gamma: 伽马增加值, 0.1至5.0之间
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, ROI区域的大小必须一致
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageAdjustColors(HGImage image, HGImage destImage,
|
|
||||||
HGInt brightness, HGInt contrast, HGFloat gamma);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 图像自动裁剪
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) autoCrop: in, 是否自动裁剪, 为HGTRUE则忽略destWidth和destHeight
|
|
||||||
* 3) deskew: in, 是否纠偏
|
|
||||||
* 4) fillBlank: in, 是否进行黑底填充
|
|
||||||
* 5) param: in, 参数, 为NULL时使用默认参数
|
|
||||||
* 6) destWidth: in, 目标图像宽度
|
|
||||||
* 7) destHeight: in, 目标图像高度
|
|
||||||
* 8) destType: in, 目标图像类型, 0表示和image一样
|
|
||||||
* 9) destOrigin: in, 目标图像数据排列方式, 0表示和image一样
|
|
||||||
* 10) destImage: out, 输出的目标图像句柄, 不用的时候需要调用HGBase_DestroyImage销毁
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是image的ROI区域
|
|
||||||
*/
|
|
||||||
HGEXPORT 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);
|
|
||||||
|
|
||||||
/* 判断图像是否是空白
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) param: in, 参数, 为NULL时使用默认参数
|
|
||||||
* 3) blank: out, HGTRUE为空白图像, HGFALSE为非空白图像
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是image的ROI区域
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageBlankCheck(HGImage image, const HGImgBlankCheckParam *param, HGBool *blank);
|
|
||||||
|
|
||||||
/* 图像画线
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) x1: in, 第一个点x坐标
|
|
||||||
* 3) y1: in, 第一个点y坐标
|
|
||||||
* 4) x2: in, 第二个点x坐标
|
|
||||||
* 5) y2: in, 第二个点y坐标
|
|
||||||
* 6) color: in, 颜色
|
|
||||||
* 7) width: in, 线宽
|
|
||||||
* 8) type: in, 表示线类型, 参见HGIMGPROC_LINETYPE_*
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageDrawLine(HGImage image, HGInt x1, HGInt y1, HGInt x2, HGInt y2,
|
|
||||||
HGColor color, HGUInt width, HGUInt type);
|
|
||||||
|
|
||||||
/* 添加图像水印
|
|
||||||
* 1) image: in, 图像句柄
|
|
||||||
* 2) text: 水印文本, windows上为GBK编码, linux上为UTF8编码
|
|
||||||
* 3) color: 颜色
|
|
||||||
* 4) posType: 位置, 见HGIMGPROC_WMPOSTYPE_*
|
|
||||||
* 5) locationX: 当posType为HGIMGPROC_WMPOSTYPE_LOCATION时表示x坐标
|
|
||||||
* 6) locationY: 当posType为HGIMGPROC_WMPOSTYPE_LOCATION时表示y坐标
|
|
||||||
* 7) fontParam: 字体参数, 为NULL时使用默认参数
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_AddImageWatermark(HGImage image, const HGChar *text, HGColor color, HGUInt posType,
|
|
||||||
HGInt locationX, HGInt locationY, const HGImgWatermarkFontParam *fontParam);
|
|
||||||
|
|
||||||
/* 消除文稿纸张底色
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 3) param: in, 参数, 为NULL时使用默认参数
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, ROI区域的大小必须一致
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageFadeBkColor(HGImage image, HGImage destImage, const HGImgFaceBkColorParam *param);
|
|
||||||
|
|
||||||
/* 图像去污
|
|
||||||
* 1) image: in, 源图像句柄
|
|
||||||
* 2) destImage: in, 目标图像句柄
|
|
||||||
* 3) decoType: in, 去污类型, 参见HGIMGPROC_DECOTYPE_*
|
|
||||||
* 4) x: in, 选择区域的x坐标
|
|
||||||
* 5) y: in, 选择区域的y坐标
|
|
||||||
* 6) width: in, 选择区域的宽
|
|
||||||
* 7) height: in, 选择区域的高
|
|
||||||
* 说明:
|
|
||||||
* 1) 操作的只是图像的ROI区域, ROI区域的大小必须一致
|
|
||||||
* 2) 源图像和目标图像的type必须一样
|
|
||||||
* 3) 自动处理origon不一致的情况
|
|
||||||
* 4) image和destImage可以是同一个句柄
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageDecontamination(HGImage image, HGImage destImage, HGUInt decoType, HGUInt x, HGUInt y,
|
|
||||||
HGUInt width, HGUInt height, HGColor color);
|
|
||||||
|
|
||||||
#endif /* __HGIMGPROC_H__ */
|
|
|
@ -1,13 +0,0 @@
|
||||||
#ifndef __HGIMGPROCERR_H__
|
|
||||||
#define __HGIMGPROCERR_H__
|
|
||||||
|
|
||||||
/* 一般错误 */
|
|
||||||
#define HGIMGPROC_ERR_FAIL 0x00003001L
|
|
||||||
|
|
||||||
/* OCR初始化错误 */
|
|
||||||
#define HGIMGPROC_ERR_OCRINIT 0x00003002L
|
|
||||||
|
|
||||||
/* OCR错误 */
|
|
||||||
#define HGIMGPROC_ERR_OCR 0x00003003L
|
|
||||||
|
|
||||||
#endif /* __HGIMGPROCERR_H__ */
|
|
|
@ -1,188 +0,0 @@
|
||||||
#include "HGOCR.h"
|
|
||||||
#include "HGOCRBase.hpp"
|
|
||||||
#include "HGOCRHanvon.hpp"
|
|
||||||
#include "HGOCRTesseract.hpp"
|
|
||||||
#include "HGOCRRetImpl.hpp"
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_CreateOCRMgr(HGUInt algo, HGOCRMgr* ocrMgr)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HGIMGPROC_OCRALGO_DEFAULT == algo)
|
|
||||||
{
|
|
||||||
HGOCRBase* ocrMgrImpl = new HGOCRHanvon;
|
|
||||||
HGResult ret = ocrMgrImpl->Init();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete ocrMgrImpl;
|
|
||||||
ocrMgrImpl = new HGOCRTesseract;
|
|
||||||
ret = ocrMgrImpl->Init();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete ocrMgrImpl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*ocrMgr = (HGOCRMgr)ocrMgrImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_OCRALGO_HANVON == algo)
|
|
||||||
{
|
|
||||||
HGOCRBase* ocrMgrImpl = new HGOCRHanvon;
|
|
||||||
HGResult ret = ocrMgrImpl->Init();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete ocrMgrImpl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ocrMgr = (HGOCRMgr)ocrMgrImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_OCRALGO_TESSERACT == algo)
|
|
||||||
{
|
|
||||||
HGOCRBase* ocrMgrImpl = new HGOCRTesseract;
|
|
||||||
HGResult ret = ocrMgrImpl->Init();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
delete ocrMgrImpl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ocrMgr = (HGOCRMgr)ocrMgrImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_DestroyOCRMgr(HGOCRMgr ocrMgr)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRBase* ocrMgrImpl = (HGOCRBase*)ocrMgr;
|
|
||||||
HGResult ret = ocrMgrImpl->Deinit();
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete ocrMgrImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_ImageOCR(HGOCRMgr ocrMgr, HGImage image, HGOCRRet* ocrRet)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRBase* ocrMgrImpl = (HGOCRBase*)ocrMgr;
|
|
||||||
HGOCRRetImpl* ocrRetImpl = NULL;
|
|
||||||
HGResult ret = ocrMgrImpl->ImageOCR(image, &ocrRetImpl);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
assert(NULL == ocrRetImpl);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ocrRet = (HGOCRRet)ocrRetImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_DestroyOCRRet(HGOCRRet ocrRet)
|
|
||||||
{
|
|
||||||
if (NULL == ocrRet)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRRetImpl* ocrRetImpl = (HGOCRRetImpl*)ocrRet;
|
|
||||||
delete ocrRetImpl;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_GetOCRRetBlockCount(HGOCRRet ocrRet, HGUInt* count)
|
|
||||||
{
|
|
||||||
if (NULL == ocrRet)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRRetImpl* ocrRetImpl = (HGOCRRetImpl*)ocrRet;
|
|
||||||
return ocrRetImpl->GetBlockCount(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_GetOCRRetBlockText(HGOCRRet ocrRet, HGUInt index, const HGChar** text)
|
|
||||||
{
|
|
||||||
if (NULL == ocrRet)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRRetImpl* ocrRetImpl = (HGOCRRetImpl*)ocrRet;
|
|
||||||
return ocrRetImpl->GetBlockText(index, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_ImageOCRToFile(HGOCRMgr ocrMgr, HGImage image, HGUInt outType, const HGChar* outFileName)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRBase* ocrMgrImpl = (HGOCRBase*)ocrMgr;
|
|
||||||
return ocrMgrImpl->ImageOCRToFile(image, outType, outFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_ImageTextDirectOCR(HGOCRMgr ocrMgr, HGImage image, HGUInt* direct)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRBase* ocrMgrImpl = (HGOCRBase*)ocrMgr;
|
|
||||||
return ocrMgrImpl->ImageTextDirectOCR(image, direct);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_AddToImageOCRList(HGOCRMgr ocrMgr, HGImage image)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRBase* ocrMgrImpl = (HGOCRBase*)ocrMgr;
|
|
||||||
return ocrMgrImpl->AddToImageList(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_ClearImageOCRList(HGOCRMgr ocrMgr)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRBase* ocrMgrImpl = (HGOCRBase*)ocrMgr;
|
|
||||||
return ocrMgrImpl->ClearImageList();
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGAPI HGImgProc_ImageListOCRToFile(HGOCRMgr ocrMgr, HGUInt outType, const HGChar* outFileName, HGImageListOcrFunc func, HGPointer param)
|
|
||||||
{
|
|
||||||
if (NULL == ocrMgr)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRBase* ocrMgrImpl = (HGOCRBase*)ocrMgr;
|
|
||||||
return ocrMgrImpl->ImageListOCRToFile(outType, outFileName, func, param);
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
#ifndef __HGOCR_H__
|
|
||||||
#define __HGOCR_H__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include "HGImgProcErr.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
|
|
||||||
HG_DECLARE_HANDLE(HGOCRMgr);
|
|
||||||
HG_DECLARE_HANDLE(HGOCRRet);
|
|
||||||
|
|
||||||
/* algo */
|
|
||||||
#define HGIMGPROC_OCRALGO_DEFAULT 0L
|
|
||||||
#define HGIMGPROC_OCRALGO_HANVON 1L
|
|
||||||
#define HGIMGPROC_OCRALGO_TESSERACT 2L
|
|
||||||
|
|
||||||
/* RTF */
|
|
||||||
#define HGIMGPROC_OCROUTTYPE_RTF 1L
|
|
||||||
/* XLS */
|
|
||||||
#define HGIMGPROC_OCROUTTYPE_XLS 2L
|
|
||||||
/* TXT */
|
|
||||||
#define HGIMGPROC_OCROUTTYPE_TXT 3L
|
|
||||||
/* PDF */
|
|
||||||
#define HGIMGPROC_OCROUTTYPE_PDF 4L
|
|
||||||
/* OFD */
|
|
||||||
#define HGIMGPROC_OCROUTTYPE_OFD 5L
|
|
||||||
|
|
||||||
/* 未旋转 */
|
|
||||||
#define HGIMGPROC_OCRTEXTDIRECT_ORI 1L
|
|
||||||
/* 顺时针旋转了90度 */
|
|
||||||
#define HGIMGPROC_OCRTEXTDIRECT_RIGHT 2L
|
|
||||||
/* 逆时针旋转了90度 */
|
|
||||||
#define HGIMGPROC_OCRTEXTDIRECT_LEFT 3L
|
|
||||||
/* 旋转了180度 */
|
|
||||||
#define HGIMGPROC_OCRTEXTDIRECT_180 4L
|
|
||||||
|
|
||||||
/* 多页OCR进度
|
|
||||||
*/
|
|
||||||
typedef HGInt (HGAPI *HGImageListOcrFunc)(HGUInt total, HGUInt now, HGPointer param);
|
|
||||||
|
|
||||||
/* 初始化OCR模块
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_CreateOCRMgr(HGUInt algo, HGOCRMgr *ocrMgr);
|
|
||||||
|
|
||||||
/* 反初始化OCR模块
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_DestroyOCRMgr(HGOCRMgr ocrMgr);
|
|
||||||
|
|
||||||
/* 图像OCR
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageOCR(HGOCRMgr ocrMgr, HGImage image, HGOCRRet *ocrRet);
|
|
||||||
|
|
||||||
/* 销毁OCR结果
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_DestroyOCRRet(HGOCRRet ocrRet);
|
|
||||||
|
|
||||||
/* 获取OCR结果块数量
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_GetOCRRetBlockCount(HGOCRRet ocrRet, HGUInt *count);
|
|
||||||
|
|
||||||
/* 获取OCR结果块文本
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_GetOCRRetBlockText(HGOCRRet ocrRet, HGUInt index, const HGChar **text);
|
|
||||||
|
|
||||||
/* 图像OCR到文件
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageOCRToFile(HGOCRMgr ocrMgr, HGImage image, HGUInt outType, const HGChar *outFileName);
|
|
||||||
|
|
||||||
/* 获取图像识别方向
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageTextDirectOCR(HGOCRMgr ocrMgr, HGImage image, HGUInt *direct);
|
|
||||||
|
|
||||||
/* 添加到图像OCR列表
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_AddToImageOCRList(HGOCRMgr ocrMgr, HGImage image);
|
|
||||||
|
|
||||||
/* 清理图像OCR列表
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ClearImageOCRList(HGOCRMgr ocrMgr);
|
|
||||||
|
|
||||||
/* 图像列表OCR到文件
|
|
||||||
*/
|
|
||||||
HGEXPORT HGResult HGAPI HGImgProc_ImageListOCRToFile(HGOCRMgr ocrMgr, HGUInt outType, const HGChar* outFileName, HGImageListOcrFunc func, HGPointer param);
|
|
||||||
|
|
||||||
#endif /* __HGOCR_H__ */
|
|
|
@ -1,71 +0,0 @@
|
||||||
#include "HGOCRBase.hpp"
|
|
||||||
#include "HGOCR.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
|
|
||||||
HGUInt HGOCRBase::GetOutTypeByFileName(const HGChar* fileName)
|
|
||||||
{
|
|
||||||
if (NULL == fileName)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* p = strrchr(fileName, '.');
|
|
||||||
if (NULL == p)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
if (0 == _stricmp(p, ".pdf"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_PDF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == _stricmp(p, ".rtf"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_RTF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == _stricmp(p, ".xls"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_XLS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == _stricmp(p, ".txt"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_TXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == _stricmp(p, ".ofd"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_OFD;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (0 == strcasecmp(p, ".pdf"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_PDF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == strcasecmp(p, ".rtf"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_RTF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == strcasecmp(p, ".xls"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_XLS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == strcasecmp(p, ".txt"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_TXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == strcasecmp(p, ".ofd"))
|
|
||||||
{
|
|
||||||
return HGIMGPROC_OCROUTTYPE_OFD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
#ifndef __HGOCRBASE_H__
|
|
||||||
#define __HGOCRBASE_H__
|
|
||||||
|
|
||||||
#include "HGOCR.h"
|
|
||||||
|
|
||||||
class HGOCRBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGOCRBase() {};
|
|
||||||
virtual ~HGOCRBase() {};
|
|
||||||
|
|
||||||
virtual HGResult Init() = 0;
|
|
||||||
virtual HGResult Deinit() = 0;
|
|
||||||
virtual HGResult ImageOCR(HGImage image, class HGOCRRetImpl **ocrRet) = 0;
|
|
||||||
virtual HGResult ImageOCRToFile(HGImage image, HGUInt outType, const HGChar *outFileName) = 0;
|
|
||||||
virtual HGResult ImageTextDirectOCR(HGImage image, HGUInt* direct) = 0;
|
|
||||||
virtual HGResult AddToImageList(HGImage image) = 0;
|
|
||||||
virtual HGResult ClearImageList() = 0;
|
|
||||||
virtual HGResult ImageListOCRToFile(HGUInt outType, const HGChar* outFileName, HGImageListOcrFunc func, HGPointer param) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static HGUInt GetOutTypeByFileName(const HGChar* fileName);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGOCRBASE_H__ */
|
|
|
@ -1,475 +0,0 @@
|
||||||
#include "HGOCRHanvon.hpp"
|
|
||||||
#include "HGOCRRetImpl.hpp"
|
|
||||||
#include "../base/HGUtility.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
#include "../imgfmt/HGBmp.h"
|
|
||||||
#include "../imgfmt/HGJpeg.h"
|
|
||||||
|
|
||||||
//HGUInt HGOCRHanvon::m_refCount = 0;
|
|
||||||
//HGOCRHanvon* HGOCRHanvon::m_OCR = NULL;
|
|
||||||
|
|
||||||
HGOCRHanvon::HGOCRHanvon()
|
|
||||||
{
|
|
||||||
m_dll = NULL;
|
|
||||||
m_ocrHandle = NULL;
|
|
||||||
m_imageList.clear();
|
|
||||||
m_func = NULL;
|
|
||||||
m_param = NULL;
|
|
||||||
//m_FuncRet = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRHanvon::~HGOCRHanvon()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::Init()
|
|
||||||
{
|
|
||||||
if (NULL != m_ocrHandle)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(NULL == m_dll);
|
|
||||||
|
|
||||||
HGChar moduleName[256];
|
|
||||||
HGBase_GetModuleName((void *)HGImgProc_CreateOCRMgr, moduleName, 256);
|
|
||||||
HGChar dllPath[256];
|
|
||||||
HGBase_GetFilePath(moduleName, dllPath, 256);
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
strcat(dllPath, "hanwangOCRdetect.dll");
|
|
||||||
#else
|
|
||||||
strcat(dllPath, "libhwocrdetect.so");
|
|
||||||
#endif
|
|
||||||
HGResult ret = HGBase_CreateDll(dllPath, &m_dll);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != HWOCR_SDKInitialize(&m_ocrHandle))
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::Init: HWOCR_SDKInitialize fail");
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGIMGPROC_ERR_OCRINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (0 == m_refCount)
|
|
||||||
//{
|
|
||||||
//HWOCR_InitPdf();
|
|
||||||
//}
|
|
||||||
//++m_refCount;
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::Deinit()
|
|
||||||
{
|
|
||||||
if (NULL == m_ocrHandle)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClearImageList();
|
|
||||||
|
|
||||||
//assert(0 != m_refCount);
|
|
||||||
//--m_refCount;
|
|
||||||
//if (0 == m_refCount)
|
|
||||||
//{
|
|
||||||
//HWOCR_ExitPdf();
|
|
||||||
//}
|
|
||||||
|
|
||||||
HWOCR_SDKExit(m_ocrHandle);
|
|
||||||
m_ocrHandle = NULL;
|
|
||||||
|
|
||||||
HGBase_DestroyDll(m_dll);
|
|
||||||
m_dll = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::ImageOCR(HGImage image, class HGOCRRetImpl **ocrRet)
|
|
||||||
{
|
|
||||||
if (NULL == image || NULL == ocrRet)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar tmpFileName[256];
|
|
||||||
HGBase_GetTmpFileName("bmp", tmpFileName, 256);
|
|
||||||
HGResult ret = HGImgFmt_SaveBmpImage(image, NULL, tmpFileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageOCR: HGImgFmt_SaveBmpImage fail %s", tmpFileName);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* rst = NULL;
|
|
||||||
int len = 0;
|
|
||||||
int rc = HWOCR_RecognizeFile2Str((unsigned char*)tmpFileName, m_ocrHandle, &rst, &len);
|
|
||||||
HGBase_DeleteFile(tmpFileName);
|
|
||||||
if (0 != rc)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageOCR: HWOCR_RecognizeFile2Str fail in=%s", tmpFileName);
|
|
||||||
return HGIMGPROC_ERR_OCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(NULL != rst && len > 0);
|
|
||||||
|
|
||||||
std::vector<std::string> blockInfo;
|
|
||||||
blockInfo.push_back(rst);
|
|
||||||
HWOCR_FreeStrRst(&rst);
|
|
||||||
|
|
||||||
*ocrRet = new HGOCRRetImpl(blockInfo);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::ImageOCRToFile(HGImage image, HGUInt outType, const HGChar *outFileName)
|
|
||||||
{
|
|
||||||
if (NULL == image || outType > HGIMGPROC_OCROUTTYPE_OFD || NULL == outFileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == outType)
|
|
||||||
outType = GetOutTypeByFileName(outFileName);
|
|
||||||
|
|
||||||
int fileType = -1;
|
|
||||||
if (HGIMGPROC_OCROUTTYPE_RTF == outType)
|
|
||||||
fileType = FILE_RTF;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_XLS == outType)
|
|
||||||
fileType = FILE_XLS;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_TXT == outType)
|
|
||||||
fileType = FILE_TXT;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_PDF == outType)
|
|
||||||
fileType = FILE_PDF;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_OFD == outType)
|
|
||||||
fileType = FILE_OFD;
|
|
||||||
if (-1 == fileType)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar tmpFileName[256];
|
|
||||||
HGBase_GetTmpFileName("bmp", tmpFileName, 256);
|
|
||||||
HGResult ret = HGImgFmt_SaveBmpImage(image, NULL, tmpFileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageOCRToFile: HGImgFmt_SaveBmpImage fail %s", tmpFileName);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar tmpDir[256];
|
|
||||||
HGBase_GetTmpFileName(NULL, tmpDir, 256);
|
|
||||||
ret = HGBase_CreateDir(tmpDir);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageOCRToFile: HGBase_CreateDir fail %s", tmpDir);
|
|
||||||
HGBase_DeleteFile(tmpFileName);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc = HWOCR_RecognizeFile((unsigned char*)tmpFileName, (unsigned char*)outFileName, fileType, m_ocrHandle, NULL, tmpDir);
|
|
||||||
HGBase_DeleteDir(tmpDir);
|
|
||||||
HGBase_DeleteFile(tmpFileName);
|
|
||||||
if (0 != rc)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageOCR: HWOCR_RecognizeFile fail in=%s, out=%s, tmpdir=%s",
|
|
||||||
tmpFileName, outFileName, tmpDir);
|
|
||||||
return HGIMGPROC_ERR_OCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::ImageTextDirectOCR(HGImage image, HGUInt* direct)
|
|
||||||
{
|
|
||||||
if (NULL == image || NULL == direct)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar tmpFileName[256];
|
|
||||||
HGBase_GetTmpFileName("bmp", tmpFileName, 256);
|
|
||||||
HGResult ret = HGImgFmt_SaveBmpImage(image, NULL, tmpFileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageTextDirectOCR: HGImgFmt_SaveBmpImage fail %s", tmpFileName);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dire = -1;
|
|
||||||
int rc = HWOCR_GetFileDirect((unsigned char*)tmpFileName, m_ocrHandle, &dire);
|
|
||||||
HGBase_DeleteFile(tmpFileName);
|
|
||||||
if (0 != rc)
|
|
||||||
{
|
|
||||||
return HGIMGPROC_ERR_OCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ROT0 == dire)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_ORI;
|
|
||||||
else if (ROT90 == dire)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_RIGHT;
|
|
||||||
else if (ROT180 == dire)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_180;
|
|
||||||
else if (ROT270 == dire)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_LEFT;
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::AddToImageList(HGImage image)
|
|
||||||
{
|
|
||||||
if (NULL == image)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar tmpFileName[256] = {0};
|
|
||||||
HGBase_GetTmpFileName("jpg", tmpFileName, 256);
|
|
||||||
HGResult ret = HGImgFmt_SaveJpegImage(image, NULL, tmpFileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::AddToImageList: HGImgFmt_SaveJpegImage fail %s", tmpFileName);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_imageList.push_back(tmpFileName);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::ClearImageList()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < (int)m_imageList.size(); ++i)
|
|
||||||
{
|
|
||||||
HGBase_DeleteFile(m_imageList[i].c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_imageList.clear();
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRHanvon::ImageListOCRToFile(HGUInt outType, const HGChar* outFileName, HGImageListOcrFunc func, HGPointer param)
|
|
||||||
{
|
|
||||||
if (m_imageList.empty())
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outType > HGIMGPROC_OCROUTTYPE_OFD || NULL == outFileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == outType)
|
|
||||||
outType = GetOutTypeByFileName(outFileName);
|
|
||||||
|
|
||||||
int fileType = -1;
|
|
||||||
if (HGIMGPROC_OCROUTTYPE_RTF == outType)
|
|
||||||
fileType = FILE_RTF;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_XLS == outType)
|
|
||||||
fileType = FILE_XLS;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_TXT == outType)
|
|
||||||
fileType = FILE_TXT;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_PDF == outType)
|
|
||||||
fileType = FILE_PDF;
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_OFD == outType)
|
|
||||||
fileType = FILE_OFD;
|
|
||||||
if (-1 == fileType)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
//m_OCR = this;
|
|
||||||
m_func = func;
|
|
||||||
m_param = param;
|
|
||||||
|
|
||||||
HGChar** ppImageFiles = new HGChar* [m_imageList.size() + 1];
|
|
||||||
for (int i = 0; i < (int)m_imageList.size(); ++i)
|
|
||||||
ppImageFiles[i] = (HGChar *)m_imageList[i].c_str();
|
|
||||||
ppImageFiles[m_imageList.size()] = NULL;
|
|
||||||
|
|
||||||
HGChar tmpDir[256];
|
|
||||||
HGBase_GetTmpFileName(NULL, tmpDir, 256);
|
|
||||||
HGResult ret = HGBase_CreateDir(tmpDir);
|
|
||||||
if (HGBASE_ERR_OK == ret)
|
|
||||||
{
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
int rc = HWOCR_RecognizeFileBatch(ppImageFiles, (unsigned char*)outFileName, fileType, m_ocrHandle, NULL, tmpDir, RecogProgress, IsCanceled);
|
|
||||||
#else
|
|
||||||
int rc = HWOCR_RecognizeFileBatch(ppImageFiles, (unsigned char*)outFileName, fileType, m_ocrHandle, NULL, tmpDir);
|
|
||||||
#endif
|
|
||||||
if (0 != rc)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageListOCRToFile: HWOCR_RecognizeFileBatch fail out=%s, tmpdir=%s",
|
|
||||||
outFileName, tmpDir);
|
|
||||||
ret = HGIMGPROC_ERR_OCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_DeleteDir(tmpDir);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRHanvon::ImageListOCRToFile: HGBase_CreateDir fail %s", tmpDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] ppImageFiles;
|
|
||||||
m_param = NULL;
|
|
||||||
m_func = NULL;
|
|
||||||
//m_OCR = NULL;
|
|
||||||
|
|
||||||
// 不管成功与否都清空
|
|
||||||
for (int i = 0; i < (int)m_imageList.size(); ++i)
|
|
||||||
{
|
|
||||||
HGBase_DeleteFile(m_imageList[i].c_str());
|
|
||||||
}
|
|
||||||
m_imageList.clear();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGOCRHanvon::HWOCR_SDKInitialize(void** ppstOcrHandle)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(void**);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_SDKInitialize", (HGPointer *)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ppstOcrHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGOCRHanvon::HWOCR_SDKExit(void* pstOcrHandle)
|
|
||||||
{
|
|
||||||
typedef void (*Func)(void*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_SDKExit", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(pstOcrHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGOCRHanvon::HWOCR_InitPdf()
|
|
||||||
{
|
|
||||||
typedef void (*Func)();
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_InitPdf", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGOCRHanvon::HWOCR_ExitPdf()
|
|
||||||
{
|
|
||||||
typedef void (*Func)();
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_ExitPdf", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGOCRHanvon::HWOCR_RecognizeFile2Str(unsigned char* ImgFile, void* pstHandle, char** ppRst, int* pnLen)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(unsigned char*, void*, char**, int*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_RecognizeFile2Str", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ImgFile, pstHandle, ppRst, pnLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HGOCRHanvon::HWOCR_FreeStrRst(char** ppRst)
|
|
||||||
{
|
|
||||||
typedef void (*Func)(char**);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_FreeStrRst", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
func(ppRst);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGOCRHanvon::HWOCR_RecognizeFile(unsigned char* ImgFile, unsigned char* OutFile, int nFileType, void* pstHandle, char* pLibDir, char* pTmpDir)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(unsigned char*, unsigned char*, int, void*, char*, char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_RecognizeFile", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ImgFile, OutFile, nFileType, pstHandle, pLibDir, pTmpDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGOCRHanvon::HWOCR_GetFileDirect(unsigned char* ImgFile, void* pstHandle, int* pDirect)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(unsigned char*, void *, int *);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_GetFileDirect", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ImgFile, pstHandle, pDirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
int HGOCRHanvon::HWOCR_RecognizeFileBatch(char** ppImageFiles, unsigned char* OutFile, int nFileType, void* pstHandle, char* pLibDir, char* pTmpDir,
|
|
||||||
HWOCR_RecogProgress aFuncRecogProgress, HWOCR_IsCanceled aFuncIsCanceled)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(char**, unsigned char*, int, void*, char*, char*, HWOCR_RecogProgress, HWOCR_IsCanceled);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_RecognizeFileBatch", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ppImageFiles, OutFile, nFileType, pstHandle, pLibDir, pTmpDir, aFuncRecogProgress, aFuncIsCanceled);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int HGOCRHanvon::HWOCR_RecognizeFileBatch(char** ppImageFiles, unsigned char* OutFile, int nFileType, void* pstHandle, char* pLibDir, char* pTmpDir)
|
|
||||||
{
|
|
||||||
typedef int (*Func)(char**, unsigned char*, int, void*, char*, char*);
|
|
||||||
Func func = NULL;
|
|
||||||
HGBase_GetDllProcAddress(m_dll, "HWOCR_RecognizeFileBatch", (HGPointer*)&func);
|
|
||||||
if (NULL == func)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(ppImageFiles, OutFile, nFileType, pstHandle, pLibDir, pTmpDir);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
int HGOCRHanvon::RecogProgress(int nPercent)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int HGOCRHanvon::IsCanceled()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,60 +0,0 @@
|
||||||
#ifndef __HGOCRHANVON_HPP__
|
|
||||||
#define __HGOCRHANVON_HPP__
|
|
||||||
|
|
||||||
#include "HGOCRBase.hpp"
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
#include "../base/HGDll.h"
|
|
||||||
#include "hanwangOCRdetect.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class HGOCRHanvon : public HGOCRBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGOCRHanvon();
|
|
||||||
virtual ~HGOCRHanvon();
|
|
||||||
|
|
||||||
HGResult Init();
|
|
||||||
HGResult Deinit();
|
|
||||||
HGResult ImageOCR(HGImage image, class HGOCRRetImpl **ocrRet);
|
|
||||||
HGResult ImageOCRToFile(HGImage image, HGUInt outType, const HGChar *outFileName);
|
|
||||||
HGResult ImageTextDirectOCR(HGImage image, HGUInt* direct);
|
|
||||||
HGResult AddToImageList(HGImage image);
|
|
||||||
HGResult ClearImageList();
|
|
||||||
HGResult ImageListOCRToFile(HGUInt outType, const HGChar* outFileName, HGImageListOcrFunc func, HGPointer param);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int HWOCR_SDKInitialize(void** ppstOcrHandle);
|
|
||||||
void HWOCR_SDKExit(void* pstOcrHandle);
|
|
||||||
void HWOCR_InitPdf();
|
|
||||||
void HWOCR_ExitPdf();
|
|
||||||
int HWOCR_RecognizeFile2Str(unsigned char* ImgFile, void* pstHandle, char** ppRst, int* pnLen);
|
|
||||||
void HWOCR_FreeStrRst(char** ppRst);
|
|
||||||
int HWOCR_RecognizeFile(unsigned char* ImgFile, unsigned char* OutFile, int nFileType, void* pstHandle, char* pLibDir, char* pTmpDir);
|
|
||||||
int HWOCR_GetFileDirect(unsigned char* ImgFile, void* pstHandle, int* pDirect);
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
int HWOCR_RecognizeFileBatch(char** ppImageFiles, unsigned char* OutFile, int nFileType, void* pstHandle, char* pLibDir, char* pTmpDir,
|
|
||||||
HWOCR_RecogProgress aFuncRecogProgress, HWOCR_IsCanceled aFuncIsCanceled);
|
|
||||||
#else
|
|
||||||
int HWOCR_RecognizeFileBatch(char** ppImageFiles, unsigned char* OutFile, int nFileType, void* pstHandle, char* pLibDir, char* pTmpDir);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
static int RecogProgress(int nPercent);
|
|
||||||
static int IsCanceled();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
//static HGUInt m_refCount;
|
|
||||||
//static HGOCRHanvon* m_OCR;
|
|
||||||
HGDll m_dll;
|
|
||||||
void* m_ocrHandle;
|
|
||||||
std::vector<std::string> m_imageList;
|
|
||||||
HGImageListOcrFunc m_func;
|
|
||||||
HGPointer m_param;
|
|
||||||
//HGInt m_FuncRet;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGOCRHANVON_HPP__ */
|
|
|
@ -1,33 +0,0 @@
|
||||||
#include "HGOCRRetImpl.hpp"
|
|
||||||
|
|
||||||
HGOCRRetImpl::HGOCRRetImpl(const std::vector<std::string>& blockInfo)
|
|
||||||
{
|
|
||||||
m_blockInfo = blockInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRRetImpl::~HGOCRRetImpl()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRRetImpl::GetBlockCount(HGUInt* count)
|
|
||||||
{
|
|
||||||
if (NULL == count)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*count = (HGUInt)m_blockInfo.size();
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRRetImpl::GetBlockText(HGUInt index, const HGChar** text)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= (HGUInt)m_blockInfo.size() || NULL == text)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*text = m_blockInfo[index].c_str();
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
#ifndef __HGOCRRETIMPL_HPP__
|
|
||||||
#define __HGOCRRETIMPL_HPP__
|
|
||||||
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGBaseErr.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class HGOCRRetImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGOCRRetImpl(const std::vector<std::string> &blockInfo);
|
|
||||||
~HGOCRRetImpl();
|
|
||||||
|
|
||||||
HGResult GetBlockCount(HGUInt *count);
|
|
||||||
HGResult GetBlockText(HGUInt index, const HGChar** text);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::string> m_blockInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGOCRRETIMPL_HPP__ */
|
|
|
@ -1,336 +0,0 @@
|
||||||
#include "HGOCRTesseract.hpp"
|
|
||||||
#include "HGOCR.h"
|
|
||||||
#include "HGOCRRetImpl.hpp"
|
|
||||||
#include "HGOCRRetImpl.hpp"
|
|
||||||
#include "../base/HGUtility.h"
|
|
||||||
#include "../base/HGInfo.h"
|
|
||||||
#include "../imgfmt/HGBmp.h"
|
|
||||||
#include "../imgfmt/HGJpeg.h"
|
|
||||||
#include "HGString.h"
|
|
||||||
|
|
||||||
HGOCRTesseract::HGOCRTesseract()
|
|
||||||
{
|
|
||||||
m_baseApi = NULL;
|
|
||||||
m_tiffFileName.clear();
|
|
||||||
m_tiffWriter = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGOCRTesseract::~HGOCRTesseract()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::Init()
|
|
||||||
{
|
|
||||||
if (NULL != m_baseApi)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_baseApi = TessBaseAPICreate();
|
|
||||||
if (NULL == m_baseApi)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRTesseract::Init: TessBaseAPICreate fail");
|
|
||||||
return HGIMGPROC_ERR_OCRINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGChar moduleName[256];
|
|
||||||
HGBase_GetModuleName((void*)HGImgProc_CreateOCRMgr, moduleName, 256);
|
|
||||||
HGChar dataPath[256];
|
|
||||||
HGBase_GetFilePath(moduleName, dataPath, 256);
|
|
||||||
strcat(dataPath, "tessdata");
|
|
||||||
|
|
||||||
int rc = TessBaseAPIInit3(m_baseApi, dataPath, "chi_sim");
|
|
||||||
if (0 != rc)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRTesseract::Init: TessBaseAPIInit3 fail");
|
|
||||||
TessBaseAPIDelete(m_baseApi);
|
|
||||||
m_baseApi = NULL;
|
|
||||||
return HGIMGPROC_ERR_OCRINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
TessBaseAPISetPageSegMode(m_baseApi, TessPageSegMode::PSM_AUTO_OSD);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::Deinit()
|
|
||||||
{
|
|
||||||
if (NULL == m_baseApi)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClearImageList();
|
|
||||||
|
|
||||||
TessBaseAPIDelete(m_baseApi);
|
|
||||||
m_baseApi = NULL;
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::ImageOCR(HGImage image, class HGOCRRetImpl** ocrRet)
|
|
||||||
{
|
|
||||||
if (NULL == image || NULL == ocrRet)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
if (HGBASE_IMGTYPE_RGB != imgInfo.type || HGBASE_IMGORIGIN_TOP != imgInfo.origin)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image2 = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_GetImageInfo(image2, &imgInfo);
|
|
||||||
HGByte* imageData = NULL;
|
|
||||||
HGBase_GetImageData(image2, &imageData);
|
|
||||||
|
|
||||||
TessBaseAPISetImage(m_baseApi, imageData, imgInfo.width, imgInfo.height, 3, imgInfo.widthStep);
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image2, &xDpi, &yDpi);
|
|
||||||
TessBaseAPISetSourceResolution(m_baseApi, (xDpi + yDpi) / 2);
|
|
||||||
|
|
||||||
char *text = TessBaseAPIGetUTF8Text(m_baseApi);
|
|
||||||
if (NULL == text)
|
|
||||||
{
|
|
||||||
if (image2 != image)
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGIMGPROC_ERR_OCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> blockInfo;
|
|
||||||
blockInfo.push_back(Utf8ToStdString(text));
|
|
||||||
*ocrRet = new HGOCRRetImpl(blockInfo);
|
|
||||||
|
|
||||||
TessDeleteText(text);
|
|
||||||
if (image2 != image)
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::ImageOCRToFile(HGImage image, HGUInt outType, const HGChar* outFileName)
|
|
||||||
{
|
|
||||||
if (NULL == image || outType > HGIMGPROC_OCROUTTYPE_OFD || NULL == outFileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == outType)
|
|
||||||
outType = GetOutTypeByFileName(outFileName);
|
|
||||||
|
|
||||||
HGChar tmpFileName[256];
|
|
||||||
HGBase_GetTmpFileName("bmp", tmpFileName, 256);
|
|
||||||
HGResult ret = HGImgFmt_SaveBmpImage(image, NULL, tmpFileName);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRTesseract::ImageOCRToFile: HGImgFmt_SaveBmpImage fail %s", tmpFileName);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = OCRToFile(tmpFileName, outType, outFileName);
|
|
||||||
HGBase_DeleteFile(tmpFileName);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::ImageTextDirectOCR(HGImage image, HGUInt* direct)
|
|
||||||
{
|
|
||||||
if (NULL == image || NULL == direct)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImage image2 = NULL;
|
|
||||||
|
|
||||||
HGImageInfo imgInfo;
|
|
||||||
HGBase_GetImageInfo(image, &imgInfo);
|
|
||||||
if (HGBASE_IMGTYPE_RGB != imgInfo.type || HGBASE_IMGORIGIN_TOP != imgInfo.origin)
|
|
||||||
{
|
|
||||||
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image2 = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGBase_GetImageInfo(image2, &imgInfo);
|
|
||||||
HGByte* imageData = NULL;
|
|
||||||
HGBase_GetImageData(image2, &imageData);
|
|
||||||
|
|
||||||
TessBaseAPISetImage(m_baseApi, imageData, imgInfo.width, imgInfo.height, 3, imgInfo.widthStep);
|
|
||||||
HGUInt xDpi, yDpi;
|
|
||||||
HGBase_GetImageDpi(image2, &xDpi, &yDpi);
|
|
||||||
TessBaseAPISetSourceResolution(m_baseApi, (xDpi + yDpi) / 2);
|
|
||||||
|
|
||||||
TessPageIterator* iter = TessBaseAPIAnalyseLayout(m_baseApi);
|
|
||||||
if (NULL == iter)
|
|
||||||
{
|
|
||||||
if (image2 != image)
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGIMGPROC_ERR_OCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
TessOrientation orientation;
|
|
||||||
TessWritingDirection writing_direction;
|
|
||||||
TessTextlineOrder textline_order;
|
|
||||||
float deskew_angle;
|
|
||||||
TessPageIteratorOrientation(iter, &orientation, &writing_direction, &textline_order, &deskew_angle);
|
|
||||||
|
|
||||||
if (TessOrientation::ORIENTATION_PAGE_UP == orientation)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_ORI;
|
|
||||||
else if (TessOrientation::ORIENTATION_PAGE_RIGHT == orientation)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_RIGHT;
|
|
||||||
else if (TessOrientation::ORIENTATION_PAGE_DOWN == orientation)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_180;
|
|
||||||
else if (TessOrientation::ORIENTATION_PAGE_LEFT == orientation)
|
|
||||||
*direct = HGIMGPROC_OCRTEXTDIRECT_LEFT;
|
|
||||||
|
|
||||||
TessPageIteratorDelete(iter);
|
|
||||||
if (image2 != image)
|
|
||||||
HGBase_DestroyImage(image2);
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::AddToImageList(HGImage image)
|
|
||||||
{
|
|
||||||
if (NULL == image)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == m_tiffWriter)
|
|
||||||
{
|
|
||||||
HGChar tmpFileName[256] = { 0 };
|
|
||||||
HGBase_GetTmpFileName("tif", tmpFileName, 256);
|
|
||||||
m_tiffFileName = tmpFileName;
|
|
||||||
|
|
||||||
HGResult ret = HGImgFmt_OpenTiffWriter(m_tiffFileName.c_str(), &m_tiffWriter);
|
|
||||||
if (HGBASE_ERR_OK != ret)
|
|
||||||
{
|
|
||||||
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGOCRTesseract::AddToImageList: HGImgFmt_OpenTiffWriter fail %s", m_tiffFileName.c_str());
|
|
||||||
m_tiffFileName.clear();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGImgFmt_SaveImageToTiffWriter(m_tiffWriter, image, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::ClearImageList()
|
|
||||||
{
|
|
||||||
if (NULL != m_tiffWriter)
|
|
||||||
{
|
|
||||||
HGImgFmt_CloseTiffWriter(m_tiffWriter);
|
|
||||||
m_tiffWriter = NULL;
|
|
||||||
HGBase_DeleteFile(m_tiffFileName.c_str());
|
|
||||||
m_tiffFileName.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return HGBASE_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::ImageListOCRToFile(HGUInt outType, const HGChar* outFileName, HGImageListOcrFunc func, HGPointer param)
|
|
||||||
{
|
|
||||||
if (NULL == m_tiffWriter)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outType > HGIMGPROC_OCROUTTYPE_OFD || NULL == outFileName)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == outType)
|
|
||||||
outType = GetOutTypeByFileName(outFileName);
|
|
||||||
|
|
||||||
if (HGIMGPROC_OCROUTTYPE_PDF != outType && HGIMGPROC_OCROUTTYPE_TXT != outType)
|
|
||||||
{
|
|
||||||
return HGBASE_ERR_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGImgFmt_CloseTiffWriter(m_tiffWriter);
|
|
||||||
m_tiffWriter = NULL;
|
|
||||||
assert(!m_tiffFileName.empty());
|
|
||||||
HGResult ret = OCRToFile(m_tiffFileName.c_str(), outType, outFileName);
|
|
||||||
HGBase_DeleteFile(m_tiffFileName.c_str());
|
|
||||||
m_tiffFileName.clear();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGResult HGOCRTesseract::OCRToFile(const HGChar* inFileName, HGUInt outType, const HGChar* outFileName)
|
|
||||||
{
|
|
||||||
assert(NULL != inFileName);
|
|
||||||
assert(NULL != outFileName);
|
|
||||||
|
|
||||||
HGResult ret = HGBASE_ERR_NOTSUPPORT;
|
|
||||||
if (HGIMGPROC_OCROUTTYPE_PDF == outType)
|
|
||||||
{
|
|
||||||
HGChar outputbase[256] = { 0 };
|
|
||||||
const char* p = strrchr(outFileName, '.');
|
|
||||||
if (NULL != p && 0 == strcmp(p, ".pdf"))
|
|
||||||
memcpy(outputbase, outFileName, p - outFileName);
|
|
||||||
else
|
|
||||||
strcpy(outputbase, outFileName);
|
|
||||||
|
|
||||||
ret = HGIMGPROC_ERR_OCR;
|
|
||||||
TessResultRenderer* pdfRender = TessPDFRendererCreate(outputbase, TessBaseAPIGetDatapath(m_baseApi), FALSE);
|
|
||||||
if (NULL != pdfRender)
|
|
||||||
{
|
|
||||||
if (TessBaseAPIProcessPages(m_baseApi, inFileName, NULL, 0, pdfRender))
|
|
||||||
ret = HGBASE_ERR_OK;
|
|
||||||
TessDeleteResultRenderer(pdfRender);
|
|
||||||
|
|
||||||
if (HGBASE_ERR_OK == ret)
|
|
||||||
{
|
|
||||||
HGChar destFileName[256];
|
|
||||||
sprintf(destFileName, "%s.pdf", outputbase);
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
MoveFileA(destFileName, outFileName);
|
|
||||||
#else
|
|
||||||
rename(destFileName, outFileName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (HGIMGPROC_OCROUTTYPE_TXT == outType)
|
|
||||||
{
|
|
||||||
HGChar outputbase[256] = { 0 };
|
|
||||||
const char* p = strrchr(outFileName, '.');
|
|
||||||
if (NULL != p && 0 == strcmp(p, ".txt"))
|
|
||||||
memcpy(outputbase, outFileName, p - outFileName);
|
|
||||||
else
|
|
||||||
strcpy(outputbase, outFileName);
|
|
||||||
|
|
||||||
ret = HGIMGPROC_ERR_OCR;
|
|
||||||
TessResultRenderer* txtRender = TessTextRendererCreate(outputbase);
|
|
||||||
if (NULL != txtRender)
|
|
||||||
{
|
|
||||||
if (TessBaseAPIProcessPages(m_baseApi, inFileName, NULL, 0, txtRender))
|
|
||||||
ret = HGBASE_ERR_OK;
|
|
||||||
TessDeleteResultRenderer(txtRender);
|
|
||||||
|
|
||||||
if (HGBASE_ERR_OK == ret)
|
|
||||||
{
|
|
||||||
HGChar destFileName[256];
|
|
||||||
sprintf(destFileName, "%s.txt", outputbase);
|
|
||||||
#if defined(HG_CMP_MSC)
|
|
||||||
MoveFileA(destFileName, outFileName);
|
|
||||||
#else
|
|
||||||
rename(destFileName, outFileName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
#ifndef __HGOCRTESSERACT_HPP__
|
|
||||||
#define __HGOCRTESSERACT_HPP__
|
|
||||||
|
|
||||||
#include "HGOCRBase.hpp"
|
|
||||||
#include "../base/HGDef.h"
|
|
||||||
#include "../base/HGInc.h"
|
|
||||||
#include "../base/HGImage.h"
|
|
||||||
#include "../base/HGDll.h"
|
|
||||||
#include "../imgfmt/HGTiff.h"
|
|
||||||
#include "tesseract/capi.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class HGOCRTesseract : public HGOCRBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HGOCRTesseract();
|
|
||||||
virtual ~HGOCRTesseract();
|
|
||||||
|
|
||||||
HGResult Init();
|
|
||||||
HGResult Deinit();
|
|
||||||
HGResult ImageOCR(HGImage image, class HGOCRRetImpl** ocrRet);
|
|
||||||
HGResult ImageOCRToFile(HGImage image, HGUInt outType, const HGChar* outFileName);
|
|
||||||
HGResult ImageTextDirectOCR(HGImage image, HGUInt* direct);
|
|
||||||
HGResult AddToImageList(HGImage image);
|
|
||||||
HGResult ClearImageList();
|
|
||||||
HGResult ImageListOCRToFile(HGUInt outType, const HGChar* outFileName, HGImageListOcrFunc func, HGPointer param);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HGResult OCRToFile(const HGChar *inFileName, HGUInt outType, const HGChar* outFileName);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TessBaseAPI* m_baseApi;
|
|
||||||
std::string m_tiffFileName;
|
|
||||||
HGTiffWriter m_tiffWriter;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __HGOCRTESSERACT_HPP__ */
|
|
|
@ -1,9 +0,0 @@
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
CImageApply::CImageApply(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApply::~CImageApply(void)
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:所有图像处理功能类的基类
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2020/4/21
|
|
||||||
* 最近修改时间:2020/4/21
|
|
||||||
* 版本号:v1.0
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_H
|
|
||||||
#define IMAGE_APPLY_H
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <opencv2/opencv.hpp>
|
|
||||||
|
|
||||||
class CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CImageApply(void);
|
|
||||||
virtual ~CImageApply(void);
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib,int side) = 0;
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::shared_ptr<CImageApply> ImageApplyPtr;
|
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_H
|
|
|
@ -1,90 +0,0 @@
|
||||||
#include "ImageApplyAdjustColors.h"
|
|
||||||
|
|
||||||
CImageApplyAdjustColors::CImageApplyAdjustColors(void)
|
|
||||||
: m_brightness(0)
|
|
||||||
, m_contrast(0)
|
|
||||||
, m_gamma(1.0f)
|
|
||||||
, lut(1, 256, CV_8UC1)
|
|
||||||
{
|
|
||||||
update_lutData();
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyAdjustColors::CImageApplyAdjustColors(int brightness, int contrast, float gamma)
|
|
||||||
: lut(1, 256, CV_8UC1)
|
|
||||||
{
|
|
||||||
setAdjustColors(brightness, contrast, gamma);
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyAdjustColors::~CImageApplyAdjustColors(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAdjustColors::apply(cv::Mat& pDib,int side)
|
|
||||||
{
|
|
||||||
(void)side;
|
|
||||||
if (pDib.empty()) return;
|
|
||||||
|
|
||||||
if (m_brightness != 0 || m_contrast != 0 || m_gamma < 0.999999f || m_gamma > 1.000001f)
|
|
||||||
cv::LUT(pDib, lut, pDib);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAdjustColors::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|
||||||
{
|
|
||||||
(void)isTwoSide;
|
|
||||||
int i = 0;
|
|
||||||
for (cv::Mat& var : mats) {
|
|
||||||
if (i != 0 && isTwoSide == false)
|
|
||||||
break;
|
|
||||||
if(!var.empty())
|
|
||||||
apply(var, 0);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAdjustColors::setAdjustColors(int brightness, int contrast, float gamma)
|
|
||||||
{
|
|
||||||
m_brightness = cv::max(-255, cv::min(brightness, 255));
|
|
||||||
m_contrast = cv::max(-127, cv::min(contrast, 127));
|
|
||||||
m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
|
|
||||||
update_lutData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAdjustColors::setBrightness(int brightness)
|
|
||||||
{
|
|
||||||
m_brightness = cv::max(-255, cv::min(brightness, 255));
|
|
||||||
update_lutData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAdjustColors::setContrast(int contrast)
|
|
||||||
{
|
|
||||||
m_contrast = cv::max(-127, cv::min(contrast, 127));
|
|
||||||
update_lutData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAdjustColors::setGamma(float gamma)
|
|
||||||
{
|
|
||||||
m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
|
|
||||||
update_lutData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAdjustColors::update_lutData()
|
|
||||||
{
|
|
||||||
unsigned char* ptr = lut.data;
|
|
||||||
//update gamma
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
//update brightness
|
|
||||||
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(i + m_brightness, 255)));
|
|
||||||
|
|
||||||
//update contrast
|
|
||||||
if (ptr[i] < 128)
|
|
||||||
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(ptr[i] - m_contrast, 127)));
|
|
||||||
else
|
|
||||||
ptr[i] = static_cast<unsigned char>(cv::max(127, cv::min(ptr[i] + m_contrast, 255)));
|
|
||||||
}
|
|
||||||
float g = 1.0f / m_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)));
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:色彩调整,可以调整伽马、亮度、对比度效果。叠加优先级:亮度 > 对比度 > 伽马
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2020/4/21
|
|
||||||
* 最近修改时间:2020/4/21
|
|
||||||
* 版本号:v1.0
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_ADJUST_COLOR_H
|
|
||||||
#define IMAGE_APPLY_ADJUST_COLOR_H
|
|
||||||
|
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
class CImageApplyAdjustColors : public CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
CImageApplyAdjustColors(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* brightness [in]: 亮度调节,取值范围[-255, 255]
|
|
||||||
* constrast [in]: 对比度调节,取值范围[-128, 127]
|
|
||||||
* gamma [in]: 伽马调节,取值范围[0.1, 5.0]
|
|
||||||
*/
|
|
||||||
CImageApplyAdjustColors(int brightness, int contrast, float gamma);
|
|
||||||
|
|
||||||
virtual ~CImageApplyAdjustColors(void);
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib, int side);
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
|
||||||
|
|
||||||
void setAdjustColors(int brightness, int contrast, float gamma);
|
|
||||||
|
|
||||||
int getContrast() { return m_contrast; }
|
|
||||||
|
|
||||||
int getBrightness() { return m_brightness; }
|
|
||||||
|
|
||||||
double getGamma() { return m_gamma; }
|
|
||||||
|
|
||||||
void setBrightness(int brightness);
|
|
||||||
|
|
||||||
void setContrast(int contrast);
|
|
||||||
|
|
||||||
void setGamma(float gamma);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void update_lutData();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int m_brightness;
|
|
||||||
int m_contrast;
|
|
||||||
float m_gamma;
|
|
||||||
cv::Mat lut;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_ADJUST_COLOR_H
|
|
||||||
|
|
||||||
|
|
|
@ -1,330 +0,0 @@
|
||||||
#include "ImageApplyAutoCrop.h"
|
|
||||||
#include "ImageProcess_Public.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <opencv2/imgproc/hal/hal.hpp>
|
|
||||||
#include "ImageApplyDispersion.h"
|
|
||||||
|
|
||||||
CImageApplyAutoCrop::CImageApplyAutoCrop()
|
|
||||||
: m_isCrop(false)
|
|
||||||
, m_isDesaskew(false)
|
|
||||||
, m_isFillBlank(false)
|
|
||||||
, m_isConvexHull(true)
|
|
||||||
, m_isFillColor(false)
|
|
||||||
, m_threshold(40)
|
|
||||||
, m_noise(8)
|
|
||||||
, m_indent(5)
|
|
||||||
, m_normalCrop(false)
|
|
||||||
, m_isDispersion(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor,
|
|
||||||
double threshold, int noise, int indent, bool normalCrop, bool dispersion)
|
|
||||||
: m_isCrop(isCrop)
|
|
||||||
, m_isDesaskew(isDesaskew)
|
|
||||||
, m_isFillBlank(isFillBlank)
|
|
||||||
, m_isConvexHull(isConvex)
|
|
||||||
, m_isFillColor(isFillColor)
|
|
||||||
, m_threshold(threshold)
|
|
||||||
, m_noise(noise)
|
|
||||||
, m_indent(indent)
|
|
||||||
, m_fixedSize(fixedSize)
|
|
||||||
, m_normalCrop(normalCrop)
|
|
||||||
, m_isDispersion(dispersion)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyAutoCrop::~CImageApplyAutoCrop()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
|
|
||||||
{
|
|
||||||
cv::Mat dst;
|
|
||||||
autoCrop_desaskew_fillBlank(pDib, dst, m_isCrop, m_isDesaskew, m_isFillBlank, m_fixedSize.width, m_fixedSize.height,
|
|
||||||
m_isConvexHull, m_isFillColor, m_threshold, m_noise, m_indent, m_normalCrop, m_isDispersion);
|
|
||||||
pDib = dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|
||||||
{
|
|
||||||
(void)isTwoSide;
|
|
||||||
int i = 0;
|
|
||||||
for (cv::Mat& var : mats) {
|
|
||||||
if (i != 0 && isTwoSide == false)
|
|
||||||
break;
|
|
||||||
if (!var.empty())
|
|
||||||
apply(var, 0);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FRONT_TOP 70
|
|
||||||
#define FX_FY 0.5f
|
|
||||||
|
|
||||||
void myWarpAffine(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _M0, cv::Size dsize, int flags, int borderType, const cv::Scalar& borderValue)
|
|
||||||
{
|
|
||||||
int interpolation = flags;
|
|
||||||
cv::Mat src = _src.getMat(), M0 = _M0.getMat();
|
|
||||||
cv::Mat dst = _dst.getMat();
|
|
||||||
|
|
||||||
if (dst.data == src.data)
|
|
||||||
src = src.clone();
|
|
||||||
|
|
||||||
double M[6] = { 0 };
|
|
||||||
cv::Mat matM(2, 3, CV_64F, M);
|
|
||||||
if (interpolation == cv::INTER_AREA)
|
|
||||||
interpolation = cv::INTER_LINEAR;
|
|
||||||
|
|
||||||
M0.convertTo(matM, matM.type());
|
|
||||||
|
|
||||||
if (!(flags & cv::WARP_INVERSE_MAP))
|
|
||||||
{
|
|
||||||
double D = M[0] * M[4] - M[1] * M[3];
|
|
||||||
D = D != 0 ? 1. / D : 0;
|
|
||||||
double A11 = M[4] * D, A22 = M[0] * D;
|
|
||||||
M[0] = A11; M[1] *= -D;
|
|
||||||
M[3] *= -D; M[4] = A22;
|
|
||||||
double b1 = -M[0] * M[2] - M[1] * M[5];
|
|
||||||
double b2 = -M[3] * M[2] - M[4] * M[5];
|
|
||||||
M[2] = b1; M[5] = b2;
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::hal::warpAffine(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows,
|
|
||||||
M, interpolation, borderType, borderValue.val);
|
|
||||||
}
|
|
||||||
|
|
||||||
uchar getBackGroudChannelMean(const cv::Mat& gray, int total, int threshold)
|
|
||||||
{
|
|
||||||
cv::Mat image_clone;
|
|
||||||
cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25);
|
|
||||||
|
|
||||||
int threnshold = total / 32;
|
|
||||||
int channels[] = { 0 };
|
|
||||||
int nHistSize[] = { 256 };
|
|
||||||
float range[] = { 0, 256 };
|
|
||||||
const float* fHistRanges[] = { range };
|
|
||||||
cv::Mat hist;
|
|
||||||
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false);
|
|
||||||
|
|
||||||
int hist_array[256];
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
hist_array[i] = hist.at<float>(i, 0);
|
|
||||||
|
|
||||||
int length = 1;
|
|
||||||
const int length_max = 255 - threshold;
|
|
||||||
while (length < length_max)
|
|
||||||
{
|
|
||||||
for (int i = threshold + 1; i < 256 - length; i++)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
uint pixSum = 0;
|
|
||||||
for (int j = 0; j < length; j++)
|
|
||||||
{
|
|
||||||
count += hist_array[j + i];
|
|
||||||
pixSum += hist_array[j + i] * (i + j);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count >= threnshold)
|
|
||||||
return pixSum / count;
|
|
||||||
}
|
|
||||||
length++;
|
|
||||||
}
|
|
||||||
return 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::Scalar getBackGroudColor(const cv::Mat& image, int total, int threshold)
|
|
||||||
{
|
|
||||||
if (image.channels() == 3)
|
|
||||||
{
|
|
||||||
cv::Mat image_bgr[3];
|
|
||||||
cv::split(image, image_bgr);
|
|
||||||
|
|
||||||
uchar bgr[3];
|
|
||||||
for (size_t i = 0; i < 3; i++)
|
|
||||||
bgr[i] = getBackGroudChannelMean(image_bgr[i], total, threshold);
|
|
||||||
return cv::Scalar(bgr[0], bgr[1], bgr[2]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return cv::Scalar::all(getBackGroudChannelMean(image, total, threshold));
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyDispersion dispersion_apply;
|
|
||||||
#define COLOR_SCALE_THRE 0.5
|
|
||||||
void autoCrop_desaskew_fillBlank(const cv::Mat& src, cv::Mat& dst, bool isAutoCrop, bool isDesaskew, bool isFillBlank, int dWidth, int dHeight,
|
|
||||||
bool isConvex, bool isColorBlank, double threshold, int noise, int indent, bool isNormalCrop, bool dispersion)
|
|
||||||
{
|
|
||||||
if (src.empty()) return;
|
|
||||||
|
|
||||||
if (isNormalCrop)
|
|
||||||
{
|
|
||||||
cv::Rect roi = cv::Rect((src.cols - dWidth) / 2, FRONT_TOP, dWidth, dHeight) & cv::Rect(0, 0, src.cols, src.rows);
|
|
||||||
dst = src(roi).clone();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isAutoCrop && !isDesaskew && !isFillBlank && (dWidth <= 0 || dHeight <= 0))
|
|
||||||
{
|
|
||||||
dst = src.clone();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::Mat resizeMat;
|
|
||||||
cv::Mat thre;
|
|
||||||
|
|
||||||
cv::resize(src, resizeMat, cv::Size(), FX_FY, FX_FY, cv::INTER_NEAREST);
|
|
||||||
hg::threshold_Mat(resizeMat, thre, threshold);
|
|
||||||
|
|
||||||
if (noise > 0)
|
|
||||||
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, getStructuringElement(cv::MORPH_RECT, cv::Size(noise * FX_FY, 1)),
|
|
||||||
cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
|
|
||||||
|
|
||||||
std::vector<cv::Vec4i> hierarchy;
|
|
||||||
std::vector<std::vector<cv::Point>> contours;
|
|
||||||
|
|
||||||
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
|
|
||||||
|
|
||||||
for (std::vector<cv::Point>& sub : contours)
|
|
||||||
for (cv::Point& p : sub)
|
|
||||||
p /= FX_FY;
|
|
||||||
|
|
||||||
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
|
|
||||||
|
|
||||||
if (maxContour.empty())
|
|
||||||
{
|
|
||||||
if (isAutoCrop)
|
|
||||||
dst = src.clone();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv::Rect roi = cv::Rect((src.cols - dWidth) / 2, FRONT_TOP, dWidth, dHeight) & cv::Rect(0, 0, src.cols, src.rows);
|
|
||||||
dst = src(roi).clone();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
|
|
||||||
|
|
||||||
if (dispersion)
|
|
||||||
{
|
|
||||||
cv::Mat mat_dispersion = src(cv::boundingRect(maxContour));
|
|
||||||
dispersion_apply.apply(mat_dispersion, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::Scalar blankColor;
|
|
||||||
if (isFillBlank)
|
|
||||||
if (isColorBlank)
|
|
||||||
blankColor = getBackGroudColor(resizeMat, rect.size.area() * FX_FY * FX_FY, COLOR_SCALE_THRE);
|
|
||||||
else
|
|
||||||
blankColor = cv::Scalar::all(255);
|
|
||||||
else
|
|
||||||
blankColor = cv::Scalar::all(0);
|
|
||||||
|
|
||||||
if (isAutoCrop)
|
|
||||||
if (isDesaskew)
|
|
||||||
dst = cv::Mat(cv::Size(rect.size), src.type(), blankColor);
|
|
||||||
else
|
|
||||||
dst = cv::Mat(rect.boundingRect().size(), src.type(), blankColor);
|
|
||||||
else
|
|
||||||
dst = cv::Mat(dHeight, dWidth, src.type(), blankColor);
|
|
||||||
|
|
||||||
cv::Mat dstROI;
|
|
||||||
if (isDesaskew && rect.angle != 0)
|
|
||||||
{
|
|
||||||
cv::Point2f srcTri[4], dstTri[3];
|
|
||||||
rect.points(srcTri);
|
|
||||||
srcTri[0].x -= 1;
|
|
||||||
srcTri[1].x -= 1;
|
|
||||||
srcTri[2].x -= 1;
|
|
||||||
|
|
||||||
int w = rect.size.width;
|
|
||||||
int h = rect.size.height;
|
|
||||||
int x = (dst.cols - w) / 2;
|
|
||||||
int y = (dst.rows - h) / 2;
|
|
||||||
dstTri[0] = cv::Point2f(0, h);
|
|
||||||
dstTri[1] = cv::Point2f(0, 0);
|
|
||||||
dstTri[2] = cv::Point2f(w, 0);
|
|
||||||
|
|
||||||
dstROI = dst(cv::Rect(x, y, w, h) & cv::Rect(0, 0, dst.cols, dst.rows));
|
|
||||||
myWarpAffine(src, dstROI, cv::getAffineTransform(srcTri, dstTri), dstROI.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv::Rect bounding = cv::boundingRect(maxContour);
|
|
||||||
|
|
||||||
if (bounding.width > dst.cols)
|
|
||||||
{
|
|
||||||
bounding.x += (bounding.width - dst.cols) / 2;
|
|
||||||
bounding.width = dst.cols;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bounding.height > dst.rows)
|
|
||||||
{
|
|
||||||
bounding.y += (bounding.height - dst.rows) / 2;
|
|
||||||
bounding.height = dst.rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
dstROI = dst(cv::Rect((dst.cols - bounding.width) / 2, (dst.rows - bounding.height) / 2, bounding.width, bounding.height));
|
|
||||||
src(bounding).copyTo(dstROI);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFillBlank)
|
|
||||||
{
|
|
||||||
if (isConvex)
|
|
||||||
{
|
|
||||||
hg::convexHull(maxContour, maxContour);
|
|
||||||
contours.clear();
|
|
||||||
contours.push_back(maxContour);
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::Point2f srcTri[4], dstTri[3];
|
|
||||||
int w, h;
|
|
||||||
if (isDesaskew && rect.angle != 0)
|
|
||||||
{
|
|
||||||
rect.points(srcTri);
|
|
||||||
srcTri[0].x -= 1;
|
|
||||||
srcTri[1].x -= 1;
|
|
||||||
srcTri[2].x -= 1;
|
|
||||||
w = rect.size.width;
|
|
||||||
h = rect.size.height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv::Rect bounding = rect.boundingRect();
|
|
||||||
srcTri[0] = cv::Point(bounding.x, bounding.br().y - 1);
|
|
||||||
srcTri[1] = cv::Point(bounding.x, bounding.y);
|
|
||||||
srcTri[2] = cv::Point(bounding.br().x - 1, bounding.y);
|
|
||||||
w = bounding.width;
|
|
||||||
h = bounding.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
dstTri[0] = cv::Point2f((dstROI.cols - w) / 2 + indent, (dstROI.rows - h) / 2 + h - indent);
|
|
||||||
dstTri[1] = cv::Point2f((dstROI.cols - w) / 2 + indent, (dstROI.rows - h) / 2 + indent);
|
|
||||||
dstTri[2] = cv::Point2f((dstROI.cols - w) / 2 - indent + w, (dstROI.rows - h) / 2 + indent);
|
|
||||||
cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
|
||||||
|
|
||||||
double* ptr_m = reinterpret_cast<double*>(warp_mat.data);
|
|
||||||
double a = ptr_m[0];
|
|
||||||
double b = ptr_m[1];
|
|
||||||
double c = ptr_m[2];
|
|
||||||
double d = ptr_m[3];
|
|
||||||
double e = ptr_m[4];
|
|
||||||
double f = ptr_m[5];
|
|
||||||
|
|
||||||
int x, y;
|
|
||||||
for (std::vector<cv::Point>& sub : contours)
|
|
||||||
for (cv::Point& p : sub)
|
|
||||||
{
|
|
||||||
x = p.x;
|
|
||||||
y = p.y;
|
|
||||||
p.x = static_cast<int>(a * x + b * y + c);
|
|
||||||
p.y = static_cast<int>(d * x + e * y + f);
|
|
||||||
}
|
|
||||||
|
|
||||||
contours.push_back(std::vector<cv::Point>());
|
|
||||||
contours[contours.size() - 1].push_back(cv::Point(-1, dstROI.rows - 1));
|
|
||||||
contours[contours.size() - 1].push_back(cv::Point(-1, -1));
|
|
||||||
contours[contours.size() - 1].push_back(cv::Point(dstROI.cols, -1));
|
|
||||||
contours[contours.size() - 1].push_back(cv::Point(dstROI.cols, dst.rows));
|
|
||||||
hg::fillPolys(dstROI, contours, blankColor);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:自动裁剪、纠偏、除黑底
|
|
||||||
* 作者:刘丁绿
|
|
||||||
* 生成时间_020/4/21
|
|
||||||
* 最近修改时间:2020/4/21 v1.0
|
|
||||||
2020/7/22 v1.1 增加获取图像有效区域轮廓的接口maxContour(用于配合一体机的“跳过空白页”算法,PC端暂时无需使用_
|
|
||||||
2020/10/16 v1.2 修复自动裁剪尺寸精度丢失的BUG;提高除黑底缩进精度
|
|
||||||
2020/10/28 v1.2.1 修复凹凸多边形填充背景的逻辑BUG
|
|
||||||
2020/10/28 v1.2.2 修复图像处理必定会缩小尺寸的BUG
|
|
||||||
2020/10/29 v1.2.3 避免无谓的纠偏(0°纠偏_
|
|
||||||
2020/11/30 v1.3.0 增加功能,可识别文稿颜色进行填充黑底
|
|
||||||
2021/06/18 v1.3.1 调整默认noise
|
|
||||||
2021/07/01 v1.3.2 修复 无裁切情况下,自适应颜色除黑底不生效的BUG
|
|
||||||
2021/07/08 v1.3.3 完善流程。当无法定位内容时,且为固定幅面裁切,则返回按照固定幅面进行裁切的结果
|
|
||||||
2021/07/08 v1.3.4 调整参数,让消除背景噪声不对纵向像素造成影响
|
|
||||||
2021/07/09 v1.3.5 增加normalCrop机制,当m_isCrop m_isDesaskew m_isFillBlank均为false时可选用,实现传统裁切
|
|
||||||
2021/07/13 v1.3.6 调整normalCrop逻辑,当normalCrop为true时,m_isCrop m_isDesaskew m_isFillBlank失效
|
|
||||||
2021/07/19 v1.3.7 调整仿射变换模式为INTER_LINEAR
|
|
||||||
2021/07/22 v1.3.8 修复第二次寻边,找不到外界轮廓会导致崩溃的BUG
|
|
||||||
2021/08/02 v1.3.9 精细化除黑底算法,可以应对只有条纹内容的黑色图像
|
|
||||||
2021/10/08 v1.3.10 优化算法,用腐蚀代替绘制实现缩进,提高整体算法效率
|
|
||||||
2021/10/19 v1.3.11 解决一些极端情况,例如纸张自然0角度,纸张定格在图像顶部的处理
|
|
||||||
2021/10/19 v1.3.12 微调裁切纠偏像素精度
|
|
||||||
2022/04/24 v1.4 重构算法,增加除色散功能
|
|
||||||
2022/05/03 v1.4.1 完善逻辑
|
|
||||||
2022/06/09 v1.4.2 修复获取文稿底色时,threshold值,设为固定值0.5
|
|
||||||
* 版本号:v1.4.2
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_AUTO_CROP_H
|
|
||||||
#define IMAGE_APPLY_AUTO_CROP_H
|
|
||||||
|
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
class CImageApplyAutoCrop : public CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CImageApplyAutoCrop();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* isCrop [in]:自动幅面裁剪使能,true自动裁剪,false为固定裁剿
|
|
||||||
* isDesaskew [in]:自动纠偏使能,true自动纠偏,false为不纠偏
|
|
||||||
* isFillBlank [in]:黑底填充使能,true为填充,false为不填充
|
|
||||||
* fixedSize [in]:固定幅面尺寸,当isCrop为false时生效,结果尺寸按fixedSize大小输出,单位像紿
|
|
||||||
* isConvex [in]:黑底填充时的填充方式,true为凸多边形填充,false为凹多边形填充,默认true
|
|
||||||
* isFillColor [in]:黑底填充时采用自适应色彩填充,false为白色填充,true为自适应文稿底色填充,默认false
|
|
||||||
* threshold [in]:二值化阈值,取值范囿0, 255),默访0
|
|
||||||
* noise [in]:除噪像素,能够消除noise宽度的背景竖条纹干扰,默访
|
|
||||||
* indent [in]:轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默访
|
|
||||||
* normalCrop [in]:为true时,m_isCrop m_isDesaskew m_isFillBlank失效,固定裁切采用最传统的裁切方式,默认false
|
|
||||||
* dispersion [in]:为true时,除色散;false时不除色散。默认为true
|
|
||||||
*/
|
|
||||||
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true,
|
|
||||||
bool isFillColor = false, double threshold = 40, int noise = 8, int indent = 5, bool normalCrop = false, bool dispersion = true);
|
|
||||||
|
|
||||||
virtual ~CImageApplyAutoCrop();
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib, int side);
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
|
||||||
|
|
||||||
bool isAutoCrop() { return m_isCrop; }
|
|
||||||
|
|
||||||
bool isFillBlank() { return m_isFillBlank; }
|
|
||||||
|
|
||||||
bool isDesaskew() { return m_isDesaskew; }
|
|
||||||
|
|
||||||
bool isConvexHull() { return m_isConvexHull; }
|
|
||||||
|
|
||||||
cv::RotatedRect getROI() { return m_rect; }
|
|
||||||
|
|
||||||
double threshold() { return m_threshold; }
|
|
||||||
|
|
||||||
int noise() { return m_noise; }
|
|
||||||
|
|
||||||
int indent() { return m_indent; }
|
|
||||||
|
|
||||||
cv::Size fixedSize() { return m_fixedSize; }
|
|
||||||
|
|
||||||
const std::vector<cv::Point>& maxContour() { return m_maxContour; }
|
|
||||||
|
|
||||||
void setAutoCrop(bool enabled) { m_isCrop = enabled; }
|
|
||||||
|
|
||||||
void setFillBlank(bool enabled) { m_isFillBlank = enabled; }
|
|
||||||
|
|
||||||
void setDesaskew(bool enabled) { m_isDesaskew = enabled; }
|
|
||||||
|
|
||||||
void setConvexHull(bool convex) { m_isConvexHull = convex; }
|
|
||||||
|
|
||||||
void setThreshold(double value) { m_threshold = value; }
|
|
||||||
|
|
||||||
void setNoise(int value) { m_noise = value; }
|
|
||||||
|
|
||||||
void setIndent(int value) { m_indent = value; }
|
|
||||||
|
|
||||||
void setFixedSize(cv::Size size) { m_fixedSize = size; }
|
|
||||||
|
|
||||||
void setDispersion(bool enable) { m_isDispersion = enable; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_isCrop;
|
|
||||||
bool m_isDesaskew;
|
|
||||||
bool m_isFillBlank;
|
|
||||||
bool m_isConvexHull;
|
|
||||||
bool m_isFillColor;
|
|
||||||
bool m_isDispersion;
|
|
||||||
|
|
||||||
double m_threshold;
|
|
||||||
int m_noise;
|
|
||||||
int m_indent;
|
|
||||||
bool m_normalCrop; //为true且m_isCrop m_isDesaskew m_isFillBlank均为false时生效,固定裁切采用最传统的裁切方弿
|
|
||||||
cv::Size m_fixedSize;
|
|
||||||
cv::RotatedRect m_rect;
|
|
||||||
std::vector<cv::RotatedRect> m_rects;
|
|
||||||
std::vector<cv::Point> m_maxContour;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void autoCrop_desaskew_fillBlank(const cv::Mat& src, cv::Mat& dst, bool isAutoCrop, bool isDesaskew, bool isFillBlank, int dWidth, int dHeight,
|
|
||||||
bool isConvex = true, bool isColorBlank = false, double threshold = 40, int noise = 8, int indent = 5, bool isNormalCrop = false, bool dispersion = true);
|
|
||||||
#endif // !IMAGE_APPLY_AUTO_CROP_H
|
|
|
@ -1,167 +0,0 @@
|
||||||
#include "ImageApplyBWBinaray.h"
|
|
||||||
|
|
||||||
CImageApplyBWBinaray::CImageApplyBWBinaray(ThresholdType type, int threshold, int blockSize, int constant)
|
|
||||||
: m_threshold(threshold)
|
|
||||||
, m_type(type)
|
|
||||||
, m_blockSize(blockSize)
|
|
||||||
, m_constant(constant)
|
|
||||||
, m_table(new uchar[256])
|
|
||||||
{
|
|
||||||
memset(m_table, 255, 256);
|
|
||||||
memset(m_table, 0, static_cast<size_t>(m_threshold));
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyBWBinaray::CImageApplyBWBinaray()
|
|
||||||
: m_threshold(120)
|
|
||||||
, m_type(ThresholdType::THRESH_BINARY)
|
|
||||||
, m_blockSize(51)
|
|
||||||
, m_constant(41)
|
|
||||||
, m_table(new uchar[256])
|
|
||||||
{
|
|
||||||
memset(m_table, 255, 256);
|
|
||||||
memset(m_table, 0, static_cast<size_t>(m_threshold));
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyBWBinaray::~CImageApplyBWBinaray(void)
|
|
||||||
{
|
|
||||||
delete[] m_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define THRESHOLD_LOW 30
|
|
||||||
#define THRESHOLD_UP 245
|
|
||||||
void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side)
|
|
||||||
{
|
|
||||||
(void)side;
|
|
||||||
if (pDib.empty()) return;
|
|
||||||
|
|
||||||
if (pDib.channels() == 3)
|
|
||||||
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
|
|
||||||
|
|
||||||
cv::Mat integ;
|
|
||||||
int blockSize = m_blockSize;//邻域尺寸
|
|
||||||
int threshold = m_constant;
|
|
||||||
int low = THRESHOLD_LOW;
|
|
||||||
int up = THRESHOLD_UP;
|
|
||||||
int halfSize = blockSize / 2;
|
|
||||||
int square_blockSize = blockSize * blockSize;
|
|
||||||
switch (m_type)
|
|
||||||
{
|
|
||||||
case ThresholdType::THRESH_BINARY:
|
|
||||||
cv::integral(pDib, integ, CV_32S);
|
|
||||||
|
|
||||||
for (int j = halfSize; j < integ.rows - halfSize - 1; j++)
|
|
||||||
{
|
|
||||||
uchar* data = pDib.ptr<uchar>(j);
|
|
||||||
int* idata1 = integ.ptr<int>(j - halfSize);
|
|
||||||
int* idata2 = integ.ptr<int>(j + halfSize + 1);
|
|
||||||
for (int i = halfSize; i < integ.cols - halfSize - 1; i++)
|
|
||||||
{
|
|
||||||
if (data[i] < low)
|
|
||||||
data[i] = 0;
|
|
||||||
else if (data[i] > up)
|
|
||||||
data[i] = 255;
|
|
||||||
else
|
|
||||||
data[i] = data[i] < ((idata2[i + halfSize + 1] - idata2[i - halfSize] - idata1[i + halfSize + 1] + idata1[i - halfSize]) / square_blockSize - threshold) ? 0 : 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::threshold(pDib(cv::Rect(0, 0, halfSize, pDib.rows)), pDib(cv::Rect(0, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY);
|
|
||||||
cv::threshold(pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY);
|
|
||||||
cv::threshold(pDib(cv::Rect(0, 0, pDib.cols, halfSize)), pDib(cv::Rect(0, 0, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY);
|
|
||||||
cv::threshold(pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY);
|
|
||||||
break;
|
|
||||||
case ThresholdType::THRESH_OTSU:
|
|
||||||
cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU);
|
|
||||||
break;
|
|
||||||
case ThresholdType::ADAPTIVE_GAUSSIAN:
|
|
||||||
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
|
|
||||||
break;
|
|
||||||
case ThresholdType::ADAPTIVE_MEAN:
|
|
||||||
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
|
|
||||||
break;
|
|
||||||
case ThresholdType::ERROR_DIFFUSION:
|
|
||||||
errorDiffuse(pDib);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LOG
|
|
||||||
FileTools::write_log("imgprc.txt", "exit CImageApplyBWBinaray apply");
|
|
||||||
#endif // LOG
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyBWBinaray::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|
||||||
{
|
|
||||||
(void)isTwoSide;
|
|
||||||
int i = 0;
|
|
||||||
for (cv::Mat& var : mats) {
|
|
||||||
if (i != 0 && isTwoSide == false)
|
|
||||||
break;
|
|
||||||
if (!var.empty())
|
|
||||||
apply(var, 0);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyBWBinaray::errorDiffuse(cv::Mat& image)
|
|
||||||
{
|
|
||||||
if (image.rows < 3 || image.cols < 3)
|
|
||||||
{
|
|
||||||
cv::threshold(image, image, m_threshold, 255, CV_THRESH_BINARY);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::Mat dst;
|
|
||||||
image.convertTo(dst, CV_16S);
|
|
||||||
|
|
||||||
size_t rows = static_cast<size_t>(image.rows) - 1;
|
|
||||||
size_t cols = static_cast<size_t>(image.cols) - 1;
|
|
||||||
|
|
||||||
short** pixels_dst = new short* [static_cast<size_t>(image.rows)];
|
|
||||||
for (int i = 0; i < image.rows; i++)
|
|
||||||
pixels_dst[i] = reinterpret_cast<short*>(dst.data + i * static_cast<int>(dst.step));
|
|
||||||
|
|
||||||
short error;
|
|
||||||
for (size_t y = 0; y < rows; y++)
|
|
||||||
for (size_t x = 1; x < cols; x++)
|
|
||||||
{
|
|
||||||
short dstPix = pixels_dst[y][x];
|
|
||||||
if (dstPix >= m_threshold)
|
|
||||||
{
|
|
||||||
pixels_dst[y][x] = 255;
|
|
||||||
error = dstPix - 255;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixels_dst[y][x] = 0;
|
|
||||||
error = dstPix;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixels_dst[y][x + 1] += error * 1 / 16;
|
|
||||||
pixels_dst[y + 1][x - 1] += error * 1 / 16;
|
|
||||||
pixels_dst[y + 1][x] += error * 1 / 16;
|
|
||||||
pixels_dst[y + 1][x + 1] += error * 1 / 16;
|
|
||||||
}
|
|
||||||
image.release();
|
|
||||||
dst.convertTo(image, CV_8U);
|
|
||||||
|
|
||||||
rows++;
|
|
||||||
uchar* ptr = image.data;
|
|
||||||
size_t step = image.step;
|
|
||||||
size_t offset;
|
|
||||||
for (size_t y = 0; y < rows; y++)
|
|
||||||
{
|
|
||||||
offset = y * step;
|
|
||||||
ptr[offset] = m_table[ptr[offset]];
|
|
||||||
offset += cols;
|
|
||||||
ptr[offset] = m_table[ptr[offset]];
|
|
||||||
}
|
|
||||||
|
|
||||||
cols++;
|
|
||||||
ptr = image.data + step * (rows - 1);
|
|
||||||
for (size_t x = 0; x < cols; x++)
|
|
||||||
ptr[x] = m_table[ptr[x]];
|
|
||||||
|
|
||||||
delete[] pixels_dst;
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:二值化处理
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2020/4/21
|
|
||||||
* 最近修改时间:2020/5/28 v1.1 修改传统二值化算法,改用自定义局部自适应阈值算法
|
|
||||||
2020/5/29 v1.2 在传统二值化之前添加增强锐化效果,二值化之后增加除噪效果
|
|
||||||
2020/6/19 v1.3 编写自定义自适应阈值二值化;取消锐化处理;保留除噪效果
|
|
||||||
2020/12/21 v1.3.1 调整自适应阈值上下限
|
|
||||||
2020/12/21 v1.3.2 调整blockSize,从原来的51调整到25
|
|
||||||
2022/05/25 v1.3.3 调整blockSize和constant,对THRESH_BINARY同样有效
|
|
||||||
* 版本号:v1.3.3
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_BW_BINARAY_H
|
|
||||||
#define IMAGE_APPLY_BW_BINARAY_H
|
|
||||||
|
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
class CImageApplyBWBinaray:public CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum class ThresholdType
|
|
||||||
{
|
|
||||||
THRESH_BINARY = 0, //传统二值化
|
|
||||||
THRESH_OTSU, //大津阈值
|
|
||||||
|
|
||||||
ADAPTIVE_GAUSSIAN, //高斯局部自适应阈值
|
|
||||||
ADAPTIVE_MEAN, //均值局部自适应阈值
|
|
||||||
|
|
||||||
ERROR_DIFFUSION //错误扩散
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* type [in]:二值化模式
|
|
||||||
* threshold [in]:阈值,当选择THRESH_OTSU时无效
|
|
||||||
* blockSize [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,表示局部观察块的宽度
|
|
||||||
* constant [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,与blockSize形成比例关系,作为局部筛选阈值
|
|
||||||
*/
|
|
||||||
CImageApplyBWBinaray(ThresholdType type, int threshold = 120, int blockSize = 51, int constant = 41);
|
|
||||||
|
|
||||||
CImageApplyBWBinaray();
|
|
||||||
|
|
||||||
virtual ~CImageApplyBWBinaray(void);
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib,int side);
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
|
||||||
|
|
||||||
double getThreshold() { return m_threshold; }
|
|
||||||
|
|
||||||
ThresholdType getThresholdType() { return m_type; }
|
|
||||||
|
|
||||||
int getBlockSize() { return m_blockSize; }
|
|
||||||
|
|
||||||
double getConstant() { return m_constant; }
|
|
||||||
|
|
||||||
void setThreshold(double value) { m_threshold = value; }
|
|
||||||
|
|
||||||
void setThresholdType(ThresholdType type) { m_type = type; }
|
|
||||||
|
|
||||||
void setBlockSize(int value) { m_blockSize = value; }
|
|
||||||
|
|
||||||
void setConstant(double value) { m_constant = value; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void errorDiffuse(cv::Mat& image);
|
|
||||||
|
|
||||||
private:
|
|
||||||
double m_threshold;
|
|
||||||
|
|
||||||
ThresholdType m_type;
|
|
||||||
|
|
||||||
int m_blockSize;
|
|
||||||
|
|
||||||
double m_constant;
|
|
||||||
|
|
||||||
uchar* m_table;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!IMAGE_APPLY_BW_BINARAY_H
|
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
#include "ImageApplyChannel.h"
|
|
||||||
#include "ImageApplyAdjustColors.h"
|
|
||||||
|
|
||||||
CImageApplyChannel::CImageApplyChannel()
|
|
||||||
: m_channel(Invalid)
|
|
||||||
, colors(new CImageApplyAdjustColors(0, 30, 1.0))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyChannel::CImageApplyChannel(Channel channel)
|
|
||||||
: m_channel(channel)
|
|
||||||
, colors(new CImageApplyAdjustColors(0, 30, 1.0))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyChannel::~CImageApplyChannel()
|
|
||||||
{
|
|
||||||
if (colors != nullptr) delete colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyChannel::apply(cv::Mat& pDib, int side)
|
|
||||||
{
|
|
||||||
(void)side;
|
|
||||||
if (pDib.empty()) return;
|
|
||||||
|
|
||||||
cv::Mat dst(pDib.rows, pDib.cols, CV_8UC1);
|
|
||||||
switch (m_channel)
|
|
||||||
{
|
|
||||||
case Red:
|
|
||||||
cv::extractChannel(pDib, dst, 2);
|
|
||||||
colors->apply(pDib, side);
|
|
||||||
break;
|
|
||||||
case Green:
|
|
||||||
cv::extractChannel(pDib, dst, 1);
|
|
||||||
break;
|
|
||||||
case Blue:
|
|
||||||
cv::extractChannel(pDib, dst, 0);
|
|
||||||
break;
|
|
||||||
case All:
|
|
||||||
colourless(pDib, dst, 80);
|
|
||||||
break;
|
|
||||||
case Except_Red:
|
|
||||||
except_channel(pDib, dst, 2);
|
|
||||||
break;
|
|
||||||
case Except_Green:
|
|
||||||
except_channel(pDib, dst, 1);
|
|
||||||
break;
|
|
||||||
case Except_Blue:
|
|
||||||
except_channel(pDib, dst, 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pDib.release();
|
|
||||||
pDib = dst;
|
|
||||||
|
|
||||||
#ifdef LOG
|
|
||||||
FileTools::write_log("imgprc.txt", "exit CImageApplyChannel apply");
|
|
||||||
#endif // LOG
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyChannel::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|
||||||
{
|
|
||||||
(void)isTwoSide;
|
|
||||||
int i = 0;
|
|
||||||
for (cv::Mat& var : mats) {
|
|
||||||
if (i != 0 && isTwoSide == false)
|
|
||||||
break;
|
|
||||||
if (!var.empty())
|
|
||||||
apply(var, 0);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyChannel::except_channel(const cv::Mat& src, cv::Mat& dst, int channel)
|
|
||||||
{
|
|
||||||
cv::Mat mv[3];
|
|
||||||
cv::split(src, mv);
|
|
||||||
cv::Mat mask, mask1, mask2;
|
|
||||||
switch (channel)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
mask1 = mv[0] - mv[1];
|
|
||||||
mask2 = mv[0] - mv[2];
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
mask1 = mv[1] - mv[0];
|
|
||||||
mask2 = mv[1] - mv[2];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mask1 = mv[2] - mv[1];
|
|
||||||
mask2 = mv[2] - mv[0];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cv::min(mask1, mask2, mask);
|
|
||||||
|
|
||||||
cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);
|
|
||||||
dst -= mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyChannel::colourless(const cv::Mat& src, cv::Mat& dst, uchar threshold)
|
|
||||||
{
|
|
||||||
if (src.channels() != 3)
|
|
||||||
{
|
|
||||||
dst = src;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::Mat hsv;
|
|
||||||
cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV_FULL);
|
|
||||||
cv::Mat mv_hsv[3];
|
|
||||||
cv::split(hsv, mv_hsv);
|
|
||||||
size_t total = mv_hsv[1].total();
|
|
||||||
uchar* ptr_s = mv_hsv[1].data;
|
|
||||||
uchar* ptr_v = mv_hsv[2].data;
|
|
||||||
for (size_t i = 0; i < total; i++)
|
|
||||||
if (ptr_s[i] > threshold)
|
|
||||||
{
|
|
||||||
ptr_s[i] = 0;
|
|
||||||
ptr_v[i] = 255;
|
|
||||||
}
|
|
||||||
cv::merge(mv_hsv, 3, hsv);
|
|
||||||
cv::cvtColor(hsv, hsv, cv::COLOR_HSV2BGR_FULL);
|
|
||||||
cv::cvtColor(hsv, dst, cv::COLOR_BGR2GRAY);
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:通道提取,又名除色。可提取BGR图像中的单个通道、两种通道的混合以及去除彩色像素的图像,目标图像均为灰度图
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2020/4/21
|
|
||||||
* 最近修改时间:v1.0 2020/4/21
|
|
||||||
v1.1 2020/6/11 在除红时,增加对比度,提高除色效果。
|
|
||||||
v1.2 2020/7/21 修正之前增强红绿蓝效果的色彩配比。
|
|
||||||
v1.3 2021/5/24 替换红色增强算法方案。
|
|
||||||
* 版本号:v1.3
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_CHANNEL_H
|
|
||||||
#define IMAGE_APPLY_CHANNEL_H
|
|
||||||
|
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
class CImageApplyAdjustColors;
|
|
||||||
class CImageApplyChannel : public CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef enum channel
|
|
||||||
{
|
|
||||||
Red, //红色通道
|
|
||||||
Green, //绿色通道
|
|
||||||
Blue, //蓝色通道
|
|
||||||
All, //去除所有HSV色彩结构中,S大于80的色彩
|
|
||||||
Invalid, //无效
|
|
||||||
Except_Red, //绿蓝色通道混合
|
|
||||||
Except_Green, //红蓝色通道混合
|
|
||||||
Except_Blue //红绿色通道混合
|
|
||||||
}Channel;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CImageApplyChannel();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* channel [in]:通道模式
|
|
||||||
* */
|
|
||||||
CImageApplyChannel(Channel channel);
|
|
||||||
|
|
||||||
virtual ~CImageApplyChannel(void);
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib,int side);
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void except_channel(const cv::Mat& src, cv::Mat& dst, int channel);
|
|
||||||
|
|
||||||
void colourless(const cv::Mat& src, cv::Mat& dst, uchar threshold = 80);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Channel m_channel;
|
|
||||||
CImageApplyAdjustColors* colors;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_CHANNEL_H
|
|
|
@ -1,156 +0,0 @@
|
||||||
#include "ImageApplyColorRecognition.h"
|
|
||||||
#include "ImageApplyBWBinaray.h"
|
|
||||||
#include "ImageApplyAdjustColors.h"
|
|
||||||
|
|
||||||
static CImageApplyBWBinaray m_bw;
|
|
||||||
static CImageApplyAdjustColors m_ac(0, 50, 1.0f);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检测图像是否是彩色。当前逻辑仅针对红色像素进行判断,即存在红色像素则为彩色,否则为非彩色
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="image">待测图像</param>
|
|
||||||
/// <returns>true为彩色,false为非彩色</returns>
|
|
||||||
bool isColor(const cv::Mat& image)
|
|
||||||
{
|
|
||||||
if (image.channels() != 3) return false;
|
|
||||||
|
|
||||||
cv::Mat pDib_resize;
|
|
||||||
cv::resize(image, pDib_resize, cv::Size(image.cols / 4, image.rows / 4), 0, 0, cv::INTER_NEAREST);
|
|
||||||
|
|
||||||
cv::Mat hsv;
|
|
||||||
cv::cvtColor(pDib_resize, hsv, cv::COLOR_BGR2HSV_FULL);
|
|
||||||
std::vector<cv::Mat> hsv_channels;
|
|
||||||
cv::split(hsv, hsv_channels);
|
|
||||||
|
|
||||||
cv::Mat range_s1, range_s2;
|
|
||||||
cv::inRange(hsv_channels[1], 220, 255, range_s1); //饱和度在[220, 255]的像素
|
|
||||||
cv::inRange(hsv_channels[1], 50, 220, range_s2); //饱和度在[50, 220]的像素
|
|
||||||
#if 0
|
|
||||||
cv::imwrite("range_s1.bmp", range_s1);
|
|
||||||
cv::imwrite("range_s2.bmp", range_s2);
|
|
||||||
#endif
|
|
||||||
double sum = cv::sum(range_s1)[0] / 255;
|
|
||||||
double total = range_s1.total();
|
|
||||||
|
|
||||||
// if (sum / total > 0.0001)
|
|
||||||
if (sum / total > 0.001)
|
|
||||||
return true;
|
|
||||||
sum += cv::sum(range_s2)[0] / 255;
|
|
||||||
// if (sum / total > 0.001)
|
|
||||||
if (sum / total > 0.03)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isGray(const cv::Mat& image)
|
|
||||||
{
|
|
||||||
//if (image.channels() == 3) return true;
|
|
||||||
|
|
||||||
//cv::Mat image_clone;
|
|
||||||
//cv::resize(image, image_clone, cv::Size(), 0.25, 0.25);
|
|
||||||
//int channels[] = { 0 };
|
|
||||||
//int histsize[] = { 256 };
|
|
||||||
//float range[] = { 0, 256 };
|
|
||||||
//const float* histRanges[] = { range };
|
|
||||||
//cv::Mat hist;
|
|
||||||
//cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, histsize, histRanges, true, false);
|
|
||||||
//float pixels[256] = { 0 };
|
|
||||||
//for (size_t i = 0; i < 256; i++)
|
|
||||||
// pixels[i] = hist.at<float>(i, 0);
|
|
||||||
|
|
||||||
|
|
||||||
//float sum = 0;
|
|
||||||
//for (size_t i = 0; i < 40; i++)
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
//float pixel_count0 = hist.at<float>(0, 0);
|
|
||||||
//float pixel_count255 = hist.at<float>(255, 0);
|
|
||||||
//float total = image_clone.total();
|
|
||||||
|
|
||||||
//return ((pixel_count0 + pixel_count255) / total) > 0.95;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyColorRecognition::CImageApplyColorRecognition(ColorRecognitionMode mode)
|
|
||||||
: m_mode(mode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyColorRecognition::~CImageApplyColorRecognition(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyColorRecognition::apply(cv::Mat& pDib, int side)
|
|
||||||
{
|
|
||||||
if (pDib.channels() != 3)
|
|
||||||
{
|
|
||||||
m_result = Gray;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_result = isColor(pDib) ? Color : Gray;
|
|
||||||
//if (m_result == Gray && pDib.channels() == 3)
|
|
||||||
// cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
|
|
||||||
|
|
||||||
//先判断是否需要判断是彩色
|
|
||||||
//if (m_mode == AllColor || m_mode == Color_Gray || m_mode == Color_Mono)
|
|
||||||
//{
|
|
||||||
// //如果是彩色,直接退出
|
|
||||||
// if (isColor(pDib))
|
|
||||||
// {
|
|
||||||
// m_result = Color;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (pDib.channels() == 3)
|
|
||||||
// cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
|
|
||||||
|
|
||||||
//if (m_mode == Color_Gray)
|
|
||||||
//{
|
|
||||||
// m_result = Gray;
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (m_mode == Color_Mono)
|
|
||||||
//{
|
|
||||||
// m_bw.apply(pDib, side);
|
|
||||||
// m_result = Mono;
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (isGray(pDib))
|
|
||||||
// m_result = Gray;
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// m_bw.apply(pDib, side);
|
|
||||||
// m_result = Mono;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyColorRecognition::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|
||||||
{
|
|
||||||
m_results.clear();
|
|
||||||
if (mats.empty()) return;
|
|
||||||
|
|
||||||
if (!mats[0].empty())
|
|
||||||
apply(mats[0], 0);
|
|
||||||
|
|
||||||
m_results.push_back(m_result);
|
|
||||||
|
|
||||||
if (isTwoSide && mats.size() > 1)
|
|
||||||
if (!mats[1].empty())
|
|
||||||
apply(mats[1], 1);
|
|
||||||
|
|
||||||
m_results.push_back(m_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyColorRecognition::ColorType CImageApplyColorRecognition::getResult()
|
|
||||||
{
|
|
||||||
return m_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CImageApplyColorRecognition::ColorType> CImageApplyColorRecognition::getResults()
|
|
||||||
{
|
|
||||||
return m_results;
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:色彩识别,将识别会“灰度”的24位图转化为256色8位图, 把识别为“黑白”图转化为二值化的8位图
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2020/7/17
|
|
||||||
* 最近修改时间:2021/04/19
|
|
||||||
* 版本号:v1.0 2020/7/17
|
|
||||||
* v1.1 2020/12/15 调整策略,仅判断红色像素,存在红色像素为彩色,否则为灰度;删除输出结果,直接转换图像。
|
|
||||||
* v1.2 2020/12/16 增加颜色限制模式(输出结果只可能两种),增加结果访问接口
|
|
||||||
* v1.3 2021/04/19 修改识别策略,能够识别占比1‰的彩色图像。只区分彩色和灰度图。
|
|
||||||
* v1.4 2021/06/18 调整二级色彩区间,从原来的[90, 200]调整为[50, 200]。
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_COLOR_RECOGNITION_H
|
|
||||||
#define IMAGE_APPLY_COLOR_RECOGNITION_H
|
|
||||||
|
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
class CImageApplyColorRecognition : public CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
//色彩识别模式
|
|
||||||
enum ColorRecognitionMode
|
|
||||||
{
|
|
||||||
AllColor, //全色模式 识别结果可能会是彩色、灰度、黑白
|
|
||||||
Color_Gray, //彩色灰度模式 识别结果只会是彩色或者灰度
|
|
||||||
Color_Mono, //彩色黑白模式 识别结果只会是彩色或者黑白
|
|
||||||
Gray_Mono //灰度黑白模式 识别结果只会是灰度或者黑白
|
|
||||||
};
|
|
||||||
|
|
||||||
//色彩类型
|
|
||||||
enum ColorType
|
|
||||||
{
|
|
||||||
Color, //彩色
|
|
||||||
Gray, //灰度
|
|
||||||
Mono //黑白
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
CImageApplyColorRecognition(ColorRecognitionMode mode = AllColor);
|
|
||||||
|
|
||||||
virtual ~CImageApplyColorRecognition(void);
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib, int side);
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取图片色彩类型。配合void apply(cv::Mat&, int)接口使用
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>色彩类型</returns>
|
|
||||||
ColorType getResult();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取图片色彩类型。配合void apply(std::vector<cv::Mat>&, int)接口使用
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>色彩类型数组</returns>
|
|
||||||
std::vector<ColorType> getResults();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ColorType m_result;
|
|
||||||
std::vector<ColorType> m_results;
|
|
||||||
ColorRecognitionMode m_mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_CONCATENATION_H
|
|
|
@ -1,114 +0,0 @@
|
||||||
#include "ImageApplyDiscardBlank.h"
|
|
||||||
#include "ImageProcess_Public.h"
|
|
||||||
|
|
||||||
CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh)
|
|
||||||
: m_threshold(threshold)
|
|
||||||
, m_edge(edge)
|
|
||||||
, m_devTh(devTh)
|
|
||||||
, m_meanTh(meanTh)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
|
|
||||||
{
|
|
||||||
if (apply(pDib, m_threshold, m_edge, m_devTh))
|
|
||||||
pDib.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|
||||||
{
|
|
||||||
(void)isTwoSide;
|
|
||||||
int i = 0;
|
|
||||||
for (cv::Mat& var : mats) {
|
|
||||||
if (i != 0 && isTwoSide == false)
|
|
||||||
break;
|
|
||||||
if (!var.empty())
|
|
||||||
apply(var, 0);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
if (val1[i] > val2[i])
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double meanTh)
|
|
||||||
{
|
|
||||||
double min, max;
|
|
||||||
cv::minMaxLoc(img, &min, &max, 0, 0, mask);
|
|
||||||
if (cv::mean(img, mask)[0] < meanTh)
|
|
||||||
return false;
|
|
||||||
return (max - min) < devTh;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, int blockSize, double devTh, double meanTh)
|
|
||||||
{
|
|
||||||
if (pDib.empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
cv::Mat img_resize;
|
|
||||||
cv::resize(pDib, img_resize, cv::Size(), 0.2, 0.2);
|
|
||||||
|
|
||||||
cv::Mat threshold_img;
|
|
||||||
if (img_resize.channels() == 3)
|
|
||||||
cv::cvtColor(img_resize, threshold_img, cv::COLOR_BGR2GRAY);
|
|
||||||
cv::threshold(img_resize.channels() == 3 ? threshold_img : img_resize, threshold_img, threshold, 255, CV_THRESH_BINARY);
|
|
||||||
|
|
||||||
std::vector<std::vector<cv::Point>> contours;
|
|
||||||
std::vector<cv::Vec4i> h1;
|
|
||||||
hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
|
|
||||||
|
|
||||||
std::vector<cv::Point> contour;
|
|
||||||
for (const std::vector<cv::Point>& sub : contours)
|
|
||||||
for (const cv::Point& p : sub)
|
|
||||||
contour.push_back(p);
|
|
||||||
|
|
||||||
cv::RotatedRect rect = hg::getBoundingRect(contour);
|
|
||||||
rect.size = cv::Size2f(rect.size.width - edge / 2.5, rect.size.height - edge / 2.5);
|
|
||||||
cv::Point2f box[4];
|
|
||||||
rect.points(box);
|
|
||||||
contour.clear();
|
|
||||||
contours.clear();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 4; i++)
|
|
||||||
contour.push_back(box[i]);
|
|
||||||
contours.push_back(contour);
|
|
||||||
cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1);
|
|
||||||
hg::fillPolys(mask, contours, cv::Scalar::all(255));
|
|
||||||
cv::blur(img_resize, img_resize, cv::Size(3, 3));
|
|
||||||
|
|
||||||
bool b = true;
|
|
||||||
if (img_resize.channels() == 3)
|
|
||||||
{
|
|
||||||
cv::Mat bgr[3];
|
|
||||||
cv::split(img_resize, bgr);
|
|
||||||
for (size_t i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
b &= maxMinCompare(bgr[i], mask, devTh, meanTh);
|
|
||||||
if (!b) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
b &= maxMinCompare(img_resize, mask, devTh, meanTh);
|
|
||||||
/*
|
|
||||||
if (b)
|
|
||||||
{
|
|
||||||
cv::imwrite("空白页/img1/" + std::to_string(index) + ".bmp", img_resize);
|
|
||||||
cv::imwrite("空白页/mask1/" + std::to_string(index) + ".bmp", mask);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv::imwrite("空白页/img2/" + std::to_string(index) + ".bmp", img_resize);
|
|
||||||
cv::imwrite("空白页/mask2/" + std::to_string(index) + ".bmp", mask);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:空白页识别。
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2020/4/21
|
|
||||||
* 最近修改时间:2020/4/21 v1.0
|
|
||||||
2020/8/12 v1.1 开放setIntensity和setMinArea;取消isNormal标识位;扩大setIntensity的设置范围,从[2, 20]扩大到[1, 100]
|
|
||||||
2020/8/25 v1.1.1 纸张检测缩进,从100像素调整到20像素
|
|
||||||
2020/10/16 v1.2 添加新接口,能够高效便捷判断图片是否为空白页
|
|
||||||
2020/10/19 v1.2.1 修复静态空白页判断识别误判的BUG
|
|
||||||
2021/04/13 v1.3.0 增加标准/票据标识位
|
|
||||||
2021/08/12 v1.3.1 添加防止不同opencv版本导致计算结果存在差异的代码。
|
|
||||||
2021/12/14 v1.3.2 重构算法。
|
|
||||||
2021/12/15 v1.3.3 微调参数。
|
|
||||||
2021/12/17 v1.3.4 增加背景色接口,实现对纯色纸张的空白页判定
|
|
||||||
* 版本号:v1.3.4
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_DISCARD_BLANK_H
|
|
||||||
#define IMAGE_APPLY_DISCARD_BLANK_H
|
|
||||||
|
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
class CImageApplyDiscardBlank : public CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
CImageApplyDiscardBlank(double threshold = 40, int edge = 150, double devTh = 50, double meanTh = 200);
|
|
||||||
|
|
||||||
virtual ~CImageApplyDiscardBlank(void);
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib, int side);
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
|
||||||
|
|
||||||
static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 150, int blockSize = 10, double devTh = 50, double meanTh = 200);
|
|
||||||
|
|
||||||
private:
|
|
||||||
double m_threshold;
|
|
||||||
int m_edge;
|
|
||||||
double m_devTh;
|
|
||||||
double m_meanTh;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // !IMAGE_APPLY_DISCARD_BLANK_H
|
|
|
@ -1,44 +0,0 @@
|
||||||
#include "ImageApplyDispersion.h"
|
|
||||||
|
|
||||||
CImageApplyDispersion::CImageApplyDispersion()
|
|
||||||
: CImageApply()
|
|
||||||
, m_kernal_b(3, 1, CV_32FC1)
|
|
||||||
, m_kernal_g(3, 1, CV_32FC1)
|
|
||||||
, m_kernal_r(3, 1, CV_32FC1)
|
|
||||||
{
|
|
||||||
m_kernal_b.at<float>(0, 0) = 0.15f;
|
|
||||||
m_kernal_b.at<float>(1, 0) = 1.15f;
|
|
||||||
m_kernal_b.at<float>(2, 0) = -0.3f;
|
|
||||||
|
|
||||||
m_kernal_g.at<float>(0, 0) = 0.806f;
|
|
||||||
m_kernal_g.at<float>(1, 0) = 0.484f;
|
|
||||||
m_kernal_g.at<float>(2, 0) = -0.3f;
|
|
||||||
|
|
||||||
m_kernal_r.at<float>(0, 0) = 0.484f;
|
|
||||||
m_kernal_r.at<float>(1, 0) = 0.806f;
|
|
||||||
m_kernal_r.at<float>(2, 0) = -0.3f;
|
|
||||||
}
|
|
||||||
|
|
||||||
CImageApplyDispersion::~CImageApplyDispersion()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyDispersion::apply(cv::Mat& pDib, int side)
|
|
||||||
{
|
|
||||||
(void)side;
|
|
||||||
|
|
||||||
if (pDib.channels() != 3) return;
|
|
||||||
|
|
||||||
cv::Mat bgr[3];
|
|
||||||
cv::split(pDib, bgr);
|
|
||||||
|
|
||||||
cv::filter2D(bgr[0], bgr[0], bgr[0].depth(), m_kernal_b);
|
|
||||||
cv::filter2D(bgr[1], bgr[1], bgr[1].depth(), m_kernal_g);
|
|
||||||
cv::filter2D(bgr[2], bgr[2], bgr[2].depth(), m_kernal_r);
|
|
||||||
|
|
||||||
cv::merge(bgr, 3, pDib);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImageApplyDispersion::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================
|
|
||||||
|
|
||||||
* 功能:消除色散
|
|
||||||
* 作者:刘丁维
|
|
||||||
* 生成时间:2021/09/24
|
|
||||||
* 最近修改时间:2021/11/12 v1.1.0 重构算法
|
|
||||||
* 2022/04/21 v1.2.0 重构算法
|
|
||||||
* 版本号:v1.2.0
|
|
||||||
|
|
||||||
* ====================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IMAGE_APPLY_DISPERSION_COLOR_H
|
|
||||||
#define IMAGE_APPLY_DISPERSION_COLOR_H
|
|
||||||
|
|
||||||
#include "ImageApply.h"
|
|
||||||
|
|
||||||
class CImageApplyDispersion : public CImageApply
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CImageApplyDispersion();
|
|
||||||
|
|
||||||
virtual ~CImageApplyDispersion();
|
|
||||||
|
|
||||||
virtual void apply(cv::Mat& pDib, int side);
|
|
||||||
|
|
||||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
|
||||||
|
|
||||||
private:
|
|
||||||
cv::Mat m_kernal_b;
|
|
||||||
cv::Mat m_kernal_g;
|
|
||||||
cv::Mat m_kernal_r;
|
|
||||||
};
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue