C#解析SGI图形

 

 

SGI图形前2个字节 0x01,0xDA 应该是文件标识

第7个字节和第8个字节 是图形的宽

第9和第10个字节 是图形的高

一直到512个字节才是图形数据..这里的图形数据格式和PCX文件一样 先是文件RED分量 然后个Green 最后才是Blue ..

也就是说 先读取所有的RED分量然后Green.

使用方法

RED分量

            ImageSGI _SGI = new ImageSGI(@"c:\tEMP\24.SGI");
            pictureBox1.Image = _SGI.Image;
            _SGI.Image = this.Icon.ToBitmap();
            _SGI.SaveImage(@"C:\111.SGI"); 

下面是全部代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace WindowsApplication1
{
    /// <summary>
    /// Targa文件
    /// </summary>
    public class ImageSGI
    {
        public ImageSGI()
        {

        }

        public ImageSGI(string p_FileFullName)
        {
            if (System.IO.File.Exists(p_FileFullName))
            {
                LoadData(File.ReadAllBytes(p_FileFullName));
            }
        }

        #region 属性

        /// <summary>
        /// 文件头
        /// </summary>
        private byte[] m_Header = new byte[] { 0x01, 0xDA, 0x0, 0x1, 0x0, 0x3 };

        /// <summary>
        /// 宽
        /// </summary>
        private ushort m_Width = 0;

        /// <summary>
        /// 高
        /// </summary>
        private ushort m_Height = 0;

        /// <summary>
        /// 未知数据
        /// </summary>
        private byte[] m_UnknownData1 = new byte[] { 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF };

        /// <summary>
        /// 未知数据
        /// </summary>
        private byte[] m_UnknownData2 = new byte[492];

        /// <summary>
        /// 图形
        /// </summary>
        private Bitmap m_Image;

        #endregion

        /// <summary>
        /// 图形
        /// </summary>
        public Bitmap Image
        {
            get { return m_Image; }
            set
            {
                if (value != null)
                {
                    m_Width = (ushort)value.Width;
                    m_Height = (ushort)value.Height;
                    if (value.PixelFormat != PixelFormat.Format24bppRgb)
                    {
                        Bitmap _NewBitmap = new Bitmap(value.Width, value.Height, PixelFormat.Format24bppRgb);
                        Graphics _Graphics = Graphics.FromImage(_NewBitmap);
                        _Graphics.DrawImage(value, new Rectangle(0, 0, value.Width, value.Height));
                        _Graphics.Dispose();
                        m_Image = _NewBitmap;
                        return;
                    }
                }
                m_Image = value;
            }
        }
     
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="p_TGABytes"></param>
        private void LoadData(byte[] p_SGIBytes)
        {
            if (p_SGIBytes[0] == m_Header[0] && p_SGIBytes[1] == m_Header[1] && p_SGIBytes[2] == m_Header[2] && p_SGIBytes[3] == m_Header[3] && p_SGIBytes[4] == m_Header[4] && p_SGIBytes[5] == m_Header[5])
            {
                byte[] _ValueInt16 = new byte[2];
                _ValueInt16[1] = p_SGIBytes[6];
                _ValueInt16[0] = p_SGIBytes[7];
                m_Width = BitConverter.ToUInt16(_ValueInt16, 0);
                _ValueInt16[1] = p_SGIBytes[8];
                _ValueInt16[0] = p_SGIBytes[9];
                m_Height = BitConverter.ToUInt16(_ValueInt16, 0);

                int _ReadIndex = 512;
                LoadImageData(p_SGIBytes, ref _ReadIndex);
            }
            else
            {
                throw new Exception("格式不正确!");
            }
               
        }


        /// <summary>
        /// 获取数据到图形
        /// </summary>
        /// <param name="p_TAGBytes">数据</param>
        /// <param name="p_ReadIndex">数据开始位置</param>
        private void LoadImageData(byte[] p_SGIBytes,ref int p_ReadIndex)
        {
            m_Image = new Bitmap(m_Width, m_Height, PixelFormat.Format24bppRgb);
            BitmapData _ImageData = m_Image.LockBits(new Rectangle(0, 0, m_Image.Width, m_Image.Height), ImageLockMode.ReadWrite, m_Image.PixelFormat);
            byte[] _WriteBytes = new byte[_ImageData.Stride * _ImageData.Height];
            int _WriteIndex = 0;

            int _Address = m_Width * m_Height;
            for (int i = _ImageData.Height-1; i != -1; i--)
            {
                _WriteIndex = i * _ImageData.Stride;
                for (int z = 0; z != _ImageData.Width; z++)
                {
                    _WriteBytes[_WriteIndex + 2] = p_SGIBytes[p_ReadIndex];
                    _WriteBytes[_WriteIndex + 1] = p_SGIBytes[p_ReadIndex + _Address];
                    _WriteBytes[_WriteIndex] = p_SGIBytes[p_ReadIndex + _Address * 2];
                    _WriteIndex += 3;
                    p_ReadIndex++;
                }
            }
            Marshal.Copy(_WriteBytes, 0, _ImageData.Scan0, _WriteBytes.Length);
            m_Image.UnlockBits(_ImageData);
        }


        /// <summary>
        /// 保存SGI图形到文件
        /// </summary>
        /// <param name="p_FileFullName"></param>
        public void SaveImage(string p_FileFullName)
        {
            if (m_Image != null) File.WriteAllBytes(p_FileFullName, SaveImageToSGI());
        }

        private byte[] SaveImageToSGI()
        {          
            BitmapData _ImageData = m_Image.LockBits(new Rectangle(0, 0, m_Image.Width, m_Image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            byte[] _WriteBytes = new byte[_ImageData.Stride * _ImageData.Height];
            Marshal.Copy(_ImageData.Scan0, _WriteBytes, 0, _WriteBytes.Length);
            m_Image.UnlockBits(_ImageData);
            
            int _ReadIndex = 0;
            int _WidthIndex = 0;            
            
            int _Address = m_Width * m_Height;
            byte[] _Red = new byte[_Address];
            byte[] _Green = new byte[_Address];
            byte[] _Blue = new byte[_Address];
            for (int i = _ImageData.Height - 1; i != -1; i--)
            {
                _ReadIndex = i * _ImageData.Stride;
                for (int z = 0; z != _ImageData.Width; z++)
                {
                    _Red[_WidthIndex] = _WriteBytes[_ReadIndex + 2];
                    _Green[_WidthIndex] = _WriteBytes[_ReadIndex + 1];
                    _Blue[_WidthIndex] = _WriteBytes[_ReadIndex];
                    _ReadIndex += 3;
                    _WidthIndex++;
                }
            }

            MemoryStream _Stream = new MemoryStream();
            _Stream.Write(m_Header, 0, m_Header.Length);         
            byte[] _ValueInt16 = BitConverter.GetBytes(m_Width);
            Array.Reverse(_ValueInt16);
            _Stream.Write(_ValueInt16, 0,2);
            _ValueInt16 = BitConverter.GetBytes(m_Height);
            Array.Reverse(_ValueInt16);
            _Stream.Write(_ValueInt16, 0, 2);
            _Stream.Write(m_UnknownData1, 0, m_UnknownData1.Length);
            _Stream.Write(m_UnknownData2, 0, m_UnknownData2.Length);

            _Stream.Write(_Red, 0, _Address);
            _Stream.Write(_Green, 0, _Address);
            _Stream.Write(_Blue, 0, _Address);

            return _Stream.ToArray();
        }

    }
}

共有0个回答