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));
Related
I am trying to crop image from center and want to generate image with 100 * 46 dimensions but i am getting image with 46 * 17 dimension.
Code:
SaveCroppedImage(Image.FromStream(file.InputStream), 100, 46, "MyfilePath", true);
public void SaveCroppedImage(Image image, UInt16 thumbWidth, UInt16 thumbHeight, string filePath, Boolean checkDimension)
{
if (checkDimension && image.Width > image.Height)
{
var tmp = thumbHeight;
thumbHeight = thumbWidth;
thumbWidth = tmp;
}
if (image.Width > thumbWidth || image.Height > thumbHeight)
{
float scaleWidth = 1;
float scaleHeight = 1;
float scale = 1;
scaleWidth = ((float)thumbWidth / (float)image.Width);
scaleHeight = ((float)thumbHeight / (float)image.Height);
if (scaleWidth < scaleHeight)
{
scale = scaleWidth;
}
else
{
scale = scaleHeight;
}
thumbWidth = (UInt16)Math.Round(image.Width * scale, 0);
thumbHeight = (UInt16)Math.Round(image.Height * scale, 0);
}
if (thumbWidth > image.Width)
thumbWidth = (UInt16)image.Width;
if (thumbHeight > image.Height)
thumbHeight = (UInt16)image.Height;
//System.Drawing.Image thumb = image.GetThumbnailImage(thumbWidth, thumbHeight, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
System.Drawing.Image thumb = new System.Drawing.Bitmap(thumbWidth, thumbHeight);
System.Drawing.Graphics gr = System.Drawing.Graphics.FromImage(thumb);
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
System.Drawing.Rectangle rectDestination = new System.Drawing.Rectangle(0, 0, thumbWidth, thumbHeight);
gr.DrawImage(image, rectDestination, 0, 0, image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel);
//
// get raw format
System.Drawing.Imaging.ImageFormat format = image.RawFormat;
//
// get encoder
System.Drawing.Imaging.ImageCodecInfo info = null;
foreach (System.Drawing.Imaging.ImageCodecInfo ici in System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders())
{
if (System.Drawing.Imaging.ImageFormat.Jpeg.Equals(format))
{
info = ici;
break;
}
else if (System.Drawing.Imaging.ImageFormat.Gif.Equals(format))
{
info = ici;
break;
}
else if (System.Drawing.Imaging.ImageFormat.Png.Equals(format))
{
info = ici;
break;
}
else if (System.Drawing.Imaging.ImageFormat.Bmp.Equals(format))
{
info = ici;
break;
}
else if (System.Drawing.Imaging.ImageFormat.Tiff.Equals(format))
{
info = ici;
break;
}
else if (System.Drawing.Imaging.ImageFormat.Wmf.Equals(format))
{
info = ici;
break;
}
}
// check if we found the right encoder, otherwise use the rawformat and save
using (var stream = new MemoryStream())
{
if (info == null)
{
thumb.Save(stream, format);
}
else
{
//
// create parameters and save
System.Drawing.Imaging.EncoderParameters encParams = new System.Drawing.Imaging.EncoderParameters(1);
encParams.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
thumb.Save(stream, info, encParams);
}
stream.Seek(0, SeekOrigin.Begin);
StoreFile(stream, filePath);
image.Dispose();
}
gr.Dispose();
}
private static Boolean StoreFile(Stream fileStream, String filePath, Boolean overwriteIfExists = true)
{
if (fileStream.CanSeek) fileStream.Seek(0, SeekOrigin.Begin);
var fileWasWritten = false;
try
{
using (var stream = File.Open(filePath, FileMode.Create, FileAccess.Write))
{
if (stream.CanSeek) stream.Seek(0, SeekOrigin.Begin);
fileStream.CopyTo(stream);
}
fileWasWritten = true;
}
catch
{
return false;
}
return fileWasWritten;
}
My sample input image:Trial Image
Output Image:
I am trying to save image that format only which user image has.For Eg:If user selected image is in png format then i would like to save image in
png format only and if image is in jpg format then save image in jpg format.
I have tried code from below link but code from below link produces very bad quality image:
Reference
As the Image width is always bigger than the height this condition always is true
if (checkDimension && image.Width > image.Height)
and switches the dimensions of your result image.
If you wanted this to check for the image oriantation you could do something like:
var oriantationthumb = (thumbWidth/(float)thumbHeight) > 1;
var oriantationImage = (imageWidth/(float)imageHeight) > 1;
if(oriantationthumb != oriantationImage)
{
//exchange
}
Am working in windows form.I have an image. Its size is 960*1280.
When i tried to add this image to my picture box at run time. the image is getting rotated and its size of the image is 1280*960.
my aim is to resize the image to 100*100 and then add to picture box. i don't want that image to get rotated. Can you suggest me some ideas?
put this in a class file and use the below resizer code
public class ImageResizer
{
private int allowedFileSizeInByte;
private string sourcePath;
private string destinationPath;
public ImageResizer()
{
}
public ImageResizer(int allowedSize, string sourcePath, string destinationPath)
{
allowedFileSizeInByte = allowedSize;
this.sourcePath = sourcePath;
this.destinationPath = destinationPath;
}
public void ScaleImage()
{
using (MemoryStream ms = new MemoryStream())
{
using (FileStream fs = new FileStream(sourcePath, FileMode.Open))
{
Bitmap bmp = (Bitmap)Image.FromStream(fs);
SaveTemporary(bmp, ms, 100);
while (ms.Length < 0.9 * allowedFileSizeInByte || ms.Length > allowedFileSizeInByte)
{
double scale = Math.Sqrt((double)allowedFileSizeInByte / (double)ms.Length);
ms.SetLength(0);
bmp = ScaleImage(bmp, scale);
SaveTemporary(bmp, ms, 100);
}
if (bmp != null)
bmp.Dispose();
SaveImageToFile(ms);
}
}
}
public byte[] GetScaledImage(int allowedSize, string sourcePath)
{
allowedFileSizeInByte = allowedSize;
this.sourcePath = sourcePath;
//this.destinationPath = destinationPath;
using (MemoryStream ms = new MemoryStream())
{
using (FileStream fs = new FileStream(sourcePath, FileMode.Open))
{
Bitmap bmp = (Bitmap)Image.FromStream(fs);
SaveTemporary(bmp, ms, 100);
while (ms.Length < 0.9 * allowedFileSizeInByte || ms.Length > allowedFileSizeInByte)
{
double scale = Math.Sqrt((double)allowedFileSizeInByte / (double)ms.Length);
ms.SetLength(0);
bmp = ScaleImage(bmp, scale);
SaveTemporary(bmp, ms, 100);
}
if (bmp != null)
bmp.Dispose();
Byte[] buffer = null;
if (ms != null && ms.Length > 0)
{
ms.Position = 0;
buffer = new byte[ms.Length];
ms.Read(buffer, 0, buffer.Length);
}
return buffer;
}
}
}
private void SaveImageToFile(MemoryStream ms)
{
byte[] data = ms.ToArray();
using (FileStream fs = new FileStream(destinationPath, FileMode.Create))
{
fs.Write(data, 0, data.Length);
}
}
private void SaveTemporary(Bitmap bmp, MemoryStream ms, int quality)
{
EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
var codec = GetImageCodecInfo();
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
if (codec != null)
bmp.Save(ms, codec, encoderParams);
else
bmp.Save(ms, GetImageFormat());
}
public Bitmap ScaleImage(Bitmap image, double scale)
{
int newWidth = (int)(image.Width * scale);
int newHeight = (int)(image.Height * scale);
Bitmap result = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb);
result.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics g = Graphics.FromImage(result))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(image, 0, 0, result.Width, result.Height);
}
return result;
}
private ImageCodecInfo GetImageCodecInfo()
{
FileInfo fi = new FileInfo(sourcePath);
switch (fi.Extension)
{
case ".bmp": return ImageCodecInfo.GetImageEncoders()[0];
case ".jpg":
case ".jpeg": return ImageCodecInfo.GetImageEncoders()[1];
case ".gif": return ImageCodecInfo.GetImageEncoders()[2];
case ".tiff": return ImageCodecInfo.GetImageEncoders()[3];
case ".png": return ImageCodecInfo.GetImageEncoders()[4];
default: return null;
}
}
private ImageFormat GetImageFormat()
{
FileInfo fi = new FileInfo(sourcePath);
switch (fi.Extension)
{
case ".jpg": return ImageFormat.Jpeg;
case ".bmp": return ImageFormat.Bmp;
case ".gif": return ImageFormat.Gif;
case ".png": return ImageFormat.Png;
case ".tiff": return ImageFormat.Tiff;
default: return ImageFormat.Png;
}
}
}
here is the code for resize the image
byte[] compressedBuffer = new ImageResizer().GetScaledImage(300000, FileName);
here 30000 shows the size, and the filename is the name of the file
One of the Bitmap class constructors takes an original image and a new size as an input:
Image uploadedImage = new Bitmap("Path/to/your/image.bmp");
Image resizedImage = new Bitmap(uploadedImage, new Size(100, 100));
In the first line of the sample you load the image. In the second line of the example you create a new object using the uploaded image and a new size.
Twain scan images to memory and it consumes too much memory. So I scanned images in batch, and compress images in memory. So source images should be released. how can I do it?
protected void OnTwainTransferReady()
{
if (TwainTransferReady == null)
return; // not likely..
List<ImageSource> imageSources = new List<ImageSource>();
ArrayList pics = tw.TransferPictures();
tw.CloseSrc();
EndingScan();
picnumber++;
for (int i = 0; i < pics.Count; i++) {
IntPtr imgHandle = (IntPtr)pics[i];
/*if (i == 0) { // first image only
imageSources.Add(DibToBitmap.FormHDib(imgHandle));
//Refresh(image1); // force a redraw
}*/
ImageSource src = DibToBitmap.FormHDib(imgHandle);
ImageSource temp = ImageHelper.compressImage(src);
src = null;
imageSources.Add(temp);
Win32.GlobalFree(imgHandle);
}
// for some reason the main window does not refresh properly - resizing of the window solves the proble.
// happens only with the Canon LIDE Scanner
// Suspected: some messages where eaten by Twain
TwainTransferReady(this, imageSources);
}
Generate the BitSource
public static BitmapSource FormHDib(IntPtr dibHandle)
{
BitmapSource bs = null;
IntPtr bmpPtr = IntPtr.Zero;
bool flip = true; // vertivcally flip the image
try {
bmpPtr = Win32.GlobalLock(dibHandle);
Win32.BITMAPINFOHEADER bmi = new Win32.BITMAPINFOHEADER();
Marshal.PtrToStructure(bmpPtr, bmi);
if (bmi.biSizeImage == 0)
bmi.biSizeImage = (uint)(((((bmi.biWidth * bmi.biBitCount) + 31) & ~31) >> 3) * bmi.biHeight);
int palettSize = 0;
if (bmi.biClrUsed != 0)
throw new NotSupportedException("DibToBitmap: DIB with pallet is not supported");
// pointer to the beginning of the bitmap bits
IntPtr pixptr = (IntPtr)((int)bmpPtr + bmi.biSize + palettSize);
// Define parameters used to create the BitmapSource.
PixelFormat pf = PixelFormats.Default;
switch (bmi.biBitCount) {
case 32:
pf = PixelFormats.Bgr32;
break;
case 24:
pf = PixelFormats.Bgr24;
break;
case 8:
pf = PixelFormats.Gray8;
break;
case 1:
pf = PixelFormats.BlackWhite;
break;
default: // not supported
throw new NotSupportedException("DibToBitmap: Can't determine picture format (biBitCount=" + bmi.biBitCount + ")");
// break;
}
int width = bmi.biWidth;
int height = bmi.biHeight;
int stride = (int)(bmi.biSizeImage / height);
byte[] imageBytes = new byte[stride * height];
//Debug: Initialize the image with random data.
//Random value = new Random();
//value.NextBytes(rawImage);
if (flip) {
for (int i = 0, j = 0, k = (height - 1) * stride; i < height; i++, j += stride, k -= stride)
Marshal.Copy(((IntPtr)((int)pixptr + j)), imageBytes, k, stride);
} else {
Marshal.Copy(pixptr, imageBytes, 0, imageBytes.Length);
}
int xDpi = (int)Math.Round(bmi.biXPelsPerMeter * 2.54 / 100); // pels per meter to dots per inch
int yDpi = (int)Math.Round(bmi.biYPelsPerMeter * 2.54 / 100);
// Create a BitmapSource.
bs = BitmapSource.Create(width, height, xDpi, yDpi, pf, null, imageBytes, stride);
Win32.GlobalUnlock(pixptr);
Win32.GlobalFree(pixptr);
} catch (Exception ex) {
string msg = ex.Message;
}
finally {
// cleanup
if (bmpPtr != IntPtr.Zero) { // locked sucsessfully
Win32.GlobalUnlock(dibHandle);
}
}
Win32.GlobalUnlock(bmpPtr);
Win32.GlobalFree(bmpPtr);
return bs;
}
Compress Image in Memory
internal static System.Windows.Media.ImageSource compressImage(System.Windows.Media.ImageSource ims)
{
using (MemoryStream stream = new MemoryStream())
{
using (MemoryStream outS = new MemoryStream())
{
BitmapSource bs = ims as BitmapSource;
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
BitmapFrame bf = BitmapFrame.Create(bs);
//encoder.Frames.Add(BitmapFrame.Create(image1.Source));
encoder.Frames.Add(bf);
encoder.Save(stream);
stream.Flush();
try
{
// Read first frame of gif image
using (MagickImage image = new MagickImage(stream))
{
image.Quality = 75;
image.Resize(new Percentage(0.65));
image.Density = new Density(200, DensityUnit.PixelsPerInch);
image.Write(outS);
image.Dispose();
}
stream.Close();
stream.Dispose();
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
outS.Position = 0;
bitmap.StreamSource = outS;
//
bitmap.EndInit();
//bitmap.Freeze();
outS.Flush();
outS.Close();
outS.Dispose();
ims = null;
return bitmap;
}
catch (Exception e)
{
return null;
}
}
}
}
public Bitmap GrabScreenshot()
{
Bitmap bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
System.Drawing.Imaging.BitmapData data = bmp.LockBits(this.ClientRectangle, System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
CsGL.OpenGL.GL.glReadPixels(0, 0, 800, 600, CsGL.OpenGL.GL.GL_3D, CsGL.OpenGL.GL.GL_8X_BIT_ATI, data.Scan0);
CsGL.OpenGL.GL.glFinish();
bmp.UnlockBits(data);
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
return bmp;
}
private void button1_Click(object sender, EventArgs e)
{
GrabScreenshot();
Bitmap bmp = GrabScreenshot();
bmp.Save("C:\\temp\\test.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
}
To capture a full screenshot use this:
public static Bitmap CaptureScreen()
{
Rectangle bounds = SystemInformation.VirtualScreen;
Bitmap Target = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppRgb);
using (Graphics g = Graphics.FromImage(Target))
{
g.CopyFromScreen(0, 0, 0, 0, bounds.Size);
}
return Target;
}
If you need a specific screen then use this option:
private enum CaptureType
{
AllScreens,
PrimaryScreen,
VirtualScreen,
WorkingArea
}
private static Bitmap[] Capture(CaptureType typeOfCapture)
{
Bitmap[] images = null;
Bitmap memoryImage;
int count = 1;
Screen[] screens = Screen.AllScreens;
Rectangle SourceRectangle;
switch (typeOfCapture)
{
case CaptureType.PrimaryScreen:
SourceRectangle = Screen.PrimaryScreen.Bounds;
break;
case CaptureType.VirtualScreen:
SourceRectangle = SystemInformation.VirtualScreen;
break;
case CaptureType.WorkingArea:
SourceRectangle = Screen.PrimaryScreen.WorkingArea;
break;
case CaptureType.AllScreens:
count = screens.Length;
typeOfCapture = CaptureType.WorkingArea;
SourceRectangle = screens[0].WorkingArea;
break;
default:
SourceRectangle = SystemInformation.VirtualScreen;
break;
}
// allocate a member for saving the captured image(s)
images = new Bitmap[count];
// cycle across all desired screens
for (int index = 0; index < count; index++)
{
if (index > 0)
{
SourceRectangle = screens[index].WorkingArea;
}
// redefine the size on multiple screens
memoryImage = new Bitmap(SourceRectangle.Width, SourceRectangle.Height, PixelFormat.Format32bppArgb);
using (Graphics memoryGrahics = Graphics.FromImage(memoryImage))
{
memoryGrahics.CopyFromScreen(SourceRectangle.X, SourceRectangle.Y, 0, 0, SourceRectangle.Size, CopyPixelOperation.SourceCopy);
}
images[index] = memoryImage;
}
return images;
}
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);