Compress and save base64 image on Windows Phone 8.1 - windows-phone

I have implemented the following solution to compress a base 64 image and get back the new base 64 string. It works fine in Windows Phone 8.0 but targeting Windows Phone 8.1 it seems that there are changes in the environment.
The WriteableBitmap has no constructor for a BitmapImage and the WriteableBitmap has no function SaveJpeg. I know that SaveJpeg is an extension, is there a way to add this extension to Windows Phone 8.1? Or is there any API which I can use? What do I have to change to make this 8.1 compatible? I'm kinda stuck with it here :-/
public static string Compress(String base64String, int compression)
{
String compressedImage;
byte[] imageBytes = Convert.FromBase64String(base64String);
MemoryStream memoryStream = new MemoryStream(imageBytes, 0, imageBytes.Length);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(memoryStream.AsRandomAccessStream());
WriteableBitmap bmp = new WriteableBitmap(bitmapImage);
int height = bmp.PixelHeight;
int width = bmp.PixelWidth;
int orientation = 0;
int quality = 100 - compression;
MemoryStream targetStream = new MemoryStream();
bmp.SaveJpeg(targetStream, width, height, orientation, quality);
byte[] targetImage = targetStream.ToArray();
compressedImage = System.Convert.ToBase64String(targetImage);
return compressedImage;
}

In WP8.1 Runtime I've used BitmapPropertySet to define a level of compression. Here below is sample code operating on Streams:
/// <summary>
/// Method compressing image stored in stream
/// </summary>
/// <param name="sourceStream">stream with the image</param>
/// <param name="quality">new quality of the image 0.0 - 1.0</param>
/// <returns></returns>
private async Task<IRandomAccessStream> CompressImageAsync(IRandomAccessStream sourceStream, double newQuality)
{
// create bitmap decoder from source stream
BitmapDecoder bmpDecoder = await BitmapDecoder.CreateAsync(sourceStream);
// bitmap transform if you need any
BitmapTransform bmpTransform = new BitmapTransform() { ScaledHeight = newHeight, ScaledWidth = newWidth, InterpolationMode = BitmapInterpolationMode.Cubic };
PixelDataProvider pixelData = await bmpDecoder.GetPixelDataAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, bmpTransform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage);
InMemoryRandomAccessStream destStream = new InMemoryRandomAccessStream(); // destination stream
// define new quality for the image
var propertySet = new BitmapPropertySet();
var quality = new BitmapTypedValue(newQuality, PropertyType.Single);
propertySet.Add("ImageQuality", quality);
// create encoder with desired quality
BitmapEncoder bmpEncoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, destFileStream, propertySet);
bmpEncoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, newHeight, newWidth, 300, 300, pixelData.DetachPixelData());
await bmpEncoder.FlushAsync();
return destStream;
}

Related

Watermarking pdf on document upload

I want to add a functionality of adding a watermark using itextSharp library to the pdf document that is being added to the library. For this I created an event listener that is triggered when item is being added. The code is as follows :
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;
namespace ProjectPrac.WaterMarkOnUpload
{
/// <summary>
/// List Item Events
/// </summary>
public class WaterMarkOnUpload : SPItemEventReceiver
{
/// <summary>
/// An item is being added.
/// </summary>
public override void ItemAdding(SPItemEventProperties properties)
{
base.ItemAdding(properties);
string watermarkedFile = "Watermarked.pdf";
// Creating watermark on a separate layer
// Creating iTextSharp.text.pdf.PdfReader object to read the Existing PDF Document
PdfReader reader1 = new PdfReader("C:\\Users\\Desktop\\Hello.pdf"); //THE RELATIVE PATH
using (FileStream fs = new FileStream(watermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None))
// Creating iTextSharp.text.pdf.PdfStamper object to write Data from iTextSharp.text.pdf.PdfReader object to FileStream object
using (PdfStamper stamper = new PdfStamper(reader1, fs))
{
// Getting total number of pages of the Existing Document
int pageCount = reader1.NumberOfPages;
// Create New Layer for Watermark
PdfLayer layer = new PdfLayer("WatermarkLayer", stamper.Writer);
// Loop through each Page
for (int i = 1; i <= pageCount; i++)
{
// Getting the Page Size
Rectangle rect = reader1.GetPageSize(i);
// Get the ContentByte object
PdfContentByte cb = stamper.GetUnderContent(i);
// Tell the cb that the next commands should be "bound" to this new layer
cb.BeginLayer(layer);
cb.SetFontAndSize(BaseFont.CreateFont(
BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 50);
PdfGState gState = new PdfGState();
gState.FillOpacity = 0.25f;
cb.SetGState(gState);
cb.SetColorFill(BaseColor.BLACK);
cb.BeginText();
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Confidential", rect.Width / 2, rect.Height / 2, 45f);
cb.EndText();
// Close the layer
cb.EndLayer();
}
}
}
I want to know how to add the path without hardcoding it here :
PdfReader reader1 = new PdfReader("C:\\Users\\Desktop\\Hello.pdf"); //THE RELATIVE PATH
And then uploading the watermarked document to the library and not the original pdf.
I know that it can also be done through workflow but I am pretty new to sharepoint. So if at all you have an answer that has workflow in it please give the link that explains the workflow for automating the pdf watermarking.
You don't need to have workflow to achieve what you are looking for:
First, use ItemAdded event instead of ItemAdding. Then you can access SPFile associated with updated list item.
public override void ItemAdded(SPItemEventProperties properties)
{
var password = string.Empty; //or you put some password handling
SPListItem listItemToFile = properties.Listitem;
SPFile pdfOriginalFile = listItemToFile.File;
//get byte[] of uploaded file
byte[] contentPdfOriginalFile = pdfOriginalFile.OpenBinary();
//create reader from byte[]
var pdfReader = new PdfReader(new RandomAccessFileOrArray(contentPdfOriginalFile), password);
using (var ms = new MemoryStream()) {
using (var stamper = new PdfStamper(pdfReader, ms, '\0', true)) {
// do your watermarking stuff
...
// resuming SP stuff
}
var watermarkedPdfContent = ms.ToArray();
base.EventFiringEnabled = false; //to prevent other events being fired
var folder = pdfOriginalFile.ParentFolder;//you want to upload to the same place
folder.Files.Add(contentPdfOriginalFile.Name, fs.ToArray(),true);
base.EventFiringEnabled = true;
}
}
I probably did a typo or two since I didn't run this code. However, it should give you an idea.

Using wcf how to upload a image

using wcf/wcf web services to upload a images give me with example?
In my project i want to upload image by using WCF
Basically you should use WCF streaming.
[ServiceContract]
public interface ITransferService
{
[OperationContract]
void UploadFile(RemoteFileInfo request);
}
public void UploadFile(RemoteFileInfo request)
{
FileStream targetStream = null;
Stream sourceStream = request.FileByteStream;
string uploadFolder = #"C:\\upload\\";
string filePath = Path.Combine(uploadFolder, request.FileName);
using (targetStream = new FileStream(filePath, FileMode.Create,
FileAccess.Write, FileShare.None))
{
//read from the input stream in 65000 byte chunks
const int bufferLen = 65000;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
// save to output stream
targetStream.Write(buffer, 0, count);
}
targetStream.Close();
sourceStream.Close();
}
}
The easiest way is to convert the image to a byte array before sending it, and then converting it back to an image on the destination site.
Here are two methods for doing just that:
public byte[] ImageToByteArray( Image image)
{
var ms = new MemoryStream();
image.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
public static Image ByteArrayToImage(byte[] byteArray)
{
var ms = new MemoryStream(byteArray);
return Image.FromStream(ms);
}
That means your web service can have a method something like this:
public void UploadImage( byte[] imageData )
{
var image = ByteArrayToImage( imageData );
//save image to disk here, or do whatever you like with it
}

Convert BitmapImage to Byte[] in Silverlight4

can any one has idea. how to convert BitmapImage to Byte[] in silverlight4 application
i have one image file in .xap file.
BitmapImage bi = new BitmapImage(new Uri("images/GRed.png", UriKind.Relative));
now i want to convert BitmapImage to Byte[] and save in to db as binary format.
private byte[] ToByteArray(BitmapImage bi)
{
WriteableBitmap bmp = new WriteableBitmap(bi);
int[] p = bmp.Pixels;
int len = p.Length * 4;
byte[] result = new byte[len];
Buffer.BlockCopy(p, 0, result, 0, len);
return result;
}

Scaling PNG images in silverlight

In my application, I am accepting an image from user. If the image is more than specified size, then I am scaling down to appropriate size and saving in database. I am using FJCore library for scaling image. The library works well with JPEG images. But it does not support PNG images. It seems that library is not being updated recently. Any idea how can this be done in Silverlight?
What you can do is create a new Image element and set its source to a Writeable bitmap created from the stream but don't add this Image element to the visual tree. Create another WriteableBitmap of the final size you want and then call render on this WriteableBitmap passing the Image element and a ScaleTransform to resize the image to the appropriate size. You can then use the second WriteableBitmap as the source for a second Image element and add that to the visual tree.
I used WriteableBitmapEx project do acheive this. Here is the code if someone needs it.
private void ShowCustomImageButton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openDialog = new OpenFileDialog();
openDialog.Multiselect = false;
openDialog.Filter = "PNG Files|*.PNG";
bool? userClickedOK = openDialog.ShowDialog();
if (userClickedOK == true)
{
BitmapImage image = new BitmapImage();
// get image that user has selected.
image.SetSource(openDialog.File.OpenRead());
WriteableBitmap wrtbmp = new WriteableBitmap(image);
// resize image if needed.
wrtbmp = wrtbmp.Resize(64, 64, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
var img = wrtbmp.ToImage();
// convert image into file stream.
Stream filestram = img.ToStream();
filestram.Position = 0;
using (filestram)
{
// convert file stream into memory stream.
var memoryStream = new MemoryStream();
byte[] aryBuffer = new byte[16384];
int nRead = filestram.Read(aryBuffer, 0, aryBuffer.Length);
while (nRead > 0)
{
memoryStream.Write(aryBuffer, 0, nRead);
nRead = filestram.Read(aryBuffer, 0, aryBuffer.Length);
}
// use following line to convert in bytes and save into database.
memoryStream.ToArray();
imgCustomImage.Source = CreateBitmapImage(memoryStream);
}
}
}
private BitmapImage CreateBitmapImage(MemoryStream memoryStream)
{
if ((memoryStream == null) || (memoryStream.Length == 0))
return null;
var image = new BitmapImage();
image.SetSource(memoryStream);
return image;
}

Silverlight 4.0: How to convert byte[] to image?

public Image Base64ToImage(string base64String)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
MemoryStream ms = new MemoryStream(imageBytes, 0,
imageBytes.Length);
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
System.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
return image;
}
I want to convert byte[] to image, however System.Drawing.Image is not supported in Silverlight. Any alternative?
You need to create an ImageSource and assign that to an Image control or use an ImageBrush to set on the background. BitmapImage is located in the System.Windows.Media.Imaging namespace.
byte[] imageBytes = Convert.FromBase64String(base64String);
using (MemoryStream ms = new MemoryStream(imageBytes, 0,
imageBytes.Length))
{
BitmapImage im = new BitmapImage();
im.SetSource(ms);
this.imageControl.Source = im;
}
or for the ImageBrush
byte[] imageBytes = Convert.FromBase64String(base64String);
using (MemoryStream ms = new MemoryStream(imageBytes, 0,
imageBytes.Length))
{
BitmapImage im = new BitmapImage();
im.SetSource(ms);
imageBrush.ImageSource = im;
this.BoxBorder.Background = imageBrush;
}
this code can convert image to byte[]
BitmapImage imageSource = new BitmapImage();
Stream stream = openFileDialog1.File.OpenRead();
BinaryReader binaryReader = new BinaryReader(stream);
currentImageInBytes = new byte[0];
currentImageInBytes = binaryReader.ReadBytes((int)stream.Length);
stream.Position = 0;
imageSource.SetSource(stream);
and this code can convert byte[] to image
public void Base64ToImage(byte[] imageBytes)
{
using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
BitmapImage im = new BitmapImage();
im.SetSource(ms);
img.Source = im;
}
}
An other way:
public static BitmapImage ConvertStreamToImage(Stream stream)
{
BitmapImage _resultImage = new BitmapImage();
_resultImage.SetSource(stream);
return _resultImage;
}
which uses these name spaces:
using System.IO;
using System.Windows.Media.Imaging;