Esempio n. 1
0
        public void Build(
            GlyphTextureBitmapGenerator glyphTextureGen,
            Typeface typeface, float fontSizeInPoints,
            TextureKind textureKind,
            GlyphTextureBuildDetail[] buildDetails)
        {
#if DEBUG
            //overall, glyph atlas generation time
            System.Diagnostics.Stopwatch dbugStopWatch = new System.Diagnostics.Stopwatch();
            dbugStopWatch.Start();
#endif
            var atlasBuilder = new SimpleBitmapAtlasBuilder();
            glyphTextureGen.CreateTextureFontFromBuildDetail(
                atlasBuilder,
                typeface,
                fontSizeInPoints,
                textureKind,
                buildDetails);

            //3. set information before write to font-info
            atlasBuilder.SpaceCompactOption = SimpleBitmapAtlasBuilder.CompactOption.ArrangeByHeight;
            atlasBuilder.SetAtlasFontInfo(typeface.Name, fontSizeInPoints);

            //4. merge all glyph in the builder into a single image
            using (MemBitmap totalGlyphsImg = atlasBuilder.BuildSingleImage(true))
            {
                if (TextureInfoFilename == null)
                {
                    //use random suffix
                    string random_suffix      = Guid.NewGuid().ToString().Substring(0, 7);
                    string textureName        = typeface.Name.ToLower() + "_" + random_suffix + ".info";
                    string output_imgFilename = textureName + ".png";

                    TextureInfoFilename = textureName;
                    OutputImgFilename   = output_imgFilename;
                }


                //5. save atlas info to disk
                using (FileStream fs = new FileStream(TextureInfoFilename, FileMode.Create))
                {
                    atlasBuilder.SaveAtlasInfo(fs);
                }

                //6. save total-glyph-image to disk
                totalGlyphsImg.SaveImage(OutputImgFilename);
            }

#if DEBUG
            dbugStopWatch.Stop();
            dbugBuildTimeMillisec = dbugStopWatch.ElapsedMilliseconds;
#endif
        }
Esempio n. 2
0
        static void FillAndSave(VertexStore vxs, string filename)
        {
            using (MemBitmap bmp = new MemBitmap(300, 300)) //approximate
                using (Tools.BorrowCurveFlattener(out var flattener))
                    using (Tools.BorrowVxs(out var v1))
                        using (Tools.BorrowAggPainter(bmp, out var painter))
                        {
                            painter.Clear(PixelFarm.Drawing.Color.White);//bg
                            painter.FillColor = PixelFarm.Drawing.Color.Black;
                            flattener.MakeVxs(vxs, v1);
                            painter.Fill(v1);

                            bmp.SaveImage(filename);
                        }
        }
Esempio n. 3
0
        static void CreateSampleMsdfTextureFont(string fontfile, float sizeInPoint, ushort startGlyphIndex, ushort endGlyphIndex, string outputFile)
        {
            //sample

            var reader = new OpenFontReader();

            Typeface typeface = null;

            using (var fs = new FileStream(fontfile, FileMode.Open))
            {
                //1. read typeface from font file
                typeface = reader.Read(fs);
            }

            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var builder = new GlyphOutlineBuilder(typeface);
            //builder.UseTrueTypeInterpreter = this.chkTrueTypeHint.Checked;
            //builder.UseVerticalHinting = this.chkVerticalHinting.Checked;
            //-------------------------------------------------------------
            RequestFont reqFont = new RequestFont(typeface.Name, sizeInPoint);

            var atlasBuilder = new SimpleBitmapAtlasBuilder();

            atlasBuilder.FontFilename = System.IO.Path.GetFileName(fontfile);
            atlasBuilder.FontKey      = reqFont.FontKey;
            //create temp folder for each glyph

            string tempFolderName = "tmp_msdf";

            if (Directory.Exists(tempFolderName))
            {
                //DANGER!
                Directory.Delete(tempFolderName, true);
            }
            Directory.CreateDirectory(tempFolderName);

            if (endGlyphIndex < 1)
            {
                endGlyphIndex = (ushort)(typeface.GlyphCount - 1);
            }


            for (ushort gindex = startGlyphIndex; gindex <= endGlyphIndex; ++gindex)
            {
                //build glyph
                builder.BuildFromGlyphIndex(gindex, sizeInPoint);

                var glyphContourBuilder = new ContourBuilder();
                //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
                var genParams = new MsdfGenParams();
                builder.ReadShapes(new GlyphContourBuilder2(glyphContourBuilder));
                //genParams.shapeScale = 1f / 64; //we scale later (as original C++ code use 1/64)
                BitmapAtlasItemSource glyphImg = MsdfImageGen.CreateMsdfImageV1(glyphContourBuilder, genParams);
                glyphImg.UniqueInt16Name = gindex;
                atlasBuilder.AddItemSource(glyphImg);

                using (Bitmap bmp = new Bitmap(glyphImg.Width, glyphImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    int[] buffer  = glyphImg.GetImageBuffer();
                    var   bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg.Width, glyphImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                    bmp.UnlockBits(bmpdata);
                    bmp.Save(tempFolderName + "//glyph_" + gindex + ".png");
                }
            }

            MemBitmap glyphImg2 = atlasBuilder.BuildSingleImage(true);

            glyphImg2.SaveImage(outputFile);


            string saveToFile = "a_info.bin";

            using (System.IO.FileStream saveFs = new FileStream(saveToFile, FileMode.Create))
            {
                atlasBuilder.SaveAtlasInfo(saveFs);
                saveFs.Flush();
                saveFs.Close();
            }

            //
            //-----------
            //test read texture info back
            var atlasBuilder2 = new SimpleBitmapAtlasBuilder();

            using (System.IO.FileStream readFromFs = new FileStream(saveToFile, FileMode.Open))
            {
                var readbackFontAtlas = atlasBuilder2.LoadAtlasInfo(readFromFs);
            }
        }
Esempio n. 4
0
        public void BuildMultiFontSize(string multiFontSizeAtlasFilename, string imgOutputFilename)
        {
            //merge to the new one
            //1. ensure same atlas width
            int atlasW      = 0;
            int j           = _atlasList.Count;
            int totalHeight = 0;

            const int interAtlasSpace = 2;

            for (int i = 0; i < j; ++i)
            {
                TempMergingAtlasInfo atlasInfo = _atlasList[i];
                SimpleBitmapAtlas    fontAtlas = atlasInfo.fontAtlasFile.AtlasList[0];
                totalHeight += fontAtlas.Height + interAtlasSpace;
                if (i == 0)
                {
                    atlasW = fontAtlas.Width;
                }
                else
                {
                    if (atlasW != fontAtlas.Width)
                    {
                        throw new NotSupportedException();
                    }
                }
            }
            //--------------------------------------------
            //in this version, the glyph offsetY is measure from bottom***
            int[] offsetFromBottoms = new int[j];
            int   offsetFromBottom  = interAtlasSpace;//start offset

            for (int i = j - 1; i >= 0; --i)
            {
                TempMergingAtlasInfo atlasInfo = _atlasList[i];
                SimpleBitmapAtlas    fontAtlas = atlasInfo.fontAtlasFile.AtlasList[0];
                offsetFromBottoms[i] = offsetFromBottom;
                offsetFromBottom    += fontAtlas.Height + interAtlasSpace;
            }
            //--------------------------------------------
            //merge all img to one
            int top = 0;

            using (MemBitmap memBitmap = new MemBitmap(atlasW, totalHeight))
            {
                AggPainter painter = AggPainter.Create(memBitmap);
                for (int i = 0; i < j; ++i)
                {
                    TempMergingAtlasInfo atlasInfo = _atlasList[i];
                    BitmapAtlasFile      atlasFile = atlasInfo.fontAtlasFile;
                    SimpleBitmapAtlas    fontAtlas = atlasInfo.fontAtlasFile.AtlasList[0];

                    atlasInfo.NewCloneLocations = SimpleBitmapAtlas.CloneLocationWithOffset(fontAtlas, 0, offsetFromBottoms[i]);
                    atlasInfo.ImgUrlDict        = fontAtlas.ImgUrlDict;

                    using (Stream fontImgStream = PixelFarm.Platforms.StorageService.Provider.ReadDataStream(atlasInfo.imgFile))
                        using (MemBitmap atlasBmp = MemBitmapExt.LoadBitmap(fontImgStream))
                        {
                            painter.DrawImage(atlasBmp, 0, top);
                            top += atlasBmp.Height + interAtlasSpace;
                        }
                }
                memBitmap.SaveImage(imgOutputFilename);
            }
            //--------------------------------------------
            //save merged font atlas
            //TODO: use 'File' provider to access system file
            using (FileStream fs = new FileStream(multiFontSizeAtlasFilename, FileMode.Create))
                using (BinaryWriter w = new BinaryWriter(fs))
                {
                    //-----------
                    //overview
                    //total img info
                    BitmapAtlasFile fontAtlasFile = new BitmapAtlasFile();
                    fontAtlasFile.StartWrite(fs);

                    //1. simple atlas count
                    fontAtlasFile.WriteOverviewMultiSizeFontInfo((ushort)j);
                    //2.
                    for (int i = 0; i < j; ++i)
                    {
                        TempMergingAtlasInfo atlasInfo = _atlasList[i];

                        RequestFont reqFont = atlasInfo.reqFont;
                        fontAtlasFile.WriteOverviewFontInfo(reqFont.Name, reqFont.GetReqKey(), reqFont.SizeInPoints);//size in points

                        fontAtlasFile.WriteTotalImageInfo(
                            (ushort)atlasW,
                            (ushort)top,
                            4,
                            atlasInfo.textureKind);
                        //

                        fontAtlasFile.WriteAtlasItems(atlasInfo.NewCloneLocations);

                        if (atlasInfo.ImgUrlDict != null)
                        {
                            fontAtlasFile.WriteImgUrlDict(atlasInfo.ImgUrlDict);
                        }
                    }
                    fontAtlasFile.EndWrite();
                }
        }
Esempio n. 5
0
        void BuildAtlas_FromInputChars()
        {
            if (!float.TryParse(txtSelectedFontSize.Text, out float fontSizeInPoints))
            {
                MessageBox.Show("err: selected font size " + txtSelectedFontSize.Text);
                return;
            }


            //1. create glyph-texture-bitmap generator
            var glyphTextureGen = new GlyphTextureBitmapGenerator();

            glyphTextureGen.SetSvgBmpBuilderFunc(SvgBuilderHelper.ParseAndRenderSvg);

            //2. generate the glyphs
            TextureKindAndDescription textureKindAndDesc = (TextureKindAndDescription)this.cmbTextureKind.SelectedItem;

            if (textureKindAndDesc.Kind == TextureKind.Msdf)
            {
                glyphTextureGen.MsdfGenVersion = textureKindAndDesc.TechniqueDetail;
            }

            var atlasBuilder = new SimpleBitmapAtlasBuilder();

            glyphTextureGen.CreateTextureFontFromInputChars(
                atlasBuilder,
                _typeface,
                fontSizeInPoints,
                textureKindAndDesc.Kind,
                GetUniqueChars()
                );

            //3. set information before write to font-info
            atlasBuilder.SpaceCompactOption = SimpleBitmapAtlasBuilder.CompactOption.ArrangeByHeight;


            //4. merge all glyph in the builder into a single image
            MemBitmap totalGlyphsImg = atlasBuilder.BuildSingleImage(true);
            string    fontTextureImg = "test_glyph_atlas.png";

            //5. save to png
            totalGlyphsImg.SaveImage(fontTextureImg);
            //-----------------------------------------------


            //let view result...
            SimpleUtils.DisposeExistingPictureBoxImage(picOutput);

            this.lblOutput.Text  = "output: " + fontTextureImg;
            this.picOutput.Image = new Bitmap(fontTextureImg);
#if DEBUG
            //save glyph image for debug
            //PixelFarm.Agg.ActualImage.SaveImgBufferToPngFile(
            //    totalGlyphsImg.GetImageBuffer(),
            //    totalGlyphsImg.Width * 4,
            //    totalGlyphsImg.Width, totalGlyphsImg.Height,
            //    "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 static void Test(string imgdir, Func <string, MemBitmap> imgLoader)
        {
            SimpleBitmapAtlasBuilder bmpAtlasBuilder = new SimpleBitmapAtlasBuilder();
            //test!
            int imgdirNameLen = imgdir.Length;

            string[] filenames = System.IO.Directory.GetFiles(imgdir, "*.png");
            ushort   index     = 0;

            Dictionary <string, ushort> imgDic = new Dictionary <string, ushort>();

            foreach (string f in filenames)
            {
                MemBitmap      itemBmp   = imgLoader(f);
                AtlasItemImage atlasItem = new AtlasItemImage(itemBmp.Width, itemBmp.Height);
                atlasItem.OriginalBounds = new PixelFarm.Drawing.RectangleF(0, 0, itemBmp.Width, itemBmp.Height);
                atlasItem.SetBitmap(itemBmp, false);
                //
                bmpAtlasBuilder.AddAtlasItemImage(index, atlasItem);
                string imgPath = f.Substring(imgdirNameLen);
                imgDic.Add(imgPath, index);
                index++;

                //------------
#if DEBUG
                if (index >= ushort.MaxValue)
                {
                    throw new NotSupportedException();
                }
#endif
                //------------
            }

            //string atlasInfoFile = "d:\\WImageTest\\test1_atlas.info";
            //string totalImgFile = "d:\\WImageTest\\test1_atlas.png";
            string atlasInfoFile = "test1_atlas.info";
            string totalImgFile  = "test1_atlas.png";
            //test, write data to disk
            AtlasItemImage totalImg = bmpAtlasBuilder.BuildSingleImage();
            bmpAtlasBuilder.ImgUrlDict = imgDic;
            bmpAtlasBuilder.SetAtlasInfo(TextureKind.Bitmap);
            bmpAtlasBuilder.SaveAtlasInfo(atlasInfoFile); //save to filename
            totalImg.Bitmap.SaveImage(totalImgFile);

            //-----
            //test, read data back
            bmpAtlasBuilder = new SimpleBitmapAtlasBuilder();
            SimpleBitmaptAtlas bitmapAtlas = bmpAtlasBuilder.LoadAtlasInfo(atlasInfoFile);
            //
            MemBitmap      totalAtlasImg = imgLoader(totalImgFile);
            AtlasItemImage atlasImg      = new AtlasItemImage(totalAtlasImg.Width, totalAtlasImg.Height);
            bitmapAtlas.TotalImg = atlasImg;

            for (int i = 0; i < index; ++i)
            {
                if (bitmapAtlas.TryGetBitmapMapData((ushort)i, out BitmapMapData bmpMapData))
                {
                    //test copy data from bitmap
                    MemBitmap itemImg = totalAtlasImg.CopyImgBuffer(bmpMapData.Left, bmpMapData.Top, bmpMapData.Width, bmpMapData.Height);
                    itemImg.SaveImage("test1_atlas_item" + i + ".png");
                }
            }

            //test,
            {
                if (bitmapAtlas.TryGetBitmapMapData(@"\chk_checked.png", out BitmapMapData bmpMapData))
                {
                    MemBitmap itemImg = totalAtlasImg.CopyImgBuffer(bmpMapData.Left, bmpMapData.Top, bmpMapData.Width, bmpMapData.Height);
                    itemImg.SaveImage("test1_atlas_item_a.png");
                }
            }
        }
Esempio n. 7
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));
                    }
        }
Esempio n. 8
0
        public static void BuildBitmapAtlas(AtlasProject atlasProj, Func <string, MemBitmap> imgLoader, bool test_extract = false)
        {
            //demonstrate how to build a bitmap atlas
            List <AtlasItemSourceFile> fileList = atlasProj.Items;
            //1. create builder
            var bmpAtlasBuilder = new SimpleBitmapAtlasBuilder();

            ushort index = 0;
            Dictionary <string, ushort> imgDic = new Dictionary <string, ushort>();

            foreach (AtlasItemSourceFile f in fileList)
            {
                if (f.Kind != AtlasItemSourceKind.Image)
                {
                    continue;
                }

                //3. load a bitmap

                BitmapAtlasItemSource atlasItem = null;
                using (MemBitmap itemBmp = imgLoader(f.AbsoluteFilename))
                {
                    //4. get information about it
                    atlasItem = new BitmapAtlasItemSource(itemBmp.Width, itemBmp.Height);
                    atlasItem.SetImageBuffer(MemBitmap.CopyImgBuffer(itemBmp));
                }

                atlasItem.UniqueInt16Name = index;
                //5. add to builder
                bmpAtlasBuilder.AddItemSource(atlasItem);

                //get relative filename
                string imgPath = "//" + f.Link;
                imgDic.Add(imgPath, index);
                index++;

                //------------
#if DEBUG
                if (index >= ushort.MaxValue)
                {
                    throw new NotSupportedException();
                }
#endif
                //------------
            }
            if (imgDic.Count == 0)
            {
                //no file
                return;
            }

            string atlasInfoFile = atlasProj.OutputFilename + ".info";
            string totalImgFile  = atlasProj.OutputFilename + ".png";

            //5. merge all small images into a bigone
            using (MemBitmap totalImg = bmpAtlasBuilder.BuildSingleImage(false))
            {
                bmpAtlasBuilder.ImgUrlDict = imgDic;
                bmpAtlasBuilder.SetAtlasInfo(TextureKind.Bitmap, 0); //font size
                                                                     //6. save atlas info and total-img (.png file)
                bmpAtlasBuilder.SaveAtlasInfo(atlasInfoFile);
                totalImg.SaveImage(totalImgFile);
            }


            //----------------------
            //7. create an atlas file in a source file version, user can embed the source to file
            //easy, just read .info and .png then convert to binary buffer

            BuildAtlasInEmbededSourceVersion(atlasProj, atlasInfoFile, totalImgFile, imgDic);

            //----------------------
            //test, read data back
            //----------------------
            if (test_extract)
            {
                bmpAtlasBuilder = new SimpleBitmapAtlasBuilder();
                SimpleBitmapAtlas bitmapAtlas = bmpAtlasBuilder.LoadAtlasInfo(atlasInfoFile)[0];
                //
                MemBitmap totalAtlasImg = imgLoader(totalImgFile);
                bitmapAtlas.SetMainBitmap(imgLoader(totalImgFile), true);

                //-----
                for (int i = 0; i < index; ++i)
                {
                    if (bitmapAtlas.TryGetItem((ushort)i, out AtlasItem bmpMapData))
                    {
                        //test copy data from bitmap
                        MemBitmap itemImg = totalAtlasImg.CopyImgBuffer(bmpMapData.Left, bmpMapData.Top, bmpMapData.Width, bmpMapData.Height);
                        itemImg.SaveImage("test1_atlas_item" + i + ".png");
                    }
                }
                //test,
                {
                    if (bitmapAtlas.TryGetItem(@"\chk_checked.png", out AtlasItem bmpMapData))
                    {
                        MemBitmap itemImg = totalAtlasImg.CopyImgBuffer(bmpMapData.Left, bmpMapData.Top, bmpMapData.Width, bmpMapData.Height);
                        itemImg.SaveImage("test1_atlas_item_a.png");
                    }
                }
            }
        }