Unable to acess all the pixels in a bitmap


Last Updated:

  1. JamesBurnstone

    JamesBurnstone Member This Topic's Starter

    Joined:
    Nov 22, 2010
    Messages:
    9
    Likes Received:
    0
    In short I am unable to access all the pixels of a bitmap image.
    I have used an intent to fire the native Camera app and returned a Bitmap image to my application activity. The data is definitely a bitmap object and I am able to display, get the height/width etc and access some pixels using getPixel(). However when I use the values of getHeight() and getWidth() I get an array out of bounds error. By trail and error I have found I can only access a reduced number of pixels of the image, for example with one image which returned a height and width value of 420,380, I could also access 200,100. I then do some image processing and used setPixel() on the original image. When I display the image it shows the, say 200,100, processing pixels and the rest normal, therefore the pixels are obviously there and accessible by android but not by me. I have to spoken to other people who have also had this problem with images.
    Does anyone know anything more about this, reasons? or a work around?
    Many thanks in advance.
     

    Advertisement
  2. AlbertPucciani

    AlbertPucciani Well-Known Member

    Joined:
    Oct 2, 2010
    Messages:
    71
    Likes Received:
    8
    Hi,

    Not sure whats happening, maybe try this little snippet I just wrote:

    Code (Text):
    1.  
    2.    Bitmap mBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.my_image);
    3.    int height = mBitmap.getHeight(), width = mBitmap.getWidth();
    4.    int currentPixelPosition = 0;
    5.    int findValue = 0, replaceValue = 1;
    6.        
    7.    IntBuffer mPixels = IntBuffer.allocate(mBitmap.getWidth()*mBitmap.getHeight());
    8.    mBitmap.copyPixelsToBuffer(mPixels);
    9.        
    10.    for (int rowCounter=0;rowCounter<height;rowCounter++) {
    11.            
    12.       for (int colCounter = 0;colCounter<width;colCounter++) {
    13.          currentPixelPosition = (rowCounter*width)+colCounter;
    14.                
    15.          if (mPixels.get(currentPixelPosition) == findValue) {
    16.             mPixels.put(currentPixelPosition, replaceValue);
    17.          }
    18.       }
    19.            
    20.    }
    21.  
    22.    mBitmap.copyPixelsFromBuffer(mPixels);  
    23.  
    The getPixel()/setPixel() routine are really slow anyways, this is a much faster way to access the values of a pixel without causing much Garbage Collection.

    I didn't actually test the above code, I just rewrote it in the editor from memory of other code I wrote that does the same thing, so you might have to play with it.

    Let me know if you need any more help.
     
    JamesBurnstone likes this.
  3. JamesBurnstone

    JamesBurnstone Member This Topic's Starter

    Joined:
    Nov 22, 2010
    Messages:
    9
    Likes Received:
    0
    Thank you this has helped alot
     
  4. JamesBurnstone

    JamesBurnstone Member This Topic's Starter

    Joined:
    Nov 22, 2010
    Messages:
    9
    Likes Received:
    0
    Albert,

    The code allows me to access all the pixels, I wondered if you could tell me what format I am getting the individually pixels in.

    Before I was taking a pixel and then used shifting and an and operator to get the alpha, R, G and B components.

    From previous testing I know that the first pixel, of my test image, (0,0) as an int should be -4100278 which corresponds to 11111111 11000001 01101111 01001010, but the first pixel I get in the buffer is -1012221079 which is not a pixel value anywhere in the image as all transparacenies are always 255.

    I thought as you seemed to have worked with image processing you may be able to point me in the right direction.

    To let you know this is all for my PhD project for which I am currently building a real time adaptive skin filter which was easy on MATLAB, not so much on android!
     
  5. AlbertPucciani

    AlbertPucciani Well-Known Member

    Joined:
    Oct 2, 2010
    Messages:
    71
    Likes Received:
    8
    Hi,
    I've done some image processing, but not much so most of this is my experience doing things for the game I created. "get/setPixels()" gives you a converted number, not the 32bit pixel value. If you are using "copyPixels...Buffer()" you are getting the raw pixel format.

    See the Android Bitmap Code here: android.git.kernel.org Git - platform/frameworks/base.git/blob - graphics/java/android/graphics/Bitmap.java.

    If you look at the comments for "copyPixel...Buffer()" and "set/getPixel()" you'll see that the author comments on the 32bit pixel format conversion. Hope that answers your question, let me know if it doesn't.
     
  6. JamesBurnstone

    JamesBurnstone Member This Topic's Starter

    Joined:
    Nov 22, 2010
    Messages:
    9
    Likes Received:
    0
    Thanks for the advice the raw image format, I've done all my image processing on matlab so I'm new to understanding file formats and stuff. I looked through the buffer of pixels and found that again out of the 262144 capacity, 512 h x 512 w, only 131071 entires are made, am I missing pixels again or is this to do with the format or the pixels as this is very nearly half of 512x512. Are the pixels, as bytes, being placed in different ints and therefore one int does not imply the four bytes of a single pixel? I hope that makes sense, sorry I wasn't very good at understanding the Bitmap api
     
  7. AlbertPucciani

    AlbertPucciani Well-Known Member

    Joined:
    Oct 2, 2010
    Messages:
    71
    Likes Received:
    8
    Try changing the IntBuffer to a ByteBuffer or a ShortBuffer. Start with the ByteBuffer because that's your best bet. I'm guessing that the ByteBuffer would contain 4 bytes per stride indicating RGBA color values, but I don't know that.

    Its also possible that each integer holds more than one pixel and you'd have to do a bit shift on the integer to get the RGBA value(s). See Double Greater Than Sign (>>) in Java? - Stack Overflow for some details on how a bit shift works.

    Android does some really weird things that don't make sense. Such as the bit shift being used throughout the API to get a certain output (like handling multitouch pre 2.2).

    Keep me updated, maybe even post your code and I'll see if I can help.
     
  8. JamesBurnstone

    JamesBurnstone Member This Topic's Starter

    Joined:
    Nov 22, 2010
    Messages:
    9
    Likes Received:
    0
    The program crashes when I use a ByteBuffer. What I have discovered is that the original problem was due to memory. At first I was creating 2D arrays of all the R G and B data from the image, now I tried to run through the whole image just overwriting a single int variable for each pixel using getPixel. It worked but its very slow no chance of this being a real time application. I've read that there's only 24MB of allocated memory to a process, this might of been version 1.5 so hopefully that's changed. My plan is now to use the OpenGL stuff to handle to image as this has a separate memory allocation or try to resize each image though reading through stackoverflow this seems quite difficult on it's own. If not my supervisor has advised I create my own native code to access the image in memory though a bit out of my league at the moment. Thanks for all your help, is you have anymore advice on the above topics please let me know.
     
  9. AlbertPucciani

    AlbertPucciani Well-Known Member

    Joined:
    Oct 2, 2010
    Messages:
    71
    Likes Received:
    8
    Yes, calling getPixel()/setPixel() is very slow. CopyPixelsToBuffer() is on the order of 5-10x faster or more, but still really slow compared to something you could write in the JNI. However, I'm not sure if you could access the Bitmaps native buffer at all, you may still have to use the Bitmaps CopyPixelsToBuffer() option for anything requiring some speed.

    In my tests (this is from recent memory) one level on my game runs 40-60 fps, but when using the CopyPixelsToBuffer on one 1100x400 png each frame, the fps dropped to 11-17. When I used getPixel()/setPixel() the fps dropped to 1-2.

    Hope that helps
     

Share This Page

Loading...