How to adjust jpeg quality with Magick.Net - c#

I am trying to set the image quality of two images appended to one another to 10% and resize the images to 40x40.
using (var images = new MagickImageCollection {designFile, swatchFile})
{
MagickImage sprite = images.AppendHorizontally();
sprite.Format = MagickFormat.Jpeg;
sprite.SetOption(MagickFormat.Jpeg, "quality", "10%");
sprite.SetOption(MagickFormat.Jpeg, "size", "40x40"); ;
sprite.Write(spriteFile);
}
Unfortunately the SetOption and Format calls don't seem to be affecting the file that is written to sprite.Write()?

The method SetOption is the same as -define in ImageMagick. And this method will be renamed to SetDefine in the next release. The following resizes your image to 40x40 and uses a quality of 10%.
using (MagickImage sprite = images.AppendHorizontally())
{
sprite.Format = MagickFormat.Jpeg;
sprite.Quality = 10;
sprite.Resize(40, 40);
sprite.Write(spriteFile);
}
If you need more help feel free to post another question here: https://magick.codeplex.com/discussions

Related

ImageMagick gif creation is very slow (~40 seconds)

I'm trying to create a gif out of some Bitmap images and it takes a really long time for it to load. I followed the example on the library github page for this.
Here is my code:
public void SaveAsGif(Stream stream, ICollection<Bitmap> images, float fps, bool loop)
{
ICollection<IMagickImage> magickImages = new System.Collections.ObjectModel.Collection<IMagickImage>();
float exactDelay = 100 / fps;
foreach (Bitmap bitmap in images)
{
MagickImage image = new MagickImage(bitmap);
image.AnimationDelay = (int) exactDelay;
if (!loop)
{
image.AnimationIterations = 1;
}
magickImages.Add(image);
}
using (MagickImageCollection collection = new MagickImageCollection(magickImages))
{
QuantizeSettings settings = new QuantizeSettings();
settings.Colors = 256;
collection.Quantize(settings);
collection.Optimize();
collection.Write(stream, MagickFormat.Gif);
}
}
I tested and the conversion of the images from bitmap to MagickImages doesn't take very long, at most 5 seconds. And my images are about 4000x3000.
All the images have the same size. Writing to stream doesn't take long either. Any way to improve the timing?
If I understand your question correctly, the slowness is in displaying the GIF, not generating it. If that is the case, try resizing the image prior to calling the Add method.
e.g.:
image.Resize(400,300);

Xamarin.iOS Image on Image Watermark

How can I add a png image as a watermark to a larger image using Xamarin.iOS c# and save the output to the device?
I figured out the Xamarin.Android version from another question posted here.
Thanks in Advance!!
Using an image context, you can draw the original, then the watermark at the necessary location and obtain a new image from the context.
ImageContext example:
var originalImage = UIImage.FromBundle("buymore.jpg");
var watermarkImage = UIImage.FromFile("vs.png");
UIGraphics.BeginImageContextWithOptions(originalImage.Size, true, 1.0f);
originalImage.Draw(CGPoint.Empty);
watermarkImage.Draw(new CGRect(new CGPoint(200, 200), watermarkImage.Size));
var processedImage = UIGraphics.GetImageFromCurrentImageContext();
If your original and watermark images are the same size, you can use a CIFilter (CISourceOverCompositing) to "overlay" one image on top of another (assuming your watermark has a white or alpha background. This is my preferred method due to the speed.
CISourceOverCompositing example:
UIImage processedimage;
using (var filter = new CISourceOverCompositing())
{
filter.Image = new CIImage(UIImage.FromBundle("vs.png"));
filter.BackgroundImage = new CIImage(UIImage.FromBundle("buymore.jpg"));
processedimage = UIImage.FromImage(filter.OutputImage);
}

Barcode i25 using ItextSharp

i am using BarcodeInter25 class to make barcode. I am able to make it but its just blur how can it become more sharp ??
also its background white colour is not completely white
My Code:
BarcodeInter25 code25 = new BarcodeInter25();
Rectangle r = new iTextSharp.text.Rectangle(38, 152);
code25.ChecksumText = false;
code25.Code = "some digits";
code25.BarHeight = 2
System.Drawing.Image i = code25.CreateDrawingImage(System.Drawing.Color.Black, System.Drawing.Color.White);
MemoryStream ms = new MemoryStream();
i.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
Image img = Image.GetInstance(ms.ToArray());
ms.Dispose();
Looking at your code, it should be obvious why the barcode is blurry. You convert it to a System.Drawing.Image (making it a raster image) and then you convert it to an iTextSharp.text.Image (but by then the image is already blurry).
The correct way to achieve what you want, is to create an iTextSharp.text.Image straight from the barcode (do not pass through System.Drawing.Image). This can be done like this:
BarcodeInter25 code25 = new BarcodeInter25();
Rectangle r = new iTextSharp.text.Rectangle(38, 152);
code25.ChecksumText = false;
code25.Code = "some digits";
code25.BarHeight = 2;
PdfContentByte cb = writer.DirectContent;
Image img = code25.CreateImageWithBarcode(cb, null, null);
Now the Image object won't be a raster image (with pixels that make the lines blurry), but it will be a true vector image (no pixels, but instructions such as moveTo(), lineTo() and stroke()). Vector data has the advantage that it is resolution independent: you can zoom in and zoom out as much as you want, it will always be sharp.
This is explained in Chapter 10 of my book where you'll find the Barcodes example. In that chapter, you'll also discover the setFont() (or in iTextSharp the Font property). I quote from the API documentation:
public void setFont(BaseFont font)
Sets the text font.
Parameters:
font - the text font. Set to null to suppress any text
So if you don't want to see any text, you can add the following line to the above code snippet:
code25.Font = null;
You should avoid re-sizing by any means. The output is most likely pixel-perfect but when you scale it up/down a bilinear filter will smooth it rendering it blurry.
I had the same exact problem by embedding a QRC code in a PDF and solved it by avoiding a resize.
If you really need a different size apply it programmatically in code by using the correct interpolation algorithm.

How to process only one part of image by ImageMagick?

I have an image like below and I want to create a distort effect on it. But just the one part of image, not the whole image.
Thanks.
I am assuming you are using Magick.NET (https://magick.codeplex.com) because you added the C# tag.
The example below will first cut out the top 123 pixels of your image and applies a distortion to it. After the distortion it will have to be put on top of the source image.
using (MagickImage image = new MagickImage("0nF6D.png"))
{
using (MagickImage top = image.Clone())
{
top.Crop(image.Width, 123, Gravity.North);
top.Distort(DistortMethod.ScaleRotateTranslate, new double[] { 2, 45 });
image.Composite(top, Gravity.North, CompositeOperator.SrcOver);
image.Write("0nF6D.distorted.png");
}
}

How to use the autorotate plugin in ImageResizer

How do I use the AutoRotate plugin in a c# console application? I thought I'd be able to do something like settings.AutoRotate = true; like I can change the fit mode to use the seam carving plugin.
I've tried settings.Add("autorotate","true") to the keycollection, as well as other keynames AutoRotate and autoRotate.
I'm using it in a simple method.
new AutoRotate().Install(ImageResizer.Configuration.Config.Current);
...
protected static Image ResizeImage(Image image, double scaleFactor)
{
var settings = new ResizeSettings
{
Scale = ScaleMode.Both,
Width = (int)Math.Floor(Image.Width * scaleFactor),
Height = (int)Math.Floor(Image.Height * scaleFactor),
Mode = FitMode.None,
Format = "png"
};
settings.Set("autorotate", "true");
return ImageBuilder.Current.Build(image, settings, true);
}
After a lot of research, I've found the error that I'm making, and reveals a nice little "hidden feature" of .Net!
When an image is read into the Bitmap object, the meta data is erased, so, by accepting an Image object, the data about the orientation is lost and auto rotate doesn't kick in. So, passing the image filename instead of the image object, and my code above above works!
Thanks guys!

Categories