Extracting jfif image from 2d barcode - image-processing

I have data read from 2d bar code pdf417. It contains an embedded image in the format of (jfif), The image is not at the beginning of the decoded data it has some data fields and the image is somewhere after, the data fields does not seam to have fixed lengths. How can I extract the Image from the decoded data. I used ClearImage Library to decode the barcode and I have it as text and Hex.
Please help. Thank you in advance

I was able to extract the image thanks to many experts in StackOverflow, I have being reviewing their posts. The following code explains how to extract the image from a mixed binary file, the code is not so beautiful but it can do the job. It searches for (JFIF) image header and extracts it into an image file.
public static void ExtractImage(string fname)
{
try
{
FileStream fs = new FileStream(fname, FileMode.Open);
BinaryReader br = new BinaryReader(fs);
//read the first binary
char[] soi="Empty".ToCharArray();
br.BaseStream.Position = 0;
long imgpos = 0;
ushort r = 0;
while ((r = br.ReadUInt16())> 0)
{
Console.WriteLine(r);
if (r == 0xd8ff)
{
Console.WriteLine("Detcted----->");
imgpos = br.BaseStream.Position;
break;
//UInt16 jfif = br.ReadUInt16(); // JFIF marker
//Console.WriteLine("jfif " + jfif);
//if (jfif == 0xe0ff || jfif == 57855)
// Console.WriteLine(" also Detected--->");
}
}
//now copy to stream
FileStream str = new FileStream("bcimage.jpg", FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(str);
br.BaseStream.Position = imgpos-2;
int l = (int)(fs.Length - imgpos - 2);
bw.Write(br.ReadBytes(l));
fs.Close();
br.Close();
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}

Related

How to print bitmap without zoom from MVC controller in Debian

Document is printed from MVC controller to Debian Squeeze Linux server printer using code below in Mono.
Page in printer is A4.
Printed text in paper is too big and unsharp. Rightmost part of text is not visible since it does not fit to page.
If printed from Windows from .NET to HP Laserjet, output is correct.
So it looks like Mono or Samsung ML-331x Series printer zooms bitmap for unknown reason which causes too big and unsharp output.
How to fix this so that bitmap is printed like in windows ?
Possible solutions:
Best way would be to print formatted html directly. How to do it in server where there are no browser installed? wkhtmltopdf does not support printing. I posted it in How to print formatted html in Linux server
Maybe it is possible to use wkhtmltopdf convert html to pdf instead of bitmap I posted it as separate question in How to print pdf in debian linux from MVC controller
wkhtmltoimage can produce also other image formats. Maybe some other format is better ?
Maybe some wkhtmltoimage command line swithches like --width=750 or --dpi can fix this ?
public class Test: Controller
{
public ActionResult Print()
{
PrintOrderVormiga();
return new ContentResult() { Content = "OK" };
}
void PrintOrderVormiga()
{
StringBuilder sb = new StringBuilder();
sb.Insert(0, " test ", 500);
var bmp = ConvertHtmlToBMP("<html><body>" +sb.Tostring()+ "</body></html>");
var doc = new PrintDocument();
doc.PrinterSettings.PrinterName = "Samsung ML-331x Series";
doc.PrintPage += new PrintPageEventHandler(ProvideContent);
pageHeight = doc.DefaultPageSettings.PaperSize.Height;
using (bm = new Bitmap(new MemoryStream(bmp)))
{
lehti = (int)Math.Ceiling(bm.Height / (double)pageHeight);
doc.PrinterSettings.FromPage = 1;
doc.PrinterSettings.ToPage = lehti;
pageno = 0;
doc.Print();
}
}
int pageno, lehti;
int pageHeight;
Bitmap bm;
void ProvideContent(object sender, PrintPageEventArgs e)
{
Rectangle cropRect = new Rectangle(0, pageHeight * pageno++,
bm.Width, pageHeight);
Bitmap target = new Bitmap(cropRect.Width, cropRect.Height);
e.Graphics.DrawImage(bm, new Rectangle(0, 0, target.Width, target.Height),
cropRect,
GraphicsUnit.Pixel);
e.HasMorePages = pageno < lehti;
}
static byte[] ConvertHtmlToBMP(string html)
{
string programm = "wkhtmltoimage";
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
programm = "wkhtmltoimage-amd64";
}
var p = new Process
{
StartInfo =
{
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
UseShellExecute = false,
FileName = Environment.OSVersion.Platform == PlatformID.Win32NT ?
"C:\\Program Files\\wkhtmltopdf\\bin\\" + programm + ".exe" : "/usr/bin/" + programm
}
};
p.StartInfo.Arguments = "--format bmp --disable-javascript --quality 10";
p.StartInfo.Arguments += " - -";
p.Start();
using (var stream = p.StandardInput)
{
byte[] ibuffer = System.Text.Encoding.UTF8.GetBytes(html);
stream.BaseStream.Write(ibuffer, 0, ibuffer.Length);
stream.WriteLine();
}
var buffer = new byte[32768];
byte[] file;
using (var ms = new MemoryStream())
{
while (true)
{
var read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
if (read <= 0)
{
break;
}
ms.Write(buffer, 0, read);
}
file = ms.ToArray();
}
p.WaitForExit(60000);
var returnCode = p.ExitCode;
p.Close();
return file;
}
}
You can use this HTML to PDF Converter for Mono solution from EvoPdf. The C# code for converting a HTML to PDF in Mono is:
// create the HTML to PDF converter object
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter(serverIPAddress, serverPortNumber);
// set service password if necessary
if (serverPassword.Length > 0)
htmlToPdfConverter.ServicePassword = serverPassword;
// set PDF page size
htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
// set PDF page orientation
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
// convert the HTML page from given URL to PDF in a buffer
byte[] pdfBytes = htmlToPdfConverter.ConvertUrl(urlToConvert);

Not able to properly download files from azure storage and data are lost too when downloading files

I have 2 files saved on Azure blob storage:
Abc.txt
Pqr.docx
Now i want to create zip files of this 2 files and allow user to download.
I have saved this in my database table field like this:
Document
Abc,Pqr
Now when i click on download then i am getting file like below with no data in it and file extension are lost too like below:
I want user to get exact file(.txt,.docx) in zip when user download zip file.
This is my code:
public ActionResult DownloadImagefilesAsZip()
{
string documentUrl = repossitory.GetDocumentsUrlbyId(id);//output:Abc.txt,Pqr.Docx
if (!string.IsNullOrEmpty(documentUrl))
{
string[] str = documentUrl.Split(',');
if (str.Length > 1)
{
using (ZipFile zip = new ZipFile())
{
int cnt = 0;
foreach (string t in str)
{
if (!string.IsNullOrEmpty(t))
{
Stream s = this.GetFileContent(t);
zip.AddEntry("File" + cnt, s);
}
cnt++;
}
zip.Save(outputStream);
outputStream.Position = 0;
return File(outputStream, "application/zip", "all.zip");
}
}
}
public Stream GetFileContent(string fileName)
{
CloudBlobContainer container = this.GetCloudBlobContainer();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
var stream = new MemoryStream();
blockBlob.DownloadToStream(stream);
return stream;
}
public CloudBlobContainer GetCloudBlobContainer()
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"].ToString());
CloudBlobClient blobclient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer blobcontainer = blobclient.GetContainerReference("Mystorage");
if (blobcontainer.CreateIfNotExists())
{
blobcontainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
}
blobcontainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
return blobcontainer;
}
I want same file to be downloaded when user download zip file.
Can anybody help me with this??
I'm not a web dev, but hopefully this will help. This snippet of code is in a method where I download a list of blobs into a zip file archive using a stream. The list of files had the slashes in all directions, so there's code in here to fix this, and to make sure I'm getting the blob reference with the right text (no URL, and no opening slash if the blob is in a "folder").
I suspect your problem is not using a memory stream or a binary writer. Specificity helps sometimes. Good luck.
using (ZipArchive zipFile = ZipFile.Open(outputZipFileName, ZipArchiveMode.Create))
{
foreach (string oneFile in listOfFiles)
{
//Need the filename, complete with relative path. Make it like a file name on disk, with backwards slashes.
//Also must be relative, so can't start with a slash. Remove if found.
string filenameInArchive = oneFile.Replace(#"/", #"\");
if (filenameInArchive.Substring(0, 1) == #"\")
filenameInArchive = filenameInArchive.Substring(1, filenameInArchive.Length - 1);
//blob needs slashes in opposite direction
string blobFile = oneFile.Replace(#"\", #"/");
//take first slash off of the (folder + file name) to access it directly in blob storage
if (blobFile.Substring(0, 1) == #"/")
blobFile = oneFile.Substring(1, oneFile.Length - 1);
var cloudBlockBlob = this.BlobStorageSource.GetBlobRef(blobFile);
if (!cloudBlockBlob.Exists()) //checking just in case
{
//go to the next file
//should probably trace log this
//add the file name with the fixed slashes rather than the raw, messed-up one
// so anyone looking at the list of files not found doesn't think it's because
// the slashes are different
filesNotFound.Add(blobFile);
}
else
{
//blob listing has files with forward slashes; that's what the zip file requires
//also, first character should not be a slash (removed it above)
ZipArchiveEntry newEntry = zipFile.CreateEntry(filenameInArchive, CompressionLevel.Optimal);
using (MemoryStream ms = new MemoryStream())
{
//download the blob to a memory stream
cloudBlockBlob.DownloadToStream(ms);
//write to the newEntry using a BinaryWriter and copying it 4k at a time
using (BinaryWriter entry = new BinaryWriter(newEntry.Open()))
{
//reset the memory stream's position to 0 and copy it to the zip stream in 4k chunks
//this keeps the process from taking up a ton of memory
ms.Position = 0;
byte[] buffer = new byte[4096];
bool copying = true;
while (copying)
{
int bytesRead = ms.Read(buffer, 0, buffer.Length);
if (bytesRead > 0)
{
entry.Write(buffer, 0, bytesRead);
}
else
{
entry.Flush();
copying = false;
}
}
}//end using for BinaryWriter
}//end using for MemoryStream
}//if file exists in blob storage
}//end foreach file
} //end of using ZipFileArchive
There are two things I noticed:
Once you read the blob contents in stream, you are not resetting that stream's position to 0. Thus all files in your zip are of zero bytes.
When calling AddEntry, you may want to specify the name of the blob there instead of "File"+cnt.
Please look at the code below. It's a console app that creates the zip file and writes it on the local file system.
static void SaveBlobsToZip()
{
string[] str = new string[] { "CodePlex.png", "DocumentDB.png" };
var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var blobClient = account.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("images");
using (var fs = new FileStream("D:\\output.zip", FileMode.Create))
{
fs.Position = 0;
using (var ms1 = new MemoryStream())
{
using (ZipFile zip = new ZipFile())
{
int cnt = 0;
foreach (string t in str)
{
var ms = new MemoryStream();
container.GetBlockBlobReference(t).DownloadToStream(ms);
ms.Position = 0;//This was missing from your code
zip.AddEntry(t, ms);//You may want to give the name of the blob here.
cnt++;
}
zip.Save(ms1);
}
ms1.Position = 0;
ms1.CopyTo(fs);
}
}
}
UPDATE
Here's the code in the MVC application (though I am not sure it is the best code :) but it works). I modified your code a little bit.
public ActionResult DownloadImagefilesAsZip()
{
string[] str = new string[] { "CodePlex.png", "DocumentDB.png" }; //repossitory.GetDocumentsUrlbyId(id);//output:Abc.txt,Pqr.Docx
CloudBlobContainer blobcontainer = GetCloudBlobContainer();// azureStorageUtility.GetCloudBlobContainer();
MemoryStream ms1 = new MemoryStream();
using (ZipFile zip = new ZipFile())
{
int cnt = 0;
foreach (string t in str)
{
var ms = new MemoryStream();
CloudBlockBlob blockBlob = blobcontainer.GetBlockBlobReference(t);
blockBlob.DownloadToStream(ms);
ms.Position = 0;//This was missing from your code
zip.AddEntry(t, ms);//You may want to give the name of the blob here.
cnt++;
}
zip.Save(ms1);
}
ms1.Position = 0;
return File(ms1, "application/zip", "all.zip");
}
I have seen people using ICSharpZip library, take a look at this piece of code
public void ZipFilesToResponse(HttpResponseBase response, IEnumerable<Asset> files, string zipFileName)
{
using (var zipOutputStream = new ZipOutputStream(response.OutputStream))
{
zipOutputStream.SetLevel(0); // 0 - store only to 9 - means best compression
response.BufferOutput = false;
response.AddHeader("Content-Disposition", "attachment; filename=" + zipFileName);
response.ContentType = "application/octet-stream";
foreach (var file in files)
{
var entry = new ZipEntry(file.FilenameSlug())
{
DateTime = DateTime.Now,
Size = file.Filesize
};
zipOutputStream.PutNextEntry(entry);
storageService.ReadToStream(file, zipOutputStream);
response.Flush();
if (!response.IsClientConnected)
{
break;
}
}
zipOutputStream.Finish();
zipOutputStream.Close();
}
response.End();
}
Taken from here generate a Zip file from azure blob storage files

Make picture from base64 on client-side

How to make a picture from a base64-string to send it to server by using HttpRequest.request?
For example, I have the following base64-string:
'data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
Instead of sending it I would like to post a jpeg to server? Is it possible?
Convert Base64 to bytes
How to native convert string -> base64 and base64 -> string
Upload binary as image
Dart how to upload image
EDIT
(this is the server part, I have to look for the client part)
Client code:
var request = new HttpRequest()
..open("POST", 'http://yourdomain.com/yourservice')
..overrideMimeType("image/your-imagetype") // might be that this doesn't work than use the next line
..setRequestHeader("Content-Type", "image/your-imagetype")
..onProgress.listen((e) => ...);
request
..onReadyStateChange.listen((e) => ...)
..onLoad.listen((e) => ...)
..send(yourBinaryDataAsUint8List);
Convert to image:
I think you need to create a dataURL like show here How to upload a file in Dart?
and then use the created dataUrl as src in code like shown here How to load an image in Dart
see also Base64 png data to html5 canvas as #DanFromGermany mentioned in his comment on the question.
It may be necessary to convert List to Uint8List in between.
Please add a comment if you need more information.
I like decoding on server-side, but anyways.
Basically you just split a text you got from canvas.toDataUrl(), convert the Base64 text to binary data, then send it to server. Use "CryptoUtils" in "crypto" library to treat Base64. I haven't tested with any proper http server, but this code should work.
// Draw an on-memory image.
final CanvasElement canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
final CanvasRenderingContext2D context = canvas.getContext('2d');
final CanvasGradient gradient = context.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, "#1e4877");
gradient.addColorStop(0.5, "#4584b4");
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(10, 10);
context.lineTo(240, 240);
context.lineWidth = 10;
context.strokeStyle = '#ff0000';
context.stroke();
// Convert the image to data url
final String dataUrl = canvas.toDataUrl('image/jpeg');
final String base64Text = dataUrl.split(',')[1];
final Uint8ClampedList base64Data = new Uint8ClampedList.fromList(
CryptoUtils.base64StringToBytes(base64Text));
// Now send the base64 encoded data to the server.
final HttpRequest request = new HttpRequest();
request
..open("POST", 'http://yourdomain.com/postservice')
..onReadyStateChange.listen((_) {
if (request.readyState == HttpRequest.DONE &&
(request.status == 200 || request.status == 0)) {
// data saved OK.
print("onReadyStateChange: " + request.responseText); // output the response from the server
}
})
..onError.listen((_) {
print("onError: " + _.toString());
})
..send(base64Data);
I posted a complete snippet here. https://gist.github.com/hyamamoto/9391477
I found the Blob conversion part not to be working (anymore?).
The code from here does work:
Blob createImageBlob(String dataUri) {
String byteString = window.atob(dataUri.split(',')[1]);
String mimeString = dataUri.split(',')[0].split(':')[1].split(';')[0];
Uint8List arrayBuffer = new Uint8List(byteString.length);
Uint8List dataArray = new Uint8List.view(arrayBuffer.buffer);
for (var i = 0; i < byteString.length; i++) {
dataArray[i] = byteString.codeUnitAt(i);
}
Blob blob = new Blob([arrayBuffer], mimeString);
return blob;
}

Generate torrent links from server-side

I don't know a lot about torrents, at least not enough to understand how certain websites can offer both a normal download link and a torrent link to download a file uploaded by a user.
Is generating a torrent link something common and simple to achieve. Would I need a server installation?
I've made an ugly C# implementation from a Java source, and to make sure some of my encoded variables were correct, I used NBEncode from Lars Warholm.
// There are 'args' because I'm using it from command-line. (arg0 is an option not used here)
// Source file
args[1] = Directory.GetCurrentDirectory() + args[1];
// Name to give to the torrent file
args[2] = Directory.GetCurrentDirectory() + args[2];
var inFileStream = new FileStream(args[1], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var filename = args[2];
//BEncoding with NBEencode
var transform = new BObjectTransform();
MemoryStream s = new MemoryStream();
OSS.NBEncode.Entities.BDictionary bod = new OSS.NBEncode.Entities.BDictionary();
OSS.NBEncode.Entities.BDictionary meta = new OSS.NBEncode.Entities.BDictionary();
// Preparing the first part of the file by creating BEncoded objects
string announceURL = "https://www.mysite.com/announce";
int pieceLength = 512 * 1024;
bod.Value.Add(new BByteString("name"), new OSS.NBEncode.Entities.BByteString(filename));
bod.Value.Add(new BByteString("length"), new OSS.NBEncode.Entities.BInteger(inFileStream.Length));
bod.Value.Add(new BByteString("piece length"), new OSS.NBEncode.Entities.BInteger(pieceLength));
bod.Value.Add(new BByteString("pieces"), new BByteString(""));
meta.Value.Add(new BByteString("announce"), new BByteString(announceURL));
meta.Value.Add(new BByteString("info"), bod);
byte[] pieces = hashPieces(args[1], pieceLength);
transform.EncodeObject(meta, s);
s.Close();
// Notice that we finish with a dictionary entry of "pieces" with an empty string.
byte[] trs = s.ToArray();
s.Close();
inFileStream.Close();
// I don't know how to write array of bytes using NBEncode library, so let's continue manually
// All data has been written a MemoryStreamp, except the byte array with the hash info about each parts of the file
Stream st = new FileStream(filename + ".torrent", FileMode.Create);
BinaryWriter bw = new BinaryWriter(st);
// Let's write these Bencoded variables to the torrent file:
// The -4 is there to skip the current end of the file created by NBEncode
for (int i = 0; i < trs.Length - 4; i++)
{
bw.BaseStream.WriteByte(trs[i]);
}
// We'll add the length of the pieces SHA1 hashes:
var bt = stringToBytes(pieces.Length.ToString() + ":");
// Then we'll close the Bencoded dictionary with 'ee'
var bu = stringToBytes("ee");
// Let's append this to the end of the file.
foreach (byte b in bt)
{
bw.BaseStream.WriteByte(b);
}
foreach (byte b in pieces)
{
bw.BaseStream.WriteByte(b);
}
foreach (byte b in bu)
{
bw.BaseStream.WriteByte(b);
}
bw.Close();
st.Close();
// That's it.
}
Functions used:
private static byte[] stringToBytes(String str)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[] bytes = encoding.GetBytes(str);
return bytes;
}
private static byte[] hashPieces(string file, int pieceLength)
{
SHA1 sha1 = new SHA1CryptoServiceProvider();
StreamReader inn = new StreamReader(file);
MemoryStream pieces = new MemoryStream();
byte[] bytes = new byte[pieceLength];
byte[] digest = new byte[20];
int pieceByteCount = 0, readCount = inn.BaseStream.Read(bytes, 0, pieceLength);
while (readCount != 0)
{
pieceByteCount += readCount;
digest = sha1.ComputeHash(bytes, 0, readCount);
if (pieceByteCount == pieceLength)
{
pieceByteCount = 0;
foreach (byte b in digest)
{
pieces.WriteByte(b);
}
}
readCount = inn.BaseStream.Read(bytes, 0, pieceLength - pieceByteCount);
}
inn.Close();
if (pieceByteCount > 0)
foreach (byte b in digest)
{
pieces.WriteByte(b);
}
return pieces.ToArray();
}
It depends on how you're trying to create it. If you run a website, and want to generate torrent files from uploaded files, then you'll obviously need server-side code.
Generating a torrent file involves: adding the files you want to the torrent, and adding tracker info. Some popular trackers are:
http://open.tracker.thepiratebay.org/announce
http://www.torrent-downloads.to:2710/announce
To create the .torrent file, you'll have to read the about the format of the file. A piece of Java that generates .torrent files is given at https://stackoverflow.com/a/2033298/384155

POST image from webcam in Silverlight window to MVC Controller

I have an MVC 4 application with a button for taking a photo that opens up a new window with javascript which contains a silverlight application in it. The silverlight application can then take a photo using the webcam and store it as a Writeable Bitmap. What I would like to do is then push that bitmap onto an action in my controller for saving to the database and refreshing the view.
I know I need to send the image as a post to my controller, but any code examples or suggestions on how I would go about doing that would be greatly appreciated. I think it should work as follows, Button Click for saving the image in my silverlight application would call a POST to the MVC controller and attach the image stream as a parameter in the controller, and the controller can then take the stream and push it up to the database then I can close the silverlight window. Just not sure how to go about coding that.
You could send the image using a WebClient. Let's suppose that you have the image inside your Silverlight application in a byte array:
byte[] image = ... get the image from your webcam
var client = new WebClient();
var uri = new Uri("http://example.com/photos/upload");
client.OpenWriteCompleted += (sender, e) =>
{
var buffer = (byte[])e.UserState;
e.Result.Write(buffer, 0, buffer.Length);
e.Result.Close();
};
client.OpenWriteAsync(uri, "POST", image);
and on the MVC side:
[HttpPost]
public ActionResult Upload()
{
byte[] image = new byte[Request.InputStream.Length];
Request.InputStream.Read(image, 0, image.Length);
// TODO: do something with the uploaded image here ...
}
Thank you for the reply. This is exactly what I was looking for, however ive run into a problem. Silverlight gives me the webcam snapshot as a WriteableBitmap type. Which I then tried to convert to a byte[] array before sending it over to MVC. It is saving to the database successfully, however it does not appear to be a valid image when I try to pull it back out from the database and display it. Is there an issue that you can see with my conversion code? Or perhaps can I send it over as an image type, or can I only send over byte[] arrays through http posts like this?
In my Silverlight application:
private void SendImage()
{
var client = new WebClient();
var uri = new Uri("http://localhost:4600/GuestBadge/GetCameraImage");
client.OpenWriteCompleted += (sender, e) =>
{
var buffer = (byte[])e.UserState;
e.Result.Write(buffer, 0, buffer.Length);
e.Result.Close();
};
client.OpenWriteAsync(uri, "POST", ToByteArray(SnapShot));
}
public static byte[] ToByteArray(WriteableBitmap bmp)
{
// Init buffer
int w = bmp.PixelWidth;
int h = bmp.PixelHeight;
int[] p = bmp.Pixels;
int len = p.Length;
byte[] result = new byte[4 * w * h];
// Copy pixels to buffer
for (int i = 0, j = 0; i < len; i++, j += 4)
{
int color = p[i];
result[j + 0] = (byte)(color >> 24); // A
result[j + 1] = (byte)(color >> 16); // R
result[j + 2] = (byte)(color >> 8); // G
result[j + 3] = (byte)(color); // B
}
return result;
}
And in my controller:
[HttpPost]
public ActionResult GetCameraImage()
{
byte[] image = new byte[Request.InputStream.Length];
Request.InputStream.Read(image, 0, image.Length);
var getPerson = (from a in db.Persons where a.PersonID == 3 select a).FirstOrDefault();
getPerson.Picture = image;
db.SaveChanges();
return null;
}
I ended up using FJCore http://code.google.com/p/fjcore/ to encode my WriteableBitmap into JPEG and then converted that to BASE64 using code I found at this question Using FJCore to encode Silverlight WriteableBitmap THANKS!. Then in turn converted that out to a byte[] array and sent it to MVC using your code and now its working great. I'm pretty new at all this stuff and didn't quite understand the encoding process enough before. Below is the code I used for this. Thanks again for your help!
private static string GetBase64Jpg(WriteableBitmap bitmap)
{
int width = bitmap.PixelWidth;
int height = bitmap.PixelHeight;
int bands = 3;
byte[][,] raster = new byte[bands][,];
for (int i = 0; i < bands; i++)
{
raster[i] = new byte[width, height];
}
for (int row = 0; row < height; row++)
{
for (int column = 0; column < width; column++)
{
int pixel = bitmap.Pixels[width * row + column];
raster[0][column, row] = (byte)(pixel >> 16);
raster[1][column, row] = (byte)(pixel >> 8);
raster[2][column, row] = (byte)pixel;
}
}
ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };
FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);
MemoryStream stream = new MemoryStream();
JpegEncoder encoder = new JpegEncoder(img, 90, stream);
encoder.Encode();
stream.Seek(0, SeekOrigin.Begin);
byte[] binaryData = new Byte[stream.Length];
long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);
string base64String =
System.Convert.ToBase64String(binaryData,
0,
binaryData.Length);
return base64String;
}
private void SendImage()
{
var client = new WebClient();
var uri = new Uri("http://localhost:4600/GuestBadge/GetCameraImage");
client.OpenWriteCompleted += (sender, e) =>
{
var buffer = (byte[])e.UserState;
e.Result.Write(buffer, 0, buffer.Length);
e.Result.Close();
};
client.OpenWriteAsync(uri, "POST", Convert.FromBase64String(GetBase64Jpg(SnapShot)));
}

Resources