用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
8.8 KiB

5 months ago
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <png.h>
#include <pngstruct.h>
#include <pnginfo.h>
#include "decoder-apng.h"
#include <assert.h>
#include <tchar.h>
#define SASSERT(x) assert(x)
struct IPngReader
{
virtual png_size_t read(png_bytep data, png_size_t length) = 0;
};
struct IPngReader_Mem : public IPngReader
{
const char *pbuf;
png_size_t nLen;
IPngReader_Mem(const char *_pbuf,png_size_t _nLen):pbuf(_pbuf),nLen(_nLen){}
png_size_t read(png_bytep data, png_size_t length)
{
if(nLen < length) length = nLen;
memcpy(data,pbuf,length);
pbuf += length;
nLen -= length;
return length;
}
};
struct IPngReader_File: public IPngReader
{
FILE *f;
IPngReader_File(FILE *_f):f(_f){}
png_size_t read(png_bytep data, png_size_t length)
{
return fread(data,1,length,f);
}
};
void
mypng_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
if (png_ptr == NULL)
return;
IPngReader * pMem = (IPngReader*)png_ptr->io_ptr;
png_size_t rc = pMem->read(data,length);
if(rc < length)
{
png_error(png_ptr,"read error");
}
}
APNGDATA * loadPng(IPngReader *pSrc)
{
png_bytep dataFrame;
png_uint_32 bytesPerRow;
png_uint_32 bytesPerFrame;
png_bytepp rowPointers;
png_byte sig[8];
png_structp png_ptr_read;
png_infop info_ptr_read;
pSrc->read(sig,8);
if(!png_check_sig(sig,8))
{
return NULL;
}
png_ptr_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info_ptr_read = png_create_info_struct(png_ptr_read);
if (setjmp(png_jmpbuf(png_ptr_read)))
{
png_destroy_read_struct(&png_ptr_read, &info_ptr_read, NULL);
return NULL;
}
png_set_read_fn(png_ptr_read,pSrc,mypng_read_data);
png_set_sig_bytes(png_ptr_read, 8);
if ((png_ptr_read->bit_depth < 8) ||
(png_ptr_read->color_type == PNG_COLOR_TYPE_PALETTE) ||
(info_ptr_read->valid & PNG_INFO_tRNS))
png_set_expand(png_ptr_read);
png_set_add_alpha(png_ptr_read, 0xff, PNG_FILLER_AFTER);
png_set_interlace_handling(png_ptr_read);
png_set_gray_to_rgb(png_ptr_read);
png_set_strip_16(png_ptr_read);
png_read_info(png_ptr_read, info_ptr_read);
png_read_update_info(png_ptr_read, info_ptr_read);
bytesPerRow = png_ptr_read->width * 4;
bytesPerFrame = bytesPerRow * png_ptr_read->height;
APNGDATA * apng = (APNGDATA*) malloc(sizeof(APNGDATA));
memset(apng,0,sizeof(APNGDATA));
apng->nWid = png_ptr_read->width;
apng->nHei = png_ptr_read->height;
//图像帧数据
dataFrame = (png_bytep)malloc(bytesPerRow * apng->nHei);
memset(dataFrame,0,bytesPerFrame);
//获得扫描行指针
rowPointers = (png_bytepp)malloc(sizeof(png_bytep)* apng->nHei);
for(int i=0;i<apng->nHei;i++)
rowPointers[i] = dataFrame + bytesPerRow * i;
if (!png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_acTL))
{//load png doesn't has this trunk.
png_read_image(png_ptr_read,rowPointers);
apng->pdata =dataFrame;
apng->nFrames =1;
}else
{//load apng
apng->nFrames = png_get_num_frames(png_ptr_read, info_ptr_read);//获取总帧数
png_bytep data = (png_bytep)malloc( bytesPerFrame * apng->nFrames);//为每一帧分配内存
png_bytep curFrame = (png_bytep)malloc(bytesPerFrame);
memset(curFrame,0,bytesPerFrame);
apng->nLoops = png_get_num_plays(png_ptr_read, info_ptr_read);
apng->pDelay = (unsigned short*)malloc(sizeof(unsigned short)*apng->nFrames);
for(int iFrame = 0;iFrame<apng->nFrames;iFrame++)
{
//读帧信息头
png_read_frame_head(png_ptr_read, info_ptr_read);
//计算出帧延时信息
if (png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_fcTL))
{
png_uint_16 delay_num = info_ptr_read->next_frame_delay_num,
delay_den = info_ptr_read->next_frame_delay_den;
if (delay_den==0 || delay_den==100)
apng->pDelay[iFrame] = delay_num;
else
if (delay_den==10)
apng->pDelay[iFrame] = delay_num*10;
else
if (delay_den==1000)
apng->pDelay[iFrame] = delay_num/10;
else
apng->pDelay[iFrame] = delay_num*100/delay_den;
}else
{
apng->pDelay[iFrame] = 0;
}
//读取PNG帧到dataFrame中,不含偏移数据
png_read_image(png_ptr_read, rowPointers);
{//将当前帧数据绘制到当前显示帧中:1)获得绘制的背景;2)计算出绘制位置; 3)使用指定的绘制方式与背景混合
//1)计算出绘制位置
png_bytep lineDst=curFrame+info_ptr_read->next_frame_y_offset*bytesPerRow + 4 * info_ptr_read->next_frame_x_offset;
png_bytep lineSour=dataFrame;
//2)使用指定的绘制方式与背景混合
switch(info_ptr_read->next_frame_blend_op)
{
case PNG_BLEND_OP_OVER:
{
for(unsigned int y=0;y<info_ptr_read->next_frame_height;y++)
{
png_bytep lineDst1=lineDst;
png_bytep lineSour1=lineSour;
for(unsigned int x=0;x<info_ptr_read->next_frame_width;x++)
{
png_byte alpha = lineSour1[3];
*lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8;
*lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8;
*lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8;
*lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8;
}
lineDst += bytesPerRow;
lineSour+= bytesPerRow;
}
}
break;
case PNG_BLEND_OP_SOURCE:
{
for(unsigned int y=0;y<info_ptr_read->next_frame_height;y++)
{
memcpy(lineDst,lineSour,info_ptr_read->next_frame_width*4);
lineDst += bytesPerRow;
lineSour+= bytesPerRow;
}
}
break;
default:
SASSERT(FALSE);
break;
}
png_bytep targetFrame = data + bytesPerFrame * iFrame;
memcpy(targetFrame,curFrame,bytesPerFrame);
lineDst=curFrame+info_ptr_read->next_frame_y_offset*bytesPerRow + 4 * info_ptr_read->next_frame_x_offset;
//3)处理当前帧绘制区域
switch(info_ptr_read->next_frame_dispose_op)
{
case PNG_DISPOSE_OP_BACKGROUND://clear background
{
for(unsigned int y=0;y<info_ptr_read->next_frame_height;y++)
{
memset(lineDst,0,info_ptr_read->next_frame_width*4);
lineDst += bytesPerRow;
}
}
break;
case PNG_DISPOSE_OP_PREVIOUS://copy previous frame
if(iFrame>0)
{
memcpy(curFrame,targetFrame-bytesPerFrame,bytesPerFrame);
}
break;
case PNG_DISPOSE_OP_NONE://using current frame, doing nothing
break;
default:
SASSERT(0);
break;
}
}
}
free(curFrame);
free(dataFrame);
apng->pdata =data;
}
free(rowPointers);
png_read_end(png_ptr_read,info_ptr_read);
png_destroy_read_struct(&png_ptr_read, &info_ptr_read, NULL);
return apng;
}
APNGDATA * LoadAPNG_from_file( const wchar_t * pszFileName )
{
FILE *f = _wfopen(pszFileName,L"rb");
if(!f) return NULL;
IPngReader_File file(f);
APNGDATA *pRet = loadPng(&file);
fclose(f);
return pRet;
}
APNGDATA * LoadAPNG_from_memory(const char * pBuf, size_t nLen )
{
IPngReader_Mem mem(pBuf,nLen);
return loadPng(&mem);
}
void APNG_Destroy( APNGDATA *apng )
{
if(apng)
{
if(apng->pdata) free(apng->pdata);
if(apng->pDelay) free(apng->pDelay);
free(apng);
}
}