How can I reduce the size of an image - c#

I am trying to reduce the size of an Image I am taking from the camera before I save it to Isolated Storage. I already have it reduced to the lowest resolution (640x480) How can I reduce the bytes to 100kb instead of what they are coming out at almost 1mb.
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
string fileName = folderName+"\\MyImage" + savedCounter + ".jpg";
try
{
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
// Save picture as JPEG to isolated storage.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to isolated storage.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}

I have nothing about Windows Phone, but maybe this link will help you:
http://msdn.microsoft.com/en-us/library/ff769549(v=vs.92).aspx
1) load your jpeg
2) copy to bitmap
3) save as bitmap with quality settings
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.extensions.savejpeg(v=vs.92).aspx

Related

Uploading image as Parse File

I am trying to upload a select image file from within my WPF application to be stored on Parse however I cannot find the correct method to do this anywhere.
At the moment I have selected my image from 'OpenFileDialog' and have the path for that image stored within a text box.
How do I now upload this file to Parse?
I am familiar with parse and have no problems saving strings, images, video etc in Objective-C but cannot for the life of me think of how to get this to work in a WPF application in C#.
Any help would be massively appreciated.
Here is a piece of code that loads an image file and save the data into a byte array.
private byte[] LoadByteArrayFromFile(string fileName)
{
try
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
byte[] byteArray = new byte[fs.Length];
int bytesRead = 0;
int bytesToRead = (int)fs.Length;
while (bytesToRead > 0)
{
int read = file.Read(byteArray, bytesRead, bytesToRead);
if (read == 0)
break;
bytesToRead -= read;
bytesRead += read;
}
return byteArray;
}
}
catch (Exception ex)
{
return null;
}
}
So you first get the data.
byte[] data = LoadByteArrayFromFile(filename); //OpenFileDialog.Path, full path to the image
And then, construct a ParseFile - you should be familiar with the rest steps.
if (data != null)
{
ParseFile file = new ParseFile(System.IO.Path.GetFileName(filename), data);
await file.SaveAsync();
//then assign the ParseFile into a ParseObject, like the doc says...
}

How to store image on button click in windows phone 8?

I am developing an application which has many images & i want to implement that on clicking "save button" the Image should be stored to Photo Album.
Please reply i am new to app dev.
To work with this function you just need to pass needed Image as parameter in SaveImageToPhotoHub function.
private bool SaveImageToPhotoHub(WriteableBitmap bmp)
{
using (var mediaLibrary = new MediaLibrary())
{
using (var stream = new MemoryStream())
{
var fileName = string.Format("Gs{0}.jpg", Guid.NewGuid());
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
var picture = mediaLibrary.SavePicture(fileName, stream);
if (picture.Name.Contains(fileName)) return true;
}
}
return false;
}
Heres more to it http://www.codeproject.com/Articles/747273/How-to-Save-Image-in-Local-Photos-album-of-Windows
Try this code. This is in VB.Net but I am sure you can convert it yourself or through online tools for C#:
' Create a file name for the JPEG file in isolated storage.
Dim tempJPEG As String = "dummyImage1"
' Create a virtual store and file stream. Check for duplicate tempJPEG files.
Dim myStore = IsolatedStorageFile.GetUserStoreForApplication()
If myStore.FileExists(tempJPEG) Then
myStore.DeleteFile(tempJPEG)
End If
Dim myFileStream As IsolatedStorageFileStream = myStore.CreateFile(tempJPEG)
' Create a stream out of the sample JPEG file.
' For [Application Name] in the URI, use the project name that you entered
' in the previous steps. Also, TestImage.jpg is an example;
' you must enter your JPEG file name if it is different.
Dim sri As StreamResourceInfo = Nothing
Dim uri As New Uri("/projectName;component/Assets/1.jpg", UriKind.Relative)
sri = Application.GetResourceStream(uri)
' Create a new WriteableBitmap object and set it to the JPEG stream.
Dim bitmap As New BitmapImage()
bitmap.CreateOptions = BitmapCreateOptions.None
bitmap.SetSource(sri.Stream)
Dim wb As New WriteableBitmap(bitmap)
' Encode WriteableBitmap object to a JPEG stream.
wb.SaveJpeg(myFileStream, wb.PixelWidth, wb.PixelHeight, 0, 85)
myFileStream.Close()
' Create a new stream from isolated storage, and save the JPEG file to the media library on Windows Phone.
myFileStream = myStore.OpenFile(tempJPEG, FileMode.Open, FileAccess.Read)
' Save the image to the camera roll or saved pictures album.
Dim library As New MediaLibrary()
' Save the image to the saved pictures album.
Dim pic As Picture = library.SavePicture("dummyImage1.jpg", myFileStream)
MessageBox.Show("Image saved to saved pictures album")
myFileStream.Close()
I found on something like that:source https://msdn.microsoft.com.
// Informs when full resolution photo has been taken, saves to local media library and the local folder.
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
string fileName = savedCounter + ".jpg";
try
{ // Write message to the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Captured image available, saving photo.";
});
// Save photo to the media library camera roll.
library.SavePictureToCameraRoll(fileName, e.ImageStream);
// Write message to the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Photo has been saved to camera roll.";
});
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
// Save photo as JPEG to the local folder.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to the local folder.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
// Write message to the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Photo has been saved to the local folder.";
});
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
// Informs when thumbnail photo has been taken, saves to the local folder
// User will select this image in the Photos Hub to bring up the full-resolution.
public void cam_CaptureThumbnailAvailable(object sender, ContentReadyEventArgs e)
{
string fileName = savedCounter + "_th.jpg";
try
{
// Write message to UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Captured image available, saving thumbnail.";
});
// Save thumbnail as JPEG to the local folder.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the thumbnail to the local folder.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
// Write message to UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Thumbnail has been saved to the local folder.";
});
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}

Windows Phone reading in a pdf using binary reader

(Warning: First time on Stackoverflow) I want to be able to read in a pdf via binary but I encounter an issue when writing it back to the isolated storage. When it is written back to isolated storage and I try to open the file but I get an error message from adobe reader saying this is not a valid pdf. The file is 102 Kbytes but when I write it to isolated storage it is 108 Kbytes.
My reasoning for doing this is that I want to be able to split the pdfs. I have tried PDFsharp (doesn't open all pdf types). Here is my code:
public void pdf_split()
{
string prefix = #"/PDFread;component/";
string fn = originalFile;
StreamResourceInfo sr = Application.GetResourceStream(new Uri(prefix + fn, UriKind.Relative));
IsolatedStorageFile iStorage = IsolatedStorageFile.GetUserStoreForApplication();
using (var outputStream = iStorage.OpenFile(sFile, FileMode.CreateNew))
{
Stream resourceStream = sr.Stream;
long length = resourceStream.Length;
byte[] buffer = new byte[32];
int readCount = 0;
while (readCount < length)
{
int read = sr.Stream.Read(buffer, 0, buffer.Length);
readCount += read;
outputStream.Write(buffer, 0, read);
}
}
}

Adding Text on Image

I am trying to add some text on top of a photo take by the camera, and here is the method I am using, but unfortunately I either get a closedStream error, or that there is cross-thread access when I try use the dispatcher. Could someone please explain me what is going wrong?
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
DateTime dt = DateTime.Now;
string fileName = dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Second.ToString() + ".jpg";
try
{
// Save picture to the library camera roll.
library.SavePictureToCameraRoll(fileName, e.ImageStream);
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// load photo to writable bitmap
WriteableBitmap writeableBitmap = PictureDecoder.DecodeJpeg(e.ImageStream);
writeableBitmap.Invalidate();
var renderText = new TextBlock
{
Text = "Hello World",
FontSize = 72,
Foreground = new SolidColorBrush(Colors.White),
FontWeight = FontWeights.Black,
Width = 500,
Height = 100
};
writeableBitmap.Render(renderText, new TranslateTransform() { X = 100, Y = 300 });
writeableBitmap.Invalidate();
using (var ms = new MemoryStream())
{
writeableBitmap.SaveJpeg(ms, 1024, 768, 0, 100);
ms.Seek(0, SeekOrigin.Begin);
library.SavePicture("x" + fileName, ms);
}
// e.ImageStream.Close();
});
// Save picture as JPEG to isolated storage.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to isolated storage.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
With the code above I get the following error: Cannot access a closed Stream.
If i remove the Dispatcher, I get this error: Invalid cross-thread access.
Thanks.
place ui less code outside dispatcher scope.
or save your e.ImageStream to other stream can be gotted in dispatcher scope.
First, what is occurring?
Dispatcher.BeginInvoke postpones your code and tells the UI thread to execute it whenever it's available. Therefore, your e.ImageStream.Close(); line is executed before the code inside of the BeginInvoke. So when you're trying to read the contents of the stream, it's already closed.
Two ways to solve that:
Remove the e.ImageStream.Close(); from the finally block. But I don't know if the stream will remain open anyway.
If 1. doesn't work, copy the contents of the stream to a MemoryStream, then use this stream to create the WriteableBitmap:
var stream = new MemoryStream();
e.ImageStream.CopyTo(stream);
In both case, don't forget to close the stream when you're done creating the WriteableBitmap.

IsolatedStorage causes Memory to run out

hey.
I'm reading an image from Isolated Storage when the user clicks on an item like this:
using (IsolatedStorageFile currentIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var img = currentIsolatedStorage.OpenFile(fileName, FileMode.Open))
{
byte[] buffer = new byte[img.Length];
imgStream = new MemoryStream(buffer);
//read the imagestream into the byte array
int read;
while ((read = img.Read(buffer, 0, buffer.Length)) > 0)
{
img.Write(buffer, 0, read);
}
img.Close();
}
}
This works fine, but if I click back and forth between two images, the memory consumption keeps increasing and then runs out of memory. Is there a more efficient way of reading images from Isolated Storage? I could cache a few images in memory, but with hundreds of results, it ends up taking up memory anyway. Any suggestions?
Are you disposing the MemoryStream at some point? This is the only leak I could find.
Also, Stream has a CopyTo() method. Your code could be rewritten like:
using (IsolatedStorageFile currentIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var img = currentIsolatedStorage.OpenFile(fileName, FileMode.Open))
{
var imgStream = new MemoryStream(img.Length);
img.CopyTo(imgStream);
return imgStream;
}
}
This will save many many memory allocations.
EDIT:
And for Windows Phone (which does not define a CopyTo()), replaced the CopyTo() method with it's code:
using (IsolatedStorageFile currentIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var img = currentIsolatedStorage.OpenFile(fileName, FileMode.Open))
{
var imgStream = new MemoryStream(img.Length);
var buffer = new byte[Math.Min(1024, img.Length)];
int read;
while ((read = img.Read(buffer, 0, buffer.Length)) != 0)
imgStream.Write(buffer, 0, read);
return imgStream;
}
}
The main difference here is that the buffer is set relatively small (1K). Also, added an optimization by providing the constructor of MemoryStream with the length of the image. That makes MemoryStream pre-alloc the necessary space.

Categories