📄 jpegpropertyreader.cs
字号:
//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
// Copyright (c) Telligent Systems Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.IO;
namespace CommunityServer.Galleries.Components
{
/// <summary>
/// Summary description for JpegPropertyReader.
/// </summary>
public class JpegPropertyReader
{
private Stream stream;
private Hashtable segmentMap;
private Hashtable metadata;
#region Offsets
private readonly static byte SEGMENT_SOS = (byte)0xDA;
private readonly static byte MARKER_EOI = (byte)0xD9;
public readonly static byte SEGMENT_APP0 = (byte)0xE0;
public readonly static byte SEGMENT_APP1 = (byte)0xE1;
public readonly static byte SEGMENT_APP2 = (byte)0xE2;
public readonly static byte SEGMENT_APP3 = (byte)0xE3;
public readonly static byte SEGMENT_APP4 = (byte)0xE4;
public readonly static byte SEGMENT_APP5 = (byte)0xE5;
public readonly static byte SEGMENT_APP6 = (byte)0xE6;
public readonly static byte SEGMENT_APP7 = (byte)0xE7;
public readonly static byte SEGMENT_APP8 = (byte)0xE8;
public readonly static byte SEGMENT_APP9 = (byte)0xE9;
public readonly static byte SEGMENT_APPA = (byte)0xEA;
public readonly static byte SEGMENT_APPB = (byte)0xEB;
public readonly static byte SEGMENT_APPC = (byte)0xEC;
public readonly static byte SEGMENT_APPD = (byte)0xED;
public readonly static byte SEGMENT_APPE = (byte)0xEE;
public readonly static byte SEGMENT_APPF = (byte)0xEF;
public readonly static byte SEGMENT_SOI = (byte)0xD8;
public readonly static byte SEGMENT_DQT = (byte)0xDB;
public readonly static byte SEGMENT_DHT = (byte)0xC4;
public readonly static byte SEGMENT_SOF0 = (byte)0xC0;
public readonly static byte SEGMENT_COM = (byte)0xFE;
#endregion
#region Constructors
public JpegPropertyReader(Stream stream)
{
this.stream = stream;
}
public JpegPropertyReader(Stream stream, Hashtable metadata) : this(stream)
{
this.metadata = metadata;
}
#endregion
#region Public Properties
public Stream Stream
{
get { return stream; }
set { stream = value; }
}
public Hashtable Metadata
{
get { return metadata; }
set { metadata = value; }
}
#endregion
#region Public Methods
public void Process()
{
// Get the segments
ReadSegments();
// Pass through the segments and process each one
foreach(byte key in segmentMap.Keys)
{
if(key == JpegPropertyReader.SEGMENT_APP1)
{
foreach(byte[] bt in (ArrayList)segmentMap[key])
{
ExifMetadataProcessor exifp = new ExifMetadataProcessor(bt, metadata);
exifp.Extract();
}
}
}
}
#endregion
#region Private Methods
private void ReadSegments()
{
segmentMap = new Hashtable();
BufferedStream inStream;
if(stream is BufferedStream)
inStream = (BufferedStream)stream;
else
inStream = new BufferedStream(stream);
try
{
int offset = 2; // Skip the first two bytes that identify the image, if we use this, we'll already know it is a jpeg
inStream.Position += 2;
do
{
// next byte is 0xFF
byte segmentIdentifier = (byte)(inStream.ReadByte() & 0xFF);
if((segmentIdentifier & 0xFF) != 0xFF)
{
throw new Exception( // was JpegProcessingException
"expected jpeg segment start identifier 0xFF at offset "
+ offset
+ ", not 0x"
+ (segmentIdentifier & 0xFF).ToString("X"));
}
offset++;
// next byte is <segment-marker>
byte thisSegmentMarker = (byte) (inStream.ReadByte() & 0xFF);
offset++;
// next 2-bytes are <segment-size>: [high-byte] [low-byte]
byte[] segmentLengthBytes = new byte[2];
inStream.Read(segmentLengthBytes, 0, 2);
offset += 2;
int segmentLength =
((segmentLengthBytes[0] << 8) & 0xFF00)
| (segmentLengthBytes[1] & 0xFF);
// segment length includes size bytes, so subtract two
segmentLength -= 2;
if (segmentLength > (inStream.Length-inStream.Position))
throw new Exception("segment size would extend beyond file stream length"); // was JpegProcessingException
byte[] segmentBytes = new byte[segmentLength];
inStream.Read(segmentBytes, 0, segmentLength);
offset += segmentLength;
if ((thisSegmentMarker & 0xFF) == (SEGMENT_SOS & 0xFF))
{
// The 'Start-Of-Scan' segment's length doesn't include the image data, instead would
// have to search for the two bytes: 0xFF 0xD9 (EOI).
// It comes last so simply return at this point
return;
}
else if ((thisSegmentMarker & 0xFF) == (MARKER_EOI & 0xFF))
{
// the 'End-Of-Image' segment -- this should never be found in this fashion
return;
}
else
{
IList segmentList;
if (segmentMap.Contains(thisSegmentMarker))
{
segmentList = (IList) segmentMap[thisSegmentMarker];
}
else
{
segmentList = new ArrayList();
segmentMap.Add(thisSegmentMarker, segmentList);
}
segmentList.Add(segmentBytes);
}
// didn't find the one we're looking for, loop through to the next segment
} while (true);
}
catch (IOException ioe)
{
//throw new JpegProcessingException("IOException processing Jpeg file", ioe);
throw new Exception( // was JpegProcessingException
"IOException processing Jpeg file: " + ioe.Message,
ioe);
}
finally
{
try
{
if (inStream != null)
{
inStream.Close();
}
}
catch (IOException ioe)
{
//throw new JpegProcessingException("IOException processing Jpeg file", ioe);
throw new Exception( // was JpegProcessingException
"IOException processing Jpeg file: " + ioe.Message,
ioe);
}
}
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -