我有一个Image文件,我想使用System.Drawing类同时裁剪和调整大小
我正在努力建立在本文中的想法:http://www.schnieds.com/2011/07/image-upload-crop-and-resize-with.html
我可以单独裁剪和调整大小但是当我尝试组合这个过程时,我得到了一些奇怪的输出。
这是我一直在尝试的事情
using (System.Drawing.Bitmap _bitmap = new System.Drawing.Bitmap(w, h))
{
_bitmap.SetResolution(img.HorizontalResolution, img.VerticalResolution);
using (Graphics _graphic = Graphics.FromImage(_bitmap))
{
_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;
//Code used to crop
_graphic.DrawImage(img, 0, 0, w, h);
_graphic.DrawImage(img, new Rectangle(0, 0, w, h), x, y, w, h, GraphicsUnit.Pixel);
//Code I used to resize
_graphic.DrawImage(img, 0, 0, img.Width, img.Height);
_graphic.DrawImage(img, new Rectangle(0, 0, W_FixedSize, H_FixedSize), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
//continued...
}
}
在上面的代码中......有两个部分被评论...一个要裁剪,一个要调整大小。
对于裁剪,我将图像的适当坐标和宽度/高度部分传递给裁剪(x,y,w,h)。
我想基于我的参数进行裁剪,并根据W_FixedSize和H_Fixed size参数绘制图像。
答案 0 :(得分:7)
我正在使用我写的这个课:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
namespace Studio.Utilities
{
public class ImageResizer
{
public void ResizeImage(string origFileLocation, string newFileLocation, string origFileName, string newFileName, int newWidth, int maxHeight, bool resizeIfWider)
{
System.Drawing.Image FullSizeImage = System.Drawing.Image.FromFile(origFileLocation + origFileName);
// Ensure the generated thumbnail is not being used by rotating it 360 degrees
FullSizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
FullSizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
if (resizeIfWider)
{
if (FullSizeImage.Width <= newWidth)
{
//newWidth = FullSizeImage.Width;
}
}
int newHeight = FullSizeImage.Height * newWidth / FullSizeImage.Width;
if (newHeight > maxHeight) // Height resize if necessary
{
//newWidth = FullSizeImage.Width * maxHeight / FullSizeImage.Height;
newHeight = maxHeight;
}
newHeight = maxHeight;
// Create the new image with the sizes we've calculated
System.Drawing.Image NewImage = FullSizeImage.GetThumbnailImage(newWidth, newHeight, null, IntPtr.Zero);
FullSizeImage.Dispose();
NewImage.Save(newFileLocation + newFileName);
}
public void ResizeImageAndRatio(string origFileLocation, string newFileLocation, string origFileName, string newFileName, int newWidth, int newHeight, bool resizeIfWider)
{
System.Drawing.Image initImage = System.Drawing.Image.FromFile(origFileLocation + origFileName);
int templateWidth = newWidth;
int templateHeight = newHeight;
double templateRate = double.Parse(templateWidth.ToString()) / templateHeight;
double initRate = double.Parse(initImage.Width.ToString()) / initImage.Height;
if (templateRate == initRate)
{
System.Drawing.Image templateImage = new System.Drawing.Bitmap(templateWidth, templateHeight);
System.Drawing.Graphics templateG = System.Drawing.Graphics.FromImage(templateImage);
templateG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
templateG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
templateG.Clear(Color.White);
templateG.DrawImage(initImage, new System.Drawing.Rectangle(0, 0, templateWidth, templateHeight), new System.Drawing.Rectangle(0, 0, initImage.Width, initImage.Height), System.Drawing.GraphicsUnit.Pixel);
templateImage.Save(newFileLocation + newFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}
else
{
System.Drawing.Image pickedImage = null;
System.Drawing.Graphics pickedG = null;
Rectangle fromR = new Rectangle(0, 0, 0, 0);
Rectangle toR = new Rectangle(0, 0, 0, 0);
if (templateRate > initRate)
{
pickedImage = new System.Drawing.Bitmap(initImage.Width, int.Parse(Math.Floor(initImage.Width / templateRate).ToString()));
pickedG = System.Drawing.Graphics.FromImage(pickedImage);
fromR.X = 0;
fromR.Y = int.Parse(Math.Floor((initImage.Height - initImage.Width / templateRate) / 2).ToString());
fromR.Width = initImage.Width;
fromR.Height = int.Parse(Math.Floor(initImage.Width / templateRate).ToString());
toR.X = 0;
toR.Y = 0;
toR.Width = initImage.Width;
toR.Height = int.Parse(Math.Floor(initImage.Width / templateRate).ToString());
}
else
{
pickedImage = new System.Drawing.Bitmap(int.Parse(Math.Floor(initImage.Height * templateRate).ToString()), initImage.Height);
pickedG = System.Drawing.Graphics.FromImage(pickedImage);
fromR.X = int.Parse(Math.Floor((initImage.Width - initImage.Height * templateRate) / 2).ToString());
fromR.Y = 0;
fromR.Width = int.Parse(Math.Floor(initImage.Height * templateRate).ToString());
fromR.Height = initImage.Height;
toR.X = 0;
toR.Y = 0;
toR.Width = int.Parse(Math.Floor(initImage.Height * templateRate).ToString());
toR.Height = initImage.Height;
}
pickedG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
pickedG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
pickedG.DrawImage(initImage, toR, fromR, System.Drawing.GraphicsUnit.Pixel);
System.Drawing.Image templateImage = new System.Drawing.Bitmap(templateWidth, templateHeight);
System.Drawing.Graphics templateG = System.Drawing.Graphics.FromImage(templateImage);
templateG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
templateG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
templateG.Clear(Color.White);
templateG.DrawImage(pickedImage, new System.Drawing.Rectangle(0, 0, templateWidth, templateHeight), new System.Drawing.Rectangle(0, 0, pickedImage.Width, pickedImage.Height), System.Drawing.GraphicsUnit.Pixel);
templateImage.Save(newFileLocation + newFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
templateG.Dispose();
templateImage.Dispose();
pickedG.Dispose();
pickedImage.Dispose();
}
initImage.Dispose();
}
}
}
答案 1 :(得分:6)
似乎你应该能够通过调用DrawImage来裁剪和调整大小
_graphic.DrawImage(img,
new Rectangle(/*..cropped rect..*/),
new Rectangle(/*..new size..*/),
GraphicsUnit.Pixel);
答案 2 :(得分:5)
由于GDI中存在错误,所有错过的答案之一就是图像周围会产生50%透明的1像素边框。
要正确裁剪和调整大小,您需要将以下设置应用于图形对象:
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.CompositingMode = CompositingMode.SourceOver;
然后你需要创建一个ImageAttributes实例来修复边框错误:
ImageAttributes ia = new ImageAttributes();
ia.SetWrapMode(WrapMode.TileFlipXY);
然后,在调用DrawImage时,将ia
作为最后一个参数传递。
如果您正在处理任何PNG,TIFF或ICO图像并将其转换为不支持透明度的格式,则还需要在调用DrawImage之前调用g.Clear(bgcolor)。
如果要编码为jpeg格式,请确保设置Quality参数并随后处理EncoderParameters对象。
您正在读取的Bitmap实例将锁定基础文件,直到它被丢弃。如果使用FromStream方法,则必须保持流打开,直到处理Bitmap实例。一个好方法是将流克隆到MemoryStream实例并将其分配给Bitmap.Tag属性。
我的博客上有more complete list of GDI+ cropping & resizing bugs to avoid。
我经常尝试将人们推向use my imageresizing.net library,因为它设计为在具有最佳性能的网站上安全运行。 1行代码,用户错误的空间很小。
我下载了Schnieds&#39;示例项目,我不得不说它是一种(不必要的)复杂的做事方式。非破坏性编辑实际上更容易,as shown on this article。它很容易与Uploadify结合使用,但我不会在博客上介绍它。
此外,在上传期间重新编码图像对于jpeg和png文件都是非常具有破坏性的。验证很好,但只需在验证后处理实例,不要对其进行重新编码。 Schnieds&#39;示例还通过未处理的Bitmap实例泄漏内存 - 在高容量服务器上运行它会使其快速崩溃。
答案 3 :(得分:4)
解决了问题...
我将裁剪区域的宽度和高度传递给实例化新位图实例的语句。
我已经通过在调整大小的图像所需的固定大小中创建位图对象来纠正它...
using (System.Drawing.Bitmap _bitmap = new System.Drawing.Bitmap(W_FixedSize, H_FixedSize))
{
_bitmap.SetResolution(img.HorizontalResolution, img.VerticalResolution);
using (Graphics _graphic = Graphics.FromImage(_bitmap))
{
_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;
//Code used to crop
_graphic.DrawImage(img, 0, 0, w, h);
_graphic.DrawImage(img, new Rectangle(0, 0, w, h), x, y, w, h, GraphicsUnit.Pixel);
//Code I used to resize
_graphic.DrawImage(img, 0, 0, img.Width, img.Height);
_graphic.DrawImage(img, new Rectangle(0, 0, W_FixedSize, H_FixedSize), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
//continued...
}
}
答案 4 :(得分:0)
用于客户端使用的http://jcrop.org/
public static class ImageHelper
{
public static byte[] CropImage(byte[] content, int x, int y, int width, int height)
{
using (MemoryStream stream = new MemoryStream(content))
{
return CropImage(stream, x, y, width, height);
}
}
public static byte[] CropImage(Stream content, int x, int y, int width, int height)
{
//Parsing stream to bitmap
using (Bitmap sourceBitmap = new Bitmap(content))
{
//Get new dimensions
double sourceWidth = Convert.ToDouble(sourceBitmap.Size.Width);
double sourceHeight = Convert.ToDouble(sourceBitmap.Size.Height);
Rectangle cropRect = new Rectangle(x, y, width, height);
//Creating new bitmap with valid dimensions
using (Bitmap newBitMap = new Bitmap(cropRect.Width, cropRect.Height))
{
using (Graphics g = Graphics.FromImage(newBitMap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(sourceBitmap, new Rectangle(0, 0, newBitMap.Width, newBitMap.Height), cropRect, GraphicsUnit.Pixel);
return GetBitmapBytes(newBitMap);
}
}
}
}
public static byte[] GetBitmapBytes(Bitmap source)
{
//Settings to increase quality of the image
ImageCodecInfo codec = ImageCodecInfo.GetImageEncoders()[4];
EncoderParameters parameters = new EncoderParameters(1);
parameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
//Temporary stream to save the bitmap
using (MemoryStream tmpStream = new MemoryStream())
{
source.Save(tmpStream, codec, parameters);
//Get image bytes from temporary stream
byte[] result = new byte[tmpStream.Length];
tmpStream.Seek(0, SeekOrigin.Begin);
tmpStream.Read(result, 0, (int)tmpStream.Length);
return result;
}
}
public static Image Resize(Image current, int maxWidth, int maxHeight)
{
int width, height;
#region reckon size
if (current.Width > current.Height)
{
width = maxWidth;
height = Convert.ToInt32(current.Height * maxHeight / (double)current.Width);
}
else
{
width = Convert.ToInt32(current.Width * maxWidth / (double)current.Height);
height = maxHeight;
}
#endregion
#region get resized bitmap
var canvas = new Bitmap(width, height);
using (var graphics = Graphics.FromImage(canvas))
{
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(current, 0, 0, width, height);
}
return canvas;
#endregion
}
public static Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
public static byte[] imageToByteArray(Image image)
{
using (var ms = new MemoryStream())
{
image.Save(ms, image.RawFormat);
return ms.ToArray();
}
}
}
并在控制器
中使用 int cropPointX = Convert.ToInt32(model.imgX1);
int cropPointY = Convert.ToInt32(model.imgY1);
int imageCropWidth = Convert.ToInt32(model.imgWidth);
int imageCropHeight = Convert.ToInt32(model.imgHeight);
byte[] imageBytes = ConvertToBytes(model.ProductImage);
byte[] croppedImage;
if (cropPointX > 0 || cropPointY > 0 || imageCropWidth > 0 || imageCropHeight > 0)
{
croppedImage = CropImage(imageBytes, cropPointX, cropPointY, imageCropWidth, imageCropHeight);
}
else
{
croppedImage = imageBytes;
}
Stream stream = new MemoryStream(croppedImage);
Image img = Image.FromStream(stream, true, true);
if (img.Height > 522 || img.Width > 522)
{
img = Resize(img, 522, 522);
}
byte[] imageBytes = (byte[])(new ImageConverter()).ConvertTo(img, typeof(byte[]));
在imageBytes中,您将被裁剪并调整图像大小。您可以在db或文件夹中的任何位置存储图像。