J2ME: Convertire immagini PNG trasparenti in scala di grigi
Domanda
c'è qualche possiblity in J2ME per convertire un'immagine (caricata da un file png con alpha) per una nuova scala di grigio trasparente?
Fino ad ora ho ottenuto solo i valori RGB, ma non l'alfa.
Grazie.
Modifica: sì, dovrebbe essere a 32 bit in scala di grigi
.Soluzione
Ho trovato la soluzione ed ecco il codice:
public Image getGrayScaleImage() {
int[] rgbData = new int[getWidth() * getHeight()];
image.getRGB(rgbData, 0, getWidth(), 0, 0, getWidth(), getHeight());
for (int x = 0; x < getWidth() * getHeight(); x++) {
rgbData[x] = getGrayScale(rgbData[x]);
}
Image grayImage = Image.createRGBImage(rgbData, getWidth(), getHeight(), true);
return grayImage;
}
private int getGrayScale(int c) {
int[] p = new int[4];
p[0] = (int) ((c & 0xFF000000) >>> 24); // Opacity level
p[1] = (int) ((c & 0x00FF0000) >>> 16); // Red level
p[2] = (int) ((c & 0x0000FF00) >>> 8); // Green level
p[3] = (int) (c & 0x000000FF); // Blue level
int nc = p[1] / 3 + p[2] / 3 + p[3] / 3;
// a little bit brighter
nc = nc / 2 + 127;
p[1] = nc;
p[2] = nc;
p[3] = nc;
int gc = (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
return gc;
}
getRGB restituisce il valore del colore che comprende anche il canale alfa. Così ho dovuto solo cambiare ogni valore nella matrice e creare un'immagine da questo.
Ho trovato un documento utile nel forum nokia: MIDP 2.0: Lavorare con Pixel e drawRGB ()
Altri suggerimenti
Grazie per il codice sulla conversione in scala di grigi. Tuttavia, ho notato che, sul Nokia Serie 40, questo codice viene eseguito piuttosto lentamente.
Ci sono 2 ottimizzazioni. Il principale è quello di rimuovere ogni creazione oggetto in getGrayScale (). Attualmente, un oggetto array viene creata per ogni pixel. Per una media, dire QVGA, schermo che è 76800 oggetti array creati, che è un sacco di immondizia, e probabilmente richiamare GC. Definizione del int [4] come un campo nella classe rimuove questo la creazione di oggetti. Il trade-off: ecco un piccola quantità di RAM aggiuntivo utilizzato per la classe.
Il secondo è quello di memorizzare nella cache la larghezza e l'altezza in getGrayScaleImage (). In alcuni dispositivi, il metodo chiama a getWidth () e getHeight () sarà chiamato ripetutamente senza ottimizzazioni (un compilatore JIT sarà OK ma comunque interpretato dispositivi non). Così, ancora una volta per QVGA, la getWidth () e getHeight () sarà chiamato alcuni> 150000 tra di loro.
In tutto, ho trovato questa versione modificata di corsa molto più veloce: -)
public Image getGrayScaleImage(Image screenshot) {
int width = getWidth();
int height = getHeight();
int screenSizeInPixels = (width * height);
int[] rgbData = new int[width * height];
image.getRGB(rgbData, 0, width, 0, 0, width, height);
for (int x = 0; x < screenSizeInPixels ; x++) {
rgbData[x] = getGrayScale(rgbData[x]);
}
Image grayImage = Image.createRGBImage(rgbData, width, height, true);
return grayImage;
}
static int[] p = new int[4];
private int getGrayScale(int c) {
p[0] = (int) ((c & 0xFF000000) >>> 24); // Opacity level
p[1] = (int) ((c & 0x00FF0000) >>> 16); // Red level
p[2] = (int) ((c & 0x0000FF00) >>> 8); // Green level
p[3] = (int) (c & 0x000000FF); // Blue level
int nc = p[1] / 3 + p[2] / 3 + p[3] / 3;
// a little bit brighter
nc = nc / 2 + 127;
p[1] = nc;
p[2] = nc;
p[3] = nc;
int gc = (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
return gc;
}
(Se davvero non si vuole utilizzare lo spazio dei dati di classe, basta sostituire l'int [] con quattro variabili int locali separati che vivono sullo stack)