コード例 #1
0
ファイル: GorgonRawHID.cs プロジェクト: ishkang/Gorgon
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            _preParsedData?.Dispose();
            _preParsedData = null;

            GC.SuppressFinalize(this);
        }
コード例 #2
0
        /// <summary>
        /// Function to return the object.
        /// </summary>
        /// <returns>The object created or updated by this builder.</returns>
        /// <exception cref="GorgonException">Thrown if the polygonal sprite has less than 3 vertices.</exception>
        /// <remarks>
        /// <para>
        /// This will return a <see cref="GorgonPolySprite"/> for use with the <see cref="Gorgon2D.DrawPolygonSprite"/> method. The object returned implements <see cref="IDisposable"/>, so it is the
        /// responsibility of the user to dispose of the object when they are done with it.
        /// </para>
        /// <para>
        /// <note type="warning">
        /// <para>
        /// A polygon sprite must have a minimum of 3 vertices.  If it does not, then this method will throw an exception.
        /// </para>
        /// </note>
        /// </para>
        /// </remarks>
        /// <seealso cref="GorgonPolySprite"/>
        /// <seealso cref="Gorgon2D"/>
        public GorgonPolySprite Build()
        {
            if (_workingSprite.RwVertices.Count < 3)
            {
                throw new GorgonException(GorgonResult.CannotCreate, Resources.GOR2D_ERR_POLY_SPRITE_NOT_ENOUGH_VERTS);
            }

            var newSprite = new GorgonPolySprite();

            CopySprite(newSprite, _workingSprite);

            newSprite.Renderable.ActualVertexCount = newSprite.RwVertices.Count;
            if ((newSprite.Renderable.Vertices == null) || (newSprite.Renderable.Vertices.Length < newSprite.RwVertices.Count))
            {
                newSprite.Renderable.Vertices = new Gorgon2DVertex[newSprite.RwVertices.Count];
            }

            for (int i = 0; i < newSprite.RwVertices.Count; ++i)
            {
                newSprite.Renderable.Vertices[i] = newSprite.RwVertices[i].Vertex;
            }

            // Enforce clockwise ordering.
            _triangulator.EnsureWindingOrder(newSprite.Renderable.Vertices, WindingOrder.CounterClockwise);

            // Split the polygon hull into triangles.
            (GorgonNativeBuffer <int> indices, DX.RectangleF bounds) = _triangulator.Triangulate(newSprite.Renderable.Vertices, WindingOrder.CounterClockwise);
            GorgonNativeBuffer <Gorgon2DVertex> vertexData = newSprite.Renderable.Vertices.ToNativeBuffer();

            try
            {
                newSprite.Renderable.IndexBuffer = new GorgonIndexBuffer(Graphics, new GorgonIndexBufferInfo
                {
                    Binding         = VertexIndexBufferBinding.None,
                    Use16BitIndices = false,
                    IndexCount      = indices.Length,
                    Usage           = ResourceUsage.Immutable
                }, indices);


                newSprite.Renderable.VertexBuffer = GorgonVertexBufferBinding.CreateVertexBuffer(Graphics, new GorgonVertexBufferInfo
                {
                    Usage       = ResourceUsage.Immutable,
                    Binding     = VertexIndexBufferBinding.None,
                    SizeInBytes = Gorgon2DVertex.SizeInBytes * newSprite.RwVertices.Count
                }, vertexData);
                newSprite.Renderable.ActualVertexCount = newSprite.RwVertices.Count;
                newSprite.Renderable.IndexCount        = indices.Length;
                newSprite.Bounds = new DX.RectangleF(newSprite.Position.X, newSprite.Position.Y, bounds.Width, bounds.Height);
            }
            finally
            {
                vertexData?.Dispose();
                indices?.Dispose();
            }

            return(newSprite);
        }
コード例 #3
0
        /// <summary>
        /// Function to convert the image data into a premultiplied format.
        /// </summary>
        /// <param name="baseImage">The image to convert.</param>
        /// <returns>A <see cref="IGorgonImage"/> containing the image data with the premultiplied alpha pixel data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="baseImage"/> is <b>null</b>.</exception>
        /// <exception cref="ArgumentException">Thrown when image format is compressed.</exception>
        /// <remarks>
        /// <para>
        /// Use this to convert an image to a premultiplied format. This takes each Red, Green and Blue element and multiplies them by the Alpha element.
        /// </para>
        /// <para>
        /// If the image does not contain alpha then the method will return right away and no alterations to the image will be performed.
        /// </para>
        /// </remarks>
        public static IGorgonImage ConvertToPremultipliedAlpha(this IGorgonImage baseImage)
        {
            IGorgonImage newImage = null;
            GorgonNativeBuffer <byte> imageData = null;

            if (baseImage == null)
            {
                throw new ArgumentNullException(nameof(baseImage));
            }

            if (!baseImage.FormatInfo.HasAlpha)
            {
                return(baseImage);
            }

            if (baseImage.FormatInfo.IsCompressed)
            {
                throw new ArgumentException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, baseImage.Format), nameof(baseImage));
            }

            try
            {
                var cloneImageInfo = new GorgonImageInfo(baseImage)
                {
                    HasPreMultipliedAlpha = true
                };
                imageData = new GorgonNativeBuffer <byte>(baseImage.ImageData.Length);
                baseImage.ImageData.CopyTo(imageData);

                unsafe
                {
                    newImage = new GorgonImage(cloneImageInfo, new GorgonReadOnlyPointer((void *)imageData, imageData.SizeInBytes));

                    int arrayOrDepth = newImage.ImageType == ImageType.Image3D ? newImage.Depth : newImage.ArrayCount;

                    for (int mip = 0; mip < newImage.MipCount; ++mip)
                    {
                        for (int i = 0; i < arrayOrDepth; ++i)
                        {
                            IGorgonImageBuffer buffer = newImage.Buffers[mip, i];
                            byte *ptr      = (byte *)buffer.Data;
                            int   rowPitch = buffer.PitchInformation.RowPitch;

                            for (int y = 0; y < buffer.Height; ++y)
                            {
                                ImageUtilities.SetPremultipliedScanline(ptr, rowPitch, ptr, rowPitch, buffer.Format);
                                ptr += rowPitch;
                            }
                        }
                    }
                }

                newImage.CopyTo(baseImage);

                return(baseImage);
            }
            finally
            {
                imageData?.Dispose();
                newImage?.Dispose();
            }
        }
コード例 #4
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();
                    }
                }
            }
        }