/// <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(); } }
/// <summary> /// Function to perform the copying of image data into the buffer. /// </summary> /// <param name="reader">A reader used to read the data from the source stream.</param> /// <param name="image">Image data.</param> /// <param name="conversionFlags">Flags used to convert the image.</param> private void CopyImageData(GorgonBinaryReader reader, IGorgonImage image, TGAConversionFlags conversionFlags) { // TGA only supports 1 array level, and 1 mip level, so we only need to get the first buffer. IGorgonImageBuffer buffer = image.Buffers[0]; // Determine how large a row is, in bytes. var formatInfo = new GorgonFormatInfo(image.Format); GorgonPitchLayout srcPitch = (conversionFlags & TGAConversionFlags.Expand) == TGAConversionFlags.Expand ? new GorgonPitchLayout(image.Width * 3, image.Width * 3 * image.Height) : formatInfo.GetPitchForFormat(image.Width, image.Height); unsafe { // Otherwise, allocate a buffer for conversion. byte *destPtr = (byte *)buffer.Data; // Adjust destination for inverted axes. if ((conversionFlags & TGAConversionFlags.InvertX) == TGAConversionFlags.InvertX) { destPtr += buffer.PitchInformation.RowPitch - formatInfo.SizeInBytes; } if ((conversionFlags & TGAConversionFlags.InvertY) != TGAConversionFlags.InvertY) { destPtr += (image.Height - 1) * buffer.PitchInformation.RowPitch; } // Used to counter the number of lines to force as opaque. int opaqueLineCount = 0; // The buffer used to hold an uncompressed scanline. GorgonNativeBuffer <byte> lineBuffer = null; try { for (int y = 0; y < image.Height; y++) { // Indicates that the scanline has an alpha of 0 for the entire run. bool lineHasZeroAlpha; if ((conversionFlags & TGAConversionFlags.RLE) == TGAConversionFlags.RLE) { lineHasZeroAlpha = ReadCompressed(reader, image.Width, destPtr, image.Format, conversionFlags); } else { // Read the current scanline into memory. if (lineBuffer == null) { lineBuffer = new GorgonNativeBuffer <byte>(srcPitch.RowPitch); } reader.ReadRange(lineBuffer, count: srcPitch.RowPitch); lineHasZeroAlpha = ReadUncompressed((byte *)lineBuffer, srcPitch.RowPitch, destPtr, image.Format, conversionFlags); } if ((lineHasZeroAlpha) && ((conversionFlags & TGAConversionFlags.SetOpaqueAlpha) == TGAConversionFlags.SetOpaqueAlpha)) { opaqueLineCount++; } // The components of the pixel data in a TGA file need swizzling for 32 bit. if (formatInfo.BitDepth == 32) { ImageUtilities.SwizzleScanline(destPtr, buffer.PitchInformation.RowPitch, destPtr, buffer.PitchInformation.RowPitch, image.Format, ImageBitFlags.None); } if ((conversionFlags & TGAConversionFlags.InvertY) != TGAConversionFlags.InvertY) { destPtr -= buffer.PitchInformation.RowPitch; } else { destPtr += buffer.PitchInformation.RowPitch; } } } finally { lineBuffer?.Dispose(); } if (opaqueLineCount != image.Height) { return; } // Set the alpha to opaque if we don't have any alpha values (i.e. alpha = 0 for all pixels). destPtr = (byte *)buffer.Data; for (int y = 0; y < image.Height; y++) { ImageUtilities.CopyScanline(destPtr, buffer.PitchInformation.RowPitch, destPtr, buffer.PitchInformation.RowPitch, image.Format, ImageBitFlags.OpaqueAlpha); destPtr += buffer.PitchInformation.RowPitch; } } }