Пример #1
0
        internal override Set <SavableBitDepths> CreateAllowedBitDepthListFromToken(PropertyBasedSaveConfigToken token)
        {
            PngBitDepthUIChoices bitDepthFromToken = (PngBitDepthUIChoices)token.GetProperty <StaticListChoiceProperty>(PropertyNames.BitDepth).Value;

            Set <SavableBitDepths> 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);
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        protected override bool IsReflexive(PropertyBasedSaveConfigToken token)
        {
            PngBitDepthUIChoices bitDepth = (PngBitDepthUIChoices)token.GetProperty <StaticListChoiceProperty>(PropertyNames.BitDepth).Value;

            // Only 32-bit is reflexive
            return(bitDepth == PngBitDepthUIChoices.Bpp32);
        }
Пример #4
0
 internal abstract void FinalSave(
     Document input,
     Stream output,
     Surface scratchSurface,
     int ditherLevel,
     SavableBitDepths bitDepth,
     PropertyBasedSaveConfigToken token,
     ProgressEventHandler progressCallback);
Пример #5
0
        internal override Set <SavableBitDepths> CreateAllowedBitDepthListFromToken(PropertyBasedSaveConfigToken token)
        {
            var bitDepths = new Set <SavableBitDepths>();

            bitDepths.Add(SavableBitDepths.Rgb8);
            bitDepths.Add(SavableBitDepths.Rgba8);

            return(bitDepths);
        }
Пример #6
0
        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));
            }
        }
Пример #7
0
        protected override void OnSaveT(Document input, Stream output, PropertyBasedSaveConfigToken token, Surface scratchSurface, ProgressEventHandler progressCallback)
        {
            int quality = token.GetProperty <Int32Property>(PropertyNames.Quality).Value;

            ImageCodecInfo    icf   = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Jpeg);
            EncoderParameters parms = new EncoderParameters(1);
            EncoderParameter  parm  = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);

            parms.Param[0] = parm;

            scratchSurface.Clear(ColorBgra.White);

            using (RenderArgs ra = new RenderArgs(scratchSurface))
            {
                input.Render(ra, false);
            }

            using (Bitmap bitmap = scratchSurface.CreateAliasedBitmap())
            {
                GdiPlusFileType.LoadProperties(bitmap, input);
                bitmap.Save(output, icf, parms);
            }
        }
Пример #8
0
        internal override int GetDitherLevelFromToken(PropertyBasedSaveConfigToken token)
        {
            int ditherLevel = token.GetProperty <Int32Property>(PropertyNames.DitherLevel).Value;

            return(ditherLevel);
        }
Пример #9
0
        internal override int GetThresholdFromToken(PropertyBasedSaveConfigToken token)
        {
            int threshold = token.GetProperty <Int32Property>(PropertyNames.Threshold).Value;

            return(threshold);
        }
Пример #10
0
 internal override int GetThresholdFromToken(PropertyBasedSaveConfigToken token)
 {
     return(0);
 }
Пример #11
0
 private PropertyBasedSaveConfigToken(PropertyBasedSaveConfigToken copyMe)
     : base(copyMe)
 {
     this.properties = copyMe.properties.Clone();
 }
Пример #12
0
        protected unsafe override sealed void OnSaveT(
            Document input,
            Stream output,
            PropertyBasedSaveConfigToken token,
            Surface scratchSurface,
            ProgressEventHandler progressCallback)
        {
            // flatten the document -- render w/ transparent background
            scratchSurface.Clear(ColorBgra.Transparent);

            using (RenderArgs ra = new RenderArgs(scratchSurface))
            {
                input.Render(ra, false);
            }

            // load properties from token
            int thresholdFromToken = GetThresholdFromToken(token);
            int ditherLevel        = GetDitherLevelFromToken(token);

            Set <SavableBitDepths> allowedBitDepths = CreateAllowedBitDepthListFromToken(token);

            if (allowedBitDepths.Count == 0)
            {
                throw new ArgumentException("there must be at least 1 element returned from CreateAllowedBitDepthListFromToken()");
            }

            // allowedBitDepths.Count >= 1

            // set to 1 unless allowedBitDepths contains only Rgb8 and Rgba8
            int threshold;

            if (allowedBitDepths.IsSubsetOf(Set.Create(SavableBitDepths.Rgb8, SavableBitDepths.Rgba8)))
            {
                threshold = thresholdFromToken;
            }
            else
            {
                threshold = 1;
            }

            // Analyze image, try to detect what bit-depth or whatever to use, based on allowedBitDepths
            bool allOpaque;
            bool all0or255Alpha;
            int  uniqueColorCount;

            Analyze(scratchSurface, out allOpaque, out all0or255Alpha, out uniqueColorCount);

            Set <SavableBitDepths> losslessBitDepths = new Set <SavableBitDepths>();

            losslessBitDepths.Add(SavableBitDepths.Rgba32);

            if (allOpaque)
            {
                losslessBitDepths.Add(SavableBitDepths.Rgb24);

                if (uniqueColorCount <= 256)
                {
                    losslessBitDepths.Add(SavableBitDepths.Rgb8);
                }
            }
            else if (all0or255Alpha && uniqueColorCount < 256)
            {
                losslessBitDepths.Add(SavableBitDepths.Rgba8);
            }

            SavableBitDepths bitDepth = ChooseBitDepth(allowedBitDepths, losslessBitDepths, allOpaque, all0or255Alpha, uniqueColorCount);

            if (bitDepth == SavableBitDepths.Rgba8 && threshold == 0 && allowedBitDepths.Contains(SavableBitDepths.Rgba8) && allowedBitDepths.Contains(SavableBitDepths.Rgb8))
            {
                // threshold of 0 should effectively force full 256 color palette, instead of 255+1 transparent
                bitDepth = SavableBitDepths.Rgb8;
            }

            // if bit depth is 24 or 8, then we have to do away with the alpha channel
            // for 8-bit, we must have pixels that have either 0 or 255 alpha
            if (bitDepth == SavableBitDepths.Rgb8 ||
                bitDepth == SavableBitDepths.Rgba8 ||
                bitDepth == SavableBitDepths.Rgb24)
            {
                UserBlendOps.NormalBlendOp blendOp = new UserBlendOps.NormalBlendOp();

                for (int y = 0; y < scratchSurface.Height; ++y)
                {
                    for (int x = 0; x < scratchSurface.Width; ++x)
                    {
                        ColorBgra p = scratchSurface[x, y];

                        if (p.A < threshold && bitDepth == SavableBitDepths.Rgba8)
                        {
                            p = ColorBgra.FromBgra(0, 0, 0, 0);
                        }
                        else
                        {
                            p = blendOp.Apply(ColorBgra.White, p);
                        }

                        scratchSurface[x, y] = p;
                    }
                }
            }

            Tracing.Ping("Chose " + bitDepth + ", ditherLevel=" + ditherLevel + ", threshold=" + threshold);

            // finally, do the save.
            FinalSave(input, output, scratchSurface, ditherLevel, bitDepth, token, progressCallback);
        }
Пример #13
0
 internal abstract int GetDitherLevelFromToken(PropertyBasedSaveConfigToken token);
Пример #14
0
 internal abstract int GetThresholdFromToken(PropertyBasedSaveConfigToken token);
Пример #15
0
 internal abstract Set <SavableBitDepths> CreateAllowedBitDepthListFromToken(PropertyBasedSaveConfigToken token);