C#, should I store Bitmap size separately? - c#

My application works with large amount of images and I have to store some calculated info about each one. Frequently I need to get image's size for my calculations (sometimes without need to load original image).
What is better: each time to load needed Bitmap and to get its size, or at first get the size and store it in a Size object?

You said yourself "without need to load original image" - so sure get the compiled info for your bitmaps and store them. If you use a DB then you can for example store just your infos and the path to your bitmap. Only load big pictures if you really need them.

Related

Is it possible to reduce a JPEG image's file size by reducing its dimensions?

If there is a JPEG image with dimensions 800x600 and I want to reduce its file size by reducing its dimensions to, say, 768x576, how would I go about it?
Using the GDI+ library in .NET, I would have thought that by just opening the image, copying it to another with the desired dimensions and a quality setting of 100, the resulting image would have the same quality and would be automatically smaller (in bytes), because its dimensions are smaller than the original, but in my tests this doesn't seem to be the case. In fact, the size of the resulting image is larger than the original: from ~70K to ~280K.
So, is there any way this can be done? The final goal is to reduce the image size. I have also tried to save the image with the same dimensions and a quality setting of 70 or even 50, but I don't want to do that because it's impossible to determine if the original image has already been compressed to a point where saving it with such low settings will produce too much quality loss.
You shoudn't save the file with a quality setting of 100. What you are doing is like taking a 128 kbps mp3 file and saving it at 192 kbps. You get a larger file with the same information in it, and you are probably losing some data just by decoding and encoding again.
I would start by keeping the image size and finding the quality at which you get the same file size. After that you can play around with the size and quality until you get your desired file size.

Some specific questions to GDI+ in C#

Im trying to create a little game with C# and GDI+. For learning purposes I'm trying to avoid as much frameworks etc. as possible. So I have some specific questions to GDI+
Is it possible to fill a region object in GDI with an image?
-If not, is there a manual way for it?
Can you read and set single pixels in a graphics object (not a bitmap)?
Have you got any tips for me to increase overall performance in GDI?
Thanks for any help
Is it possible to fill a region object in GDI with an image?
A region can't be filled, it doesn't store pixels. What you are almost certainly looking for here is the Graphics.Clip property. Assign the region to it and draw the image, it will be clipped by the region.
Can you read and set single pixels in a graphics object (not a bitmap)?
No, the Graphics object doesn't store any pixels itself, it only keeps track of where you draw to. The "device context" in Windows speak. Which can be a bitmap, the screen, a printer, a metafile. Not all of these device contexts let you read a pixel back after drawing (not a printer and not a metafile for example). But no problem of course when you draw to a bitmap.
Have you got any tips for me to increase overall performance in GDI?
There is one crucial one, .NET makes it very easy to overlook. The pixel format of the bitmap you draw to is super-duper important. The most expensive thing you'll ever do with a bitmap is copying it, from CPU memory to the video-adapter's memory. That copy is only fast if the format of the pixels exactly match the format the video-adapter uses. On all modern machines that's PixelFormat.Format32bppPArgb. The difference is huge, it is ten times faster than all the other ones.
Many answers that will detail these points:
Once you have a Region it will limit where pixels are drawn. Use Graphics.DrawImage then
No way to read and only a perverted way to set a Pixel by Graphics.FillRectangle(br, x,y,1,1); The reason behind this is probably that Graphics can not only operate in a Pixel mode but also with various other Units from points to inches and mm..
Use Lockbits. Just one example using one Bitmap. Other common jobs demand locking two (one input one output) or or even three (two inputs and one calculated output) bitmaps..
Know what you invalidate, often only a small part really needs it..
Learn about ImageList, it can't do much but is useful for what it does, that is cache images of one size and color depth
Learn when to use a Panel and when a Picturebox

Image size in DB?

I made an application that stores Item picture (jpeg) on SQL Server DB, I am using pictures shot with my camera (file size ~ 2 M). I am checking if picture.Width > 800 or picture.Height > 600, then I resize the picture to 800x600.
If I export picture from DB, the file size is about 100k, and if I open the same picture in photoshop, the image size is shown 1.37M.
Now my questions are:
First, I want to know the space that this picture takes in my DB.
The reason I'm resizing the picture before storing it in my DB, is that I imagine it taking a huge space in my DB.
Second, How do I resize a picture to keep it's aspect ratio?
The size of the jpg file depends of the widht, height and the color dept. Check this link http://jan.ucc.nau.edu/lrm22/pixels2bytes/calculator.htm to calculate the image size.
to resize the picture size and keep the aspect ratio there is a lot of libraries and framewrok to complete the task. I do not recomend you to implement one unless
you have to (there is a lot of good libraries). check this post Image resizing algorithm.
Its not good idea to store image in DB check Storing Images in DB - Yea or Nay?

Generating extremely large images in C#

I need to generate some large graphs whose width and height can go up to millions of pixels in size. Please note that I do NOT want to scale down the image. Each point must represent one pixel.
Now using the Bitmap and Graphics objects, this is very much possible if I split the image into smaller squares but it is painfully slow.
I already calculate the pixel RGB values so was wondering if there is a way to create a byte array with these values and manually save them as an uncompressed BMP format file instead of dealing with the Bitmap class and the drawing functions of the Graphics class.
I am comfortable with unsafe code if that helps to speed up the process.
If you're displaying graphs, why don't you use a technology like SVG that can be rendered on the fly with very little processing power, yet can scale to near-infinite sizes thanks to vector expansion?
(While there is good question if anything will be able to read such files...)
BMP format is very simple - you can write it directly to disk (I'd recommend avoiding building huge file in memory unless you have other reasons to do so). There is a fixed-size header and then (for 24bpp) sequences of colors aligned on some width. Assuming you can pick width you will not even need to add any padding - just rows of colors for each pixel.

Re-encoding of Jpeg Image in binary column when saving

I know there are similar questions, but I have a question concerning the storage of images in a binary-column.
I have a small windows forms app that loads an image into a picturebox control from a sql compact db using Linq2SQL. The user can drag any image (jpg,bmp,gif) on a picturebox. On the DragDrop-Event the image is loaded into the picturebox.
When I save the record following code is executed to store the image of the picturebox control:
MemoryStream imgStream = new MemoryStream();
pictureBox1.Image.Save(imgStream, System.Drawing.Imaging.ImageFormat.Jpeg);
myTable.MyImage = imgStream.ToArray();
I have checked the size of the byte array and it didn't change after saving the record.
Is the image re-encoded every time the Save-Method is called? It would be maybe then better to check if the image has changed at all.
JPEG images are decoded as a function of their being displayed by .NET (or really just about anything). So, if you pull a JPEG out as a binary, put it in a PictureBox (which will convert it to a raster format to display), then take that now-uncompressed raster Image and recompress it, you MAY end up making changes to that image.
I would keep the original bytestream for the displayed Image somewhere behind the scenes, and write that back to the DB when the user saves the data. This will not only help preserve the integrity of the image, it will boost performance by reducing the need to recompress the image every time.
If this code is called when you call Save then yes, the PictureBox will "export" itself as a JPEG every time. Are you noticing a performance issue because of this? If you want to avoid it, set a flag on application load and when the drag/drop event occurs raise the flag signaling that the Save method should update the image data.

Categories