Пример #1
0
        /// <summary>
        /// Function to decode an image from a <see cref="Stream"/>.
        /// </summary>
        /// <param name="stream">The stream containing the image data to read.</param>
        /// <param name="size">The size of the image within the stream, in bytes.</param>
        /// <returns>A <see cref="IGorgonImage"/> containing the image data from the stream.</returns>
        /// <exception cref="GorgonException">Thrown when the image data in the stream has a pixel format that is unsupported.</exception>
        /// <remarks>
        /// <para>
        /// A codec must implement this method in order to decode the image data.
        /// </para>
        /// </remarks>
        protected override IGorgonImage OnDecodeFromStream(Stream stream, long size)
        {
            // Read the image meta data so we'll know how large the data should be.
            IGorgonImageInfo settings = ReadMetaData(stream);

            // Calculate the expected size of the image.
            int dataSize = settings.Width * settings.Height * sizeof(ushort);

            if ((size - TvHeader.SizeInBytes) != dataSize)
            {
                throw new GorgonException(GorgonResult.CannotRead, "The data in the stream is not the same size as the proposed image size.");
            }

            // Create our resulting image buffer.
            var result = new GorgonImage(settings);

            using (var reader = new GorgonBinaryReader(stream, true))
            {
                // Write each scanline.
                for (int y = 0; y < settings.Height; ++y)
                {
                    // Ensure that we move to the next line by the row pitch and not the amount of pixels.
                    // Some images put padding in for alignment reasons which can throw off the data offsets.
                    int ptrPosition = (y * result.Buffers[0].PitchInformation.RowPitch);

                    // Decode the pixels in the scan line for our resulting image.
                    for (int x = 0; x < settings.Width; ++x)
                    {
                        // Get our current pixel.
                        ushort pixel = reader.ReadUInt16();

                        // Since we encode 1 byte per color component for each pixel, we need to bump up the bit shift
                        // by 8 bits.  Once we get above 24 bits we'll start over since we're only working with 4 bytes
                        // per pixel in the destination.

                        // We determine how many bits to shift the pixel based on horizontal positioning.
                        // We assume that the image is based on 4 bytes/pixel.  In most cases this value should be
                        // determined by dividing the row pitch by the image width.

                        // Write the color by shifting the byte in the source data to the appropriate byte position.
                        uint color = (uint)(((pixel >> 8) & 0xff) << (8 * (x % 3)));
                        uint alpha = (uint)((pixel & 0xff) << 24);

                        ref uint imagePixel = ref result.ImageData.ReadAs <uint>(ptrPosition);
                        imagePixel   = color | alpha;
                        ptrPosition += sizeof(uint);
                    }
                }
            }
Пример #2
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);
        }
Пример #3
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);
        }
Пример #4
0
        /// <summary>
        /// Function to determine if the assembly defined in the assembly path is a .NET managed assembly or not.
        /// </summary>
        /// <param name="assemblyPath">The path to the assembly.</param>
        /// <returns>A tuple containing <b>true</b> if the file is a .NET managed assembly, <b>false</b> if not, and the type of expected platform that the assembly code is supposed to work under.</returns>
        public static (bool isManaged, AssemblyPlatformType platform) IsManagedAssembly(string assemblyPath)
        {
            if (!File.Exists(assemblyPath))
            {
                return(false, AssemblyPlatformType.Unknown);
            }

            uint cor2HeaderPtr = 0;
            AssemblyPlatformType platformType;

            // For this, we'll go into the guts of the file and read the data required instead of loading the assembly data and using exceptions to determine
            // the assembly type.
            //
            // This code is adapted from this stack overflow answer:
            // https://stackoverflow.com/questions/367761/how-to-determine-whether-a-dll-is-a-managed-assembly-or-native-prevent-loading

            using (FileStream stream = File.Open(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var reader = new GorgonBinaryReader(stream, false))
                {
                    // File is less than 64 bytes, not a portable executable.
                    if (stream.Length < 64)
                    {
                        return(false, AssemblyPlatformType.Unknown);
                    }

                    stream.Position = 0x3C;
                    uint headerPointer = reader.ReadUInt32();

                    if (headerPointer == 0)
                    {
                        headerPointer = 0x80;
                    }

                    if (headerPointer > stream.Length - 256)
                    {
                        return(false, AssemblyPlatformType.Unknown);
                    }

                    stream.Position = headerPointer;
                    uint signature = reader.ReadUInt32();

                    if (signature != PeHeaderSignature)
                    {
                        return(false, AssemblyPlatformType.Unknown);
                    }

                    stream.Position += 20;

                    ushort exePlatform = reader.ReadUInt16();

                    if ((exePlatform != Pe32Bit) && (exePlatform != Pe64bit))
                    {
                        return(false, AssemblyPlatformType.Unknown);
                    }

                    uint rvaPointer = 0;

                    switch (exePlatform)
                    {
                    case Pe32Bit:
                        platformType = AssemblyPlatformType.x86;
                        rvaPointer   = headerPointer + 232;
                        break;

                    case Pe64bit:
                        platformType = AssemblyPlatformType.x64;
                        rvaPointer   = headerPointer + 248;
                        break;

                    default:
                        return(false, AssemblyPlatformType.Unknown);
                    }

                    stream.Position = rvaPointer;
                    cor2HeaderPtr   = reader.ReadUInt32();
                }

            // AnyCPU assemblies are marked as x86.  We need to read the cor20 header, but I'm lazy and it's a lot of work.
            // So, we'll use the old tried and true method of reading the assembly metadata.  We shouldn't exception here because
            // we've already determined that we're not using a native DLL.  GetAssemblyName doesn't care if our executing platform
            // environment is x64 or x86 and our DLL doesn't match, it just reads the metadata (tested and confirmed).
            if ((cor2HeaderPtr != 0) && (platformType == AssemblyPlatformType.x86))
            {
                var name = AssemblyName.GetAssemblyName(assemblyPath);

                if (name.ProcessorArchitecture == ProcessorArchitecture.MSIL)
                {
                    platformType = AssemblyPlatformType.AnyCpu;
                }
            }

            return(cor2HeaderPtr != 0, platformType);
        }