往PNG图像文件写数据
2015-12-26 17:05
274 查看
1. PngStruct.h // 定义PNG文件的数据结构
#pragma once
// 参考文章:http://blog.chinaunix.net/uid-20622737-id-3130430.html
// 根据PNG文件的定义来说,其文件头位置总是由8位固定的字节来描述的
// 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
#define PNG_FILE_HEADER_LEN 8
#define PNG_CHUNK_HEAER_LEN 8
typedef struct tagPngChunkHeader
{
int iLength ; // 4字节 数据块中数据域的长度,其长度不超过(231-1)字节
CHAR szChunkTypeCode[5]; // 4字节,这里写5,是为了给字符串结束符使用的, 数据块类型码由ASCII字母(A-Z和a-z)组成
//BYTE bChunkData[...]; // 数据块数据,可变长度,存储按照Chunk Type Code指定的数据
//int iCRC; // (循环冗余检测)存储用来检测是否有错误的循环冗余码
tagPngChunkHeader()
{
iLength = 0;
ZeroMemory(szChunkTypeCode, sizeof(szChunkTypeCode));
}
}PngChunkHeader;
---------------------------------------------------------------------------------------------------
2. PngHelper.h // PNG文件操作接口定义
#pragma once
#include "PngStruct.h"
#include <stdio.h>
#define PNG_CLOSE_FILE(pFile) if(NULL != pFile){fclose(pFile); pFile = NULL;}
BOOL PNG_IsPngFile(LPCTSTR szPngPath); // 判断文件是否是PNG文件
void PNG_PrintfChunkInfo(LPCTSTR szPngPath); // 打印PNG文件数据块信息
BOOL PNG_WriteFile2PNG(LPCTSTR szPngPath, LPCTSTR szFilePath); // 将文件写到PNG文件中去
unsigned long PNG_GetFileSize(LPCTSTR szFilePath); // 获取文件大小
BOOL PNG_RestoreData(LPCTSTR szPngPath, LPCTSTR szDstFilePath); // 还原隐写的数据
BOOL PNG_IsHaveEncData(LPCTSTR szPngPath); // 判断是否已经隐写数据
-----------------------------------------------------------
3. PngHelper.cpp // PNG操作接口实现文件
#include "StdAfx.h"
#include "PngHelper.h"
#define PNG_INSERT_CHUNK_NAME "XX00"
// PNG文件头标志
BYTE g_pngHeaderFlag[PNG_FILE_HEADER_LEN] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
// 判断文件是否是PNG文件
BOOL PNG_IsPngFile(LPCTSTR szPngPath)
{
if (szPngPath == NULL)
{
return FALSE;
}
FILE* pFile = NULL;
pFile = fopen(szPngPath, "rb+");
if (pFile == NULL)
{
return FALSE;
}
BYTE bTmp[PNG_FILE_HEADER_LEN] = {0};
fread(bTmp, 1, PNG_FILE_HEADER_LEN, pFile);
fclose(pFile);
pFile = NULL;
return memcmp(bTmp, g_pngHeaderFlag, PNG_FILE_HEADER_LEN) == 0;
}
// 打印PNG文件数据块信息
void PNG_PrintfChunkInfo(LPCTSTR szPngPath)
{
if (!PNG_IsPngFile(szPngPath))
{
return;
}
FILE* pFile = NULL;
pFile = fopen(szPngPath, "rb+");
if (NULL == pFile)
{
return;
}
fseek(pFile, PNG_FILE_HEADER_LEN, SEEK_SET);
PngChunkHeader pngChunkHdr;
CHAR szLog[1024] = {0};
BYTE bTmpLen[4] = {0};
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pFile);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
_stprintf(szLog, "pngChunkHdr.iLength=%d, pngChunkHdr.szChunkTypeCode=%s \r\n", pngChunkHdr.iLength, pngChunkHdr.szChunkTypeCode);
OutputDebugString(szLog);
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
fseek(pFile, pngChunkHdr.iLength + 4, SEEK_CUR);
}
fclose(pFile);
pFile = NULL;
}
// 将文件写到PNG文件中去
BOOL PNG_WriteFile2PNG(LPCTSTR szPngPath, LPCTSTR szFilePath)
{
if (szPngPath == NULL || szFilePath == NULL)
{
return FALSE;
}
if (!PNG_IsPngFile(szPngPath))
{
return FALSE;
}
CHAR szDstFile[MAX_PATH] = {0};
_tcsncpy(szDstFile, szPngPath, _tcslen(szPngPath) - _tcslen(".png"));
_tcscat(szDstFile, "隐写.png");
FILE* pfilePng = NULL;
FILE* pfileEnc = NULL;
FILE* pfileDst = NULL;
pfilePng = fopen(szPngPath, "rb+");
pfileEnc = fopen(szFilePath, "rb+");
pfileDst = fopen(szDstFile, "wb+");
if (NULL == pfilePng || NULL == pfileEnc || NULL == pfileDst)
{
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileEnc);
PNG_CLOSE_FILE(pfileDst);
return FALSE;
}
// PNG头
BYTE bPngHdr[PNG_FILE_HEADER_LEN] = {0};
fread(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfilePng);
fwrite(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfileDst);
// PNG数据块
PngChunkHeader pngChunkHdr;
BYTE bTmpLen[4] = {0};
fseek(pfilePng, PNG_FILE_HEADER_LEN, SEEK_SET);
LONG liPos = 0;
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfilePng);
fwrite(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfileDst);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
PBYTE bTmpData = new BYTE[pngChunkHdr.iLength + 4];
if (bTmpData != NULL)
{
fread(bTmpData, 1, pngChunkHdr.iLength + 4, pfilePng);
fwrite(bTmpData, 1, pngChunkHdr.iLength + 4, pfileDst);
}
if (bTmpData != NULL)
{
delete[] bTmpData;
bTmpData = NULL;
}
static BOOL isWrite = FALSE;
if (_tcscmp(pngChunkHdr.szChunkTypeCode, "IDAT") == 0 && FALSE == isWrite)
{
isWrite = TRUE;
unsigned long ulFileLen = PNG_GetFileSize(szFilePath);
pngChunkHdr.iLength = ulFileLen;
_tcscpy(pngChunkHdr.szChunkTypeCode, PNG_INSERT_CHUNK_NAME);
fwrite(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfileDst);
PBYTE bTmpData = new BYTE[ulFileLen];
fread(bTmpData, 1, ulFileLen, pfileEnc);
fwrite(bTmpData, 1, ulFileLen, pfileDst);
}
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
/*liPos = ftell(pfilePng);
fseek(pfilePng, pngChunkHdr.iLength + 0, SEEK_CUR);
liPos = ftell(pfilePng);*/
}
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileEnc);
PNG_CLOSE_FILE(pfileDst);
return TRUE;
}
// 取文件大小,单位字节
unsigned long PNG_GetFileSize(LPCTSTR szFilePath)
{
unsigned long size;
FILE *fp = fopen(szFilePath,"rb+");
if(fp == NULL)
{
return 0;
}
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fclose(fp);
return size;
}
// 还原隐写的数据
BOOL PNG_RestoreData(LPCTSTR szPngPath, LPCTSTR szDstFilePath)
{
if(NULL == szPngPath || NULL == szDstFilePath)
{
return FALSE;
}
if (!PNG_IsHaveEncData(szPngPath))
{
return FALSE;
}
FILE* pfilePng = NULL;
FILE* pfileDst = NULL;
pfilePng = fopen(szPngPath, "rb+");
pfileDst = fopen(szDstFilePath, "wb+");
if (NULL == pfilePng || NULL == pfileDst)
{
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileDst);
return FALSE;
}
// PNG头
BYTE bPngHdr[PNG_FILE_HEADER_LEN] = {0};
fread(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfilePng);
fwrite(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfileDst);
// PNG数据块
PngChunkHeader pngChunkHdr;
BYTE bTmpLen[4] = {0};
fseek(pfilePng, PNG_FILE_HEADER_LEN, SEEK_SET);
LONG liPos = 0;
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfilePng);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
// 找到隐写的数据块
if (_tcscmp(pngChunkHdr.szChunkTypeCode, PNG_INSERT_CHUNK_NAME) == 0)
{
unsigned long ulFileLen = pngChunkHdr.iLength;
PBYTE bTmpData = new BYTE[ulFileLen];
fread(bTmpData, 1, ulFileLen, pfilePng);
fwrite(bTmpData, 1, ulFileLen, pfileDst);
break;
}
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
fseek(pfilePng, pngChunkHdr.iLength + 4, SEEK_CUR);
}
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileDst);
return TRUE;
}
// 判断是否已经隐写数据
BOOL PNG_IsHaveEncData(LPCTSTR szPngPath)
{
if(szPngPath == NULL)
{
return FALSE;
}
if (!PNG_IsPngFile(szPngPath))
{
return FALSE;
}
FILE* pFile = NULL;
pFile = fopen(szPngPath, "rb+");
if (NULL == pFile)
{
return FALSE;
}
fseek(pFile, PNG_FILE_HEADER_LEN, SEEK_SET);
BOOL bRet = FALSE;
PngChunkHeader pngChunkHdr;
CHAR szLog[1024] = {0};
BYTE bTmpLen[4] = {0};
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pFile);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
// 标志数据块
if (_tcscmp(pngChunkHdr.szChunkTypeCode, PNG_INSERT_CHUNK_NAME) == 0)
{
bRet = TRUE;
break;
}
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
fseek(pFile, pngChunkHdr.iLength + 4, SEEK_CUR);
}
fclose(pFile);
pFile = NULL;
return bRet;
}
-------------------------------
#pragma once
// 参考文章:http://blog.chinaunix.net/uid-20622737-id-3130430.html
// 根据PNG文件的定义来说,其文件头位置总是由8位固定的字节来描述的
// 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
#define PNG_FILE_HEADER_LEN 8
#define PNG_CHUNK_HEAER_LEN 8
typedef struct tagPngChunkHeader
{
int iLength ; // 4字节 数据块中数据域的长度,其长度不超过(231-1)字节
CHAR szChunkTypeCode[5]; // 4字节,这里写5,是为了给字符串结束符使用的, 数据块类型码由ASCII字母(A-Z和a-z)组成
//BYTE bChunkData[...]; // 数据块数据,可变长度,存储按照Chunk Type Code指定的数据
//int iCRC; // (循环冗余检测)存储用来检测是否有错误的循环冗余码
tagPngChunkHeader()
{
iLength = 0;
ZeroMemory(szChunkTypeCode, sizeof(szChunkTypeCode));
}
}PngChunkHeader;
---------------------------------------------------------------------------------------------------
2. PngHelper.h // PNG文件操作接口定义
#pragma once
#include "PngStruct.h"
#include <stdio.h>
#define PNG_CLOSE_FILE(pFile) if(NULL != pFile){fclose(pFile); pFile = NULL;}
BOOL PNG_IsPngFile(LPCTSTR szPngPath); // 判断文件是否是PNG文件
void PNG_PrintfChunkInfo(LPCTSTR szPngPath); // 打印PNG文件数据块信息
BOOL PNG_WriteFile2PNG(LPCTSTR szPngPath, LPCTSTR szFilePath); // 将文件写到PNG文件中去
unsigned long PNG_GetFileSize(LPCTSTR szFilePath); // 获取文件大小
BOOL PNG_RestoreData(LPCTSTR szPngPath, LPCTSTR szDstFilePath); // 还原隐写的数据
BOOL PNG_IsHaveEncData(LPCTSTR szPngPath); // 判断是否已经隐写数据
-----------------------------------------------------------
3. PngHelper.cpp // PNG操作接口实现文件
#include "StdAfx.h"
#include "PngHelper.h"
#define PNG_INSERT_CHUNK_NAME "XX00"
// PNG文件头标志
BYTE g_pngHeaderFlag[PNG_FILE_HEADER_LEN] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
// 判断文件是否是PNG文件
BOOL PNG_IsPngFile(LPCTSTR szPngPath)
{
if (szPngPath == NULL)
{
return FALSE;
}
FILE* pFile = NULL;
pFile = fopen(szPngPath, "rb+");
if (pFile == NULL)
{
return FALSE;
}
BYTE bTmp[PNG_FILE_HEADER_LEN] = {0};
fread(bTmp, 1, PNG_FILE_HEADER_LEN, pFile);
fclose(pFile);
pFile = NULL;
return memcmp(bTmp, g_pngHeaderFlag, PNG_FILE_HEADER_LEN) == 0;
}
// 打印PNG文件数据块信息
void PNG_PrintfChunkInfo(LPCTSTR szPngPath)
{
if (!PNG_IsPngFile(szPngPath))
{
return;
}
FILE* pFile = NULL;
pFile = fopen(szPngPath, "rb+");
if (NULL == pFile)
{
return;
}
fseek(pFile, PNG_FILE_HEADER_LEN, SEEK_SET);
PngChunkHeader pngChunkHdr;
CHAR szLog[1024] = {0};
BYTE bTmpLen[4] = {0};
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pFile);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
_stprintf(szLog, "pngChunkHdr.iLength=%d, pngChunkHdr.szChunkTypeCode=%s \r\n", pngChunkHdr.iLength, pngChunkHdr.szChunkTypeCode);
OutputDebugString(szLog);
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
fseek(pFile, pngChunkHdr.iLength + 4, SEEK_CUR);
}
fclose(pFile);
pFile = NULL;
}
// 将文件写到PNG文件中去
BOOL PNG_WriteFile2PNG(LPCTSTR szPngPath, LPCTSTR szFilePath)
{
if (szPngPath == NULL || szFilePath == NULL)
{
return FALSE;
}
if (!PNG_IsPngFile(szPngPath))
{
return FALSE;
}
CHAR szDstFile[MAX_PATH] = {0};
_tcsncpy(szDstFile, szPngPath, _tcslen(szPngPath) - _tcslen(".png"));
_tcscat(szDstFile, "隐写.png");
FILE* pfilePng = NULL;
FILE* pfileEnc = NULL;
FILE* pfileDst = NULL;
pfilePng = fopen(szPngPath, "rb+");
pfileEnc = fopen(szFilePath, "rb+");
pfileDst = fopen(szDstFile, "wb+");
if (NULL == pfilePng || NULL == pfileEnc || NULL == pfileDst)
{
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileEnc);
PNG_CLOSE_FILE(pfileDst);
return FALSE;
}
// PNG头
BYTE bPngHdr[PNG_FILE_HEADER_LEN] = {0};
fread(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfilePng);
fwrite(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfileDst);
// PNG数据块
PngChunkHeader pngChunkHdr;
BYTE bTmpLen[4] = {0};
fseek(pfilePng, PNG_FILE_HEADER_LEN, SEEK_SET);
LONG liPos = 0;
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfilePng);
fwrite(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfileDst);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
PBYTE bTmpData = new BYTE[pngChunkHdr.iLength + 4];
if (bTmpData != NULL)
{
fread(bTmpData, 1, pngChunkHdr.iLength + 4, pfilePng);
fwrite(bTmpData, 1, pngChunkHdr.iLength + 4, pfileDst);
}
if (bTmpData != NULL)
{
delete[] bTmpData;
bTmpData = NULL;
}
static BOOL isWrite = FALSE;
if (_tcscmp(pngChunkHdr.szChunkTypeCode, "IDAT") == 0 && FALSE == isWrite)
{
isWrite = TRUE;
unsigned long ulFileLen = PNG_GetFileSize(szFilePath);
pngChunkHdr.iLength = ulFileLen;
_tcscpy(pngChunkHdr.szChunkTypeCode, PNG_INSERT_CHUNK_NAME);
fwrite(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfileDst);
PBYTE bTmpData = new BYTE[ulFileLen];
fread(bTmpData, 1, ulFileLen, pfileEnc);
fwrite(bTmpData, 1, ulFileLen, pfileDst);
}
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
/*liPos = ftell(pfilePng);
fseek(pfilePng, pngChunkHdr.iLength + 0, SEEK_CUR);
liPos = ftell(pfilePng);*/
}
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileEnc);
PNG_CLOSE_FILE(pfileDst);
return TRUE;
}
// 取文件大小,单位字节
unsigned long PNG_GetFileSize(LPCTSTR szFilePath)
{
unsigned long size;
FILE *fp = fopen(szFilePath,"rb+");
if(fp == NULL)
{
return 0;
}
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fclose(fp);
return size;
}
// 还原隐写的数据
BOOL PNG_RestoreData(LPCTSTR szPngPath, LPCTSTR szDstFilePath)
{
if(NULL == szPngPath || NULL == szDstFilePath)
{
return FALSE;
}
if (!PNG_IsHaveEncData(szPngPath))
{
return FALSE;
}
FILE* pfilePng = NULL;
FILE* pfileDst = NULL;
pfilePng = fopen(szPngPath, "rb+");
pfileDst = fopen(szDstFilePath, "wb+");
if (NULL == pfilePng || NULL == pfileDst)
{
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileDst);
return FALSE;
}
// PNG头
BYTE bPngHdr[PNG_FILE_HEADER_LEN] = {0};
fread(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfilePng);
fwrite(bPngHdr, 1, PNG_FILE_HEADER_LEN, pfileDst);
// PNG数据块
PngChunkHeader pngChunkHdr;
BYTE bTmpLen[4] = {0};
fseek(pfilePng, PNG_FILE_HEADER_LEN, SEEK_SET);
LONG liPos = 0;
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pfilePng);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
// 找到隐写的数据块
if (_tcscmp(pngChunkHdr.szChunkTypeCode, PNG_INSERT_CHUNK_NAME) == 0)
{
unsigned long ulFileLen = pngChunkHdr.iLength;
PBYTE bTmpData = new BYTE[ulFileLen];
fread(bTmpData, 1, ulFileLen, pfilePng);
fwrite(bTmpData, 1, ulFileLen, pfileDst);
break;
}
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
fseek(pfilePng, pngChunkHdr.iLength + 4, SEEK_CUR);
}
PNG_CLOSE_FILE(pfilePng);
PNG_CLOSE_FILE(pfileDst);
return TRUE;
}
// 判断是否已经隐写数据
BOOL PNG_IsHaveEncData(LPCTSTR szPngPath)
{
if(szPngPath == NULL)
{
return FALSE;
}
if (!PNG_IsPngFile(szPngPath))
{
return FALSE;
}
FILE* pFile = NULL;
pFile = fopen(szPngPath, "rb+");
if (NULL == pFile)
{
return FALSE;
}
fseek(pFile, PNG_FILE_HEADER_LEN, SEEK_SET);
BOOL bRet = FALSE;
PngChunkHeader pngChunkHdr;
CHAR szLog[1024] = {0};
BYTE bTmpLen[4] = {0};
while(TRUE)
{
fread(&pngChunkHdr, 1, PNG_CHUNK_HEAER_LEN, pFile);
// 00 00 00 0D
bTmpLen[0] = (pngChunkHdr.iLength & 0xFF000000) / 0x1000000;
bTmpLen[1] = (pngChunkHdr.iLength & 0xFF0000) / 0x10000;
bTmpLen[2] = (pngChunkHdr.iLength & 0xFF00) / 0x100;
bTmpLen[3] = (pngChunkHdr.iLength & 0xFF);
pngChunkHdr.iLength = *(int*)bTmpLen;
// 标志数据块
if (_tcscmp(pngChunkHdr.szChunkTypeCode, PNG_INSERT_CHUNK_NAME) == 0)
{
bRet = TRUE;
break;
}
// 判断是否是最后一个数据块
if (0 == pngChunkHdr.iLength && _tcscmp(pngChunkHdr.szChunkTypeCode, "IEND") == 0)
{
break;
}
// 移动到下一个数据块
fseek(pFile, pngChunkHdr.iLength + 4, SEEK_CUR);
}
fclose(pFile);
pFile = NULL;
return bRet;
}
-------------------------------
相关文章推荐
- Flex 获得png透明截图的问题和解决方法
- 获取图片宽度和高度的类,支持JPG,GIF,PNG,BMP
- Cross-Browser Variable Opacity with PNG
- php不用GD库生成当前时间的PNG格式图象的程序第1/2页
- IE浏览器下PNG相关功能
- 关于若干数据库数据插入性能的对比分析
- 支持png透明图片的php生成缩略图类分享
- PHP实现对png图像进行缩放的方法(支持透明背景)
- PHP+MySQL之Insert Into数据插入用法分析
- PHP中使用Imagick读取pdf并生成png缩略图实例
- python通过pil为png图片填充上背景颜色的方法
- Python实现批量把SVG格式转成png、pdf格式的代码分享
- Optipng—PNG的优化图像工具
- android ImageButton使用形状非方形的png图片但却显示出正方形白边的情况
- ubuntu下实现桌面截图并保存为png格式
- Java实现图片压缩
- cairo绘图png,pdf,svg
- png 批量 转 pvr.ccz
- 好的icon图标网站
- 使IE6正常显示PNG-24格式图片代码