We're a community of 1076K IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,075,574 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Start New Discussion Reply to this Discussion

Flip vector of bytes.

I'm trying to flip an image which has its pixels stored in a vector. For some reason, when I try to flip it, the image gets distorted and gray/fuzzy. Any idea why?

My code is as follows:

void JNIData::FlipBytes(void*& Result, bool TopDown)
{
    unsigned char* Pixels = &BufferPixels[0];  //vector of pixels/unsigned chars.
    unsigned char* BuffPos = static_cast<unsigned char*>(Result);

    for (int I = 0; I < height; ++I)
    {
        for (int J = 0; J < width; ++J)
        {
            int Offset = TopDown ? (height - 1 - I) * width + J : I * width + J;
            *(BuffPos++) = *(Pixels++ + Offset);
            *(BuffPos++) = *(Pixels++ + Offset);
            *(BuffPos++) = *(Pixels++ + Offset);

            if (Bpp > 24)
                *(BuffPos++) = *(Pixels++ + Offset);
        }

        if (Bpp == 24)
        {
            BuffPos += width % 4;
            Pixels += width % 4;
        }
    }
}
3
Contributors
3
Replies
18 Hours
Discussion Span
6 Months Ago
Last Updated
4
Views
Question
Answered
triumphost
Practically a Master Poster
625 posts since Oct 2009
Reputation Points: 59
Solved Threads: 55
Skill Endorsements: 1

A few questions:
Are BufferPixels, Bpp, height, and width instance variables? They aren't declared or passed anywhere in the method as shown.

Why couldn't unsigned char* Pixels = &BufferPixels[0]; be written as unsigned char* Pixels = BufferPixels;?

What does Bpp represent? Pixel depth (bits per pixel)? If so, shouldn't the pixels be a 32-bit unsigned, rather than an 8-bit unsigned (even if only 24 bits are actually used at times)? Or is this the reason why you have unrolled the loop by three (or four, in cases where Bpp is greater than 24)?

Why is Result a void pointer?

Do the pixels have to be aligned on word or doubleword boundaries in order to be rendered correctly? Is byte order significant?

Schol-R-LEA
Veteran Poster
1,016 posts since Oct 2010
Reputation Points: 414
Solved Threads: 163
Skill Endorsements: 10
  1. BufferPixels is a std::vector<unsigned char> within a class. Private member non-static.
  2. Width and Height are also private non-static class members.
  3. Bpp = BitsPerPixel which can be both 24 or 32.
  4. I used unsigned char* Pixels = &BufferPixels[0] because it's a vector. I would have just used Pixels = BufferPixels.data();
  5. What do you mean 32bit unsigned vs. 8bit unsigned?
  6. I loop through 3 times because if it's 24 bit, alpha doesn't matter. 4 times for 32 bit.
  7. Result is a void pointer because I'm given a void pointer that I will be filling with the flipped Pixels. Ex: I take the vector, flip all the bytes and copy the flipped pixels to the void pointer. The void ptr can also be an unsigned char*.
  8. Well it's for rendering so yes I need to align it to render correctly. I assume I'd need to pad it on 4 byte boundaries and byte order would matter.

I'm basically getting a buffer from JNI (Java) and passing it to my DLL. The DLL fills that buffer with the pixels of an image but sometimes it renders badly and sometimes upside down.

My second attempt to flip it was (I didn't want to use Memcpy):

void JNIData::FlipBytes(void*& Result)
{
   unsigned long Chunk = width * Bpp > 24 ? 4 : 3;
   unsigned char* Destination = static_cast<unsigned char*>(Result);

   unsigned char* Source = &BufferPixels[0] + Chunk * (height - 1);

   for (int I = 0; I < height; ++I)
   {
      std::memcpy(Destination, Source, Chunk);
      Destination += Chunk;
      Source -= Chunk;
   }
}

The above works but it will only render if I fake the image size and make the width and height divisible by 4.

triumphost
Practically a Master Poster
625 posts since Oct 2009
Reputation Points: 59
Solved Threads: 55
Skill Endorsements: 1

In the function you just posted, you forgot to handle the misalignment at the end of the pixel rows. This should work:

void JNIData::FlipBytes(void*& Result) {
   unsigned long Chunk = (Bpp > 24 ? width * 4 : width * 3 + width % 4);
   unsigned char* Destination = static_cast<unsigned char*>(Result);

   unsigned char* Source = &BufferPixels[0] + Chunk * (height - 1);

   while(Source != &BufferPixels[0]) {
      std::memcpy(Destination, Source, Chunk);
      Destination += Chunk;
      Source -= Chunk;
   }
}

As for the earlier version (in original post), I would just forget about it. The monkey business with this line:

int Offset = TopDown ? (height - 1 - I) * width + J : I * width + J;

looks very suspicious to me. If anything, you should probably use a strategy similar to that of the other version, i.e., go backwards in the source image, and forward in the destination image.

mike_2000_17
21st Century Viking
Moderator
3,135 posts since Jul 2010
Reputation Points: 2,050
Solved Threads: 625
Skill Endorsements: 41
Question Answered as of 6 Months Ago by mike_2000_17 and Schol-R-LEA

This question has already been solved: Start a new discussion instead

Post: Markdown Syntax: Formatting Help
 
You
 
© 2013 DaniWeb® LLC
Page rendered in 0.0717 seconds using 2.78MB