1 ///////////////////////////////////////////////////////////////////////////////// 2 // Paint.NET // 3 // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. // 4 // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. // 5 // See license-pdn.txt for full licensing and attribution details. // 6 // // 7 // Ported to Pinta by: Marco Rolappe <m_rolappe@gmx.net> // 8 ///////////////////////////////////////////////////////////////////////////////// 9 10 using System; 11 using Cairo; 12 using Pinta.Gui.Widgets; 13 using Pinta.Core; 14 using Mono.Unix; 15 16 namespace Pinta.Effects 17 { 18 public class PixelateEffect : BaseEffect 19 { 20 public override string Icon { 21 get { return "Menu.Effects.Distort.Pixelate.png"; } 22 } 23 24 public override string Name { 25 get { return Catalog.GetString ("Pixelate"); } 26 } 27 28 public override bool IsConfigurable { 29 get { return true; } 30 } 31 32 public PixelateData Data { 33 get { return EffectData as PixelateData; } 34 } 35 36 public override string EffectMenuCategory { 37 get { return Catalog.GetString ("Distort"); } 38 } 39 PixelateEffect()40 public PixelateEffect () { 41 EffectData = new PixelateData (); 42 } 43 LaunchConfiguration()44 public override bool LaunchConfiguration () { 45 return EffectHelper.LaunchSimpleEffectDialog (this); 46 } 47 48 #region Algorithm Code Ported From PDN ComputeCellColor(int x, int y, ImageSurface src, int cellSize, Gdk.Rectangle srcBounds)49 private ColorBgra ComputeCellColor (int x, int y, ImageSurface src, int cellSize, Gdk.Rectangle srcBounds) { 50 Gdk.Rectangle cell = GetCellBox (x, y, cellSize); 51 cell.Intersect (srcBounds); 52 53 int left = cell.Left; 54 int right = cell.GetRight (); 55 int bottom = cell.GetBottom (); 56 int top = cell.Top; 57 58 ColorBgra colorTopLeft = src.GetColorBgraUnchecked (left, top).ToStraightAlpha(); 59 ColorBgra colorTopRight = src.GetColorBgraUnchecked (right, top).ToStraightAlpha(); 60 ColorBgra colorBottomLeft = src.GetColorBgraUnchecked (left, bottom).ToStraightAlpha(); 61 ColorBgra colorBottomRight = src.GetColorBgraUnchecked (right, bottom).ToStraightAlpha(); 62 63 ColorBgra c = ColorBgra.BlendColors4W16IP (colorTopLeft, 16384, colorTopRight, 16384, colorBottomLeft, 16384, colorBottomRight, 16384); 64 65 return c.ToPremultipliedAlpha(); 66 } 67 GetCellBox(int x, int y, int cellSize)68 private Gdk.Rectangle GetCellBox (int x, int y, int cellSize) { 69 int widthBoxNum = x % cellSize; 70 int heightBoxNum = y % cellSize; 71 var leftUpper = new Gdk.Point (x - widthBoxNum, y - heightBoxNum); 72 73 var returnMe = new Gdk.Rectangle (leftUpper, new Gdk.Size (cellSize, cellSize)); 74 75 return returnMe; 76 } 77 78 Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois)79 unsafe public override void Render (ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { 80 var cellSize = Data.CellSize; 81 82 Gdk.Rectangle src_bounds = src.GetBounds (); 83 Gdk.Rectangle dest_bounds = dest.GetBounds (); 84 85 foreach (var rect in rois) { 86 for (int y = rect.Top; y <= rect.GetBottom (); ++y) { 87 int yEnd = y + 1; 88 89 for (int x = rect.Left; x <= rect.GetRight (); ++x) { 90 var cellRect = GetCellBox (x, y, cellSize); 91 cellRect.Intersect (dest_bounds); 92 var color = ComputeCellColor (x, y, src, cellSize, src_bounds); 93 94 int xEnd = Math.Min (rect.GetRight (), cellRect.GetRight ()); 95 yEnd = Math.Min (rect.GetBottom (), cellRect.GetBottom ()); 96 97 for (int y2 = y; y2 <= yEnd; ++y2) { 98 ColorBgra* ptr = dest.GetPointAddressUnchecked (x, y2); 99 100 for (int x2 = x; x2 <= xEnd; ++x2) { 101 ptr->Bgra = color.Bgra; 102 ++ptr; 103 } 104 } 105 106 x = xEnd; 107 } 108 109 y = yEnd; 110 } 111 } 112 } 113 #endregion 114 } 115 116 117 public class PixelateData : EffectData 118 { 119 [Caption ("Cell Size"), MinimumValue(1), MaximumValue(100)] 120 public int CellSize = 2; 121 } 122 } 123