Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/184.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
访问ARGB_8888 Android位图中的原始数据_Android_Bitmap_Java Native Interface_Alpha Transparency_Argb - Fatal编程技术网

访问ARGB_8888 Android位图中的原始数据

访问ARGB_8888 Android位图中的原始数据,android,bitmap,java-native-interface,alpha-transparency,argb,Android,Bitmap,Java Native Interface,Alpha Transparency,Argb,我正在尝试使用copyPixelsToBuffer和copyPixelsFromBuffer方法在Android上访问ARGB_8888格式位图的原始数据。然而,调用这些调用似乎总是将alpha通道应用于rgb通道。我需要字节[]或类似的原始数据(要通过JNI;是的,我知道Android 2.2中的bitmap.h,不能使用它) 以下是一个示例: // Create 1x1 Bitmap with alpha channel, 8 bits per channel Bitmap

我正在尝试使用
copyPixelsToBuffer
copyPixelsFromBuffer
方法在Android上访问ARGB_8888格式位图的原始数据。然而,调用这些调用似乎总是将alpha通道应用于rgb通道。我需要字节[]或类似的原始数据(要通过JNI;是的,我知道Android 2.2中的bitmap.h,不能使用它)

以下是一个示例:

    // Create 1x1 Bitmap with alpha channel, 8 bits per channel
    Bitmap one = Bitmap.createBitmap(1,1,Bitmap.Config.ARGB_8888);
    one.setPixel(0,0,0xef234567);
    Log.v("?","hasAlpha() = "+Boolean.toString(one.hasAlpha()));
    Log.v("?","pixel before = "+Integer.toHexString(one.getPixel(0,0)));

    // Copy Bitmap to buffer
    byte[] store = new byte[4];
    ByteBuffer buffer  = ByteBuffer.wrap(store);
    one.copyPixelsToBuffer(buffer);

    // Change value of the pixel
    int value=buffer.getInt(0);
    Log.v("?", "value before = "+Integer.toHexString(value));
    value = (value >> 8) | 0xffffff00;
    buffer.putInt(0, value);
    value=buffer.getInt(0);
    Log.v("?", "value after = "+Integer.toHexString(value));

    // Copy buffer back to Bitmap
    buffer.position(0);
    one.copyPixelsFromBuffer(buffer);
    Log.v("?","pixel after = "+Integer.toHexString(one.getPixel(0,0)));
然后显示日志

hasAlpha() = true
pixel before = ef234567
value before = 214161ef
value after = ffffff61
pixel after = 619e9e9e
我知道argb通道的顺序不同;那很好。但我不知道 希望alpha通道应用于每个副本(这似乎就是它正在做的)

这就是
copyPixelsToBuffer
copyPixelsFromBuffer
的工作原理吗?有没有办法获取字节[]中的原始数据

在回答以下问题时添加:

放入
buffer.order(ByteOrder.nativeOrder())
copyPixelsToBuffer
更改结果之前,但仍然不是以我想要的方式:

pixel before = ef234567
value before = ef614121
value after = ffffff41
pixel after = ff41ffff

似乎存在本质上相同的问题(alpha应用于/ToBuffer的每个
复制像素)。

我猜这可能与您使用的ByteBuffer的字节顺序有关。默认情况下,ByteBuffer使用big-endian。 使用设置缓冲区的endianess

buffer.order(ByteOrder.nativeOrder());
看看是否有帮助


此外,copyPixelsFromBuffer/copyPixelsToBuffer不会以任何方式更改像素数据。它们是原始复制的。

我意识到这非常陈旧,现在可能帮不了你,但我最近在尝试让
copyPixelsFromBuffer
在我的应用程序中工作时遇到了这一点。(谢谢你问这个问题,顺便说一句!你在调试中为我节省了很多时间。)我添加这个答案是希望它能帮助像我这样的人继续前进

虽然我还没有使用它来确保它工作,但从API级别19开始,我们终于有了一种方法来指定在
位图中不“应用alpha”(也称为预乘)。他们正在添加一种方法,允许我们指定
false
,这将有助于解决类似情况


我希望这有帮助

访问位图中数据的一种方法是使用getPixels()方法。下面您可以找到一个示例,我使用它从argb数据获取灰度图像,然后从字节数组返回到位图(当然,如果您需要rgb,您可以保留3x字节并将它们全部保存…):

/*Sami Varjo提供的免费使用许可证(但如果您保留这一行,则很好)*/
公共最终类位图转换器{
私有位图转换器(){};
/**
*从argb图像到字节数组获取灰度数据
*/
公共静态字节[]ARGB2Gray(位图img)
{
int width=img.getWidth();
int height=img.getHeight();
int[]像素=新int[高度*宽度];
字节grayIm[]=新字节[高度*宽度];
获取像素(像素,0,宽度,0,0,宽度,高度);
整数像素=0;
整数计数=宽度*高度;
同时(计数-->0){
int inVal=像素[像素];
//从int获取像素通道值
双r=(双)((无效和0x00ff0000)>>16);
双g=(双)((无效和0x0000ff00)>>8);
双b=(双)(无效和0x000000ff);
灰度[pixel++]=(字节)(0.2989*r+0.5870*g+0.1140*b);
}
返回格雷姆;
}
/**
*从字节数组创建灰度位图
*/
公共静态位图gray2ARGB(字节[]数据,整型宽度,整型高度)
{
整数计数=高度*宽度;
int[]outPix=新的int[计数];
整数像素=0;
同时(计数-->0){
int val=data[pixel]&0xff;//将字节转换为无符号

outPix[pixel++]=0xff000000 | val这是一个老问题,但我也遇到了同样的问题,我刚刚发现位图字节是预乘的,您可以将位图(从API 19开始)设置为不预乘缓冲区,但在API中它们不保证

发件人:

public final void set预乘(布尔预乘)

设置位图是否应将其数据视为预乘。 出于性能原因,位图始终被视为视图系统和画布的预乘。如果由框架绘制,则在位图中存储未预乘的数据(通过
setPixel
setPixels
BitmapFactory.Options.inPremultiplied
)可能导致不正确的混合

如果
hasAlpha()
返回false,此方法不会影响没有alpha通道的位图的行为

使用颜色未预乘的源位图调用
createBitmap
createScaledBitmap
,可能会导致
RuntimeException
,因为这些函数需要绘制源位图,而未预乘的位图不支持绘制源位图


这改变了结果,但不是主要问题:alpha通道仍应用于每个副本(请参阅我问题中添加的注释)。实际上,copyPixelsToBuffer似乎正在将alpha通道应用于rgb通道。设置Pixel(0,0.0x7f224466)时,可以清楚地看到这一点当读到缓冲区时,这将是0x7f33 2211。这可能是一个bug。考虑报告这个问题。嗨,我也遇到了这个问题。你找到了解决这个问题的方法吗?也许是把数据转换成真的RGB值的方法?你可能想检查<代码>位图。
也是。当alpha通道存在时,猜测默认设置为
true
。您是否尝试过
Bitmap.getPixels()
?文档明确说明它返回未乘以的ARGB像素。还有一个关于
getPixels()的答案
但您没有对此发表评论。@Kasperpeters呵呵,谢谢!我希望这能解决我们的问题!
/*Free to use licence by Sami Varjo (but nice if you retain this line)*/

public final class BitmapConverter {

    private BitmapConverter(){};

   /**
    * Get grayscale data from argb image to byte array
    */
   public static byte[] ARGB2Gray(Bitmap img)
   {

       int width = img.getWidth();
       int height = img.getHeight();

       int[] pixels = new int[height*width];
       byte grayIm[] = new byte[height*width];

       img.getPixels(pixels,0,width,0,0,width,height);

       int pixel=0;
       int count=width*height;

       while(count-->0){
           int inVal = pixels[pixel];

           //Get the pixel channel values from int 
           double r = (double)( (inVal & 0x00ff0000)>>16 );
           double g = (double)( (inVal & 0x0000ff00)>>8  );
           double b = (double)(  inVal & 0x000000ff)      ;

           grayIm[pixel++] = (byte)( 0.2989*r + 0.5870*g + 0.1140*b );
       }

       return grayIm;
   }

   /**
    * Create a gray scale bitmap from byte array
    */
   public static Bitmap gray2ARGB(byte[] data, int width, int height)
   {
       int count = height*width;
       int[] outPix = new int[count];
       int pixel=0;
       while(count-->0){
           int val = data[pixel] & 0xff; //convert byte to unsigned
           outPix[pixel++] = 0xff000000 | val << 16 | val << 8 | val ;
       }

       Bitmap out =  Bitmap.createBitmap(outPix,0,width,width, height, Bitmap.Config.ARGB_8888);
       return out;
   }

}