/src/Data/PngFileType.cs
C# | 241 lines | 195 code | 35 blank | 11 comment | 3 complexity | d64d908f0517b23d17770d63dfb82739 MD5 | raw file
- /////////////////////////////////////////////////////////////////////////////////
- // Paint.NET //
- // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
- // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
- // See src/Resources/Files/License.txt for full licensing and attribution //
- // details. //
- // . //
- /////////////////////////////////////////////////////////////////////////////////
-
- using PaintDotNet.Base;
- using PaintDotNet.Base.PropertySystem;
- using PaintDotNet.IndirectUI;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.IO;
-
- namespace PaintDotNet
- {
- public sealed class PngFileType
- : InternalFileType
- {
- protected override bool IsReflexive(PropertyBasedSaveConfigToken token)
- {
- var bitDepth = (PngBitDepthUIChoices)token.GetProperty<StaticListChoiceProperty>(PropertyNames.BitDepth).Value;
-
- // Only 32-bit is reflexive
- return (bitDepth == PngBitDepthUIChoices.Bpp32);
- }
-
- public PngFileType()
- : base("PNG", FileTypeFlags.SupportsLoading | FileTypeFlags.SupportsSaving, new[] { ".png" })
- {
- }
-
- public enum PropertyNames
- {
- BitDepth = 0,
- DitherLevel = 1,
- Threshold = 2
- }
-
- public enum PngBitDepthUIChoices
- {
- AutoDetect = 0,
- Bpp32 = 1,
- Bpp24 = 2,
- Bpp8 = 3
- }
-
- public override ControlInfo OnCreateSaveConfigUI(PropertyCollection props)
- {
- ControlInfo configUI = CreateDefaultSaveConfigUI(props);
-
- configUI.SetPropertyControlValue(
- PropertyNames.BitDepth,
- ControlInfoPropertyNames.DisplayName,
- PdnResources.GetString("PngFileType.ConfigUI.BitDepth.DisplayName"));
-
- PropertyControlInfo bitDepthPCI = configUI.FindControlForPropertyName(PropertyNames.BitDepth);
- bitDepthPCI.SetValueDisplayName(PngBitDepthUIChoices.AutoDetect, PdnResources.GetString("PngFileType.ConfigUI.BitDepth.AutoDetect.DisplayName"));
- bitDepthPCI.SetValueDisplayName(PngBitDepthUIChoices.Bpp32, PdnResources.GetString("PngFileType.ConfigUI.BitDepth.Bpp32.DisplayName"));
- bitDepthPCI.SetValueDisplayName(PngBitDepthUIChoices.Bpp24, PdnResources.GetString("PngFileType.ConfigUI.BitDepth.Bpp24.DisplayName"));
- bitDepthPCI.SetValueDisplayName(PngBitDepthUIChoices.Bpp8, PdnResources.GetString("PngFileType.ConfigUI.BitDepth.Bpp8.DisplayName"));
-
- configUI.SetPropertyControlType(PropertyNames.BitDepth, PropertyControlType.RadioButton);
-
- configUI.SetPropertyControlValue(
- PropertyNames.DitherLevel,
- ControlInfoPropertyNames.DisplayName,
- PdnResources.GetString("PngFileType.ConfigUI.DitherLevel.DisplayName"));
-
- configUI.SetPropertyControlValue(
- PropertyNames.Threshold,
- ControlInfoPropertyNames.DisplayName,
- PdnResources.GetString("PngFileType.ConfigUI.Threshold.DisplayName"));
-
- configUI.SetPropertyControlValue(
- PropertyNames.Threshold,
- ControlInfoPropertyNames.Description,
- PdnResources.GetString("PngFileType.ConfigUI.Threshold.Description"));
-
- return configUI;
- }
-
- public override PropertyCollection OnCreateSavePropertyCollection()
- {
- var props = new List<Property>
- {
- StaticListChoiceProperty.CreateForEnum(PropertyNames.BitDepth,
- PngBitDepthUIChoices.
- AutoDetect, false),
- new Int32Property(PropertyNames.DitherLevel, 7, 0, 8),
- new Int32Property(PropertyNames.Threshold, 128, 0, 255)
- };
-
- var rules = new List<PropertyCollectionRule>
- {
- new ReadOnlyBoundToValueRule<object, StaticListChoiceProperty>(
- PropertyNames.Threshold,
- PropertyNames.BitDepth,
- PngBitDepthUIChoices.Bpp8,
- true),
- new ReadOnlyBoundToValueRule<object, StaticListChoiceProperty>(
- PropertyNames.DitherLevel,
- PropertyNames.BitDepth,
- PngBitDepthUIChoices.Bpp8,
- true)
- };
-
- var pc = new PropertyCollection(props, rules);
-
- return pc;
- }
-
- protected override Document OnLoad(Stream input)
- {
- using (Image image = PdnResources.LoadImage(input))
- {
- Document document = Document.FromImage(image);
- return document;
- }
- }
-
- internal override Set<SavableBitDepths> CreateAllowedBitDepthListFromToken(PropertyBasedSaveConfigToken token)
- {
- var bitDepthFromToken = (PngBitDepthUIChoices)token.GetProperty<StaticListChoiceProperty>(PropertyNames.BitDepth).Value;
-
- var bitDepths = new Set<SavableBitDepths>();
-
- switch (bitDepthFromToken)
- {
- case PngBitDepthUIChoices.AutoDetect:
- bitDepths.AddRange(SavableBitDepths.Rgb24, SavableBitDepths.Rgb8, SavableBitDepths.Rgba32, SavableBitDepths.Rgba8);
- break;
-
- case PngBitDepthUIChoices.Bpp24:
- bitDepths.AddRange(SavableBitDepths.Rgb24);
- break;
-
- case PngBitDepthUIChoices.Bpp32:
- bitDepths.AddRange(SavableBitDepths.Rgba32);
- break;
-
- case PngBitDepthUIChoices.Bpp8:
- bitDepths.AddRange(SavableBitDepths.Rgb8, SavableBitDepths.Rgba8);
- break;
-
- default:
- throw new InvalidEnumArgumentException("bitDepthFromToken", (int)bitDepthFromToken, typeof(PngBitDepthUIChoices));
- }
-
- return bitDepths;
- }
-
- internal override int GetThresholdFromToken(PropertyBasedSaveConfigToken token)
- {
- int threshold = token.GetProperty<Int32Property>(PropertyNames.Threshold).Value;
- return threshold;
- }
-
- internal override int GetDitherLevelFromToken(PropertyBasedSaveConfigToken token)
- {
- int ditherLevel = token.GetProperty<Int32Property>(PropertyNames.DitherLevel).Value;
- return ditherLevel;
- }
-
- internal override void FinalSave(
- Document input,
- Stream output,
- Surface scratchSurface,
- int ditherLevel,
- SavableBitDepths bitDepth,
- PropertyBasedSaveConfigToken token,
- ProgressEventHandler progressCallback)
- {
- switch (bitDepth)
- {
- case SavableBitDepths.Rgba32:
- {
- ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Png);
- var parms = new EncoderParameters(1);
- var parm = new EncoderParameter(Encoder.ColorDepth, 32);
- parms.Param[0] = parm;
-
- using (Bitmap bitmap = scratchSurface.CreateAliasedBitmap())
- {
- GdiPlusFileType.LoadProperties(bitmap, input);
- bitmap.Save(output, icf, parms);
- }
- }
- break;
- case 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.Png);
- var parms = new EncoderParameters(1);
- var parm = new EncoderParameter(Encoder.ColorDepth, 24);
- parms.Param[0] = parm;
-
- using (Bitmap bitmap = CreateAliased24BppBitmap(scratchSurface))
- {
- GdiPlusFileType.LoadProperties(bitmap, input);
- bitmap.Save(output, icf, parms);
- }
- }
- break;
- case SavableBitDepths.Rgb8:
- using (Bitmap quantized = Quantize(scratchSurface, ditherLevel, 256, false, progressCallback))
- {
- ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Png);
- var parms = new EncoderParameters(1);
- var parm = new EncoderParameter(Encoder.ColorDepth, 8);
- parms.Param[0] = parm;
-
- GdiPlusFileType.LoadProperties(quantized, input);
- quantized.Save(output, icf, parms);
- }
- break;
- case SavableBitDepths.Rgba8:
- using (Bitmap quantized = Quantize(scratchSurface, ditherLevel, 256, true, progressCallback))
- {
- ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Png);
- var parms = new EncoderParameters(1);
- var parm = new EncoderParameter(Encoder.ColorDepth, 8);
- parms.Param[0] = parm;
-
- GdiPlusFileType.LoadProperties(quantized, input);
- quantized.Save(output, icf, parms);
- }
- break;
- default:
- throw new InvalidEnumArgumentException("bitDepth", (int)bitDepth, typeof(SavableBitDepths));
- }
- }
- }
- }