public bool IsThumbnailIncluded()
{
return m_bThumbnailFilled;
} public int GetBitsPerPixel()
{
return m_HeaderInfo.nBitsPerPixel;
} public int GlobalAngle()
{
return m_nGlobalAngle;
} public bool IsCopyrighted()
{
return m_bCopyright;
} public IntPtr GetHBitmap()
{
return m_hBitmap;
} public int GetWidth()
{
return m_HeaderInfo.nWidth;
}
public int GetHeight()
{
return m_HeaderInfo.nHeight;
} public int GetXResolution()
{
return m_ResolutionInfo.hRes;
} public int GetYResolution()
{
return m_ResolutionInfo.vRes;
} public int GetCompression()
{
return m_nCompression;
}
protected bool ReadHeader(FileStream stream)
{
bool bSuccess = false; BinaryReader binReader = new BinaryReader(stream);
try
{
// Set Position to the beginning of the stream.
binReader.BaseStream.Position = 0;
byte [] Signature = binReader.ReadBytes(4); // always equal 8BPS, do not read file if not
byte [] Version = binReader.ReadBytes(2); // always equal 1, do not read file if not
byte [] Reserved = binReader.ReadBytes(6); // must be zero
byte [] Channels = binReader.ReadBytes(2); // numer of channels including any alpha channels, supported range 1 to 24
byte [] Rows = binReader.ReadBytes(4); // height in PIXELS, supported range 1 to 30000
byte [] Columns = binReader.ReadBytes(4); // width in PIXELS, supported range 1 to 30000
byte [] Depth = binReader.ReadBytes(2); // number of bpp
byte [] Mode = binReader.ReadBytes(2); // colour mode of the file
// Btmap=0, Grayscale=1, Indexed=2, RGB=3,
// CMYK=4, Multichannel=7, Duotone=8, Lab=9
ASCIIEncoding encoding = new ASCIIEncoding(); if( encoding.GetString(Signature).Equals("8BPS") && Version[1] == 0x01)
{
m_HeaderInfo = new HeaderInfo(); if(SwapBytes(Channels,2)) m_HeaderInfo.nChannels = BitConverter.ToInt16(Channels,0);
if(SwapBytes(Rows,4)) m_HeaderInfo.nHeight = BitConverter.ToInt32(Rows,0);
if(SwapBytes(Columns,4)) m_HeaderInfo.nWidth = BitConverter.ToInt32(Columns,0);
if(SwapBytes(Depth,2)) m_HeaderInfo.nBitsPerPixel = BitConverter.ToInt16(Depth,0);
if(SwapBytes(Mode,2)) m_HeaderInfo.nColourMode = BitConverter.ToInt16(Mode,0); if(m_HeaderInfo.nChannels != -1 && m_HeaderInfo.nHeight != -1 && m_HeaderInfo.nWidth != -1 && m_HeaderInfo.nBitsPerPixel != -1 && m_HeaderInfo.nColourMode != -1) bSuccess = true;
}
}
catch(EndOfStreamException e)
{
System.Windows.Forms.MessageBox.Show("Exception occurs while reading file header: {0}", e.GetType().Name);
} return bSuccess;
} protected bool ReadColourModeData(FileStream stream)
{
bool bSuccess = false;
// Only indexed colour and duotone have colour mode data,
// for all other modes this section is 4 bytes length, the length field is set to zero // For indexed color images, the length will be equal to 768, and the color
// will contain the color table for the image, in non杋nterleaved order. // For duotone images, the color data will contain the duotone specification,
// the format of which is not documented. Other applications that read
// Photoshop files can treat a duotone image as a grayscale image, and just
// preserve the contents of the duotone information when reading and writing
// the file.
BinaryReader binReader = new BinaryReader(stream);
try
{
// Set Position to the beginning of the stream + size of HeaderInfo.
binReader.BaseStream.Position = 26;
byte [] ColorMode = binReader.ReadBytes(4); int nLength = 0; m_ColorModeData = new ColorModeData();
if(SwapBytes(ColorMode,4)) nLength = BitConverter.ToInt32(ColorMode,0);
m_ColorModeData.nLength = nLength; if(nLength>0)
{
m_ColorModeData.ColourData = new byte[nLength];
m_ColorModeData.ColourData = binReader.ReadBytes(nLength);
}
bSuccess = true;
}
catch(EndOfStreamException e)
{
MessageBox.Show("Exception occurs while reading color mode data: {0}", e.GetType().Name);
} return bSuccess;
}
protected bool ReadImageResource(FileStream stream)
{
bool bSuccess = false;
BinaryReader binReader = new BinaryReader(stream);
try
{
int nLength = 0; byte [] Length = binReader.ReadBytes(4); m_ImageResource = new ImageResource();
m_ResolutionInfo = new ResolutionInfo();
m_DisplayInfo = new DisplayInfo();
m_ThumbNail = new ThumbNail();
if(SwapBytes(Length,4)) nLength = BitConverter.ToInt32(Length,0);
m_ImageResource.nLength = nLength; int nBytesRead = 0;
int nTotalBytes = m_ImageResource.nLength;
long nStreamLen = stream.Length; while(stream.Position < nStreamLen && nBytesRead < nTotalBytes)
{
m_ImageResource.Reset();
m_ImageResource.OSType = binReader.ReadBytes(4);
nBytesRead += 4; ASCIIEncoding encoding = new ASCIIEncoding();
if(encoding.GetString(m_ImageResource.OSType).Equals("8BIM"))
{
byte [] ID = binReader.ReadBytes(2);
nBytesRead += 2; if(SwapBytes(ID,2)) m_ImageResource.nID = BitConverter.ToInt16(ID,0); byte SizeOfName = binReader.ReadByte();
nBytesRead += 1;
int nSizeOfName = (int)SizeOfName;
if(nSizeOfName>0)
{
if((nSizeOfName % 2)!=0) // must read 1 more byte to make size even
{
SizeOfName = binReader.ReadByte();
nBytesRead += 1;
}
m_ImageResource.Name = new byte[nSizeOfName];
m_ImageResource.Name = binReader.ReadBytes(nSizeOfName);
nBytesRead += nSizeOfName;
}
SizeOfName = binReader.ReadByte();
nBytesRead += 1; byte [] Size = binReader.ReadBytes(4);
if(SwapBytes(Size,4)) m_ImageResource.nSize = BitConverter.ToInt32(Size,0);
nBytesRead += 4; if((m_ImageResource.nSize % 2) != 0) // resource data must be even
m_ImageResource.nSize++;
if(m_ImageResource.nSize>0)
{
byte [] IntValue = new byte[4];
byte [] ShortValue = new byte[2]; switch(m_ImageResource.nID)
{
case 1005:
{
m_bResolutionInfoFilled = true; ShortValue = binReader.ReadBytes(2);
if(SwapBytes(ShortValue,2)) m_ResolutionInfo.hRes = BitConverter.ToInt16(ShortValue,0);
nBytesRead += 2;
IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ResolutionInfo.hResUnit = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4;
ShortValue = binReader.ReadBytes(2);
if(SwapBytes(ShortValue,2)) m_ResolutionInfo.widthUnit = BitConverter.ToInt16(ShortValue,0);
nBytesRead += 2;
ShortValue = binReader.ReadBytes(2);
if(SwapBytes(ShortValue,2)) m_ResolutionInfo.vRes = BitConverter.ToInt16(ShortValue,0);
nBytesRead += 2;
IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ResolutionInfo.vResUnit = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4;
ShortValue = binReader.ReadBytes(2);
if(SwapBytes(ShortValue,2)) m_ResolutionInfo.heightUnit = BitConverter.ToInt16(ShortValue,0);
nBytesRead += 2;
}
break;
case 1007:
{
ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
if(SwapBytes(ShortValue,2)) m_DisplayInfo.ColourSpace = BitConverter.ToInt16(ShortValue,0); for(int n=0; n<4; ++n)
{
ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
if(SwapBytes(ShortValue,2)) m_DisplayInfo.Colour[n] = BitConverter.ToInt16(ShortValue,0);
}
ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
if(SwapBytes(ShortValue,2)) m_DisplayInfo.Opacity = BitConverter.ToInt16(ShortValue,0);
if(m_DisplayInfo.Opacity<0 || m_DisplayInfo.Opacity>100) m_DisplayInfo.Opacity = 100; byte c = binReader.ReadByte();
nBytesRead += 1;
if(c == 0x00) m_DisplayInfo.kind = false;
else m_DisplayInfo.kind = true; nBytesRead += 1;
m_DisplayInfo.padding = binReader.ReadByte();
}
break;
case 1034:
{
ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
int nCopyright = 0;
if(SwapBytes(ShortValue,2)) nCopyright = BitConverter.ToInt16(ShortValue,0);
if(nCopyright>0) m_bCopyright = true;
else m_bCopyright = false;
}
break;
case 1033:
{
m_bThumbnailFilled = true; IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ThumbNail.nFormat = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4; IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ThumbNail.nWidth = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4; IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ThumbNail.nHeight = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4; IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ThumbNail.nWidthBytes = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4; IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ThumbNail.nSize = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4; IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_ThumbNail.nCompressedSize = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4;
ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
if(SwapBytes(ShortValue,2)) m_ThumbNail.nBitPerPixel = BitConverter.ToInt16(ShortValue,0); ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
if(SwapBytes(ShortValue,2)) m_ThumbNail.nPlanes = BitConverter.ToInt16(ShortValue,0);
int nTotalData = m_ImageResource.nSize - 28; // header byte [] buffer = new byte[nTotalData];
byte c;
if(m_ImageResource.nID == 1033)
{
// In BGR format
for(int n=0; n<nTotalData; n=n+3)
{
c = binReader.ReadByte();
nBytesRead += 1;
buffer[n+2] = c;
c = binReader.ReadByte();
nBytesRead += 1;
buffer[n+1] = c;
c = binReader.ReadByte();
nBytesRead += 1;
buffer[n] = c;
}
}
else if(m_ImageResource.nID == 1036)
{
// In RGB format
for (int n=0; n<nTotalData; ++n)
{
c = binReader.ReadByte();
nBytesRead += 1;
buffer[n] = c;
}
}
}
break;
case 1037:
{
IntValue = binReader.ReadBytes(4);
if(SwapBytes(IntValue,4)) m_nGlobalAngle = BitConverter.ToInt32(IntValue,0);
nBytesRead += 4;
}
break;
case 1046:
{
ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
if(SwapBytes(ShortValue,2)) m_nColourCount = BitConverter.ToInt16(ShortValue,0);
}
break;
case 1047:
{
ShortValue = binReader.ReadBytes(2);
nBytesRead += 2;
if(SwapBytes(ShortValue,2)) m_nTransparentIndex = BitConverter.ToInt16(ShortValue,0);
}
break;
default:
{
byte c;
for(int n=0; n<m_ImageResource.nSize; ++n )
{
c = binReader.ReadByte();
nBytesRead += 1;
}
}
break;
}
}
}
}
bSuccess = true;
}
catch(EndOfStreamException e)
{
bSuccess = false;
MessageBox.Show("Exception occurs while reading image resources: {0}", e.GetType().Name);
}
return bSuccess;
} protected bool ReadLayerAndMaskInfoSection(FileStream stream) // currently ignore it
{
bool bSuccess = false;
BinaryReader binReader = new BinaryReader(stream);
try
{
byte [] DataLength = new byte[4];
int nTotalBytes = 0; DataLength = binReader.ReadBytes(4);
if(SwapBytes(DataLength,4)) nTotalBytes = BitConverter.ToInt32(DataLength,0);
if(stream.Position+nTotalBytes < stream.Length) stream.Position += nTotalBytes; // byte c = 0x00;
// for(int i=0;i<nTotalBytes;i++)
// {
// if(binReader.PeekChar() == -1) break;
// c = binReader.ReadByte();
// } bSuccess = true;
}
catch(EndOfStreamException e)
{
bSuccess = false;
MessageBox.Show("Exception occurs while reading layer and mask section: {0}", e.GetType().Name);
}
return bSuccess;
}