protected override void Dispose(bool disposing) { if (disposing) { if (this.disposeDocument && (this.documentCanvas.Document != null)) { PaintDotNet.Document document = this.documentCanvas.Document; this.documentCanvas.Document = null; document.Dispose(); } this.CleanupTimer(); if (this.handIcon != null) { this.handIcon.Dispose(); this.handIcon = null; } if (this.handIconMouseDown != null) { this.handIconMouseDown.Dispose(); this.handIconMouseDown = null; } if (this.components != null) { this.components.Dispose(); this.components = null; } } base.Dispose(disposing); }
private void DocumentSetImpl(PaintDotNet.Document value) { PointDouble documentScrollPosition = this.DocumentScrollPosition; this.OnDocumentChanging(value); this.SuspendRefresh(); try { if (this.document != null) { this.document.Metadata.Changed -= new EventHandler(this.DocumentMetadataChangedHandler); this.document.Invalidated -= new EventHandler <RectInt32InvalidatedEventArgs>(this.DocumentInvalidated); } this.document = value; this.documentCanvas.Document = value; if (this.document != null) { this.document.Metadata.Changed += new EventHandler(this.DocumentMetadataChangedHandler); this.document.Invalidated += new EventHandler <RectInt32InvalidatedEventArgs>(this.DocumentInvalidated); } base.Invalidate(true); this.DocumentMetadataChangedHandler(this, EventArgs.Empty); this.OnResize(EventArgs.Empty); this.OnDocumentChanged(); } finally { this.ResumeRefresh(); } this.DocumentScrollPosition = documentScrollPosition; this.RaiseCanvasLayout(); }
private void UpdateFileSizeAndPreview(string tempFileName) { if (!base.IsDisposed) { if (tempFileName == null) { string str = PdnResources.GetString("SaveConfigDialog.FileSizeText.Text.Error"); this.previewHeader.Text = string.Format(this.fileSizeTextFormat, str); } else { FileInfo info = new FileInfo(tempFileName); long length = info.Length; this.previewHeader.Text = string.Format(this.fileSizeTextFormat, SizeStringFromBytes(length)); this.canvasControl.Visible = true; using (PaintDotNet.Document document = null) { if (this.disposeDocument && (this.documentCanvas.Document != null)) { document = this.documentCanvas.Document; } if (this.fileType.IsReflexive(this.SaveConfigToken)) { this.documentCanvas.Document = this.Document; this.disposeDocument = false; } else { PaintDotNet.Document document2; FileStream input = new FileStream(tempFileName, FileMode.Open, FileAccess.Read, FileShare.Read); try { CleanupManager.RequestCleanup(); document2 = this.fileType.Load(input); } catch (Exception) { document2 = null; string str2 = PdnResources.GetString("SaveConfigDialog.FileSizeText.Text.Error"); this.previewHeader.Text = string.Format(this.fileSizeTextFormat, str2); } input.Close(); if (document2 != null) { this.documentCanvas.Document = document2; this.disposeDocument = true; } CleanupManager.RequestCleanup(); } try { info.Delete(); } catch (Exception) { } } } } }
public static void LoadProperties(Image dstImage, Document srcDoc) { Bitmap asBitmap = dstImage as Bitmap; if (asBitmap != null) { // Sometimes GDI+ does not honor the resolution tags that we // put in manually via the EXIF properties. float dpiX; float dpiY; switch (srcDoc.DpuUnit) { case MeasurementUnit.Centimeter: dpiX = (float)Document.DotsPerCmToDotsPerInch(srcDoc.DpuX); dpiY = (float)Document.DotsPerCmToDotsPerInch(srcDoc.DpuY); break; case MeasurementUnit.Inch: dpiX = (float)srcDoc.DpuX; dpiY = (float)srcDoc.DpuY; break; default: case MeasurementUnit.Pixel: dpiX = 1.0f; dpiY = 1.0f; break; } try { asBitmap.SetResolution(dpiX, dpiY); } catch (Exception) { // Ignore error } } Metadata metaData = srcDoc.Metadata; foreach (string key in metaData.GetKeys(Metadata.ExifSectionName)) { string blob = metaData.GetValue(Metadata.ExifSectionName, key); PropertyItem pi = PdnGraphics.DeserializePropertyItem(blob); try { dstImage.SetPropertyItem(pi); } catch (ArgumentException) { // Ignore error: the image does not support property items } } }
public CompositionBenchmark(string name, Document composeMe, Surface dstSurface, SetLayerInfoDelegate sliDelegate) : base(name) { this.composeMe = composeMe; this.dstSurface = dstSurface; this.sliDelegate = sliDelegate; }
protected override void Dispose(bool disposing) { if (disposing && (this.document != null)) { this.document.Dispose(); this.document = null; } base.Dispose(disposing); }
public DocumentView() { this.InitializeComponent(); this.documentCanvas.CompositionIdle += new EventHandler(this.OnDocumentCanvasCompositionIdle); this.scrollableCanvasControl.Canvas = this.documentCanvas; this.scrollableCanvasControl.CanvasView.ViewportCanvasOffsetChanged += new ValueChangedEventHandler <PointDouble>(this.OnViewportCanvasOffsetChanged); this.scrollableCanvasControl.CanvasView.ScaleRatioChanged += new ValueChangedEventHandler <double>(this.OnScaleRatioChanged); PixelGridCanvasLayer.AddIsPixelGridEnabledChangedHandler(this.scrollableCanvasControl.CanvasView, new ValueChangedEventHandler <bool>(this.OnCanvasViewIsPixelGridEnabledChanged)); this.document = null; }
protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { if (callback == null) { input.SaveToStream(output); } else { UpdateProgressTranslator upt = new UpdateProgressTranslator(ApproximateMaxOutputOffset(input), callback); input.SaveToStream(output, new IOEventHandler(upt.IOEventHandler)); } }
protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler progressCallback) { GifSaveConfigToken gsct = (GifSaveConfigToken)token; // Flatten and pre-process the image scratchSurface.Clear(ColorBgra.FromBgra(255, 255, 255, 0)); using (RenderArgs ra = new RenderArgs(scratchSurface)) { input.Render(ra, true); } for (int y = 0; y < scratchSurface.Height; ++y) { unsafe { ColorBgra* ptr = scratchSurface.GetRowAddressUnchecked(y); for (int x = 0; x < scratchSurface.Width; ++x) { if (ptr->A < gsct.Threshold) { ptr->Bgra = 0; } else { if (gsct.PreMultiplyAlpha) { int r = ((ptr->R * ptr->A) + (255 * (255 - ptr->A))) / 255; int g = ((ptr->G * ptr->A) + (255 * (255 - ptr->A))) / 255; int b = ((ptr->B * ptr->A) + (255 * (255 - ptr->A))) / 255; int a = 255; *ptr = ColorBgra.FromBgra((byte)b, (byte)g, (byte)r, (byte)a); } else { ptr->Bgra |= 0xff000000; } } ++ptr; } } } using (Bitmap quantized = Quantize(scratchSurface, gsct.DitherLevel, 255, progressCallback)) { quantized.Save(output, ImageFormat.Gif); } }
protected override unsafe void OnSave( Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback ) { DdsSaveConfigToken ddsToken = ( DdsSaveConfigToken )token; // We need to be able to feast on the goo inside.. scratchSurface.Clear( ColorBgra.Transparent ); using ( RenderArgs ra = new RenderArgs( scratchSurface ) ) { input.Render( ra, true ); } // Create the DDS file, and save it.. DdsFile ddsFile = new DdsFile(); ddsFile.Save( output, scratchSurface, ddsToken, callback ); }
public DocumentCanvasLayerView(DocumentCanvasLayer owner, PaintDotNet.Canvas.CanvasView canvasView, IList <DocumentCanvasTileCache> tileCaches) { Validate.Begin().IsNotNull <DocumentCanvasLayer>(owner, "owner").IsNotNull <PaintDotNet.Canvas.CanvasView>(canvasView, "canvasView").IsNotNull <IList <DocumentCanvasTileCache> >(tileCaches, "tileCaches").Check(); this.owner = owner; this.document = this.owner.Document; this.canvasView = canvasView; this.canvasView.IsVisibleChanged += new ValueChangedEventHandler <bool>(this.OnCanvasViewIsVisibleChanged); this.tileCaches = tileCaches; this.mipLayers = new DocumentCanvasLayerViewMipLayer[this.tileCaches.Count]; for (int i = 0; i < this.mipLayers.Length; i++) { this.mipLayers[i] = new DocumentCanvasLayerViewMipLayer(this, this.tileCaches[i].TileMathHelper.TileEdgeLog2, i, this.tileCaches[i]); } this.deviceBitmapPool = new ObjectPool <SizeInt32, IDeviceBitmap>(new Func <SizeInt32, IDeviceBitmap>(this.CreateDeviceBitmap), new Action <SizeInt32, IDeviceBitmap>(this.DisposeDeviceBitmap)); this.mipLayerZOrder = new List <DocumentCanvasLayerViewMipLayer>(); }
protected override Document OnLoad(Stream input) { // This allows us to open images that were created in Explorer using New -> Bitmap Image // which actually just creates a 0-byte file if (input.Length == 0) { Document newDoc = new Document(800, 600); Layer layer = Layer.CreateBackgroundLayer(newDoc.Width, newDoc.Height); newDoc.Layers.Add(layer); return newDoc; } else { return base.OnLoad(input); } }
public static void Save(Document input, Stream output, Surface scratchSurface, ImageFormat format, ProgressEventHandler callback) { // flatten the document scratchSurface.Clear(ColorBgra.FromBgra(0, 0, 0, 0)); using (RenderArgs ra = new RenderArgs(scratchSurface)) { input.Render(ra, true); } using (Bitmap bitmap = scratchSurface.CreateAliasedBitmap()) { LoadProperties(bitmap, input); bitmap.Save(output, format); } }
protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Bmp); EncoderParameters parms = new EncoderParameters(1); EncoderParameter parm = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 24); // BMP's should always save as 24-bit parms.Param[0] = parm; scratchSurface.Clear(ColorBgra.White); using (RenderArgs ra = new RenderArgs(scratchSurface)) { input.Render(ra, true); } // In order to save memory, we 'squish' the 32-bit bitmap down to 24-bit in-place // instead of allocating a new bitmap and copying it over. SquishSurfaceTo24Bpp(scratchSurface); using (Bitmap bitmap = CreateAliased24BppBitmap(scratchSurface)) { GdiPlusFileType.LoadProperties(bitmap, input); bitmap.Save(output, icf, parms); } }
public void Save( Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback, bool rememberToken) { if (!this.SupportsSaving) { throw new NotImplementedException("Saving is not supported by this FileType"); } else { Surface disposeMe = null; if (scratchSurface == null) { disposeMe = new Surface(input.Size); scratchSurface = disposeMe; } else if (scratchSurface.Size != input.Size) { throw new ArgumentException("scratchSurface.Size must equal input.Size"); } if (rememberToken) { Type ourType = this.GetType(); string savedTokenName = ourType.Namespace + "." + ourType.Name; SoapFormatter soap = new SoapFormatter(); MemoryStream ms = new MemoryStream(); soap.Serialize(ms, token); byte[] bytes = ms.GetBuffer(); string utf8 = Encoding.UTF8.GetString(bytes); Settings.CurrentUser.SetString(savedTokenName, utf8); } if (!this.SavesWithProgress) { try { OnSave(input, output, token, scratchSurface, null); } catch (OnSaveNotImplementedException) { OldOnSaveTrampoline(input, output, token, null); } } else { try { OnSave(input, output, token, scratchSurface, callback); } catch (OnSaveNotImplementedException) { OldOnSaveTrampoline(input, output, token, callback); } } if (disposeMe != null) { disposeMe.Dispose(); disposeMe = null; } } }
protected virtual void OnSave(Document input, Stream output, SaveConfigToken token, ProgressEventHandler callback) { }
private long ApproximateMaxOutputOffset(Document measureMe) { return (long)measureMe.Layers.Count * (long)measureMe.Width * (long)measureMe.Height * (long)ColorBgra.SizeOf; }
public void Save(Document input, Stream output, SaveConfigToken token, ProgressEventHandler callback, bool rememberToken) { using (Surface scratch = new Surface(input.Width, input.Height)) { Save(input, output, token, callback, rememberToken); } }
protected virtual void OnDocumentChanging(PaintDotNet.Document newDocument) { this.DocumentChanging.Raise <PaintDotNet.Document>(this, newDocument); }
protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { GdiPlusFileType.Save(input, output, scratchSurface, this.ImageFormat, callback); }
internal override void FinalSave( Document input, Stream output, Surface scratchSurface, int ditherLevel, SavableBitDepths bitDepth, PropertyBasedSaveConfigToken token, ProgressEventHandler progressCallback) { // finally, do the save. if (bitDepth == SavableBitDepths.Rgb24) { // In order to save memory, we 'squish' the 32-bit bitmap down to 24-bit in-place // instead of allocating a new bitmap and copying it over. SquishSurfaceTo24Bpp(scratchSurface); ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Bmp); EncoderParameters parms = new EncoderParameters(1); EncoderParameter parm = new EncoderParameter(Encoder.ColorDepth, 24); parms.Param[0] = parm; using (Bitmap bitmap = CreateAliased24BppBitmap(scratchSurface)) { GdiPlusFileType.LoadProperties(bitmap, input); bitmap.Save(output, icf, parms); } } else if (bitDepth == SavableBitDepths.Rgb8) { using (Bitmap quantized = Quantize(scratchSurface, ditherLevel, 256, false, progressCallback)) { ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Bmp); EncoderParameters parms = new EncoderParameters(1); EncoderParameter parm = new EncoderParameter(Encoder.ColorDepth, 8); parms.Param[0] = parm; GdiPlusFileType.LoadProperties(quantized, input); quantized.Save(output, icf, parms); } } else { throw new InvalidEnumArgumentException("bitDepth", (int)bitDepth, typeof(SavableBitDepths)); } }
public LayerList(Document parent) { this.parent = parent; }
protected override Document OnLoad(System.IO.Stream input) { TgaHeader header = new TgaHeader(input); bool compressed; switch (header.imageType) { case TgaType.Map: case TgaType.Rgb: case TgaType.Mono: compressed = false; break; case TgaType.RleMap: case TgaType.RleRgb: case TgaType.RleMono: compressed = true; break; default: throw new FormatException("unknown TGA image type"); } if (header.imageWidth == 0 || header.imageHeight == 0 || header.pixelDepth == 0 || header.cmapLength > 256) { throw new FormatException("bad TGA header"); } if (header.pixelDepth != 8 && header.pixelDepth != 15 && header.pixelDepth != 16 && header.pixelDepth != 24 && header.pixelDepth != 32) { throw new FormatException("bad TGA header: pixelDepth not one of {8, 15, 16, 24, 32}"); } if (header.idLength > 0) { input.Position += header.idLength; // skip descriptor } BitmapLayer layer = Layer.CreateBackgroundLayer(header.imageWidth, header.imageHeight); try { Surface surface = layer.Surface; surface.Clear((ColorBgra)0xffffffff); ColorBgra[] palette = null; if (header.cmapType != 0) { palette = LoadPalette(input, header.cmapLength); } if (header.imageType == TgaType.Mono || header.imageType == TgaType.RleMono) { palette = CreateGrayPalette(); } // Bits 0 - 3 of the image descriptor byte describe number of bits used for alpha channel // For loading, we won't worry about this. Not all TGA implementations are correct (such // as older Paint.NET TGA implementations!) and we don't want to lose all their alpha bits. //int alphaBits = header.imageDesc & 0xf; // Bits 4 & 5 of the image descriptor byte control the ordering of the pixels bool xReversed = ((header.imageDesc & 16) == 16); bool yReversed = ((header.imageDesc & 32) == 32); byte rleLeftOver = 255; // for images with illegal packet boundary for (int y = 0; y < header.imageHeight; ++y) { MemoryBlock dstRow; if (yReversed) { dstRow = surface.GetRow(y); } else { dstRow = surface.GetRow(header.imageHeight - y - 1); } if (compressed) { rleLeftOver = ExpandCompressedLine(dstRow, 0, ref header, input, header.imageWidth, y, rleLeftOver, palette); } else { ExpandUncompressedLine(dstRow, 0, ref header, input, header.imageWidth, y, 0, palette); } } if (xReversed) { MirrorX(surface); } Document document = new Document(surface.Width, surface.Height); document.Layers.Add(layer); return document; } catch { if (layer != null) { layer.Dispose(); layer = null; } throw; } }
internal override void FinalSave( Document input, Stream output, Surface scratchSurface, int ditherLevel, SavableBitDepths bitDepth, PropertyBasedSaveConfigToken token, ProgressEventHandler progressCallback) { bool rleCompress = token.GetProperty<BooleanProperty>(PropertyNames.RleCompress).Value; SaveTga(scratchSurface, output, bitDepth, rleCompress, progressCallback); }
private void OnSaveImpl( Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { HDPhotoSaveConfigToken hdToken = token as HDPhotoSaveConfigToken; WmpBitmapEncoder wbe = new WmpBitmapEncoder(); using (RenderArgs ra = new RenderArgs(scratchSurface)) { input.Render(ra, true); } MemoryBlock block = scratchSurface.Scan0; IntPtr scan0 = block.Pointer; double dpiX; double dpiY; switch (input.DpuUnit) { case MeasurementUnit.Centimeter: dpiX = Document.DotsPerCmToDotsPerInch(input.DpuX); dpiY = Document.DotsPerCmToDotsPerInch(input.DpuY); break; case MeasurementUnit.Inch: dpiX = input.DpuX; dpiY = input.DpuY; break; case MeasurementUnit.Pixel: dpiX = Document.GetDefaultDpu(MeasurementUnit.Inch); dpiY = Document.GetDefaultDpu(MeasurementUnit.Inch); break; default: throw new InvalidEnumArgumentException(); } BitmapSource bitmapSource = BitmapFrame.Create( scratchSurface.Width, scratchSurface.Height, dpiX, dpiY, System.Windows.Media.PixelFormats.Bgra32, null, scan0, (int)block.Length, // TODO: does not support >2GB images scratchSurface.Stride); FormatConvertedBitmap fcBitmap = new FormatConvertedBitmap( bitmapSource, hdToken.BitDepth == 24 ? PixelFormats.Bgr24 : PixelFormats.Bgra32, null, 0); BitmapFrame outputFrame0 = BitmapFrame.Create(fcBitmap); wbe.Frames.Add(outputFrame0); wbe.ImageQualityLevel = (float)hdToken.Quality / 100.0f; string tempFileName = FileSystem.GetTempFileName(); FileStream tempFileOut = new FileStream(tempFileName, FileMode.Create, FileAccess.Write, FileShare.Read); wbe.Save(tempFileOut); tempFileOut.Close(); tempFileOut = null; FileStream tempFileIn = new FileStream(tempFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); WmpBitmapDecoder wbd = new WmpBitmapDecoder(tempFileIn, BitmapCreateOptions.None, BitmapCacheOption.None); BitmapFrame ioFrame0 = wbd.Frames[0]; InPlaceBitmapMetadataWriter metadata2 = ioFrame0.CreateInPlaceBitmapMetadataWriter(); CopyMetadataTo(metadata2, input.Metadata); tempFileIn.Close(); tempFileIn = null; FileStream tempFileIn2 = new FileStream(tempFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); Utility.CopyStream(tempFileIn2, output); tempFileIn2.Close(); tempFileIn2 = null; try { File.Delete(tempFileName); } catch (Exception) { } // WPF doesn't give us an IDisposable implementation on its types Utility.GCFullCollect(); }
public void Save( Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback, bool rememberToken) { Tracing.LogFeature("Save(" + GetType().FullName + ")"); if (!this.SupportsSaving) { throw new NotImplementedException("Saving is not supported by this FileType"); } else { Surface disposeMe = null; if (scratchSurface == null) { disposeMe = new Surface(input.Size); scratchSurface = disposeMe; } else if (scratchSurface.Size != input.Size) { throw new ArgumentException("scratchSurface.Size must equal input.Size"); } if (rememberToken) { Type ourType = this.GetType(); string savedTokenName = "SaveConfigToken." + ourType.Namespace + "." + ourType.Name + ".BinaryFormatter"; MemoryStream ms = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); DeferredFormatter deferredFormatter = new DeferredFormatter(false, null); StreamingContext streamingContext = new StreamingContext(formatter.Context.State, deferredFormatter); formatter.Context = streamingContext; object tokenSubset = GetSerializablePortionOfSaveConfigToken(token); formatter.Serialize(ms, tokenSubset); deferredFormatter.FinishSerialization(ms); byte[] bytes = ms.GetBuffer(); string base64Bytes = Convert.ToBase64String(bytes); Settings.CurrentUser.SetString(savedTokenName, base64Bytes); } try { OnSave(input, output, token, scratchSurface, callback); } catch (OnSaveNotImplementedException) { OldOnSaveTrampoline(input, output, token, callback); } if (disposeMe != null) { disposeMe.Dispose(); disposeMe = null; } } }
protected override Document OnLoad( Stream input ) { DdsFile ddsFile = new DdsFile(); ddsFile.Load( input ); BitmapLayer layer = Layer.CreateBackgroundLayer( ddsFile.GetWidth(), ddsFile.GetHeight() ); Surface surface = layer.Surface; ColorBgra writeColour = new ColorBgra(); byte[] readPixelData = ddsFile.GetPixelData(); for ( int y = 0; y < ddsFile.GetHeight(); y++ ) { for ( int x = 0; x < ddsFile.GetWidth(); x++ ) { int readPixelOffset = ( y * ddsFile.GetWidth() * 4 ) + ( x * 4 ); writeColour.R = readPixelData[ readPixelOffset + 0 ]; writeColour.G = readPixelData[ readPixelOffset + 1 ]; writeColour.B = readPixelData[ readPixelOffset + 2 ]; writeColour.A = readPixelData[ readPixelOffset + 3 ]; surface[ x, y ] = writeColour; } } // Create a document, add the surface layer to it, and return to caller. Document document = new Document( surface.Width, surface.Height ); document.Layers.Add( layer ); return document; }
protected virtual void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { throw new OnSaveNotImplementedException("Derived classes must implement this method. It is virtual instead of abstract in order to maintain compatibility with legacy plugins."); }
protected override void OnSave( Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { switch (Thread.CurrentThread.GetApartmentState()) { // WIC does not support MTA, so we must marshal this stuff to another thread that is guaranteed to be STA. case ApartmentState.Unknown: case ApartmentState.MTA: ParameterizedThreadStart pts = new ParameterizedThreadStart(OnSaveThreadProc); OnSaveArgs osa = new OnSaveArgs(); osa.input = input; osa.output = output; osa.token = token; osa.scratchSurface = scratchSurface; osa.callback = callback; Thread staThread = new Thread(pts); staThread.SetApartmentState(ApartmentState.STA); staThread.Start(osa); staThread.Join(); if (osa.exception != null) { throw new ApplicationException("OnSaveImpl() threw an exception", osa.exception); } break; case ApartmentState.STA: OnSaveImpl(input, output, token, scratchSurface, callback); break; default: throw new InvalidOperationException(); } }
/// <summary> /// Because the old OnSave() method is obsolete, we must use reflection to call it. /// This is important for legacy FileType plugins. It allows us to ensure that no /// new plugins can be compiled using the old OnSave() overload. /// </summary> private void OldOnSaveTrampoline(Document input, Stream output, SaveConfigToken token, ProgressEventHandler callback) { MethodInfo onSave = GetType().GetMethod( "OnSave", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy, Type.DefaultBinder, new Type[] { typeof(Document), typeof(Stream), typeof(SaveConfigToken), typeof(ProgressEventHandler) }, null); onSave.Invoke( this, new object[] { input, output, token, callback }); }
private Document OnLoadImpl(Stream input) { WmpBitmapDecoder wbd = new WmpBitmapDecoder(input, BitmapCreateOptions.None, BitmapCacheOption.None); BitmapFrame frame0 = wbd.Frames[0]; Document output = new Document(frame0.PixelWidth, frame0.PixelHeight); output.DpuUnit = MeasurementUnit.Inch; output.DpuX = frame0.DpiX; output.DpuY = frame0.DpiY; BitmapLayer layer = Layer.CreateBackgroundLayer(output.Width, output.Height); MemoryBlock memoryBlock = layer.Surface.Scan0; IntPtr scan0 = memoryBlock.Pointer; FormatConvertedBitmap fcb = new FormatConvertedBitmap(frame0, System.Windows.Media.PixelFormats.Bgra32, null, 0); fcb.CopyPixels(Int32Rect.Empty, scan0, (int)memoryBlock.Length, layer.Surface.Stride); output.Layers.Add(layer); BitmapMetadata hdMetadata = (BitmapMetadata)frame0.Metadata; CopyMetadataTo(output.Metadata, hdMetadata); // WPF doesn't give us an IDisposable implementation on its types Utility.GCFullCollect(); return output; }
static void Main(string[] args) { for (int i = 0; i < args.Length; i++) { switch (args[i]) { case "/proc": if (i + 1 == args.Length) { Console.WriteLine("Use /proc <N> to specify number of processors"); return; } int numProcs; if (Int32.TryParse(args[i + 1], out numProcs)) { // only increment i if successful b/c we're going to continue the run // with the default # of processors and don't want to automatically // eat the next parameter. ++i; Processor.LogicalCpuCount = numProcs; } else { Console.WriteLine("You must specify a integer for /proc <N>, continuing with default"); } break; case "/image": if (i + 1 == args.Length) { Console.WriteLine("Use /image <filename> to specify a file to perform benchmark with"); return; } ++i; benchmarkImageName = args[i]; if (!System.IO.File.Exists(benchmarkImageName)) { Console.WriteLine("Specified image doesn't exist"); return; } break; case "/tsv": useTsvOutput = true; break; case "/?": PrintHelp(); return; default: break; } } //Processor.LogicalCpuCount = 1; Console.WriteLine("PdnBench v" + PdnInfo.GetVersion()); Console.WriteLine("Running in " + (8 * Marshal.SizeOf(typeof(IntPtr))) + "-bit mode on Windows " + Environment.OSVersion.Version.ToString() + " " + OS.Revision + (OS.Revision.Length > 0 ? " " : string.Empty) + OS.Type + " " + Processor.NativeArchitecture.ToString().ToLower()); Console.WriteLine("Processor: " + Processor.LogicalCpuCount + "x \"" + Processor.CpuName + "\" @ ~" + GetCpuSpeed() + " MHz"); Console.WriteLine("Memory: " + ((Memory.TotalPhysicalBytes / 1024) / 1024) + " MB"); Console.WriteLine(); Console.WriteLine("Using " + Processor.LogicalCpuCount + " threads."); ArrayList benchmarks = new ArrayList(); Document document; Console.Write("Loading image ... "); Stream imageStream = null; try { imageStream = (defaultImageName == benchmarkImageName) ? Assembly.GetExecutingAssembly().GetManifestResourceStream(benchmarkImageName) : new FileStream(benchmarkImageName, FileMode.Open); JpegFileType jft = new JpegFileType(); document = jft.Load(imageStream); } finally { if (imageStream != null) { imageStream.Dispose(); } } Console.WriteLine("(" + document.Width + " x " + document.Height + ") done"); Surface surface = ((BitmapLayer)document.Layers[0]).Surface; #if EFFECTS for (double i = 0; i < (2 * Math.PI); i += 70.0 * ((2 * Math.PI) / 360.0)) { benchmarks.Add( new EffectBenchmark("Rotate/Zoom at " + ((i * 180.0) / Math.PI).ToString("F2") + " degrees", 3, new PaintDotNet.Effects.RotateZoomEffect(), new PaintDotNet.Effects.RotateZoomEffectConfigToken( true, (float)(Math.PI * 0.3f), (float)((Math.PI * -0.4) + i), 50, 0.5f, new PointF(-0.2f, 0.3f), false, true), surface)); } for (int i = 1; i <= 4; i += 3) { for (int j = 10; j < 100; j += 75) { benchmarks.Add( new EffectBenchmark( "Oil Painting, brush size = " + i + ", coarseness = " + j, 1, new OilPaintingEffect(), new TwoAmountsConfigToken(i, j), surface)); } } for (int i = 2; i <= 50; i += i) { benchmarks.Add( new EffectBenchmark( "Blur with radius of " + i, 1, new BlurEffect(), new AmountEffectConfigToken(i), surface)); } for (int i = 1; i <= 4; i += 3) { benchmarks.Add( new EffectBenchmark( "Sharpen with value of " + i, 1, new SharpenEffect(), new AmountEffectConfigToken(i), surface)); } benchmarks.Add( new EffectBenchmark( "Auto-Levels", 50, new AutoLevelEffect(), null, surface)); for (int i = 81; i >= 5; i /= 3) { benchmarks.Add( new EffectBenchmark( "Clouds, roughness = " + i, 2, new CloudsEffect(), new CloudsEffectConfigToken(50, i, 12345, new UserBlendOps.NormalBlendOp()), surface)); } for (int i = 4; i <= 64; i *= 4) { benchmarks.Add( new EffectBenchmark( "Median, radius " + i, 1, new MedianEffect(), new TwoAmountsConfigToken(/*radius*/i, /*roughness*/50), surface)); } for (int i = 4; i <= 64; i *= 4) { benchmarks.Add( new EffectBenchmark( "Unfocus, radius " + i, 1, new UnfocusEffect(), new AmountEffectConfigToken(i), surface)); } benchmarks.Add( new EffectBenchmark( "Motion Blur, Horizontal", 1, new MotionBlurEffect(), new MotionBlurEffectConfigToken(0, 100, true), surface)); benchmarks.Add( new EffectBenchmark( "Motion Blur, Vertical", 1, new MotionBlurEffect(), new MotionBlurEffectConfigToken(90, 100, true), surface)); #endif Surface dst = new Surface(surface.Width * 4, surface.Height * 4); #if RESIZE // Resize benchmarks for (int i = 1; i < 8; i += 2) { int newWidth = i * (dst.Width / 8); int newHeight = i * (dst.Height / 8); Surface dstWindow = dst.CreateWindow(new Rectangle(0, 0, newWidth, newHeight)); benchmarks.Add(new ResizeBenchmark("Resize from " + surface.Width + "x" + surface.Height + " to " + newWidth + "x" + newHeight, surface, dstWindow)); benchmarks.Add(new ResizeBenchmark("Resize from " + newWidth + "x" + newHeight + " to " + surface.Width + "x" + surface.Height, dstWindow, surface)); } #endif #if GRADIENT // Gradient benchmarks benchmarks.Add(new GradientBenchmark( "Linear reflected gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.LinearReflected(false, new UserBlendOps.NormalBlendOp()), 2)); benchmarks.Add(new GradientBenchmark( "Conical gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.Conical(false, new UserBlendOps.NormalBlendOp()), 2)); benchmarks.Add(new GradientBenchmark( "Radial gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.Radial(false, new UserBlendOps.NormalBlendOp()), 2)); #endif #if COMPOSITION // Composition benchmarks Document doc1 = new Document(surface.Size); BitmapLayer layer1 = Layer.CreateBackgroundLayer(doc1.Width, doc1.Height); layer1.Surface.CopySurface(surface); doc1.Layers.Add(layer1); doc1.Layers.Add(layer1.Clone()); doc1.Layers.Add(layer1.Clone()); doc1.Layers.Add(layer1.Clone()); benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else { layer.Visible = false; } })); benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else { layer.Visible = false; } })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 (layer 0) and 128 (layer 1-3) opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing three layers, Normal+Multiply+Overlay blending, 150+255+170 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 150; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else if (layerIndex == 1) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.MultiplyBlendOp()); } else if (layerIndex == 2) { layer.Visible = true; layer.Opacity = 170; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.OverlayBlendOp()); } else { layer.Visible = false; } })); #endif #if TRANSFORM // Transform benchmarks Matrix m = new Matrix(); m.Reset(); MaskedSurface msSimple = new MaskedSurface(surface, new PdnRegion(surface.Bounds)); // simple masked surface PdnRegion complexRegion = new PdnRegion(surface.Bounds); // cut 4 holes in region 1 to form a complex clipping surface for (int x = -1; x < 3; ++x) { for (int y = -1; y < 3; ++y) { int left = (1 + (x * 3)) * (surface.Width / 6); int top = (1 + (x * 3)) * (surface.Height / 6); int right = (2 + (x * 3)) * (surface.Width / 6); int bottom = (2 + (x * 3)) * (surface.Height / 6); Rectangle rect = Rectangle.FromLTRB(left, top, right, bottom); PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(rect); complexRegion.Exclude(path); } } MaskedSurface msComplex = new MaskedSurface(surface, complexRegion); benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, false)); benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, false)); benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, true)); Matrix m2 = m.Clone(); m2.RotateAt(45.0f, new PointF(surface.Width / 2, surface.Height / 2)); benchmarks.Add(new TransformBenchmark("Transform simple surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m2, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m2, true)); Matrix m3 = m.Clone(); m3.Scale(0.5f, 0.75f); benchmarks.Add(new TransformBenchmark("Transform simple surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m3, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m3, true)); #endif #if BLIT // Blit benchmarks benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 66% (" + ZoomOutBlitBenchmark.IterationCount + "x)", surface, dst, new Size((surface.Width * 2) / 3, (surface.Height * 2) / 3))); benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 28% (" + ZoomOutBlitBenchmark.IterationCount + "x)", surface, dst, new Size((surface.Width * 28) / 100, (surface.Height * 28) / 100))); benchmarks.Add(new ZoomOneToOneBlitBenchmark("Zoom 1:1, straight blit (" + ZoomOneToOneBlitBenchmark.IterationCount + "x)", surface, dst.CreateWindow(new Rectangle(0, 0, surface.Width, surface.Height)))); #endif // Run benchmarks! Timing timing = new Timing(); ulong start = timing.GetTickCount(); foreach (Benchmark benchmark in benchmarks) { Console.Write(benchmark.Name + (useTsvOutput ? "\t" : " ... ")); TimeSpan timeSpan = benchmark.Execute(); Console.WriteLine(" " + timeSpan.TotalMilliseconds.ToString() + (useTsvOutput ? "\t" : "") + " milliseconds"); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } ulong end = timing.GetTickCount(); Console.WriteLine(); Console.WriteLine("Total time: " + (useTsvOutput ? "\t" : "") + (end - start).ToString() + (useTsvOutput ? "\t" : "") + " milliseconds"); Console.WriteLine(); }
internal override void FinalSave( Document input, Stream output, Surface scratchSurface, int ditherLevel, SavableBitDepths bitDepth, PropertyBasedSaveConfigToken token, ProgressEventHandler progressCallback) { bool enableAlpha; switch (bitDepth) { case SavableBitDepths.Rgb8: enableAlpha = false; break; case SavableBitDepths.Rgba8: enableAlpha = true; break; default: throw new InvalidEnumArgumentException("bitDepth", (int)bitDepth, typeof(SavableBitDepths)); } using (Bitmap quantized = Quantize(scratchSurface, ditherLevel, 256, enableAlpha, progressCallback)) { quantized.Save(output, ImageFormat.Gif); } }
public MetadataHistoryMementoData(PaintDotNet.Document document) { this.document = document; }
protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback) { scratchSurface.Clear(ColorBgra.FromBgra(255, 255, 255, 0)); using (RenderArgs ra = new RenderArgs(scratchSurface)) { input.Render(ra, true); } SaveTga(scratchSurface, output, token, callback); }