Sign in to follow this  
MajinMusashi

Converting images from upper-left to bottom-left origin

Recommended Posts

CONTEXT: These days I was revising my TGA image loading methods and found out that some images use top-left origin instead of the most used nowadays bottom-left origin. So, I've read the TGA specification and discovered that the 17th byte of the image header contains the information I wanted: whether coordinates system origin is upper-left or bottom-right. Then I wrote a method that, after all the image loading and such, swap the lines and make every texture bottom-left origin. PROBLEM: As you can see from the source code below, everything is working fine, but the readibility is not so good (and I'm using C style functions).
// Check if the image has upper-left origin. If so, swap lines so that
// the origin stays at the image bottom-left
if ( header[17] & 0x00000020 ) {
  unsigned int lineSize = auxTex.bytesPerPixel * auxTex.width;
  unsigned int halfHeight = auxTex.height / 2;
  GLubyte* tempLine = new GLubyte[ lineSize ];

  // Swap lines using a temporary line
  for (int currentLine = 0; currentLine < halfHeight; ++currentLine ) {
    memcpy( tempLine, auxTex.imageData + (currentLine * lineSize), lineSize );
    memcpy( auxTex.imageData + (currentLine * lineSize), auxTex.imageData + ((auxTex.width - currentLine - 1) * lineSize), lineSize );
    memcpy( auxTex.imageData + ((auxTex.width - currentLine - 1) * lineSize), tempLine, lineSize );
  }

  delete [] tempLine;
}

QUESTION: Do you have any advices on how to rewrite this block of code so it looks more friendly? Is there any ultra-secret STL algorithm that can do the job in one pass? Thanks a lot!

Share this post


Link to post
Share on other sites
The std::reverse algorithm was designed for scenarios like this, but you have to provide it with an iterator of some sort. For working directly with in-memory data as you are, I'd say what you have is fine -- and in fact, perfectly readable and understandable to me. As soon as I saw that you were reversing the data top-to-bottom and using a variable "halfHeight", I understood that you were performing an in-place swap moving from the top and bottom of the image toward the middle.

Share this post


Link to post
Share on other sites
Quote:
Original post by MajinMusashi
QUESTION: Do you have any advices on how to rewrite this block of code so it looks more friendly? Is there any ultra-secret STL algorithm that can do the job in one pass?
I'll post a std::reverse method just for comparison; see if it fits your performance needs:
template< unsigned int width >
struct scanline { unsigned char scanline_[width]; };
// ...
if( header[17] & 0x00000020 ) {

// size and point our scanline iterator at image data
unsigned int lineSize = auxTex.bytesPerPixel * auxTex.width;

scanline<lineSize> * sl = (scanline<lineSize> *)(auxTex.imageData)

// and reverse image data
std::reverse( sl, sl+auxTex.height );
}



EDITED: to correct typos and add friendliness

[Edited by - stylin on October 5, 2005 1:54:09 PM]

Share this post


Link to post
Share on other sites
ERRATA: The above method does not work; it errors unless you feed it compile-time constant arguments (as I was naively doing in my test app).

I've tried using array pointers, obviously with the same result. Does anyone know if this can be done without using a temp copy array?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this