Size image placed in byte[] array (don't know the type of image). I have to produce another byte [] array, which size should be up to 50kB. How can I do some kind of scaling?
6 Answers
Unless you want to get into some serious math, you need to load your byte array into a memory stream, load an image from that memory stream, and use the built-in GDI functions in the System.Drawing namespace.
Doing a 25%, or 50% scale is easy. Beyond that, you need to start doing interpolation and differencing to make anything look halfway decent in binary data manipulation. You'll be several days into it before you can match what's already available in 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.
BTW - if you really need to figure out your source image type, see: How to check if a byte array is a valid image

- 1
- 1

- 1,708
- 10
- 20
-
Other than adding a "Using" statement on the stream functions, yes. This should be the answer. – DFTR Aug 07 '15 at 15:26
-
not "a" using. 4 usings are needed there. Great answer though. – yazanpro Jan 28 '16 at 18:27
-
@Yazanpro - I just threw up the relevant functions. If you want to flesh it out to a production-worthy block, be my guest. – Wesley Long Feb 05 '16 at 17:44
-
Will this approach work in .NET Core for Linux? As far as I know, System.Drawing is a Windows-specific namespace that is not a part of the .net now. It is available only as a separate NuGet. – Grigory Zhadko Jul 12 '21 at 06:48
-
1@GrigoryZhadko Read more here: https://learn.microsoft.com/en-us/dotnet/api/system.drawing?view=net-5.0#remarks System.Drawing depends on windows-specific api GDI+. You can get some functionality on linux by using System.Drawing.Common along with linux package libgdxplus which is not installed on most distros. – Pontus Magnusson Jul 22 '21 at 14:57
Ok, so after some experiments, I have something like that:
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;
}
Has someone another idea? Unfortunatelly Image.GetThumbnailImage() was causing very dirty images.

- 1,737
- 1
- 25
- 42
-
How is the quality of the images from byte array? is it compressing correctly? – Sade Feb 26 '19 at 09:03
The updated answer below works with Docker SixLabors.ImageSharp
.
The solution for .net core 3.1 and greater:
- Install
System.Drawing.Common
nuget:
Install-Package System.Drawing.Common
- The code to change the size of the image from a byte array:
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();
}
Update: The approach above can don't work for Linux, so the universal solution is:
- Install
SixLabors.ImageSharp
nuget:
Install-Package SixLabors.ImageSharp
- Write the following code:
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();
}

- 3,688
- 2
- 27
- 25

- 1,484
- 1
- 19
- 33
Suppose you read a file from Drive
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;
}

- 2,238
- 4
- 31
- 68
I have no definite implementation for you, but I would approach it that way:
You can store 51200 values (uncompressed). And you know the ratio from the original: Calculate the dimensions with the ratio and the size of the new image:
x = y / ratio
size(51200) = x * y
y = size / x
x = (size / x) / ratio;
y = x * ratio
for the resampling of the values I would go for using a filter kernel: http://en.wikipedia.org/wiki/Lanczos_resampling
Haven't used it yet, but sounds promising.

- 1,096
- 2
- 11
- 19
I am used this....
public static byte[] ImagenToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}

- 1
- 1