Domanda

Sto provando ad accedere ai dati grezzi di una bitmap in formato ARGB_8888 su Android, utilizzando il file copyPixelsToBuffer E copyPixelsFromBuffer metodi.Tuttavia, l'invocazione di tali chiamate sembra applicare sempre il canale alfa ai canali RGB.Ho bisogno dei dati grezzi in un byte[] o simile (per passare attraverso JNI;sì, conosco bitmap.h in Android 2.2, non posso usarlo).

Ecco un esempio:

    // 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)));

Il registro quindi mostra

hasAlpha() = true
pixel before = ef234567
value before = 214161ef
value after = ffffff61
pixel after = 619e9e9e

Capisco che l'ordine dei canali argb sia diverso;va bene.Ma non voglio che il canale Alpha venga applicato su ogni copia (che è quello che sembra fare).

È così? copyPixelsToBuffer E copyPixelsFromBuffer dovrebbero funzionare?È lì Qualunque modo per ottenere i dati grezzi in un byte[]?

Aggiunto in risposta alla risposta di seguito:

Mettere dentro buffer.order(ByteOrder.nativeOrder()); prima di copyPixelsToBuffer cambia il risultato, ma non ancora nel modo in cui lo voglio:

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

Sembra soffrire essenzialmente dello stesso problema (l'alfa viene applicato su ciascuno copyPixelsFrom/ToBuffer).

È stato utile?

Soluzione

Mi rendo conto che questo è molto stantio e probabilmente non ti aiuterà ora, ma ho incontrato di recente questo nel tentativo di ottenere copyPixelsFromBuffer per lavorare nella mia app.(Grazie per aver fatto questa domanda, btw! Mi hai salvato tonnellate di tempo nel debug.) Sto aggiungendo questa risposta nella speranza Aiuta gli altri come me andare avanti ...

Sebbene non abbia ancora usato questo per assicurarmi che funzioni, sembra che, a partire dal livello 19 API, avremo finalmente un modo per specificare di non "applicare l'alfa" (AKA Premultaliply) all'interno di Bitmap.Stanno aggiungendo un setPremultiplied(boolean) Metodo che dovrebbeAiutare in situazioni come questa andando avanti permettendoci di specificare false.

Spero che questo aiuti!

Altri suggerimenti

Un modo per accedere ai dati in bitmap è utilizzare il metodo GetPixels ().Di seguito è possibile trovare un esempio che ho usato per ottenere un'immagine in scala di grigi da dati di argb e poi torna da byte array a bitmap (ovviamente se hai bisogno di RGB prenoti 3x byte e salvali tutti ...):

/*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;
   }

}
.

La mia ipotesi è che questo potrebbe dover fare con l'ordine dei byte del bytebuffer che stai utilizzando.Bytebuffer utilizza Big Endian per impostazione predefinita. Impostare Endianess sul buffer con

buffer.order(ByteOrder.nativeOrder());
.

Vedi se aiuta.

Inoltre, CopypixelsFruffuffer / CopypixelStoBuffer non modifica i dati dei pixel in alcun modo.Sono copiati crudi.

Questa è una vecchia domanda, ma ho riscontrato lo stesso problema e ho appena scoperto che i byte bitmap sono premoltiplicati, puoi impostare la bitmap (a partire dall'API 19) per non premoltiplicare il buffer, ma nell'API non danno alcuna garanzia.

Da i documenti:

public final void setPremultiplied(boolean premultiplied)

Imposta se la bitmap deve considerare i propri dati come premoltiplicati.Le bitmap vengono sempre trattate come premoltiplicate dal sistema di visualizzazione e dal Canvas per motivi di prestazioni.Memorizzazione di dati non premoltiplicati in una bitmap (attraverso setPixel, setPixels, O BitmapFactory.Options.inPremultiplied) può portare a una fusione errata se disegnata dal quadro.

Questo metodo non influenzerà il comportamento di una bitmap senza canale alfa o se hasAlpha() restituisce falso.

Chiamando createBitmap O createScaledBitmap con una bitmap di origine i cui colori non sono premoltiplicati può risultare in a RuntimeException, poiché tali funzioni richiedono il disegno della sorgente, che non è supportata per le bitmap non premoltiplicate.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top