I am switching an existing MVC 4 website from home-cooked user file uploads to resizing files with ImageResizer as they are uploaded.
I see in the documentation that I should not use System.Drawing, but I can't figure out any other way of grabbing the image dimensions.
It does not matter if the dimensions are from the original image or a resized image, since I am preserving aspect ratio and merely need to determine if an image is landscape or portrait.
I am adding the code here that I refer to in my comment responding to #Nathanael's answer.
ImageJob ij = new ImageJob(file, requestedImageInfo: null);
int ? y = ij.SourceWidth;
int ? z = ij.SourceHeight;
If you can store the image dimensions during upload (from ImageJob.SourceWidth/Height or LoadImageInfo), that is best, as reading image dimensions from a file involves lots of I/O.
If not, ImageResizer offers the IDictionary LoadImageInfo(object source, IEnumerable requestedInfo) method to do so after the fact. Just keep in mind, it does involve reading from disk, and you don't want to call this lots of times in a single HTTP request. Put those numbers in the database.
You can always calculate the final size of an image via ImageBuilder.GetFinalSize(originalSize, instructions). This, on the other hand, is very fast, as it involves no I/O, just math.
Related
I use this link to add my program the capability to adjust the brightness of the image. This code is ok but it takes time to adjust the brightness(Image file size 1.8mb). When I try the lower quality image it instantly adjusts the image(Image file size 100KB). Is there any efficient way to adjust the brightness of the image.
The code seems to use GetPixel and SetPixel on regular Bitmaps. This is a bad idea because it is so slow.
To manipulate a single pixel of a Bitmap it must be locked (which Get/SetPixel do behind the scenes) and doing it on a pixel by pixel basis means that for a 1000x1000 sized image a million locking/unlocking operations must be performed. This creates an enormous overhead.
Method one
One way to avoid this is to lock the whole bitmap with the LockBits function. Now we can loop over the pixels and modify them.
Two notes about this method:
What we now access are the raw bytes of each pixel, that is each channel separately: either BGR or BGRA, depending on the pixel format. This means that the channels are physically reversed from the usual RGB/ARGB format of the Color methods.
To loop over the physical bitmap pixel rows we also need to add some stride to each row, which pads the rows to a multiple of 4 bytes. Also see here
For some examples you may want to browse over some of these posts. Note especially this one which uses a delegate to allow for flexible operations!
(Note that several of the posts use 2 or even 3 locked bitmaps because they aim at combining images..)
Method two
Another way to get around the overhead of locking pixels one by one are ready-made bitmap classes that help by locking themselves as a whole. Here and here are examples I didn't try myself.
Method three
Finally there is a very elegant method for image manipulation, which is both rather simple and really fast; also professionally crafted for best results: You can set up a ColorMatrix.
It will let you change brightness, gamma, hues and then some. Here is a very nice introduction.
The only drawback is, that is limited to some fixed operations, so you can't create custom filters for other fancy stuff, like photoshop-type layer modes or others, especially those that need to process neighbouring pixels e.g. for blurring..
But if all you want is changing brightness, this is what I would recommend!
The title pretty much explains my question. I would like to be able to read and write JPEG data on a per-pixel basis using C#.
I'm thinking something along the lines of CreateJPEG(x, y) which would set up a blank JPEG image in memory, and would give me a JPEG object, and then something like SetPixel(x, y, Color) and GetPixel(x, y) the latter of which would return a Color or something similar. You could then call an Apply() or Save() method, for example, to save the image in a standard JPEG-readable format (preferrably with compression options, but that's not necessary).
And I'm assuming some C# library or namespace makes this all a very easy process, I'd just like to know the best way to go about it.
Have a look at the Bitmap class. For advanced drawing besides manipulating single pixel you will have to use the Graphics class.
var image = new Bitmap("foo.jpg");
var color = image.GetPixel(1, 2);
image.SetPixel(42, 42, Color.White);
image.Save("bar.jpg", ImageFormat.Jpeg);
As Lasse V. Karlsen mentions in his answer this will not really manipulate the JPEG file. The JPEG file will be decompressed, this image data will be altered, and on saving a new JPEG file is created from the altered image data.
This will lower the image quality because even recompressing an unaltered image does usually not yield a bit-identical JPEG file due to the nature of lossy JPEG compressions.
There are some operations that can be performed on JPEG files without decompressing and recompressing it - for example rotating by 90° - put manipulating single pixels does not fit in this category.
JPEG is not a processing format, it's a storage format.
As such, you don't actually use a JPEG image in memory, you just have an image. It's only when you store it that you pick the format, like PNG or JPEG.
As such, I believe you're looking for the Bitmap class in .NET.
I want to create large image by C#. (i have some photos with large size (4800 * 4800). i want to merge these photos.)
I use Bitmap but don't support. (Error : Invalid Parameter)
Some code would be useful ...
... However, to hazard an educated guess, I suspect you're trying to create an instance of Bitmap with either Width or Height (or both) greater than 2^15.
Essentially, you can't - the .NET bitmap classes have a limitation on how big an image they can handle. Your original 4800 pixel square images won't be a problem, but going over 32,767 pixels will be.
you might like to check AForge.NET, it has a large image processor built in, and it's open source.
We have an application that show a large image file (satellite image) from local network resource.
To speed up the image rendering, we divide the image to smaller patches (e.g. 6x6 cm) and the app tiles them appropriately.
But each time the satellite image updated, the dividing pre-process should be done, which is a time consuming work.
I wonder how can we load the patches from the original file?
PS 1: I find the LeadTools library, but we need an open source solution.
PS 2: The app is in .NET C#
Edit 1:
The format is not a point for us, but currently it's JPG.
changing the format to a another could be consider, but BMP format is hardly acceptable, because of it large volume.
I wote a beautifull attempt of answer to your question, but my browser ate it... :(
Basically what I tried to say was:
1.- Since Jpeg (and most compression formats) uses a secuential compression, you'll always need to decode all the bits that are before the ones that you need.
2.- The solution I propose need to be done with each format you need to support.
3.- There are a lot of open source jpeg decoders that you could modify. Jpeg decoders need to decode blocks of bits (of variable size) that convert into pixel blocks of size 8x8. What you could do is modify the code to save in memory only the blocks you need and discard all the others as soon as they aren't needed any more (basically as soon as they are decoded). With those memory-saved blocks, create the image you need.
4.- Since Jpeg works with blocks of 8x8, your work could be easier if you work with patches of sizes multiples of 8 pixels.
5.- The modification done to the jpeg decoder could be used to substitute the preprocessing of the images you are doing if you save the patch and discard the blocks as soon as you complete them. It would be really fast and less memory consuming.
I know it needs a lot of work and there are a lot of details to be taken in consideration (specially if you work with color images), but if you need performance I belive you will always end fighting or playing (as you want to see it) with the bytes.
Hope it helps.
I'm not 100% sure what you're after but if you're looking for a way to go from string imagePath, Rectangle desiredPortion to a System.Drawing.Image object then perhaps something like this:
public System.Drawing.Image LoadImagePiece(string imagePath, Rectangle desiredPortion)
{
using (Image img = Image.FromFile(path))
{
Bitmap result = new Bitmap(desiredPortion.Width, desiredPortion.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage((Image)result))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(img, 0, 0, desiredPortion, GraphicsUnit.Pixel);
}
return result;
}
}
Note that for performance reasons you may want to consider building multiple output images at once rather than calling this multiple times - perhaps passing it an array of rectangles and getting back an array of images or similar.
If that's not what you're after can you clarify what you're actually looking for?
I'm writing some map software for my smartphone and have hit a problem whereby I don't want to load all of the (large) image files into memory when only a portion will be displayed.
Is there a way to read only a subsection (the viewable portion) of a big image given that you know the x and y offsets and width? I know it's probably possibly to do it by reading the file a byte at a time but I'm not sure how to do this.
Thank you,
Nico
It's going to depend at least in part on what format(s) your images are saved in. If you have raw image files or bitmaps, it may be possible, but if your data is compressed in any manner, such as JPEG or PNG, it's going to be a lot more difficult to read just a subsection.
If you truly don't want to ever load the full data into memory, you'll have to write your own IO routine that reads the file. For anything more complex than BMP, your decompression algorithm could get complicated.
If it's a BMP file, it shouldn't be that hard.
First you read the header from the file, if I recall correctly it's 44 bytes, but you can find that out from searching the web for a specification.
The header contains information like how many bytes there are per pixel, total width and height, how many bytes per scan line. Normally the bitmap is stored upside down, so you would calculate where in the file the first pixel of the bottom line was and skip to that location. Then you read the pixels you want from that line and skip to the correct pixel on the next line.
The FileStream class has what you need; a Read method for reading and a Seek method to skip to a given position.
Couldn't you cut the image up into sections beforehand?
Splitting it into many 256x256 pixel images means you'd only have to load a couple of them and stitch them back together on the viewable canvas. To name one implementation - google maps uses this technique.
This is something I have done with bitmaps...
public BitmapCropBitmap(BitMap fullBitmap, Rectangle rectangle)
{
return proBitmap.clone(fullBitmap, rectangle, fullBitmap.PixelFormat);
}