I am reading an image from file that contains transparency area in the center (frame image type).
Image myFrame = Image.FromFile("d:\mypngfile.png");
After i call image resize custome function:
myFrame = resizeImage(myFrame, new Size(otherbmp.Width, otherbmp.Height));
The problem is that after reszing the image it seems transparency is removed.
resize function:
public Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight,PixelFormat.Format32bppArgb);
b.MakeTransparent();
Graphics g = Graphics.FromImage((Image)b);
g.CompositingQuality = CompositingQuality.HighQuality;
g.CompositingMode = CompositingMode.SourceOver;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
After i am checking the alpha pixels which doesn't work after resize (it does work before resizing and returns a value). It always return 0!
public int GetBorderWidth(Bitmap bmp)
{
var hy = bmp.Height/ 2;
while (bmp.GetPixel(0, hy).A == 255 && sz.Width < hx)
sz.Width++;
return sz.width;
}
I can't seem to solve this issue no matter what i try...
I found the issue, it was related that after resizing the image it seems that the border has some transparent pixels ..(like Alpha 150) so the border was not ALPHA 255..
What i did i changed the function GetBorderWidth code with
while (bmp.GetPixel(sz.Width, hy).A > 10 && sz.Width < hx)
sz.Width++;
and it seems it fixed the issue.
thank you all for giving me some idea of what to check.
Related
I am using windows GDI Library to resize the image using the following code. I am trying to generate the transparent images. This function is called from from and function that generates images. If I save the image without resizing I am getting transparency
static Image FixedSize(Image imgPhoto, int Width, int Height)
{
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)Width/(float)sourceWidth);
nPercentH = ((float)Height/(float)sourceHeight);
if(nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = System.Convert.ToInt16((Width -
(sourceWidth * nPercent))/2);
}
else
{
nPercent = nPercentW;
destY = System.Convert.ToInt16((Height -
(sourceHeight * nPercent))/2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(Width, Height,
PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.Transparent);
grPhoto.InterpolationMode =
InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX,destY,destWidth,destHeight),
new Rectangle(sourceX,sourceY,sourceWidth,sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
fileName= txtImgName.text();
bitmap.Save(Server.MapPath("~/images32/") + fileName, ImageFormat.Png);
}
I am getting the image resized but the problem is that it is having black background.
Please help me in generating Transparent Image
Thanks in Advance
I guess that is because you use a bitmap with RGB colors (Format24bppRgb) as source.
Use one that contains an alpha channel, such as Format32bppArgb.
How would you resize a JPEG image, to a fixed width whilst keeping aspect ratio? In a simple way, whilst preserving quality.
This will scale in the vertical axis only:
public static Image ResizeImageFixedWidth(Image imgToResize, int width)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = ((float)width / (float)sourceWidth);
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
If you are reducing the width by 25 percent to a fixed value, you must reduce the height by 25 percent.
If you are increasing the width by 25 percent to a fixed value, you must increasing the height by 25 percent.
It's really straight forward.
Assuming there is a (double width) variable:
Image imgOriginal = Bitmap.FromFile(path);
double height = (imgOriginal.Height * width) / imgOriginal.Width;
Image imgnew = new Bitmap((int)width, (int)height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(imgnew);
g.DrawImage(imgOriginal, new Point[]{new Point(0,0), new Point(width, 0), new Point(0, height)}, new Rectangle(0,0,imgOriginal.Width, imgOriginal.Height), GraphicsUnit.Pixel);
In the end you´ll have a new image with widthxheight, then, you´ll need to flush the graphics e save the imgnew.
I think there are plenty of samples of this if you search for them. Here's the one I commonly use...
public static Stream ResizeGdi(Stream stream, System.Drawing.Size size)
{
Image image = Image.FromStream(stream);
int width = image.Width;
int height = image.Height;
int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
float percent = 0, percentWidth = 0, percentHeight = 0;
percentWidth = ((float)size.Width / (float)width);
percentHeight = ((float)size.Height / (float)height);
int destW = 0;
int destH = 0;
if (percentHeight < percentWidth)
{
percent = percentHeight;
}
else
{
percent = percentWidth;
}
destW = (int)(width * percent);
destH = (int)(height * percent);
MemoryStream mStream = new MemoryStream();
if (destW == 0
&& destH == 0)
{
image.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return mStream;
}
using (Bitmap bitmap = new Bitmap(destW, destH, System.Drawing.Imaging.PixelFormat.Format48bppRgb))
{
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
{
//graphics.Clear(Color.Red);
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawImage(image,
new Rectangle(destX, destY, destW, destH),
new Rectangle(sourceX, sourceY, width, height),
GraphicsUnit.Pixel);
}
bitmap.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}
mStream.Position = 0;
return mStream as Stream;
}
Example of the calling code...
Stream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
resizedStream = ImageUtility.ResizeGdi(stream, new System.Drawing.Size(resizeWidth, resizeHeight));
A quick search on code project has found the following article. It allows for resizing of images which accepts a boolean to restrain the new image to keep the originals aspect ratio. I'm unsure of what the quality is like as no screenshots were provided. See the article here
I want to create thumbnails of size 75x75 square from originals.
The thumbnail will not look stretched in one dimension as it will not follow the aspect ratio.
If have used Flickr, you will see they generate square thumbnails. I need the same thing.
Any clue or help is appreciated.
EDIT:
I am on .NET 4.0 C#
I am looking for programmatic way to generate thumbs. Batch capability needed if no dll available.
This is from Codeproject:
static System.Drawing.Image FixedSize(System.Drawing.Image imgPhoto, int Width, int Height)
{
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)Width / (float)sourceWidth);
nPercentH = ((float)Height / (float)sourceHeight);
if (nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = System.Convert.ToInt16((Width -
(sourceWidth * nPercent)) / 2);
}
else
{
nPercent = nPercentW;
destY = System.Convert.ToInt16((Height -
(sourceHeight * nPercent)) / 2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(Width, Height,
PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.White);
grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
You can actually do this with MSPaint if you are on windows.
I using simple re-size method to change my bitmap to new size.
The original bitmap size is 320x240 and i change the size two times
To 250x160
Doing some process on the bitmap
Change it back to 320x240
I found out that after i change it back to 320x240 i see that the bitmap is little smooth and not as i excepted.
How can i avoid this smooth to appear ?
The Resize method:
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
The sad thing is you cannot.
When you resize your bitmap to a smaller size, information is lost. And information is interpolated from the small image (with less information) to create the new redimensionned image with the original size. It's this interpolation that gives the resulting image its smooth aspect.
To avoid this, the only thing you can do is finding a way to do the processing you have to without resizing down your image as part of your process.
Since you're using the HighQualityBicubic interpolation mode, the image will be prefiltered and resized using the highest possible quality, resulting in the "smoothing effect".
You can try setting the InterpolationMode property to NearestNeighbor to obtain a "rougher" result:
Bitmap b = new Bitmap(destWidth, destHeight);
using (Graphics g = Graphics.FromImage((Image) b)) {
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
}
I have a class which helps me out to re-size my images to a specified image size but the problem is with the file sizes of the output images—actually it's kinda funny but here is the thing:
the original image is : 800x600 24bit 96dpi file-size : 82kb
the re-size image is : 466x340 24bit 96dpi file-size : 366kb
what should I do? is there any 3rd party component or open source project according to this issue?
here is my mentioned class :
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
public class imageClass
{
public enum Dimensions
{
Width,
Height
}
public enum AnchorPosition
{
Top,
Center,
Bottom,
Left,
Right
}
public static Image ScaleByPercent(Image imgPhoto, int Percent)
{
float nPercent = ((float)Percent / 100);
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
public static Image ConstrainProportions(Image imgPhoto, int Size, Dimensions Dimension)
{
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
switch (Dimension)
{
case Dimensions.Width:
nPercent = ((float)Size / (float)sourceWidth);
break;
default:
nPercent = ((float)Size / (float)sourceHeight);
break;
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
public static Image FixedSize(Image imgPhoto, int Width, int Height)
{
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)Width / (float)sourceWidth);
nPercentH = ((float)Height / (float)sourceHeight);
//if we have to pad the height pad both the top and the bottom
//with the difference between the scaled height and the desired height
if (nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = (int)((Width - (sourceWidth * nPercent)) / 2);
}
else
{
nPercent = nPercentW;
destY = (int)((Height - (sourceHeight * nPercent)) / 2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.Red);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
public static Image Crop(Image imgPhoto, int Width, int Height, AnchorPosition Anchor)
{
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)Width / (float)sourceWidth);
nPercentH = ((float)Height / (float)sourceHeight);
if (nPercentH < nPercentW)
{
nPercent = nPercentW;
switch (Anchor)
{
case AnchorPosition.Top:
destY = 0;
break;
case AnchorPosition.Bottom:
destY = (int)(Height - (sourceHeight * nPercent));
break;
default:
destY = (int)((Height - (sourceHeight * nPercent)) / 2);
break;
}
}
else
{
nPercent = nPercentH;
switch (Anchor)
{
case AnchorPosition.Left:
destX = 0;
break;
case AnchorPosition.Right:
destX = (int)(Width - (sourceWidth * nPercent));
break;
default:
destX = (int)((Width - (sourceWidth * nPercent)) / 2);
break;
}
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
}
regards.
the file format I'm using is : JPEG
This is a normal side-effect of resampling the image with the InterpolationMode set to a high quality value, like Bicubic. This subtly alters the pixel values of just about every pixel, especially since jpeg decompression produces subtle noise in the image. Barely visible to the human eye, quite visible to the resampling filter. Giving the jpeg encoder a much harder time compressing the image. Only starting out with a non-compressed image format, like PNG, can improve the outcome.
If you are not explicitly defining an image format, it will default to BMP or PNG format. If you do explicitly specify ImageFomat.Jpeg, it will use quality=100, instead of quality=90 (the best setting, with no discernable differences). Check out the 28 image resizing pitfalls if you aren't going to use the recommended library for this situation
The ImageResizer library
You mentioned a library, and yes, it exists. The ImageResizer library avoids all of the GDI bugs, defaults to quality=90, and doesn't leak memory or GDI handles, even when images are corrupted. It also supports autocropping, manual cropping, resizing, rotating, and a ton of other features. It's time tested, traffic tested, and unit tested.
It has a 1-line API that is very simple to use.
Go check it out!