Пример #1
0
        public override void Init()
        {
            //steps : detail ...
            //1. create a text service (or get it from a singleton class)

            _textServices = new LayoutFarm.OpenFontTextService();

            //2. create manager
            _bmpFontMx = new BitmapFontManager <MemBitmap>(
                TextureKind.StencilLcdEffect,
                _textServices,
                atlas =>
            {
                GlyphImage totalGlyphImg = atlas.TotalGlyph;
                return(MemBitmap.CreateFromCopy(totalGlyphImg.Width, totalGlyphImg.Height, totalGlyphImg.GetImageBuffer()));
            }
                );


            //3.
            _font      = new RequestFont("tahoma", 10);
            _fontAtlas = _bmpFontMx.GetFontAtlas(_font, out _fontBmp);


            //----------
        }
Пример #2
0
        public FontAtlasTextPrinter(AggPainter painter)
        {
            StartDrawOnLeftTop = true;
            _painter           = painter;

            this.PositionTechnique = PositionTechnique.OpenFont;

            _textServices = new LayoutFarm.OpenFontTextService();
            //2. create manager
            _bmpFontMx = new BitmapFontManager <MemBitmap>(
                TextureKind.StencilLcdEffect,
                _textServices,
                atlas =>
            {
                GlyphImage totalGlyphImg = atlas.TotalGlyph;
                return(MemBitmap.CreateFromCopy(totalGlyphImg.Width, totalGlyphImg.Height, totalGlyphImg.GetImageBuffer()));
            }
                );


            //3.

            ChangeFont(new RequestFont("tahoma", 10));
            SetupMaskPixelBlender(painter.Width, painter.Height);
        }
Пример #3
0
        public FontAtlasTextPrinter(AggPainter painter)
        {
            StartDrawOnLeftTop = true;
            _painter           = painter;

            this.PositionTechnique = PositionTechnique.OpenFont;
            _textServices          = new LayoutFarm.OpenFontTextService();

            //2.
            _bmpFontMx = new BitmapFontManager <MemBitmap>(
                _textServices,
                atlas =>
            {
                GlyphImage totalGlyphImg = atlas.TotalGlyph;
                if (atlas.UseSharedGlyphImage)
                {
                    if (!_sharedGlyphImgs.TryGetValue(totalGlyphImg, out MemBitmap found))
                    {
                        found = MemBitmap.CreateFromCopy(totalGlyphImg.Width, totalGlyphImg.Height, totalGlyphImg.GetImageBuffer());
                        _sharedGlyphImgs.Add(totalGlyphImg, found);
                    }
                    return(found);
                }
                else
                {
                    return(MemBitmap.CreateFromCopy(totalGlyphImg.Width, totalGlyphImg.Height, totalGlyphImg.GetImageBuffer()));
                }
            }
                );

            //3.
            ChangeFont(painter.CurrentFont);
            SetupMaskPixelBlender(painter.Width, painter.Height);
        }
Пример #4
0
        protected override void OnReadyForInitGLShaderProgram()
        {
            //1. create color bmp
            _colorBmp = new MemBitmap(100, 100);
            using (Tools.BorrowAggPainter(_colorBmp, out var painter))
            {
                painter.Clear(Color.White);
                painter.FillRect(2, 2, 80, 80, Color.Red);
            }
            //2. create mask bmp

            using (Tools.BorrowEllipse(out var ellipse))
                using (Tools.BorrowVxs(out var v1, out var v2))
                {
                    var msdf = new Msdfgen.MsdfGen3();

                    v1.AddMoveTo(0, 0);
                    v1.AddLineTo(20, 0);
                    v1.AddLineTo(10, 15);
                    v1.AddCloseFigure();

                    v1.ScaleToNewVxs(1, -1, v2); //flipY

                    //msdf.MsdfGenParams = new Msdfgen.MsdfGenParams() { UseCustomImageSize = true, CustomWidth = 64, CustomHeight = 64 };
                    BitmapAtlasItemSource itemSrc = msdf.GenerateMsdfTexture(v2);
                    _msdfMaskBmp = MemBitmap.CreateFromCopy(itemSrc.Width, itemSrc.Height, itemSrc.Source);
#if DEBUG
                    //_msdfMaskBmp.SaveImage("mask_msdf.png");
#endif
                }
            _colorGLBmp    = new GLBitmap(_colorBmp);
            _msdfMaskGLBmp = new GLBitmap(_msdfMaskBmp);
        }
Пример #5
0
 public MySimpleGLBitmapFontManager(Typography.Text.OpenFontTextService textServices)
     : base(textServices)
 {
     SetLoadNewBmpDel(atlas =>
     {
         MemBitmap mainBmp = atlas.MainBitmap;
         if (atlas.UseSharedImage)
         {
             if (!_sharedGlyphImgs.TryGetValue(mainBmp, out GLBitmap found))
             {
                 found = new GLBitmap(MemBitmap.CreateFromCopy(mainBmp), true);
                 //set true=> glbmp is the original owner of the membmp, when glbmp is disposed => the membmp is disposed too
                 found.IsYFlipped = false;
                 _sharedGlyphImgs.Add(mainBmp, found);
             }
             return(found);
         }
         else
         {
             //create new one
             //load to glbmp
             GLBitmap bmp = new GLBitmap(MemBitmap.CreateFromCopy(mainBmp), true);
             //set true=> glbmp is the original owner of the membmp, when glbmp is disposed => the membmp is disposed too
             bmp.IsYFlipped = false;
             return(bmp);
         }
     });
 }
Пример #6
0
        public override MemBitmap ScaleImage(MemBitmap bitmap, float x_scale, float y_scale)
        {
            //scale
            using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(bitmap.Width, bitmap.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
            {
                var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                           System.Drawing.Imaging.ImageLockMode.WriteOnly,
                                           System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                unsafe
                {
                    byte *ptr = (byte *)MemBitmap.GetBufferPtr(bitmap).Ptr;
                    PixelFarm.Drawing.Internal.MemMx.memcpy((byte *)bmpdata.Scan0, ptr, bmpdata.Stride * bmp.Height);
                }
                bmp.UnlockBits(bmpdata);

                //
                int new_w = (int)Math.Round(bitmap.Width * x_scale);
                int new_h = (int)Math.Round(bitmap.Height * y_scale);
                if (new_w < 64 && new_h < 64)
                {
                    using (System.Drawing.Bitmap scaledBmp = (System.Drawing.Bitmap)bmp.GetThumbnailImage(new_w, new_h, null, IntPtr.Zero))
                    {
#if DEBUG
                        //scaledBmp.Save("thumb01.png");
#endif
                        //copy
                        var bmpdata2 = scaledBmp.LockBits(new System.Drawing.Rectangle(0, 0, new_w, new_h),
                                                          System.Drawing.Imaging.ImageLockMode.ReadOnly,//***read
                                                          System.Drawing.Imaging.PixelFormat.Format32bppArgb);

                        MemBitmap newMemBitmap = MemBitmap.CreateFromCopy(new_w, new_h, new_w * new_h * 4, bmpdata2.Scan0);
                        scaledBmp.UnlockBits(bmpdata2);
#if DEBUG
                        //newMemBitmap.SaveImage("thumb01_1.png");
#endif

                        return(newMemBitmap);
                    }
                }
                else
                {
                    using (System.Drawing.Bitmap scaledBmp = new System.Drawing.Bitmap(bmp, new_w, new_h))
                    {
                        //copy
                        var bmpdata2 = scaledBmp.LockBits(new System.Drawing.Rectangle(0, 0, new_w, new_h),
                                                          System.Drawing.Imaging.ImageLockMode.ReadOnly, //***read
                                                          System.Drawing.Imaging.PixelFormat.Format32bppArgb);

                        MemBitmap newMemBitmap = MemBitmap.CreateFromCopy(new_w, new_h, new_w * new_h * 4, bmpdata2.Scan0);
                        scaledBmp.UnlockBits(bmpdata2);
                        return(newMemBitmap);
                    }
                }
            }
        }
Пример #7
0
            public TextureRenderVx CreateRenderVx(VertexStore vxs)
            {
#if DEBUG
                //_msdfGen.dbugWriteMsdfTexture = true;
#endif
                CpuBlit.BitmapAtlas.BitmapAtlasItemSource item = _msdfGen.GenerateMsdfTexture(vxs);
                var itemSrc = new CpuBlit.BitmapAtlas.AtlasItemSource <MemBitmap>(item.Left, item.Top, item.Width, item.Height);
                itemSrc.TextureXOffset = item.TextureXOffset;
                itemSrc.TextureYOffset = item.TextureYOffset;
                itemSrc.Source         = MemBitmap.CreateFromCopy(item.Width, item.Height, item.Source);
                return(new TextureRenderVx(itemSrc));
            }
Пример #8
0
        private void button1_Click_1(object sender, EventArgs e)
        {
            PixelFarm.CpuBlit.MemBitmapExtensions.DefaultMemBitmapIO = new PixelFarm.Drawing.WinGdi.GdiBitmapIO();


            var storageProvider = new LocalFileStorageProvider("", true);

            PixelFarm.Platforms.StorageService.RegisterProvider(storageProvider);


            var bmpFontMx = new BitmapFontManager <MemBitmap>(
                _textServices,
                atlas =>
            {
                GlyphImage totalGlyphImg = atlas.TotalGlyph;
                return(MemBitmap.CreateFromCopy(totalGlyphImg.Width, totalGlyphImg.Height, totalGlyphImg.GetImageBuffer()));
            }
                );

            string multiSizeFontAtlasFilename = "tahoma_set1.multisize_fontAtlas";
            string totalImgAtlasFilename      = "tahoma_set1.multisize_fontAtlas.png";
            //in this version, mutlsize font texture must use the same typeface
            {
                MultiSizeFontAtlasBuilder multiSizeFontAtlasBuilder = new MultiSizeFontAtlasBuilder();
                {
                    bmpFontMx.TextureKindForNewFont = PixelFarm.Drawing.BitmapAtlas.TextureKind.StencilLcdEffect;
                    AddExistingOrCreateNewSimpleFontAtlas(multiSizeFontAtlasBuilder, new RequestFont("tahoma", 10), bmpFontMx);
                    AddExistingOrCreateNewSimpleFontAtlas(multiSizeFontAtlasBuilder, new RequestFont("tahoma", 11), bmpFontMx);
                    AddExistingOrCreateNewSimpleFontAtlas(multiSizeFontAtlasBuilder, new RequestFont("tahoma", 12), bmpFontMx);
                    AddExistingOrCreateNewSimpleFontAtlas(multiSizeFontAtlasBuilder, new RequestFont("tahoma", 13), bmpFontMx);
                    AddExistingOrCreateNewSimpleFontAtlas(multiSizeFontAtlasBuilder, new RequestFont("tahoma", 14), bmpFontMx);

                    bmpFontMx.TextureKindForNewFont = PixelFarm.Drawing.BitmapAtlas.TextureKind.Msdf;
                    AddExistingOrCreateNewSimpleFontAtlas(multiSizeFontAtlasBuilder, new RequestFont("tahoma", 24), bmpFontMx);
                }

                //-------
                multiSizeFontAtlasBuilder.BuildMultiFontSize(multiSizeFontAtlasFilename, totalImgAtlasFilename);
            }
            {
                //test load the font altas back
                FontAtlasFile atlasFile = new FontAtlasFile();
                using (FileStream fs = new FileStream(multiSizeFontAtlasFilename, FileMode.Open))
                {
                    atlasFile.Read(fs);
                }
            }
        }
Пример #9
0
        void RenderWithMsdfImg(Typeface typeface, char testChar, float sizeInPoint)
        {
            _painter.FillColor = PixelFarm.Drawing.Color.Black;
            //p.UseSubPixelRendering = chkLcdTechnique.Checked;
            _painter.Clear(PixelFarm.Drawing.Color.White);
            //----------------------------------------------------
            var builder = new GlyphPathBuilder(typeface);

            builder.SetHintTechnique(_glyphRenderOptions.HintTechnique);

            //----------------------------------------------------
            builder.Build(testChar, sizeInPoint);
            //----------------------------------------------------
            var glyphToContour = new GlyphContourBuilder();
            var msdfGenPars    = new MsdfGenParams();

            builder.ReadShapes(glyphToContour);
            //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
            MsdfGenParams genParams = new MsdfGenParams();
            GlyphImage    glyphImg  = MsdfGlyphGen.CreateMsdfImage(glyphToContour, genParams);

            MemBitmap actualImg = MemBitmap.CreateFromCopy(glyphImg.Width, glyphImg.Height, glyphImg.GetImageBuffer());

            _painter.DrawImage(actualImg, 0, 0);

            //using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
            //{
            //    var bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
            //    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
            //    bmp.UnlockBits(bmpdata);
            //    bmp.Save("d:\\WImageTest\\a001_xn2_" + n + ".png");
            //}

            if (_contourAnalysisOpts.ShowGrid)
            {
                //render grid
                RenderGrids(800, 600, _gridSize, _painter);
            }

            //6. use this util to copy image from Agg actual image to System.Drawing.Bitmap
            PixelFarm.CpuBlit.Imaging.BitmapHelper.CopyToGdiPlusBitmapSameSize(_destImg, _winBmp);
            //---------------
            //7. just render our bitmap
            _g.Clear(Color.White);
            _g.DrawImage(_winBmp, new Point(30, 20));
        }
Пример #10
0
        public override void Init()
        {
            //steps : detail ...
            //1. create a text service (or get it from a singleton class)

            _textServices = new OpenFontTextService();
            _txtClient    = _textServices.CreateNewServiceClient();
            //2. create manager
            _bmpFontMx = new BitmapFontManager <MemBitmap>(
                _textServices,
                atlas => MemBitmap.CreateFromCopy(atlas.MainBitmap)
                );

            //3.
            _font      = new RequestFont("tahoma", 16);
            _fontAtlas = _bmpFontMx.GetFontAtlas(_textServices.ResolveFont(_font), _font.StartCodePoint, _font.EndCodePoint, out _fontBmp);
        }
Пример #11
0
        private void cmdTestFontAtlas_Click(object sender, EventArgs e)
        {
            //read string from txtSampleChars
            //please make sure all are unique. (TODO: check it)
            //then create a font atlas from the sample chars

            char[] sampleChars = txtSampleChars.Text.ToCharArray();
            if (sampleChars.Length == 0)
            {
                return;
            }
            //

            GlyphImage             totalGlyphsImg = null;
            SimpleFontAtlasBuilder atlasBuilder   = null;
            var glyphTextureGen = new GlyphTextureBitmapGenerator();
            //
            Typeface typeface         = _basicOptions.Typeface;
            float    fontSizeInPoints = _basicOptions.FontSizeInPoints;

            //
            glyphTextureGen.CreateTextureFontFromInputChars(
                typeface,
                fontSizeInPoints,
                TextureKind.StencilLcdEffect,
                sampleChars,
                (glyphIndex, glyphImage, outputAtlasBuilder) =>
            {
                if (outputAtlasBuilder != null)
                {
                    //finish
                    atlasBuilder = outputAtlasBuilder;
                }
            }
                );

            atlasBuilder.SpaceCompactOption = SimpleFontAtlasBuilder.CompactOption.ArrangeByHeight;
            totalGlyphsImg = atlasBuilder.BuildSingleImage();
            string fontTextureImg = "d:\\WImageTest\\test_glyph_atlas.png";


            //create atlas
            SimpleFontAtlas fontAtlas = atlasBuilder.CreateSimpleFontAtlas();

            fontAtlas.TotalGlyph = totalGlyphsImg;
            //
            using (MemBitmap memBmp = MemBitmap.CreateFromCopy(totalGlyphsImg.Width, totalGlyphsImg.Height, totalGlyphsImg.GetImageBuffer()))
                using (System.Drawing.Bitmap bmp = new Bitmap(memBmp.Width, memBmp.Height))
                {
                    var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, memBmp.Width, memBmp.Height),
                                               System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    var tmpMem = MemBitmap.GetBufferPtr(memBmp);
                    unsafe
                    {
                        PixelFarm.CpuBlit.NativeMemMx.MemCopy((byte *)bmpdata.Scan0,
                                                              (byte *)tmpMem.Ptr,
                                                              tmpMem.LengthInBytes);
                    }
                    bmp.UnlockBits(bmpdata);
                    bmp.Save(fontTextureImg);
                }


#if DEBUG
            //save glyph image for debug
            //PixelFarm.Agg.ActualImage.SaveImgBufferToPngFile(
            //    totalGlyphsImg.GetImageBuffer(),
            //    totalGlyphsImg.Width * 4,
            //    totalGlyphsImg.Width, totalGlyphsImg.Height,
            //    "d:\\WImageTest\\total_" + reqFont.Name + "_" + reqFont.SizeInPoints + ".png");
            ////save image to cache
            //SaveImgBufferToFile(totalGlyphsImg, fontTextureImg);
#endif

            //cache the atlas
            //_createdAtlases.Add(fontKey, fontAtlas);
            ////
            ////calculate some commonly used values
            //fontAtlas.SetTextureScaleInfo(
            //    resolvedTypeface.CalculateScaleToPixelFromPointSize(fontAtlas.OriginalFontSizePts),
            //    resolvedTypeface.CalculateScaleToPixelFromPointSize(reqFont.SizeInPoints));
            ////TODO: review here, use scaled or unscaled values
            //fontAtlas.SetCommonFontMetricValues(
            //    resolvedTypeface.Ascender,
            //    resolvedTypeface.Descender,
            //    resolvedTypeface.LineGap,
            //    resolvedTypeface.CalculateRecommendLineSpacing());

            ///
        }
 public override Image CopyToNewMemBitmap() => MemBitmap.CreateFromCopy(_memBitmap);
Пример #13
0
        public PixelFarm.CpuBlit.BitmapAtlas.BitmapAtlasItemSource GenerateMsdfTexture(VertexStore vxs)
        {
            Shape shape = CreateShape(vxs, out EdgeBmpLut edgeBmpLut);

            if (MsdfGenParams == null)
            {
                MsdfGenParams = new MsdfGenParams();//use default
            }

            //---preview v1 bounds-----------
            PreviewSizeAndLocation(
                shape,
                MsdfGenParams,
                out int imgW, out int imgH,
                out Vector2 translateVec);

            _dx = translateVec.x;
            _dy = translateVec.y;
            //------------------------------------
            List <ContourCorner> corners = edgeBmpLut.Corners;

            TranslateCorners(corners, _dx, _dy);

            //[1] create lookup table (lut) bitmap that contains area/corner/shape information
            //each pixel inside it contains data that map to area/corner/shape

            //
            using (MemBitmap bmpLut = new MemBitmap(imgW, imgH))
                using (Tools.BorrowAggPainter(bmpLut, out var painter))
                    using (Tools.BorrowShapeBuilder(out var sh))
                    {
                        _msdfEdgePxBlender.ClearOverlapList();//reset
                        painter.RenderSurface.SetCustomPixelBlender(_msdfEdgePxBlender);

                        //1. clear all bg to black
                        painter.Clear(PixelFarm.Drawing.Color.Black);

                        sh.InitVxs(vxs) //...
                        .TranslateToNewVxs(_dx, _dy)
                        .Flatten();


                        //---------
                        //2. force fill the shape (this include hole(s) inside shape to)
                        //( we set threshold to 50 and do force fill)
                        painter.RenderSurface.SetGamma(_prebuiltThresholdGamma_50);
                        _msdfEdgePxBlender.FillMode = MsdfEdgePixelBlender.BlenderFillMode.Force;
                        painter.Fill(sh.CurrentSharedVxs, EdgeBmpLut.EncodeToColor(0, AreaKind.AreaInsideCoverage50));

                        painter.RenderSurface.SetGamma(_prebuiltThresholdGamma_50);//restore
#if DEBUG
                        //debug for output
                        //painter.Fill(v7, Color.Red);
                        //bmpLut.SaveImage("dbug_step0.png");
                        //int curr_step = 1;
#endif
                        //---------

                        int        cornerCount          = corners.Count;
                        List <int> cornerOfNextContours = edgeBmpLut.CornerOfNextContours;
                        int        startAt      = 0;
                        int        n            = 1;
                        int        corner_index = 1;

                        for (int cnt_index = 0; cnt_index < cornerOfNextContours.Count; ++cnt_index)
                        {
                            //contour scope
                            int next_corner_startAt = cornerOfNextContours[cnt_index];

                            //-----------
                            //AA-borders of the contour
                            painter.RenderSurface.SetGamma(_prebuiltThresholdGamma_OverlappedBorder); //this creates overlapped area

                            for (; n < next_corner_startAt; ++n)
                            {
                                //0-> 1
                                //1->2 ... n
                                FillBorders(painter, corners[n - 1], corners[n]);

#if DEBUG
                                //bmpLut.SaveImage("dbug_step" + curr_step + ".png");
                                //curr_step++;
#endif
                            }
                            {
                                //the last one
                                //close contour, n-> 0
                                FillBorders(painter, corners[next_corner_startAt - 1], corners[startAt]);
#if DEBUG
                                //bmpLut.SaveImage("dbug_step" + curr_step + ".png");
                                //curr_step++;
#endif
                            }

                            startAt = next_corner_startAt;
                            n++;
                            corner_index++;
                        }
#if DEBUG
                        //bmpLut.SaveImage("dbug_step2.png");
#endif


                        //painter.RenderSurface.SetGamma(_prebuiltThresholdGamma_100);
                        //_msdfEdgePxBlender.FillMode = MsdfEdgePixelBlender.BlenderFillMode.InnerAreaX;
                        //painter.Fill(sh.CurrentSharedVxs, EdgeBmpLut.EncodeToColor(0, AreaKind.AreaInsideCoverage100));



                        painter.RenderSurface.SetCustomPixelBlender(null);
                        painter.RenderSurface.SetGamma(null);

                        //
                        List <CornerList> overlappedList = MakeUniqueList(_msdfEdgePxBlender._overlapList);
                        edgeBmpLut.SetOverlappedList(overlappedList);

#if DEBUG
                        if (dbugWriteMsdfTexture)
                        {
                            //save for debug
                            //we save to msdf_shape_lut2.png
                            //and check it from external program
                            //but we generate msdf bitmap from msdf_shape_lut.png
                            bmpLut.SaveImage(dbug_msdf_shape_lutName);
                            var   bmp5       = MemBitmap.LoadBitmap(dbug_msdf_shape_lutName);
                            int[] lutBuffer5 = bmp5.CopyImgBuffer(bmpLut.Width, bmpLut.Height);
                            if (bmpLut.Width == 338 && bmpLut.Height == 477)
                            {
                                dbugBreak = true;
                            }
                            edgeBmpLut.SetBmpBuffer(bmpLut.Width, bmpLut.Height, lutBuffer5);
                            //generate actual sprite
                            PixelFarm.CpuBlit.BitmapAtlas.BitmapAtlasItemSource item = CreateMsdfImage(shape, MsdfGenParams, imgW, imgH, translateVec, edgeBmpLut);
                            //save msdf bitmap to file
                            using (MemBitmap memBmp = MemBitmap.CreateFromCopy(item.Width, item.Height, item.Source))
                            {
                                memBmp.SaveImage(dbug_msdf_output);
                            }

                            return(item);
                        }
#endif

                        //[B] after we have a lookup table
                        int[] lutBuffer = bmpLut.CopyImgBuffer(bmpLut.Width, bmpLut.Height);
                        edgeBmpLut.SetBmpBuffer(bmpLut.Width, bmpLut.Height, lutBuffer);

                        return(CreateMsdfImage(shape, MsdfGenParams, imgW, imgH, translateVec, edgeBmpLut));
                    }
        }
Пример #14
0
        public static MemBitmap Read(Stream strm)
        {
            Hjg.Pngcs.PngReader reader  = new Hjg.Pngcs.PngReader(strm);
            Hjg.Pngcs.ImageInfo imgInfo = reader.ImgInfo;
            Hjg.Pngcs.ImageLine iline2  = new Hjg.Pngcs.ImageLine(imgInfo, Hjg.Pngcs.ImageLine.ESampleType.BYTE);

            int imgH = imgInfo.Rows;
            int imgW = imgInfo.Cols;

            int widthPx = imgInfo.Cols;
            int stride  = widthPx * 4;

            //expand to 32 bits
            int[] buffer     = new int[(stride / 4) * imgH];
            bool  isInverted = false;

            if (isInverted)
            {
                //read each row
                //and fill the glyph image
                int startWriteAt = (imgW * (imgH - 1));
                int destIndex    = startWriteAt;
                for (int row = 0; row < imgH; row++)
                {
                    Hjg.Pngcs.ImageLine iline = reader.ReadRowByte(row);
                    byte[] scline             = iline.ScanlineB;
                    int    b_src = 0;
                    destIndex = startWriteAt;


                    if (imgInfo.BitspPixel == 32)
                    {
                        for (int mm = 0; mm < imgW; ++mm)
                        {
                            byte b = scline[b_src];
                            byte g = scline[b_src + 1];
                            byte r = scline[b_src + 2];
                            byte a = scline[b_src + 3];
                            b_src += 4;

                            buffer[destIndex] = (b << 16) | (g << 8) | (r) | (a << 24);
                            destIndex++;
                        }
                    }
                    else if (imgInfo.BitspPixel == 24)
                    {
                        for (int mm = 0; mm < imgW; ++mm)
                        {
                            byte b = scline[b_src];
                            byte g = scline[b_src + 1];
                            byte r = scline[b_src + 2];
                            b_src            += 3;
                            buffer[destIndex] = (b << 16) | (g << 8) | (r) | (255 << 24);
                            destIndex++;
                        }
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }



                    startWriteAt -= imgW;
                }
                return(MemBitmap.CreateFromCopy(imgW, imgH, buffer));
            }
            else
            {
                //read each row
                //and fill the glyph image
                int startWriteAt = 0;
                int destIndex    = startWriteAt;
                for (int row = 0; row < imgH; row++)
                {
                    Hjg.Pngcs.ImageLine iline = reader.ReadRowByte(row);
                    byte[] scline             = iline.ScanlineB;

                    int b_src = 0;
                    destIndex = startWriteAt;


                    if (imgInfo.BitspPixel == 32)
                    {
                        for (int mm = 0; mm < imgW; ++mm)
                        {
                            byte b = scline[b_src];
                            byte g = scline[b_src + 1];
                            byte r = scline[b_src + 2];
                            byte a = scline[b_src + 3];
                            b_src += 4;
                            if (a > 0)
                            {
                            }
                            //buffer[destIndex] = (b << 16) | (g << 8) | (r) | (a << 24);
                            buffer[destIndex] = -1;
                            destIndex++;
                        }
                        startWriteAt += imgW;
                    }
                    else if (imgInfo.BitspPixel == 24)
                    {
                        for (int mm = 0; mm < imgW; ++mm)
                        {
                            byte b = scline[b_src];
                            byte g = scline[b_src + 1];
                            byte r = scline[b_src + 2];
                            if (g == 0)
                            {
                            }
                            b_src            += 3;
                            buffer[destIndex] = (b << 16) | (g << 8) | (r) | (255 << 24);
                            destIndex++;
                        }
                        startWriteAt += imgW;
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                }
                return(MemBitmap.CreateFromCopy(imgW, imgH, buffer));
            }
        }