I'm using the following code to resize a tif. The tif has an alpha channel set for transparency. I'm trying to resize this image and honour the transparency but at the moment it's coming out with a black background. Any ideas?
public static void ResizeImage(string OriginalImagePath, string NewImagePath, int Width, int Height)
{
Size NewSize = new Size(Width, Height);
using (Image OriginalImage = Image.FromFile(OriginalImagePath))
{
//Graphics objects can not be created from bitmaps with an Indexed Pixel Format, use RGB instead.
PixelFormat Format = OriginalImage.PixelFormat;
if (Format.ToString().Contains("Indexed"))
Format = PixelFormat.Format24bppRgb;
using (Bitmap NewImage = new Bitmap(NewSize.Width, NewSize.Height, OriginalImage.PixelFormat))
{
using (Graphics Canvas = Graphics.FromImage(NewImage))
{
Canvas.SmoothingMode = SmoothingMode.AntiAlias;
Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
Canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
Canvas.DrawImage(OriginalImage, new Rectangle(new Point(0, 0), NewSize));
NewImage.Save(NewImagePath, OriginalImage.RawFormat);
}
}
}
}
}
Try this:
if (Format.ToString().Contains("Indexed"))
Format = PixelFormat.Format32bppArgb;
Format32bppArgb specifies an alpha channel in the pixel format.
And I think you meant to do this:
using (Bitmap NewImage = new Bitmap(NewSize.Width, NewSize.Height, Format))
EDIT:
Actually, try just forcing the pixel format on the NewImage to Format32bppArgb like so:
using (Bitmap NewImage = new Bitmap(NewSize.Width, NewSize.Height,
PixelFormat.Format32bppArgb))
Canvas.Clear(Color.Transparent)
before you blit.
I actually found out that due to the way the transparency is stored in the tiff format with photoshop it was better to create png's by automating photoshop and then crunching off the resulting png.
Related
Is it possible to convert a indexed Bitmap to a unindexed without losing any quality?
I currently use this code to convert:
public Bitmap CreateNonIndexedImage(Image src)
{
Bitmap newBmp = new Bitmap(src.Width, src.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics gfx = Graphics.FromImage(newBmp))
{
gfx.DrawImage(src, 0, 0);
}
return newBmp;
}
Here is the indexed bitmap: http://puu.sh/6VO1N.png
And this is the converted image: http://puu.sh/6VO2Q.png
I need the unindexed to be exactly the same as the indexed but I donĀ“t know what to do.
The image was resampled. That's normally a Good Thing, it helps to get rid of the dithering artifacts in the original image. But you don't like it so you have to turn interpolation off. You also should use the DrawImage() overload that prevents rescaling due to the resolution of the original image. Not actually a problem with the image you've got but it could be one with another. Thus:
public static Bitmap CreateNonIndexedImage(Image src) {
Bitmap newBmp = new Bitmap(src.Width, src.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics gfx = Graphics.FromImage(newBmp)) {
gfx.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
gfx.DrawImage(src, new Rectangle(0, 0, src.Width, src.Height));
}
return newBmp;
}
I am having image sharing application where users upload images and I take thumbnails of these images...how ever , everything is working fine but sometimes the image thumbnail(600 * 800) size is almost 1 mb which is very huge is there anyway to modify the image resolution or something to make the size like..100 kb or something . this is my code .
Bitmap bmp = new Bitmap(Width, Height);
System.Drawing.Graphics gr = System.Drawing.Graphics.FromImage(bmp);
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
System.Drawing.Rectangle rectDestination = new System.Drawing.Rectangle(0, 0, Width, Height);
System.Drawing.Size rs = new System.Drawing.Size();
rs.Height = Height;
rs.Width = Width;
gr.DrawImage(originalImage, new Rectangle(new Point(0, 0), rs), 0, 0, originalImage.Width, originalImage.Height, GraphicsUnit.Pixel);
string thumbnailPath = string.Concat(pathToSaveIn, thumbnailName);
bmp.Save(thumbnailPath);
gr.Dispose();
The image resizing code looks OK (at first glance). However, you're saving the image in bitmap format, which is lossless -- hence the large size of the file.
You probably want to use JPEG instead for a thumbnail: for photographs, etc., this gives good compression.
This may help:
public void SaveImage(Bitmap image, string filename)
{
long quality = 80L; // adjust as appropriate
var qualityEncoder = Encoder.Quality;
using (var encoderParameter = new EncoderParameter(qualityEncoder, quality))
using (var encoderParams = new EncoderParameters(1))
{
encoderParams.Param[0] = encoderParameter;
var jpegEncoder = GetEncoder(ImageFormat.Jpeg);
image.Save(filename, jpegEncoder, encoderParams);
}
}
private static ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
return codecs
.Where(codec => codec.FormatID == format.Guid)
.FirstOrDefault();
}
This looks like .NET. Scott Hanselman had a good blog post on this. Essentially a review of a package on NuGet that helps with this.
http://www.hanselman.com/blog/NuGetPackageOfWeek11ImageResizerEnablesCleanClearImageResizingInASPNET.aspx
Try System.Drawing.Image.GetThumbnailImage. I haven't used it myself, but looks like it might work.
I have a problem with the code below. I was able to convert the image into the pixel format I want. But the problem is that when I use the bitmap for my picturebox, its just black.
sourceImage = new Bitmap(sourceImage.Width, sourceImage.Height,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
pictureBoxCurrency.Image = sourceImage;
You have created the new bitmap, but you need to paint the image (transfer) from the original one to the new one.
Bitmap newBitmap = new Bitmap(sourceImage.Size.Width, sourceImage.Size.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(newBitmap);
g.DrawImage(sourceImage, new Point(0, 0));
g.Dispose();
pictureBoxCurrency.Image = sourceImage;
I have the following code to take an image and generate the thumbnail.
how can I alter the quality or compression to get smaller file sizes programatically?
Image thumbNail = image.GetThumbnailImage(Width, Height, null, new IntPtr());
If you truly need better control over the thumbnails produced, you will be better off producing your own by manually generating an image of smaller size and different quality. The GetThumbnailImage dows not give you much control.
See this article for how it's done.
http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing
When saving the thumbNail with Image.Save you can specify the quality by passing a EncoderParameter. See: Reducing JPEG Picture Quality using C#
EncoderParameter epQuality = new EncoderParameter(
System.Drawing.Imaging.Encoder.Quality,
(int)numQual.Value);
...
newImage.Save(..., iciJpegCodec, epParameters);
You do not use the GetThumbnailImage API:
protected Stream ResizeImage(string source, int width, int height) {
using (System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(source))
using (System.Drawing.Bitmap newBmp = new System.Drawing.Bitmap(width, height))
using (System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(newBmp))
{
graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphic.DrawImage(bmp, 0, 0, width, height);
MemoryStream ms = new MemoryStream();
newBmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms;
}
}
I'm using this code to convert a jpg image into a png 8.
The code works but the image looks grainy. I did an export in Photoshop as png 8 and it looks smoother and no grain.
Note: 8-bit png
Any image gurus out there that can help?
My code:
Image ImageFile = Image.FromFile(#"C:\Documents and Settings\dvela\My Documents\Downloads\pngtest\Batman01.jpg");
Rectangle NewSize = new Rectangle();
NewSize.Width = 112;
NewSize.Height = (NewSize.Width * ImageFile.Height) / ImageFile.Width;
Bitmap image = new Bitmap(NewSize.Width, NewSize.Height);
Graphics graphics = Graphics.FromImage(image);
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(ImageFile, NewSize);
FormatConvertedBitmap fcb = new FormatConvertedBitmap(System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(image.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(NewSize.Width, NewSize.Height)), PixelFormats.Indexed8, BitmapPalettes.Halftone256Transparent, 0.5);
PngBitmapEncoder pngBitmapEncoder = new PngBitmapEncoder();
pngBitmapEncoder.Interlace = PngInterlaceOption.Off;
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(fcb));
using (Stream fileStream = File.Open(#"C:\Documents and Settings\dvela\My Documents\Downloads\pngtest\test.png", FileMode.Create))
{
pngBitmapEncoder.Save(fileStream);
}
You are using a fixed palette with 256 colors for your converted image. Photoshop probably uses a palette that is created specially for that image and contains all of it's colors (or most of them).
You could use dithering, or somehow generate a custom palette, or both.
some more information is also here.
I found this library that does Palette-based and Octree-based color Quantization.
This MSDN article explains the difference between the algorithms with code.