프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / ConvertService / ConverterService / ImageFields / BitmapTransformer.cs @ 8c128693

이력 | 보기 | 이력해설 | 다운로드 (44.8 KB)

1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Windows;
6
using System.Windows.Media.Imaging;
7
using System.Windows.Media;
8
using System.Collections.ObjectModel;
9
using System.Diagnostics;
10
using System.Security.Permissions;
11
using System.Windows.Threading;
12
using System.IO;
13

    
14
namespace ImageFields
15
{
16
    internal class BitmapTransformer
17
    {
18
        // Fields
19
        private WriteableBitmap bitmap;
20
        private KeyedCollection<string, CachedFrame> cachedFrames = new CachedFrameCollection();
21
        private KeyedCollection<string, InputNode> inputs = new InputNodeCollection();
22
        private int largeFile = 0x5f5e100;
23
        private KeyedCollection<string, OutputNode> outputs = new OutputNodeCollection();
24
        private byte[] pixelStorage;
25
        public const int TargetDpi = 0x60;
26
        private const double Tolerance = 1E-10;
27
        private int totalBlank;
28
        private int totalComposite;
29
        private int totalOutputs;
30
        private int totalSingle;
31

    
32
        // Events
33
        public event EventHandler<StreamEventArgs> InputCompleted;
34

    
35
        public event EventHandler<StreamEventArgs> InputNeeded;
36

    
37
        public event EventHandler<StreamEventArgs> OutputCompleted;
38

    
39
        public event EventHandler<StreamEventArgs> OutputNeeded;
40

    
41
        // Methods
42
        public BitmapTransformer()
43
        {
44
            this.OutputAlpha = true;
45
            this.KeepImagesInCache = true;
46
            this.StripingEnabled = true;
47
        }
48

    
49
        public void AddInput(string fileName)
50
        {
51
            if (!this.inputs.Contains(fileName))
52
            {
53
                this.inputs.Add(new InputNode(fileName));
54
            }
55
        }
56

    
57
        public void AddOutput(string fileName, int width, int height, double quality, ImageFormat format, Color backgroundColor, bool cacheFrame)
58
        {
59
            if (!this.outputs.Contains(fileName))
60
            {
61
                OutputNode item = new OutputNode(fileName)
62
                {
63
                    BackgroundColor = backgroundColor,
64
                    Width = width,
65
                    Height = height,
66
                    Quality = quality,
67
                    Format = format,
68
                    CacheFrame = cacheFrame
69
                };
70
                this.outputs.Add(item);
71
                this.totalOutputs++;
72
            }
73
        }
74

    
75
        public void AddOutputAsInput(string fileName)
76
        {
77
            if (!this.inputs.Contains(fileName) && this.cachedFrames.Contains(fileName))
78
            {
79
                InputNode node = new InputNode(fileName);
80

    
81
                   node.InputSource = this.cachedFrames[fileName].frame;
82
                   node. PixelHeight = node.InputSource.PixelHeight;
83
                    node.PixelWidth = node.InputSource.PixelWidth;
84
                    node.LastScanLineLoaded = node.PixelHeight;
85
                this.inputs.Add(node);
86
            }
87
        }
88

    
89
        public void AddTransformation(string input, string output, Rect inputRect, Rect outputRect)
90
        {
91
            Debug.Assert(!inputRect.IsEmpty, "Empty input rect");
92
            Debug.Assert(!outputRect.IsEmpty, "Empty output rect");
93
            Debug.Assert((inputRect.X >= 0.0) && (inputRect.Y >= 0.0), "Negative input rect");
94
            Debug.Assert((outputRect.X >= 0.0) && (outputRect.Y >= 0.0), "Negative output rect");
95
            if ((outputRect.Width > 0.5) && (outputRect.Height > 0.5))
96
            {
97
                Int32Rect rect = RectToInt32Rect(inputRect);
98
                if ((inputRect.Width > 0.0) && (rect.Width == 0))
99
                {
100
                    rect.Width = 1;
101
                    rect.X = (int)Math.Floor(inputRect.X);
102
                }
103
                if ((inputRect.Height > 0.0) && (rect.Height == 0))
104
                {
105
                    rect.Height = 1;
106
                    rect.Y = (int)Math.Floor(inputRect.Y);
107
                }
108
                if ((rect.Width > 0) && (rect.Height > 0))
109
                {
110
                    TransformationNode item = new TransformationNode
111
                    {
112
                        Input = input,
113
                        InputRect = rect,
114
                        OutputRect = outputRect
115
                    };
116
                    this.outputs[output].Transforms.Add(item);
117
                }
118
            }
119
        }
120

    
121
        internal PixelFormat ChoosePixelFormat(ImageFormat imageFormat)
122
        {
123
            if (((imageFormat == ImageFormat.Png) || (imageFormat == ImageFormat.Wdp)) && this.OutputAlpha)
124
            {
125
                return PixelFormats.Bgra32;
126
            }
127
            return PixelFormats.Bgr24;
128
        }
129

    
130
        public void CleanUp()
131
        {
132
            this.CloseAllInputs();
133
            this.cachedFrames.Clear();
134
            this.outputs.Clear();
135
            GC.Collect(2);
136
            GC.Collect(2);
137
        }
138

    
139
        public void CloseAllInputs()
140
        {
141
            foreach (InputNode node in this.inputs)
142
            {
143
                this.CloseInput(node.FileName);
144
            }
145
            this.bitmap = null;
146
            this.pixelStorage = null;
147
        }
148

    
149
        public void CloseInput(string fileName)
150
        {
151
            InputNode node = this.inputs[fileName];
152
            node.InputSource = null;
153
            node.FirstScanLineLoaded = 0;
154
            node.LastScanLineLoaded = 0;
155
        }
156

    
157
        [FileIOPermission(SecurityAction.LinkDemand)]
158
        public void CloseOutput(string fileName)
159
        {
160
            if (this.outputs.Contains(fileName))
161
            {
162
                this.CloseOutputImpl(this.outputs[fileName]);
163
                this.outputs.Remove(fileName);
164
            }
165
        }
166

    
167
        [FileIOPermission(SecurityAction.LinkDemand)]
168
        private void CloseOutputImpl(OutputNode outputNode)
169
        {
170
            PixelFormat format;
171
            BitmapSource source;
172
            string str;
173
            DrawingVisual visual;
174
            DrawingContext context;
175
            RenderTargetBitmap bitmap2;
176
            FormatConvertedBitmap bitmap3;
177
            WriteableBitmap bitmap4;
178
            BitmapEncoder encoder = this.GetEncoder(outputNode, out format, out str);
179
            Rect rectangle = new Rect(0.0, 0.0, (double)outputNode.Width, (double)outputNode.Height);
180
            BitmapMetadata destinationMD = null;
181
            if (this.CopyMetadata)
182
            {
183
                string containerFormat = string.Empty;
184
                switch (outputNode.Format)
185
                {
186
                    case ImageFormat.Jpg:
187
                        containerFormat = "jpg";
188
                        break;
189

    
190
                    case ImageFormat.Png:
191
                        containerFormat = "png";
192
                        break;
193

    
194
                    case ImageFormat.Wdp:
195
                        containerFormat = "wmphoto";
196
                        break;
197
                }
198
                destinationMD = new BitmapMetadata(containerFormat);
199
            }
200
            bool flag = true;
201
            if (((IsFormatOpaque(format) && (outputNode.BackgroundColor.R == Colors.Black.R)) && ((outputNode.BackgroundColor.G == Colors.Black.G) && (outputNode.BackgroundColor.B == Colors.Black.B))) || (!IsFormatOpaque(format) && (outputNode.BackgroundColor.A == Colors.Transparent.A)))
202
            {
203
                flag = false;
204
            }
205
            if (outputNode.Transforms.Count <= 0)
206
            {
207
                if (flag)
208
                {
209
                    bitmap2 = new RenderTargetBitmap(outputNode.Width, outputNode.Height, 96.0, 96.0, PixelFormats.Default);
210
                    visual = new DrawingVisual();
211
                    using (context = visual.RenderOpen())
212
                    {
213
                        context.DrawRectangle(new SolidColorBrush(outputNode.BackgroundColor), null, rectangle);
214
                    }
215
                    bitmap2.Render(visual);
216
                    bitmap3 = new FormatConvertedBitmap(bitmap2, format, null, 0.0);
217
                    source = bitmap3;
218
                }
219
                else
220
                {
221
                    bitmap4 = new WriteableBitmap(outputNode.Width, outputNode.Height, 96.0, 96.0, format, null);
222
                    source = bitmap4;
223
                }
224
                this.totalBlank++;
225
            }
226
            else
227
            {
228
                TransformationNode node = null;
229
                Rect outputRect;
230
                Int32Rect rect3;
231
                BitmapSource source2;
232
                Int32Rect inputRect;
233
                InputNode node2;
234
                BitmapSource source4;
235
                BitmapMetadata metadata;
236
                bool flag2 = true;
237
                for (int i = outputNode.Transforms.Count - 1; i > 0; i--)
238
                {
239
                    node = outputNode.Transforms[i];
240
                    if (node.OutputRect == rectangle)
241
                    {
242
                        rect3 = new Int32Rect(0, 0, 0, 0);
243
                        if (IsFormatOpaque(this.CreateInputFrame(this.inputs[node.Input], rect3).Format))
244
                        {
245
                            outputNode.Transforms.RemoveRange(0, i);
246
                            break;
247
                        }
248
                    }
249
                }
250
                if (outputNode.Transforms.Count != 1)
251
                {
252
                    flag2 = false;
253
                }
254
                if (flag2)
255
                {
256
                    node = outputNode.Transforms[0];
257
                    rect3 = new Int32Rect(0, 0, 0, 0);
258
                    BitmapSource source3 = this.CreateInputFrame(this.inputs[node.Input], rect3);
259
                    if ((source3.DpiX != 96.0) || (source3.DpiY != 96.0))
260
                    {
261
                        flag2 = false;
262
                    }
263
                    if (!RectEqualWithTolerance(node.OutputRect, rectangle))
264
                    {
265
                        flag2 = false;
266
                    }
267
                    if (!(!(outputNode.BackgroundColor != Colors.Transparent) || IsFormatOpaque(source3.Format)))
268
                    {
269
                        flag2 = false;
270
                    }
271
                }
272
                if (flag2)
273
                {
274
                    node = outputNode.Transforms[0];
275
                    outputRect = node.OutputRect;
276
                    inputRect = node.InputRect;
277
                    node2 = this.inputs[node.Input];
278
                    source2 = this.CreateInputFrame(node2, inputRect);
279
                    if (!this.KeepImagesInCache)
280
                    {
281
                        this.CloseInput(node.Input);
282
                    }
283
                    inputRect.Y -= node2.FirstScanLineLoaded;
284
                    source4 = ScaleAndCropBitmap(ref outputRect, ref inputRect, source2);
285
                    if (source2.Format != format)
286
                    {
287
                        source4 = new FormatConvertedBitmap(source4, format, null, 0.0);
288
                    }
289
                    if (this.CopyMetadata)
290
                    {
291
                        metadata = (BitmapMetadata)source2.Metadata;
292
                        if (metadata != null)
293
                        {
294
                            CopyBitmapMetadata(metadata, destinationMD);
295
                        }
296
                    }
297
                    source = source4;
298
                    this.totalSingle++;
299
                }
300
                else
301
                {
302
                    bool flag3 = flag;
303
                    if (!flag3)
304
                    {
305
                        foreach (TransformationNode item in outputNode.Transforms)
306
                        {
307
                            rect3 = new Int32Rect(0, 0, 0, 0);
308
                            source2 = this.CreateInputFrame(this.inputs[item.Input], rect3);
309
                            if (!(IsFormatOpaque(source2.Format) && (source2.DpiX == source2.DpiY)))
310
                            {
311
                                flag3 = true;
312
                                break;
313
                            }
314
                        }
315
                    }
316
                    if (flag3)
317
                    {
318
                        visual = new DrawingVisual();
319
                        using (context = visual.RenderOpen())
320
                        {
321
                            if (flag)
322
                            {
323
                                context.DrawRectangle(new SolidColorBrush(outputNode.BackgroundColor), null, rectangle);
324
                            }
325
                            foreach (TransformationNode item in outputNode.Transforms)
326
                            {
327
                                outputRect = item.OutputRect;
328
                                inputRect = item.InputRect;
329
                                node2 = this.inputs[item.Input];
330
                                source2 = this.CreateInputFrame(node2, inputRect);
331
                                if (!this.KeepImagesInCache)
332
                                {
333
                                    this.CloseInput(node.Input);
334
                                }
335
                                if (this.CopyMetadata)
336
                                {
337
                                    metadata = (BitmapMetadata)source2.Metadata;
338
                                    if (metadata != null)
339
                                    {
340
                                        CopyBitmapMetadata(metadata, destinationMD);
341
                                    }
342
                                }
343
                                inputRect.Y -= node2.FirstScanLineLoaded;
344
                                if (source2.DpiX == source2.DpiY)
345
                                {
346
                                    source4 = ScaleAndCropBitmap(ref outputRect, ref inputRect, source2);
347
                                    context.DrawImage(source4, outputRect);
348
                                }
349
                                else
350
                                {
351
                                    Rect r = Int32RectToRect(inputRect);
352
                                    if (source2.DpiX > source2.DpiY)
353
                                    {
354
                                        r.Scale(1.0, source2.DpiX / source2.DpiY);
355
                                    }
356
                                    else
357
                                    {
358
                                        r.Scale(source2.DpiY / source2.DpiX, 1.0);
359
                                    }
360
                                    Int32Rect sourceRect = RectToInt32Rect(r);
361
                                    CroppedBitmap imageSource = new CroppedBitmap(source2, sourceRect);
362
                                    context.DrawImage(imageSource, outputRect);
363
                                }
364
                            }
365
                            context.Close();
366
                        }
367
                        bitmap2 = new RenderTargetBitmap(outputNode.Width, outputNode.Height, 96.0, 96.0, PixelFormats.Default);
368
                        bitmap2.Render(visual);
369
                        bitmap3 = new FormatConvertedBitmap(bitmap2, format, null, 0.0);
370
                        source = bitmap3;
371
                    }
372
                    else
373
                    {
374
                        bitmap4 = new WriteableBitmap(outputNode.Width, outputNode.Height, 96.0, 96.0, format, null);
375
                        foreach (TransformationNode item in outputNode.Transforms)
376
                        {
377
                            outputRect = item.OutputRect;
378
                            inputRect = item.InputRect;
379
                            node2 = this.inputs[item.Input];
380
                            source2 = this.CreateInputFrame(node2, inputRect);
381
                            if (!this.KeepImagesInCache)
382
                            {
383
                                this.CloseInput(node.Input);
384
                            }
385
                            if (this.CopyMetadata)
386
                            {
387
                                metadata = (BitmapMetadata)source2.Metadata;
388
                                if (metadata != null)
389
                                {
390
                                    CopyBitmapMetadata(metadata, destinationMD);
391
                                }
392
                            }
393
                            inputRect.Y -= node2.FirstScanLineLoaded;
394
                            Int32Rect rect7 = RectToInt32Rect(outputRect);
395
                            if ((rect7.Width > 0) && (rect7.Height > 0))
396
                            {
397
                                var _rec = Int32RectToRect(rect7);
398
                                source4 = ScaleAndCropBitmap(ref _rec, ref inputRect, source2);
399
                                if (source2.Format != format)
400
                                {
401
                                    source4 = new FormatConvertedBitmap(source4, format, null, 0.0);
402
                                }
403
                                int num2 = (source4.PixelWidth * source4.PixelHeight) * 4;
404
                                if ((this.pixelStorage == null) || (this.pixelStorage.Length < num2))
405
                                {
406
                                    this.pixelStorage = new byte[num2];
407
                                }
408
                                int stride = ((rect7.Width * format.BitsPerPixel) + 7) / 8;
409
                                source4.CopyPixels(this.pixelStorage, stride, 0);
410
                                bitmap4.WritePixels(rect7, this.pixelStorage, stride, 0);
411
                            }
412
                        }
413
                        source = bitmap4;
414
                    }
415
                    this.totalComposite++;
416
                }
417
            }
418
            List<ColorContext> list = new List<ColorContext> {
419
            new ColorContext(format)
420
        };
421
            BitmapFrame frameToCache = BitmapFrame.Create(source, null, destinationMD, null);
422
            if (outputNode.CacheFrame)
423
            {
424
                this.cachedFrames.Add(new CachedFrame(outputNode.FileName, frameToCache));
425
            }
426
            encoder.Frames.Add(frameToCache);
427
            StreamEventArgs e = new StreamEventArgs(outputNode.FileName)
428
            {
429
                MimeType = str,
430
                Compress = false,
431
                Progress = ((double)((this.totalBlank + this.totalComposite) + this.totalSingle)) / ((double)this.totalOutputs)
432
            };
433
            EventHandler<StreamEventArgs> outputNeeded = this.OutputNeeded;
434
            if (outputNeeded == null)
435
            {
436
                using (FileStream stream = new FileStream(outputNode.FileName, FileMode.Create))
437
                {
438
                    encoder.Save(stream);
439
                    stream.Flush();
440
                }
441
            }
442
            else
443
            {
444
                outputNeeded(this, e);
445
                encoder.Save(e.Stream);
446
                e.Stream.Flush();
447
            }
448
            EventHandler<StreamEventArgs> outputCompleted = this.OutputCompleted;
449
            if (outputCompleted != null)
450
            {
451
                outputCompleted(this, e);
452
            }
453
            outputNode.Transforms.Clear();
454
        }
455

    
456
        private static void CopyBitmapMetadata(BitmapMetadata sourceMD, BitmapMetadata destinationMD)
457
        {
458
            if (destinationMD.Format == sourceMD.Format)
459
            {
460
                destinationMD.SetQuery("/", sourceMD);
461
            }
462
            else
463
            {
464
                if (sourceMD.DateTaken != null)
465
                {
466
                    destinationMD.DateTaken = sourceMD.DateTaken;
467
                }
468
                if ((destinationMD.Format != "png") && (sourceMD.Format != "png"))
469
                {
470
                    if (sourceMD.ApplicationName != null)
471
                    {
472
                        destinationMD.ApplicationName = sourceMD.ApplicationName;
473
                    }
474
                    if (sourceMD.Author != null)
475
                    {
476
                        destinationMD.Author = sourceMD.Author;
477
                    }
478
                    if (sourceMD.CameraManufacturer != null)
479
                    {
480
                        destinationMD.CameraManufacturer = sourceMD.CameraManufacturer;
481
                    }
482
                    if (sourceMD.CameraModel != null)
483
                    {
484
                        destinationMD.CameraModel = sourceMD.CameraModel;
485
                    }
486
                    if (sourceMD.Comment != null)
487
                    {
488
                        destinationMD.Comment = sourceMD.Comment;
489
                    }
490
                    if (sourceMD.Copyright != null)
491
                    {
492
                        destinationMD.Copyright = sourceMD.Copyright;
493
                    }
494
                    if (sourceMD.Keywords != null)
495
                    {
496
                        destinationMD.Keywords = sourceMD.Keywords;
497
                    }
498
                    destinationMD.Rating = sourceMD.Rating;
499
                    if (sourceMD.Subject != null)
500
                    {
501
                        destinationMD.Subject = sourceMD.Subject;
502
                    }
503
                    if (sourceMD.Title != null)
504
                    {
505
                        destinationMD.Title = sourceMD.Title;
506
                    }
507
                }
508
            }
509
        }
510

    
511
        internal BitmapDecoder CreateBitmapDecoder(StreamEventArgs streamEventArgs, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption)
512
        {
513
            BitmapDecoder decoder = null;
514
            string absoluteUri;
515
            NotSupportedException exception;
516
            if (this.InputNeeded == null)
517
            {
518
                Uri bitmapUri = new Uri(streamEventArgs.FileName, UriKind.RelativeOrAbsolute);
519
                absoluteUri = bitmapUri.AbsoluteUri;
520
                try
521
                {
522
                    decoder = BitmapDecoder.Create(bitmapUri, createOptions, cacheOption);
523
                }
524
                catch (NotSupportedException exception1)
525
                {
526
                    exception = exception1;
527
                    throw new InvalidDataException("File is not in an image format '" + absoluteUri + "'. Exception message: " + exception.Message);
528
                }
529
                catch (OutOfMemoryException)
530
                {
531
                    decoder = BitmapDecoder.Create(bitmapUri, BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.None);
532
                }
533
            }
534
            else
535
            {
536
                absoluteUri = streamEventArgs.FileName;
537
                this.InputNeeded(this, streamEventArgs);
538
                try
539
                {
540
                    decoder = BitmapDecoder.Create(streamEventArgs.Stream, createOptions, cacheOption);
541
                }
542
                catch (NotSupportedException exception3)
543
                {
544
                    exception = exception3;
545
                    throw new InvalidDataException("File is not in an image format '" + absoluteUri + "'. Exception message: " + exception.Message);
546
                }
547
            }
548
            if (decoder.IsDownloading)
549
            {
550
                bool downloadFailed = false;
551
                DispatcherFrame frame = new DispatcherFrame();
552
                decoder.DownloadCompleted += delegate
553
                {
554
                    frame.Continue = false;
555
                };
556
                decoder.DownloadFailed += delegate
557
                {
558
                    downloadFailed = true;
559
                    frame.Continue = false;
560
                };
561
                Dispatcher.PushFrame(frame);
562
                if (downloadFailed)
563
                {
564
                    throw new InvalidDataException("Download failed '" + absoluteUri + "'.");
565
                }
566
            }
567
            return decoder;
568
        }
569

    
570
        private BitmapSource CreateInputFrame(InputNode inputNode, Int32Rect rectNeeded)
571
        {
572
            bool flag = false;
573
            if ((inputNode.InputSource == null) || (!rectNeeded.IsEmpty && ((rectNeeded.Y < inputNode.FirstScanLineLoaded) || ((rectNeeded.Height + rectNeeded.Y) > inputNode.LastScanLineLoaded))))
574
            {
575
                if (inputNode.InputSource != null)
576
                {
577
                    inputNode.InputSource = null;
578
                    inputNode.FirstScanLineLoaded = 0;
579
                    inputNode.LastScanLineLoaded = 0;
580
                    GC.Collect(2);
581
                    GC.Collect(2);
582
                }
583
                BitmapDecoder decoder = null;
584
                StreamEventArgs streamEventArgs = new StreamEventArgs(inputNode.FileName);
585
                decoder = this.CreateBitmapDecoder(streamEventArgs, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
586
                if (!rectNeeded.IsEmpty)
587
                {
588
                    inputNode.FirstScanLineLoaded = 0;
589
                    inputNode.LastScanLineLoaded = decoder.Frames[0].PixelHeight;
590
                }
591
                bool flag2 = false;
592
                if ((this.LargeFile != 0) && ((decoder.Frames[0].PixelWidth * rectNeeded.Height) <= this.LargeFile))
593
                {
594
                    flag2 = true;
595
                }
596
                bool flag3 = false;
597
                if ((decoder.Frames[0].PixelHeight * decoder.Frames[0].PixelWidth) > this.LargeFile)
598
                {
599
                    flag3 = true;
600
                }
601
                if ((this.LargeFile != 0) && flag3)
602
                {
603
                    if ((!rectNeeded.IsEmpty && this.StripingEnabled) && flag2)
604
                    {
605
                        flag = true;
606
                    }
607
                    decoder = this.CreateBitmapDecoder(streamEventArgs, BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.None);
608
                }
609
                BitmapSource frame = decoder.Frames[0];
610
                StraightenFrame(ref frame);
611
                inputNode.PixelHeight = frame.PixelHeight;
612
                inputNode.PixelWidth = frame.PixelWidth;
613
                inputNode.Format = frame.Format;
614
                inputNode.Palette = frame.Palette;
615
                inputNode.InputSource = frame;
616
                if (flag)
617
                {
618
                    int num = (int)Math.Ceiling((double)((inputNode.PixelHeight * inputNode.PixelWidth) / ((double)this.LargeFile)));
619
                    int pixelHeight = (int)Math.Round((double)(((double)inputNode.PixelHeight) / ((double)num)));
620
                    int num3 = (int)Math.Truncate((double)(((double)rectNeeded.Y) / ((double)pixelHeight)));
621
                    inputNode.FirstScanLineLoaded = pixelHeight * num3;
622
                    inputNode.LastScanLineLoaded = Math.Min(inputNode.FirstScanLineLoaded + pixelHeight, inputNode.PixelHeight);
623
                    if ((inputNode.FirstScanLineLoaded > rectNeeded.Y) || (inputNode.LastScanLineLoaded < (rectNeeded.Height + rectNeeded.Y)))
624
                    {
625
                        inputNode.FirstScanLineLoaded = rectNeeded.Y;
626
                        inputNode.LastScanLineLoaded = rectNeeded.Height + rectNeeded.Y;
627
                        pixelHeight = inputNode.LastScanLineLoaded - inputNode.FirstScanLineLoaded;
628
                    }
629
                    Int32Rect sourceRect = new Int32Rect(0, inputNode.FirstScanLineLoaded, inputNode.PixelWidth, inputNode.LastScanLineLoaded - inputNode.FirstScanLineLoaded);
630
                    if (((this.bitmap == null) || (this.bitmap.PixelHeight < pixelHeight)) || (this.bitmap.PixelWidth < inputNode.PixelWidth))
631
                    {
632
                        if (this.bitmap != null)
633
                        {
634
                            this.bitmap = null;
635
                            GC.Collect();
636
                            GC.Collect();
637
                        }
638
                        this.bitmap = new WriteableBitmap(inputNode.PixelWidth, pixelHeight, 96.0, 96.0, inputNode.Format, inputNode.Palette);
639
                    }
640
                    int stride = ((inputNode.PixelWidth * inputNode.Format.BitsPerPixel) + 7) / 8;
641
                    int num5 = stride * pixelHeight;
642
                    byte[] pixels = new byte[num5];
643
                    frame.CopyPixels(sourceRect, pixels, stride, 0);
644
                    frame = null;
645
                    sourceRect.Y = 0;
646
                    this.bitmap.WritePixels(sourceRect, pixels, stride, 0);
647
                    inputNode.InputSource = this.bitmap;
648
                    inputNode.Format = this.bitmap.Format;
649
                    inputNode.Palette = this.bitmap.Palette;
650
                    GC.Collect(2);
651
                    GC.Collect(2);
652
                }
653
                if (this.InputCompleted != null)
654
                {
655
                    this.InputCompleted(this, streamEventArgs);
656
                }
657
            }
658
            return inputNode.InputSource;
659
        }
660

    
661
        [FileIOPermission(SecurityAction.LinkDemand)]
662
        public void Execute()
663
        {
664
            Debug.WriteLine("Inputs:" + this.inputs.Count);
665
            Debug.WriteLine("Outputs:" + this.outputs.Count);
666
            int num = 0;
667
            foreach (OutputNode node in this.outputs)
668
            {
669
                this.CloseOutputImpl(node);
670
                num++;
671
                if ((num % 30) == 0)
672
                {
673
                    GC.Collect(2);
674
                }
675
            }
676
            this.outputs.Clear();
677
            Debug.WriteLine("Single Outputs written:" + this.totalSingle);
678
            Debug.WriteLine("Composite Outputs written:" + this.totalComposite);
679
            Debug.WriteLine("Blank Outputs written:" + this.totalBlank);
680
        }
681

    
682
        public Point GetDpi(string fileName)
683
        {
684
            Int32Rect rectNeeded = new Int32Rect(0, 0, 0, 0);
685
            BitmapSource source = this.CreateInputFrame(this.inputs[fileName], rectNeeded);
686
            return new Point(source.DpiX, source.DpiY);
687
        }
688

    
689
        private BitmapEncoder GetEncoder(OutputNode outputNode, out PixelFormat pixelFormat, out string mimeType)
690
        {
691
            pixelFormat = this.ChoosePixelFormat(outputNode.Format);
692
            switch (outputNode.Format)
693
            {
694
                case ImageFormat.Jpg:
695
                    {
696
                        JpegBitmapEncoder encoder = new JpegBitmapEncoder
697
                        {
698
                            QualityLevel = 1 + ((int)Math.Round((double)(outputNode.Quality * 99.0)))
699
                        };
700
                        mimeType = "image/jpeg";
701
                        return encoder;
702
                    }
703
                case ImageFormat.Png:
704
                    mimeType = "image/png";
705
                    return new PngBitmapEncoder();
706

    
707
                case ImageFormat.Wdp:
708
                    {
709
                        WmpBitmapEncoder encoder2 = new WmpBitmapEncoder
710
                        {
711
                            QualityLevel = (byte)Math.Round((double)(105.0 - (outputNode.Quality * 100.0)))
712
                        };
713
                        if (outputNode.Quality == 1.0)
714
                        {
715
                            encoder2.QualityLevel = 1;
716
                        }
717
                        encoder2.OverlapLevel = 0;
718
                        encoder2.InterleavedAlpha = true;
719
                        encoder2.UseCodecOptions = true;
720
                        mimeType = "image/vnd.ms-photo";
721
                        return encoder2;
722
                    }
723
            }
724
            pixelFormat = PixelFormats.Default;
725
            mimeType = "";
726
            return null;
727
        }
728

    
729
        public PixelFormat GetPixelFormat(string fileName)
730
        {
731
            Int32Rect rectNeeded = new Int32Rect(0, 0, 0, 0);
732
            return this.CreateInputFrame(this.inputs[fileName], rectNeeded).Format;
733
        }
734

    
735
        public Point GetPixelSize(string fileName)
736
        {
737
            Int32Rect rectNeeded = new Int32Rect(0, 0, 0, 0);
738
            InputNode inputNode = this.inputs[fileName];
739
            this.CreateInputFrame(inputNode, rectNeeded);
740
            return new Point((double)inputNode.PixelWidth, (double)inputNode.PixelHeight);
741
        }
742

    
743
        public static Rect Int32RectToRect(Int32Rect r)
744
        {
745
            if (r.IsEmpty)
746
            {
747
                return Rect.Empty;
748
            }
749
            return new Rect((double)r.X, (double)r.Y, (double)r.Width, (double)r.Height);
750
        }
751

    
752
        private static bool IsFormatOpaque(PixelFormat pixelFormat)
753
        {
754
            return ((((((pixelFormat == PixelFormats.Bgr101010) || (pixelFormat == PixelFormats.Bgr24)) || ((pixelFormat == PixelFormats.Bgr32) || (pixelFormat == PixelFormats.Bgr555))) || (((pixelFormat == PixelFormats.Bgr565) || (pixelFormat == PixelFormats.BlackWhite)) || ((pixelFormat == PixelFormats.Cmyk32) || (pixelFormat == PixelFormats.Gray16)))) || ((((pixelFormat == PixelFormats.Gray2) || (pixelFormat == PixelFormats.Gray32Float)) || ((pixelFormat == PixelFormats.Gray4) || (pixelFormat == PixelFormats.Gray8))) || ((pixelFormat == PixelFormats.Rgb128Float) || (pixelFormat == PixelFormats.Rgb24)))) || (pixelFormat == PixelFormats.Rgb48));
755
        }
756

    
757
        public bool IsOpaque(string fileName)
758
        {
759
            return IsFormatOpaque(this.GetPixelFormat(fileName));
760
        }
761

    
762
        private static bool RectEqualWithTolerance(Rect a, Rect b)
763
        {
764
            return ((a == b) || ((((Math.Abs((double)(a.X - b.X)) < 1E-10) && (Math.Abs((double)(a.Y - b.Y)) < 1E-10)) && (Math.Abs((double)(a.Width - b.Width)) < 1E-10)) && (Math.Abs((double)(a.Height - b.Height)) < 1E-10)));
765
        }
766

    
767
        public static Int32Rect RectToInt32Rect(Rect r)
768
        {
769
            int x = (int)Math.Round(r.X);
770
            int y = (int)Math.Round(r.Y);
771
            int width = ((int)Math.Round(r.Right)) - x;
772
            return new Int32Rect(x, y, width, ((int)Math.Round(r.Bottom)) - y);
773
        }
774

    
775
        private static BitmapSource ScaleAndCropBitmap(ref Rect outputRect, ref Int32Rect inputRect, BitmapSource inputSource)
776
        {
777
            bool flag = (Math.Round(outputRect.Width) != inputRect.Width) || (Math.Round(outputRect.Height) != inputRect.Height);
778
            bool flag2 = (((inputRect.X != 0) || (inputRect.Y != 0)) || (inputRect.Width != inputSource.PixelWidth)) || (inputRect.Height != inputSource.PixelHeight);
779
            BitmapSource source = inputSource;
780
            if (flag2)
781
            {
782
                source = new CroppedBitmap(source, inputRect);
783
            }
784
            if (flag)
785
            {
786
                ScaleTransform newTransform = new ScaleTransform(outputRect.Width / ((double)inputRect.Width), outputRect.Height / ((double)inputRect.Height));
787
                source = new TransformedBitmap(source, newTransform);
788
            }
789
            return source;
790
        }
791

    
792
        internal static bool StraightenFrame(ref BitmapSource frame)
793
        {
794
            bool flag = false;
795
            BitmapMetadata metadata = (BitmapMetadata)frame.Metadata;
796
            if ((metadata != null) && metadata.ContainsQuery("/app1/ifd/exif:{uint=274}"))
797
            {
798
                int angle = 0;
799
                object query = metadata.GetQuery("/app1/ifd/exif:{uint=274}");
800
                if (query.GetType() == typeof(ushort))
801
                {
802
                    switch (((ushort)query))
803
                    {
804
                        case 6:
805
                            angle = 90;
806
                            break;
807

    
808
                        case 8:
809
                            angle = 270;
810
                            break;
811

    
812
                        case 3:
813
                            angle = 180;
814
                            break;
815
                    }
816
                }
817
                if (angle != 0)
818
                {
819
                    RotateTransform newTransform = new RotateTransform(angle, ((double)frame.PixelWidth) / 2.0, ((double)frame.PixelHeight) / 2.0);
820
                    BitmapSource source = new TransformedBitmap(frame, newTransform);
821
                    BitmapMetadata metadata2 = metadata.Clone();
822
                    metadata2.SetQuery("/app1/ifd/exif:{uint=274}", (ushort)1);
823
                    switch (angle)
824
                    {
825
                        case 90:
826
                        case 270:
827
                            {
828
                                flag = true;
829
                                object obj3 = null;
830
                                object obj4 = null;
831
                                if (metadata2.ContainsQuery("/app1/ifd/exif:{uint=282}"))
832
                                {
833
                                    obj3 = metadata2.GetQuery("/app1/ifd/exif:{uint=282}");
834
                                }
835
                                if (metadata2.ContainsQuery("/app1/ifd/exif:{uint=283}"))
836
                                {
837
                                    obj4 = metadata2.GetQuery("/app1/ifd/exif:{uint=283}");
838
                                }
839
                                if (obj3 != null)
840
                                {
841
                                    metadata2.SetQuery("/app1/ifd/exif:{uint=283}", obj3);
842
                                }
843
                                else
844
                                {
845
                                    metadata2.RemoveQuery("/app1/ifd/exif:{uint=283}");
846
                                }
847
                                if (obj4 != null)
848
                                {
849
                                    metadata2.SetQuery("/app1/ifd/exif:{uint=282}", obj4);
850
                                }
851
                                else
852
                                {
853
                                    metadata2.RemoveQuery("/app1/ifd/exif:{uint=282}");
854
                                }
855
                                object obj5 = null;
856
                                object obj6 = null;
857
                                if (metadata2.ContainsQuery("/app1/ifd/exif/subifd:{uint=40962}"))
858
                                {
859
                                    obj5 = metadata2.GetQuery("/app1/ifd/exif/subifd:{uint=40962}");
860
                                }
861
                                if (metadata2.ContainsQuery("/app1/ifd/exif/subifd:{uint=40963}"))
862
                                {
863
                                    obj6 = metadata2.GetQuery("/app1/ifd/exif/subifd:{uint=40963}");
864
                                }
865
                                if (obj5 != null)
866
                                {
867
                                    metadata2.SetQuery("/app1/ifd/exif/subifd:{uint=40963}", obj5);
868
                                }
869
                                else
870
                                {
871
                                    metadata2.RemoveQuery("/app1/ifd/exif/subifd:{uint=40963}");
872
                                }
873
                                if (obj6 != null)
874
                                {
875
                                    metadata2.SetQuery("/app1/ifd/exif/subifd:{uint=40962}", obj6);
876
                                }
877
                                else
878
                                {
879
                                    metadata2.RemoveQuery("/app1/ifd/exif/subifd:{uint=40962}");
880
                                }
881
                                break;
882
                            }
883
                    }
884
                    frame = source;
885
                }
886
            }
887
            return flag;
888
        }
889

    
890
        // Properties
891
        public bool CopyMetadata { get; set; }
892

    
893
        public bool KeepImagesInCache { get; set; }
894

    
895
        public int LargeFile
896
        {
897
            get
898
            {
899
                return this.largeFile;
900
            }
901
            set
902
            {
903
                this.largeFile = value;
904
            }
905
        }
906

    
907
        public bool OutputAlpha { get; set; }
908

    
909
        public bool StripingEnabled { get; set; }
910

    
911
        // Nested Types
912
        private class CachedFrameCollection : KeyedCollection<string, CachedFrame>
913
        {
914
            // Methods
915
            protected override string GetKeyForItem(CachedFrame item)
916
            {
917
                return item.path;
918
            }
919
        }
920

    
921
        private class InputNode
922
        {
923
            // Fields
924
            private string fileName;
925
            private int firstScanLineLoaded;
926
            private int lastScanLineLoaded;
927

    
928
            // Methods
929
            public InputNode(string fileName)
930
            {
931
                this.fileName = fileName;
932
                this.PixelHeight = 0;
933
                this.PixelWidth = 0;
934
                this.firstScanLineLoaded = 0;
935
                this.lastScanLineLoaded = 0;
936
                this.Format = PixelFormats.Default;
937
                this.Palette = null;
938
            }
939

    
940
            // Properties
941
            public string FileName
942
            {
943
                get
944
                {
945
                    return this.fileName;
946
                }
947
            }
948

    
949
            public int FirstScanLineLoaded
950
            {
951
                get
952
                {
953
                    return this.firstScanLineLoaded;
954
                }
955
                set
956
                {
957
                    this.firstScanLineLoaded = value;
958
                }
959
            }
960

    
961
            public PixelFormat Format { get; set; }
962

    
963
            public BitmapSource InputSource { get; set; }
964

    
965
            public int LastScanLineLoaded
966
            {
967
                get
968
                {
969
                    return this.lastScanLineLoaded;
970
                }
971
                set
972
                {
973
                    this.lastScanLineLoaded = value;
974
                }
975
            }
976

    
977
            public BitmapPalette Palette { get; set; }
978

    
979
            public int PixelHeight { get; set; }
980

    
981
            public int PixelWidth { get; set; }
982
        }
983

    
984
        private class InputNodeCollection : KeyedCollection<string, BitmapTransformer.InputNode>
985
        {
986
            // Methods
987
            protected override string GetKeyForItem(BitmapTransformer.InputNode item)
988
            {
989
                return item.FileName;
990
            }
991
        }
992

    
993
        private class OutputNode
994
        {
995
            // Fields
996
            private Color backgroundColor;
997
            public bool CacheFrame;
998
            private string fileName;
999
            private ImageFormat format;
1000
            private int height;
1001
            private double quality;
1002
            private List<BitmapTransformer.TransformationNode> transforms;
1003
            private int width;
1004

    
1005
            // Methods
1006
            public OutputNode(string fileName)
1007
            {
1008
                this.fileName = fileName;
1009
                this.transforms = new List<BitmapTransformer.TransformationNode>();
1010
                this.CacheFrame = false;
1011
            }
1012

    
1013
            // Properties
1014
            public Color BackgroundColor
1015
            {
1016
                get
1017
                {
1018
                    return this.backgroundColor;
1019
                }
1020
                set
1021
                {
1022
                    this.backgroundColor = value;
1023
                }
1024
            }
1025

    
1026
            public string FileName
1027
            {
1028
                get
1029
                {
1030
                    return this.fileName;
1031
                }
1032
            }
1033

    
1034
            public ImageFormat Format
1035
            {
1036
                get
1037
                {
1038
                    return this.format;
1039
                }
1040
                set
1041
                {
1042
                    this.format = value;
1043
                }
1044
            }
1045

    
1046
            public int Height
1047
            {
1048
                get
1049
                {
1050
                    return this.height;
1051
                }
1052
                set
1053
                {
1054
                    Debug.Assert(value > 0, "Height must be greater than 0.");
1055
                    this.height = value;
1056
                }
1057
            }
1058

    
1059
            public double Quality
1060
            {
1061
                get
1062
                {
1063
                    return this.quality;
1064
                }
1065
                set
1066
                {
1067
                    Debug.Assert((value >= 0.0) && (value <= 1.0), "Quality must be between 0 and 1.");
1068
                    this.quality = value;
1069
                }
1070
            }
1071

    
1072
            public List<BitmapTransformer.TransformationNode> Transforms
1073
            {
1074
                get
1075
                {
1076
                    return this.transforms;
1077
                }
1078
            }
1079

    
1080
            public int Width
1081
            {
1082
                get
1083
                {
1084
                    return this.width;
1085
                }
1086
                set
1087
                {
1088
                    Debug.Assert(value > 0, "Width must be greater than 0.");
1089
                    this.width = value;
1090
                }
1091
            }
1092
        }
1093

    
1094
        private class OutputNodeCollection : KeyedCollection<string, BitmapTransformer.OutputNode>
1095
        {
1096
            // Methods
1097
            protected override string GetKeyForItem(BitmapTransformer.OutputNode item)
1098
            {
1099
                return item.FileName;
1100
            }
1101
        }
1102

    
1103
        private class TransformationNode
1104
        {
1105
            // Fields
1106
            private string input;
1107
            private Int32Rect inputRect;
1108
            private Rect outputRect;
1109

    
1110
            // Properties
1111
            public string Input
1112
            {
1113
                get
1114
                {
1115
                    return this.input;
1116
                }
1117
                set
1118
                {
1119
                    this.input = value;
1120
                }
1121
            }
1122

    
1123
            public Int32Rect InputRect
1124
            {
1125
                get
1126
                {
1127
                    return this.inputRect;
1128
                }
1129
                set
1130
                {
1131
                    this.inputRect = value;
1132
                }
1133
            }
1134

    
1135
            public Rect OutputRect
1136
            {
1137
                get
1138
                {
1139
                    return this.outputRect;
1140
                }
1141
                set
1142
                {
1143
                    this.outputRect = value;
1144
                }
1145
            }
1146
        }
1147
    }
1148

    
1149
 
1150

    
1151
}
클립보드 이미지 추가 (최대 크기: 500 MB)