ALPHA_8 bitmaps and getPixel

后端 未结 4 1584
既然无缘
既然无缘 2020-12-31 19:59

I am trying to load a movement map from a PNG image. In order to save memory after I load the bitmap I do something like that.

 
 `Bitmap mapBmp = tempBmp.         


        
相关标签:
4条回答
  • 2020-12-31 20:38

    I was able to find a nice and sort of clean way to create boundary maps. I create an ALPHA_8 bitmap from the start. I paint my boundry map with paths. Then I use the copyPixelsToBuffer() and transfer the bytes into a ByteBuffer. I use the buffer to "getPixels" from. I think is a good solution since you can scale down or up the path() and draw the boundary map at the desired screen resolution scale and no IO + decode operations. Bitmap.getPixel() is useless for ALPHA_8 bitmaps, it always returns 0.

    0 讨论(0)
  • 2020-12-31 20:38

    I developed solution with PNGJ library, to read image from assets and then create Bitmap with Config.ALPHA_8.

    import ar.com.hjg.pngj.IImageLine;
    import ar.com.hjg.pngj.ImageLineHelper;
    import ar.com.hjg.pngj.PngReader;
    
    public Bitmap getAlpha8BitmapFromAssets(String file) {
    
        Bitmap result = null;
    
        try {
    
            PngReader pngr = new PngReader(getAssets().open(file));
            int channels = pngr.imgInfo.channels;
            if (channels < 3 || pngr.imgInfo.bitDepth != 8)
                throw new RuntimeException("This method is for RGB8/RGBA8 images");
    
            int bytes = pngr.imgInfo.cols * pngr.imgInfo.rows;
            ByteBuffer buffer = ByteBuffer.allocate(bytes);
    
            for (int row = 0; row < pngr.imgInfo.rows; row++) { 
    
                IImageLine l1 = pngr.readRow();
    
                for (int j = 0; j < pngr.imgInfo.cols; j++) {
    
                    int original_color = ImageLineHelper.getPixelARGB8(l1, j);
    
                    byte x = (byte) Color.alpha(original_color);
    
                    buffer.put(row * pngr.imgInfo.cols + j, x ^= 0xff);
    
                }
    
            }
    
            pngr.end();
    
            result = Bitmap.createBitmap(pngr.imgInfo.cols,pngr.imgInfo.rows, Bitmap.Config.ALPHA_8);
            result.copyPixelsFromBuffer(buffer);
    
        } catch (IOException e) {
            Log.e(LOG_TAG, e.getMessage());
        }
    
        return result;
    
    }
    

    I also invert alpha values, because of my particular needs. This code is only tested for API 21.

    0 讨论(0)
  • 2020-12-31 20:46

    Seems to be an Android bug in handling ALPHA_8. I also tried copyPixelsToBuffer, to no avail. Simplest workaround is to waste lots of memory and use ARGB_8888.

    Issue 25690

    0 讨论(0)
  • 2020-12-31 20:52

    I found this question from Google and I was able to extract the pixels using the copyPixelsToBuffer() method that Mitrescu Catalin ended up using. This is what my code looks like in case anyone else finds this as well:

    public byte[] getPixels(Bitmap b) {
        int bytes = b.getRowBytes() * b.getHeight();
        ByteBuffer buffer = ByteBuffer.allocate(bytes);
        b.copyPixelsToBuffer(buffer);
        return buffer.array();
    }
    

    If you are coding for API level 12 or higher you could use getByteCount() instead to get the total number of bytes to allocate. However if you are coding for API level 19 (KitKat) you should probably use getAllocationByteCount() instead.

    0 讨论(0)
提交回复
热议问题