views:

132

answers:

2

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.

+1  A: 

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?

Tim Schneider
You got my point correctly:I want to load only a patch of a very large image.But without load original image itself, in (Image img = Image.FromFile(path)), whole image has been loaded in memory. I want to create a stream, seek directly to place which data of specific rectangle are, read data and decode it to image format.
A Poostchi
Reading your comment above : I now believe what you are trying to do is to precompute a collection of some exact fixed-size areas of an image file on some kind of server (or stored in some data format on some medium), and download only those bytes within those areas. Obviously, the moment the source image changes in size, you are going to have some notification method that tells you to re-compute the byte offsets into the file you need to use to locate the areas of interest. Also, this implies, you have the code at hand to read/parse the structure of the image file (or its header ?). Correct ?
BillW
BillWthanks for your participation.I think the above comment, goes too far, and the program is more simple than that, but yes: we have server, a pyramid of multiple satellite images (different resolutions) on it, an explorer application on client shows one of the level of the pyramid each time based on end user zoom choice. Change in satellite image is infrequent, although the original satellite image has been saved in different resolution level, but still each level has a large size. So we enforce to split them in smaller rectangular parts.
A Poostchi
Then the app load a required patches collection based on its view.our problem is that when the satellite images has been updated, we must divide it , but if we could read specific area of the large image, this preprocess eliminate, and the app become more handy.
A Poostchi
Ah, I see, you're looking to somehow load a subset of the main image in binary without actually pulling in the main image. I'm pretty sure with the way jpeg encoding works this simply won't be possible. I don't know if any image encoding exists that would work like this (other than bmp - but that's got it's own obvious problems).
Tim Schneider
A fascinating problem; one I wish had the technical "chops" to help with. But two further questions : 1. is the end-user able to select a continuous zoom-level, or only select from a set of fixed zoom-levels ? 2. if the answer to #1 is "yes," and you are able to have some kind of "heuristic" about the most frequently accessed zoom levels, and you've got some super-duper-cpu-horsepower on the server : could the server do some pre-computation of all possible (or most likely ?) rectangles of interest (this is partially based on your statement that the change in the image is "infrequent"). best,
BillW
BillW, I appreciate your interest.No, Currently the zoom level is discrete, but in future, we can the provide continuous zoom level by interpolating patches, until the next actual level (in the pyramid) reaches.By the way, I guess, this is not only my problem, and I wonder how its solution is not available in an open source code!?Some of the guys commented above, said that different file format, can be manipulated in different way, then I hope somebody help us with this clue.
A Poostchi
+1  A: 

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.

Limo Wan Kenobi
hi LimoThanks, It's really helpful.and after more that one month, I don't expect any answers.as I see you are good at Image works, and since we do not stick to JPG format, can you suggest another image format, which reduces our work in this process?
A Poostchi
Hi Poostchi, I really don't know what your requeriments are (for image size and quality and all that stuff), but since you are ok working with JPEG I don't see a reason to change the format. Well, maybe that after I finish my answer, I started looking for a open source JPEG decoder in .Net and I could not find one! :S Everyone uses the framework decoder. So, maybe you'll have to make your own decoder (based in a C++ or Java one) and I don't know if it is acceptable for you. Really sorry...
Limo Wan Kenobi