Esempio n. 1
0
        public static void SetPixelData(this byte[] data, PixelBitmapContent <Color> bmpContent, SurfaceFormat format)
        {
            var formatSize = format.Size();

            for (int y = 0; y < bmpContent.Height; y++)
            {
                for (int x = 0; x < bmpContent.Width; x++)
                {
                    switch (format)
                    {
                    case SurfaceFormat.Vector4:

                        var startIdx = (y * formatSize) + (x * formatSize);
                        var vec4     = new Vector4(BitConverter.ToSingle(data, startIdx),
                                                   BitConverter.ToSingle(data, startIdx + 4),
                                                   BitConverter.ToSingle(data, startIdx + 8),
                                                   BitConverter.ToSingle(data, startIdx + 12));

                        bmpContent._pixelData[y][x] = new Color(vec4);
                        break;

                    default:
                        break;
                    }
                }
            }
        }
Esempio n. 2
0
        public static BitmapContent ToXnaBitmap(this Bitmap systemBitmap)
        {
            // Any bitmap using this function should use 32bpp ARGB pixel format, since we have to
            // swizzle the channels later
            System.Diagnostics.Debug.Assert(systemBitmap.PixelFormat == PixelFormat.Format32bppArgb);

            var bitmapData = systemBitmap.LockBits(new System.Drawing.Rectangle(0, 0, systemBitmap.Width, systemBitmap.Height),
                                                   ImageLockMode.ReadOnly,
                                                   systemBitmap.PixelFormat);

            var length    = bitmapData.Stride * bitmapData.Height;
            var pixelData = new byte[length];

            // Copy bitmap to byte[]
            Marshal.Copy(bitmapData.Scan0, pixelData, 0, length);
            systemBitmap.UnlockBits(bitmapData);

            // NOTE: According to http://msdn.microsoft.com/en-us/library/dd183449%28VS.85%29.aspx
            // and http://stackoverflow.com/questions/8104461/pixelformat-format32bppargb-seems-to-have-wrong-byte-order
            // Image data from any GDI based function are stored in memory as BGRA/BGR, even if the format says RGBA.
            // Because of this we flip the R and B channels.

            BGRAtoRGBA(pixelData);

            var xnaBitmap = new PixelBitmapContent <Color>(systemBitmap.Width, systemBitmap.Height);

            xnaBitmap.SetPixelData(pixelData);

            return(xnaBitmap);
        }
Esempio n. 3
0
        /// <summary>
        /// Copies one bitmap into another.
        /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly.
        /// </summary>
        /// <param name="sourceBitmap">BitmapContent being copied.</param>
        /// <param name="sourceRegion">Region of sourceBitmap.</param>
        /// <param name="destinationBitmap">BitmapContent being overwritten.</param>
        /// <param name="destinationRegion">Region of bitmap to be overwritten.</param>
        public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion)
        {
            ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion);

            SurfaceFormat sourceFormat;

            if (!sourceBitmap.TryGetFormat(out sourceFormat))
            {
                throw new InvalidOperationException("Could not retrieve surface format of source bitmap");
            }
            SurfaceFormat destinationFormat;

            if (!destinationBitmap.TryGetFormat(out destinationFormat))
            {
                throw new InvalidOperationException("Could not retrieve surface format of destination bitmap");
            }

            // If the formats are the same and the regions are the full bounds of the bitmaps and they are the same size, do a simpler copy
            if (sourceFormat == destinationFormat && sourceRegion == destinationRegion &&
                sourceRegion == new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height) &&
                destinationRegion == new Rectangle(0, 0, destinationBitmap.Width, destinationBitmap.Height))
            {
                destinationBitmap.SetPixelData(sourceBitmap.GetPixelData());
                return;
            }

            // The basic process is
            // 1. Copy from source bitmap region to a new PixelBitmapContent<Vector4> using sourceBitmap.TryCopyTo()
            // 2. If source and destination regions are a different size, resize Vector4 version
            // 3. Copy from Vector4 to destination region using destinationBitmap.TryCopyFrom()

            // Copy from the source to the intermediate Vector4 format
            var intermediate       = new PixelBitmapContent <Vector4>(sourceRegion.Width, sourceRegion.Height);
            var intermediateRegion = new Rectangle(0, 0, intermediate.Width, intermediate.Height);

            if (sourceBitmap.TryCopyTo(intermediate, sourceRegion, intermediateRegion))
            {
                // Resize the intermediate if required
                if (intermediate.Width != destinationRegion.Width || intermediate.Height != destinationRegion.Height)
                {
                    intermediate = intermediate.Resize(destinationRegion.Width, destinationRegion.Height) as PixelBitmapContent <Vector4>;
                }
                // Copy from the intermediate to the destination
                if (destinationBitmap.TryCopyFrom(intermediate, new Rectangle(0, 0, intermediate.Width, intermediate.Height), destinationRegion))
                {
                    return;
                }
            }

            // If we got here, one of the above steps didn't work
            throw new InvalidOperationException("Could not copy between " + sourceFormat + " and " + destinationFormat);
        }
        // Once arranging is complete, copies each glyph to its chosen position in the single larger output bitmap.
        static BitmapContent CopyGlyphsToOutput(List <ArrangedGlyph> glyphs, int width, int height)
        {
            var output = new PixelBitmapContent <Color>(width, height);

            foreach (var glyph in glyphs)
            {
                var sourceGlyph       = glyph.Source;
                var sourceRegion      = sourceGlyph.Subrect;
                var destinationRegion = new Rectangle(glyph.X + 1, glyph.Y + 1, sourceRegion.Width, sourceRegion.Height);

                BitmapContent.Copy(sourceGlyph.Bitmap, sourceRegion, output, destinationRegion);

                sourceGlyph.Bitmap  = output;
                sourceGlyph.Subrect = destinationRegion;
            }

            return(output);
        }
Esempio n. 5
0
        internal static void Resize(this TextureContent content, int newWidth, int newHeight)
        {
            var resizedBmp = new Bitmap(newWidth, newHeight);

            using (var graphics = System.Drawing.Graphics.FromImage(resizedBmp))
            {
                graphics.DrawImage(content._bitmap, 0, 0, newWidth, newHeight);

                content._bitmap.Dispose();
                content._bitmap = resizedBmp;
            }

            var imageData = content._bitmap.GetData();

            var bitmapContent = new PixelBitmapContent <Color>(content._bitmap.Width, content._bitmap.Height);

            bitmapContent.SetPixelData(imageData);

            content.Faces.Clear();
            content.Faces.Add(new MipmapChain(bitmapContent));
        }
Esempio n. 6
0
        internal static BitmapContent Resize(this BitmapContent bitmap, int newWidth, int newHeight)
        {
            BitmapContent src = bitmap;
            SurfaceFormat format;

            src.TryGetFormat(out format);
            if (format != SurfaceFormat.Vector4)
            {
                var v4 = new PixelBitmapContent <Vector4>(src.Width, src.Height);
                BitmapContent.Copy(src, v4);
                src = v4;
            }

            // Convert to FreeImage bitmap
            var bytes = src.GetPixelData();
            var fi    = FreeImage.ConvertFromRawBits(bytes, FREE_IMAGE_TYPE.FIT_RGBAF, src.Width, src.Height, SurfaceFormat.Vector4.GetSize() * src.Width, 128, 0, 0, 0, true);

            // Resize
            var newfi = FreeImage.Rescale(fi, newWidth, newHeight, FREE_IMAGE_FILTER.FILTER_BICUBIC);

            FreeImage.UnloadEx(ref fi);

            // Convert back to PixelBitmapContent<Vector4>
            src   = new PixelBitmapContent <Vector4>(newWidth, newHeight);
            bytes = new byte[SurfaceFormat.Vector4.GetSize() * newWidth * newHeight];
            FreeImage.ConvertToRawBits(bytes, newfi, SurfaceFormat.Vector4.GetSize() * newWidth, 128, 0, 0, 0, true);
            src.SetPixelData(bytes);
            FreeImage.UnloadEx(ref newfi);
            // Convert back to source type if required
            if (format != SurfaceFormat.Vector4)
            {
                var s = (BitmapContent)Activator.CreateInstance(bitmap.GetType(), new object[] { newWidth, newHeight });
                BitmapContent.Copy(src, s);
                src = s;
            }

            return(src);
        }
Esempio n. 7
0
 public static void SetPixelData <T>(this byte[] data, PixelBitmapContent <T> bmpContent, int startIndex, SurfaceFormat format) where T : struct, IEquatable <T>
 {
 }
        protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion)
        {
            SurfaceFormat sourceFormat;

            if (!sourceBitmap.TryGetFormat(out sourceFormat))
            {
                return(false);
            }

            SurfaceFormat format;

            TryGetFormat(out format);

            // A shortcut for copying the entire bitmap to another bitmap of the same type and format
            if (format == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion)
            {
                SetPixelData(sourceBitmap.GetPixelData());
                return(true);
            }

            // TODO: Add a XNA unit test to see what it does
            // my guess is that this is invalid for DXT.
            //
            // Destination region copy is not yet supported
            if (destinationRegion != new Rectangle(0, 0, Width, Height))
            {
                return(false);
            }

            // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy
            if (!(sourceBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height)
            {
                try
                {
                    BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion);
                    return(true);
                }
                catch (InvalidOperationException)
                {
                    return(false);
                }
            }

            // NVTT wants 8bit data in BGRA format.
            var colorBitmap = new PixelBitmapContent <Color>(sourceBitmap.Width, sourceBitmap.Height);

            BitmapContent.Copy(sourceBitmap, colorBitmap);
            var sourceData = colorBitmap.GetPixelData();
            var dataHandle = GCHandle.Alloc(sourceData, GCHandleType.Pinned);

            AlphaMode alphaMode;
            Format    outputFormat;
            var       alphaDither = false;

            switch (format)
            {
            case SurfaceFormat.Dxt1:
            case SurfaceFormat.Dxt1SRgb:
            {
                bool hasTransparency;
                PrepareNVTT_DXT1(sourceData, out hasTransparency);
                outputFormat = hasTransparency ? Format.DXT1a : Format.DXT1;
                alphaMode    = hasTransparency ? AlphaMode.Transparency : AlphaMode.None;
                alphaDither  = true;
                break;
            }

            case SurfaceFormat.Dxt3:
            case SurfaceFormat.Dxt3SRgb:
            {
                PrepareNVTT(sourceData);
                outputFormat = Format.DXT3;
                alphaMode    = AlphaMode.Transparency;
                break;
            }

            case SurfaceFormat.Dxt5:
            case SurfaceFormat.Dxt5SRgb:
            {
                PrepareNVTT(sourceData);
                outputFormat = Format.DXT5;
                alphaMode    = AlphaMode.Transparency;
                break;
            }

            default:
                throw new InvalidOperationException("Invalid DXT surface format!");
            }

            // Do all the calls to the NVTT wrapper within this handler
            // so we properly clean up if things blow up.
            try
            {
                var dataPtr = dataHandle.AddrOfPinnedObject();

                var inputOptions = new InputOptions();
                inputOptions.SetTextureLayout(TextureType.Texture2D, colorBitmap.Width, colorBitmap.Height, 1);
                inputOptions.SetMipmapData(dataPtr, colorBitmap.Width, colorBitmap.Height, 1, 0, 0);
                inputOptions.SetMipmapGeneration(false);
                inputOptions.SetGamma(1.0f, 1.0f);
                inputOptions.SetAlphaMode(alphaMode);

                var compressionOptions = new CompressionOptions();
                compressionOptions.SetFormat(outputFormat);
                compressionOptions.SetQuality(Quality.Normal);

                // TODO: This isn't working which keeps us from getting the
                // same alpha dither behavior on DXT1 as XNA.
                //
                // See https://github.com/MonoGame/MonoGame/issues/6259
                //
                //if (alphaDither)
                //compressionOptions.SetQuantization(false, false, true);

                var outputOptions = new OutputOptions();
                outputOptions.SetOutputHeader(false);
                outputOptions.SetOutputOptionsOutputHandler(NvttBeginImage, NvttWriteImage, NvttEndImage);

                var dxtCompressor = new Compressor();
                dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);
            }
            finally
            {
                dataHandle.Free();
            }

            return(true);
        }
        protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion)
        {
            SurfaceFormat sourceFormat;

            if (!sourceBitmap.TryGetFormat(out sourceFormat))
            {
                return(false);
            }

            SurfaceFormat format;

            TryGetFormat(out format);

            // A shortcut for copying the entire bitmap to another bitmap of the same type and format
            if (format == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion)
            {
                SetPixelData(sourceBitmap.GetPixelData());
                return(true);
            }

            // Destination region copy is not yet supported
            if (destinationRegion != new Rectangle(0, 0, Width, Height))
            {
                return(false);
            }

            // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy
            if (!(sourceBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height)
            {
                try
                {
                    BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion);
                    return(true);
                }
                catch (InvalidOperationException)
                {
                    return(false);
                }
            }

            // Convert to full colour 32-bit format. Floating point would be preferred for processing, but it appears the ATICompressor does not support this
            var colorBitmap = new PixelBitmapContent <Color>(sourceRegion.Width, sourceRegion.Height);

            BitmapContent.Copy(sourceBitmap, sourceRegion, colorBitmap, new Rectangle(0, 0, colorBitmap.Width, colorBitmap.Height));
            sourceBitmap = colorBitmap;

            ATICompressor.CompressionFormat targetFormat;
            switch (format)
            {
            case SurfaceFormat.RgbaAtcExplicitAlpha:
                targetFormat = ATICompressor.CompressionFormat.AtcRgbaExplicitAlpha;
                break;

            case SurfaceFormat.RgbaAtcInterpolatedAlpha:
                targetFormat = ATICompressor.CompressionFormat.AtcRgbaInterpolatedAlpha;
                break;

            default:
                return(false);
            }

            var sourceData     = sourceBitmap.GetPixelData();
            var compressedData = ATICompressor.Compress(sourceData, Width, Height, targetFormat);

            SetPixelData(compressedData);

            return(true);
        }
Esempio n. 10
0
        protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion)
        {
            SurfaceFormat sourceFormat;

            if (!sourceBitmap.TryGetFormat(out sourceFormat))
            {
                return(false);
            }

            SurfaceFormat format;

            TryGetFormat(out format);

            // A shortcut for copying the entire bitmap to another bitmap of the same type and format
            if (format == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion)
            {
                SetPixelData(sourceBitmap.GetPixelData());
                return(true);
            }

            // Destination region copy is not yet supported
            if (destinationRegion != new Rectangle(0, 0, Width, Height))
            {
                return(false);
            }

            // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy
            if (!(sourceBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height)
            {
                try
                {
                    BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion);
                    return(true);
                }
                catch (InvalidOperationException)
                {
                    return(false);
                }
            }

            //SquishFlags targetFormat = SquishFlags.ColourClusterFit;
            Format outputFormat = Format.DXT1;

            switch (format)
            {
            case SurfaceFormat.Dxt1:
                outputFormat = Format.DXT1;
                break;

            case SurfaceFormat.Dxt1SRgb:
                outputFormat = Format.DXT1;
                break;

            case SurfaceFormat.Dxt3:
                outputFormat = Format.DXT3;
                break;

            case SurfaceFormat.Dxt3SRgb:
                outputFormat = Format.DXT3;
                break;

            case SurfaceFormat.Dxt5:
                outputFormat = Format.DXT5;
                break;

            case SurfaceFormat.Dxt5SRgb:
                outputFormat = Format.DXT5;
                break;

            default:
                return(false);
            }

            // libsquish requires RGBA8888
            var colorBitmap = new PixelBitmapContent <Color>(sourceBitmap.Width, sourceBitmap.Height);

            BitmapContent.Copy(sourceBitmap, colorBitmap);

            var sourceData = colorBitmap.GetPixelData();

            /*
             * var dataSize = Squish.GetStorageRequirements(colorBitmap.Width, colorBitmap.Height, targetFormat);
             * var data = new byte[dataSize];
             * var metric = new float[] { 1.0f, 1.0f, 1.0f };
             * Squish.CompressImage(sourceData, colorBitmap.Width, colorBitmap.Height, data, targetFormat, metric);
             * SetPixelData(data);
             */

            var dxtCompressor = new Compressor();
            var inputOptions  = new InputOptions();

            if (outputFormat != Format.DXT1)
            {
                inputOptions.SetAlphaMode(AlphaMode.Premultiplied);
            }
            else
            {
                inputOptions.SetAlphaMode(AlphaMode.None);
            }
            inputOptions.SetTextureLayout(TextureType.Texture2D, colorBitmap.Width, colorBitmap.Height, 1);

            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(sourceData);
            var dataHandle = GCHandle.Alloc(sourceData, GCHandleType.Pinned);

            try
            {
                var dataPtr = dataHandle.AddrOfPinnedObject();

                inputOptions.SetMipmapData(dataPtr, colorBitmap.Width, colorBitmap.Height, 1, 0, 0);
                inputOptions.SetMipmapGeneration(false);
                inputOptions.SetGamma(1.0f, 1.0f);

                var outputOptions = new OutputOptions();
                outputOptions.SetOutputHeader(false);

                var handler = new DxtDataHandler(this);
                outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

                var compressionOptions = new CompressionOptions();
                compressionOptions.SetFormat(outputFormat);
                compressionOptions.SetQuality(Quality.Normal);

                dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);
            }
            finally
            {
                dataHandle.Free();
            }
            return(true);
        }
Esempio n. 11
0
        // Rasterizes a single character glyph.
        private Glyph ImportGlyph(char character, Face face)
        {
            uint glyphIndex = face.GetCharIndex(character);

            face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
            face.Glyph.RenderGlyph(RenderMode.Normal);

            // Render the character.
            BitmapContent glyphBitmap = null;

            if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0)
            {
                glyphBitmap = new PixelBitmapContent <byte>(face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows);
                byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows];
                //if the character bitmap has 1bpp we have to expand the buffer data to get the 8bpp pixel data
                //each byte in bitmap.bufferdata contains the value of to 8 pixels in the row
                //if bitmap is of width 10, each row has 2 bytes with 10 valid bits, and the last 6 bits of 2nd byte must be discarded
                if (face.Glyph.Bitmap.PixelMode == PixelMode.Mono)
                {
                    //variables needed for the expansion, amount of written data, length of the data to write
                    int written = 0, length = face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows;
                    for (int i = 0; written < length; i++)
                    {
                        //width in pixels of each row
                        int width = face.Glyph.Bitmap.Width;
                        while (width > 0)
                        {
                            //valid data in the current byte
                            int stride = MathHelper.Min(8, width);
                            //copy the valid bytes to pixeldata
                            //System.Array.Copy(ExpandByte(face.Glyph.Bitmap.BufferData[i]), 0, gpixelAlphas, written, stride);
                            ExpandByteAndCopy(face.Glyph.Bitmap.BufferData[i], stride, gpixelAlphas, written);
                            written += stride;
                            width   -= stride;
                            if (width > 0)
                            {
                                i++;
                            }
                        }
                    }
                }
                else
                {
                    Marshal.Copy(face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length);
                }
                glyphBitmap.SetPixelData(gpixelAlphas);
            }

            if (glyphBitmap == null)
            {
                var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6;
                var gVA = face.Size.Metrics.Height >> 6;

                gHA = gHA > 0 ? gHA : gVA;
                gVA = gVA > 0 ? gVA : gHA;

                glyphBitmap = new PixelBitmapContent <byte>(gHA, gVA);
            }

            // not sure about this at all
            var abc = new ABCFloat();

            abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6;
            abc.B = face.Glyph.Metrics.Width >> 6;
            abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B);

            // Construct the output Glyph object.
            return(new Glyph(character, glyphBitmap)
            {
                XOffset = -(face.Glyph.Advance.X >> 6),
                XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6,
                YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6),
                CharacterWidths = abc
            });
        }