Re: Image Tiling with GDI+ and C++

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Hopefully this won't double post - seems the first one went into the void...
------------------------------------------

You need to be careful with differentiating offset and stride.

Although the locked bits arrays are linear, they are arranged in pixel rows,
the length of which are BitmapData::Stride bytes.

This value should always be a multiple of 4, so it willl NOT always match
width*3 in a 24bpp image.

Therefore, I'm suspicious of your offset calculations using width*3.
width*3 should only be used as the number of bytes per row to copy from the
source tile bitmaps to the destination bitmap.
When moving to the next destination row, the destination bitmap's stride
should be used.

Here's some pseudocode (pretty close to real code) that hopefully simplifies
what you're doing....note where I used stride and where I used width*3.
This will work for both top-down and bottom-up bitmaps, and will work for
horizontal or vertical tiling, as long as you calculate destX and destY
properly :)

//-----------------------------------------------------------------------------------

// code to copy one tile to a destination bitmap...
// assumes you've already locked the pixel bits and obtained the BitmapData
structs

destX = ... (upper-left corner of destination location to copy a tile to)
destY = ... (upper-left corner of destination location to copy a tile to)

BYTE *pCurSrcRow = srcBitmapData.Scan0;
BYTE *pCurDestRow = destBitmapData.Scan0 + (destBitmapData.Stride * destY) +
(destX * 3);

for (curRow = 0; curRow < srcbitmap.Height(); curRow++)
{
memcpy(pCurDestRow, pCurSrcRow, srcbitmap.Height() * 3)

pCurSrcRow += srcBitmapData.Stride;
pCurSrcRow += destBitmapData.Stride;
}
//-----------------------------------------------------------------------------------


Mark

--
Mark Salsbery
Microsoft MVP - Visual C++








"ahumphries" <ahumphries@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message news:045094CB-6559-4BE7-97CC-D70DA24A56CF@xxxxxxxxxxxxxxxx
Hi folks,

I'm trying to take individual images and tile them together to form one
larger image. The images are ordered, as they are pieces of a larger view,
and currently I am trying to do this with 9 images in a grid of 3 by 3. Does
anyone have any experience of this kind of thing using native unmanaged C++
and GDI+? I need to add one tile at at time to the overall image, and then
process the overall image with the new tile included. Then I can add the next
tile, and process the new extended image, and so on. All of the images are
24-bit.

Right now I'm just trying to add one tile to another horizontally. After I
get that working I can think about multiple tiling in both axes. I'm having a
problem with the new image (Bitmap object) I create using GDI+. Here is the
code I am currently using, and I will explain my problem a bit better after
it:

-----------------------

Bitmap b(L"blobtest.jpg");
Bitmap* b2;

int iWidth = b.GetWidth();
int iHeight = b.GetHeight();

Rect rect(0,0,iWidth,iHeight);
b2 = b.Clone(rect,PixelFormat24bppRGB);


BitmapData bmData;
BitmapData bmData2;

b.LockBits(&rect,ImageLockModeRead | ImageLockModeWrite,
PixelFormat24bppRGB,&bmData);
b2->LockBits(&rect,ImageLockModeRead |ImageLockModeWrite,
PixelFormat24bppRGB,&bmData2);

int stride = bmData.Stride;
int offset = stride - iWidth*3;

byte * p1 = (byte *)(void *)bmData.Scan0;
byte * p2 = (byte *)(void *)bmData2.Scan0;

Bitmap b3(iWidth*2,iHeight,PixelFormat24bppRGB);

int iWidth3 = b3.GetWidth();
int iHeight3 = b3.GetHeight();

Rect rect3(0,0,iWidth3,iHeight3);

BitmapData bmData3;

b3.LockBits(&rect3,ImageLockModeRead |ImageLockModeWrite,
PixelFormat24bppRGB,&bmData3);

int stride3 = bmData3.Stride;
int offset3 = stride3 - iWidth3*3;

byte * p3 = (byte *)(void *)bmData3.Scan0;

for (int y = 0; y < iHeight3; y++)
{
for (int x = 0; x < iWidth3; x++)
{
if (x < iWidth)
{
p3[0] = p3[1] = p3[2] = p1[0];
p1 += 3;
}
else if (x >= iWidth)
{
// COMMENTED OUT UNTIL PROBLEM RESOLVED
//p3[0] = p3[1] = p3[2] = p2[0];
//p2 += 3;
}
p3 += 3;
}
p1 += offset;
p2 += offset;
p3 += offset;
}

-----------------------------

Hopefully a lot of it will be self-explanatory. p1, p2 and p3 are the
pointers to the Scan0 attributes of bmData, bmData2 and bmData3. Rather than
using a multi-dimensional array I'm keeping the image data where it is and
iterating through it's one-dimensional array.

Now here's the problem. When I run that code above I get the first tile b
stretched into a parallellogram across the new bitmap b3. Thats why I
commented out adding the second tile, because it tries to write over the
bounds of the new image.

The first two images both have an offset of 2 which is pretty standard for
the kind of images I'm working with. The third has an offset of 0 which might
be causing the problem. I'm not sure why this is. Am I creating the new
bitmap incorrectly?! Have you seen something like this before? Am I even
using a good method for adding the tiles together (regardless of the current
issue)?

I really appreciate any help. Thanks!

.



Relevant Pages

  • Re: Image Tiling with GDI+ and C++
    ... I'm suspicious of your offset calculations using width*3. ... width*3 should only be used as the number of bytes per row to copy from the source tile bitmaps to the destination bitmap. ... When moving to the next destination row, the destination bitmap's stride should be used. ...
    (microsoft.public.win32.programmer.gdi)
  • Image Tiling with GDI+ and C++
    ... I'm trying to take individual images and tile them together to form one ... problem with the new image (Bitmap object) I create using GDI+. ... int iHeight = b.GetHeight; ... p1 += offset; ...
    (microsoft.public.win32.programmer.gdi)
  • Re: How to display a DIB or draw it into a Bitmap
    ... The correct calculation of the offset for .bfOffBits is important. ... CreateDIBSection would fail! ... If you loaded a bitmap that was aligned this way and did not check the ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How to display a DIB or draw it into a Bitmap
    ... The correct calculation of the offset for .bfOffBits is important. ... If you want to use memory mapped files for very large bitmaps and pass a ... If you loaded a bitmap that was aligned this way and did not check the ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Newbie: Bamboozled
    ... octal dump of bitmap formed by hack - works. ... You should either be writing field by field ... As you still got the offset correctly, ... I can not control the format, it is a standard format and I need to ...
    (comp.unix.programmer)