I have bitmap of 24*24 pixels, I want to resize the bitmap dynamically 48*48 pixels or 5*5 pixels. How to do this with out losing the information
You could try something like this
Bitmap bm = new Bitmap(#"C:\Test1.bmp");
Bitmap result = new Bitmap(48, 48);
using (Graphics g = Graphics.FromImage(result))
g.DrawImage(bm, 0, 0, 48, 48);
result.Save(#"C:\Test2.bmp");
Typically scaling/Resizing images does change the quality of the new image...
You will lose information. To give the impression you are not losing as much information you need to use anti-aliasing. Iterate over the original image and consolidate the pixels which will become one pixel in your final image by taking the average of their colours.
Related
I'm making a tool that does some graphical editing to some bitmaps. I have some 8bppIndexed bitmaps with an existing color palette that I have to convert to 24bppRgb to allow me to draw on it and edit colors of pixels based on some options the user selected. Bitmap graphic is the original 8bpp .bmp file:
//Get Bitmap from file
Bitmap graphic = new Bitmap(source);
//Get palette and pixel format
ColorPalette pal = graphic.Palette;
PixelFormat pix = graphic.PixelFormat; //Format8bppIndexed
//Create datagraphic in 24bppRgb to allow for editing
PixelFormat datapix = PixelFormat.Format24bppRgb;
Bitmap datagraphic = graphic.Clone(new Rectangle(0, 0, graphic.Width, graphic.Height), datapix);
After drawing and editing Bitmap datagraphic, I'm trying to convert it back to 8bppIndexed with the same color palette as Bitmap graphic. I can do that like this:
//Convert back to graphic pixel format
datagraphic = datagraphic.Clone(new Rectangle(0, 0, datagraphic.Width, datagraphic.Height), pix); //Format8bppIndexed
//Apply color palette
datagraphic.Palette = pal;
However, after cloning datagraphic with the same pixel format as graphic, it creates an entirely new color palette. The colors in datagraphic are then all incorrect after applying ColorPalette pal. They only match by their index number between the two palettes. Is there another way of doing this that preserves the colors?
And yes, the bitmaps need to be 8bppIndexed with the custom palette. I'm trying to avoid the need to go through Photoshop to change the color index of all the end result data graphics with the correct palette.
I should say that I'm still fairly new to C#. I hope I was clear as to what I'm trying to do. I appreciate any help here. Thanks in advance.
Converting an 8-bit image to 24bpp is trivial: you just paint it on a new image of the same dimensions and the preferred pixel format.
public static Bitmap PaintOn24bpp(Image image)
{
Bitmap bp = new Bitmap(image.Width, image.Height, PixelFormat.Format24bppRgb);
using (Graphics gr = Graphics.FromImage(bp))
gr.DrawImage(image, new Rectangle(0, 0, bp.Width, bp.Height));
return bp;
}
This works with any source image no matter its pixel format, though for images containing transparency you may want to preprocess them to fill any transparent areas, because I don't know if painting with transparency taken into account will work if the image you're drawing on doesn't support alpha.
The reverse, to convert a high-colour image to indexed, is a lot trickier, but if you have the palette, it is certainly possible. The main problem in this case is that using Graphics doesn't work, since indexed graphics don't have coloured pixels; they have a coloured palette, and pixels that just reference those colours.
Editing 8-bit data generally boils down to building a byte array containing the image data, and converting that to an image with the palette slapped onto it. The actual conversion is done by making a new 8bpp Bitmap, opening its backing byte array with the LockBits function, and copying your new data into it with Marshal.Copy.
After that, the final missing link is a method to match your image's coloured pixels to their closest palette match, so you can then take the array of resulting matches and bake it into an 8bpp image. This is generally done by calculating the Pythagorean distance (in 3D RGB colour space) of your colour to each of the palette colours, and then taking the index of the colour for which that distance is the smallest.
The whole process, from start to end, is explained in detail in this answer:
A: How to convert a colored image to a image that has only two predefined colors?
This deals with 2 colours, but the method for dealing with 2 or with 256 colours is completely identical, since the end result in both cases was an 8bpp image.
It could be optimised for dealing with 24bpp images directly instead of converting the input to 32bpp, but that's probably not worth the effort, especially since the method posted there works with absolutely any input.
I want to make very simplistic paint/image editor. Mainly, for pixel editing, but that doesn't seem relevant.
To ease up my effort, I decided to keep the image size at 16x16.
I populate the form, add a PixelBox and slap a default image on it.
Of course, I need to make the pixels visible, set the interpolation to NearestNeighbor.
Then, I stretch the pixelbox to 320x320. And there the situation arises.
The image is displayed as thus:
Cropped image
Could someone shed some light on this? This is just a 16x16 image with a checkerboard pattern that I made, but I can't figure out why it is displayed with that offset at the top left.
Also, no code as been yet added. I assume this is default behavior?
If you look at the examples on the page that exact same error happens, so it must be a bug on the PixelBox.
Instead of using a custom control for this type of operation just use the standard PictureBox and scale the image by yourself:
public Bitmap ScaleBitmap(Bitmap src, Size NewSize)
{
Bitmap bmp = new Bitmap(NewSize.Width, NewSize.Height, src.PixelFormat);
Graphics g = Graphics.FromImage(src);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.DrawImage(src, new Rectangle(Point.Empty, NewSize), new Rectangle(0, 0, src.Width, src.Height), GraphicsUnit.Pixel);
g.Dispose();
return bmp;
}
Sometimes when I resize semi-transparent png's I get weird white pixels on shapes edges. This happens only with images that have shapes (not photos) and when InterpolationMode is set to HighQualityBicubic. Does anyone know why this white pixels show? I get them only on some images.
This is the result I get:
This is the source file:
This is similar file, that does not cause that "white pixel" effect.
Drawing code is very simple:
Bitmap resize = new Bitmap(1024, 177, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(resize))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(Properties.Resources.Wave01, 0, 0, 1024, 177);
}
Please note, that I use HighQualityBicubic because the code is used for resizing various types of images including photos. Using InterpolationMode.Default seems to solve the problem, but then resizing some image types may produce worse results than HighQualityBicubic.
suppose i have two images img1.jpg and img2.jpg. using some routine i could extract the difference between two images. now difference is saved in another bitmap variable called diff
here is code
Bitmap diff = new Bitmap(bounds.Width, bounds.Height);
Graphics g = Graphics.FromImage(diff);
g.DrawImage(secondImg, 0, 0, bounds, GraphicsUnit.Pixel);
g.Dispose();
i know the difference in terms of rectangle and also save the difference in diff variable. now i want to merge or draw this difference on my first image. i tried with code like
Graphics g1 = Graphics.FromImage(firstImg);
g1.DrawImage(secondImg, 0, 0, bounds, GraphicsUnit.Pixel);
g1.Dispose();
but it is not working because when i open my first image img1.jpg then i am seeing any changes in that image. i want to draw the changes on my first image img1.jpg. what is wrong in my code which is not being able to dump or draw the changes on first image.
basically i have to reconstruct img1, if i have img2 and difference between img2 and img1.
please guide me. thanks
I'm trying to scale down a Bitmap using GDI+ by doing the following:
Bitmap newImage = new Bitmap(NewWidth, NewHeight, Im.PixelFormat);
Graphics g = Graphics.FromImage(newImage);
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.ScaleTransform(0.1, 0.1); // 10%
g.DrawImage(Im, 0, 0, Im.Width, Im.Height);
Im is the original image, NewWidth and NewHeight are 10% or the original image. I've tested this on a 1000x1000 image (shrinking it down to 100x100)
The scaling is done correctly with high quality as promised but for some reason there is a gray border on the left, right and top borders (none on the bottom).
I assume this is due to the fact the all the image borders are white and the color "outside" of the bitmap is by default black so some of the default black get mixed into the scaling interpolation.
I looked for a way to set the default background color to white (white will do just fine) but couldn't find it anywhere..
My alternative is to pad the border with a white frame, scale the image down and the crop it but I was wondering if there is a simpler and less CPU consuming way?
Any ideas?
Well. After some more digging I found it..
System.Drawing.Imaging.ImageAttributes Att = new System.Drawing.Imaging.ImageAttributes();
Att.SetWrapMode(System.Drawing.Drawing2D.WrapMode.Clamp, System.Drawing.Color.White);
g.DrawImage(Im, new Rectangle(0,0,Im.Width,Im.Height), 0, 0, Im.Width, Im.Height, GraphicsUnit.Pixel, Att);
Try adding an alpha overlay with an extra transparent pixel or two on all sides. This should get a better result than using either an explicit or implied solid color frame. Though converting to RGBA and adding the frame has a higher execution cost, if you are really interested in high quality and don't want to switch graphics libraries it may be the way to go.