Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
BitmapUtils.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 //
4 // Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 // THE SOFTWARE.
23 // -----------------------------------------------------------------------------
24 // The following code is a port of MakeSpriteFont from DirectXTk
25 // http://go.microsoft.com/fwlink/?LinkId=248929
26 // -----------------------------------------------------------------------------
27 // Microsoft Public License (Ms-PL)
28 //
29 // This license governs use of the accompanying software. If you use the
30 // software, you accept this license. If you do not accept the license, do not
31 // use the software.
32 //
33 // 1. Definitions
34 // The terms "reproduce," "reproduction," "derivative works," and
35 // "distribution" have the same meaning here as under U.S. copyright law.
36 // A "contribution" is the original software, or any additions or changes to
37 // the software.
38 // A "contributor" is any person that distributes its contribution under this
39 // license.
40 // "Licensed patents" are a contributor's patent claims that read directly on
41 // its contribution.
42 //
43 // 2. Grant of Rights
44 // (A) Copyright Grant- Subject to the terms of this license, including the
45 // license conditions and limitations in section 3, each contributor grants
46 // you a non-exclusive, worldwide, royalty-free copyright license to reproduce
47 // its contribution, prepare derivative works of its contribution, and
48 // distribute its contribution or any derivative works that you create.
49 // (B) Patent Grant- Subject to the terms of this license, including the license
50 // conditions and limitations in section 3, each contributor grants you a
51 // non-exclusive, worldwide, royalty-free license under its licensed patents to
52 // make, have made, use, sell, offer for sale, import, and/or otherwise dispose
53 // of its contribution in the software or derivative works of the contribution
54 // in the software.
55 //
56 // 3. Conditions and Limitations
57 // (A) No Trademark License- This license does not grant you rights to use any
58 // contributors' name, logo, or trademarks.
59 // (B) If you bring a patent claim against any contributor over patents that
60 // you claim are infringed by the software, your patent license from such
61 // contributor to the software ends automatically.
62 // (C) If you distribute any portion of the software, you must retain all
63 // copyright, patent, trademark, and attribution notices that are present in the
64 // software.
65 // (D) If you distribute any portion of the software in source code form, you
66 // may do so only under this license by including a complete copy of this
67 // license with your distribution. If you distribute any portion of the software
68 // in compiled or object code form, you may only do so under a license that
69 // complies with this license.
70 // (E) The software is licensed "as-is." You bear the risk of using it. The
71 // contributors give no express warranties, guarantees or conditions. You may
72 // have additional consumer rights under your local laws which this license
73 // cannot change. To the extent permitted under your local laws, the
74 // contributors exclude the implied warranties of merchantability, fitness for a
75 // particular purpose and non-infringement.
76 //--------------------------------------------------------------------
77 
78 using System;
79 using System.Drawing;
80 using System.Drawing.Imaging;
81 using System.Runtime.InteropServices;
82 
83 namespace SiliconStudio.Paradox.Assets.SpriteFont.Compiler
84 {
85  // Assorted helpers for doing useful things with bitmaps.
86  internal static class BitmapUtils
87  {
88  // Copies a rectangular area from one bitmap to another.
89  public static void CopyRect(Bitmap source, Rectangle sourceRegion, Bitmap output, Rectangle outputRegion)
90  {
91  if (sourceRegion.Width != outputRegion.Width ||
92  sourceRegion.Height != outputRegion.Height)
93  {
94  throw new ArgumentException();
95  }
96 
97  using (var sourceData = new PixelAccessor(source, ImageLockMode.ReadOnly, sourceRegion))
98  using (var outputData = new PixelAccessor(output, ImageLockMode.WriteOnly, outputRegion))
99  {
100  for (int y = 0; y < sourceRegion.Height; y++)
101  {
102  for (int x = 0; x < sourceRegion.Width; x++)
103  {
104  outputData[x, y] = sourceData[x, y];
105  }
106  }
107  }
108  }
109 
110 
111  // Checks whether an area of a bitmap contains entirely the specified alpha value.
112  public static bool IsAlphaEntirely(byte expectedAlpha, Bitmap bitmap, Rectangle? region = null)
113  {
114  using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadOnly, region))
115  {
116  for (int y = 0; y < bitmapData.Region.Height; y++)
117  {
118  for (int x = 0; x < bitmapData.Region.Width; x++)
119  {
120  byte alpha = bitmapData[x, y].A;
121 
122  if (alpha != expectedAlpha)
123  return false;
124  }
125  }
126  }
127 
128  return true;
129  }
130 
131 
132  // Checks whether a bitmap contains entirely the specified RGB value.
133  public static bool IsRgbEntirely(Color expectedRgb, Bitmap bitmap)
134  {
135  using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadOnly))
136  {
137  for (int y = 0; y < bitmap.Height; y++)
138  {
139  for (int x = 0; x < bitmap.Width; x++)
140  {
141  Color color = bitmapData[x, y];
142 
143  if (color.A == 0)
144  continue;
145 
146  if ((color.R != expectedRgb.R) ||
147  (color.G != expectedRgb.G) ||
148  (color.B != expectedRgb.B))
149  {
150  return false;
151  }
152  }
153  }
154  }
155 
156  return true;
157  }
158 
159 
160  // Converts greyscale luminosity to alpha data.
161  public static void ConvertGreyToAlpha(Bitmap bitmap, Rectangle region)
162  {
163  using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite, region))
164  {
165  for (int y = 0; y < region.Height; y++)
166  {
167  for (int x = 0; x < region.Width; x++)
168  {
169  var color = bitmapData[x, y];
170 
171  // Average the red, green and blue values to compute brightness.
172  var alpha = (color.R + color.G + color.B) / 3;
173 
174  bitmapData[x, y] = Color.FromArgb(alpha, 255, 255, 255);
175  }
176  }
177  }
178  }
179 
180  // Converts a bitmap to premultiplied alpha format.
181  public static void PremultiplyAlphaClearType(Bitmap bitmap)
182  {
183  using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
184  {
185  for (int y = 0; y < bitmap.Height; y++)
186  {
187  for (int x = 0; x < bitmap.Width; x++)
188  {
189  Color color = bitmapData[x, y];
190 
191  int a = (color.R + color.G + color.B) / 3;
192  int r = color.R;
193  int g = color.G;
194  int b = color.B;
195 
196  bitmapData[x, y] = Color.FromArgb(a, r, g, b);
197  }
198  }
199  }
200  }
201 
202  // Converts a bitmap to premultiplied alpha format.
203  public static void PremultiplyAlpha(Bitmap bitmap)
204  {
205  using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
206  {
207  for (int y = 0; y < bitmap.Height; y++)
208  {
209  for (int x = 0; x < bitmap.Width; x++)
210  {
211  Color color = bitmapData[x, y];
212 
213  int a = color.A;
214  int r = color.R * a / 255;
215  int g = color.G * a / 255;
216  int b = color.B * a / 255;
217 
218  bitmapData[x, y] = Color.FromArgb(a, r, g, b);
219  }
220  }
221  }
222  }
223 
224 
225  // To avoid filtering artifacts when scaling or rotating fonts that do not use premultiplied alpha,
226  // make sure the one pixel border around each glyph contains the same RGB values as the edge of the
227  // glyph itself, but with zero alpha. This processing is an elaborate no-op when using premultiplied
228  // alpha, because the premultiply conversion will change the RGB of all such zero alpha pixels to black.
229  public static void PadBorderPixels(Bitmap bitmap, Rectangle region)
230  {
231  using (var bitmapData = new PixelAccessor(bitmap, ImageLockMode.ReadWrite))
232  {
233  // Pad the top and bottom.
234  for (int x = region.Left; x < region.Right; x++)
235  {
236  CopyBorderPixel(bitmapData, x, region.Top, x, region.Top - 1);
237  CopyBorderPixel(bitmapData, x, region.Bottom - 1, x, region.Bottom);
238  }
239 
240  // Pad the left and right.
241  for (int y = region.Top; y < region.Bottom; y++)
242  {
243  CopyBorderPixel(bitmapData, region.Left, y, region.Left - 1, y);
244  CopyBorderPixel(bitmapData, region.Right - 1, y, region.Right, y);
245  }
246 
247  // Pad the four corners.
248  CopyBorderPixel(bitmapData, region.Left, region.Top, region.Left - 1, region.Top - 1);
249  CopyBorderPixel(bitmapData, region.Right - 1, region.Top, region.Right, region.Top - 1);
250  CopyBorderPixel(bitmapData, region.Left, region.Bottom - 1, region.Left - 1, region.Bottom);
251  CopyBorderPixel(bitmapData, region.Right - 1, region.Bottom - 1, region.Right, region.Bottom);
252  }
253  }
254 
255 
256  // Copies a single pixel within a bitmap, preserving RGB but forcing alpha to zero.
257  static void CopyBorderPixel(PixelAccessor bitmapData, int sourceX, int sourceY, int destX, int destY)
258  {
259  Color color = bitmapData[sourceX, sourceY];
260 
261  bitmapData[destX, destY] = Color.FromArgb(0, color);
262  }
263 
264 
265  // Converts a bitmap to the specified pixel format.
266  public static Bitmap ChangePixelFormat(Bitmap bitmap, PixelFormat format)
267  {
268  Rectangle bounds = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
269 
270  return bitmap.Clone(bounds, format);
271  }
272 
273 
274  // Helper for locking a bitmap and efficiently reading or writing its pixels.
275  public sealed class PixelAccessor : IDisposable
276  {
277  // Constructor locks the bitmap.
278  public PixelAccessor(Bitmap bitmap, ImageLockMode mode, Rectangle? region = null)
279  {
280  this.bitmap = bitmap;
281 
282  Region = region.GetValueOrDefault(new Rectangle(0, 0, bitmap.Width, bitmap.Height));
283 
284  data = bitmap.LockBits(Region, mode, PixelFormat.Format32bppArgb);
285  }
286 
287 
288  // Dispose unlocks the bitmap.
289  public void Dispose()
290  {
291  if (data != null)
292  {
293  bitmap.UnlockBits(data);
294 
295  data = null;
296  }
297  }
298 
299 
300  // Query what part of the bitmap is locked.
301  public Rectangle Region { get; private set; }
302 
303 
304  // Get or set a pixel value.
305  public Color this[int x, int y]
306  {
307  get
308  {
309  return Color.FromArgb(Marshal.ReadInt32(PixelAddress(x, y)));
310  }
311 
312  set
313  {
314  Marshal.WriteInt32(PixelAddress(x, y), value.ToArgb());
315  }
316  }
317 
318 
319  // Helper computes the address of the specified pixel.
320  unsafe IntPtr PixelAddress(int x, int y)
321  {
322  return new IntPtr((byte*)data.Scan0 + (y * data.Stride) + (x * sizeof(int)));
323  }
324 
325  // Fields.
326  Bitmap bitmap;
327  BitmapData data;
328  }
329  }
330 }
function b
function a
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
SiliconStudio.Core.Mathematics.Color Color
Definition: ColorPicker.cs:14
PixelAccessor(Bitmap bitmap, ImageLockMode mode, Rectangle?region=null)
Definition: BitmapUtils.cs:278
System.Windows.Shapes.Rectangle Rectangle
Definition: ColorPicker.cs:16
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
PixelFormat
Defines various types of pixel formats.
Definition: PixelFormat.cs:32
HRESULT PremultiplyAlpha(_In_ const Image &srcImage, _In_ DWORD flags, _Out_ ScratchImage &image)