Пример #1
0
 /// <summary>
 /// Creates a new instance of the TargaImage object.
 /// </summary>
 public TargaImage()
 {
     this.objTargaFooter = new TargaFooter();
     this.objTargaHeader = new TargaHeader();
     this.objTargaExtensionArea = new TargaExtensionArea();
     this.bmpTargaImage = null;
     this.bmpImageThumbnail = null;
 }
Пример #2
0
        public static IPixelArray CreatePixelArrayFromFileStream(FileStream filestream)
        {
            int tgaSize;
            bool isExtendedFile;

            long fileLength = filestream.Length;

            // We'll use a binary reader to make it easier
            // to get at the specific data types
            BinaryReader reader = new BinaryReader(filestream);

            // Targa images come in many different formats, and there are a couple of different versions
            // of the specification.
            // First thing to do is determine if the file is adhereing to version 2.0 of the spcification.
            // We do that by reading a 'footer', which is the last 26 bytes of the file.

            string targaXFileID = "TRUEVISION-XFILE";
            TargaFooter footer = null;

            // Get the last 26 bytes of the file so we can see if the signature
            // is in there.
            long seekPosition = filestream.Seek(fileLength - 26, SeekOrigin.Begin);
            byte[] targaFooterBytes = reader.ReadBytes(26);
            string targaFooterSignature = System.Text.ASCIIEncoding.ASCII.GetString(targaFooterBytes, 8, 16);

            // If the strings compare favorably, then we have a match for an extended
            // TARGA file type.
            isExtendedFile = (0 == string.Compare(targaFooterSignature, targaXFileID));
            if (isExtendedFile)
            {
                // Since we now know it's an extended file, 
                // we'll create the footer object and fill
                // in the details.
                footer = new TargaFooter();

                // Of the 26 bytes we read from the end of the file
                // the bytes are layed out as follows.
                //Bytes 0-3: The Extension Area Offset
                //Bytes 4-7: The Developer Directory Offset
                //Bytes 8-23: The Signature
                //Byte 24: ASCII Character “.”
                //Byte 25: Binary zero string terminator (0x00)

                // We take those raw bytes, and turn them into meaningful fields
                // in the footer object.
                footer.ExtensionAreaOffset = BitConverter.ToInt32(targaFooterBytes, 0);
                footer.DeveloperDirectoryOffset = BitConverter.ToInt32(targaFooterBytes, 4);
                footer.Signature = targaFooterSignature;
                footer.Period = (byte)'.';
                footer.BinaryZero = 0;

            }

            // Now create the header that we'll fill int
            TargaHeader fHeader = new TargaHeader();

            // Go back to the beginning of the file first
            filestream.Seek(0, SeekOrigin.Begin);


            fHeader.IDLength = reader.ReadByte();
            fHeader.ColorMapType = (TargaColorMapType)reader.ReadByte();
            fHeader.ImageType = (TargaImageType)reader.ReadByte();
            fHeader.CMapStart = reader.ReadInt16();
            fHeader.CMapLength = reader.ReadInt16();
            fHeader.CMapDepth = reader.ReadByte();


            // Image description
            fHeader.XOffset = reader.ReadInt16();
            fHeader.YOffset = reader.ReadInt16();
            fHeader.Width = reader.ReadInt16();         // Width of image in pixels
            fHeader.Height = reader.ReadInt16();        // Height of image in pixels
            fHeader.PixelDepth = reader.ReadByte();     // How many bits per pixel
            fHeader.ImageDescriptor = reader.ReadByte();


            /// The single byte that is the ImageDescriptor contains the following
            /// information.
            //  Bits 3-0 - number of attribute bits associated with each  |
            //               pixel.  For the Targa 16, this would be 0 or |
            //               1.  For the Targa 24, it should be 0.  For   |
            //               Targa 32, it should be 8.                    |
            //  Bit 4    - controls left/right transfer of pixels to 
            ///             the screen.
            ///             0 = left to right
            ///             1 = right to left
            //  Bit 5    - controls top/bottom transfer of pixels to 
            ///             the screen.
            ///             0 = bottom to top
            ///             1 = top to bottom
            ///             
            ///             In Combination bits 5/4, they would have these values
            ///             00 = bottom left
            ///             01 = bottom right
            ///             10 = top left
            ///             11 = top right
            ///             
            //  Bits 7-6 - Data storage interleaving flag.                |
            //             00 = non-interleaved.                          |
            //             01 = two-way (even/odd) interleaving.          |
            //             10 = four way interleaving.                    |
            //             11 = reserved.         

            byte desc = fHeader.ImageDescriptor;
            byte attrBits = (byte)(desc & 0x0F);
            byte horizontalOrder = (byte)((desc & 0x10) >> 4);
            byte verticalOrder = (byte)((desc & 0x20) >> 5);
            byte interleave = (byte)((desc & 0xC0) >> 6);


            // We can't deal with the compressed image types, so if we encounter
            // any of them, we'll just return null.
            if ((TargaImageType.TrueColor != fHeader.ImageType) && (TargaImageType.Monochrome != fHeader.ImageType))
            {
                return null;
            }

            PixmapOrientation pixmapOrientation = PixmapOrientation.BottomToTop;
            if (0 == verticalOrder)
                pixmapOrientation = PixmapOrientation.BottomToTop;
            else
                pixmapOrientation = PixmapOrientation.TopToBottom;

            int bytesPerPixel = fHeader.PixelDepth / 8;


            // Skip past the Image Identification field if there is one
            byte[] ImageIdentification;
            if (fHeader.IDLength > 0)
                ImageIdentification = reader.ReadBytes(fHeader.IDLength);

            // calculate image size based on bytes per pixel, width and height.
            int bytesPerRow = fHeader.Width * bytesPerPixel;
            tgaSize = bytesPerPixel * fHeader.Height;
            byte[] imageData = reader.ReadBytes((int)tgaSize);

            // Create the correct pixel array for the data
            switch (bytesPerPixel)
            {
                case 3:
                    {
                        PixelArray<BGRb> pixmap = new PixelArray<BGRb>(fHeader.Width, fHeader.Height, imageData);
                        return pixmap;
                    }

                case 4:
                    {
                        PixelArray<BGRAb> pixmap = new PixelArray<BGRAb>(fHeader.Width, fHeader.Height, imageData);
                        return pixmap;
                    }

                case 1:
                    {
                        PixelArray<Lumb> pixmap = new PixelArray<Lumb>(fHeader.Width, fHeader.Height, imageData);
                        return pixmap;
                    }
            }

            return null;
        }
Пример #3
0
        public static IPixelArray CreatePixelArrayFromFile(string filename)
        {
            int tgaSize;
            bool isExtendedFile;

            // Open the file.
            if ((null == filename) || (string.Empty == filename))
                return null;

            FileStream filestream = new FileStream(filename, FileMode.Open, FileAccess.Read);
            BinaryReader reader = new BinaryReader(filestream);

            // Targa images come in many different formats, and there are a couple of different versions
            // of the specification.
            // First thing to do is determine if the file is adhereing to version 2.0 of the spcification.
            // We do that by reading a 'footer', which is the last 26 bytes of the file.
            long fileLength = filestream.Length;
            long seekPosition = filestream.Seek(fileLength - 26, SeekOrigin.Begin);
            byte[] targaFooterBytes = reader.ReadBytes(26);
            string targaXFileID = "TRUEVISION-XFILE";
            string targaFooterSignature = System.Text.ASCIIEncoding.ASCII.GetString(targaFooterBytes, 8, 16);
            TargaFooter footer=null;
            isExtendedFile = (0 == string.Compare(targaFooterSignature, targaXFileID));
            if (isExtendedFile)
            {
                // Since we now know it's an extended file, 
                // we'll create the footer object and fill
                // in the details.
                footer = new TargaFooter();

                // Of the 26 bytes we read from the end of the file
                // the bytes are layed out as follows.
                //Bytes 0-3: The Extension Area Offset
                //Bytes 4-7: The Developer Directory Offset
                //Bytes 8-23: The Signature
                //Byte 24: ASCII Character “.”
                //Byte 25: Binary zero string terminator (0x00)

                // We take those raw bytes, and turn them into meaningful fields
                // in the footer object.
                footer.ExtensionAreaOffset = BitConverter.ToInt32(targaFooterBytes, 0);
                footer.DeveloperDirectoryOffset = BitConverter.ToInt32(targaFooterBytes, 4);
                footer.Signature = targaFooterSignature;
                footer.Period = (byte)'.';
                footer.BinaryZero = 0;

            }

            TargaHeader fHeader = new TargaHeader();

            // If you want to use unsafe code, you could do the following
            // there are two primary drawbacks.
            // 1. The targa image data is in Little-Endian format.  On platforms
            // that are big-endian, the data will not necessarily show up correctly in the header.
            // 2. You must compile with unsafe code.  That may or may not be a problem depending
            // on the application, but it really isn't a necessity.
            // 
            // The speed gain may not be realized, so there's really no reason for the added complexity.
            // First, just reader enough of bytes from the file to capture the 
            // header into a chunk of memory.
            //byte[] headerBytes = reader.ReadBytes(Marshal.SizeOf(fHeader));
            //IntPtr headerPtr;

            //unsafe
            //{
            //    GCHandle dataHandle = GCHandle.Alloc(headerBytes, GCHandleType.Pinned);
            //    try
            //    {
            //        headerPtr = (IntPtr)dataHandle.AddrOfPinnedObject();

            //        // Now use the marshaller to copy the header bytes into a structure
            //        fHeader = (TargaHeader)Marshal.PtrToStructure(headerPtr, typeof(TargaHeader));

            //    }
            //    finally
            //    {
            //        dataHandle.Free();
            //    }
            //}

            filestream.Seek(0, SeekOrigin.Begin);
            fHeader.IDLength = reader.ReadByte();
            fHeader.ColorMapType = (TargaColorMapType)reader.ReadByte();
            fHeader.ImageType = (TargaImageType)reader.ReadByte();
            fHeader.CMapStart = reader.ReadInt16();
            fHeader.CMapLength = reader.ReadInt16();
            fHeader.CMapDepth = reader.ReadByte();


            // Image description
            fHeader.XOffset = reader.ReadInt16();
            fHeader.YOffset = reader.ReadInt16();
            fHeader.Width = reader.ReadInt16();         // Width of image in pixels
            fHeader.Height = reader.ReadInt16();        // Height of image in pixels
            fHeader.PixelDepth = reader.ReadByte();     // How many bits per pixel
            fHeader.ImageDescriptor = reader.ReadByte();


            //              Image Descriptor Byte.                        |
            //  Bits 3-0 - number of attribute bits associated with each  |
            //               pixel.  For the Targa 16, this would be 0 or |
            //               1.  For the Targa 24, it should be 0.  For   |
            //               Targa 32, it should be 8.                    |
            //  Bit 4    - controls left/right transfer of pixels to 
            ///             the screen.
            ///             0 = left to right
            ///             1 = right to left
            //  Bit 5    - controls top/bottom transfer of pixels to 
            ///             the screen.
            ///             0 = bottom to top
            ///             1 = top to bottom
            ///             
            ///             In Combination bits 5/4, they would have these values
            ///             00 = bottom left
            ///             01 = bottom right
            ///             10 = top left
            ///             11 = top right
            ///             
            //  Bits 7-6 - Data storage interleaving flag.                |
            //             00 = non-interleaved.                          |
            //             01 = two-way (even/odd) interleaving.          |
            //             10 = four way interleaving.                    |
            //             11 = reserved.         

            byte desc = fHeader.ImageDescriptor;
            byte attrBits = (byte)(desc & 0x0F);
            ImageOrigin origin = (ImageOrigin)(desc & (byte)ImageOrigin.OriginMask);
            byte interleave = (byte)((desc & 0xC0) >> 6);


            // This routine can only deal with the uncompressed image types.
            // So, fail if this is not the case.
            if ((TargaImageType.TrueColor != fHeader.ImageType) && (TargaImageType.Monochrome != fHeader.ImageType))
            {
                filestream.Close();
                return null;
            }


            PixmapOrientation pixmapOrientation = PixmapOrientation.BottomToTop;
            if ((ImageOrigin.BottomLeft == origin) || (ImageOrigin.BottomRight == origin))
                pixmapOrientation = PixmapOrientation.BottomToTop;
            else
                pixmapOrientation = PixmapOrientation.TopToBottom;

            int bytesPerPixel = fHeader.PixelDepth / 8;
            

            // Skip past the Image Identification field
            byte[] ImageIdentification;
            if (fHeader.IDLength > 0)
                ImageIdentification = reader.ReadBytes(fHeader.IDLength);

            // calculate image size based on bytes per pixel, width and height.
            tgaSize = fHeader.Width * fHeader.Height * bytesPerPixel;
            byte[] imageData = reader.ReadBytes((int)tgaSize);
            filestream.Close();
            
            // Pin the array in mememory, and get a data pointer to it
            IntPtr dataPtr;

            unsafe
            {
                GCHandle dataHandle = GCHandle.Alloc(imageData, GCHandleType.Pinned);
                dataPtr = (IntPtr)dataHandle.AddrOfPinnedObject();

                // Create the appropriate PixelArray
                // then create an accessor to match
                // Copy the data from the buffer pointer to the new array
                switch (bytesPerPixel)
                {
                    case 3:
                        {
                            PixelAccessorBGRb srcAccess = new PixelAccessorBGRb(fHeader.Width, fHeader.Height, pixmapOrientation, dataPtr);
                            PixelArray<BGRb> pixmap = new PixelArray<BGRb>(srcAccess);

                            return pixmap;
                        }
                        break;

                    case 4:
                        {
                            PixelAccessorBGRAb srcAccess = new PixelAccessorBGRAb(fHeader.Width, fHeader.Height, pixmapOrientation, dataPtr);
                            PixelArray<BGRAb> pixmap = new PixelArray<BGRAb>(srcAccess);

                            return pixmap;
                        }
                        break;

                    case 1:
                        {
                            PixelAccessorLumb srcAccess = new PixelAccessorLumb(fHeader.Width, fHeader.Height, pixmapOrientation, dataPtr);
                            PixelArray<Lumb> pixmap = new PixelArray<Lumb>(srcAccess);

                            return pixmap;
                        }
                        break;
                }
            }

            return null;
        }
Пример #4
0
        /// <summary>
        /// Clears out all objects and resources.
        /// </summary>
        private void ClearAll()
        {
            if (this.bmpTargaImage != null)
            {
                this.bmpTargaImage.Dispose();
                this.bmpTargaImage = null;
            }
            if (this.ImageByteHandle.IsAllocated)
                this.ImageByteHandle.Free();

            if (this.ThumbnailByteHandle.IsAllocated)
                this.ThumbnailByteHandle.Free();

            this.objTargaHeader = new TargaHeader();
            this.objTargaExtensionArea = new TargaExtensionArea();
            this.objTargaFooter = new TargaFooter();
            this.eTGAFormat = TGAFormat.UNKNOWN;
            this.intStride = 0;
            this.intPadding = 0;
            this.rows.Clear();
            this.row.Clear();
            this.strFileName = string.Empty;
        }