实现这个功能需要imageHelper.h imageHelper.cpp这两个源代码文件
imageHelper.h
#ifndef _IMAGE_HELPER_H_
#define _IMAGE_HELPER_H_
/*
Title: Image Helper
Author: kagula
Date: 2018-10-3
Function Description:
用来判断内存中的数据是不是合法的ipng或jpg文件!
Test Environment:
[1]Win10 Pro with visual studio 2017 community
[2]CentOS7 with gcc 5.x
Dependencies:
[1]libjpeg9c
[2]libpng-libpng16
[3]zlib 1.2.8
How to use:
使用前先把jpg/png文件的内容读到DataBlock实例中,
然后,就可以使用IsValidJPG和IsValidPNG来判断文件格式是否正确了。
*/
namespace kagula
{
struct DataBlock;
bool IsValidJPG(DataBlock &db);
bool IsValidPNG(DataBlock &db);
}
#endif // _DEBUG
imageHelper.cpp
#include "imageHelper.h"
#include "fileHelper.h"
#include <png.h>
#include <zlib.h>
#ifdef _WIN32
#pragma comment(lib,"libjpeg9c.lib")
#ifdef _DEBUG
#pragma comment(lib,"libpng16d.lib")
#pragma comment(lib,"zlibd.lib")
#else
#pragma comment(lib,"libpng16.lib")
#pragma comment(lib,"zlib.lib")
#endif
#endif // DEBUG
#include "../libjpeg9c/jpeglib.h"
#include "cderror.h"
#define JMESSAGE(code,string) string ,
static const char * const cdjpeg_message_table[] = {
#include "cderror.h"
nullptr
};
namespace kagula
{
bool IsValidJPG(DataBlock &db)
{
bool isOK = false;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* Initialize the JPEG decompression object with default error handling. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
/* Add some application-specific error messages (from cderror.h) */
jerr.addon_message_table = cdjpeg_message_table;
jerr.first_addon_message = ADDON_MESSAGE_CODE::JMSG_FIRSTADDONCODE;
jerr.last_addon_message = ADDON_MESSAGE_CODE::JMSG_LASTADDONCODE;
/* Specify data source for decompression */
jpeg_mem_src(&cinfo, db.pData,db.length);
/* Read file header, set default decompression parameters */
(void)jpeg_read_header(&cinfo, TRUE);//如果不是合法的jpg文件,这段代码会挂掉。
if (cinfo.image_width > 0 && cinfo.image_height > 0)
{
isOK = true;
}
jpeg_destroy_decompress(&cinfo);
return isOK;
}
typedef struct {
unsigned char *data;
unsigned int size;
unsigned int offset;
}ImageSource;
static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
{
ImageSource *is = (ImageSource*)png_get_io_ptr(png_ptr);
if (is->offset + length <= is->size)
{
memcpy(data, is->data + is->offset, length);
is->offset += length;
}
else
{
png_error(png_ptr, "pngReaderCallback failed.");
}
}
png_uint_32 width, height;
ImageSource srcImg;
int color_type;
bool IsValidPNG(DataBlock &db)
{
png_structp png_ptr;
png_infop info_ptr;
int bit_depth;
FILE *fp;
//printf("lpng[%s], zlib[%s]\n", PNG_LIBPNG_VER_STRING, ZLIB_VERSION);
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL)
{
return false;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
png_destroy_read_struct(&png_ptr, NULL, NULL);
return false;
}
if (setjmp(png_jmpbuf(png_ptr))) {
/* Free all of the memory associated with the png_ptr and info_ptr */
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
/* If we get here, we had a problem reading the file */
return false;
}
//定义被移到了global scope.
srcImg.data = db.pData;
srcImg.size = db.length;
srcImg.offset = 0;
png_set_read_fn(png_ptr, &srcImg, pngReadCallback);
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
//获取png图片相关信息
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
NULL, NULL, NULL);
//printf("width[%d], height[%d], bit_depth[%d], color_type[%d]\n",
//width, height, bit_depth, color_type);
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
return true;
}
}
imageHelper的定义需要struct DataBlock的声明和实现,
下面是DataBlock的声明和实现:
struct DataBlock {
unsigned char *pData;
unsigned long long length;
DataBlock() :pData(nullptr), length(0) {}
~DataBlock() {
if (pData != nullptr)
{
delete pData;
length = 0;
}
}
};//struct