Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transparent Color on PadTransform #120

Open
paul-van-der-hoeven opened this issue Sep 7, 2023 · 1 comment
Open

Transparent Color on PadTransform #120

paul-van-der-hoeven opened this issue Sep 7, 2023 · 1 comment

Comments

@paul-van-der-hoeven
Copy link

The padding Color.Transparent is inconsistent between the two methods:

using var outStreamF_PNG = new FileStream(StorePathFile_PNG, FileMode.OpenOrCreate);
var padSettings_PNG = new ProcessImageSettings { EncoderOptions = new PngEncoderOptions { Filter = PngFilter.Adaptive } };
MagicImageProcessor.BuildPipeline(mStream_PNG, padSettings_PNG).AddTransform(new PadTransform(System.Drawing.Color.Transparent, padTop, padRight, padBottom, padLeft)).WriteOutput(outStreamF_PNG);

Despite the instruction of System.Drawing.Color.Transparent, the padded area is rendered as white.

Whereas setting the ProcessImageSettings with MatteColor = System.Drawing.Color.Transparent will produce a transparent padded area around the image.

ProcessImageSettings processImgSettings = new()
{
    HybridMode = HybridScaleMode.FavorQuality,
    Width = destF.MaxWidth,
    Height = destF.MaxHeight,
    Sharpen = true,
    ResizeMode = CropScaleMode.Pad,
    MatteColor = System.Drawing.Color.Transparent
};

processImgSettings.EncoderOptions = new PngEncoderOptions { Filter = PngFilter.Adaptive };
MagicImageProcessor.ProcessImage(btArr, StorePathFile_PNG, processImgSettings);

I noticed that the documentation for PadTransform says "Adds solid-colored padding pixels to an image." But why would this not honor System.Drawing.Color.Transparent when padding a png image?

When we process images that are larger than the target size, the ProcessImageSettings with CropScaleMod.Pad works perfectly.
But when the source image is smaller than the target size we have to calculate the padding for each side and apply the PadTransform. This is where it fails us. A cropscale mode for padding with the option to not upscale the image would be ideal, but would gladly settle for a solution where the PadTransform option works with Color.Transparent.

@saucecontrol
Copy link
Owner

saucecontrol commented Sep 7, 2023

Howdy! Thanks for the detailed write-up.

The PadTransform behavior you're seeing is intentional, as ProcessingPipeline (open pipeline) is meant to be a lower-level API than the all-in-one ProcessImage (closed pipeline). The format of the open pipeline's IPixelSource will attempt to match the input image as closely as possible, while giving you the flexibility to change it if you prefer.

So, if you start with a source that does not contain transparency, the pipeline's output IPixelSource will also not have transparency, and the alpha channel of the PadTransform's matte color will be ignored. Same would happen if you started with a source image in a greyscale pixel format -- a matte color that is not grey would have its additional color channels ignored, keeping only one channel (blue) as the grey value.

Here's an example including the format conversion explicitly, which should give your desired result:

var settings = ProcessImageSettings.Default;
_ = settings.TrySetEncoderFormat(ImageMimeTypes.Png);

using var outStreamF_PNG = File.Create(StorePathFile_PNG);
using var pipeline = MagicImageProcessor.BuildPipeline(mStream_PNG, settings);
pipeline
    .AddTransform(new FormatConversionTransform(PixelFormats.Bgra32bpp))
    .AddTransform(new PadTransform(System.Drawing.Color.Transparent, padTop, padRight, padBottom, padLeft))
    .WriteOutput(outStreamF_PNG);

Note that adding the FormatConversionTransform will be a no-op if the format is already the one you are requesting. There is a limitation currently that you can't request the format of the current IPixelSource and then modify the pipeline after, so this is the best way to handle format if you're unsure what you have. I will address that limitation in a future version.

Also be aware ProcessingPipeline needs to be disposed, as it holds on to a number of unmanaged codec resources. Kind of messes with the fluent API, but it's important.

And finally, I agree an additional CropScaleMode (PadOnly, maybe?) would probably be useful, so I'll look at that for next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants