【发布时间】:2012-02-06 02:20:10
【问题描述】:
大小图像放置在 byte[] 数组中(不知道图像的类型)。 我必须生成另一个字节 [] 数组,其大小应最大为 50kB。 如何进行某种缩放?
【问题讨论】:
大小图像放置在 byte[] 数组中(不知道图像的类型)。 我必须生成另一个字节 [] 数组,其大小应最大为 50kB。 如何进行某种缩放?
【问题讨论】:
我对你没有明确的实现,但我会这样处理:
您可以存储 51200 个值(未压缩)。你知道原来的比例: 用比例和新图像的大小计算尺寸:
x = y / ratio
size(51200) = x * y
y = size / x
x = (size / x) / ratio;
y = x * ratio
对于值的重采样,我将使用过滤器内核: http://en.wikipedia.org/wiki/Lanczos_resampling
还没用过,但听起来很有希望。
【讨论】:
除非您想进行一些严肃的数学运算,否则您需要将字节数组加载到内存流中,从该内存流中加载图像,并使用 System.Drawing 命名空间中的内置 GDI 函数。
做 25% 或 50% 的比例很容易。除此之外,您需要开始进行插值和差分,以使二进制数据操作中的任何东西看起来都不错。您将需要几天的时间才能匹配 GDI 中已有的内容。
System.IO.MemoryStream myMemStream = new System.IO.MemoryStream(myBytes);
System.Drawing.Image fullsizeImage = System.Drawing.Image.FromStream(myMemStream);
System.Drawing.Image newImage = fullsizeImage .GetThumbnailImage(newWidth, newHeight, null, IntPtr.Zero);
System.IO.MemoryStream myResult = new System.IO.MemoryStream();
newImage.Save(myResult ,System.Drawing.Imaging.ImageFormat.Gif); //Or whatever format you want.
return myResult.ToArray(); //Returns a new byte array.
顺便说一句 - 如果您确实需要确定源图像类型,请参阅:How to check if a byte array is a valid image
【讨论】:
我用这个....
public static byte[] ImagenToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
【讨论】:
好的,经过一些实验,我有类似的东西:
public static byte[] Resize2Max50Kbytes(byte[] byteImageIn)
{
byte[] currentByteImageArray = byteImageIn;
double scale = 1f;
if (!IsValidImage(byteImageIn))
{
return null;
}
MemoryStream inputMemoryStream = new MemoryStream(byteImageIn);
Image fullsizeImage = Image.FromStream(inputMemoryStream);
while (currentByteImageArray.Length > 50000)
{
Bitmap fullSizeBitmap = new Bitmap(fullsizeImage, new Size((int)(fullsizeImage.Width * scale), (int)(fullsizeImage.Height * scale)));
MemoryStream resultStream = new MemoryStream();
fullSizeBitmap.Save(resultStream, fullsizeImage.RawFormat);
currentByteImageArray = resultStream.ToArray();
resultStream.Dispose();
resultStream.Close();
scale -= 0.05f;
}
return currentByteImageArray;
}
有人有其他想法吗?不幸的是 Image.GetThumbnailImage() 导致图像非常脏。
【讨论】:
假设您从云端硬盘读取文件
FileStream streamObj = System.IO.File.OpenRead(@"C:\Files\Photo.jpg");
Byte[] newImage=UploadFoto(streamObj);
public static Byte[] UploadFoto(FileStream fileUpload)
{
Byte[] imgByte = null;
imgByte = lnkUpload(fileUpload);
return imgByte;
}
private static Byte[] lnkUpload(FileStream img)
{
byte[] resizedImage;
using (Image orginalImage = Image.FromStream(img))
{
ImageFormat orginalImageFormat = orginalImage.RawFormat;
int orginalImageWidth = orginalImage.Width;
int orginalImageHeight = orginalImage.Height;
int resizedImageWidth = 60; // Type here the width you want
int resizedImageHeight = Convert.ToInt32(resizedImageWidth * orginalImageHeight / orginalImageWidth);
using (Bitmap bitmapResized = new Bitmap(orginalImage, resizedImageWidth, resizedImageHeight))
{
using (MemoryStream streamResized = new MemoryStream())
{
bitmapResized.Save(streamResized, orginalImageFormat);
resizedImage = streamResized.ToArray();
}
}
}
return resizedImage;
}
【讨论】:
.net core 3.1 及更高版本的解决方案:
System.Drawing.Commonnuget:Install-Package System.Drawing.Common
byte[] ReduceImage(byte[] bytes)
{
using var memoryStream = new MemoryStream(bytes);
using var originalImage = new Bitmap(memoryStream);
var resized = new Bitmap(newWidth, newHeight);
using var graphics = Graphics.FromImage(resized);
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(originalImage, 0, 0, ReducedWidth, ReducedHeight);
using var stream = new MemoryStream();
resized.Save(stream, ImageFormat.Png);
return stream.ToArray();
}
更新: 上面的方法在 Linux 上是行不通的,所以通用的解决方案是:
SixLabors.ImageSharpnuget:Install-Package SixLabors.ImageSharp
private static byte[] ReduceImage(byte[] bytes)
{
using var memoryStream = new MemoryStream(bytes);
using var image = Image.Load(memoryStream);
image.Mutate(x => x.Resize(ReducedWidth, ReducedHeight));
using var outputStream = new MemoryStream();
image.Save(outputStream, new PngEncoder() /*or another encoder*/);
return outputStream.ToArray();
}
【讨论】: