Пример #1
0
 public unsafe void SetData(ByteColor[] data, Rectangle? rect)
 {
     Threading.EnsureUIThread (delegate {
         fixed(ByteColor *ptr = data) {
             SetData ((IntPtr)ptr, rect);
         }
     });
 }
Пример #2
0
        static ByteColor[] GetData(byte[][] scanlines, int width, int height, ColorType colorType, int bitsPerSample, ByteColor[] palette)
        {
            var bytesPerPixel    = BytesPerPixel(colorType, bitsPerSample);
            var bytesPerSample   = bitsPerSample / 8;
            var bytesPerScanline = (bytesPerPixel * width) + 1;
            var data             = new ByteColor[width * height];

            byte[] previousScanline = new byte[bytesPerScanline];
            for (int y = 0; y < height; y++)
            {
                var        scanline   = scanlines[y];
                FilterType filterType = (FilterType)scanline[0];
                byte[]     defilteredScanline;
                switch (filterType)
                {
                case FilterType.None:
                    defilteredScanline = new byte[scanline.Length];
                    Array.Copy(scanline, defilteredScanline, scanline.Length);
                    break;

                case FilterType.Sub:
                    defilteredScanline = SubDefilter(scanline, bytesPerPixel);
                    break;

                case FilterType.Up:
                    defilteredScanline = UpDefilter(scanline, previousScanline);
                    break;

                case FilterType.Average:
                    defilteredScanline = AverageDefilter(scanline, previousScanline, bytesPerPixel);
                    break;

                case FilterType.Paeth:
                    defilteredScanline = PaethDefilter(scanline, previousScanline, bytesPerPixel);
                    break;

                default:
                    throw new Exception("Unknown filter type.");
                }

                previousScanline = defilteredScanline;
                ConvertColors(defilteredScanline, y, width, colorType, bytesPerPixel, bytesPerSample, data, palette);
            }
            return(data);
        }
Пример #3
0
        public static Texture LoadPng(Stream stream)
        {
            List<byte> idat = new List<byte> ();
            byte bitDepth = 0;
            ColorType colorType = ColorType.Grayscale;
            ByteColor[] palette = null;
            int width = 0, height = 0;
            using (var reader = new BinaryReader (stream)) {
                if (reader.ReadUInt64 () != PNG_SIGNATURE) {
                    throw new Exception ("Not a PNG file");
                }
                string chunktype = "";
                byte[] typeBuf = new byte[4];
                while (chunktype != "IEND") {
                    var length = reader.ReadInt32BE ();
                    reader.Read (typeBuf, 0, 4);
                    chunktype = Encoding.ASCII.GetString (typeBuf);
                    switch (chunktype) {
                    case "IHDR":
                        width = reader.ReadInt32BE ();
                        height = reader.ReadInt32BE ();
                        bitDepth = reader.ReadByte ();
                        colorType = (ColorType)reader.ReadByte ();
                        if (reader.ReadByte () != 0) {
                            throw new Exception (); //Compression method
                        }
                        if (reader.ReadByte () != 0) {
                            throw new Exception (); //Filter method
                        }
                        if (reader.ReadByte () != 0) {
                            throw new NotImplementedException (); //Interlacing
                        }
                        break;
                    case "PLTE":
                        if (length % 3 != 0)
                            throw new Exception (); //Invalid Palette
                        int count = length / 3;
                        palette = new ByteColor[length / 3];
                        for (int i = 0; i < count; i++) {
                            palette [i] = new ByteColor (
                                reader.ReadByte (),
                                reader.ReadByte (),
                                reader.ReadByte (),
                                255);
                        }
                        break;
                    case "tRNS":
                        if (colorType == ColorType.Palette) {
                            for (int i = 0; i < length; i++) {
                                palette [i].A = reader.ReadByte ();
                            }
                        } else {
                            throw new NotImplementedException (); //Are the others BigEndian? Investigate
                        }
                        break;
                    case "IDAT":
                        idat.AddRange (reader.ReadBytes (length));
                        break;
                    default:
                        reader.BaseStream.Seek (length, SeekOrigin.Current);
                        break;
                    }
                    reader.BaseStream.Seek (4, SeekOrigin.Current); //Skip CRC
                }
            }
            byte[] decompressedBytes = null;
            using (var compressedStream = new MemoryStream (idat.ToArray (), 2, idat.Count - 6)) { //skip zlib header
                using (var decompressedStream = new MemoryStream ()) {
                    try {
                        using (var deflateStream = new DeflateStream (compressedStream, CompressionMode.Decompress)) {
                            deflateStream.CopyTo (decompressedStream);
                        }
                        decompressedBytes = decompressedStream.ToArray ();
                    } catch (Exception exception) {
                        throw new Exception ("An error occurred during DEFLATE decompression.", exception);
                    }
                }

            }
            var scanlines = GetScanlines (decompressedBytes, bitDepth, colorType, width);
            var colors = GetData (scanlines, width, height, colorType, bitDepth, palette);
            var texture = new Texture (width, height);
            texture.SetData (colors, null);
            return texture;
        }
Пример #4
0
        static ByteColor[] GetData(byte[][] scanlines, int width, int height, ColorType colorType, int bitsPerSample, ByteColor[] palette)
        {
            var bytesPerPixel = BytesPerPixel(colorType, bitsPerSample);
            var bytesPerSample = bitsPerSample / 8;
            var bytesPerScanline = (bytesPerPixel * width) + 1;
            var data = new ByteColor[width * height];
            byte[] previousScanline = new byte[bytesPerScanline];
            for (int y = 0; y < height; y++)
            {
                var scanline = scanlines[y];
                FilterType filterType = (FilterType)scanline[0];
                byte[] defilteredScanline;
                switch (filterType)
                {
                case FilterType.None:
                    defilteredScanline = new byte[scanline.Length];
                    Array.Copy (scanline, defilteredScanline, scanline.Length);
                    break;

                case FilterType.Sub:
                    defilteredScanline = SubDefilter(scanline, bytesPerPixel);
                    break;

                case FilterType.Up:
                    defilteredScanline = UpDefilter(scanline, previousScanline);
                    break;

                case FilterType.Average:
                    defilteredScanline = AverageDefilter(scanline, previousScanline, bytesPerPixel);
                    break;

                case FilterType.Paeth:
                    defilteredScanline = PaethDefilter(scanline, previousScanline, bytesPerPixel);
                    break;

                default:
                    throw new Exception("Unknown filter type.");
                }

                previousScanline = defilteredScanline;
                ConvertColors (defilteredScanline, y, width, colorType, bytesPerPixel, bytesPerSample, data, palette);
            }
            return data;
        }
Пример #5
0
        static void ConvertColors(byte[] defilteredScanline, int y, int width, ColorType colorType, int bytesPerPixel, int bytesPerSample, ByteColor[] data, ByteColor[] palette)
        {
            switch (colorType)
            {
            case ColorType.Grayscale:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    byte intensity = defilteredScanline[offset];

                    data[(y * width) + x] = new ByteColor(intensity, intensity, intensity, 255);
                }

                break;

            case ColorType.GrayscaleAlpha:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    byte intensity = defilteredScanline[offset];
                    byte alpha = defilteredScanline[offset + bytesPerSample];

                    data[(y * width) + x] = new ByteColor(intensity, intensity, intensity, alpha);
                }

                break;

            case ColorType.Palette:

                for (int x = 0; x < width; x++)
                {
                    var pixelColor = palette[defilteredScanline[x + 1]];

                    data[(y * width) + x] = pixelColor;
                }

                break;

            case ColorType.Rgb:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    int red = defilteredScanline[offset];
                    int green = defilteredScanline[offset + bytesPerSample];
                    int blue = defilteredScanline[offset + 2 * bytesPerSample];

                    data[(y * width) + x] = new ByteColor((byte)red, (byte)green, (byte)blue, 255);
                }

                break;

            case ColorType.Rgba:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    int red = defilteredScanline[offset];
                    int green = defilteredScanline[offset + bytesPerSample];
                    int blue = defilteredScanline[offset + 2 * bytesPerSample];
                    int alpha = defilteredScanline[offset + 3 * bytesPerSample];

                    data[(y * width) + x] = new ByteColor((byte)red, (byte)green, (byte)blue, (byte)alpha);
                }

                break;

            default:
                break;
            }
        }
Пример #6
0
        unsafe void AddCharacter(uint codepoint)
        {
            if (codepoint == (uint)'\t')
            {
                var spaceGlyph = GetGlyph((uint)' ');
                glyphs.Add(codepoint, new GlyphInfo(spaceGlyph.AdvanceX * 4, spaceGlyph.AdvanceY, spaceGlyph.CharIndex, spaceGlyph.Face, spaceGlyph.Kerning));
                return;
            }
            IntPtr face;
            uint   index;

            if (!GetFace(codepoint, out index, out face))
            {
                if (codepoint == (uint)'?')
                {
                    throw new Exception("Font does not have required ASCII characters");
                }
                var qmGlyph = GetGlyph((uint)'?');
                glyphs.Add(codepoint, qmGlyph);
                return;
            }
            FT.FT_Load_Glyph(face, index, FT.FT_LOAD_DEFAULT | FT.FT_LOAD_TARGET_NORMAL);
            var faceRec = Marshal.PtrToStructure <FT.FaceRec> (face);
            //not exactly the right spot, but this is the only place we access the members of the face
            bool kerning = (((long)faceRec.face_flags) & FT.FT_FACE_FLAG_KERNING) == FT.FT_FACE_FLAG_KERNING;

            FT.FT_Render_Glyph(faceRec.glyph, FT.FT_RENDER_MODE_NORMAL);
            var glyphRec = Marshal.PtrToStructure <FT.GlyphSlotRec> (faceRec.glyph);

            if (glyphRec.bitmap.width == 0 || glyphRec.bitmap.rows == 0)
            {
                glyphs.Add(codepoint,
                           new GlyphInfo(
                               (int)Math.Ceiling(FTMath.From26Dot6(glyphRec.advance.x)),
                               (int)Math.Ceiling(FTMath.From26Dot6(glyphRec.advance.y)),
                               index,
                               face,
                               kerning
                               )
                           );
            }
            else
            {
                var colors = new ByteColor[glyphRec.bitmap.width * glyphRec.bitmap.rows];
                if (glyphRec.bitmap.pixel_mode == 2)
                {
                    byte *data = (byte *)glyphRec.bitmap.buffer;
                    for (int i = 0; i < glyphRec.bitmap.width * glyphRec.bitmap.rows; i++)
                    {
                        //TODO: 4 bytes used for 1 byte of alpha data? investigate compression with GL_RED and shader.
                        colors [i] = new ByteColor(255, 255, 255, data [i]);
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }
                if (currentX + glyphRec.bitmap.width > PAGE_SIZE)
                {
                    currentX  = 0;
                    currentY += lineMax;
                    lineMax   = 0;
                }
                if (currentY + glyphRec.bitmap.rows > PAGE_SIZE)
                {
                    currentX = 0;
                    currentY = 0;
                    lineMax  = 0;
                    pages.Add(new Texture(PAGE_SIZE, PAGE_SIZE));
                    //TODO: new font page! should probably log this
                }
                lineMax = (int)Math.Max(lineMax, glyphRec.bitmap.rows);
                var rect = new Rectangle(currentX, currentY, glyphRec.bitmap.width, glyphRec.bitmap.rows);
                var tex  = pages [pages.Count - 1];
                tex.SetData(colors, rect);
                currentX += glyphRec.bitmap.width;
                glyphs.Add(codepoint,
                           new GlyphInfo(
                               tex,
                               rect,
                               (int)Math.Ceiling(FTMath.From26Dot6(glyphRec.advance.x)),
                               (int)Math.Ceiling(FTMath.From26Dot6(glyphRec.advance.y)),
                               (int)Math.Ceiling(FTMath.From26Dot6(glyphRec.metrics.horiAdvance)),
                               glyphRec.bitmap_left,
                               glyphRec.bitmap_top,
                               index,
                               face,
                               kerning
                               )
                           );
            }
        }
Пример #7
0
        public static Texture LoadPng(Stream stream)
        {
            List <byte> idat      = new List <byte> ();
            byte        bitDepth  = 0;
            ColorType   colorType = ColorType.Grayscale;

            ByteColor[] palette = null;
            int         width = 0, height = 0;

            using (var reader = new BinaryReader(stream)) {
                if (reader.ReadUInt64() != PNG_SIGNATURE)
                {
                    throw new Exception("Not a PNG file");
                }
                string chunktype = "";
                byte[] typeBuf   = new byte[4];
                while (chunktype != "IEND")
                {
                    var length = reader.ReadInt32BE();
                    reader.Read(typeBuf, 0, 4);
                    chunktype = Encoding.ASCII.GetString(typeBuf);
                    switch (chunktype)
                    {
                    case "IHDR":
                        width     = reader.ReadInt32BE();
                        height    = reader.ReadInt32BE();
                        bitDepth  = reader.ReadByte();
                        colorType = (ColorType)reader.ReadByte();
                        if (reader.ReadByte() != 0)
                        {
                            throw new Exception();                              //Compression method
                        }
                        if (reader.ReadByte() != 0)
                        {
                            throw new Exception();                              //Filter method
                        }
                        if (reader.ReadByte() != 0)
                        {
                            throw new NotImplementedException();                              //Interlacing
                        }
                        break;

                    case "PLTE":
                        if (length % 3 != 0)
                        {
                            throw new Exception();                              //Invalid Palette
                        }
                        int count = length / 3;
                        palette = new ByteColor[length / 3];
                        for (int i = 0; i < count; i++)
                        {
                            palette [i] = new ByteColor(
                                reader.ReadByte(),
                                reader.ReadByte(),
                                reader.ReadByte(),
                                255);
                        }
                        break;

                    case "tRNS":
                        if (colorType == ColorType.Palette)
                        {
                            for (int i = 0; i < length; i++)
                            {
                                palette [i].A = reader.ReadByte();
                            }
                        }
                        else
                        {
                            throw new NotImplementedException();                              //Are the others BigEndian? Investigate
                        }
                        break;

                    case "IDAT":
                        idat.AddRange(reader.ReadBytes(length));
                        break;

                    default:
                        reader.BaseStream.Seek(length, SeekOrigin.Current);
                        break;
                    }
                    reader.BaseStream.Seek(4, SeekOrigin.Current);                      //Skip CRC
                }
            }
            byte[] decompressedBytes = null;
            using (var compressedStream = new MemoryStream(idat.ToArray(), 2, idat.Count - 6)) {               //skip zlib header
                using (var decompressedStream = new MemoryStream()) {
                    try {
                        using (var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress)) {
                            deflateStream.CopyTo(decompressedStream);
                        }
                        decompressedBytes = decompressedStream.ToArray();
                    } catch (Exception exception) {
                        throw new Exception("An error occurred during DEFLATE decompression.", exception);
                    }
                }
            }
            var scanlines = GetScanlines(decompressedBytes, bitDepth, colorType, width);
            var colors    = GetData(scanlines, width, height, colorType, bitDepth, palette);
            var texture   = new Texture(width, height);

            texture.SetData(colors, null);
            return(texture);
        }
Пример #8
0
        static void ConvertColors(byte[] defilteredScanline, int y, int width, ColorType colorType, int bytesPerPixel, int bytesPerSample, ByteColor[] data, ByteColor[] palette)
        {
            switch (colorType)
            {
            case ColorType.Grayscale:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    byte intensity = defilteredScanline[offset];

                    data[(y * width) + x] = new ByteColor(intensity, intensity, intensity, 255);
                }

                break;

            case ColorType.GrayscaleAlpha:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    byte intensity = defilteredScanline[offset];
                    byte alpha     = defilteredScanline[offset + bytesPerSample];

                    data[(y * width) + x] = new ByteColor(intensity, intensity, intensity, alpha);
                }

                break;

            case ColorType.Palette:

                for (int x = 0; x < width; x++)
                {
                    var pixelColor = palette[defilteredScanline[x + 1]];

                    data[(y * width) + x] = pixelColor;
                }

                break;

            case ColorType.Rgb:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    int red   = defilteredScanline[offset];
                    int green = defilteredScanline[offset + bytesPerSample];
                    int blue  = defilteredScanline[offset + 2 * bytesPerSample];

                    data[(y * width) + x] = new ByteColor((byte)red, (byte)green, (byte)blue, 255);
                }

                break;

            case ColorType.Rgba:

                for (int x = 0; x < width; x++)
                {
                    int offset = 1 + (x * bytesPerPixel);

                    int red   = defilteredScanline[offset];
                    int green = defilteredScanline[offset + bytesPerSample];
                    int blue  = defilteredScanline[offset + 2 * bytesPerSample];
                    int alpha = defilteredScanline[offset + 3 * bytesPerSample];

                    data[(y * width) + x] = new ByteColor((byte)red, (byte)green, (byte)blue, (byte)alpha);
                }

                break;

            default:
                break;
            }
        }