在CodeProject里发现一个读取的方法. 作者只要求在使用的时候保留Assembly的名称 "SimplePsd.dll ". 下面是全部原代码. CPSD.cs: using System; using System.IO; using System.Text; using System.Drawing; using System.Windows.Forms;namespace SimplePsd{ /// <summary> /// Main class is for opening Adobe Photoshop files /// </summary> public class CPSD { private HeaderInfo m_HeaderInfo; private ColorModeData m_ColorModeData; private ImageResource m_ImageResource; private ResolutionInfo m_ResolutionInfo; private DisplayInfo m_DisplayInfo; private ThumbNail m_ThumbNail; private bool m_bResolutionInfoFilled; private bool m_bThumbnailFilled; private bool m_bCopyright; private short m_nColourCount; private short m_nTransparentIndex; private int m_nGlobalAngle; private int m_nCompression; private IntPtr m_hBitmap; public CPSD() { m_bResolutionInfoFilled = false; m_bThumbnailFilled = false; m_bCopyright = false; m_nColourCount = -1; m_nTransparentIndex = -1; m_nGlobalAngle = 30; m_nCompression = -1; m_hBitmap = IntPtr.Zero; } // construction, destruction public int Load(string strPathName) { int nErrorCode = 0; // No errors FileStream stream = new FileStream(strPathName, FileMode.Open, FileAccess.Read, FileShare.Read); if (!stream.Handle.Equals(0)) { bool bSuccessHeader = false; bool bSuccessColourModeData = false; bool bSuccessImageResource = false; bool bSuccessLayerMaskInfo = false; try { bSuccessHeader = ReadHeader(stream); if (bSuccessHeader == false) nErrorCode = -2; // Error in header } catch (Exception) { bSuccessHeader = false; nErrorCode = -2; } if (bSuccessHeader) { try { bSuccessColourModeData = ReadColourModeData(stream); if (bSuccessColourModeData == false) nErrorCode = -3; // Error in ColourMode Data } catch (Exception) { bSuccessColourModeData = false; nErrorCode = -3; } } if (bSuccessColourModeData) { try { bSuccessImageResource = ReadImageResource(stream); if (bSuccessImageResource == false) nErrorCode = -4; // Error in Image Resource } catch (Exception) { bSuccessImageResource = false; nErrorCode = -4; } } if (bSuccessImageResource) { try { bSuccessLayerMaskInfo = ReadLayerAndMaskInfoSection(stream); if (false == bSuccessLayerMaskInfo) nErrorCode = -5; // Error in Mask Info } catch (Exception) { bSuccessLayerMaskInfo = false; nErrorCode = -5; } } if (bSuccessImageResource) { try { nErrorCode = ReadImageData(stream); } catch (Exception) { nErrorCode = -6; // Error in Image Data } } } else nErrorCode = -1; // Cannot open file return nErrorCode; } 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: case 1036: { 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; } }}