Closed loudenvier closed 7 months ago
Howdy!
In general, you can change the default options for a codec just after registration, like this:
CodecManager.Configure(codecs => {
// locate the desired codec
var png = codecs.OfType<EncoderInfo>().First(c => c.MimeTypes.FirstOrDefault() == ImageMimeTypes.Png);
// remove the default definition
codecs.Remove(png);
// replace it with a new one with different options
codecs.Add(png with { DefaultOptions = new PngEncoderOptions(PngFilter.None, Interlace: false) });
});
However, it seems that I inadvertently left the encoder definition for JPEG defined as internal
, so you won't be able to change JPEG options through the normal API. It is, however, possible to do in the current release through reflection, and this will be safe when done at app startup in CodecManager.Configure
.
CodecManager.Configure(codecs => {
// locate the JPEG codec
var jpeg = codecs.OfType<IImageEncoderInfo>().First(c => c.MimeTypes.FirstOrDefault() == ImageMimeTypes.Jpeg);
// change the default options on the existing definition
var prop = jpeg.GetType().GetProperty(nameof(IImageEncoderInfo.DefaultOptions));
prop!.SetValue(jpeg, new JpegEncoderOptions(Quality: 70, Subsample: ChromaSubsampleMode.Subsample420));
});
This is also possible with the libjpeg
native plugin, which supports progressive encoding for smaller file sizes.
CodecManager.Configure(codecs => {
// register the libjpeg plugin, replacing the Windows codec if present
codecs.UseLibjpeg();
// locate the JPEG codec
var jpeg = codecs.OfType<IImageEncoderInfo>().First(c => c.MimeTypes.FirstOrDefault() == ImageMimeTypes.Jpeg);
// change the default options on the existing definition
var prop = jpeg.GetType().GetProperty(nameof(IImageEncoderInfo.DefaultOptions));
prop!.SetValue(jpeg, new JpegOptimizedEncoderOptions(Quality: 70, Subsample: ChromaSubsampleMode.Subsample420, Progressive: JpegProgressiveMode.Semi));
});
I will plan on making the JPEG options public in a future release so that the reflection call isn't necessary.
Oh Internal classes, been there, done that :-) ... They have a tendency to come back and bite me in the butt... When I started "doing" Kotlin programming I found it so strange that everything defaults to public, but now I'm leaning towards this and only making private the really, really, really implementation details. If something needs to be visible inside other files in the assembly (internal) chances are they'll be needed somewhere else down the road :-)
But, anyways, reflection to the rescue. Everything now works like a charm! I'm using it on a simple Image Resizer app: https://github.com/loudenvier/imgsizer
(still need to upload the changes based on your help though)
I've just published v0.14.1 with the fix, so the reflection workaround is no longer necessary. Something like this should work:
CodecManager.Configure(codecs => {
// locate the JPEG codec
var jpeg = codecs.OfType<EncoderInfo>().First(c => c.MimeTypes.FirstOrDefault() == ImageMimeTypes.Jpeg);
// remove the default definition
codecs.Remove(jpeg);
// replace it with a new one with different options
codecs.Add(jpeg with { DefaultOptions = new JpegEncoderOptions(Quality: 70, Subsample: ChromaSubsampleMode.Subsample420) });
});
Thank you for the update! I'll update my code accordingly!
Em qua., 6 de mar. de 2024, 04:16, Clinton Ingram @.***> escreveu:
I've just published v0.14.1 with the fix, so the reflection workaround is no longer necessary. Something like this should work:
CodecManager.Configure(codecs => { // locate the JPEG codec var jpeg = codecs.OfType
().First(c => c.MimeTypes.FirstOrDefault() == ImageMimeTypes.Jpeg); // remove the default definition codecs.Remove(jpeg); // replace it with a new one with different options codecs.Add(jpeg with { DefaultOptions = new JpegEncoderOptions(Quality: 70, Subsample: ChromaSubsampleMode.Subsample420) });}); — Reply to this email directly, view it on GitHub https://github.com/saucecontrol/PhotoSauce/issues/133#issuecomment-1980229002, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEIGLJPAKMR6B6E57F7QQLYW27EBAVCNFSM6AAAAAA62IV2VGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSOBQGIZDSMBQGI . You are receiving this because you authored the thread.Message ID: @.***>
I know I can pass a
JpegEncoderOptions
object when callingMagicProcessor.ProcessImages
, but I'm at a loss how to set default jpeg encoder options. Since the encoder is selected automatically depending on the source file extension or signature, I only want to control jpeg options and not force all files to be converted to jpeg. My current code is, sadly, forcing jpeg encoding for all files:I'm aware of
CodecManager
but I didn't find any example on how to simply setup some encoder specific default options, more precisely jpeg options. I know it's probably a silly question :-) but I'm not being able to solve it by myself.