///////////////////////////////////////////////////////////////////////////////// // Paint.NET // // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. // // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. // // See license-pdn.txt for full licensing and attribution details. // // // // Ported to Pinta by: Krzysztof Marecki // ///////////////////////////////////////////////////////////////////////////////// using System; using System.Collections.Generic; using System.ComponentModel; using Cairo; using Pinta.Core; namespace Pinta.Effects { //[System.ComponentModel.Composition (typeof (BaseEffect))] public class CurvesEffect : BaseEffect { UnaryPixelOp op = null; public override string Icon { get { return "Menu.Adjustments.Curves.png"; } } public override string Text { get { return Mono.Unix.Catalog.GetString ("Curves"); } } public override bool IsConfigurable { get { return true; } } public override EffectAdjustment EffectOrAdjustment { get { return EffectAdjustment.Adjustment; } } public override Gdk.Key AdjustmentMenuKey { get { return Gdk.Key.M; } } public CurvesData Data { get { return EffectData as CurvesData; } } public CurvesEffect () { EffectData = new CurvesData (); } public override bool LaunchConfiguration () { var dialog = new CurvesDialog (Data); dialog.Title = Text; dialog.Icon = PintaCore.Resources.GetIcon (Icon); int response = dialog.Run (); dialog.Destroy (); return (response == (int)Gtk.ResponseType.Ok); } public override void RenderEffect (ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { if (Data.ControlPoints == null) return; if (op == null) op = MakeUop (); op.Apply (dest, src, rois); } private UnaryPixelOp MakeUop() { UnaryPixelOp op; byte[][] transferCurves; int entries; switch (Data.Mode) { case ColorTransferMode.Rgb: UnaryPixelOps.ChannelCurve cc = new UnaryPixelOps.ChannelCurve(); transferCurves = new byte[][] { cc.CurveR, cc.CurveG, cc.CurveB }; entries = 256; op = cc; break; case ColorTransferMode.Luminosity: UnaryPixelOps.LuminosityCurve lc = new UnaryPixelOps.LuminosityCurve(); transferCurves = new byte[][] { lc.Curve }; entries = 256; op = lc; break; default: throw new InvalidEnumArgumentException(); } int channels = transferCurves.Length; for (int channel = 0; channel < channels; channel++) { SortedList channelControlPoints = Data.ControlPoints[channel]; IList xa = channelControlPoints.Keys; IList ya = channelControlPoints.Values; SplineInterpolator interpolator = new SplineInterpolator(); int length = channelControlPoints.Count; for (int i = 0; i < length; i++) { interpolator.Add(xa[i], ya[i]); } for (int i = 0; i < entries; i++) { transferCurves[channel][i] = Utility.ClampToByte(interpolator.Interpolate(i)); } } return op; } } public class CurvesData : EffectData { public SortedList[] ControlPoints { get; set; } public ColorTransferMode Mode { get; set; } public override EffectData Clone () { // Not sure if we have to copy contents of ControlPoints // var controlPoints = new SortedList [ControlPoints.Length]; // // for (int i = 0; i < ControlPoints.Length; i++) // controlPoints[i] = new SortedList (ControlPoints[i]); return new CurvesData () { Mode = Mode, ControlPoints = ControlPoints }; } } }