数据压缩第六次作业’:还存在未知bug的PNG转YUV程序(上一篇文章TGA已完成)
一、前言:
在进行PNG和YUV的转化过程中,其实这些所有的文件之间的转化的思路都大同小异,都是先去查一下这个文件的存储格式是什么样子的,根据存储格式设计结构体来读取文件头,如果有调色板就设计调色板相关的读取方法,如果没有调色板,就按照真彩色来进行读取。但是,PNG的存储过程是一种利用了LZ77压缩算法的过程,PNG中的IDAT数据块,是经过压缩之后,完成的存储,所以若是要恢复压缩之前的状态,我们先需要在VS里配置zlib库,才可以完成解压缩。但是在实验过程中,配置成功zlib之后出现了一系列问题。在经过两周的努力后还是没搞出来最后的结果,所以就只好先行放弃,把TGA转YUV先做出来。故现将基本完成的PNG头YUV的代码发在此处,日后有时间再重新修改调整。
最终遇见的主要问题是,使用uncompress函数来正常解压一些其他的字符串可以正常解压出正确的结果,先对IDAT中的数据进行uncompress解压,再利用compress函数压缩回去也会得到和之前IDAT中数据块一样的结果。
但是如果单纯的用uncompress来解压,得出来的结果并不能恢复成RGB文件,得出来的结果往往会出现大片的“00”,代码中我调适过程中的一些痕迹已经注释掉了,剩下的均为主程序的内容。
代码如下:
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cstring>
#include <cstdlib>
#include"header.h"
int Turnround(int a)
{
int b;
b = (a & 0xFF000000) >> 24;
b += (a & 0x000000FF) << 24;
b += (a & 0x00FF0000) >> 8;
b += (a & 0x0000FF00) << 8;
return b;
}
extern"C"
{
#include"..\..\Commonfiles\zlib.h"
}
#include"header.h"
using namespace std;
typedef struct PNGFILEHEADER {
DWORD head;
DWORD others;
}PNGFILEHEADER;
//Define a struct to put the fileheader in it
//The length of the header is 8 Bytes, but only need to get the first 4 BYTE of it to recognize PNG
typedef struct PNGIHDR {
DWORD Length;//4字节长,指定数据块中数据域的长度
DWORD Chunktypecode;//4字节长,数据块类型码由ASCII字母(A-Z和a-z)组成
DWORD Width;//4字节,图像宽度,以像素为单位
DWORD Height;//4字节,图像高度,以像素为单位
BYTE Bitdepth;//1字节,图像深度
BYTE Colortype;//1字节,颜色类型
BYTE Compression_method;//1字节,压缩方法
BYTE Filter_method;//1字节,滤波器方法
BYTE Interlace_method;//1字节,隔行扫描方法
}PNGIHDR;
//Define a struct to put the fileheader in it
typedef struct PNGIDATHEAD {
DWORD length;
DWORD head;
}PNGIDATHEAD;
typedef struct PNGCRC {
DWORD CRC;
}PNGCRC;
int main(int argc, char* argv[])
{
FILE* PNG = NULL;
FILE* IDAT = NULL;
const char* OutPath = "\\Mac\\Home\\Desktop\\学习\\数据压缩\\ConsoleApplication1\\ConsoleApplication1\\2.gz";
PNGFILEHEADER FILE_HEADER;
PNGIHDR FILE_IHDR;
if (fopen_s(&PNG, "C:\\20.png", "rb") != 0)
{
cout << "Failed to open the png file!" << endl;
}
else
{
cout << "Successfully opened the png file!" << endl;
}
if (fopen_s(&IDAT, "C:\\2.gz", "wb") != 0)
{
cout << "Failed to create the rgb file!" << endl;
}
else
{
cout << "Successfully created the rgb file!" << endl;
}
cout << sizeof(PNGIHDR) << endl;
if (fread(&FILE_HEADER, sizeof(PNGFILEHEADER), 1, PNG) != 1)
{
cout << "Read File Header error!" << endl;
}
else
{
cout << "Successfully read File Header!" << endl;
}
if (FILE_HEADER.head != 0x474E5089)//The order of it is opposite
{
cout << "This is not a PNG file!" << endl;
}
else
{
cout << "This is a PNG file!" << endl;
}
if (fread(&FILE_IHDR, sizeof(PNGIHDR), 1, PNG) != 1)
{
cout << "Read IHDR error!" << endl;
}
else
{
cout << "Successfully read IHDR!" << endl;
}
if (FILE_IHDR.Chunktypecode != 0x52444849)
{
cout << "Failed to read in IHDR!" << endl;
}
else
{
cout << "Successfully read in IHDR!" << endl;
}
unsigned long width;
unsigned long height;
width = Turnround(FILE_IHDR.Width);
height = Turnround(FILE_IHDR.Height);
cout << "The width of the picture is " << width << "." << endl;
cout << "The height of the picture is " << height << "." << endl;
int bitdepth;
int colortype;
bitdepth = FILE_IHDR.Bitdepth;
colortype = FILE_IHDR.Colortype;
cout << "The bitdepth of the picture is " << bitdepth << "." << endl;
cout << "The colortype of the picture is " << colortype << "." << endl;
int compressionmethod;
int filtermethod;
int interlacemethod;
compressionmethod = FILE_IHDR.Compression_method;
filtermethod = FILE_IHDR.Filter_method;
interlacemethod = FILE_IHDR.Interlace_method;
cout << "The compressionmethod of the picture is " << compressionmethod << "." << endl;
cout << "The filtermethod of the picture is " << filtermethod << "." << endl;
cout << "The interlace method of the picture is " << interlacemethod << "." << endl;
if (bitdepth == 8 && colortype == 2 && compressionmethod == 0 && filtermethod == 0 && interlacemethod == 0)
{
cout << "This program can analyse this picture!" << endl;
}
else
{
cout << "This program can't analyse this picture!" << endl;
}
unsigned char* IDAT_DATA = NULL;
unsigned char* IDAT_UNCOMPRESS = NULL;
unsigned char* RED_DATA = NULL;
unsigned char* GREEN_DATA = NULL;
unsigned char* BLUE_DATA = NULL;
unsigned char* ALPHA_DATA = NULL;//need to test the order of RGB later!
IDAT_DATA = (unsigned char*)malloc(sizeof(unsigned char)*111);
IDAT_UNCOMPRESS = (unsigned char*)malloc(height * width * bitdepth / 2);
RED_DATA = (unsigned char*)malloc(height * width);
GREEN_DATA = (unsigned char*)malloc(height * width);
BLUE_DATA = (unsigned char*)malloc(height * width);
ALPHA_DATA = (unsigned char*)malloc(height * width);
uLong IDAT_Chunksize;
IDAT_Chunksize = width * height * bitdepth / 2;
cout << "The size of the chunks in IDAT is " << IDAT_Chunksize * 2 << " Bytes." << endl;
FILE* FILE_X = NULL;
fread(&FILE_X, sizeof(unsigned char), 1, PNG);
/*int looptimes;
int loopleft;
looptimes = (int)(IDAT_Chunksize / 4096)+1;
loopleft = (IDAT_Chunksize * 2) - (looptimes-1) * 8192;
cout <<"The looptimes is "<< looptimes<<endl;
cout << "The loopleft is "<< loopleft << endl;*/
int chunk = 0;
for (int i = 0; ; i++)
{
PNGIDATHEAD FILE_IDATHEAD;
if (fread(&FILE_IDATHEAD, sizeof(PNGIDATHEAD), 1, PNG) == 1)
{
if (FILE_IDATHEAD.head == 0x54414449)
{
int chunklength = Turnround(FILE_IDATHEAD.length);
if (chunklength == 8192)
{
if (fread(IDAT_DATA, sizeof(unsigned char), chunklength, PNG) != 0)
{
//for (int j = 0; j < chunklength; j++)
//{
// /*cout << IDAT_DATA[j] << " ";*/
// printf("%02X ", IDAT_DATA[j]);
//}
PNGCRC CRC2;
fread(&CRC2, sizeof(PNGCRC), 1, PNG);
chunk += chunklength;
cout << chunk << " ";
}
}
if (chunklength != 8192)
{
if (fread(IDAT_DATA, sizeof(unsigned char), chunklength, PNG) != 0)
{
for (int j = 0; j < chunklength; j++)
{
/*cout << IDAT_DATA[j] << " ";*/
printf("%02X ", IDAT_DATA[j]);
}
PNGCRC CRC2;
fread(&CRC2, sizeof(PNGCRC), 1, PNG);
chunk += chunklength;
cout << chunk << " " << endl;
}
break;
}
}
}
}
/*FILE* idat = NULL;
fopen_s(&idat,"C:\\2.gz", "rb");
fseek(idat, 0L, SEEK_END);
int size;
size = ftell(idat);
fseek(idat, 0L, SEEK_SET);*/
/*FILE* idat = NULL;
fopen_s(&idat,"C:\\3.rgb", "wb");*/
/*printf("% d", size);*/
Bytef dest[10000] = { 0 };
/*Byte dest[177396];*/
unsigned long ulen = 10000;
Bytef DATA[200] = { 0 };
for (int i = 0; i < chunk; i++)
{
DATA[i] = IDAT_DATA[i];
}
/*for (int i = 0; i < chunk; i++)
{
cout << IDAT_DATA[i] << " ";
}*/
unsigned long ulen1 = 200;
int r = 0;
/*r = uncompress(dest, &ulen, DATA, ulen1);*/
cout << r <<" "<<ulen<<endl;
/*compress(DATA,&ulen1,dest,ulen);
uncompress(dest, &ulen, IDAT_DATA, ulen1);*/
for (int i = 0; i < 111; i++)
{
printf("%02X ", DATA[i]);
}
fwrite(IDAT_DATA, sizeof(unsigned char), 111, IDAT);
/*fwrite(BLUE_DATA, sizeof(unsigned char), 6400, IDAT);
fwrite(GREEN_DATA, sizeof(unsigned char), 6400, IDAT);
fwrite(RED_DATA, sizeof(unsigned char), 6400, IDAT);*/
/*for (int i = 0; i < 25680; i++)
{
printf("%02X ", dest[i]);
}*/
/*unsigned long ulen2 = chunk;*/
/*compress(DATA,&ulen2,dest,ulen);*/
/*fwrite(DATA, sizeof(unsigned char), chunk, idat);*/
/*int k = 0;*/
//for (int i = 0; i <25600; i++)
//{
// if (dest[i] == 0)
// k++;
// /*printf("%02X ", dest[i]);*/
//}
/*cout << k;*/
/*for (int i = 0; i < 25600;)
{
BLUE_DATA[i] = dest[i];
GREEN_DATA[i] = dest[i + 1];
RED_DATA[i] = dest[i + 2];
i += 4;
}*/
/*fwrite(BLUE_DATA,sizeof(unsigned char),6400,IDAT);
fwrite(GREEN_DATA, sizeof(unsigned char), 6400, IDAT);
fwrite(RED_DATA, sizeof(unsigned char), 6400, IDAT);*/
unsigned char szSrc[] = "test the compression and uncompression of zlib.";
unsigned long nSrcLen = sizeof(szSrc);
unsigned char szZip[1024] = { 0 };
unsigned long nZipLen = 1024;
compress(szZip, &nZipLen, szSrc, nSrcLen);
unsigned char szUnZip[1024] = { 0 };
unsigned long nUnZipLen = 1024;
uncompress(szUnZip, &nUnZipLen, szZip, nZipLen);
cout << "Src:" << szSrc << ", len:" << nSrcLen << endl;
cout << "Zip:" << szZip << ", len:" << nZipLen << endl;
cout << "UnZip:" << szUnZip << ", len:" << nUnZipLen << endl;
}
//int main()
//{
// unsigned char* compr = NULL;
// unsigned char* uncompr = NULL;
// unsigned char* comprlen = NULL;
// unsigned long comprLen = 111;
// unsigned long uncomprLen;
// FILE* fpin, * fpout;
// int file_len_dest = 111;
// int src_len_src = 0;
// int wsize = 0;
// int err;
// fpin = fopen("C:\\2.gz", "rb"); //读取压缩文件
// fpout = fopen("C:\\a_dest.rgb", "wb");//将压缩内容输出到此文件
// if (fpin && fpout)
// {
// fseek(fpin, 0, SEEK_END);
// file_len_dest = ftell(fpin); //得到压缩文件大小
// fseek(fpin, 0, SEEK_SET);
// if (file_len_dest > 0)
// {
// //comprlen = malloc(sizeof(file_len_dest)); //分配读取前4字节原始文件长度的缓存区
// compr = new unsigned char[111]; //分配读取压缩文件缓存区
// /*if (compr == Z_NULL || uncompr == Z_NULL)
// {
// fprintf(stderr, "内存分配失败\n");
// return 1;
// }*/
// //fread(comprlen, 4, 1, fpin);//读取前4字节原始文件长度
// /*src_len_src = *((int*)comprlen);*/
// src_len_src = 4128;
// uncompr = new unsigned char[4128];//分配读取解压后写入文件的缓存区
// //fseek(fpin, 4, SEEK_SET);//设置从4字节之后读
// fread(compr,sizeof(unsigned char),4128, fpin);//读取压缩文件内容
// err = uncompress(uncompr, &uncomprLen, compr, comprLen);//解压
// if (err != Z_OK)
// {
// fprintf(stderr, "解压错误\n");
// }
// else
// {
// wsize = fwrite(uncompr, src_len_src, 1, fpout);//将解压之后的内容写入指定文件
// }
// fclose(fpin);
// fclose(fpout);
// free(compr);
// free(comprlen);
// free(uncompr);
// }
// else
// {
// fprintf(stderr, "输入文件长度为0");
// }
// }
// else
// {
// printf("打开文件出错\n");
// }
//}