Beispiel #1
0
        /// <summary>
        /// Function to read uncompressed TGA scanline data.
        /// </summary>
        /// <param name="reader">The reader used to read in the data from the source stream.</param>
        /// <param name="width">Image width.</param>
        /// <param name="dest">Destination buffer pointner</param>
        /// <param name="format">Format of the destination buffer.</param>
        /// <param name="conversionFlags">Flags used for conversion.</param>
        private unsafe bool ReadCompressed(GorgonBinaryReader reader, int width, byte *dest, BufferFormat format, TGAConversionFlags conversionFlags)
        {
            bool setOpaque      = true;
            bool flipHorizontal = (conversionFlags & TGAConversionFlags.InvertX) == TGAConversionFlags.InvertX;
            bool expand         = (conversionFlags & TGAConversionFlags.Expand) == TGAConversionFlags.Expand;

            for (int x = 0; x < width;)
            {
                if (reader.BaseStream.Position >= reader.BaseStream.Length)
                {
                    throw new IOException(string.Format(Resources.GORIMG_ERR_FILE_FORMAT_NOT_CORRECT, Codec));
                }

                byte rleBlock = reader.ReadByte();
                int  size     = (rleBlock & 0x7F) + 1;
                if ((rleBlock & 0x80) != 0)
                {
                    if (!DecodeRleEncodedRun(reader, ref dest, ref x, size, width, expand, flipHorizontal, format))
                    {
                        setOpaque = false;
                    }
                    continue;
                }

                if (!DecodeUncompressedRun(reader, ref dest, ref x, size, width, expand, flipHorizontal, format))
                {
                    setOpaque = false;
                }
            }

            return(setOpaque);
        }
        /// <summary>
        /// Function to determine if a physical file system can be read by this provider.
        /// </summary>
        /// <param name="physicalPath">Path to the packed file containing the file system.</param>
        /// <returns><b>true</b> if the provider can read the packed file, <b>false</b> if not.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="physicalPath"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="physicalPath"/> parameter is an empty string.</exception>
        /// <remarks>
        /// <para>
        /// This will test a physical file system (e.g. a Zip file) to see if the provider can open it or not. If used with a directory on an operating system file system, this method should always return
        /// <b>false</b>.
        /// </para>
        /// <para>
        /// When used with a <see cref="IGorgonFileSystemProvider"/> that supports a non operating system based physical file system, such as the <see cref="GorgonFileSystemRamDiskProvider"/>, then this
        /// method should compare the <paramref name="physicalPath"/> with its <see cref="IGorgonFileSystemProvider.Prefix"/> to ensure that the <see cref="IGorgonFileSystem"/> requesting the provider is using the correct provider.
        /// </para>
        /// <para>
        /// Implementors of a <see cref="GorgonFileSystemProvider"/> should override this method to determine if a packed file can be read by reading the header of the file specified in <paramref name="physicalPath"/>.
        /// </para>
        /// </remarks>
        protected override bool OnCanReadFile(string physicalPath)
        {
            string header;

            using (var reader = new GorgonBinaryReader(File.Open(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read)))
            {
                // If the length of the stream is less or equal to the header size, it's unlikely that we can read this file.
                if (reader.BaseStream.Length <= GorPackHeader.Length)
                {
                    return(false);
                }

                reader.ReadByte();
                header = new string(reader.ReadChars(GorPackHeader.Length));
            }

            return(string.Equals(header, GorPackHeader));
        }
Beispiel #3
0
        /// <summary>
        /// Function to determine if a file can be read by this provider.
        /// </summary>
        /// <param name="physicalPath">Path to the file containing the file system.</param>
        /// <returns>
        /// TRUE if the provider can read the packed file, FALSE if not.
        /// </returns>
        /// <remarks>This method is applicable to packed files only.
        /// <para>Implementors must use this method to determine if a packed file can be read by reading the header of the file.</para>
        /// </remarks>
        /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="physicalPath"/> parameter is NULL (Nothing in VB.Net).</exception>
        /// <exception cref="System.ArgumentException">Thrown when the <paramref name="physicalPath"/> parameter is an empty string.</exception>
        public override bool CanReadFile(string physicalPath)
        {
            string header;

            if (physicalPath == null)
            {
                throw new ArgumentNullException("physicalPath");
            }

            if (string.IsNullOrWhiteSpace(physicalPath))
            {
                throw new ArgumentException(Resources.GORFS_PARAMETER_MUST_NOT_BE_EMPTY, "physicalPath");
            }

            using (var reader = new GorgonBinaryReader(File.Open(physicalPath, FileMode.Open, FileAccess.Read, FileShare.Read), false))
            {
                reader.ReadByte();
                header = new string(reader.ReadChars(GorgonGorPackPlugIn.GorPackHeader.Length));
            }

            return(string.Equals(header, GorgonGorPackPlugIn.GorPackHeader));
        }
Beispiel #4
0
        /// <summary>
        /// Function to decode an uncompressed run of pixel data.
        /// </summary>
        /// <param name="reader">The reader used to read the data from the stream.</param>
        /// <param name="dest">The destination buffer pointer.</param>
        /// <param name="x">The current horizontal position in the scanline.</param>
        /// <param name="runLength">The size of the run, in pixels.</param>
        /// <param name="width">The total width of the run.</param>
        /// <param name="expand"><b>true</b> to expand a 24bpp scanline to 32bpp, or <b>false</b> if no expansion is needed.</param>
        /// <param name="flipHorizontal"><b>true</b> to decode the pixels from right to left, or <b>false</b> to decode from left to right.</param>
        /// <param name="format">The pixel format.</param>
        /// <returns><b>true</b> if the run contains entirely transparent pixels, or <b>false</b> if not.</returns>
        private unsafe bool DecodeUncompressedRun(GorgonBinaryReader reader, ref byte *dest, ref int x, int runLength, int width, bool expand, bool flipHorizontal, BufferFormat format)
        {
            bool result = true;

            switch (format)
            {
            case BufferFormat.R8_UNorm:
                for (; runLength > 0; --runLength, ++x)
                {
                    if (x >= width)
                    {
                        throw new IOException(string.Format(Resources.GORIMG_ERR_FILE_FORMAT_NOT_CORRECT, Codec));
                    }

                    if (!flipHorizontal)
                    {
                        *(dest++) = reader.ReadByte();
                    }
                    else
                    {
                        *(dest--) = reader.ReadByte();
                    }
                }
                break;

            case BufferFormat.B5G5R5A1_UNorm:
            {
                ushort *destPtr = (ushort *)dest;

                for (; runLength > 0; runLength--, ++x)
                {
                    if (x >= width)
                    {
                        throw new IOException(string.Format(Resources.GORIMG_ERR_FILE_FORMAT_NOT_CORRECT, Codec));
                    }

                    ushort pixel = reader.ReadUInt16();

                    if ((pixel & 0x8000) != 0)
                    {
                        result = false;
                    }

                    if (!flipHorizontal)
                    {
                        *(destPtr++) = pixel;
                    }
                    else
                    {
                        *(destPtr--) = pixel;
                    }
                }

                // Send the updated destination address back to the calling function.
                // This is kind of ugly, but too lazy to make it nice.
                dest = (byte *)destPtr;
            }
                return(result);

            case BufferFormat.R8G8B8A8_UNorm:
            {
                uint *destPtr = (uint *)dest;

                for (; runLength > 0; --runLength, ++x)
                {
                    if (x >= width)
                    {
                        throw new IOException(string.Format(Resources.GORIMG_ERR_FILE_FORMAT_NOT_CORRECT, Codec));
                    }

                    uint pixel;

                    if (expand)
                    {
                        pixel  = (uint)((reader.ReadByte() << 16) | (reader.ReadByte() << 8) | reader.ReadByte() | 0xFF000000);
                        result = false;
                    }
                    else
                    {
                        pixel = reader.ReadUInt32();

                        if ((pixel & 0xFF000000) != 0)
                        {
                            result = false;
                        }
                    }

                    if (!flipHorizontal)
                    {
                        *(destPtr++) = pixel;
                    }
                    else
                    {
                        *(destPtr--) = pixel;
                    }
                }

                // Send the updated destination address back to the calling function.
                // This is kind of ugly, but too lazy to make it nice.
                dest = (byte *)destPtr;
            }
                return(result);
            }

            return(false);
        }
Beispiel #5
0
        /// <summary>
        /// Function to decode an uncompressed run of pixel data.
        /// </summary>
        /// <param name="reader">The reader used to read the data in the stream.</param>
        /// <param name="dest">The destination buffer pointer.</param>
        /// <param name="x">The current horizontal position in the scanline.</param>
        /// <param name="runLength">The size of the run, in pixels.</param>
        /// <param name="width">The total width of the run.</param>
        /// <param name="expand"><b>true</b> to expand a 24bpp scanline to 32bpp, or <b>false</b> if no expansion is needed.</param>
        /// <param name="flipHorizontal"><b>true</b> to decode the pixels from right to left, or <b>false</b> to decode from left to right.</param>
        /// <param name="format">The pixel format.</param>
        /// <returns><b>true</b> if the run contains entirely transparent pixels, or <b>false</b> if not.</returns>
        private unsafe bool DecodeRleEncodedRun(GorgonBinaryReader reader, ref byte *dest, ref int x, int runLength, int width, bool expand, bool flipHorizontal, BufferFormat format)
        {
            bool result = true;

            switch (format)
            {
            case BufferFormat.R8_UNorm:
                for (; runLength > 0; --runLength, ++x)
                {
                    if (x >= width)
                    {
                        throw new IOException(string.Format(Resources.GORIMG_ERR_FILE_FORMAT_NOT_CORRECT, Codec));
                    }

                    if (!flipHorizontal)
                    {
                        *(dest++) = reader.ReadByte();
                    }
                    else
                    {
                        *(dest--) = reader.ReadByte();
                    }
                }
                break;

            case BufferFormat.B5G5R5A1_UNorm:
            {
                ushort *destPtr = (ushort *)dest;
                ushort  pixel   = reader.ReadUInt16();

                if ((pixel & 0x8000) != 0)
                {
                    result = false;
                }

                for (; runLength > 0; runLength--, ++x)
                {
                    if (x >= width)
                    {
                        throw new IOException(string.Format(Resources.GORIMG_ERR_FILE_FORMAT_NOT_CORRECT, Codec));
                    }

                    if (!flipHorizontal)
                    {
                        *(destPtr++) = pixel;
                    }
                    else
                    {
                        *(destPtr--) = pixel;
                    }
                }

                dest = (byte *)destPtr;
            }
                return(result);

            case BufferFormat.R8G8B8A8_UNorm:
            {
                uint pixel;

                // Do expansion.
                if (expand)
                {
                    pixel  = (uint)((reader.ReadByte() << 16) | (reader.ReadByte() << 8) | reader.ReadByte() | 0xFF000000);
                    result = false;
                }
                else
                {
                    pixel = reader.ReadUInt32();

                    if ((pixel & 0xFF000000) != 0)
                    {
                        result = false;
                    }
                }

                uint *destPtr = (uint *)dest;

                for (; runLength > 0; --runLength, ++x)
                {
                    if (x >= width)
                    {
                        throw new IOException(string.Format(Resources.GORIMG_ERR_FILE_FORMAT_NOT_CORRECT, Codec));
                    }

                    if (!flipHorizontal)
                    {
                        *(destPtr++) = pixel;
                    }
                    else
                    {
                        *(destPtr--) = pixel;
                    }
                }

                dest = (byte *)destPtr;
            }
                return(result);
            }

            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Function to read in the TGA header from a stream.
        /// </summary>
        /// <param name="reader">The reader used to read the stream containing the data.</param>
        /// <param name="conversionFlags">Flags for conversion.</param>
        /// <returns>New image settings.</returns>
        private static IGorgonImageInfo ReadHeader(GorgonBinaryReader reader, out TGAConversionFlags conversionFlags)
        {
            conversionFlags = TGAConversionFlags.None;

            // Get the header for the file.
            TgaHeader header = reader.ReadValue <TgaHeader>();

            if ((header.ColorMapType != 0) || (header.ColorMapLength != 0) ||
                (header.Width <= 0) || (header.Height <= 0) ||
                ((header.Descriptor & TgaDescriptor.Interleaved2Way) == TgaDescriptor.Interleaved2Way) ||
                ((header.Descriptor & TgaDescriptor.Interleaved4Way) == TgaDescriptor.Interleaved4Way))
            {
                throw new NotSupportedException(Resources.GORIMG_ERR_TGA_TYPE_NOT_SUPPORTED);
            }

            BufferFormat pixelFormat = BufferFormat.Unknown;

            switch (header.ImageType)
            {
            case TgaImageType.TrueColor:
            case TgaImageType.TrueColorRLE:
                switch (header.BPP)
                {
                case 16:
                    pixelFormat = BufferFormat.B5G5R5A1_UNorm;
                    break;

                case 24:
                case 32:
                    pixelFormat = BufferFormat.R8G8B8A8_UNorm;
                    if (header.BPP == 24)
                    {
                        conversionFlags |= TGAConversionFlags.Expand;
                    }
                    break;
                }

                if (header.ImageType == TgaImageType.TrueColorRLE)
                {
                    conversionFlags |= TGAConversionFlags.RLE;
                }
                break;

            case TgaImageType.BlackAndWhite:
            case TgaImageType.BlackAndWhiteRLE:
                if (header.BPP == 8)
                {
                    pixelFormat = BufferFormat.R8_UNorm;
                }
                else
                {
                    throw new IOException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, header.ImageType));
                }

                if (header.ImageType == TgaImageType.BlackAndWhiteRLE)
                {
                    conversionFlags |= TGAConversionFlags.RLE;
                }
                break;

            default:
                throw new IOException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, header.ImageType));
            }

            var settings = new GorgonImageInfo(ImageType.Image2D, pixelFormat)
            {
                MipCount   = 1,
                ArrayCount = 1,
                Width      = header.Width,
                Height     = header.Height
            };

            if ((header.Descriptor & TgaDescriptor.InvertX) == TgaDescriptor.InvertX)
            {
                conversionFlags |= TGAConversionFlags.InvertX;
            }

            if ((header.Descriptor & TgaDescriptor.InvertY) == TgaDescriptor.InvertY)
            {
                conversionFlags |= TGAConversionFlags.InvertY;
            }

            if (header.IDLength <= 0)
            {
                return(settings);
            }

            // Skip these bytes.
            for (int i = 0; i < header.IDLength; i++)
            {
                reader.ReadByte();
            }

            return(settings);
        }