C# 读写 Photoshop PSD文件 操作类

来源:互联网 发布:骚男的淘宝店叫什么 编辑:程序博客网 时间:2024/05/17 06:34

分析了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; }
        }
    }
}