/src/Data/BmpFileType.cs
C# | 192 lines | 149 code | 30 blank | 13 comment | 4 complexity | ce5338f125f58ef85e0ef2e23a467315 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 BmpFileType
- : InternalFileType
- {
- public BmpFileType()
- : base("BMP", FileTypeFlags.SupportsLoading | FileTypeFlags.SupportsSaving, new[] { ".bmp" })
- {
- }
-
- public enum PropertyNames
- {
- BitDepth = 0,
- DitherLevel = 1
- }
-
- public enum BmpBitDepthUIChoices
- {
- AutoDetect = 0,
- Bpp24 = 1,
- Bpp8 = 2
- }
-
- public override PropertyCollection OnCreateSavePropertyCollection()
- {
- var props = new List<Property>
- {
- StaticListChoiceProperty.CreateForEnum(PropertyNames.BitDepth,
- BmpBitDepthUIChoices.AutoDetect, false),
- new Int32Property(PropertyNames.DitherLevel, 7, 0, 8)
- };
-
- var rules = new List<PropertyCollectionRule>
- {
- new ReadOnlyBoundToValueRule<object, StaticListChoiceProperty>(
- PropertyNames.DitherLevel, PropertyNames.BitDepth, BmpBitDepthUIChoices.Bpp8, true)
- };
-
- var pc = new PropertyCollection(props, rules);
-
- return pc;
- }
-
- public override ControlInfo OnCreateSaveConfigUI(PropertyCollection props)
- {
- ControlInfo configUI = CreateDefaultSaveConfigUI(props);
-
- configUI.SetPropertyControlValue(
- PropertyNames.BitDepth,
- ControlInfoPropertyNames.DisplayName,
- PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.DisplayName"));
-
- PropertyControlInfo bitDepthPCI = configUI.FindControlForPropertyName(PropertyNames.BitDepth);
- bitDepthPCI.SetValueDisplayName(BmpBitDepthUIChoices.AutoDetect, PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.AutoDetect.DisplayName"));
- bitDepthPCI.SetValueDisplayName(BmpBitDepthUIChoices.Bpp24, PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.Bpp24.DisplayName"));
- bitDepthPCI.SetValueDisplayName(BmpBitDepthUIChoices.Bpp8, PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.Bpp8.DisplayName"));
-
- configUI.SetPropertyControlType(PropertyNames.BitDepth, PropertyControlType.RadioButton);
-
- configUI.SetPropertyControlValue(
- PropertyNames.DitherLevel,
- ControlInfoPropertyNames.DisplayName,
- PdnResources.GetString("BmpFileType.ConfigUI.DitherLevel.DisplayName"));
-
- return configUI;
- }
-
- 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)
- {
- var newDoc = new Document(800, 600);
-
- Layer layer = Layer.CreateBackgroundLayer(newDoc.Width, newDoc.Height);
-
- newDoc.Layers.Add(layer);
- return newDoc;
- }
- using (Image image = PdnResources.LoadImage(input))
- {
- Document document = Document.FromImage(image);
- return document;
- }
- }
-
- internal override int GetDitherLevelFromToken(PropertyBasedSaveConfigToken token)
- {
- int ditherLevel = token.GetProperty<Int32Property>(PropertyNames.DitherLevel).Value;
- return ditherLevel;
- }
-
- internal override int GetThresholdFromToken(PropertyBasedSaveConfigToken token)
- {
- return 0;
- }
-
- internal override Set<SavableBitDepths> CreateAllowedBitDepthListFromToken(PropertyBasedSaveConfigToken token)
- {
- var bitDepth = (BmpBitDepthUIChoices)token.GetProperty<StaticListChoiceProperty>(PropertyNames.BitDepth).Value;
-
- var bitDepths = new Set<SavableBitDepths>();
-
- switch (bitDepth)
- {
- case BmpBitDepthUIChoices.AutoDetect:
- bitDepths.Add(SavableBitDepths.Rgb24);
- bitDepths.Add(SavableBitDepths.Rgb8);
- break;
-
- case BmpBitDepthUIChoices.Bpp24:
- bitDepths.Add(SavableBitDepths.Rgb24);
- break;
-
- case BmpBitDepthUIChoices.Bpp8:
- bitDepths.Add(SavableBitDepths.Rgb8);
- break;
-
- default:
- throw new InvalidEnumArgumentException("bitDepth", (int)bitDepth, typeof(BmpBitDepthUIChoices));
- }
-
- return bitDepths;
- }
-
- internal override void FinalSave(
- Document input,
- Stream output,
- Surface scratchSurface,
- int ditherLevel,
- SavableBitDepths bitDepth,
- PropertyBasedSaveConfigToken token,
- ProgressEventHandler progressCallback)
- {
- // finally, do the save.
- switch (bitDepth)
- {
- 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.Bmp);
- 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.Bmp);
- 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));
- }
- }
- }
- }