public static DhtHeader ReadDhtHeader(byte[] bytes) { UInt32 dhtHeaderOffset = RawReader.FindByteValueIndex(bytes, 0xFF, 0xC4); byte[] dhtHeaderBytes = RawReader.ReadBytes(bytes, dhtHeaderOffset); UInt32 dhtHeaderLengthOffset = 2; byte[] dhtHeaderLengthBytes = RawReader.ReadBytes(dhtHeaderBytes, dhtHeaderLengthOffset, 2); UInt16 dhtHeaderLength = ConvertHelper.ConvertToUInt16(dhtHeaderLengthBytes, true); UInt32 valueHuffmanCodesOffset; UInt32 lengthNumberHuffmanCodesSum = 0; //Huffman table 1 UInt32 dhtHeaderTableIndexOffset = 4; byte dhtHeaderTableIndex; UInt32 tableOffset = dhtHeaderTableIndexOffset + 1; HuffmanTable tableOne = new HuffmanTable(); dhtHeaderTableIndex = RawReader.ReadByte(dhtHeaderBytes, dhtHeaderTableIndexOffset); tableOne.TableClass = (new HalvedByte(dhtHeaderTableIndex)).High; tableOne.TableIndex = (new HalvedByte(dhtHeaderTableIndex)).Low; byte[] lengthNumberHuffmanCodesBytes = RawReader.ReadBytes(dhtHeaderBytes, tableOffset, DhtHeader.LENGTH_NUMBER_HUFFMAN_CODES_COUNT); lengthNumberHuffmanCodesSum = Convert.ToUInt32(lengthNumberHuffmanCodesBytes.Sum(x => x)); valueHuffmanCodesOffset = tableOffset + DhtHeader.LENGTH_NUMBER_HUFFMAN_CODES_COUNT; byte[] valueHuffmanCodesBytes = RawReader.ReadBytes(dhtHeaderBytes, valueHuffmanCodesOffset, lengthNumberHuffmanCodesSum); tableOne.LengthHuffmanCodes = lengthNumberHuffmanCodesBytes; tableOne.ValueHuffmanCodes = valueHuffmanCodesBytes; //Huffman table 2 dhtHeaderTableIndexOffset = valueHuffmanCodesOffset + lengthNumberHuffmanCodesSum; tableOffset = dhtHeaderTableIndexOffset + 1; HuffmanTable tableTwo = new HuffmanTable(); dhtHeaderTableIndex = RawReader.ReadByte(dhtHeaderBytes, dhtHeaderTableIndexOffset); tableTwo.TableClass = (new HalvedByte(dhtHeaderTableIndex)).High; tableTwo.TableIndex = (new HalvedByte(dhtHeaderTableIndex)).Low; lengthNumberHuffmanCodesBytes = RawReader.ReadBytes(dhtHeaderBytes, tableOffset, DhtHeader.LENGTH_NUMBER_HUFFMAN_CODES_COUNT); lengthNumberHuffmanCodesSum = Convert.ToUInt32(lengthNumberHuffmanCodesBytes.Sum(x => x)); valueHuffmanCodesOffset = tableOffset + DhtHeader.LENGTH_NUMBER_HUFFMAN_CODES_COUNT; valueHuffmanCodesBytes = RawReader.ReadBytes(dhtHeaderBytes, valueHuffmanCodesOffset, lengthNumberHuffmanCodesSum); tableTwo.LengthHuffmanCodes = lengthNumberHuffmanCodesBytes; tableTwo.ValueHuffmanCodes = valueHuffmanCodesBytes; return(new DhtHeader() { Offset = dhtHeaderOffset, HeaderLength = dhtHeaderLength, HuffmanTables = new HuffmanTable[] { tableOne, tableTwo } }); }
public static IntegerMatrix ReadScanData(byte[] scanDataBytes, DhtHeader dhtHeader, Sof3Header sof3Header, SosHeader sosHeader, UInt16[] slices) { int columnsCount = GetImageWidth(slices); int rowsCount = sof3Header.LinesNumber; int rowIndex = 0, columnIndex = 0; IntegerMatrix resMatrix = new IntegerMatrix(rowsCount, columnsCount); ushort normalSliceWidth = slices[1]; List <int> decompressionValueList = new List <int>(); Dictionary <string, byte>[] huffmanCodeValueMapsArray = RawReader.GetHuffmanCodeValueMapsArray(dhtHeader); BitArray scanDataBitArray = RawReader.GetScanDataBitArray(scanDataBytes); int index = 0, huffmanCodeIndex = 0; BitArray huffmanCodeBitArray = new BitArray(1); string huffmanCodeString = null; byte huffmanValue = 0; int componentIndex = 0; int componentValueIndex = 0, componentValue = 0; int[] previousComponentValues = RawReader.GetInitialComponentValues(sof3Header); int lastIndex = GetLastDecompressionValueIndex(sof3Header, slices); int lastSliceFirstDecompressionValueIndex = GetLastSliceFirstDecompressionValueIndex(sof3Header, slices); int sliceSize = slices[1] * sof3Header.LinesNumber; Dictionary <string, byte> huffmanCodeValueMap = huffmanCodeValueMapsArray[GetHuffmanTableIndex(rowIndex, columnIndex, sosHeader)]; while (componentValueIndex <= lastIndex && index < scanDataBitArray.Length) { huffmanCodeBitArray[huffmanCodeIndex] = scanDataBitArray[index]; huffmanCodeString = huffmanCodeBitArray.ToBitString(); if (huffmanCodeValueMap.TryGetValue(huffmanCodeString, out huffmanValue)) { int differenceCodeValue = 0; index++; if (huffmanValue > 0) { //Read difference code int finalIndex = index + huffmanValue - 1; differenceCodeValue = GetDifferenceCodeValue(scanDataBitArray, index, finalIndex, huffmanValue); index = finalIndex + 1; } else { differenceCodeValue = 0; } componentValue = previousComponentValues[componentIndex] + differenceCodeValue; previousComponentValues[componentIndex] = componentValue; decompressionValueList.Add(componentValue); resMatrix[rowIndex, columnIndex] = componentValue; componentValueIndex++; huffmanCodeBitArray = new BitArray(1); huffmanCodeIndex = 0; rowIndex = GetNextRowIndex(componentValueIndex, lastSliceFirstDecompressionValueIndex, sliceSize, slices); columnIndex = GetNextColumnIndex(componentValueIndex, lastSliceFirstDecompressionValueIndex, sliceSize, slices); huffmanCodeValueMap = huffmanCodeValueMapsArray[GetHuffmanTableIndex(rowIndex, columnIndex, sosHeader)]; bool initComponentValuesRequired = (columnIndex == 0) || ((columnIndex > 0) && (columnIndex % normalSliceWidth == 0)); if (initComponentValuesRequired) { previousComponentValues = GetInitialComponentValues(sof3Header); } componentIndex = GetComponentIndex(rowIndex, columnIndex); } else { //Read huffman code index++; huffmanCodeIndex++; huffmanCodeBitArray.Length++; } } return(resMatrix); }
public static IntegerMatrix ReadImageFromFile(string filePath) { byte[] fileBytes = File.ReadAllBytes(filePath); List <HeaderItemDescriptor> headerItemList = HeaderItemDescriptor.GetHeaderItemDescriptorList(); #region Byte Order //Byte order HeaderItemDescriptor headerItemByteOrder = headerItemList.FirstOrDefault(item => item.Name == HeaderItemDescriptor.ITEM_BYTE_ORDER); byte[] headerItemByteOrderBytes = RawReader.ReadHeaderItem(fileBytes, headerItemByteOrder); #endregion //First IFD HeaderItemDescriptor headerItemFirstIFD = headerItemList.FirstOrDefault(item => item.Name == HeaderItemDescriptor.ITEM_TIFF_OFFSET); byte[] headerItemFirstIFDBytes = RawReader.ReadHeaderItem(fileBytes, headerItemFirstIFD); List <IFD_0_EntryDescriptor> firstIFDEntryDescriptorList = IFD_0_EntryDescriptor.GetEntryDescriptorList(); //Compression int compressionEntryIndex = firstIFDEntryDescriptorList.FindIndex(item => item.Name == IFD_0_EntryDescriptor.COMPRESSION); UInt32 localCompressionOffset = ImageFileDirectory.GetImageFileDirectoryEntryOffset(Convert.ToUInt32(compressionEntryIndex)); UInt32 compressionOffset = BitConverter.ToUInt32(headerItemFirstIFDBytes, 0) + localCompressionOffset; ImageFileDirectoryEntry compressionEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, compressionOffset); UInt16 compressionValue = compressionEntry.GetUInt16Value(); //Make int makeEntryIndex = firstIFDEntryDescriptorList.FindIndex(item => item.Name == IFD_0_EntryDescriptor.MAKE); UInt32 localMakeOffset = ImageFileDirectory.GetImageFileDirectoryEntryOffset(Convert.ToUInt32(makeEntryIndex)); UInt32 makeOffset = BitConverter.ToUInt32(headerItemFirstIFDBytes, 0) + localMakeOffset; ImageFileDirectoryEntry makeEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, makeOffset); UInt32 makeOffseValue = makeEntry.GetUInt32Value(); byte[] makeBytes = RawReader.ReadBytesUntilEndingZero(fileBytes, makeOffseValue); string makeValue = ConvertHelper.ConvertToString(makeBytes); //Model int modelEntryIndex = firstIFDEntryDescriptorList.FindIndex(item => item.Name == IFD_0_EntryDescriptor.MODEL); UInt32 localModelOffset = ImageFileDirectory.GetImageFileDirectoryEntryOffset(Convert.ToUInt32(modelEntryIndex)); UInt32 modelOffset = BitConverter.ToUInt32(headerItemFirstIFDBytes, 0) + localModelOffset; ImageFileDirectoryEntry modelEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, modelOffset); UInt32 modelOffsetValue = modelEntry.GetUInt32Value(); byte[] modelBytes = RawReader.ReadBytesUntilEndingZero(fileBytes, modelOffsetValue); string modelValue = ConvertHelper.ConvertToString(modelBytes); //X Resolution int xResolutionEntryIndex = firstIFDEntryDescriptorList.FindIndex(item => item.Name == IFD_0_EntryDescriptor.X_RESOLUTION); UInt32 localXResolutionOffset = ImageFileDirectory.GetImageFileDirectoryEntryOffset(Convert.ToUInt32(xResolutionEntryIndex)); UInt32 xResolutionOffset = BitConverter.ToUInt32(headerItemFirstIFDBytes, 0) + localXResolutionOffset; ImageFileDirectoryEntry xResolutionEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, xResolutionOffset); UInt32 xResolutionOffsetValue = xResolutionEntry.GetUInt32Value(); byte[] xResolutionBytes = RawReader.ReadBytes(fileBytes, xResolutionOffsetValue, 4); UInt32 xResolutionValue = ConvertHelper.ConvertToUInt32(xResolutionBytes); //DateTime int dateTimeEntryIndex = firstIFDEntryDescriptorList.FindIndex(item => item.Name == IFD_0_EntryDescriptor.DATE_TIME); UInt32 localDateTimeOffset = ImageFileDirectory.GetImageFileDirectoryEntryOffset(Convert.ToUInt32(dateTimeEntryIndex)); UInt32 dateTimeOffset = BitConverter.ToUInt32(headerItemFirstIFDBytes, 0) + localDateTimeOffset; ImageFileDirectoryEntry dateTimeEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, dateTimeOffset); UInt32 dateTimeOffsetValue = dateTimeEntry.GetUInt32Value(); byte[] dateTimeBytes = RawReader.ReadBytesUntilEndingZero(fileBytes, dateTimeOffsetValue); string dateTimeValue = ConvertHelper.ConvertToString(dateTimeBytes); DateTime dateTimeStruct = DateTime.ParseExact(dateTimeValue, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture); //EXIF bytes IFD_0_EntryDescriptor exifEntryDescriptor = firstIFDEntryDescriptorList.Where(item => item.Name == IFD_0_EntryDescriptor.EXIF).FirstOrDefault(); uint exifOffset = RawReader.GetEntryOffsetByTagID(fileBytes, exifEntryDescriptor.TagID); ImageFileDirectoryEntry exifOffsetEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, exifOffset); UInt32 exifOffsetValue = exifOffsetEntry.GetUInt32Value(); byte[] exifBytes = RawReader.ReadBytes(fileBytes, exifOffsetValue); //Makernote bytes List <EXIF_EntryDescriptor> exifEntryDescriptorList = EXIF_EntryDescriptor.GetEntryDescriptorList(); EXIF_EntryDescriptor makerNoteEntryDescriptor = exifEntryDescriptorList.Where(item => item.Name == EXIF_EntryDescriptor.MAKER_NOTE).FirstOrDefault(); uint makerNoteOffset = RawReader.GetEntryOffsetByTagID(fileBytes, makerNoteEntryDescriptor.TagID); ImageFileDirectoryEntry makerNoteOffsetEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, makerNoteOffset); UInt32 makerNoteOffsetValue = makerNoteOffsetEntry.GetUInt32Value(); byte[] makerNoteBytes = RawReader.ReadBytes(fileBytes, makerNoteOffsetValue); //Color Balance List <Makernote_EntryDescriptor> makernoteEntryDescriptorList = Makernote_EntryDescriptor.GetEntryDescriptorList(); Makernote_EntryDescriptor colorBalanceEntryDescriptor = makernoteEntryDescriptorList.Where(item => item.Name == Makernote_EntryDescriptor.COLOR_BALANCE).FirstOrDefault(); uint colorBalanceOffset = RawReader.GetEntryOffsetByTagID(makerNoteBytes, colorBalanceEntryDescriptor.TagID); ImageFileDirectoryEntry colorBalanceEntry = RawReader.ReadImageFileDirectoryEntry(makerNoteBytes, colorBalanceOffset); UInt32 colorBalanceOffsetValue = colorBalanceEntry.GetUInt32Value(); //Raw Data IFD HeaderItemDescriptor headerItemRawIFD = headerItemList.FirstOrDefault(item => item.Name == HeaderItemDescriptor.ITEM_RAW_IFD_OFFSET); byte[] headerItemRawBytes = RawReader.ReadHeaderItem(fileBytes, headerItemRawIFD); List <IFD_3_EntryDescriptor> rawEntryDescriptorList = IFD_3_EntryDescriptor.GetEntryDescriptorList(); //Slices int slicesIndex = rawEntryDescriptorList.FindIndex(item => item.Name == IFD_3_EntryDescriptor.CR2_SLICE); UInt32 slicesOffset = BitConverter.ToUInt32(headerItemRawBytes, 0) + ImageFileDirectory.GetImageFileDirectoryEntryOffset(Convert.ToUInt32(slicesIndex)); ImageFileDirectoryEntry slicesEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, slicesOffset); UInt16[] slices = RawReader.ReadUInt16Array(fileBytes, slicesEntry.GetUInt32Value(), slicesEntry.NumberOfValue); //Headers and compressed raw bytes int rawOffsetEntryIndex = rawEntryDescriptorList.FindIndex(item => item.Name == IFD_3_EntryDescriptor.STRIP_OFFSET); UInt32 localStripOffset = ImageFileDirectory.GetImageFileDirectoryEntryOffset(Convert.ToUInt32(rawOffsetEntryIndex)); UInt32 stripOffset = BitConverter.ToUInt32(headerItemRawBytes, 0) + localStripOffset; ImageFileDirectoryEntry stripOffsetEntry = RawReader.ReadImageFileDirectoryEntry(fileBytes, stripOffset); UInt32 stripOffsetValue = stripOffsetEntry.GetUInt32Value(); byte[] rawBytes = RawReader.ReadBytes(fileBytes, stripOffsetValue); DhtHeader dhtHeader = RawReader.ReadDhtHeader(rawBytes); Sof3Header sof3Header = RawReader.ReadSof3Header(rawBytes); SosHeader sosHeader = RawReader.ReadSosHeader(rawBytes); Dictionary <string, byte> huffmanCodeValueDictionaryOne = dhtHeader.HuffmanTables[0].GetHuffmanCodeValueMap(); Dictionary <string, byte> huffmanCodeValueDictionaryTwo = dhtHeader.HuffmanTables[1].GetHuffmanCodeValueMap(); //SCAN DATA UInt32 scanDataOffset = sosHeader.Offset + sosHeader.HeaderLength + 2; byte[] scanDataBytes = RawReader.ReadBytes(rawBytes, scanDataOffset); return(RawReader.ReadScanData(scanDataBytes, dhtHeader, sof3Header, sosHeader, slices)); }