Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GorgonChunkedFormat" /> class.
        /// </summary>
        /// <param name="stream">The stream to use to output the chunked data.</param>
        /// <param name="accessMode">Stream access mode for the chunk object.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is NULL (Nothing in VB.Net).</exception>
        /// <exception cref="System.ArgumentException">Thrown when the <paramref name="accessMode"/> parameter is set to read, but the stream cannot be read.
        /// <para>-or-</para>
        /// <para>Thrown when the accessMode parameter is set to write, but the stream cannot be written.</para>
        /// <para>-or-</para>
        /// <para>Thrown if the stream can't perform seek operations.</para>
        /// </exception>
        protected GorgonChunkedFormat(Stream stream, ChunkAccessMode accessMode)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            ChunkAccessMode = accessMode;

            if (!stream.CanSeek)
            {
                throw new ArgumentException(Resources.GOR_STREAM_NOT_SEEKABLE, "stream");
            }

            if (accessMode == ChunkAccessMode.Write)
            {
                if (!stream.CanWrite)
                {
                    throw new ArgumentException(Resources.GOR_STREAM_IS_READONLY, "accessMode");
                }

                Writer = new GorgonBinaryWriter(stream, true);
            }
            else
            {
                if (!stream.CanRead)
                {
                    throw new ArgumentException(Resources.GOR_STREAM_IS_WRITEONLY, "accessMode");
                }

                Reader = new GorgonBinaryReader(stream, true);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Function to write out the DDS header to the stream.
        /// </summary>
        /// <param name="settings">Meta data for the image header.</param>
        /// <param name="writer">Writer interface for the stream.</param>
        /// <param name="conversionFlags">Flags for image conversion.</param>
        private void WriteHeader(IImageSettings settings, GorgonBinaryWriter writer, out TGAConversionFlags conversionFlags)
        {
            TGAHeader header = default(TGAHeader);

            conversionFlags = TGAConversionFlags.None;

            if ((settings.Width > 0xFFFF) ||
                (settings.Height > 0xFFFF))
            {
                throw new IOException(string.Format(Resources.GORGFX_IMAGE_FILE_INCORRECT_ENCODER, Codec));
            }

            header.Width  = (ushort)(settings.Width);
            header.Height = (ushort)(settings.Height);

            switch (settings.Format)
            {
            case BufferFormat.R8G8B8A8_UIntNormal:
            case BufferFormat.R8G8B8A8_UIntNormal_sRGB:
                header.ImageType  = TGAImageType.TrueColor;
                header.BPP        = 32;
                header.Descriptor = TGADescriptor.InvertY | TGADescriptor.RGB888A8;
                conversionFlags  |= TGAConversionFlags.Swizzle;
                break;

            case BufferFormat.B8G8R8A8_UIntNormal:
            case BufferFormat.B8G8R8A8_UIntNormal_sRGB:
                header.ImageType  = TGAImageType.TrueColor;
                header.BPP        = 32;
                header.Descriptor = TGADescriptor.InvertY | TGADescriptor.RGB888A8;
                break;

            case BufferFormat.B8G8R8X8_UIntNormal:
            case BufferFormat.B8G8R8X8_UIntNormal_sRGB:
                header.ImageType  = TGAImageType.TrueColor;
                header.BPP        = 24;
                header.Descriptor = TGADescriptor.InvertY;
                conversionFlags  |= TGAConversionFlags.RGB888;
                break;

            case BufferFormat.R8_UIntNormal:
            case BufferFormat.A8_UIntNormal:
                header.ImageType  = TGAImageType.BlackAndWhite;
                header.BPP        = 8;
                header.Descriptor = TGADescriptor.InvertY;
                break;

            case BufferFormat.B5G5R5A1_UIntNormal:
                header.ImageType  = TGAImageType.TrueColor;
                header.BPP        = 16;
                header.Descriptor = TGADescriptor.InvertY | TGADescriptor.RGB555A1;
                break;

            default:
                throw new IOException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, settings.Format));
            }

            // Persist to stream.
            writer.WriteValue(header);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GorgonChunkedFormat" /> class.
        /// </summary>
        /// <param name="stream">The stream to use to output the chunked data.</param>
        /// <param name="accessMode">Stream access mode for the chunk object.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is NULL (Nothing in VB.Net).</exception>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="accessMode"/> parameter is set to read, but the stream cannot be read.
        /// <para>-or-</para>
        /// <para>Thrown when the accessMode parameter is set to write, but the stream cannot be written.</para>
        /// <para>-or-</para>
        /// <para>Thrown if the stream can't perform seek operations.</para>
        /// </exception>
        protected GorgonChunkedFormat(Stream stream, ChunkAccessMode accessMode)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            ChunkAccessMode = accessMode;

            if (!stream.CanSeek)
            {
                throw new ArgumentException(Resources.GOR2DIO_ERR_STREAM_UNSEEKABLE, nameof(stream));
            }

            if (accessMode == ChunkAccessMode.Write)
            {
                if (!stream.CanWrite)
                {
                    throw new ArgumentException(Resources.GOR2DIO_ERR_STREAM_IS_READ_ONLY, nameof(accessMode));
                }

                Writer = new GorgonBinaryWriter(stream, true);
            }
            else
            {
                if (!stream.CanRead)
                {
                    throw new ArgumentException(Resources.GOR2DIO_ERR_STREAM_IS_WRITE_ONLY, nameof(accessMode));
                }

                Reader = new GorgonBinaryReader(stream, true);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Function to persist image data to a stream.
        /// </summary>
        /// <param name="imageData"><see cref="GorgonLibrary.Graphics.GorgonImageData">Gorgon image data</see> to persist.</param>
        /// <param name="stream">Stream that will contain the data.</param>
        protected internal override void SaveToStream(GorgonImageData imageData, Stream stream)
        {
            // Use a binary writer.
            using (var writer = new GorgonBinaryWriter(stream, true))
            {
                // Write the header for the file.
                TGAConversionFlags conversionFlags;
                WriteHeader(imageData.Settings, writer, out conversionFlags);

                GorgonFormatPitch pitch;
                if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                {
                    pitch = new GorgonFormatPitch(imageData.Settings.Width * 3, imageData.Settings.Width * 3 * imageData.Settings.Height);
                }
                else
                {
                    var formatInfo = GorgonBufferFormatInfo.GetInfo(imageData.Settings.Format);
                    pitch = formatInfo.GetPitch(imageData.Settings.Width, imageData.Settings.Height, PitchFlags.None);
                }

                // Get the pointer to the first mip/array/depth level.
                var srcPointer = (byte *)imageData.Buffers[0].Data.UnsafePointer;
                var srcPitch   = imageData.Buffers[0].PitchInformation;

                // If the two pitches are equal, then just write out the buffer.
                if ((pitch == srcPitch) && (conversionFlags == TGAConversionFlags.None))
                {
                    writer.Write(srcPointer, srcPitch.SlicePitch);
                    return;
                }

                // If we have to do a conversion, create a worker buffer.
                using (var convertBuffer = new GorgonDataStream(pitch.SlicePitch))
                {
                    var destPtr = (byte *)convertBuffer.UnsafePointer;

                    // Write out each scan line.
                    for (int y = 0; y < imageData.Settings.Height; y++)
                    {
                        if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                        {
                            Compress24BPPScanLine(srcPointer, srcPitch.RowPitch, destPtr, pitch.RowPitch);
                        }
                        else if ((conversionFlags & TGAConversionFlags.Swizzle) == TGAConversionFlags.Swizzle)
                        {
                            SwizzleScanline(srcPointer, srcPitch.RowPitch, destPtr, pitch.RowPitch, imageData.Settings.Format, ImageBitFlags.None);
                        }
                        else
                        {
                            CopyScanline(srcPointer, srcPitch.RowPitch, destPtr, pitch.RowPitch, imageData.Settings.Format, ImageBitFlags.None);
                        }

                        destPtr    += pitch.RowPitch;
                        srcPointer += srcPitch.RowPitch;
                    }

                    // Persist to the stream.
                    writer.Write(convertBuffer.UnsafePointer, pitch.SlicePitch);
                }
            }
        }