Graphics.DrawImage产生一些“噪音”,一个关键线附近的图像边缘 您所在的位置:网站首页 grom读音 Graphics.DrawImage产生一些“噪音”,一个关键线附近的图像边缘

Graphics.DrawImage产生一些“噪音”,一个关键线附近的图像边缘

2023-04-24 06:58| 来源: 网络整理| 查看: 265

我有加载一个全尺寸的文件和种植它,它调整到所要求的尺寸和质量要求按需调整大小/作物图像的服务。Graphics.DrawImage产生一些“噪音”,一个关键线附近的图像边缘

public static byte[] Resize(Image sourceImage, int? targetWidth, int? targetHeight, int quality);

但是我正在面临的问题是,对于特定尺寸的输出图像包含沿边缘一些微弱关键线的形式的一些“噪音”。 你可以在这里如何看一个例子图像边缘应 enter image description here

这里实际上是如何返回[images here]

它增加了一个关键行只对某些维度对,误差是一致的,并且独立于质量(1-100)通过。

以下是调整大小代码,这里也简单的操场https://github.com/gromag/ImageResizeTest

有什么建议?

using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Drawing; using System.Drawing.Imaging; using System.IO; namespace grom.lib.graphics { public class ImageResizer { /// /// A quick lookup for getting image encoders /// private static Dictionary encoders = null; /// /// A quick lookup for getting image encoders /// public static Dictionary Encoders { //get accessor that creates the dictionary on demand get { //if the quick lookup isn't initialised, initialise it if (encoders == null) { encoders = new Dictionary(); } //if there are no codecs, try loading them if (encoders.Count == 0) { //get all the codecs foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders()) { //add each codec to the quick lookup encoders.Add(codec.MimeType.ToLower(), codec); } } //return the lookup return encoders; } } /// /// ************************************************************* /// Resizes or crops an images to the requested width and height. /// ************************************************************* /// If any dimension is not passed, the function will calculate the missed dimensions /// If both dimensions are not passed, the function will return a *copy* of the original image /// If any of the requested dimensions exceeds the original one's, this function will return null /// If dimensions' ratio does not match the original ratio, clipping will occur. /// /// /// /// /// A bitmap, you will **need** to dispose of such image public static byte[] Resize(Image sourceImage, int? targetWidth, int? targetHeight, int quality) { //w, h source width and height int w = sourceImage.Size.Width; int h = sourceImage.Size.Height; //wt, ht requested width and height int wt = 1; int ht = 1; //The new image would exceed the max boundary of the source image if (targetWidth > w || targetHeight > h) return null; if (targetWidth == null && targetHeight == null) { wt = w; ht = h; } var sourceRatio = (double)w/(double)h; //if no target width expressed then //if w = sourceRatio * h //then //wt = sourceRatio * ht wt = (int)(targetWidth ?? sourceRatio * ht); //if no target height expressed then //if h = w/sourceRatio //then //ht = wt/sourceRatio ht = (int)(targetHeight ?? wt/sourceRatio); var targetRatio = (double)wt/(double)ht; #region ***Clipping explaination in visual terms //Clip applied to original image before scaling // If proportions are as follow: // // target 2:1 source 1:1 // ___________ _______________ // | | | | // |___________| | | // | | // | | // |_______________| // Then we will clip as follows: // // clip to source // _______________ // |_ _ _ _ _ _ _ _| // | | // | | // |_ _ _ _ _ _ _ _| // |_______________| // or vertical clip instead if proportions are as follow: // // target 1:2 source 1:1 // ___ _______________ // | | | | // | | | | // |___| | | // | | // |_______________| // Then we will clip as follows: // // clip to source // _______________ // | ! ! | // | ! ! | // | ! ! | // | ! ! | // |____!_____!____| #endregion Rectangle clip; if (targetRatio >= sourceRatio) { //The image requested is more elungated than the original one //therefore we clip the height //targetRatio = wt/ht //ht = wt/targetRatio //hClip = w/targetRatio var hClip = (int)Math.Ceiling((double) w/(double)targetRatio); //Rectangle pars are: x, y, width, height clip = new Rectangle(0, (h - hClip)/2, w, hClip); } else { //The image requested is more stretched in height than the original one //therefore we clip the width //targetRatio = wt/ht //wt = targetRatio * ht //hClip = targetRatio * h var wClip = (int)Math.Ceiling((double)h * (double)targetRatio); //Rectangle pars are: x, y, width, height clip = new Rectangle((w - wClip)/2, 0, wClip, h); } var targetImage = new Bitmap(wt, ht); using (var g = Graphics.FromImage(targetImage)) { g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.SmoothingMode = SmoothingMode.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; var targetRectangle = new Rectangle(0, 0, wt, ht); g.DrawImage(sourceImage, targetRectangle, clip, GraphicsUnit.Pixel); } var bytes = ImageToByteArray(targetImage, ImageFormat.Jpeg, quality); targetImage.Dispose(); return bytes; } /// /// Given a System.Drawing.Image it will return the corresponding byte array given /// a format. /// /// /// /// public static byte[] ImageToByteArray(System.Drawing.Image imageIn, ImageFormat format, int quality) { //create an encoder parameter for the image quality EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality); //get the jpeg codec ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg"); //create a collection of all parameters that we will pass to the encoder EncoderParameters encoderParams = new EncoderParameters(1); //set the quality parameter for the codec encoderParams.Param[0] = qualityParam; //save the image using the codec and the parameters var ms = new MemoryStream(); imageIn.Save(ms, jpegCodec, encoderParams); return ms.ToArray(); } /// /// Converts a byte array to System.Drawing.Image. /// IMPORTANT: You must dispose of the returned image. /// /// /// Returns an image of type System.Drawing.Image, you will have to take care of disposing it public static Image ByteArrayToImage(byte[] byteArrayIn) { var ms = new MemoryStream(byteArrayIn); var returnImage = Image.FromStream(ms); return returnImage; } /// /// Returns the image codec with the given mime type /// public static ImageCodecInfo GetEncoderInfo(string mimeType) { //do a case insensitive search for the mime type string lookupKey = mimeType.ToLower(); //the codec to return, default to null ImageCodecInfo foundCodec = null; //if we have the encoder, get it to return if (Encoders.ContainsKey(lookupKey)) { //pull the codec from the lookup foundCodec = Encoders[lookupKey]; } return foundCodec; } }

}

编辑:上面上传了实际图像的特写截图

图片,我在这里将另一对夫妇的实际来源和输出图像的例子。

来源:在403x305(关键线旁边的左边缘)

Source file

输出:

Output at 403x305

来源

2016-09-13 Giuseppe Romagnuolo

+2

这是一般由Graphics.Interpolation属性设置产生的伪影。更高质量的内插器通过查看多个像素来对图像进行重新采样。边缘的问题在于它耗尽了要使用的像素。它在图像的左侧显得更加明显,但在这种情况下您不觉得它令人讨厌,因为它非常黑暗。它*额外*发音,因为你的源图像已经有这个神器。 InterpolationMode.NearestNeighbor不会生成该工件,但您可能不喜欢图像其余部分的结果。 –



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有