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); //---------- }
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); }
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); }
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); }
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); } }); }
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); } } } }
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)); }
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); } } }
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)); }
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); }
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);
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)); } }
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)); } }