Thread: Splitting an image into tiles

  1. #1
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005

    Splitting an image into tiles

    I've had an idea for a game, inspired by Advance Wars. The first hurdle I've decided to try and leap is displaying the map and I was thinking, it'd be easier to draw the whole map as a .bmp then somehow split it into tiles so I can mark certain parts; giving mountains better defensive values and fields none etc.

    Thing is, how do you split a bitmap up? I've got absolutely no clue - could someone enlighten me?

    EDIT: If I decide I don't want to use this approach, could someone give me a hint or two into a 'good' tile system? Would it be a good idea to create a class representing a tile then have an array of those?
    Last edited by cboard_member; 02-22-2006 at 09:06 AM.
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  2. #2
    C / C++
    Join Date
    Jan 2006
    The Netherlands
    I don't know the code-way but you can split a bmp into tiles with paint, photoshop or another image-editing program
    Operating Systems:
    - Ubuntu 9.04
    - XP

    Compiler: gcc

  3. #3
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Quote Originally Posted by Ideswa
    I don't know the code-way but you can split a bmp into tiles with paint, photoshop or another image-editing program
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  4. #4
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    I believe several techniques were put out during the discussion in this thread:
    Sic vis pacum para bellum. If you want peace, prepare for war.

  5. #5
    pwns nooblars
    Join Date
    Oct 2005
    Portland, Or
    Any graphics API you learn is sure to have the ability to pull out just part of an image. SDL if you get the image module, it is really simple, but if I recall right, you are using OpenGL, in which case there are probably a good couple hundred guides . You can also access OpenGL through SDL but with SDL you lose some control so that is your choice.

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    For our tile-based engine, I load the tiles into the editor I've created and split the tiles based on the current tilesize. The tilesize must be a power of 2.

    Then I go through the larger bitmap and extract the squares of tiles from it. This is done in GDI so it's hideous, but it's easier in DirectX or OpenGL since you have direct access to the surface.

    Then I save the tiles into a proprietary format and load them into the texture resource manager and then load the corresponding map data into the map resource manager.

    I'll post some code later after I leave work. No time right now.

    Ok, now for some code. Work was fast eh. Actually about ten hours between first section and this section, but you'd never know it.

    Ok I'm going to walk you through this conceptually first.

    1. We have 1 large bitmap.
    2. We want to create many smaller bitmaps from the 1 bitmap.

    Immediately you will see that we need:

    1. A desired cellsize for each smaller bitmap. You could use varying sizes, but that complicates the code enormously.
    2. A way to extract square sections from a larger bitmap, or a larger square section.

    I'll try to code this w/o using API specifics. For DirectX you would have to lock the surface of the large bitmap and the smaller bitmap and do a copy. For GDI you would need to create 2 DCs and do a whole bunch of other 'crap' to get it to work.

    This is a function that will extract tiles of size cellsize from a larger image.

    //Setup variables
    DWORD dwSourceWidth=SourceBitmap.dwWidth;
    DWORD dwSourceHeight=SourceBitmap.dwHeight;
    DWORD dwSourceOffset=0;
    DWORD dwStartSourceOffset=dwSourceOffset;
    DWORD dwDestOffset=0;
    DWORD dwDestWidth=dwCellSize;
    DWORD dwDestHeight=dwCellSize;
    //Vector to stick 'tiles' into
    std::vector<CTile *> vImages;
    int iDestColCounter=0;
    int iDestRowCounter=0;
    int iSourceColCounter=0;
    int iSourceRowCounter=0;
      //Extract 1 tile starting at dwSourceOffset
      //Create tile object
      CTile *tile=new CTile;
      //Get pointer to buffer
      DWORD *pDest=tile->GetBuffer();
        //Copy one DWORD from source to dest (movsd)
        //Increment destination offset
        //Increment source offset
        //Increment destination column counter
        //If column counter>dwCellSize
        if (iDestColCounter>dwCellSize)
           //Reset destination column counter and increment row count
           //Move down one line in source, but move to start of line
       } while (iRowCounter<dwDestHeight);
       //Reset loop vars for next tile
       //Save tile in vector
       //Move over 1 block in source bitmap
       //Check for end of source bitmap
       if (iSourceColCounter>dwSourceWidth)
          //Move down dwCellSize*iSourceRowCounter pixels
          //Set starting offset to dwStartSourceOffset
    } while (iSourceRowCounter<dwSourceHeight);
    This 'should' work if I've coded everything correctly. It traverses the source bitmap and destination bitmap linearily using offsets. There are no multiplies used to figure out the current position in either of the bitmaps.

    This is a small BitBlt w/o transparency in assembly.

    void BitBlt(DWORD dwX,DWORD dwY,DWORD *pSource,DWORD dwSrcWidth,DWORD *pDest,DWORD dwDestWidth,DWORD dwDestHeight)
      _asm {
        mov esi,[pSource]
        mov edi,[pDest]
        mov eax,dwY
        mov ebx,dwSrcWidth
        mul  ebx
        //Move to dwX,dwY in source image
        add esi,eax
        xor eax,eax
      _asm {
        mov ecx,dwDestWidth
        rep movsd
        //Increment row counter
        inc eax
        //Are we done?
        cmp eax,dwDestHeight
        //If above we are done
        ja DONE:
        //Move down one line in source bitmap
        add esi,dwSrcWidth
        //Move to start of line or left side of tile image by subtracting
        //width of destination bitmap
        sub esi,dwDestWidth
        //Here edi is at the right point
        jmp START
    You may want to test this as I coded it sitting here and have not compiled it.

    It looks strange because the compiler will not allow labels inside of _asm blocks and unfortunately in assembly there isn't any other way to do an a comparison (if) or break out of a loop w/o using them.

    This will work provided the direction flag is correct, I prob should deliberately set it, and the coordinates given with the height and width given will not run off the edges of the source bitmap. I could adjust for this with a couple more lines of code, but chose not to.
    Last edited by VirtualAce; 02-23-2006 at 03:27 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 04:17 AM
  2. Replies: 1
    Last Post: 05-27-2009, 12:46 PM
  3. Simple Image Processing
    By ejohns85 in forum C++ Programming
    Replies: 4
    Last Post: 03-19-2009, 12:10 PM
  4. Splitting the Image in four corrdinates
    By simly01 in forum C++ Programming
    Replies: 1
    Last Post: 03-29-2003, 01:12 PM
  5. Replies: 4
    Last Post: 03-02-2003, 09:12 AM