Added processing for headers and the first chunck. Some infs are still missing tho
This commit is contained in:
@@ -25,7 +25,14 @@ namespace TEST_DecodePng
|
||||
if (Directory.Exists(imageFolderPath))
|
||||
{
|
||||
lsbFiles.Enabled = true;
|
||||
string[] files = Directory.GetFiles(imageFolderPath,"*png");
|
||||
string[] files = Directory.GetFiles(imageFolderPath,"*.png");
|
||||
foreach (string file in files)
|
||||
{
|
||||
lsbFiles.Items.Add(Path.GetFileName(file));
|
||||
}
|
||||
|
||||
//TO REMOVE, ONLY HERE FOR DEBUGGING
|
||||
files = Directory.GetFiles(imageFolderPath, "*.jpg");
|
||||
foreach (string file in files)
|
||||
{
|
||||
lsbFiles.Items.Add(Path.GetFileName(file));
|
||||
|
||||
@@ -1,25 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TEST_DecodePng
|
||||
{
|
||||
internal class PngDecoder
|
||||
{
|
||||
const int PNG_SIGNATURE_LENGTH = 8;
|
||||
readonly byte[] EXPECTED_PNG_SIGNATURE = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 };
|
||||
|
||||
const int CHUNCK_SIZE_FIELD_LENGTH = 4;
|
||||
const int CHUNCK_TYPE_FIELD_LENGTH = 4;
|
||||
|
||||
const string FIRST_CHUNK_TYPE = "IHDR";
|
||||
const int IMAGE_WIDTH_FIELD_SIZE = 4;
|
||||
const int IMAGE_HEIGHT_FIELD_SIZE = 4;
|
||||
public Stopwatch chrono;
|
||||
|
||||
public PngDecoder()
|
||||
{
|
||||
//Empty
|
||||
chrono = new Stopwatch();
|
||||
//I start and stop the chronometer so all the methods can just use the Restart method.
|
||||
chrono.Start(); chrono.Stop();
|
||||
}
|
||||
public Bitmap Decode(string filename)
|
||||
{
|
||||
Byte[] content = File.ReadAllBytes(filename);
|
||||
int pngSignatureLength = 8;
|
||||
//TO REMOVE !!
|
||||
return new Bitmap(100,100);
|
||||
//Timing Stuff
|
||||
chrono.Reset();
|
||||
chrono.Start();
|
||||
//Timing Stuff
|
||||
|
||||
byte[] content = File.ReadAllBytes(filename);
|
||||
int cursor = 0;
|
||||
|
||||
byte[] pngSignature = new byte[PNG_SIGNATURE_LENGTH];
|
||||
for (int i = 0; i < PNG_SIGNATURE_LENGTH; i++)
|
||||
{
|
||||
pngSignature[i] = content[cursor];
|
||||
cursor++;
|
||||
}
|
||||
|
||||
//Checks if the file has a valid png signature
|
||||
if (!compareByteArrays(EXPECTED_PNG_SIGNATURE, pngSignature))
|
||||
return null;
|
||||
|
||||
//We are now sure that we are working with a png file and we will then read chuncks
|
||||
|
||||
byte[] chunckLength = new byte[CHUNCK_SIZE_FIELD_LENGTH];
|
||||
for (int i = 0; i < CHUNCK_SIZE_FIELD_LENGTH; i++)
|
||||
{
|
||||
chunckLength[i] = content[cursor];
|
||||
cursor++;
|
||||
}
|
||||
byte[] chunckType = new byte[CHUNCK_TYPE_FIELD_LENGTH];
|
||||
for (int i = 0; i < CHUNCK_TYPE_FIELD_LENGTH; i++)
|
||||
{
|
||||
chunckType[i] = content[cursor];
|
||||
cursor++;
|
||||
}
|
||||
|
||||
//The first chunck MUST be a IHDR chunck so we need to check if that is the case
|
||||
string ckType = System.Text.Encoding.UTF8.GetString(chunckType);
|
||||
|
||||
//If the first chunck is not the IHDR that means that we should not continue to decompress it
|
||||
if (ckType != FIRST_CHUNK_TYPE)
|
||||
return null;
|
||||
|
||||
//As it is the first chunck, his structure is a little bit different
|
||||
|
||||
int imageWidth, imageHeight, bitDepth, colorType, compressionMethod, filterMethod, interfaceMethod;
|
||||
|
||||
byte[] btaImageWidth = new byte[IMAGE_WIDTH_FIELD_SIZE];
|
||||
byte[] btaImageHeight = new byte[IMAGE_HEIGHT_FIELD_SIZE];
|
||||
for (int i = 0; i < IMAGE_WIDTH_FIELD_SIZE; i++)
|
||||
{
|
||||
btaImageWidth[i] = content[cursor];
|
||||
cursor++;
|
||||
}
|
||||
for (int i = 0; i < IMAGE_HEIGHT_FIELD_SIZE; i++)
|
||||
{
|
||||
btaImageHeight[i] = content[cursor];
|
||||
cursor++;
|
||||
}
|
||||
|
||||
//Those are in little endien notation so we need to reverse it
|
||||
Array.Reverse(btaImageWidth);
|
||||
Array.Reverse(btaImageHeight);
|
||||
imageWidth = BitConverter.ToInt32(btaImageWidth,0);
|
||||
imageHeight = BitConverter.ToInt32(btaImageHeight,0);
|
||||
|
||||
cursor++;
|
||||
bitDepth = Convert.ToInt32(content[cursor]);
|
||||
cursor++;
|
||||
colorType = Convert.ToInt32(content[cursor]);
|
||||
cursor++;
|
||||
compressionMethod = Convert.ToInt32(content[cursor]);
|
||||
cursor++;
|
||||
filterMethod = Convert.ToInt32(content[cursor]);
|
||||
cursor++;
|
||||
interfaceMethod = Convert.ToInt32(content[cursor]);
|
||||
|
||||
MessageBox.Show("Image width: " + imageWidth +
|
||||
Environment.NewLine + "Image height: " + imageHeight +
|
||||
Environment.NewLine + "byte depth : " + bitDepth +
|
||||
Environment.NewLine + "color type : " + colorType +
|
||||
Environment.NewLine + "compression method : " + compressionMethod +
|
||||
Environment.NewLine + "filter method : " + filterMethod +
|
||||
Environment.NewLine + "interface method : " + interfaceMethod
|
||||
);
|
||||
|
||||
|
||||
|
||||
//Timing Stuff
|
||||
chrono.Stop();
|
||||
//Timing Stuff
|
||||
|
||||
//TO REMOVE
|
||||
return new Bitmap(100, 100);
|
||||
}
|
||||
public byte[] ReadChunck()
|
||||
{
|
||||
//Must always return two values in the array or null
|
||||
|
||||
|
||||
|
||||
//TO REMOVE
|
||||
return new byte[] { 0, 0 };
|
||||
}
|
||||
|
||||
public bool compareByteArrays(byte[] firstArray, byte[] secondArray)
|
||||
{
|
||||
if (firstArray.Length != secondArray.Length)
|
||||
return false;
|
||||
bool result = true;
|
||||
for (int i = 0; i < firstArray.Length; i++)
|
||||
{
|
||||
if (firstArray[0] != secondArray[0])
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user