~mantas/pinta/stable

« back to all changes in this revision

Viewing changes to Pinta.Core/Classes/Layer.cs

  • Committer: Iain Lane
  • Date: 2010-02-19 15:33:30 UTC
  • Revision ID: git-v1:92cc09614a4e2801bfe39cd971f6b31e694a500b
ImportedĀ UpstreamĀ versionĀ 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 
 
2
// Layer.cs
 
3
//  
 
4
// Author:
 
5
//       Jonathan Pobst <monkey@jpobst.com>
 
6
// 
 
7
// Copyright (c) 2010 Jonathan Pobst
 
8
// 
 
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
10
// of this software and associated documentation files (the "Software"), to deal
 
11
// in the Software without restriction, including without limitation the rights
 
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
13
// copies of the Software, and to permit persons to whom the Software is
 
14
// furnished to do so, subject to the following conditions:
 
15
// 
 
16
// The above copyright notice and this permission notice shall be included in
 
17
// all copies or substantial portions of the Software.
 
18
// 
 
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
25
// THE SOFTWARE.
 
26
 
 
27
using System;
 
28
using Cairo;
 
29
 
 
30
namespace Pinta.Core
 
31
{
 
32
        public class Layer
 
33
        {
 
34
                public ImageSurface Surface { get; set; }
 
35
                public double Opacity { get; set; }
 
36
                public bool Hidden { get; set; }
 
37
                public string Name { get; set; }
 
38
                public bool Tiled { get; set; }
 
39
                public PointD Offset { get; set; }
 
40
                
 
41
                public Layer () : this (null)
 
42
                {
 
43
                }
 
44
                
 
45
                public Layer (ImageSurface surface) : this (surface, false, 1f, "")
 
46
                {
 
47
                }
 
48
                
 
49
                public Layer (ImageSurface surface, bool hidden, double opacity, string name)
 
50
                {
 
51
                        Surface = surface;
 
52
                        Hidden = hidden;
 
53
                        Opacity = opacity;
 
54
                        Name = name;
 
55
                        Offset = new PointD (0, 0);
 
56
                }       
 
57
                
 
58
                public void Clear ()
 
59
                {
 
60
                        using (Context g = new Context (Surface)) {
 
61
                                g.Operator = Operator.Clear;
 
62
                                g.Paint ();
 
63
                        }
 
64
                }
 
65
                
 
66
                public void FlipHorizontal ()
 
67
                {
 
68
                        Layer dest = PintaCore.Layers.CreateLayer ();
 
69
                        
 
70
                        using (Cairo.Context g = new Cairo.Context (dest.Surface)) {
 
71
                                g.Matrix = new Matrix (-1, 0, 0, 1, Surface.Width, 0);
 
72
                                g.SetSource (Surface);
 
73
                                
 
74
                                g.Paint ();
 
75
                        }
 
76
                        
 
77
                        Surface old = Surface;
 
78
                        Surface = dest.Surface;
 
79
                        (old as IDisposable).Dispose ();
 
80
                }
 
81
                
 
82
                public void FlipVertical ()
 
83
                {
 
84
                        Layer dest = PintaCore.Layers.CreateLayer ();
 
85
                        
 
86
                        using (Cairo.Context g = new Cairo.Context (dest.Surface)) {
 
87
                                g.Matrix = new Matrix (1, 0, 0, -1, 0, Surface.Height);
 
88
                                g.SetSource (Surface);
 
89
                                
 
90
                                g.Paint ();
 
91
                        }
 
92
                        
 
93
                        Surface old = Surface;
 
94
                        Surface = dest.Surface;
 
95
                        (old as IDisposable).Dispose ();
 
96
                }
 
97
                
 
98
                public void Rotate180 ()
 
99
                {
 
100
                        Layer dest = PintaCore.Layers.CreateLayer ();
 
101
                        
 
102
                        using (Cairo.Context g = new Cairo.Context (dest.Surface)) {
 
103
                                g.Matrix = new Matrix (-1, 0, 0, -1, Surface.Width, Surface.Height);
 
104
                                g.SetSource (Surface);
 
105
                                
 
106
                                g.Paint ();
 
107
                        }
 
108
                        
 
109
                        Surface old = Surface;
 
110
                        Surface = dest.Surface;
 
111
                        (old as IDisposable).Dispose ();
 
112
                }
 
113
                
 
114
                public void Rotate90CW ()
 
115
                {
 
116
                        double w = PintaCore.Workspace.ImageSize.X;
 
117
                        double h = PintaCore.Workspace.ImageSize.Y;
 
118
                        
 
119
                        Layer dest = PintaCore.Layers.CreateLayer ("", (int)h, (int)w);
 
120
                        
 
121
                        using (Cairo.Context g = new Cairo.Context (dest.Surface)) {
 
122
                                g.Translate (h / 2, w / 2);
 
123
                                g.Rotate (Math.PI / 2);
 
124
                                g.Translate (-w / 2, -h / 2);
 
125
                                g.SetSource (Surface);
 
126
                                
 
127
                                g.Paint ();
 
128
                        }
 
129
                        
 
130
                        Surface old = Surface;
 
131
                        Surface = dest.Surface;
 
132
                        (old as IDisposable).Dispose ();
 
133
                }
 
134
                
 
135
                public void Rotate90CCW ()
 
136
                {
 
137
                        double w = PintaCore.Workspace.ImageSize.X;
 
138
                        double h = PintaCore.Workspace.ImageSize.Y;
 
139
                        
 
140
                        Layer dest = PintaCore.Layers.CreateLayer ("", (int)h, (int)w);
 
141
                        
 
142
                        using (Cairo.Context g = new Cairo.Context (dest.Surface)) {
 
143
                                g.Translate (h / 2, w / 2);
 
144
                                g.Rotate (Math.PI / -2);
 
145
                                g.Translate (-w / 2, -h / 2);
 
146
                                g.SetSource (Surface);
 
147
                                
 
148
                                g.Paint ();
 
149
                        }
 
150
                        
 
151
                        Surface old = Surface;
 
152
                        Surface = dest.Surface;
 
153
                        (old as IDisposable).Dispose ();
 
154
                }
 
155
                
 
156
                public unsafe void Sepia ()
 
157
                {
 
158
                        Desaturate ();
 
159
                        
 
160
                        UnaryPixelOp op = new UnaryPixelOps.Level(
 
161
                                ColorBgra.Black, 
 
162
                                ColorBgra.White,
 
163
                                new float[] { 1.2f, 1.0f, 0.8f },
 
164
                                ColorBgra.Black,
 
165
                                ColorBgra.White);
 
166
 
 
167
                        ImageSurface dest = Surface.Clone ();
 
168
 
 
169
                        ColorBgra* dstPtr = (ColorBgra*)dest.DataPtr;
 
170
                        int len = Surface.Data.Length / 4;
 
171
                        
 
172
                        op.Apply (dstPtr, len);
 
173
 
 
174
                        using (Context g = new Context (Surface)) {
 
175
                                g.AppendPath (PintaCore.Layers.SelectionPath);
 
176
                                g.FillRule = FillRule.EvenOdd;
 
177
                                g.Clip ();
 
178
 
 
179
                                g.SetSource (dest);
 
180
                                g.Paint ();
 
181
                        }
 
182
 
 
183
                        (dest as IDisposable).Dispose ();
 
184
                }
 
185
                
 
186
                public unsafe void Invert ()
 
187
                {
 
188
                        ImageSurface dest = Surface.Clone ();
 
189
 
 
190
                        ColorBgra* dstPtr = (ColorBgra*)dest.DataPtr;
 
191
                        int len = Surface.Data.Length / 4;
 
192
                        
 
193
                        for (int i = 0; i < len; i++) {
 
194
                                if (dstPtr->A != 0)
 
195
                                *dstPtr = (ColorBgra.FromBgra((byte)(255 - dstPtr->B), (byte)(255 - dstPtr->G), (byte)(255 - dstPtr->R), dstPtr->A));
 
196
                                dstPtr++;
 
197
                        }
 
198
 
 
199
                        using (Context g = new Context (Surface)) {
 
200
                                g.AppendPath (PintaCore.Layers.SelectionPath);
 
201
                                g.FillRule = FillRule.EvenOdd;
 
202
                                g.Clip ();
 
203
 
 
204
                                g.SetSource (dest);
 
205
                                g.Paint ();
 
206
                        }
 
207
 
 
208
                        (dest as IDisposable).Dispose ();
 
209
                }
 
210
                
 
211
                public unsafe void Desaturate ()
 
212
                {
 
213
                        ImageSurface dest = Surface.Clone ();
 
214
 
 
215
                        ColorBgra* dstPtr = (ColorBgra*)dest.DataPtr;
 
216
                        int len = Surface.Data.Length / 4;
 
217
                        
 
218
                        for (int i = 0; i < len; i++) {
 
219
                                byte ib = dstPtr->GetIntensityByte();
 
220
 
 
221
                                dstPtr->R = ib;
 
222
                                dstPtr->G = ib;
 
223
                                dstPtr->B = ib;
 
224
                                dstPtr++;
 
225
                        }
 
226
 
 
227
                        using (Context g = new Context (Surface)) {
 
228
                                g.AppendPath (PintaCore.Layers.SelectionPath);
 
229
                                g.FillRule = FillRule.EvenOdd;
 
230
                                g.Clip ();
 
231
 
 
232
                                g.SetSource (dest);
 
233
                                g.Paint ();
 
234
                        }
 
235
                        
 
236
                        (dest as IDisposable).Dispose ();
 
237
                }
 
238
                
 
239
                public unsafe void AutoLevel ()
 
240
                {
 
241
                        ImageSurface dest = Surface.Clone ();
 
242
                        ColorBgra* dstPtr = (ColorBgra*)dest.DataPtr;
 
243
                        ColorBgra* srcPtr = (ColorBgra*)Surface.DataPtr;
 
244
                        
 
245
                        int len = Surface.Data.Length / 4;
 
246
 
 
247
                        UnaryPixelOps.Level levels = null;
 
248
                        
 
249
                        HistogramRgb histogram = new HistogramRgb();
 
250
                        histogram.UpdateHistogram (Surface, new Rectangle (0, 0, Surface.Width, Surface.Height));
 
251
                        levels = histogram.MakeLevelsAuto();
 
252
 
 
253
                        if (levels.isValid)
 
254
                                levels.Apply (dstPtr, srcPtr, len);
 
255
                                
 
256
                        using (Context g = new Context (Surface)) {
 
257
                                g.AppendPath (PintaCore.Layers.SelectionPath);
 
258
                                g.FillRule = FillRule.EvenOdd;
 
259
                                g.Clip ();
 
260
 
 
261
                                g.SetSource (dest);
 
262
                                g.Paint ();
 
263
                        }
 
264
 
 
265
                        (dest as IDisposable).Dispose ();
 
266
                }
 
267
 
 
268
                public void Resize (int width, int height)
 
269
                {
 
270
                        ImageSurface dest = new ImageSurface (Format.Argb32, width, height);
 
271
 
 
272
                        using (Context g = new Context (dest)) {
 
273
                                g.Scale ((double)width / (double)Surface.Width, (double)height / (double)Surface.Height);
 
274
                                g.SetSourceSurface (Surface, 0, 0);
 
275
                                g.Paint ();
 
276
                        }
 
277
 
 
278
                        (Surface as IDisposable).Dispose ();
 
279
                        Surface = dest;
 
280
                }
 
281
 
 
282
                public void ResizeCanvas (int width, int height, Anchor anchor)
 
283
                {
 
284
                        ImageSurface dest = new ImageSurface (Format.Argb32, width, height);
 
285
 
 
286
                        int delta_x = Surface.Width - width;
 
287
                        int delta_y = Surface.Height - height;
 
288
                        
 
289
                        using (Context g = new Context (dest)) {
 
290
                                switch (anchor) {
 
291
                                        case Anchor.NW:
 
292
                                                g.SetSourceSurface (Surface, 0, 0);
 
293
                                                break;
 
294
                                        case Anchor.N:
 
295
                                                g.SetSourceSurface (Surface, -delta_x / 2, 0);
 
296
                                                break;
 
297
                                        case Anchor.NE:
 
298
                                                g.SetSourceSurface (Surface, -delta_x, 0);
 
299
                                                break;
 
300
                                        case Anchor.E:
 
301
                                                g.SetSourceSurface (Surface, -delta_x, -delta_y / 2);
 
302
                                                break;
 
303
                                        case Anchor.SE:
 
304
                                                g.SetSourceSurface (Surface, -delta_x, -delta_y);
 
305
                                                break;
 
306
                                        case Anchor.S:
 
307
                                                g.SetSourceSurface (Surface, -delta_x / 2, -delta_y);
 
308
                                                break;
 
309
                                        case Anchor.SW:
 
310
                                                g.SetSourceSurface (Surface, 0, -delta_y);
 
311
                                                break;
 
312
                                        case Anchor.W:
 
313
                                                g.SetSourceSurface (Surface, 0, -delta_y / 2);
 
314
                                                break;
 
315
                                        case Anchor.Center:
 
316
                                                g.SetSourceSurface (Surface, -delta_x / 2, -delta_y / 2);
 
317
                                                break;
 
318
                                }
 
319
                                
 
320
                                g.Paint ();
 
321
                        }
 
322
 
 
323
                        (Surface as IDisposable).Dispose ();
 
324
                        Surface = dest;
 
325
                }
 
326
 
 
327
                public void Crop (Rectangle rect)
 
328
                {
 
329
                        ImageSurface dest = new ImageSurface (Format.Argb32, (int)rect.Width, (int)rect.Height);
 
330
 
 
331
                        using (Context g = new Context (dest)) {
 
332
                                g.SetSourceSurface (Surface, -(int)rect.X, -(int)rect.Y);
 
333
                                g.Paint ();
 
334
                        }
 
335
 
 
336
                        (Surface as IDisposable).Dispose ();
 
337
                        Surface = dest;
 
338
                }
 
339
        }
 
340
}