breaking up bitmap images

  • Thread starter Stephen.Schoenberger
  • Start date
S

Stephen.Schoenberger

Hello,

I am reading in a bitmap image and storing it as a bitmap in C#. I
need to perform some mathmatical operations on that image but it needs
to be broken up into smaller fragments (16x16). On each of these
fragments I need to perform my work, then write back the manipulated
fragment to a new image. I have tried some different techniques but so
far no luck. Any advice would be great!

Thanks.
 
N

Nicholas Paldino [.NET/C# MVP]

Stephen,

It should be easy enough. First, you create a new Bitmap instance,
passing 16x16 to indicate you want a 16x16 image. Once you have that, you
can pass the Bitmap to the static FromImage method on the Graphics class to
return a Graphics instance which will let you draw on the Bitmap. Once you
have the Graphics instance, you can then call the DrawImage method on it,
passing the original image, and the section of the original image you want
to draw on your new, smaller image.

Then you can perform your processing.

Putting the images back together is just a matter of reversing the
process. Create one image which is the size of all the smaller images, get
the Graphics instance for it, and then call DrawImage on the Graphics
instance, passing the smaller pieces and drawing them where appropriate.
 
P

Peter Duniho

Hello,

I am reading in a bitmap image and storing it as a bitmap in C#. I
need to perform some mathmatical operations on that image but it needs
to be broken up into smaller fragments (16x16). On each of these
fragments I need to perform my work, then write back the manipulated
fragment to a new image. I have tried some different techniques but so
far no luck. Any advice would be great!

In addition to what Nicholas wrote...

It sounds as though you want some sort of distributed processing to
occur. Depending on exactly how you're distributing the processing, you
may find it better to use LockBits to create a single chunk of data that
all the processors can operate on, and give each one a specific subset to
use so that they don't conflict.

In particular, if all of this is happening within a single process, the
overhead of copying all of those 16x16 subsets could be enough to
significantly reduce or eliminate any advantages you might have gotten
from parallelizing your algorithm. Actually, it could do so even if the
processing is being distributed to multiple processes or computers, but in
that case the solution would be different (maybe use memory-mapped files
for multiple processes...for multiple computers the only practical
solution is likely to be to make the chunks of work larger than 16x16).

Pete
 
S

Stephen.Schoenberger

Stephen,

It should be easy enough. First, you create a new Bitmap instance,
passing 16x16 to indicate you want a 16x16 image. Once you have that, you
can pass the Bitmap to the static FromImage method on the Graphics class to
return a Graphics instance which will let you draw on the Bitmap. Once you
have the Graphics instance, you can then call the DrawImage method on it,
passing the original image, and the section of the original image you want
to draw on your new, smaller image.

Then you can perform your processing.

Putting the images back together is just a matter of reversing the
process. Create one image which is the size of all the smaller images, get
the Graphics instance for it, and then call DrawImage on the Graphics
instance, passing the smaller pieces and drawing them where appropriate.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


I am reading in a bitmap image and storing it as a bitmap in C#. I
need to perform some mathmatical operations on that image but it needs
to be broken up into smaller fragments (16x16). On each of these
fragments I need to perform my work, then write back the manipulated
fragment to a new image. I have tried some different techniques but so
far no luck. Any advice would be great!

I am a little confused on how to use the DrawImage() for the use that
I need it...should I use Rectangle? Or PointF? Or another option????
 
P

Peter Duniho

I am a little confused on how to use the DrawImage() for the use that
I need it...should I use Rectangle? Or PointF? Or another option????

Whatever you want.

There are a lot of overloads for DrawImage(). Just find the one that
suits your needs best. For example:

Bitmap[,] BitmapsFromBitmap(Bitmap bmpSrc, int cxDst, int cyDst)
{
int ccol = (bmpSrc.Width - 1) / cxDst + 1,
crow = (bmpSrc.Height - 1) / cyDst + 1;
Bitmap[,] rgbmpRet = new Bitmap[ccol][crow];

for (int irow = 0; irow < crow; irow++)
{
for (int icol = 0; icol < ccol; icol++)
{
Bitmap bmpDst = new Bitmap(cxDst, cyDst);

using (Graphics gfx = Graphics.FromImage(bmpDst))
{
gfx.DrawImage(bmpSrc, 0, 0,
new Rectangle(icol * cxDst, irow * cyDst, cxDst,
cyDst),
GraphicsUnit.Pixel);
}

rgbmpRet[icol, irow] = bmpDst;
}
}

return rgbmpRet;
}

Caveat: the above was just typed into the message...I didn't bother to try
to compile or test it. The code also makes no attempt to deal bitmaps
that aren't an integral multiple of the size of the sub-bitmaps; if I
recall correctly, if a source that isn't an integral multiple of the
destination size is used, all that will happen is that the right and/or
bottom edge of the last sub-bitmaps just won't be painted (they'll be
black).

Finally, the above code assumes the passed in Bitmap is at least 1x1 pixel
in size.

Pete
 
N

Nicholas Paldino [.NET/C# MVP]

Stephen,

I would use the overload specified here:

http://msdn2.microsoft.com/en-us/library/ms142040.aspx

You just have to define the source and destination rectangles. The
destination rectangle should be simple enough, it's just the rectangle that
defines the boundary of the whole image (the 16x16 image).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Stephen,

It should be easy enough. First, you create a new Bitmap instance,
passing 16x16 to indicate you want a 16x16 image. Once you have that,
you
can pass the Bitmap to the static FromImage method on the Graphics class
to
return a Graphics instance which will let you draw on the Bitmap. Once
you
have the Graphics instance, you can then call the DrawImage method on it,
passing the original image, and the section of the original image you
want
to draw on your new, smaller image.

Then you can perform your processing.

Putting the images back together is just a matter of reversing the
process. Create one image which is the size of all the smaller images,
get
the Graphics instance for it, and then call DrawImage on the Graphics
instance, passing the smaller pieces and drawing them where appropriate.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


I am reading in a bitmap image and storing it as a bitmap in C#. I
need to perform some mathmatical operations on that image but it needs
to be broken up into smaller fragments (16x16). On each of these
fragments I need to perform my work, then write back the manipulated
fragment to a new image. I have tried some different techniques but so
far no luck. Any advice would be great!

I am a little confused on how to use the DrawImage() for the use that
I need it...should I use Rectangle? Or PointF? Or another option????
 
S

Stephen.Schoenberger

Stephen,

I would use the overload specified here:

http://msdn2.microsoft.com/en-us/library/ms142040.aspx

You just have to define the source and destination rectangles. The
destination rectangle should be simple enough, it's just the rectangle that
defines the boundary of the whole image (the 16x16 image).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Stephen,
It should be easy enough. First, you create a new Bitmap instance,
passing 16x16 to indicate you want a 16x16 image. Once you have that,
you
can pass the Bitmap to the static FromImage method on the Graphics class
to
return a Graphics instance which will let you draw on the Bitmap. Once
you
have the Graphics instance, you can then call the DrawImage method on it,
passing the original image, and the section of the original image you
want
to draw on your new, smaller image.
Then you can perform your processing.
Putting the images back together is just a matter of reversing the
process. Create one image which is the size of all the smaller images,
get
the Graphics instance for it, and then call DrawImage on the Graphics
instance, passing the smaller pieces and drawing them where appropriate.
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hello,
I am reading in a bitmap image and storing it as a bitmap in C#. I
need to perform some mathmatical operations on that image but it needs
to be broken up into smaller fragments (16x16). On each of these
fragments I need to perform my work, then write back the manipulated
fragment to a new image. I have tried some different techniques but so
far no luck. Any advice would be great!
Thanks.
I am a little confused on how to use the DrawImage() for the use that
I need it...should I use Rectangle? Or PointF? Or another option????

I have started to figure this out but I have a new dilemma that has me
confused. With the image I need to split it up into 16x16 sub images
and SAVE the coordinates of each of those subimages (say sub image 1
goes from 0,0 to 15,15 or sub image 10 goes from 150,165 to
160,175...just arbitrary examples) perform the work on each subimage
then recombine the subimages (with work performed on them) to a new
output image. Any advice/help on this would be great.
 
P

Peter Duniho

[...]
I have started to figure this out but I have a new dilemma that has me
confused. With the image I need to split it up into 16x16 sub images
and SAVE the coordinates of each of those subimages (say sub image 1
goes from 0,0 to 15,15 or sub image 10 goes from 150,165 to
160,175...just arbitrary examples) perform the work on each subimage
then recombine the subimages (with work performed on them) to a new
output image. Any advice/help on this would be great.

You'll either need to create a parallel data structure to contain the
coordinate information or, probably better, create a new data structure
that can contain both the image reference and the coordinate information.
That way you can correlate the coordinates with each generated image.

As for recombining, it's pretty much the inverse of the splitting. Create
a Bitmap the size you need to contain all the pieces, then iterate through
the pieces drawing each one into the destination bitmap.

Pete
 
K

Kevin Spencer

I had a similar problem. Here's how I solved it:

When saving the fragments, I simply give them a file name that contains the
coordinates of the fragment,combined with the name of the original file. For
example:

imageName

imageName_00
imageName_01
imageName_02

This way, I can work with multiple images and fragments from those images
concurrently. You can fetch the fragments using Directory.GetFiles, and a
wildcard containing the original image file name, and then parse the file
names to get their coordinates.

--
HTH,

Kevin Spencer
Chicken Salad Surgeon
Microsoft MVP

Stephen,

I would use the overload specified here:

http://msdn2.microsoft.com/en-us/library/ms142040.aspx

You just have to define the source and destination rectangles. The
destination rectangle should be simple enough, it's just the rectangle
that
defines the boundary of the whole image (the 16x16 image).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


On Jan 14, 11:08 am, "Nicholas Paldino [.NET/C# MVP]"
Stephen,
It should be easy enough. First, you create a new Bitmap
instance,
passing 16x16 to indicate you want a 16x16 image. Once you have that,
you
can pass the Bitmap to the static FromImage method on the Graphics
class
to
return a Graphics instance which will let you draw on the Bitmap.
Once
you
have the Graphics instance, you can then call the DrawImage method on
it,
passing the original image, and the section of the original image you
want
to draw on your new, smaller image.
Then you can perform your processing.
Putting the images back together is just a matter of reversing the
process. Create one image which is the size of all the smaller
images,
get
the Graphics instance for it, and then call DrawImage on the Graphics
instance, passing the smaller pieces and drawing them where
appropriate.
I am reading in a bitmap image and storing it as a bitmap in C#. I
need to perform some mathmatical operations on that image but it
needs
to be broken up into smaller fragments (16x16). On each of these
fragments I need to perform my work, then write back the manipulated
fragment to a new image. I have tried some different techniques but
so
far no luck. Any advice would be great!

I am a little confused on how to use the DrawImage() for the use that
I need it...should I use Rectangle? Or PointF? Or another option????

I have started to figure this out but I have a new dilemma that has me
confused. With the image I need to split it up into 16x16 sub images
and SAVE the coordinates of each of those subimages (say sub image 1
goes from 0,0 to 15,15 or sub image 10 goes from 150,165 to
160,175...just arbitrary examples) perform the work on each subimage
then recombine the subimages (with work performed on them) to a new
output image. Any advice/help on this would be great.
 
S

Stephen.Schoenberger

I am a little confused on how to use the DrawImage() for the use that
I need it...should I use Rectangle? Or PointF? Or another option????

Whatever you want.

There are a lot of overloads for DrawImage(). Just find the one that
suits your needs best. For example:

Bitmap[,] BitmapsFromBitmap(Bitmap bmpSrc, int cxDst, int cyDst)
{
int ccol = (bmpSrc.Width - 1) / cxDst + 1,
crow = (bmpSrc.Height - 1) / cyDst + 1;
Bitmap[,] rgbmpRet = new Bitmap[ccol][crow];

for (int irow = 0; irow < crow; irow++)
{
for (int icol = 0; icol < ccol; icol++)
{
Bitmap bmpDst = new Bitmap(cxDst, cyDst);

using (Graphics gfx = Graphics.FromImage(bmpDst))
{
gfx.DrawImage(bmpSrc, 0, 0,
new Rectangle(icol * cxDst, irow * cyDst, cxDst,
cyDst),
GraphicsUnit.Pixel);
}

rgbmpRet[icol, irow] = bmpDst;
}
}

return rgbmpRet;
}

Caveat: the above was just typed into the message...I didn't bother to try
to compile or test it. The code also makes no attempt to deal bitmaps
that aren't an integral multiple of the size of the sub-bitmaps; if I
recall correctly, if a source that isn't an integral multiple of the
destination size is used, all that will happen is that the right and/or
bottom edge of the last sub-bitmaps just won't be painted (they'll be
black).

Finally, the above code assumes the passed in Bitmap is at least 1x1 pixel
in size.

Pete

used your algorithm to attempt to solve this problem and upon the
program ending I have over 8200 files...i thought I would have 4800
files because I am using a 1280x960 image which is broken up into
16x16 blocks resulting in a 80x60 = 4800 images. Make sense? Any
further advice would be great. Here is the code that works...(your
code provided was close)

int ccol = (bmpSource.Width-1)/cxDst+1;
int crow = (bmpSource.Height-1)/cyDst+1;

Bitmap[,] ret = new Bitmap[ccol,crow];
for (int irow = 0; irow < crow; irow++ )
{
for (int icol=0; icol < ccol; icol++)
{
Bitmap bmpDst = new Bitmap(cxDst, cyDst);

using (Graphics gfx = Graphics.FromImage(bmpDst))
{
gfx.DrawImage(bmpSource, 0, 0, new
Rectangle(icol * cxDst, irow * cyDst, cyDst, cxDst),
GraphicsUnit.Pixel);
}
ret[icol, irow] = bmpDst;

//bmpDst.Save("bmpDst"+icol+"X"+irow+".bmp");
bmpDst.Save("bmpDst.bmp");
}
}
 
P

Peter Duniho

used your algorithm to attempt to solve this problem and upon the
program ending I have over 8200 files...i thought I would have 4800
files because I am using a 1280x960 image which is broken up into
16x16 blocks resulting in a 80x60 = 4800 images. Make sense? Any
further advice would be great. Here is the code that works...(your
code provided was close)

I don't see anything obviously wrong. What filenames do you get when you
use the version of Save() that embeds the row and column indices in the
file name? You can't have 8200 files and still have embedded indices that
only range from "00X00" up to "79X59", so if in fact that loop is writing
more than 4800 files (I really don't see how it could be), you should see
filenames outside that range.

You should really be testing with a much small test file to start with.
It's much easier to step through the entire algorithm, and to get a handle
on exactly what's being written, when the number of tiles is small. I'd
recommend starting with something that only generates four to six tiles.
That'd give you enough to watch several iterations, but not so many that
watching _all_ the iterations would take prohibitively long.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top