Ejemplo n.º 1
0
        /// <summary>
        /// Function to write an array of value types to a stream using the GorgonBinaryWriter and reading it back again using the GorgonBinaryReader.
        /// </summary>
        /// <param name="stream">The stream that will receive the data.</param>
        private static void WriteArrayValues(MemoryStream stream)
        {
            stream.Position = 0;

            var writer = new GorgonBinaryWriter(stream, true);
            var reader = new GorgonBinaryReader(stream, true);

            try
            {
                var expected = new SomeTestData[3];

                for (int i = 1; i < 4; ++i)
                {
                    expected[i - 1] = new SomeTestData
                    {
                        Value1 = i,
                        Value2 = System.Math.PI * i,
                        Value3 = (short)(i & 2)
                    };
                }

                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine("Writing/Reading an array of value types to a memory stream.");
                Console.ForegroundColor = ConsoleColor.White;

                writer.WriteRange(expected);

                stream.Position = 0;

                var actual = new SomeTestData[4];
                reader.ReadRange(actual, 1);

                for (int i = 1; i < 4; ++i)
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write($"[{i - 1}] ");
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.WriteLine($"int32 Value1 = {expected[i - 1].Value1}: {actual[i].Value1 == expected[i - 1].Value1}");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write($"[{i - 1}] ");
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.WriteLine($"double Value2 = {expected[i - 1].Value2:0.00000}: {actual[i].Value2.EqualsEpsilon(expected[i - 1].Value2)}");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write($"[{i - 1}] ");
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.WriteLine($"int16 Value3 = {expected[i - 1].Value3}: {actual[i].Value3 == expected[i - 1].Value3}");
                }

                stream.Position = 0;
            }
            finally
            {
                writer.Dispose();
                reader.Dispose();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Function to persist a <see cref="IGorgonImage"/> to a stream.
        /// </summary>
        /// <param name="imageData">A <see cref="IGorgonImage"/> to persist to the stream.</param>
        /// <param name="stream">The stream that will receive the image data.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/>, or the <paramref name="imageData"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="stream"/> is read only.</exception>
        /// <exception cref="NotSupportedException">Thrown when the image data in the stream has a pixel format that is unsupported by the codec.</exception>
        /// <remarks>
        /// <para>
        /// When persisting image data via a codec, the image must have a format that the codec can recognize. This list of supported formats is provided by the <see cref="SupportedPixelFormats"/>
        /// property. Applications may convert their image data a supported format before saving the data using a codec.
        /// </para>
        /// </remarks>
        public override void SaveToStream(IGorgonImage imageData, Stream stream)
        {
            // Ensure that we can actually read this format.  We do not perform total pixel conversion on behalf of the user, they are responsible for that.
            // We will, however, support swizzling and pixel compression (e.g. 32 -> 24 bit).
            if (Array.IndexOf(_supportedFormats, imageData.Format) == -1)
            {
                throw new NotSupportedException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, imageData.Format));
            }

            using (var writer = new GorgonBinaryWriter(stream, true))
            {
                // Write the header for the file before we dump the file contents.
                TgaHeader header = GetHeader(imageData, out TGAConversionFlags conversionFlags);

                GorgonPitchLayout destPitch;

                if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                {
                    destPitch = new GorgonPitchLayout(imageData.Width * 3, imageData.Width * 3 * imageData.Height);
                }
                else
                {
                    var formatInfo = new GorgonFormatInfo(imageData.Format);
                    destPitch = formatInfo.GetPitchForFormat(imageData.Width, imageData.Height);
                }

                GorgonPitchLayout srcPitch = imageData.Buffers[0].PitchInformation;

                // If the two pitches are equal and we have no conversion requirements, then just write out the buffer.
                if ((destPitch == srcPitch) && (conversionFlags == TGAConversionFlags.None))
                {
                    writer.WriteValue(ref header);
                    writer.WriteRange(imageData.Buffers[0].Data, count: srcPitch.SlicePitch);
                    return;
                }

                unsafe
                {
                    // Get the pointer to the first mip/array/depth level.
                    byte *srcPointer = (byte *)imageData.Buffers[0].Data;
                    var   lineBuffer = new GorgonNativeBuffer <byte>(srcPitch.RowPitch);

                    try
                    {
                        // Persist the working buffer to the stream.
                        writer.WriteValue(ref header);

                        // Write out each scan line.
                        for (int y = 0; y < imageData.Height; y++)
                        {
                            byte *destPtr = (byte *)lineBuffer;

                            if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                            {
                                ImageUtilities.Compress24BPPScanLine(srcPointer,
                                                                     srcPitch.RowPitch,
                                                                     destPtr,
                                                                     destPitch.RowPitch,
                                                                     (conversionFlags & TGAConversionFlags.Swizzle) == TGAConversionFlags.Swizzle);
                            }
                            else if ((conversionFlags & TGAConversionFlags.Swizzle) == TGAConversionFlags.Swizzle)
                            {
                                ImageUtilities.SwizzleScanline(srcPointer, srcPitch.RowPitch, destPtr, destPitch.RowPitch, imageData.Format, ImageBitFlags.None);
                            }
                            else
                            {
                                ImageUtilities.CopyScanline(srcPointer, srcPitch.RowPitch, destPtr, destPitch.RowPitch, imageData.Format, ImageBitFlags.None);
                            }

                            srcPointer += srcPitch.RowPitch;

                            writer.WriteRange(lineBuffer, count: destPitch.RowPitch);
                        }
                    }
                    finally
                    {
                        lineBuffer?.Dispose();
                    }
                }
            }
        }