unsafe MemBitmap GetTransformedBilinearInterpolation() { //4 points sampling //weight between four point MemBitmap destCB = new MemBitmap(_destBounds.Width, _destBounds.Height); #if DEBUG destCB._dbugNote = "GetTransformedBilinearInterpolation()"; #endif MyBitmapBlender destWriter = new MyBitmapBlender(destCB); PointF ptInPlane = new PointF(); int x1, x2, y1, y2; double dab, dbc, dcd, dda; float dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2; int rectWidth = _destBounds.Width; int rectHeight = _destBounds.Height; Vector ab_vec = _AB; Vector bc_vec = _BC; Vector cd_vec = _CD; Vector da_vec = _DA; int rectLeft = _destBounds.Left; int rectTop = _destBounds.Top; int srcW_lim = _srcW - 1; int srcH_lim = _srcH - 1; using (TempMemPtr.FromBmp(_srcBmp, out int *bufferPtr)) { BufferReader4 reader = new BufferReader4(bufferPtr, _srcBmp.Width, _srcBmp.Height); for (int y = 0; y < rectHeight; ++y) { for (int x = 0; x < rectWidth; ++x) { PointF srcPt = new PointF(x, y); srcPt.Offset(rectLeft, rectTop); if (!IsOnPlaneABCD(srcPt)) { continue; } //------------------------------------- dab = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p0, srcPt).CrossProduct(ab_vec)); dbc = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p1, srcPt).CrossProduct(bc_vec)); dcd = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p2, srcPt).CrossProduct(cd_vec)); dda = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p3, srcPt).CrossProduct(da_vec)); ptInPlane.X = (float)(_srcW * (dda / (dda + dbc))); ptInPlane.Y = (float)(_srcH * (dab / (dab + dcd))); x1 = (int)ptInPlane.X; y1 = (int)ptInPlane.Y; if (x1 >= 0 && x1 < srcW_lim && y1 >= 0 && y1 < srcH_lim) { //x2 = (x1 == srcW - 1) ? x1 : x1 + 1; //y2 = (y1 == srcH - 1) ? y1 : y1 + 1; x2 = x1 + 1; y2 = y1 + 1; dx1 = ptInPlane.X - x1; if (dx1 < 0) { dx1 = 0; } dx1 = 1f - dx1; dx2 = 1f - dx1; // // dy1 = ptInPlane.Y - y1; if (dy1 < 0) { dy1 = 0; } dy1 = 1f - dy1; dy2 = 1f - dy1; // // dx1y1 = dx1 * dy1; dx1y2 = dx1 * dy2; dx2y1 = dx2 * dy1; dx2y2 = dx2 * dy2; //use 4 points reader.SetStartPixel(x1, y1); Drawing.Color x1y1Color; Drawing.Color x2y1Color; Drawing.Color x1y2Color; Drawing.Color x2y2Color; reader.Read4(out x1y1Color, out x2y1Color, out x1y2Color, out x2y2Color); //Drawing.Color x1y1Color = srcCB.GetPixel(x1, y1); //Drawing.Color x2y1Color = srcCB.GetPixel(x2, y1); //Drawing.Color x1y2Color = srcCB.GetPixel(x1, y2); //Drawing.Color x2y2Color = srcCB.GetPixel(x2, y2); float a = (x1y1Color.A * dx1y1) + (x2y1Color.A * dx2y1) + (x1y2Color.A * dx1y2) + (x2y2Color.A * dx2y2); float b = (x1y1Color.B * dx1y1) + (x2y1Color.B * dx2y1) + (x1y2Color.B * dx1y2) + (x2y2Color.B * dx2y2); float g = (x1y1Color.G * dx1y1) + (x2y1Color.G * dx2y1) + (x1y2Color.G * dx1y2) + (x2y2Color.G * dx2y2); float r = (x1y1Color.R * dx1y1) + (x2y1Color.R * dx2y1) + (x1y2Color.R * dx1y2) + (x2y2Color.R * dx2y2); destWriter.SetPixel(x, y, new Drawing.Color((byte)a, (byte)r, (byte)g, (byte)b)); } } } return(destCB); } }
public static void Clear(this MemBitmap bmp, Color color) { Clear(MemBitmap.GetBufferPtr(bmp), color); }
static void Init(GlFwForm form) { //PART1: //1. storage io PixelFarm.Platforms.StorageService.RegisterProvider(new YourImplementation.LocalFileStorageProvider("")); //2. img-io implementation PixelFarm.CpuBlit.MemBitmapExt.DefaultMemBitmapIO = new YourImplementation.ImgCodecMemBitmapIO(); // new PixelFarm.Drawing.WinGdi.GdiBitmapIO(); //PixelFarm.CpuBlit.MemBitmapExtensions.DefaultMemBitmapIO = new PixelFarm.Drawing.WinGdi.GdiBitmapIO(); //------------------------------------------------------------------------ // //if we don't set this, it will error on read-write image //you can implement this with other lib that can read-write images var pars = new PixelFarm.Platforms.ImageIOSetupParameters(); pars.SaveToPng = (IntPtr imgBuffer, int stride, int width, int height, string filename) => { MemBitmap memBmp = new MemBitmap(width, height, imgBuffer); using (FileStream fs = new FileStream(filename, FileMode.Create)) { PixelFarm.CpuBlit.MemBitmapExt.DefaultMemBitmapIO.SaveImage(memBmp, fs, MemBitmapIO.OutputImageFormat.Png, null); } //---save with GDI+--- //using (System.Drawing.Bitmap newBmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // PixelFarm.CpuBlit.BitmapHelper.CopyToGdiPlusBitmapSameSize(imgBuffer, newBmp); // //save // newBmp.Save(filename); //} }; pars.ReadFromMemStream = (System.IO.MemoryStream ms, string kind) => { return(PixelFarm.CpuBlit.MemBitmapExt.DefaultMemBitmapIO.LoadImage(ms)); //read/guest img format //--- load img with GDI+--- ////read //using (System.Drawing.Bitmap gdiBmp = new System.Drawing.Bitmap(ms)) //{ // PixelFarm.CpuBlit.MemBitmap memBmp = new PixelFarm.CpuBlit.MemBitmap(gdiBmp.Width, gdiBmp.Height); // //#if DEBUG // // memBmp._dbugNote = "img; // //#endif // PixelFarm.CpuBlit.BitmapHelper.CopyFromGdiPlusBitmapSameSizeTo32BitsBuffer(gdiBmp, memBmp); // return memBmp; //} }; PixelFarm.Platforms.ImageIOPortal.Setup(pars); //------------------------------------------------------------------------ //3. setup text-breaker string icu_datadir = "brkitr"; //see brkitr folder, we link data from Typography project and copy to output if newer if (!System.IO.Directory.Exists(icu_datadir)) { throw new System.NotSupportedException("dic"); } Typography.TextBreak.CustomBreakerBuilder.Setup(new Typography.TextBreak.IcuSimpleTextFileDictionaryProvider() { DataDir = icu_datadir }); //--------------------------------------------------------------------------- //4. Typography TextService Typography.Text.OpenFontTextService textService = new Typography.Text.OpenFontTextService(); textService.LoadFontsFromFolder("Fonts"); Typography.Text.TextServiceClient serviceClient = textService.CreateNewServiceClient(); GlobalTextService.TextService = serviceClient; //--------------------------------------------------------------------------- //PART2: root graphics Size primScreenSize = UIPlatform.CurrentPlatform.GetPrimaryMonitorSize(); s_myRootGfx = new MyRootGraphic(primScreenSize.Width, primScreenSize.Height); s_viewroot = new GraphicsViewRoot(primScreenSize.Width, primScreenSize.Height); MyGlfwTopWindowBridge bridge1 = new MyGlfwTopWindowBridge(s_myRootGfx, s_myRootGfx.TopWinEventPortal); ((MyGlfwTopWindowBridge.GlfwEventBridge)(form.WindowEventListener)).SetWindowBridge(bridge1); var glfwWindowWrapper = new GlfwWindowWrapper(form); bridge1.BindWindowControl(glfwWindowWrapper); s_viewroot.InitRootGraphics(s_myRootGfx, s_myRootGfx.TopWinEventPortal, InnerViewportKind.GLES, glfwWindowWrapper, bridge1); //------------------------------------------------------------------------ //optional: if (s_viewroot.GetGLPainter() is GLPainter glPainter) { glPainter.SmoothingMode = SmoothingMode.AntiAlias; } }
public static CpuBlit.Imaging.TempMemPtr GetBufferPtr(MemBitmap bmp) { return(new CpuBlit.Imaging.TempMemPtr(bmp._pixelBuffer, bmp._pixelBufferInBytes)); }
/// <summary> /// swap from gles ARGB to ABGR (Gdi) /// </summary> /// <param name="src"></param> public static void SwapArgbToAbgr(this MemBitmap src) { //TODO: }
/// <summary> /// we STORE membitmap inside this rgn, /// </summary> /// <param name="bmp"></param> public BitmapBasedRegion(CpuBlit.MemBitmap bmp) { _bmp = bmp; _bounds = new Rectangle(0, 0, _bmp.Width, _bmp.Height); }
public abstract void SaveImage(MemBitmap bitmap, System.IO.Stream output, OutputImageFormat outputFormat, object saveParameters);
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; //------------------------------------------------------------- var atlasBuilder = new SimpleBitmapAtlasBuilder(); atlasBuilder.SetAtlasFontInfo(typeface.Name, sizeInPoint); //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(); 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); } }
GlyphBitmap GetGlyphBitmapFromColorOutlineGlyph(ushort glyphIndex, GlyphMeshStore glyphMeshStore, ushort colorLayerStart) { //not found=> create a newone Typography.OpenFont.Tables.COLR _colrTable = _typeface.COLRTable; Typography.OpenFont.Tables.CPAL _cpalTable = _typeface.CPALTable; Q1RectD totalBounds = Q1RectD.ZeroIntersection(); { //calculate bounds of this glyph ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { BoundingRect.GetBoundingRect(glyphMeshStore.GetGlyphMesh(_colrTable.GlyphLayers[c]), ref totalBounds); } } //dbugExportCount++; var memBmp = new MemBitmap((int)Math.Round(totalBounds.Width), (int)Math.Round(totalBounds.Height));//??? int offset_x = 0; int offset_y = 0; using (Tools.BorrowAggPainter(memBmp, out AggPainter painter)) { painter.Clear(Color.Transparent); painter.SetOrigin(0, 0); offset_x = -(int)(totalBounds.Left); offset_y = -(int)(totalBounds.Bottom); ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; int palette = 0; // FIXME: assume palette 0 for now for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { _cpalTable.GetColor( _cpalTable.Palettes[palette] + _colrTable.GlyphPalettes[c], //index out byte r, out byte g, out byte b, out byte a); ushort gIndex = _colrTable.GlyphLayers[c]; VertexStore vxs = glyphMeshStore.GetGlyphMesh(gIndex); using (Tools.BorrowVxs(out var v1)) { vxs.TranslateToNewVxs(offset_x, offset_y, v1); painter.FillColor = new Color(r, g, b);//? a component painter.Fill(v1); } } //find ex #if DEBUG //memBmp.SaveImage("a0x" + (dbugExportCount) + ".png"); #endif } return(new GlyphBitmap { Bitmap = memBmp, Width = memBmp.Width, Height = memBmp.Height, ImageStartX = -offset_x, //offset back ImageStartY = -offset_y //offset back }); }
protected virtual void OnAttachingDstBitmap(MemBitmap bmp) { }
void UpdateRenderOutput() { if (!_readyToRender) { return; } // if (_g == null) { _destImg = new MemBitmap(800, 600); _painter = AggPainter.Create(_destImg); _winBmp = new Bitmap(_destImg.Width, _destImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); _g = this.CreateGraphics(); _painter.CurrentFont = new PixelFarm.Drawing.RequestFont("tahoma", 14); _textService = new PixelFarm.Drawing.OpenFontTextService(); _textService.LoadFontsFromFolder("../../../TestFonts"); _devVxsTextPrinter = new PixelFarm.Drawing.VxsTextPrinter(_painter, _textService); _devVxsTextPrinter.SetSvgBmpBuilderFunc(ParseAndRenderSvg); _devVxsTextPrinter.ScriptLang = _basicOptions.ScriptLang; _devVxsTextPrinter.PositionTechnique = Typography.TextLayout.PositionTechnique.OpenFont; } if (string.IsNullOrEmpty(this.txtInputChar.Text)) { return; } //test option use be used with lcd subpixel rendering. //this demonstrate how we shift a pixel for subpixel rendering tech if (_contourAnalysisOpts.SetupPrinterLayoutForLcdSubPix) { //TODO: set lcd or not here } else { //TODO: set lcd or not here } //1. read typeface from font file TypographyTest.RenderChoice renderChoice = _basicOptions.RenderChoice; switch (renderChoice) { case TypographyTest.RenderChoice.RenderWithGdiPlusPath: //not render in this example //see more at ... break; case TypographyTest.RenderChoice.RenderWithTextPrinterAndMiniAgg: { //clear previous draw _painter.Clear(PixelFarm.Drawing.Color.White); _painter.UseLcdEffectSubPixelRendering = _contourAnalysisOpts.LcdTechnique; _painter.FillColor = PixelFarm.Drawing.Color.Black; _selectedTextPrinter = _devVxsTextPrinter; _selectedTextPrinter.Typeface = _basicOptions.Typeface; _selectedTextPrinter.FontSizeInPoints = _basicOptions.FontSizeInPoints; _selectedTextPrinter.ScriptLang = _basicOptions.ScriptLang; _selectedTextPrinter.PositionTechnique = _basicOptions.PositionTech; _selectedTextPrinter.HintTechnique = _glyphRenderOptions.HintTechnique; _selectedTextPrinter.EnableLigature = _glyphRenderOptions.EnableLigature; _selectedTextPrinter.SimulateSlant = _contourAnalysisOpts.SimulateSlant; _selectedTextPrinter.TextBaseline = (PixelFarm.Drawing.TextBaseline)lstTextBaseline.SelectedItem; //test print 3 lines #if DEBUG DynamicOutline.dbugTestNewGridFitting = _contourAnalysisOpts.EnableGridFit; DynamicOutline.dbugActualPosToConsole = _contourAnalysisOpts.WriteFitOutputToConsole; DynamicOutline.dbugUseHorizontalFitValue = _contourAnalysisOpts.UseHorizontalFitAlignment; #endif char[] printTextBuffer = this.txtInputChar.Text.ToCharArray(); float x_pos = 0, y_pos = 0; float lineSpacingPx = _selectedTextPrinter.FontLineSpacingPx; const int REF_LINE_LEN = 300; for (int i = 0; i < 3; ++i) { _selectedTextPrinter.DrawString(printTextBuffer, x_pos, y_pos); #if DEBUG //show debug info... var prevColor = _painter.FillColor; var prevStrokColor = _painter.StrokeColor; _painter.FillColor = PixelFarm.Drawing.Color.Red; _painter.FillRect(x_pos, y_pos, 5, 5); // start point //see //https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline switch (_selectedTextPrinter.TextBaseline) { default: { System.Diagnostics.Debug.WriteLine("UNIMPLEMENTED" + _selectedTextPrinter.TextBaseline.ToString()); goto case PixelFarm.Drawing.TextBaseline.Alphabetic; // } case PixelFarm.Drawing.TextBaseline.Alphabetic: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos, x_pos + REF_LINE_LEN, y_pos); _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos - _selectedTextPrinter.FontDescedingPx, x_pos + REF_LINE_LEN, y_pos - _selectedTextPrinter.FontDescedingPx); //bottom most } break; case PixelFarm.Drawing.TextBaseline.Top: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos + _selectedTextPrinter.FontAscendingPx, x_pos + REF_LINE_LEN, y_pos + _selectedTextPrinter.FontAscendingPx); //em bottom _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos + (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx), x_pos + REF_LINE_LEN, y_pos + (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx)); //bottom most } break; case PixelFarm.Drawing.TextBaseline.Bottom: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos + _selectedTextPrinter.FontDescedingPx, x_pos + REF_LINE_LEN, y_pos + _selectedTextPrinter.FontDescedingPx); //em bottom _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos, x_pos + REF_LINE_LEN, y_pos); //bottom most } break; } _painter.FillColor = prevColor; _painter.StrokeColor = prevColor; #endif y_pos += (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx); } //copy from Agg's memory buffer to gdi PixelFarm.CpuBlit.BitmapHelper.CopyToGdiPlusBitmapSameSizeNotFlip(_destImg, _winBmp); _g.Clear(Color.White); _g.DrawImage(_winBmp, new Point(0, 0)); } break; //============================================== //render 1 glyph for debug and test case TypographyTest.RenderChoice.RenderWithMsdfGen: case TypographyTest.RenderChoice.RenderWithSdfGen: { char testChar = this.txtInputChar.Text[0]; Typeface typeFace = _basicOptions.Typeface; RenderWithMsdfImg(typeFace, testChar, _basicOptions.FontSizeInPoints); } break; case TypographyTest.RenderChoice.RenderWithMiniAgg_SingleGlyph: { _selectedTextPrinter = _devVxsTextPrinter; //for test only 1 char RenderSingleCharWithMiniAgg( _basicOptions.Typeface, this.txtInputChar.Text[0], _basicOptions.FontSizeInPoints); } break; default: throw new NotSupportedException(); } }
public CutCopyPasteDemo() { _lionPng = MemBitmapExt.LoadBitmap("../Data/lion1.png"); }
public override void Init() { //actualImage2 = LoadImage(RootDemoPath.Path + "\\plain01.png"); _memBmp = LoadImage(RootDemoPath.Path + "\\02.jpg"); _mat = AffineMat.GetTranslateMat(50, 50); }
//ActualBitmap GetTransformedBilinearInterpolation() //{ // //4 points sampling // //weight between four point // ActualBitmap destCB = new ActualBitmap(rect.Width, rect.Height); // MyBitmapBlender destWriter = new MyBitmapBlender(destCB); // PointF ptInPlane = new PointF(); // int x1, x2, y1, y2; // double dab, dbc, dcd, dda; // float dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2; // int rectWidth = rect.Width; // int rectHeight = rect.Height; // Vector ab_vec = this.AB; // Vector bc_vec = this.BC; // Vector cd_vec = this.CD; // Vector da_vec = this.DA; // int rectLeft = this.rect.Left; // int rectTop = this.rect.Top; // for (int y = 0; y < rectHeight; ++y) // { // for (int x = 0; x < rectWidth; ++x) // { // PointF srcPt = new PointF(x, y); // srcPt.Offset(rectLeft, rectTop); // if (!IsOnPlaneABCD(srcPt)) // { // continue; // } // //------------------------------------- // dab = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p0, srcPt).CrossProduct(ab_vec)); // dbc = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p1, srcPt).CrossProduct(bc_vec)); // dcd = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p2, srcPt).CrossProduct(cd_vec)); // dda = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p3, srcPt).CrossProduct(da_vec)); // ptInPlane.X = (float)(srcW * (dda / (dda + dbc))); // ptInPlane.Y = (float)(srcH * (dab / (dab + dcd))); // x1 = (int)ptInPlane.X; // y1 = (int)ptInPlane.Y; // if (x1 >= 0 && x1 < srcW && y1 >= 0 && y1 < srcH) // { // //bilinear interpolation *** // x2 = (x1 == srcW - 1) ? x1 : x1 + 1; // y2 = (y1 == srcH - 1) ? y1 : y1 + 1; // dx1 = ptInPlane.X - x1; // if (dx1 < 0) dx1 = 0; // dx1 = 1f - dx1; // dx2 = 1f - dx1; // dy1 = ptInPlane.Y - y1; // if (dy1 < 0) dy1 = 0; // dy1 = 1f - dy1; // dy2 = 1f - dy1; // dx1y1 = dx1 * dy1; // dx1y2 = dx1 * dy2; // dx2y1 = dx2 * dy1; // dx2y2 = dx2 * dy2; // //use 4 points // Drawing.Color x1y1Color = srcCB.GetPixel(x1, y1); // Drawing.Color x2y1Color = srcCB.GetPixel(x2, y1); // Drawing.Color x1y2Color = srcCB.GetPixel(x1, y2); // Drawing.Color x2y2Color = srcCB.GetPixel(x2, y2); // float a = (x1y1Color.alpha * dx1y1) + (x2y1Color.alpha * dx2y1) + (x1y2Color.alpha * dx1y2) + (x2y2Color.alpha * dx2y2); // float b = (x1y1Color.blue * dx1y1) + (x2y1Color.blue * dx2y1) + (x1y2Color.blue * dx1y2) + (x2y2Color.blue * dx2y2); // float g = (x1y1Color.green * dx1y1) + (x2y1Color.green * dx2y1) + (x1y2Color.green * dx1y2) + (x2y2Color.green * dx2y2); // float r = (x1y1Color.red * dx1y1) + (x2y1Color.red * dx2y1) + (x1y2Color.red * dx1y2) + (x2y2Color.red * dx2y2); // destWriter.SetPixel(x, y, new Drawing.Color((byte)a, (byte)b, (byte)g, (byte)r)); // } // } // } // return destCB; //} unsafe MemBitmap GetTransformedBicubicInterpolation() { //4 points sampling //weight between four point PointF ptInPlane = new PointF(); int x1, x2, y1, y2; double dab, dbc, dcd, dda; //float dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2; int destRectWidth = _destBounds.Width; int dectRectHeight = _destBounds.Height; Vector ab_vec = _AB; Vector bc_vec = _BC; Vector cd_vec = _CD; Vector da_vec = _DA; using (TempMemPtr.FromBmp(_srcBmp, out int *bufferPtr)) { BufferReader4 reader = new BufferReader4(bufferPtr, _srcBmp.Width, _srcBmp.Height); MemBitmap destCB = new MemBitmap(_destBounds.Width, _destBounds.Height); #if DEBUG destCB._dbugNote = "GetTransformedBicubicInterpolation()"; #endif MyBitmapBlender destWriter = new MyBitmapBlender(destCB); int rectLeft = _destBounds.Left; int rectTop = _destBounds.Top; //*** PixelFarm.Drawing.Color[] colors = new PixelFarm.Drawing.Color[16]; int srcW_lim = _srcW - 2; int srcH_lim = _srcH - 2; for (int y = 0; y < dectRectHeight; ++y) { for (int x = 0; x < destRectWidth; ++x) { PointF srcPt = new PointF(x, y); srcPt.Offset(rectLeft, 0); if (!IsOnPlaneABCD(srcPt)) { continue; } //------------------------------------- dab = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p0, srcPt).CrossProduct(ab_vec)); dbc = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p1, srcPt).CrossProduct(bc_vec)); dcd = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p2, srcPt).CrossProduct(cd_vec)); dda = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p3, srcPt).CrossProduct(da_vec)); ptInPlane.X = (float)(_srcW * (dda / (dda + dbc))); ptInPlane.Y = (float)(_srcH * (dab / (dab + dcd))); x1 = (int)ptInPlane.X; y1 = (int)ptInPlane.Y; if (x1 >= 2 && x1 < srcW_lim && y1 >= 2 && y1 < srcH_lim) { reader.SetStartPixel(x1, y1); //reader.Read16(pixelBuffer); //do interpolate //find src pixel and approximate destWriter.SetPixel(x, y, GetApproximateColor_Bicubic(reader, colors, ptInPlane.X, ptInPlane.Y)); //TODO:review here blue switch to red channel } } //newline // startLine += stride2; //targetPixelIndex = startLine; } //------------------------ //System.Runtime.InteropServices.Marshal.Copy( //outputBuffer, 0, //bmpdata2.Scan0, outputBuffer.Length); //outputbmp.UnlockBits(bmpdata2); ////outputbmp.Save("n_lion_bicubic.png"); //return outputbmp; return(destCB); } }
protected override void OnAttachingDstBitmap(MemBitmap bmp) { _bmp = bmp; }
public override MemBitmap ScaleImage(MemBitmap bmp, float x_scale, float y_scale) { //TODO: implement this ... throw new NotImplementedException(); }
public override void WriteBuffer(int[] newbuffer) { MemBitmap.ReplaceBuffer(_bmp, newbuffer); }
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)); } }
BitmapBasedRegion CreateNewRegion(BitmapBasedRegion another, SetOperationName opName) { // MemBitmap myBmp = this.GetRegionBitmap(); //or create new as need MemBitmap anotherBmp = another.GetRegionBitmap(); //do bitmap union //2 rgn merge may Rectangle r1Rect = this.GetRectBounds(); Rectangle r2Rect = another.GetRectBounds(); Rectangle r3Rect = Rectangle.Union(r1Rect, r2Rect); // MemBitmap r3Bmp = new MemBitmap(r3Rect.Width, r3Rect.Height); r3Bmp.Clear(Color.Black); MaskBitmapReader r1 = new MaskBitmapReader(); r1.SetBitmap(myBmp); MaskBitmapReader r2 = new MaskBitmapReader(); r2.SetBitmap(anotherBmp); MaskBitmapWriter w3 = new MaskBitmapWriter(); w3.SetBitmap(r3Bmp); int height = r3Rect.Height; int width = r3Rect.Width; switch (opName) { case SetOperationName.Union: for (int y = 0; y < height; ++y) { r1.MoveTo(0, y); r2.MoveTo(0, y); w3.MoveTo(0, y); for (int x = 0; x < width; ++x) { w3.Union(r1.Read(), r2.Read()); r1.MoveRight(); r2.MoveRight(); w3.MoveRight(); } } break; case SetOperationName.Intersect: for (int y = 0; y < height; ++y) { r1.MoveTo(0, y); r2.MoveTo(0, y); w3.MoveTo(0, y); for (int x = 0; x < width; ++x) { w3.Intersect(r1.Read(), r2.Read()); r1.MoveRight(); r2.MoveRight(); w3.MoveRight(); } } break; case SetOperationName.Diff: for (int y = 0; y < height; ++y) { r1.MoveTo(0, y); r2.MoveTo(0, y); w3.MoveTo(0, y); for (int x = 0; x < width; ++x) { w3.Diff(r1.Read(), r2.Read()); r1.MoveRight(); r2.MoveRight(); w3.MoveRight(); } } break; case SetOperationName.Xor: for (int y = 0; y < height; ++y) { r1.MoveTo(0, y); r2.MoveTo(0, y); w3.MoveTo(0, y); for (int x = 0; x < width; ++x) { w3.Xor(r1.Read(), r2.Read()); r1.MoveRight(); r2.MoveRight(); w3.MoveRight(); } } break; } return(new BitmapBasedRegion(r3Bmp)); }
public static void Save(MemBitmap bmp, Stream strm) { //------------- unsafe { PixelFarm.CpuBlit.Imaging.TempMemPtr tmp = MemBitmap.GetBufferPtr(bmp); int *intBuffer = (int *)tmp.Ptr; int imgW = bmp.Width; int imgH = bmp.Height; Hjg.Pngcs.ImageInfo imgInfo = new Hjg.Pngcs.ImageInfo(imgW, imgH, 8, true); //8 bits per channel with alpha Hjg.Pngcs.PngWriter writer = new Hjg.Pngcs.PngWriter(strm, imgInfo); Hjg.Pngcs.ImageLine iline = new Hjg.Pngcs.ImageLine(imgInfo, Hjg.Pngcs.ImageLine.ESampleType.BYTE); bool flipYImg = true; int imgStride = imgW * 4; int srcIndex = 0; int srcIndexRowHead = (tmp.LengthInBytes / 4) - imgW; int startReadAt = 0; if (flipYImg) { srcIndexRowHead = 0; for (int row = 0; row < imgH; row++) { byte[] scanlineBuffer = iline.ScanlineB; srcIndex = srcIndexRowHead; for (int b = 0; b < imgStride;) { int srcInt = intBuffer[srcIndex]; srcIndex++; scanlineBuffer[b] = (byte)((srcInt >> 16) & 0xff); scanlineBuffer[b + 1] = (byte)((srcInt >> 8) & 0xff); scanlineBuffer[b + 2] = (byte)((srcInt) & 0xff); scanlineBuffer[b + 3] = (byte)((srcInt >> 24) & 0xff); b += 4; } srcIndexRowHead += imgW; startReadAt += imgStride; writer.WriteRow(iline, row); } } else { for (int row = 0; row < imgH; row++) { byte[] scanlineBuffer = iline.ScanlineB; srcIndex = srcIndexRowHead; for (int b = 0; b < imgStride;) { int srcInt = intBuffer[srcIndex]; srcIndex++; scanlineBuffer[b] = (byte)((srcInt >> 16) & 0xff); scanlineBuffer[b + 1] = (byte)((srcInt >> 8) & 0xff); scanlineBuffer[b + 2] = (byte)((srcInt) & 0xff); scanlineBuffer[b + 3] = (byte)((srcInt >> 24) & 0xff); b += 4; } srcIndexRowHead -= imgW; startReadAt += imgStride; writer.WriteRow(iline, row); } } writer.End(); } }
public abstract void SaveImage(MemBitmap bitmap, string filename, OutputImageFormat outputFormat, object saveParameters);
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 void ReplaceBuffer(MemBitmap bmp, int[] pixelBuffer) { System.Runtime.InteropServices.Marshal.Copy(pixelBuffer, 0, bmp._pixelBuffer, pixelBuffer.Length); }
public override Image CopyToNewMemBitmap() => MemBitmap.CreateFromCopy(_memBitmap);
//--------------- //helper... public static TempMemPtr FromBmp(MemBitmap memBmp) { return(MemBitmap.GetBufferPtr(memBmp)); }
public void Fill(MemBitmap memBmp, int x, int y) { Fill((IBitmapSrc)memBmp, x, y); }
/// <summary> /// create thumbnail img with super-sampling technique,(Expensive, High quality thumb) /// </summary> /// <param name="source"></param> /// <param name="dst"></param> public static MemBitmap CreateThumbnailWithSuperSamplingTechnique(this MemBitmap source, float scaleRatio) { // Paint.NET (MIT,from version 3.36.7, see=> https://github.com/rivy/OpenPDN //in this version new image MUST smaller than the original one *** if (scaleRatio >= 1 || scaleRatio < 0) { return(null); } //create new bitmap int newBmpW = (int)Math.Round(source.Width * scaleRatio); int newBmpH = (int)Math.Round(source.Height * scaleRatio); MemBitmap thumbBitmap = new MemBitmap(newBmpW, newBmpH); //*** IBitmapSrc source_1 = (IBitmapSrc)source; unsafe { Rectangle dstRoi2 = new Rectangle(0, 0, newBmpW, newBmpH); int dstWidth = dstRoi2.Width; int dstHeight = dstRoi2.Height; int srcH = source.Height; int srcW = source.Width; Imaging.TempMemPtr dstMemPtr = MemBitmap.GetBufferPtr(thumbBitmap); int dstStrideInt32 = newBmpW; for (int dstY = dstRoi2.Top; dstY < dstRoi2.Bottom; ++dstY) { //from dst => find proper source (y) //double srcTop = (double)(dstY * srcH) / (double)dstHeight; double srcTop = (double)(dstY * srcH) / (double)dstHeight; double srcTopFloor = Math.Floor(srcTop); double srcTopWeight = 1 - (srcTop - srcTopFloor); int srcTopInt = (int)srcTopFloor; //double srcBottom = (double)((dstY + 1) * srcH) / (double)dstHeight; double srcBottom = (double)((dstY + 1) * srcH) / (double)dstHeight; double srcBottomFloor = Math.Floor(srcBottom - 0.00001); double srcBottomWeight = srcBottom - srcBottomFloor; int srcBottomInt = (int)srcBottomFloor; int *srcBuffer = (int *)(MemBitmap.GetBufferPtr(source)).Ptr; int srcStrideInt32 = source.Width; //*** int *dstAddr = (int *)dstMemPtr.Ptr + (dstStrideInt32 * dstY); //begin at for (int dstX = dstRoi2.Left; dstX < dstRoi2.Right; ++dstX) { //from dst=> find proper source (x) double srcLeft = (double)(dstX * srcW) / (double)dstWidth; double srcLeftFloor = Math.Floor(srcLeft); double srcLeftWeight = 1 - (srcLeft - srcLeftFloor); int srcLeftInt = (int)srcLeftFloor; double srcRight = (double)((dstX + 1) * srcW) / (double)dstWidth; double srcRightFloor = Math.Floor(srcRight - 0.00001); double srcRightWeight = srcRight - srcRightFloor; int srcRightInt = (int)srcRightFloor; double blueSum = 0; double greenSum = 0; double redSum = 0; double alphaSum = 0; //now we know (left,top) of source that we want //then ask the pixel value from source at that pos //(1) left fractional edge { //PaintFx.ColorBgra* srcLeftPtr = source.GetPointAddressUnchecked(srcLeftInt, srcTopInt + 1); int *srcLeftColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt, srcTopInt + 1); for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY) { int srcColor = *srcLeftColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcLeftWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //move to next row srcLeftColorAddr += srcStrideInt32; //srcLeftPtr = (ColorBgra*)((byte*)srcLeftPtr + source._stride); } } // { //(2) right fractional edge //ColorBgra* srcRightPtr = source.GetPointAddressUnchecked(srcRightInt, srcTopInt + 1); int *srcRightColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcRightInt, srcTopInt + 1); for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY) { int srcColor = *srcRightColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcRightWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //srcRightPtr = (ColorBgra*)((byte*)srcRightPtr + source._stride); srcRightColorAddr += srcStrideInt32; //move to next row } } // { //(3) top fractional edge //ColorBgra* srcTopPtr = source.GetPointAddressUnchecked(srcLeftInt + 1, srcTopInt); int *srcTopColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt + 1, srcTopInt); for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX) { int srcColor = *srcTopColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcTopWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //move to next column //++srcTopPtr; ++srcTopColorAddr; } } // { //(4) bottom fractional edge //ColorBgra* srcBottomPtr = source.GetPointAddressUnchecked(srcLeftInt + 1, srcBottomInt); int *srcBottomColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt + 1, srcBottomInt); for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX) { int srcColor = *srcBottomColorAddr; double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * srcBottomWeight; blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //++srcBottomPtr; //move to next column //++srcTopPtr; ++srcBottomColorAddr; } } { //(5) center area for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY) { //ColorBgra* srcPtr = source.GetPointAddressUnchecked(srcLeftInt + 1, srcY); int *srcColorAddr = srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt + 1, srcY); for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX) { int srcColor = *srcColorAddr; int a = ((srcColor >> CO.A_SHIFT) & 0xff); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a; alphaSum += a; ++srcColorAddr; } } } //(6) four corner pixels { //6.1 //ColorBgra srcTL = source.GetPoint(srcLeftInt, srcTopInt); int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt, srcTopInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcTopWeight * srcLeftWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; } { //6.2 //ColorBgra srcTR = source.GetPoint(srcRightInt, srcTopInt); //double srcTRA = srcTR.A; //blueSum += srcTR.B * (srcTopWeight * srcRightWeight) * srcTRA; //greenSum += srcTR.G * (srcTopWeight * srcRightWeight) * srcTRA; //redSum += srcTR.R * (srcTopWeight * srcRightWeight) * srcTRA; //alphaSum += srcTR.A * (srcTopWeight * srcRightWeight); int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcRightInt, srcTopInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcTopWeight * srcRightWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; } { //(6.3) int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcLeftInt, srcBottomInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcBottomWeight * srcLeftWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; //without a //ColorBgra srcBL = source.GetPoint(srcLeftInt, srcBottomInt); //double srcBLA = srcBL.A; //blueSum += srcBL.B * (srcBottomWeight * srcLeftWeight) * srcBLA; //greenSum += srcBL.G * (srcBottomWeight * srcLeftWeight) * srcBLA; //redSum += srcBL.R * (srcBottomWeight * srcLeftWeight) * srcBLA; //alphaSum += srcBL.A * (srcBottomWeight * srcLeftWeight); } { //(6.4) //ColorBgra srcBR = source.GetPoint(srcRightInt, srcBottomInt); //double srcBRA = srcBR.A; //blueSum += srcBR.B * (srcBottomWeight * srcRightWeight) * srcBRA; //greenSum += srcBR.G * (srcBottomWeight * srcRightWeight) * srcBRA; //redSum += srcBR.R * (srcBottomWeight * srcRightWeight) * srcBRA; //alphaSum += srcBR.A * (srcBottomWeight * srcRightWeight); int srcColor = *(srcBuffer + source_1.GetBufferOffsetXY32(srcRightInt, srcBottomInt)); double a_w = ((srcColor >> CO.A_SHIFT) & 0xff) * (srcBottomWeight * srcRightWeight); blueSum += ((srcColor >> CO.B_SHIFT) & 0xff) * a_w; greenSum += ((srcColor >> CO.G_SHIFT) & 0xff) * a_w; redSum += ((srcColor >> CO.R_SHIFT) & 0xff) * a_w; alphaSum += a_w; } double area = (srcRight - srcLeft) * (srcBottom - srcTop); double alpha = alphaSum / area; double blue; double green; double red; if (alpha == 0) { blue = 0; green = 0; red = 0; } else { blue = blueSum / alphaSum; green = greenSum / alphaSum; red = redSum / alphaSum; } // add 0.5 so that rounding goes in the direction we want it to blue += 0.5; green += 0.5; red += 0.5; alpha += 0.5; //*** //dstPtr->Bgra = (uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24); //++dstPtr; *dstAddr = ((byte)alpha) << CO.A_SHIFT | ((byte)blue) << CO.B_SHIFT | ((byte)green) << CO.G_SHIFT | ((byte)red) << CO.R_SHIFT; //(uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24); ++dstAddr; } } } return(thumbBitmap); }
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 = MemBitmap.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.FontKey, 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(); } }
public MyBitmapBlender(MemBitmap bmp) { _memBmp = bmp; Attach(bmp); }
///////////////////////////////////////////////////////////////////////////////////// public static void CopyToGdiPlusBitmapSameSize( MemBitmap memBmp, SkiaSharp.SKBitmap skBmp) { //agg store image buffer head-down //when copy to window bmp we here to flip //style1: copy row by row *** (fastest)*** { //System.GC.Collect(); //System.Diagnostics.Stopwatch sss = new System.Diagnostics.Stopwatch(); //sss.Start(); //for (int i = 0; i < 1000; ++i) //{ int h = skBmp.Height; int w = skBmp.Width; //BitmapData bitmapData1 = bitmap.LockBits( // new Rectangle(0, 0, // w, // h), // System.Drawing.Imaging.ImageLockMode.ReadWrite, // bitmap.PixelFormat); skBmp.LockPixels(); IntPtr scan0 = skBmp.GetPixels(); int stride = memBmp.Stride; //byte[] srcBuffer = ActualImage.GetBuffer(actualImage); unsafe { CpuBlit.Imaging.TempMemPtr srcBufferPtr = MemBitmap.GetBufferPtr(memBmp); //fixed (byte* bufferH = &srcBuffer[0]) byte *bufferH = (byte *)srcBufferPtr.Ptr; { byte *target = (byte *)scan0; int startRowAt = ((h - 1) * stride); for (int y = h; y > 0; --y) { //byte* src = bufferH + ((y - 1) * stride); //System.Runtime.InteropServices.Marshal.Copy( // srcBuffer,//src // startRowAt, // (IntPtr)target, // stride); PixelFarm.CpuBlit.MemMx.memcpy(target, bufferH + startRowAt, stride); startRowAt -= stride; target += stride; } } srcBufferPtr.Dispose(); } skBmp.UnlockPixels(); //} //sss.Stop(); //long ms = sss.ElapsedMilliseconds; } //----------------------------------- //style2: copy all, then flip again //{ // System.GC.Collect(); // System.Diagnostics.Stopwatch sss = new System.Diagnostics.Stopwatch(); // sss.Start(); // for (int i = 0; i < 1000; ++i) // { // byte[] rawBuffer = ActualImage.GetBuffer(actualImage); // var bmpdata = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), // System.Drawing.Imaging.ImageLockMode.ReadOnly, // bitmap.PixelFormat); // System.Runtime.InteropServices.Marshal.Copy(rawBuffer, 0, // bmpdata.Scan0, rawBuffer.Length); // bitmap.UnlockBits(bmpdata); // bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); // } // sss.Stop(); // long ms = sss.ElapsedMilliseconds; //} //----------------------------------- //----------------------------------- //style3: copy row by row + //{ // System.GC.Collect(); // System.Diagnostics.Stopwatch sss = new System.Diagnostics.Stopwatch(); // sss.Start(); // for (int i = 0; i < 1000; ++i) // { // int h = bitmap.Height; // int w = bitmap.Width; // BitmapData bitmapData1 = bitmap.LockBits( // new Rectangle(0, 0, // w, // h), // System.Drawing.Imaging.ImageLockMode.ReadWrite, // bitmap.PixelFormat); // IntPtr scan0 = bitmapData1.Scan0; // int stride = bitmapData1.Stride; // byte[] buffer = ActualImage.GetBuffer(actualImage); // unsafe // { // fixed (byte* bufferH = &buffer[0]) // { // byte* target = (byte*)scan0; // for (int y = h; y > 0; --y) // { // byte* src = bufferH + ((y - 1) * stride); // for (int n = stride - 1; n >= 0; --n) // { // *target = *src; // target++; // src++; // } // } // } // } // bitmap.UnlockBits(bitmapData1); // } // sss.Stop(); // long ms = sss.ElapsedMilliseconds; //} }