ImageResizer get resized image - c#

I'm new with Imageresizer from imageresizing.net and i can't figure out how to get the resized image. I need the resized image because i need to add a watermark to it. I need the bitmap of the resized image.
Code:
string fileName = Path.Combine(Server.MapPath("~/Content/Gags"), System.Guid.NewGuid().ToString());
var ResizedImage = ImageBuilder.Current.Build(new ImageJob(UploadGagModel.file, fileName, new Instructions("maxwidth=556&maxheight=1500"), false, true));
I'm using ASP.NET MVC 4 C#
Thanks in advance, if i wasn't clear enough then please tell me!

Avoid using System.Drawing directly at all costs - it is fraught with memory leaks, concurrency issues, and encoding bugs. ImageResizer handles and avoids these for you, and offers a Watermarking plugin as well as SampleOverlay sample plugins to show you how to safely create your own if Watermark can't support your needs.
If, despite my warning, you want to get a Bitmap result, you can pass typeof(Bitmap) as the 'destination' parameter to ImageJob, and access the Bitmap instance from the .Result property.
Other consequences:
The Bitmap instance will not be disposed reliably unless you dispose it within a finally(){} block (use a temporary variable to cross the scope boundary).
ImageResizer will not help you with encoding the result. If you call .Save(), you will get gigantic jpeg files, and no 8-bit PNG or animated gif support.
You will not be able to take advantage of any other pipelines (WIC, FreeImage, etc). Most of our future development will be on better pipelines than GDI+/System.Drawing.

Related

Convert iTextSharp.text.pdf.BarcodeQRCode to System.Drawing.Image

Looking for a way to convert iTextSharp.text.pdf.BarcodeQRCode to System.Drawing.Image
This is what I have so far...
public System.Drawing.Image GetQRCode(string content)
{
iTextSharp.text.pdf.BarcodeQRCode qrcode = new iTextSharp.text.pdf.BarcodeQRCode(content, 115, 115, null);
iTextSharp.text.Image img = qrcode.GetImage();
MemoryStream ms = new MemoryStream(img.OriginalData);
return System.Drawing.Image.FromStream(ms);
}
In line 3 above using img.OriginalData returns null
Using img.RawData on line 3 instead thows invalid parameter error on line 4.
I've googled some of the code samples on how to perform the thing you want and your code (the "OriginalData" approach) is basicaly the same: https://csharp.hotexamples.com/examples/iTextSharp.text.pdf/BarcodeQRCode/-/php-barcodeqrcode-class-examples.html .
However, I don't see how it could work. From my investigations of BarcodeQRCode#getImage it seems that OriginalData is not set while processing such a barcode, so it will always be null.
More than that, the code you mention belongs to iText 5, which is end of life and no longer maintained (with an exception of considerable security fixes), so it's recommended to update to iText 7.
As for iText 7, I do see how to achieve the same in Java, since barcode classes do have a createAwtImage method there. .NET, on the other hand, lacks such a functionality, so I'd day that one unfortunately couldn't do it in .NET.
There are some good reasons for that. iText's Images (and a barcode could be easily converted to an iText's Image object as shown here: https://kb.itextpdf.com/home/it7kb/faq/how-to-generate-2d-barcode-as-vector-image) represent a PDF's XObject. In PDF syntax, an image file (jpg, png, etc.) is an XObject with the raw image data stored inside. However, an XObject can also contain PDF syntaxt content (it is not just used for image files). So to render such a content one needs to process the data from PDF syntax to image syntax, which is not that easy. There are some means in Java's awt to do so, that's why it's implemented in Java. As for .NET, since there is no out-of-the-box means to convert PDF images to System.Drawing.Image, it was decided not to implement it.
To conclude, there is another iText product, pdfRender, which allows one to convert PDF files (and you could create a page just for a barcode) to images. Perhaps you might want to play with it: https://itextpdf.com/en/products/itext-7/convert-pdf-to-image-pdfrender

How to remove metadata from jpg and png images

This should be a pretty trivial programming task in C#, however after I have searched a while I simply cannot find anything relevant on how to remove metadata.
I want to remove jpg and png image metadata such as: folder path, shared with, owner and computer.
My application is an MVC 4 application. In my website users can upload an image I get this image at this ActionResult method
if (image != null)
{
photo.ImageFileName = image.FileName;
photo.ImageMimeType = image.ContentType;
photo.PhotoFile = new byte[image.ContentLength];
image.InputStream.Read(photo.PhotoFile, 0, image.ContentLength);
}
Photo is a property in the model, goes like this.
public byte[] PhotoFile { get; set; }
I imagine the way to remove above mentioned metadata or just all metadata, would be to use some coding like this
if (image != null)
{
image = image.RemoveAllMetaData; !!!
I dont mind using some 3rd party dll as long as it is compatible with NET 4.
Thanks.
'Metadata' here is a bit ambiguous--Do you mean the data which is required for a viewer to properly determine the image format so it can be displayed, saving only the raw image data? Or, more likely, do you mean the extra information, such as author, camera type, GPS location, etc, that is often added via the EXIF tags?
If you mean something like the EXIF data, there's a lot of programming material already on the web about how to add/modify/remove EXIF tags, and even some apps which already strips such tags: http://www.steelbytes.com/?mid=30 for example.
If you mean you just want the raw image data, you'll probably have to read and process the image first, since both JPEG and PNG do not contain simply the raw image data; It's encoded with various methods--which is why they contain metadata to tell you how to decode it in the first place. You'll have to learn/explore the JPEG and PNG data formats to extract the original raw image data (or a reasonable facsimile in the case of a "lossy" encoding).
All the above is well-documented on various websites which can be found on Google, and many include image manipulation libraries which can handle these chores for you. I suspect you just didn't know to search for something like "JPEG PNG EXIF METADATA".
BTW, EXIF applies to JPEG's, where EXIF is, loosely (and not fully technically correct) an addition of data (extension) to the end of the JPEG file, which can usually simply be truncated to remove. A quick Google search for me turned up something like libexif.sourceforge.net and other similar results.
I'm not entirely certain about the PNG format, but I believe the PNG format (which does call such items "metadata" as well) was written to include such data as part of the file format rather than an "extension" tagged on after the fact like EXIF is. PNG, however, is open source, and you can obtain libraries and code for manipulating them from the PNG website (www.libpng.org).
There's an app for that but it's written in Perl. It doesn't recompress the image and it's here http://www.sno.phy.queensu.ca/~phil/exiftool
Found it in this thread
How to remove EXIF data without recompressing the JPEG?
Do what all the social media websites do. Create a new image file, stream in the image byte data and use the file you created than the original one that was uploaded. Of course, now you will need to find out the original image's color depth and so on so that the image you create is not of a lower quality -- unless you need to do a disk or image resize as well.

Simple Image Processing in WinRT

I'm working on a WinRT app that should require some image processing. I've done something similar so far but in Java, I would like to do some simple things in WinRT app also... But I can't seem to manage my way with the API...
Long story short, I have in xaml, on my page, an image that obtains an image with a file picker. Then when I click a "negativate" button, the image should get negativated.
Now, the method for the negativation button, I thought to look like this :
private void OnNegativateButtonClick(object sender, RoutedEventArgs e)
{
var imageToNegativate = ImagePanel.Source as WriteableBitmap ;
if (imageToNegativate == null) //Actually is ALWAYS null :(
{
//Wrong code here...
var bitmapSource = ImagePanel.Source as BitmapSource;
imageToNegativate = new WriteableBitmap(imageToNegativate.PixelWidth, imageToNegativate.PixelHeight);
}
imageToNegativate = ImageUtil.Negativate(imageToNegativate);
ImagePanel.Source = imageToNegativate;
}
This is very similar to this sample I found here but that sample project won't even load so I tried to open the files individually... My code is that method for negativation only there is something wrong with wb = new WriteableBitmap(bs); in his if (wb==null) { ... }.
What is the approach to take a WriteableBitmap from an image, do some pixel manipulation, and then set the source of the image with the new WriteableBitmap...
I'm saying about WriteableBitmap because my method for negativation uses one for input, does some processing and outputs it. (same type, WriteableBitmap.
Any suggestions or help is greatly appreciated, thank you!
The first problem is these lines of code:
var imageToNegativate = ImagePanel.Source as WriteableBitmap ;
if (imageToNegativate == null) //Actually is ALWAYS null :(
The null is telling you that ImagePanel.Source is not of type WriteableBitmap; your typecast failed. This is expected; the picker is going to give you something read-only, because read-only images are more performant (WinRT can do some optimizations if it knows the image's content isn't going to change). You only get a WriteableBitmap when you explicitly create one.
The body of your if block also doesn't make much sense -- you're trying to create a new, empty WriteableBitmap with the same size as the original image, and then you try to do an inverse-video on that empty image. Even if you got that far, you'd just get another empty image. You're not doing anything to keep the pixels from the original image.
You do need a WriteableBitmap to get access to the pixel buffer, but you need to make one that's a copy of the original image. Get rid of your cast and if block, and try this instead:
var imageToNegativate = new WriteableBitmap(ImagePanel.Source);
Joe is right in saying what is wrong with your code, but while his answer would probably work in WPF - the constructor he mentions indeed doesn't exist in WinRT/XAML. There is in fact no way to create a WriteableBitmap from a BitmapImage and the only way to attack it is to create a WriteableBitmap from the source of your BitmapImage.
One approach then would be to create a new 1x1-sized WriteableBitmap, then use its SetSource method on the source of your BitmapImage. Since the BitmapImage.UriSource property is a Uri and WriteableBitmap.SetSource() requires a Stream - you need to play with it a bit to find or download the actual image file and open a stream to read it. My toolkit has some extension methods (WriteableBitmap.FromBitmapImage()) to help you with it in case your images come from your application package and you could fairly easy expand it to also work with downloaded images.
The problem is - you get some inefficiencies that way - one is that you need to open and decode the file twice (which might be slow with large images on an ARM device - been there, done that), second is that you might need to re-download the file if it came from the network and third that there is a bug in WinRT/XAML that causes the UriSource property of a BitmapImage to become null if you set CacheMode of an associated Image control to BitmapCache, so you might need to track your sources separately anyway.
The best solution in many ways is to simply make sure you open the source image as a WriteableBitmap from the beginning, so you don't even have to create another bitmap if you want to change it anyway. In your case the user selects the image file, so there is only one file and it seems to have a pretty big chance of being processed afterwards so opening it as a WriteableBitmap sounds like the right thing to do.
Perhaps even if you want to keep both the original and processed version of the image - creating a new WriteableBitmap of same size and copying the pixels of the original might be faster (especially on an ARM device) than decoding a big image file twice.

Save bitmap to file has zero in image size field

I find when I use the Bitmap.Save method with format ImageFormat.Bmp that the bitmap header info in the file has zero in the biSizeImage field.
From what I can see this is ok according to the specs, but unfortunately the crappy embedded device I am forced to work with insists on it being set correctly.
So the question is how to go about getting this header info field always set when the bitmap is saved?
The issue, as you suspect, is that 0 is a perfectly allowable value for the image size field of an RGB bitmap. The MSDN documentation for the BITMAPINFOHEADER structure confirms this fact:
biSizeImage
The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
If biCompression is BI_JPEG or BI_PNG, biSizeImage indicates the size of the JPEG or PNG image buffer, respectively.
So the implementation in the .NET Framework is simply doing things the standard, documented way. Since you need something else, you'll have to handle the save to file process yourself, which will allow you to manually modify the biSizeImage member of the BITMAPINFOHEADER structure.
A pretty comprehensive example is available here: Saving a Control Image to a Bitmap File. Of course, it's written for the Compact Framework, but most of the individual components are still applicable. You'll need to P/Invoke several functions from the Windows API (visit www.pinvoke.net for the definitions), and work with a DC.
Taking the drawing into your own hands will probably also be faster, because you're using the GDI subsystem, rather than GDI+. An article on that general approach is available here: 1bpp in C#, and it appears to demonstrate taking matters into your own hands with the BITMAPINFOHEADER struct as well.
If you understand unmanaged C++ code, there's a tutorial available here that might give you some idea of what you'd have to implement in C# to do the same thing: Loading and Saving Bitmaps. As you can see, the code required really isn't that long, albeit still more than the one line Bitmap.Save method.
I encountered with this problem too and it solved with a simple trick.
save the bitmap, then open it as a file stream and change the biSizeimage field manually.
picbpp.Save("pic.bmp", ImageFormat.Bmp);
string path = "pic.bmp";
FileStream fs = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.None);
// Change biSizeimage field manually.
Byte[] info = new byte[] {0x10,0x59};
fs.Seek(34, SeekOrigin.Begin);
fs.Write(info, 0, info.Length);
fs.Close();

Compressing a TIF file

I'm trying to convert a multipage color tiff file to a c# CompressionCCITT3 tiff in C#. I realize that I need to make sure that all pixels are 1 bit. I have not found a useful example of this online.
You need this conversion as CCITT3 and CCITT4 don't support color (if I remember right).
Pimping disclaimer: I work for Atalasoft, a company that makes .NET imaging software.
Using dotImage, this task becomes something like this:
FileSystemImageSource source = new FileSystemImageSource("path-to-your-file.tif", true); // true = loop over all frames
// tiff encoder will auto-select an appropriate compression - CCITT4 for 1 bit.
TiffEncoder encoder = new TiffEncoder();
encoder.Append = true;
// DynamicThresholdCommand is very good for documents. For pictures, use DitherCommand
DynamicThresholdCommand threshold = new DynamicThresholdCommand();
using (FileStream outstm = new FileStream("path-to-output.tif", FileMode.Create)) {
while (source.HasMoreImages()) {
AtalaImage image = source.AcquireNext();
AtalaImage finalImage = image;
// convert when needed.
if (image.PixelFormat != PixelFormat.Pixel1bppIndexed) {
finalImage = threshold.Apply().Image;
}
encoder.Save(outstm, finalImage, null);
if (finalImage != image) {
finalImage.Dispose();
}
source.Release(image);
}
}
The Bob Powell example is good, as far as it goes, but it has a number of problems, not the least of which is that it's using a simple threshold, which is terrific if you want speed and don't actually care what your output looks like or your input domain is such that really is pretty much black and white already - just represented in color. Binarization is a tricky problem. When your task is to reduce available information by 1/24th, how to keep the right information and throw away the rest is a challenge. DotImage has six different tools (IIRC) for binarization. SimpleThreshold is bottom of the barrel, from my point of view.
I suggest to experiment with the desired results first using tiff and image utilities before diving into the coding. I found VIPS to be a handy tool. The next option is to look into what LibTIFF can do. I've had good results with the free LibTiff.NET using c# (see also stackoverflow). I was very disappointed by the GDI tiff functionality, although your milage may vary (I need the missing 16-bit-grayscale).
Also you can use the LibTiff utilities (i.e. see http://www.libtiff.org/man/tiffcp.1.html)
I saw the above code, and it looked like it was converting every pixel with manual logic.
Would this work for you?
Imports System.Drawing.Imaging
'get the color tif file
Dim bmpColorTIF As New Bitmap("C:\color.tif")
'select the an area of the tif (will grab all frames)
Dim rectColorTIF As New Rectangle(0, 0, bmpColorTIF.Width, bmpColorTIF.Height )
'clone the rectangle as 1-bit color tif
Dim bmpBlackWhiteTIF As Bitmap = bmpColorTIF.Clone(rectColorTIF, PixelFormat.Format1bppIndexed)
'do what you want with the new bitmap (save, etc)
...
Note: there are a ton of pixelformats to choose from.

Categories