I have a particular problem that I need help with. I am working with complex proteomics data and one of our plots involves a heatmap of the raw data. These heatmaps I calculate as a raw image that I then resize to fit my chart canvas. The image files that are produced that way are usually very in-balanced when it comes to the width vs height.
Usually, these images are around 10 to a 100 pixels wide and 5000 to 8000 pixels high (this is the size of my raw 2D data array that I have to convert into an image). The target resolution afterwards would be something of 1300 x 600 pixels.
I usually use this function for resizing my image to a target size
public static Image Resize(Image img, int width, int height) {
Bitmap bmp = new Bitmap(width, height);
Graphics graphic = Graphics.FromImage((Image)bmp);
graphic.InterpolationMode = InterpolationMode.NearestNeighbor;
graphic.PixelOffsetMode = PixelOffsetMode.Half;
graphic.DrawImage(img, 0, 0, width, height);
graphic.Dispose();
return (Image)bmp;
}
This usually works fine for the dimension described above. But now I have a new dataset with the dimensions of 6 x 54343 pixels.
When using the same code on this image the resized image is half blank.
Original Image:
http://files.biognosys.ch/FileSharing/20170427_StackOverflow/raw.png
(the original image does not show properly in most browsers so use “save link as…”)
How it should look (using photoshop):
http://files.biognosys.ch/FileSharing/20170427_StackOverflow/photoshop_resize.png
How it looks when I use the code snipped above
http://files.biognosys.ch/FileSharing/20170427_StackOverflow/code_resized.png
Please keep in mind, that this has worked for years without problem for images of 6 x 8000 so I guess I am not doing anything fundamentally wrong here.
It is also important that I have NearestNeighbor interpolation for the resizing so any solution that involves other interpolations that do not result in the “How it should look” image are eventually not useful for me.
Oli
2
Answers
It looks like you’ve hit some legacy limitation from 16-bit Windows era. The obvious way to work it around is to pre-split the source image into smaller chunks using just memory operations and than apply all those chunks with resizing using
Graphics
. This method assumes your source image isBitmap
rather than justImage
but this doesn’t seem to be a limitation for you. Here is a sketch of the code:Here is what I get for your example image:
It is not the same as your
photoshop_resize.png
but is quite similar to yourcode_resized.png
This code can be improved to better handle various “edges” such as cases when
srcBmp.Height
is not even or edges between different parts (pixels on the edges are interpolated using only half of the pixels they should be) but this is not easy to do without assuming some “good” size of both source and resized image or re-implementing interpolation logic yourself. Still this code might already be good enough for your usage given your scaling factors.Here is a solution that seems to work. It’s based on Windows WIC (“Windows Imaging Component”). It’s a native component that Windows (and WPF) uses for all imaging operations.
I have provided a small .NET interop layer for it. It has not all WIC features but it will allow you to load/scale/save a file/stream image. The Scale method has a scaling option similar to the GDI+ one.
It seems to work ok with your sample although the result is not strictly equivalent to the photoshop one. This is how you can use it: