Error when converting byte array to System.Drawing.Image - c#

I'm using C# 4.5 Framework and MySql
MySqlDataReader reader = Command.ExecuteReader();
if (reader.Read())
{
byte[] ReturnImage = reader["Photo"] as byte[];
MemoryStream ms = new MemoryStream(ReturnImage);
Image Photo = Image.FromStream(ms); //Error is in this statement!!
}
When this stmt is executed the following error displays "Parameter is not valid"
I couldn't find the answer from the web.. Somebody Pls help..

The most likely cause here is that the contents of the longblob are not the raw image bytes. Rather than go around in circles, the first thing to do is to: compare them. For example, you say (comments) that the data came from a jpg file, via OpenFileDialog. In that case, compare them. Check that you have successfully stored and retrieved the image.
Let's suppose that the file in question is c:\Some\Photo.jpg - stored etc per whatever process. In that case, you should be able to check the contents are the same. Until the following reports success, all bets are off:
byte[] original = File.ReadAllBytes(#"c:\Some\Photo.jpg");
byte[] ReturnImage = reader["Photo"] as byte[];
if(Convert.ToBase64String(original) == Convert.ToBase64String(ReturnImage)) {
Console.WriteLine("Success; the contents match");
} else {
Console.WriteLine("Failure; the contents are different");
}
If this reports "Failure; the contents are different", then the error is most likely in one of:
the code where you prepare the image to be stored (populating parameters etc)
the stored procedure that does the storage
the code that fetches the image back from the database
If this reports "Success; the contents match": then and only then is it meaningful to look at the code that attempts to load the Image. In this scenario, and assuming that c:\Some\Photo.jpg loads in most other image loading tools ("paint", etc) - then it is possible that Image doesn't recognise the subformat. But my guess is that it is going to say "Failure; the contents are different".
Note that Convert.ToBase64String here is used solely as a lazy way to check binary equivalence. You wouldn't use it like this in production code, but it is fine for this purpose.

Related

bulk image storage in sql server 2008

I am creating a asp.net app in C# .net 4.0 using VS 2008 & MS SQL Server 2008 R2. I want to upload image(.bmp) for each order and store it in DB corresponding to its order. It must be retrieved when View functionally is requested.
My requirement is to store images and retrieve it. Number of orders might be around 50 orders each day. It might be over be overhead as number increases. Please suggest me efficient method to overcome memory issue.
Well, you can either store them in the database as varbinary(max) or store a URL to a file. If you have 50 images a day, it might be better to go for the file and URL method.
There's advantages and disadvantages to both. But as you said you want to store them in the DB:
I think one big one on the database storage is that no one can just come along and rename / delete the folder, or mess with the files in it.
Another good point for the database is that you can restore a database and not have to try to keep the keep the folder in sync.
You can use an ImageConverter to convert between an array of bytes to an image and back
var stream = new MemoryStream();
var imageData = DataAccess.GetImageData(); //Returns a System.Linq.Binary for me
var imgageBinaryData = imageData.ImageData.ToArray(); //This returns a byte array
var img = Image.FromStream(stream); //Here is your image ready for displaying
Then to go back something like
var stream = new MemoryStream();
img.Save(stream,System.Drawing.Imaging.ImageFormat.Jpeg);
var myBytes = ms.ToArray();
Edit: Oh and storing them as Jpeg rather than Bmp will save a lotta space

Streaming VARBINARY data from SQL Server in C#

I'm trying to serve image data stored in a VARBINARY(MAX) field in the database using ASP.Net. Right now, the code is filling a data table, then pulling the byte array out of the DataRow and pushing the byte array into the response. I'm wondering if there's a way to more-or-less stream the data from the SQL Server into the response without having to marshal around these huge byte arrays (since the images are large, they cause OutOfMemoryExceptions). Is there a class/mechanism for that?
The current code looks more or less like:
DataTable table = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(commandText, connectionString);
adapter.Fill(table);
DataRow row = table.Rows[0];
byte[] imageData = row[0] as byte[];
if(imageData != null)
{
Response.Clear();
Response.BinaryWrite(imageData);
Response.End();
}
Thanks in advance - any help is appreciated.
See Download and Upload Images from SQL Server for an article covering the topic, including efficient streaming semantics. You must use a SqlDataReader opened with CommandBehavior.SequentialAccess:
SequentialAccess Provides a way for
the DataReader to handle rows that
contain columns with large binary
values. Rather than loading the entire
row, SequentialAccess enables the
DataReader to load data as a stream.
You can then use the GetBytes or
GetChars method to specify a byte
location to start the read operation,
and a limited buffer size for the data
being returned.
The linked article provides full code for creating a Stream backed by an SqlDataReader, you can simply Stream.CopyTo(HttpResponse.OutputStream), or use a byte[] chunked copy if you don't have .Net 4.0 yet.
This follow up article explains how to use a FILESTREAM column for efficient streaming of large VARBINARY data in and out of the database.
#Remus's answer above is out-of-date since .NET 4.5 introduced first-class SqlClient Streaming. It's no longer necessary to access the SqlDataReader's GetBytes() methods to get a stream from a SQL Query.
Now you simply call SqlDataReader.GetStream(int) to get a stream over a blob column.

Store an image in a SQL Server CE database

Does any one know of an example on how to store an image in a SQL Server CE database?
What data type should the column be? (I am guessing binary.)
I use Linq-To-Datasets. Is it possible using that to put the image into the database and pull it out again later?
Thanks for any advice.
Here is how I did it:
MemoryStream stream = new MemoryStream();
myBitmapImage.Save(stream, ImageFormat.Png);
myInsertLinqToDataSetRow.IMAGE_COLUMN = stream.ToArray();
To load it back out again I did this:
MemoryStream stream = new MemoryStream(myLinqToDataSetRow.IMAGE_COLUMN);
myBitmapImage.SignatureImage = new Bitmap(stream);
I found a page on MSDN that said that the Image column type is going away and that you should use varbinary(MAX). Max is not supported on SQL Server CE so I did varbinary(8000).
LATER NOTE: while varbinary(max) is not supported on SQL Server CE. Varbinary(8000) is not big enough for many images. I did end up using the Image type even though it is planned to be deprecated. Once ms offers a resonable alternitive on the mobile platform I will consider switching.
Here is an MSDN article explaining how:
http://support.microsoft.com/kb/318639
Unfortunately, the example is in VB, but I am sure that you can get the idea of how to do it.
I would say the binary datatype would be fine for storing the images.
Why aren't you using the Image type? Here is a description of types, supported by the sql server ce.
Image - Variable-length binary data with a maximum length of 2^30 – 1 (1,073,741,823) bytes.
This is not a direct answer to your question, but I've had good success storing the image's filepath (example: C:\images\image1.png) as a string value in the database instead of the raw image.
One advantage to this is that it keeps the database size smaller.
Another is that multiple tables can point to the images without storing multiple copies of the image.

Retrieving an image from database with Linq to SQL

In my database I have stored images in the "image" data type, showing up as a binary code.
I now want to retrieve all images from one column and diplay them on a asp.net page with C#.
databaseDataContext db = new databaseDataContext();
var images = from Picture p in db.Pictures
select p.pictureThumb;
then I use this:
foreach (Picture p in images)
{
galleryImages.Controls.Add(p);
}
But that doesn't work because Binary can't be converted to Picture. I have Googled this and found that I have to cast to Byte and then to image? I can't find examples on how to do that though.
This should do it:
databaseDataContext db = new databaseDataContext();
var images = from p in db.Pictures
select Image.FromStream(new MemoryStream(p.pictureThumb.ToArray());
foreach (Image image in images)
{
galleryImages.Controls.Add(image);
}
Note that Image.FromStream takes ownership of the stream - it's only a MemoryStream anyway, but do make sure that you dispose of the image, for various reasons.
EDIT: Ah... I hadn't realised that this was for ASP.NET. That makes things harder - because the HTML is going to contain URLs, and then you'll need to be able to fetch the data later.
Does a picture have an ID of some kind? If so, fetch that instead of the actual data, and then set up a URL which is able to serve any thumbnail based on the ID (by fetching it from the database and just serving it with an appropriate content type).

How to save picture in the database?

i'm working on Linq To Sql,WPF and i have a database now i need to save some picture in the database but i don't know which is the correct datatype to save the pictures Database(this database would be connect from 10 users in the same time).
Can you point me in the right way to overcome this step?
If i didn't wrong it is not a good idea to save pictures in the database but if you can advice me a better method i will apply it.
Thanks so much for your time.
Nice Regards
You can use a 'varbinary(MAX)' or 'image' column type. Linq2Sql will auto-generate a class that uses a Binary object to wrap your image. The Binary object is just a wrapper around a byte[].
myObject.Image = new Binary(imageByteArray);
Store your picture as a blob, the variable defined in your class containing the image could be a byte[] stream. Alternatively you just store a reference to the picture in the database and store the image on a file server.
Typically you will use a varbinary(max) -or less than max- on the database side and you will use a byte[] type in your class.
There's a lot of heated debates that occur when people talk about this, I would like to note that you might want to consider storing that path to a network folder in the database.
The disadvantage of storing the actual image in the database is that all those bytes have to get sent back and forth through a sql query and if those images are large you will be increasing the size of your db substantially. along with the weird things that were mentioned above.
Anyways I don't want to open up a can of worms, just wanted to show an alternative.
UPDATE:
Something like this:
public partial class LinqClass
{
public string ImagePath { get; set; }
public System.Drawing.Image Picture
{
get
{
return System.Drawing.Image.FromFile(ImagePath);
}
}
}
where ImagePath is the actual column in the db that you are saving the file path to. This doesn't have the code to save the file (something like File.Save(ImagePath) etc. but it's a start.
I've never done it with Linq, but we used a b64 conversion for the image, then a clob datatype. Then reverse the b64 when you want to view the image.

Categories