C# 读写 Photoshop PSD文件 操作类
分析了PSD的文件....才发现PSD的RGB色彩保存也是 先红 蓝 绿 这样保存的 ....麻烦的.. 另外8BIM好象没什么用..可以直接跳过..直接获取最后的图形信息就可以了.. 我只对一些PSD文件进行了解析如果大家使用中碰到不能识别的请告诉我.发送信息到zgke@Sina.com 或则给我留言就可以了。 另外这个BLOG的插入代码我不用了...太郁闷了... 使用方法 显示PSD OpenFileDialog _Dialog = new OpenFileDialog(); _Dialog.Filter = "*.psd|*.psd"; if (_Dialog.ShowDialog() == DialogResult.OK) { Zgke.MyImage.ImageFile.ImagePsd _Psd = new Zgke.MyImage.ImageFile.ImagePsd(_Dialog.FileName); pictureBox1.Image = _Psd.PSDImage; } 保存PSD Zgke.MyImage.ImageFile.ImagePsd _Psd = new Zgke.MyImage.ImageFile.ImagePsd(); _Psd.PSDImage = this.Icon.ToBitmap(); _Psd.Save(@"C:/Temp/1.psd"); 下面是全部的类 using System; using System.Collections.Generic; using System.Text; using System.Drawing.Imaging; using System.Drawing; using System.Runtime.InteropServices; using System.IO; namespace Zgke.MyImage.ImageFile { /// <summary> /// Photoshop PSD文件 /// zgke@sina.com /// qq:116149 /// </summary> public class ImagePsd { private class PSDHEAD { private byte[] m_HeadBytes = new byte[26]; public byte[] GetBytes() { return m_HeadBytes; } public PSDHEAD(byte[] p_Data) { m_HeadBytes = p_Data; } /// <summary> /// 版本 /// </summary> public byte Version { get { return m_HeadBytes[5]; } set { m_HeadBytes[5] = value; } } /// <summary> /// 颜色数 3为24位 4位23位 /// </summary> public ushort Channels { get { return BitConverter.ToUInt16(new byte[] { m_HeadBytes[13], m_HeadBytes[12] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_HeadBytes[13] = _Value[1]; m_HeadBytes[12] = _Value[0]; } } /// <summary> /// /// </summary> public uint Height { get { return BitConverter.ToUInt32(new byte[] { m_HeadBytes[17], m_HeadBytes[16], m_HeadBytes[15], m_HeadBytes[14] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_HeadBytes[17] = _Value[0]; m_HeadBytes[16] = _Value[1]; m_HeadBytes[15] = _Value[2]; m_HeadBytes[14] = _Value[3]; } } /// <summary> /// /// </summary> public uint Width { get { return BitConverter.ToUInt32(new byte[] { m_HeadBytes[21], m_HeadBytes[20], m_HeadBytes[19], m_HeadBytes[18] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_HeadBytes[21] = _Value[0]; m_HeadBytes[20] = _Value[1]; m_HeadBytes[19] = _Value[2]; m_HeadBytes[18] = _Value[3]; } } public ushort BitsPerPixel { get { return BitConverter.ToUInt16(new byte[] { m_HeadBytes[23], m_HeadBytes[22] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_HeadBytes[23] = _Value[1]; m_HeadBytes[22] = _Value[0]; } } public ushort ColorMode { get { return BitConverter.ToUInt16(new byte[] { m_HeadBytes[25], m_HeadBytes[24] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_HeadBytes[25] = _Value[1]; m_HeadBytes[24] = _Value[0]; } } public PSDHEAD() { m_HeadBytes[0] = 0x38; m_HeadBytes[1] = 0x42; m_HeadBytes[2] = 0x50; m_HeadBytes[3] = 0x53; m_HeadBytes[5] = 0x01; ColorMode = 3; BitsPerPixel = 8; } } private class ColorModel { private byte[] m_ColorData; public ColorPalette ColorData { get { Bitmap _Bitmap = new Bitmap(1, 1, PixelFormat.Format8bppIndexed); ColorPalette _ColorPalette = _Bitmap.Palette; if (m_ColorData.Length == 0) return _ColorPalette; for (int i = 0; i != 256; i++) { _ColorPalette.Entries[i] = Color.FromArgb(m_ColorData[i], m_ColorData[i + 256], m_ColorData[i + 512]); } return _ColorPalette; } set { m_ColorData = new byte[768]; for (int i = 0; i != 256; i++) { m_ColorData[i] = value.Entries[i].R; m_ColorData[i + 256] = value.Entries[i].G; m_ColorData[i + 512] = value.Entries[i].B; } } } private byte[] m_BIMSize = new byte[4]; public uint BIMSize { get { return BitConverter.ToUInt32(new byte[] { m_BIMSize[3], m_BIMSize[2], m_BIMSize[1], m_BIMSize[0] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_BIMSize[0] = _Value[3]; m_BIMSize[1] = _Value[2]; m_BIMSize[2] = _Value[1]; m_BIMSize[3] = _Value[0]; } } public ColorModel(FileStream p_FileStream) { byte[] _CountByte = new byte[4]; p_FileStream.Read(_CountByte, 0, 4); Array.Reverse(_CountByte); int _Count = BitConverter.ToInt32(_CountByte, 0); m_ColorData = new byte[_Count]; if (_Count != 0) p_FileStream.Read(m_ColorData, 0, _Count); p_FileStream.Read(m_BIMSize, 0, 4); } public ColorModel() { m_ColorData = new byte[0]; } public byte[] GetBytes() { MemoryStream _Memory = new MemoryStream(); byte[] _Value = BitConverter.GetBytes(m_ColorData.Length); Array.Reverse(_Value); _Memory.Write(_Value, 0, _Value.Length); _Memory.Write(m_ColorData, 0, m_ColorData.Length); _Memory.Write(m_BIMSize, 0, 4); return _Memory.ToArray(); } } private class BIM { private byte[] m_Data = new byte[] { 0x38, 0x42, 0x49, 0x4D }; private byte[] m_TypeID = new byte[2]; private byte[] m_Name = new byte[0]; public ushort TypeID { get { return BitConverter.ToUInt16(new byte[] { m_TypeID[1], m_TypeID[0] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_TypeID[0] = _Value[1]; m_TypeID[1] = _Value[0]; } } public byte[] m_Value; public BIM(FileStream p_FileStream) { byte[] _Type = new byte[4]; p_FileStream.Read(_Type, 0, 4); if (m_Data[0] == _Type[0] && m_Data[1] == _Type[1] && m_Data[2] == _Type[2] && m_Data[3] == _Type[3]) { p_FileStream.Read(m_TypeID, 0, 2); int _SizeOfName = p_FileStream.ReadByte(); int _nSizeOfName = (int)_SizeOfName; if (_nSizeOfName > 0) { if ((_nSizeOfName % 2) != 0) { _SizeOfName = p_FileStream.ReadByte(); } m_Name = new byte[_nSizeOfName]; p_FileStream.Read(m_Name, 0, _nSizeOfName); } _SizeOfName = p_FileStream.ReadByte(); byte[] _CountByte = new byte[4]; p_FileStream.Read(_CountByte, 0, 4); Array.Reverse(_CountByte); int _DataCount = BitConverter.ToInt32(_CountByte, 0); if (_DataCount % 2 != 0) _DataCount++; m_Value = new byte[_DataCount]; p_FileStream.Read(m_Value, 0, _DataCount); m_Read = true; } } private bool m_Read = false; public bool Read { get { return m_Read; } set { m_Read = value; } } #region Type=1005 public ushort hRes { get { return BitConverter.ToUInt16(new byte[] { m_Value[1], m_Value[0] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_Value[0] = _Value[1]; m_Value[1] = _Value[0]; } } public uint hResUnit { get { return BitConverter.ToUInt32(new byte[] { m_Value[5], m_Value[4], m_Value[3], m_Value[2] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_Value[2] = _Value[3]; m_Value[3] = _Value[2]; m_Value[4] = _Value[1]; m_Value[5] = _Value[0]; } } public ushort widthUnit { get { return BitConverter.ToUInt16(new byte[] { m_Value[7], m_Value[6] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_Value[6] = _Value[1]; m_Value[7] = _Value[0]; } } public ushort vRes { get { return BitConverter.ToUInt16(new byte[] { m_Value[9], m_Value[8] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_Value[8] = _Value[1]; m_Value[9] = _Value[0]; } } public uint vResUnit { get { return BitConverter.ToUInt32(new byte[] { m_Value[13], m_Value[12], m_Value[11], m_Value[10] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_Value[10] = _Value[3]; m_Value[11] = _Value[2]; m_Value[12] = _Value[1]; m_Value[13] = _Value[0]; } } public ushort heightUnit { get { return BitConverter.ToUInt16(new byte[] { m_Value[15], m_Value[14] }, 0); } set { byte[] _Value = BitConverter.GetBytes(value); m_Value[14] = _Value[1]; m_Value[15] = _Value[0]; } } #endregion } private class LayerMaskInfo { public byte[] m_Data = new byte[0]; public LayerMaskInfo(FileStream p_Stream) { byte[] _Count = new byte[4]; p_Stream.Read(_Count, 0, 4); Array.Reverse(_Count); int _ReadCount = BitConverter.ToInt32(_Count, 0); m_Data = new byte[_ReadCount]; if (_ReadCount != 0) p_Stream.Read(m_Data, 0, _ReadCount); } public LayerMaskInfo() { } public byte[] GetBytes() { MemoryStream _Memory = new MemoryStream(); byte[] _Value = BitConverter.GetBytes(m_Data.Length); Array.Reverse(_Value); _Memory.Write(_Value, 0, _Value.Length); if (m_Data.Length != 0) _Memory.Write(m_Data, 0, m_Data.Length); return _Memory.ToArray(); } } private class ImageData { private ushort p_Type = 0; private PSDHEAD m_HeaderInfo; public ImageData() { } public ImageData(FileStream p_FileStream, PSDHEAD p_HeaderInfo) { m_HeaderInfo = p_HeaderInfo; byte[] _ShortBytes = new byte[2]; p_FileStream.Read(_ShortBytes, 0, 2); Array.Reverse(_ShortBytes); p_Type = BitConverter.ToUInt16(_ShortBytes, 0); switch (p_Type) { case 0: //RAW DATA RawData(p_FileStream); break; case 1: RleData(p_FileStream); break; default: throw new Exception("Type =" + p_Type.ToString()); } } #region RLE数据 private void RleData(FileStream p_Stream) { switch (m_HeaderInfo.ColorMode) { case 3: //RGB LoadRLERGB(p_Stream); break; case 4: //CMYK LoadRLECMYK(p_Stream); break; default: throw new Exception("RLE ColorMode =" + m_HeaderInfo.ColorMode.ToString()); } } private void LoadRLERGB(FileStream p_Stream) { int _Width = (int)m_HeaderInfo.Width; int _Height = (int)m_HeaderInfo.Height; m_PSDImage = new Bitmap(_Width, _Height, PixelFormat.Format24bppRgb); BitmapData _PSDImageData = m_PSDImage.LockBits(new Rectangle(0, 0, m_PSDImage.Width, m_PSDImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); byte[] _ImageBytes = new byte[_PSDImageData.Stride * _PSDImageData.Height]; int _WriteIndex = 0; int _EndIndex = _PSDImageData.Stride * _PSDImageData.Height; p_Stream.Position += _Height * m_HeaderInfo.Channels * 2; int _Count = _Width * _Height; int _WrtieType = 0; int _HeightIndex = 0; int _WidthIndex = 0; int _Index = 0; while (true) { if (_WriteIndex > _EndIndex - 1) break; byte _Read = (byte)p_Stream.ReadByte(); if (_Read == 128) continue; //Erroe if (_Read > 128) { _Read ^= 0x0FF; _Read += 2; byte _ByteValue = (byte)p_Stream.ReadByte(); for (byte i = 0; i != _Read; i++) { _WrtieType = _WriteIndex / _Count; switch (_WrtieType) { case 0: //Red _HeightIndex = _WriteIndex / _Width; _WidthIndex = _WriteIndex % _Width; _Index = (_PSDImageData.Stride * _HeightIndex) + (_WidthIndex * 3) + 2; _ImageBytes[_Index] = _ByteValue; break; case 1: //Green _HeightIndex = (_WriteIndex - _Count) / _Width; _WidthIndex = (_WriteIndex - _Count) % _Width; _Index = (_PSDImageData.Stride * _HeightIndex) + (_WidthIndex * 3) + 1; _ImageBytes[_Index] = _ByteValue; break; case 2: _HeightIndex = (_WriteIndex - _Count - _Count) / _Width; _WidthIndex = (_WriteIndex - _Count - _Count) % _Width; _Index = (_PSDImageData.Stride * _HeightIndex) + (_WidthIndex * 3); _ImageBytes[_Index] = _ByteValue; break; } //_ImageBytes[_WriteIndex] = _ByteValue; _WriteIndex++; } } else { _Read++; for (byte i = 0; i != _Read; i++) { _WrtieType = _WriteIndex / _Count; switch (_WrtieType) { case 0: //Red _HeightIndex = _WriteIndex / _Width; _WidthIndex = _WriteIndex % _Width; _Index = (_PSDImageData.Stride * _HeightIndex) + (_WidthIndex * 3) + 2; _ImageBytes[_Index] = (byte)p_Stream.ReadByte(); break; case 1: //Green _HeightIndex = (_WriteIndex - _Count) / _Width; _WidthIndex = (_WriteIndex - _Count) % _Width; _Index = (_PSDImageData.Stride * _HeightIndex) + (_WidthIndex * 3) + 1; _ImageBytes[_Index] = (byte)p_Stream.ReadByte(); break; case 2: _HeightIndex = (_WriteIndex - _Count - _Count) / _Width; _WidthIndex = (_WriteIndex - _Count - _Count) % _Width; _Index = (_PSDImageData.Stride * _HeightIndex) + (_WidthIndex * 3); _ImageBytes[_Index] = (byte)p_Stream.ReadByte(); break; } //_ImageBytes[_WriteIndex] = (byte)p_Stream.ReadByte(); _WriteIndex++; } } } Marshal.Copy(_ImageBytes, 0, _PSDImageData.Scan0, _ImageBytes.Length); m_PSDImage.UnlockBits(_PSDImageData); } private void LoadRLECMYK(FileStream p_Stream) { int _Width = (int)m_HeaderInfo.Width; int _Height = (int)m_HeaderInfo.Height; int _Count = _Width * _Height * (m_HeaderInfo.BitsPerPixel / 8) * m_HeaderInfo.Channels; p_Stream.Position += _Height * m_HeaderInfo.Channels * 2; byte[] _ImageBytes = new byte[_Count]; int _WriteIndex = 0; while (true) { if (_WriteIndex > _Count - 1) break; byte _Read = (byte)p_Stream.ReadByte(); if (_Read == 128) continue; //Erroe if (_Read > 128) { _Read ^= 0x0FF; _Read += 2; byte _ByteValue = (byte)p_Stream.ReadByte(); for (byte i = 0; i != _Read; i++) { _ImageBytes[_WriteIndex] = _ByteValue; _WriteIndex++; } } else { _Read++; for (byte i = 0; i != _Read; i++) { _ImageBytes[_WriteIndex] = (byte)p_Stream.ReadByte(); _WriteIndex++; } } } m_PSDImage = new Bitmap(_Width, _Height, PixelFormat.Format24bppRgb); BitmapData _PSDImageData = m_PSDImage.LockBits(new Rectangle(0, 0, m_PSDImage.Width, m_PSDImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); byte[] _WriteBytes = new byte[_PSDImageData.Stride * _PSDImageData.Height]; int _StarIndex = 0; int _Index = 0; int _Size = _Width * _Height; double C; double M; double Y; double K; double _MaxColours = Math.Pow(2, m_HeaderInfo.BitsPerPixel); int _Size2 = _Size * 2; int _Size3 = _Size * 3; for (int i = 0; i != _PSDImageData.Height; i++) { _StarIndex = _PSDImageData.Stride * i; _Index = i * _Width; for (int z = 0; z != _PSDImageData.Width; z++) { C = 1.0 - (double)_ImageBytes[_Index + z] / _MaxColours; M = 1.0 - (double)_ImageBytes[_Index + z + _Size] / _MaxColours; Y = 1.0 - (double)_ImageBytes[_Index + z + _Size2] / _MaxColours; K = 1.0 - (double)_ImageBytes[_Index + z + _Size3] / _MaxColours; ConvertCMYKToRGB(C, M, Y, K, _WriteBytes, _StarIndex + z * 3); } } Marshal.Copy(_WriteBytes, 0, _PSDImageData.Scan0, _WriteBytes.Length); m_PSDImage.UnlockBits(_PSDImageData); } #endregion #region RAW数据 private void RawData(FileStream p_Stream) { switch (m_HeaderInfo.ColorMode) { case 2: //Index LoadRAWIndex(p_Stream); return; case 3: //RGB LoadRAWRGB(p_Stream); return; case 4: //CMYK LoadRAWCMYK(p_Stream); return; default: throw new Exception("RAW ColorMode =" + m_HeaderInfo.ColorMode.ToString()); } } private void LoadRAWCMYK(FileStream p_Stream) { int _Width = (int)m_HeaderInfo.Width; int _Height = (int)m_HeaderInfo.Height; m_PSDImage = new Bitmap(_Width, _Height, PixelFormat.Format24bppRgb); BitmapData _PSDImageData = m_PSDImage.LockBits(new Rectangle(0, 0, m_PSDImage.Width, m_PSDImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); byte[] _WriteBytes = new byte[_PSDImageData.Stride * _PSDImageData.Height]; int _PerPixel = m_HeaderInfo.BitsPerPixel / 8; int _PixelsCount = _Width * _Height; int _BytesCount = _PixelsCount * 4 * _PerPixel; byte[] _ImageBytes = new byte[_BytesCount]; p_Stream.Read(_ImageBytes, 0, _BytesCount); int _StarIndex = 0; int _Index = 0; int _Size = _Width * _Height; double C; double M; double Y; double K; double _MaxColours = Math.Pow(2, m_HeaderInfo.BitsPerPixel); int _Size2 = _Size * 2; int _Size3 = _Size * 3; if (_PerPixel == 2) { _Size *= 2; _Size2 *= 2; _Size3 *= 2; } for (int i = 0; i != _PSDImageData.Height; i++) { _StarIndex = _PSDImageData.Stride * i; _Index = i * _Width; if (_PerPixel == 2) _Index *= 2; for (int z = 0; z != _PSDImageData.Width; z++) { switch (_PerPixel) { case 1: C = 1.0 - (double)_ImageBytes[_Index + z] / _MaxColours; M = 1.0 - (double)_ImageBytes[_Index + z + _Size] / _MaxColours; Y = 1.0 - (double)_ImageBytes[_Index + z + _Size2] / _MaxColours; K = 1.0 - (double)_ImageBytes[_Index + z + _Size3] / _MaxColours; ConvertCMYKToRGB(C, M, Y, K, _WriteBytes, _StarIndex + z * 3); break; case 2: C = 1.0 - (double)BitConverter.ToUInt16(_ImageBytes, _Index + z * 2) / _MaxColours; M = 1.0 - (double)BitConverter.ToUInt16(_ImageBytes, _Index + z * 2 + _Size) / _MaxColours; Y = 1.0 - (double)BitConverter.ToUInt16(_ImageBytes, _Index + z * 2 + _Size2) / _MaxColours; K = 1.0 - (double)BitConverter.ToUInt16(_ImageBytes, _Index + z * 2 + _Size3) / _MaxColours; ConvertCMYKToRGB(C, M, Y, K, _WriteBytes, _StarIndex + z * 3); break; } } } Marshal.Copy(_WriteBytes, 0, _PSDImageData.Scan0, _WriteBytes.Length); m_PSDImage.UnlockBits(_PSDImageData); } /// <summary> /// 直接获取RGB 256色图 /// </summary> /// <param name="p_Stream"></param> private void LoadRAWIndex(FileStream p_Stream) { int _Width = (int)m_HeaderInfo.Width; int _Height = (int)m_HeaderInfo.Height; m_PSDImage = new Bitmap(_Width, _Height, PixelFormat.Format8bppIndexed); BitmapData _PSDImageData = m_PSDImage.LockBits(new Rectangle(0, 0, m_PSDImage.Width, m_PSDImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); byte[] _ImageBytes = new byte[_PSDImageData.Stride * _PSDImageData.Height]; int _PixelsCount = _Width * _Height; byte[] _Data = new byte[_PixelsCount]; p_Stream.Read(_Data, 0, _PixelsCount); int _ReadIndex = 0; int _WriteIndex = 0; for (int i = 0; i != _Height; i++) { _WriteIndex = i * _PSDImageData.Stride; for (int z = 0; z != _Width; z++) { _ImageBytes[z + _WriteIndex] = _Data[_ReadIndex]; _ReadIndex++; } } Marshal.Copy(_ImageBytes, 0, _PSDImageData.Scan0, _ImageBytes.Length); m_PSDImage.UnlockBits(_PSDImageData); } /// <summary> /// 获取图形24B Photo里对应为 /// </summary> /// <param name="p_Stream"></param> private void LoadRAWRGB(FileStream p_Stream) { int _Width = (int)m_HeaderInfo.Width; int _Height = (int)m_HeaderInfo.Height; m_PSDImage = new Bitmap(_Width, _Height, PixelFormat.Format24bppRgb); BitmapData _PSDImageData = m_PSDImage.LockBits(new Rectangle(0, 0, m_PSDImage.Width, m_PSDImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); byte[] _ImageBytes = new byte[_PSDImageData.Stride * _PSDImageData.Height]; int _PixelsCount = _Width * _Height; int _BytesCount = _PixelsCount * 3 * (m_HeaderInfo.BitsPerPixel / 8); byte[] _Data = new byte[_BytesCount]; p_Stream.Read(_Data, 0, _BytesCount); int _Red = 0; int _Green = _PixelsCount; int _Blue = _PixelsCount + _PixelsCount; int _ReadIndex = 0; int _WriteIndex = 0; if (m_HeaderInfo.BitsPerPixel == 16) { _Green *= m_HeaderInfo.BitsPerPixel / 8; _Blue *= m_HeaderInfo.BitsPerPixel / 8; } for (int i = 0; i != _Height; i++) { _WriteIndex = i * _PSDImageData.Stride; for (int z = 0; z != _Width; z++) { _ImageBytes[(z * 3) + 2 + _WriteIndex] = _Data[_ReadIndex + _Red]; _ImageBytes[(z * 3) + 1 + _WriteIndex] = _Data[_ReadIndex + _Green]; _ImageBytes[(z * 3) + _WriteIndex] = _Data[_ReadIndex + _Blue]; _ReadIndex += m_HeaderInfo.BitsPerPixel / 8; } } Marshal.Copy(_ImageBytes, 0, _PSDImageData.Scan0, _ImageBytes.Length); m_PSDImage.UnlockBits(_PSDImageData); } #endregion private Bitmap m_PSDImage; public Bitmap PSDImage { get { return m_PSDImage; } set { m_PSDImage = value; } } private void ConvertCMYKToRGB(double p_C, double p_M, double p_Y, double p_K, byte[] p_DataBytes, int p_Index) { int _Red = (int)((1.0 - (p_C * (1 - p_K) + p_K)) * 255); int _Green = (int)((1.0 - (p_M * (1 - p_K) + p_K)) * 255); int _Blue = (int)((1.0 - (p_Y * (1 - p_K) + p_K)) * 255); if (_Red < 0) _Red = 0; else if (_Red > 255) _Red = 255; if (_Green < 0) _Green = 0; else if (_Green > 255) _Green = 255; if (_Blue < 0) _Blue = 0; else if (_Blue > 255) _Blue = 255; p_DataBytes[p_Index] = (byte)_Blue; p_DataBytes[p_Index + 1] = (byte)_Green; p_DataBytes[p_Index + 2] = (byte)_Red; } } private PSDHEAD m_Head; private ColorModel m_ColorModel; private IList<BIM> m_8BIMList = new List<BIM>(); private LayerMaskInfo m_LayerMaskInfo; private ImageData m_ImageData; public ImagePsd(string p_FileFullPath) { if (!File.Exists(p_FileFullPath)) return; FileStream _PSD = File.Open(p_FileFullPath, FileMode.Open); byte[] _HeadByte = new byte[26]; _PSD.Read(_HeadByte, 0, 26); m_Head = new PSDHEAD(_HeadByte); m_ColorModel = new ColorModel(_PSD); long _ReadCount = _PSD.Position; while (true) { BIM _Bim = new BIM(_PSD); if (!_Bim.Read || _PSD.Position - _ReadCount >= m_ColorModel.BIMSize) break; m_8BIMList.Add(_Bim); } m_LayerMaskInfo = new LayerMaskInfo(_PSD); m_ImageData = new ImageData(_PSD, m_Head); if (m_Head.ColorMode == 2) m_ImageData.PSDImage.Palette = m_ColorModel.ColorData; _PSD.Close(); } public ImagePsd() { NewPsd(); } public void NewPsd() { m_Head = new PSDHEAD(new byte[] { 0x38, 0x42, 0x50, 0x53, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x2C, 0x00, 0x00, 0x01, 0xB4, 0x00, 0x08, 0x00, 0x03 }); m_ColorModel = new ColorModel(); m_ImageData = new ImageData(); m_LayerMaskInfo = new LayerMaskInfo(); } /// <summary> /// 保存成PSD 注意这里保存成PSD文件的BIM信息是没用的.如果你用该类打开PSD文件.如果保存到原文件上会丢失Photoshop的设置 /// </summary> /// <param name="p_FileFullName">文件路径</param> public void Save(string p_FileFullName) { if (PSDImage != null) { Image _SetImage = PSDImage; NewPsd(); PSDImage = (Bitmap)_SetImage; //保存需要重新在载 int _Width = PSDImage.Width; int _Height = PSDImage.Height; m_Head.Height = (uint)_Height; m_Head.Width = (uint)_Width; byte[] _Bim = new byte[] { 0x38, 0x42, 0x49, 0x4D, 0x03, 0xED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x38, 0x42, 0x49, 0x4D, 0x03, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x42, 0x49, 0x4D, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; m_ColorModel.BIMSize = (uint)_Bim.Length; FileStream _SaveFile = new FileStream(p_FileFullName, FileMode.Create, FileAccess.Write); byte[] _Bytes = m_Head.GetBytes(); _SaveFile.Write(_Bytes, 0, _Bytes.Length); _Bytes = m_ColorModel.GetBytes(); _SaveFile.Write(_Bytes, 0, _Bytes.Length); _SaveFile.Write(_Bim, 0, _Bim.Length); _SaveFile.Write(new byte[2], 0, 2); _Bytes = m_LayerMaskInfo.GetBytes(); _SaveFile.Write(_Bytes, 0, _Bytes.Length); Bitmap _Bitmap = new Bitmap(_Width, _Height, PixelFormat.Format24bppRgb); Graphics _Graphics = Graphics.FromImage(_Bitmap); _Graphics.DrawImage(PSDImage, 0, 0, _Width, _Height); _Graphics.Dispose(); BitmapData _SaveData = _Bitmap.LockBits(new Rectangle(0, 0, _Width, _Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte[] _ReadByte = new byte[_SaveData.Stride * _Height]; Marshal.Copy(_SaveData.Scan0, _ReadByte, 0, _ReadByte.Length); byte[] _WriteByte = new byte[_Bitmap.Width * _Bitmap.Height * 3]; int _Size = _Width * _Height; int _Size2 = _Size * 2; for (int i = 0; i != _Height; i++) { int _Index = i * _SaveData.Stride; int _WriteIndex = i * _Width; for (int z = 0; z != _Width; z++) { _WriteByte[_WriteIndex + z] = _ReadByte[_Index + (z * 3) + 2]; _WriteByte[_WriteIndex + _Size + z] = _ReadByte[_Index + (z * 3) + 1]; _WriteByte[_WriteIndex + _Size2 + z] = _ReadByte[_Index + (z * 3) + 0]; } } _Bitmap.UnlockBits(_SaveData); _Bitmap.Dispose(); _SaveFile.Write(_WriteByte, 0, _WriteByte.Length); _SaveFile.Close(); } } /// <summary> /// PSD图形 /// </summary> public Bitmap PSDImage { get { return m_ImageData.PSDImage; } set { m_ImageData.PSDImage = value; } } } }
原文:http://blog.csdn.net/zgke/article/details/4213443