2013-05-01 4 views
0

Je souhaite envoyer une télécopie à partir de mon application. Un document de télécopie a une résolution de 1728 x 2444 pixels. Donc je crée un bitmap, ajouter du texte et/ou des images et encodez à CCITT (Huffman):OutOfMemoryError lors de la création d'une image bitmap

Bitmap image = Bitmap.createBitmap(1728, 2444, Config.ALPHA_8); 
Canvas canvas = new Canvas(image); 
canvas.drawText("This is a fax", 100, 100, new Paint()); 
ByteBuffer buffer = ByteBuffer.allocateDirect(image.getWidth() * image.getHeight()); 
image.copyPixelsToBuffer(buffer); 
image.recycle(); 
encodeCCITT(buffer, width, height); 

Cela fonctionne parfaitement sur mon Galaxy SII (64 MB taille du tas), mais pas à l'émulateur (24 MB). Après avoir créé la deuxième page de fax, j'obtiens "une allocation externe de 4223232 octets trop grande pour ce processus ... java.lang.OutOfMemoryError" lors de l'allocation du tampon. J'ai déjà réduit la profondeur de couleur de ARGB_8888 (4 octets par pixel) à ALPHA_8 (1 octet), car les pages de fax sont de toute façon monochromes. J'ai besoin de cette résolution et j'ai besoin d'avoir accès aux pixels pour l'encodage.

Quel est le meilleur moyen?

Répondre

0

Android ne prend pas en charge les bitmaps 1-Bpp et la limite de taille de segment Java de 24/32/48MB fait partie d'Android. Les périphériques réels ne peuvent pas allouer plus que la limite de tas Java, quelle que soit la quantité de RAM qu'ils possèdent. Il semble y avoir seulement deux solutions possibles:

1) Travailler dans les limites du tas Java.

2) Utiliser le code natif (NDK).

En code natif, vous pouvez allouer la totalité de la RAM disponible sur le périphérique. Le seul inconvénient est que vous devrez écrire votre propre code pour éditer et encoder votre bitmap.

0

En plus de la réponse déjà bonne de BitBank, vous devez annuler la référence si vous voulez que le Garbage collector nettoie les références de votre Bitmap. The documentation pour que les états de la méthode:

Ceci est un appel avancé, et ne doit normalement pas être appelé, puisque le processus de GC normale libérera cette mémoire quand il n'y a plus références à ce bitmap.

+0

Je l'ai résolu en réutilisant l'objet Bitmap. L'utilisation de recycle() ou la définition de null ne fonctionnait pas. – almisoft

0

au lieu de copier tous pixels à un ByteBuffer, vous pouvez copier étape par étape. Ici avec un tableau int []. Donc, vous avez besoin de moins de mémoire:

int countLines = 100; 
int[] pixels = new int[width * countLines]; 
for (int y = 0; y < heigth; y += countLines) { 
    image.getPixels(line, 0, width, 0, y, width, countLines); 
    // do something with pixels... 
    image.setPixels(line, 0, width, 0, y, width, countLines); 
} 
Questions connexes