Splitting one Image into a d2 image array, help!

Wing

Member
Joined
May 13, 2007
Messages
15
Location
Sweden
Hi im trying to write a function to split one image into a d2 image array well i got this far

Code:
public Image[,] SplitImages(Image image, int rows, int columns)
{
    
    Image[,] images = new Image[rows, columns];
    for (int row = 0; row < rows; row++)
    {
        for (int colum = 0; colum < columns; colum++)
        {

            images[row, colum] = new Bitmap(image.Width/rows,image.Height/columns);
            
            Graphics g = Graphics.FromImage(images[row, colum]);
            g.DrawImageUnscaled(image, (image.Width / rows) * row, (image.Height / columns) * colum,
                (image.Width / rows), (image.Height / columns));
        }
    }
    return images;
}

But only the first([0,0]) image in the array works the rest of them just turn blank i dont get why or if i did do any thing wrong..

Tnx for any help you can offer!!
 
DrawImage

One important thing you are failing to do is to dispose of your Graphics object. A using block will handle this for you:

Code:
using (Graphics g = Graphics.FromImage(images[row, colum]))
{
    //Use g
}

As for your image problem, the second and third parameters of the DrawImageUnscaled method are the destination coordinates, so youd need them to be zero. Unfortunately this method does not take source coordinates, so I recommend using DrawImage instead:

Code:
g.DrawImage(
  image,                  //Source image
  0,                      //Dest x
  0,                      //Dest y
  new Rectangle(
    (image.Width / rows) * row,
    (image.Height / columns) * colum,
    (image.Width / rows),
    (image.Height / columns)
  ),                      //Src rect
  GraphicsUnit.Pixel      //Units
);

Good luck :cool:
 
Re: DrawImage

Tnx alot looks like it works!!, but its extremely slow is there any way to speed it up?
I found bitblt but i cant get it to work the result is just black....
any way here is my bitblt code:
Code:
public Image[,] SplitImage(Image image, int rows, int columns)
{
    Image[,] images = new Image[rows, columns];
    for (int row = 0; row < rows; row++)
    {
        for (int colum = 0; colum < columns; colum++)
        {
            //UnManaged way
            using (Graphics sourceG = Graphics.FromImage(image))
            {
                int width = image.Width / rows;
                int height = image.Height / columns;

                // get te hDC of the target
                IntPtr hdcSrc = sourceG.GetHdc();
                // create a device context we can copy to
                IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
                // create a bitmap we can copy it to,
                // using GetDeviceCaps to get the width/height
                IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
                // select the bitmap object
                IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);

                // bitblt over
                GDI32.BitBlt(hdcDest, 0, 0, width, height,
                    hdcSrc, width * row, height * colum, GDI32.SRCCOPY);
                // restore selection
                GDI32.SelectObject(hdcDest, hOld);
                // clean up 
                GDI32.DeleteDC(hdcDest);
                sourceG.ReleaseHdc(hdcSrc);
                // get a .NET image object for it
                images[row, colum] = Image.FromHbitmap(hBitmap);
                // free up the Bitmap object
                GDI32.DeleteObject(hBitmap);
            }
        }
    }
    return images;
}

private class GDI32
{

    public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
    [DllImport("gdi32.dll")]
    public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
        int nWidth, int nHeight, IntPtr hObjectSource,
        int nXSrc, int nYSrc, int dwRop);
    [DllImport("gdi32.dll")]
    public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth,
        int nHeight);
    [DllImport("gdi32.dll")]
    public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
    [DllImport("gdi32.dll")]
    public static extern bool DeleteDC(IntPtr hDC);
    [DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr hObject);
    [DllImport("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
}
 
Last edited by a moderator:
Re: DrawImage

If speed is important then GDI+ is not your friend. Dont get me wrong... I use GDI+ all the time, but when performance is an issue Ive resorted to GDI and even (in extreme cases) written my own blitters. From the look of things you seem like you know your way around GDI, so that would be my recommendation.
 
Re: DrawImage

If speed is important then GDI+ is not your friend. Dont get me wrong... I use GDI+ all the time, but when performance is an issue Ive resorted to GDI and even (in extreme cases) written my own blitters. From the look of things you seem like you know your way around GDI, so that would be my recommendation.

well that was my first try to use GDI, but as i said it didnt turn out so well when i copy with blitblt the result is black and i still dont know why >.<...
 
Last edited by a moderator:
Re: DrawImage

Oh, I see. Guess I didnt read your last post so well. When you use the Bitmap.GetHdc function, the Hdc is write-only. GDI+ bitmaps can be written to with GDI but not read from. To use GDI you would probably need to load the bitmaps via GDI instead of GDI+. I dont know how to do this since my experience with GDI is mostly limited to VB6 where I could actually use VB to load the bitmaps and then GDI to blit them.
 
LoadImage function

To use GDI you would probably need to load the bitmaps via GDI instead of GDI+.

This could be done with LoadImage:

Code:
[DllImport("user32.dll", EntryPoint="LoadImageW")]
public static extern IntPtr LoadImage(
    IntPtr hInst,
    [MarshalAs(UnmanagedType.LPWStr)] string lpszName,
    uint uType,
    int cxDesired,
    int cyDesired,
    uint fuLoad
);

public const int IMAGE_BITMAP = 0;
public const int LR_LOADFROMFILE = 0x10;

For hInst you would pass IntPtr.Zero for loading from a file. uType is IMAGE_BITMAP, and cxDesired and cyDesired can both be passed as zero to use the actual image dimensions. For fuLoad, pass LR_LOADFROMFILE. The returned IntPtr is a hBitmap, so remember to use CloseHandle.

Good luck :cool:
 
Back
Top