How to Detect Camera Aspect Ratio on Windows Phone - c#

I would like to be able to determine the aspect ratio of a Windows Phone 8 hardware camera. From what I understand there are three device screen sizes now, so I'm not sure if this affects the device camera aspect ratios or if they are standard across all phone models? The reason I need to determine the camera aspect ratio is to be able to resize images appropriately once a picture is taken. The default images using CameraCaptureTask are much to large for my purposes. With using the CameraCaptureTask within my application, all I receive back is the stream of image data. I was manually trying to determine the aspect ratio from this, although with testing with a Nokia 920 in the default 16:9 aspect ratio, the ratio I determined makes no sense, it equals 222:125. What I am doing is as follows
MainPage.xaml.cs
public int GCD(int a, int b)
{
while (a != 0 && b != 0)
{
if (a > b)
a %= b;
else
b %= a;
}
if (a == 0)
return b;
else
return a;
}
private void cameraTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
BitmapImage bmi = new BitmapImage();
bmi.SetSource(e.ChosenPhoto);
//MessageBox.Show(bmi.PixelWidth.ToString() + "x" + bmi.PixelHeight.ToString());
var gcd = GCD(bmi.PixelWidth, bmi.PixelHeight);
var result = string.Format("{0}:{1}", bmi.PixelWidth / gcd, bmi.PixelHeight / gcd);
WriteableBitmap wb = new WriteableBitmap(bmi);
//WriteableBitmap wb;
Stream stream = new MemoryStream();
switch (result)
{
case "3:4":
//wb = new WriteableBitmap(480, 640);
//wb.SetSource(e.ChosenPhoto);
wb.SaveJpeg(stream, 480, 640, 0, 100);
break;
case "4:3":
//wb = new WriteableBitmap(640, 480);
wb.SaveJpeg(stream, 640, 480, 0, 100);
break;
case "9:16":
//wb = new WriteableBitmap(448, 800);
wb.SaveJpeg(stream, 448, 800, 0, 100);
break;
case "16:9":
//wb = new WriteableBitmap(800, 448);
wb.SaveJpeg(stream, 800, 448, 0, 100);
break;
default:
wb = null;
return;
}
stream.Seek(0, SeekOrigin.Begin);
//stream.Dispose();
var capturedPicture = new CapturedPicture(e.OriginalFileName, stream);
}
}
My results thus far are as follows. Depending on the orientation of the device when the picture is taken, the aspect ratio are
ASPECT RATIO
16:9 shows as
2000x3552 = 125:222
3552x2000 = 222:125
4:3 shows as
2448x3264 = 3:4
3264x2448 = 4:3

Related

Resize and optimize Image before upload C#

I am using C#,MVC5 and I am uploading image from my web application but I realize that I have performance issues because I don't optimize them and I need to fix it and is important to keep the quality.
Below you can see the results of the report why is slow.
How can I do it?
I am saving the files into a path locally with the below code.
string imgpathvalue = ConfigurationManager.AppSettings["RestaurantPath"];
string path = System.IO.Path.Combine(Server.MapPath(imgpathvalue));
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string pic = System.IO.Path.GetFileName(restaurantImg.FileName.Replace(" ", "_").Replace("%", "_"));
path = System.IO.Path.Combine(Server.MapPath(imgpathvalue), pic);
// file is uploaded
restaurantImg.SaveAs(path);
I have try the code below but I am getting the error "A generic error occurred in GDI+."
System.Drawing.Bitmap bmpPostedImage = new System.Drawing.Bitmap(restaurantImg.InputStream);
System.Drawing.Image objImage = ResizeImages.ScaleImage(bmpPostedImage, 81);
using (var ms = new MemoryStream())
{
objImage.Save(ms, objImage.RawFormat);
//ResizeImages.getImage(ms.ToArray());
}
public static System.Drawing.Image ScaleImage(System.Drawing.Image image, int maxHeight)
{
var ratio = (double)maxHeight / image.Height;
var newWidth = (int)(image.Width * ratio);
var newHeight = (int)(image.Height * ratio);
var newImage = new Bitmap(newWidth, newHeight);
using (var g = Graphics.FromImage(newImage))
{
g.DrawImage(image, 0, 0, newWidth, newHeight);
}
return newImage;
}
You are missing some of the code to resize your image correctly. Appending is a function that correctly resizes images depending on the Width and Height Values you give to it (in this example the image gets resized to 120*120 if possible).
Function Call:
ResizeImage("Path to the Image you want to resize",
"Path you want to save resizes copy into", 120, 120);
To make a function call like that possible we need to write our function. Which takes the image from the sourceImagePath and creates a new Bitmap.
Then it calculates the factor to resize the image and depending on if either the width or height is bigger it gets adjusted accordingly.
After that is done we create a new BitMap fromt he sourceImagePath and resize it. At the end we also need to dispose the sourceImage, the destImage and we also need to dispose of the Graphics Element g that we used for different Quality Settings.
Resize Function:
private void ResizeImage(string sourceImagePath, string destImagePath,
int wishImageWidth, int wishImageHeight)
{
Bitmap sourceImage = new Bitmap(sourceImagePath);
Bitmap destImage = null;
Graphics g = null;
int destImageWidth = 0;
int destImageHeight = 0;
// Calculate factor of image
double faktor = (double) sourceImage.Width / (double) sourceImage.Height;
if (faktor >= 1.0) // Landscape
{
destImageWidth = wishImageWidth;
destImageHeight = (int) (destImageWidth / faktor);
}
else // Port
{
destImageHeight = wishImageHeight;
destImageWidth = (int) (destImageHeight * faktor);
}
try
{
destImage = new Bitmap(sourceImage, destImageWidth, destImageHeight);
g = Graphics.FromImage(destImage);
g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode =
System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality =
System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(sourceImage, 0, 0, destImageWidth, destImageHeight);
// Making sure that the file doesn't already exists.
if (File.Exists(destImagePath)) {
// If it does delete the old version.
File.Delete(destImagePath);
}
destImage.Save(destImagePath);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("*** ERROR-Terror: " + ex.Message)
}
finally
{
if (g != null) { g.Dispose(); g = null; }
if (destImage != null) { destImage.Dispose(); destImage = null; }
}
sourceImage.Dispose();
sourceImage = null;
}

Memory leaks with C# app? How to stop?

My app has huge memory leak and memory usage spiked from 40MB to 700MB after 1 day running. I'm coding with C# and I don't know how to stop leak. I suspect below 2 functions are main culprit.
SendLiveVideo: It captures from camera and send via socket.
ResizeImage: In order to save bandwidth it resizes image before I send out via socket.
My app calls 3-rd party library( LibImage, Libcapture) capture image from old webcams (4 cameras) and stream as video to list of LAN connected clients.
I already assigned null values to my *variables within finally statement upon exit of Sendvideo function in order to release memory, but it seems not working.
Do I need to use Dispose method instead?
this.timer_stream0.Interval = 30; /*I capture image and send to client this every 30 milseconds make it as video stream to human eye*/
this.timer_stream0.Tick += new System.EventHandler(this.timer_stream0_Tick);
private void timer_stream0_Tick(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(SendLiveVideo, 0);
ThreadPool.QueueUserWorkItem(SendLiveVideo, 1);
ThreadPool.QueueUserWorkItem(SendLiveVideo, 2);
ThreadPool.QueueUserWorkItem(SendLiveVideo, 3);
}
void SendLiveVideo(object state)
{
LibImage image=new LibImage();
LibCapture capture_camera=new LibCapture();
int cam = (int)state;
System.Collections.ArrayList m_workerSocketList_Video =
ArrayList.Synchronized(new System.Collections.ArrayList());
switch (cam)
{
case 0:
{
image = image0;
capture_camera = capture_camera0;
m_workerSocketList_Video = m_workerSocketList_Video0;
break;
}
case 1:
{
image = image1;
capture_camera = capture_camera1;
m_workerSocketList_Video = m_workerSocketList_Video1;
break;
}
case 2:
{
image = image2;
capture_camera = capture_camera2;
m_workerSocketList_Video = m_workerSocketList_Video2;
break;
}
default:
{
image = image3;
capture_camera = capture_camera3;
m_workerSocketList_Video = m_workerSocketList_Video3;
break;
}
}
byte[] imageData=new byte[1000 * 1000 * 10];
try
{
try
{
capture_camera.Capture(image);
}
catch
{
// objData = null;
imageData = null;
return;
}
imageData = image.SaveToMem(PNG);
var stream = new MemoryStream(imageData);
{
var bitmap = new Bitmap(stream);
bitmap = ResizeImage(bitmap, new Size(150, 112));
//stream = null;
MemoryStream streamnew = new MemoryStream();
bitmap.Save(streamnew, ImageFormat.Png);
imageData = streamnew.ToArray();
bitmap = null;
streamnew = null;
}
Socket workerSocket = null;
for (int i = 0; i < m_workerSocketList_Video.Count; i++)
{
workerSocket = (Socket)m_workerSocketList_Video[i];
if (workerSocket != null)
{
if (SocketConnected(workerSocket))
{
workerSocket.Send(imageData);
}
}
}
}
catch (SocketException se)
{
// MessageBox.Show(se.Message);
return;
}
finally
{
image = null;
capture_camera = null;
imageData = null;
m_workerSocketList_Video = null;
}
}
private Bitmap ResizeImage(Bitmap imgToResize, Size size)
{
try
{
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, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
b.SetResolution(200, 200);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighSpeed;
g.SmoothingMode = SmoothingMode.HighSpeed;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return b;
}
Try taking a look at my SO answer here.
Basically, it is an approach of how to find the origin of the leak.
This is practically a copy-paste:
Open a memory profiler. I use perfmon. This article has some material about setting perfmon and #fmunkert also explains it rather well.
Locate an area in the code that you suspect that it is likely that the leak is in that area. This part is mostly depending on you having good guesses about the part of the code that is responsible for the issue.
Push the Leak to the extreme: Use labels and "goto" for isolating an area / function and repeat the suspicious code many times (a loop will work to. I find goto more convenient for this matter).
In the loop I have used a breakpoint that halted every 50 hits for examining the delta in the memory usage. Of course you can change the value to feet a noticeable leak change in your application.
If you have located the area that causes the leak, the memory usage should rapidly spike. If the Memory usage does not spike, repeat stages 1-4 with another area of code that you suspect being the root cause. If it does, continue to 6.
In the area you have found to be the cause, use same technique (goto + labels) to zoom in and isolate smaller parts of the area until you find the source of the leak.
Note that the down sides of this method are:
If you are allocating an object in the loop, it's disposal should be also contained in the loop.
If you have more than one source of leak, It makes it harder to spot (yet still possible)
I would use the
using(Graphics g = Graphics.FromImage((Image)b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighSpeed;
g.SmoothingMode = SmoothingMode.HighSpeed;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
}
return b;
pattern on each type which implements the IDisposable, this way you can't forget to dispose anything?
you have to use the using keyword whenever an IDisposable instance is used.
using (MemoryStream streamnew = new MemoryStream())
// The same goes for your bitmap instance !
you have to check on LibImage and LibCapture's implementations and the native libraries they're wrapping if it's the case.
there is no need to instantiate all those three variables image, capture_camera and m_workerSocketList_Video since you're initializing them in your switch statement unless. This will lead to significant memory loss if the classes are native wrappers around libraries that poorly manage the memory they use.
With this line of code,
imageData = image.SaveToMem(PNG);
you don't need to initiate the imageData array if the SaveToMem function returns the right buffer !

Resizing an Image using WriteableBitmap is not working

I am using the Windows Phone CameraCaptureTask to gather an image, and then resize it for better use within my application. For some reason, no matter what I've tried I cannot get the image to resize.
MainPage.xaml.cs
private void cameraTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
BitmapImage bmi = new BitmapImage();
bmi.SetSource(e.ChosenPhoto);
//MessageBox.Show(bmi.PixelWidth.ToString() + "x" + bmi.PixelHeight.ToString());
var gcd = GCD(bmi.PixelWidth, bmi.PixelHeight);
var result = string.Format("{0}:{1}", bmi.PixelWidth / gcd, bmi.PixelHeight / gcd);
WriteableBitmap wb = new WriteableBitmap(bmi);
//WriteableBitmap wb;
//Stream stream = new MemoryStream();
var stream = new MemoryStream();
switch (result)
{
case "3:4":
//wb = new WriteableBitmap(480, 640);
//wb.SetSource(e.ChosenPhoto);
wb.SaveJpeg(stream, 480, 640, 0, 100);
break;
case "4:3":
//wb = new WriteableBitmap(640, 480);
//wb.SetSource(e.ChosenPhoto);
wb.SaveJpeg(stream, 640, 480, 0, 100);
break;
case "9:16":
//wb = new WriteableBitmap(448, 800);
//wb.SetSource(e.ChosenPhoto);
wb.SaveJpeg(stream, 448, 800, 0, 100);
break;
case "16:9":
//wb = new WriteableBitmap(800, 448);
//wb.SetSource(e.ChosenPhoto);
wb.SaveJpeg(stream, 800, 448, 0, 100);
break;
default:
wb = null;
return;
}
stream.Seek(0, SeekOrigin.Begin);
//stream.Dispose();
MessageBox.Show(wb.PixelWidth.ToString() + " x " + wb.PixelHeight.ToString());
var capturedPicture = new CapturedPicture(e.OriginalFileName, stream);
}
}
public int GCD(int a, int b)
{
while (a != 0 && b != 0)
{
if (a > b)
a %= b;
else
b %= a;
}
if (a == 0)
return b;
else
return a;
}
No matter what I do, setting the WriteableBitmap to either e.ChosenPhoto or bmi forces the resulting wb to be the original size. Any ideas?
try using WriteableBitmapExWinPhone.dll
wb = wb.Resize(Convert.ToInt32(pass value of width here), Convert.ToInt32(pass value of height here), WriteableBitmapExtensions.Interpolation.Bilinear);

How to Change Size of Image

I am getting an image from the CameraCaptureTask, and I would like to be able to make the image much smaller before saving. The width and height are automatically set to the highest resolution, which is much more than what I need. I have been trying to get the image, change the dimensions, and then attempt to save, although I am getting errors.
ORIGINAL
MainPage.xaml.cs
private void cameraTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
BitmapImage bmi = new BitmapImage();
bmi.SetSource(e.ChosenPhoto);
//MessageBox.Show(bmi.PixelWidth.ToString() + "x" + bmi.PixelHeight.ToString());
var gcd = GCD(bmi.PixelWidth, bmi.PixelHeight);
var result = string.Format("{0}:{1}", bmi.PixelWidth / gcd, bmi.PixelHeight / gcd);
WriteableBitmap wb;
Stream stream;
switch (result)
{
case "3:4":
wb = new WriteableBitmap(480,640);
break;
case "4:3":
wb = new WriteableBitmap(640,480);
break;
case "9:16":
wb = new WriteableBitmap(448, 800);
break;
case "16:9":
wb = new WriteableBitmap(800, 448);
break;
default:
wb = null;
return;
}
//Set the wb to the original stream?
wb.SetSource(e.ChosenPhoto);
//Convert the wb to a stream for saving
stream = new MemoryStream(wb.ToByteArray());
//Need to replace the following line with the new image stream for saving?
//var capturedPicture = new CapturedPicture(e.OriginalFileName, e.ChosenPhoto);
var capturedPicture = new CapturedPicture(e.OriginalFileName, stream);
}
}
public int GCD(int a, int b)
{
while (a != 0 && b != 0)
{
if (a > b)
a %= b;
else
b %= a;
}
if (a == 0)
return b;
else
return a;
}
EDIT: new implementation
private void cameraTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
BitmapImage bmi = new BitmapImage();
bmi.SetSource(e.ChosenPhoto);
var gcd = GCD(bmi.PixelWidth, bmi.PixelHeight);
var result = string.Format("{0}:{1}", bmi.PixelWidth / gcd, bmi.PixelHeight / gcd);
WriteableBitmap wb = new WriteableBitmap(bmi);
Stream stream = new MemoryStream();
switch (result)
{
case "3:4":
wb.SaveJpeg(stream, 480, 640, 0, 100);
break;
case "4:3":
wb.SaveJpeg(stream, 640, 480, 0, 100);
break;
case "9:16":
wb.SaveJpeg(stream, 448, 800, 0, 100);
break;
case "16:9":
wb.SaveJpeg(stream, 800, 448, 0, 100);
break;
default:
wb = null;
return;
}
stream.Seek(0, SeekOrigin.Begin);
//var capturedPicture = new CapturedPicture(e.OriginalFileName, e.ChosenPhoto);
var capturedPicture = new CapturedPicture(e.OriginalFileName, stream);
use the overloaded Bitmap constructor to create a re-sized image, the only thing you were missing was a cast back to the Image data type:
public static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
yourImage = resizeImage(yourImage, new Size(50,50));

Create thumbnail image

I want to display thumbnail image in a gridview from file location. How to generate that of .jpeg file?
I am using C# language with asp.net.
You have to use GetThumbnailImage method in the Image class:
https://msdn.microsoft.com/en-us/library/8t23aykb%28v=vs.110%29.aspx
Here's a rough example that takes an image file and makes a thumbnail image from it, then saves it back to disk.
Image image = Image.FromFile(fileName);
Image thumb = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero);
thumb.Save(Path.ChangeExtension(fileName, "thumb"));
It is in the System.Drawing namespace (in System.Drawing.dll).
Behavior:
If the Image contains an embedded thumbnail image, this method
retrieves the embedded thumbnail and scales it to the requested size.
If the Image does not contain an embedded thumbnail image, this method
creates a thumbnail image by scaling the main image.
Important: the remarks section of the Microsoft link above warns of certain potential problems:
The GetThumbnailImage method works well when the requested thumbnail
image has a size of about 120 x 120 pixels. If you request a large
thumbnail image (for example, 300 x 300) from an Image that has an
embedded thumbnail, there could be a noticeable loss of quality in the
thumbnail image.
It might be better to scale the main image (instead
of scaling the embedded thumbnail) by calling the DrawImage method.
The following code will write an image in proportional to the response, you can modify the code for your purpose:
public void WriteImage(string path, int width, int height)
{
Bitmap srcBmp = new Bitmap(path);
float ratio = srcBmp.Width / srcBmp.Height;
SizeF newSize = new SizeF(width, height * ratio);
Bitmap target = new Bitmap((int) newSize.Width,(int) newSize.Height);
HttpContext.Response.Clear();
HttpContext.Response.ContentType = "image/jpeg";
using (Graphics graphics = Graphics.FromImage(target))
{
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(srcBmp, 0, 0, newSize.Width, newSize.Height);
using (MemoryStream memoryStream = new MemoryStream())
{
target.Save(memoryStream, ImageFormat.Jpeg);
memoryStream.WriteTo(HttpContext.Response.OutputStream);
}
}
Response.End();
}
Here is a complete example of how to create a smaller image (thumbnail). This snippet resizes the Image, rotates it when needed (if a phone was held vertically) and pads the image if you want to create square thumbs. This snippet creates a JPEG, but it can easily be modified for other file types. Even if the image would be smaller than the max allowed size the image will still be compressed and it's resolution altered to create images of the same dpi and compression level.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
//set the resolution, 72 is usually good enough for displaying images on monitors
float imageResolution = 72;
//set the compression level. higher compression = better quality = bigger images
long compressionLevel = 80L;
public Image resizeImage(Image image, int maxWidth, int maxHeight, bool padImage)
{
int newWidth;
int newHeight;
//first we check if the image needs rotating (eg phone held vertical when taking a picture for example)
foreach (var prop in image.PropertyItems)
{
if (prop.Id == 0x0112)
{
int orientationValue = image.GetPropertyItem(prop.Id).Value[0];
RotateFlipType rotateFlipType = getRotateFlipType(orientationValue);
image.RotateFlip(rotateFlipType);
break;
}
}
//apply the padding to make a square image
if (padImage == true)
{
image = applyPaddingToImage(image, Color.Red);
}
//check if the with or height of the image exceeds the maximum specified, if so calculate the new dimensions
if (image.Width > maxWidth || image.Height > maxHeight)
{
double ratioX = (double)maxWidth / image.Width;
double ratioY = (double)maxHeight / image.Height;
double ratio = Math.Min(ratioX, ratioY);
newWidth = (int)(image.Width * ratio);
newHeight = (int)(image.Height * ratio);
}
else
{
newWidth = image.Width;
newHeight = image.Height;
}
//start the resize with a new image
Bitmap newImage = new Bitmap(newWidth, newHeight);
//set the new resolution
newImage.SetResolution(imageResolution, imageResolution);
//start the resizing
using (var graphics = Graphics.FromImage(newImage))
{
//set some encoding specs
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawImage(image, 0, 0, newWidth, newHeight);
}
//save the image to a memorystream to apply the compression level
using (MemoryStream ms = new MemoryStream())
{
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, compressionLevel);
newImage.Save(ms, getEncoderInfo("image/jpeg"), encoderParameters);
//save the image as byte array here if you want the return type to be a Byte Array instead of Image
//byte[] imageAsByteArray = ms.ToArray();
}
//return the image
return newImage;
}
//=== image padding
public Image applyPaddingToImage(Image image, Color backColor)
{
//get the maximum size of the image dimensions
int maxSize = Math.Max(image.Height, image.Width);
Size squareSize = new Size(maxSize, maxSize);
//create a new square image
Bitmap squareImage = new Bitmap(squareSize.Width, squareSize.Height);
using (Graphics graphics = Graphics.FromImage(squareImage))
{
//fill the new square with a color
graphics.FillRectangle(new SolidBrush(backColor), 0, 0, squareSize.Width, squareSize.Height);
//put the original image on top of the new square
graphics.DrawImage(image, (squareSize.Width / 2) - (image.Width / 2), (squareSize.Height / 2) - (image.Height / 2), image.Width, image.Height);
}
//return the image
return squareImage;
}
//=== get encoder info
private ImageCodecInfo getEncoderInfo(string mimeType)
{
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType.ToLower() == mimeType.ToLower())
{
return encoders[j];
}
}
return null;
}
//=== determine image rotation
private RotateFlipType getRotateFlipType(int rotateValue)
{
RotateFlipType flipType = RotateFlipType.RotateNoneFlipNone;
switch (rotateValue)
{
case 1:
flipType = RotateFlipType.RotateNoneFlipNone;
break;
case 2:
flipType = RotateFlipType.RotateNoneFlipX;
break;
case 3:
flipType = RotateFlipType.Rotate180FlipNone;
break;
case 4:
flipType = RotateFlipType.Rotate180FlipX;
break;
case 5:
flipType = RotateFlipType.Rotate90FlipX;
break;
case 6:
flipType = RotateFlipType.Rotate90FlipNone;
break;
case 7:
flipType = RotateFlipType.Rotate270FlipX;
break;
case 8:
flipType = RotateFlipType.Rotate270FlipNone;
break;
default:
flipType = RotateFlipType.RotateNoneFlipNone;
break;
}
return flipType;
}
//== convert image to base64
public string convertImageToBase64(Image image)
{
using (MemoryStream ms = new MemoryStream())
{
//convert the image to byte array
image.Save(ms, ImageFormat.Jpeg);
byte[] bin = ms.ToArray();
//convert byte array to base64 string
return Convert.ToBase64String(bin);
}
}
For the asp.net users a little example of how to upload a file, resize it and display the result on the page.
//== the button click method
protected void Button1_Click(object sender, EventArgs e)
{
//check if there is an actual file being uploaded
if (FileUpload1.HasFile == false)
{
return;
}
using (Bitmap bitmap = new Bitmap(FileUpload1.PostedFile.InputStream))
{
try
{
//start the resize
Image image = resizeImage(bitmap, 256, 256, true);
//to visualize the result, display as base64 image
Label1.Text = "<img src=\"data:image/jpg;base64," + convertImageToBase64(image) + "\">";
//save your image to file sytem, database etc here
}
catch (Exception ex)
{
Label1.Text = "Oops! There was an error when resizing the Image.<br>Error: " + ex.Message;
}
}
}
Here is a version based on the accepted answer. It fixes two problems...
Improper disposing of the images.
Maintaining the aspect ratio of the image.
I found this tool to be fast and effective for both JPG and PNG files.
private static FileInfo CreateThumbnailImage(string imageFileName, string thumbnailFileName)
{
const int thumbnailSize = 150;
using (var image = Image.FromFile(imageFileName))
{
var imageHeight = image.Height;
var imageWidth = image.Width;
if (imageHeight > imageWidth)
{
imageWidth = (int) (((float) imageWidth / (float) imageHeight) * thumbnailSize);
imageHeight = thumbnailSize;
}
else
{
imageHeight = (int) (((float) imageHeight / (float) imageWidth) * thumbnailSize);
imageWidth = thumbnailSize;
}
using (var thumb = image.GetThumbnailImage(imageWidth, imageHeight, () => false, IntPtr.Zero))
//Save off the new thumbnail
thumb.Save(thumbnailFileName);
}
return new FileInfo(thumbnailFileName);
}
Here is an example to convert high res image into thumbnail size-
protected void Button1_Click(object sender, EventArgs e)
{
//---------- Getting the Image File
System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath("~/profile/Avatar.jpg"));
//---------- Getting Size of Original Image
double imgHeight = img.Size.Height;
double imgWidth = img.Size.Width;
//---------- Getting Decreased Size
double x = imgWidth / 200;
int newWidth = Convert.ToInt32(imgWidth / x);
int newHeight = Convert.ToInt32(imgHeight / x);
//---------- Creating Small Image
System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image myThumbnail = img.GetThumbnailImage(newWidth, newHeight, myCallback, IntPtr.Zero);
//---------- Saving Image
myThumbnail.Save(Server.MapPath("~/profile/NewImage.jpg"));
}
public bool ThumbnailCallback()
{
return false;
}
Source-
http://iknowledgeboy.blogspot.in/2014/03/c-creating-thumbnail-of-large-image-by.html
This is the code I'm using. Also works for .NET Core > 2.0 using System.Drawing.Common NuGet.
https://www.nuget.org/packages/System.Drawing.Common/
using System;
using System.Drawing;
class Program
{
static void Main()
{
const string input = "C:\\background1.png";
const string output = "C:\\thumbnail.png";
// Load image.
Image image = Image.FromFile(input);
// Compute thumbnail size.
Size thumbnailSize = GetThumbnailSize(image);
// Get thumbnail.
Image thumbnail = image.GetThumbnailImage(thumbnailSize.Width,
thumbnailSize.Height, null, IntPtr.Zero);
// Save thumbnail.
thumbnail.Save(output);
}
static Size GetThumbnailSize(Image original)
{
// Maximum size of any dimension.
const int maxPixels = 40;
// Width and height.
int originalWidth = original.Width;
int originalHeight = original.Height;
// Return original size if image is smaller than maxPixels
if (originalWidth <= maxPixels || originalHeight <= maxPixels)
{
return new Size(originalWidth, originalHeight);
}
// Compute best factor to scale entire image based on larger dimension.
double factor;
if (originalWidth > originalHeight)
{
factor = (double)maxPixels / originalWidth;
}
else
{
factor = (double)maxPixels / originalHeight;
}
// Return thumbnail size.
return new Size((int)(originalWidth * factor), (int)(originalHeight * factor));
}
}
Source:
https://www.dotnetperls.com/getthumbnailimage

Categories

Resources