web-dev-qa-db-fra.com

Android: Conversion d'un bitmap en un bitmap monochrome (1 bit par pixel)

Je veux imprimer un Bitmap à une imprimante Bluetooth mobile (Bixolon SPP-R200) ​​- le SDK ne propose pas de méthodes direkt pour imprimer une image en mémoire. Donc, je pensais à la conversion d'un bitmap comme celui-ci:

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

Pour un monochrome Bitmap. Je dessine du texte noir sur ci-dessus étant donné Bitmap à l'aide d'une toile, qui fonctionne bien. Cependant, quand je convertir le bitmap ci-dessus à un ByteArray, l'imprimante semble être incapable de gérer ces octets. Je pense que je besoin d'un tableau avec un bit par pixel (un pixel serait soit blanc = 1 ou noir = 0).

Comme il ne semble pas pratique, de la route de la boîte pour le faire, une idée que j'avais été d'utiliser:

bitmap.getPixels(pixels, offset, stride, x, y, width, height)

pour obtenir les pixels. Je suppose que, je dois l'utiliser comme suit:

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

int [] pixels = new int [width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

Cependant - je ne suis pas sûr quelques petites choses:

  • En getPixels - est-il logique de passer simplement la largeur que l'argument " Stride "?
  • Je suppose que je dois évaluer les informations de couleur de chaque pixel et de passer soit à noir ou blanc (Et j'écrire cette valeur dans un nouveau tableau d'octets cible que je finalement passer à l'imprimante)?
  • Comment mieux évaluer chaque information de couleur de pixel afin de décider qu'il devrait être noir ou blanc? (Le Bitmap est rendu douleur noir sur un fond blanc)

Est-ce que cette approche de sens du tout? Y at-il un moyen plus facile? Il ne suffit pas de simplement faire le noir et blanc bitmap, la question principale est de réduire les informations de couleur pour chaque pixel dans un bit.

MISE À JOUR

Comme suggéré par Reuben Je vais d'abord convertir le bitmap à un Bitmap monochrome. puis j'itérer sur chaque pixel:

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

    int[] pixels = new int[width * height];
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

    // Iterate over height
    for (int y = 0; y < height; y++) {
        int offset = y * height;
        // Iterate over width
        for (int x = 0; x < width; x++) {
            int pixel = bitmap.getPixel(x, y);
        }
    }

Maintenant, Reuben a suggéré de " lire l'octet le plus bas de chaque pixel de 32 bits " - qui se rapportent à ma question sur la façon d'évaluer la couleur du pixel. Ma dernière question à cet égard: Dois-je obtenir l'octet le plus bas en faisant simplement ceci:

// Using the pixel from bitmap.getPixel(x,y)
int lowestByte = pixel & 0xff;
22
AgentKnopf

Vous pouvez convertir l'image en monochrome 32BPP à l'aide d'une colormertrix.

Bitmap bmpMonochrome = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmpMonochrome);
ColorMatrix ma = new ColorMatrix();
ma.setSaturation(0);
Paint paint = new Paint();
Paint.setColorFilter(new ColorMatrixColorFilter(ma));
canvas.drawBitmap(bmpSrc, 0, 0, Paint);

Qui simplifie la conversion de couleur-> monochrome. Maintenant, vous pouvez simplement faire des getpixels () et lire l'octet le plus bas de chaque pixel de 32 bits. Si c'est <128 c'est un 0, sinon c'est un 1.

28
Reuben Scratton

Eh bien, je pense que c'est assez tard maintenant de répondre à ce fil, mais je travaillais aussi sur ce genre de choses que de reculer et j'ai décidé de construire ma propre bibliothèque qui convertira n'importe quelle image JPG ou PNG à 1BPP .BMP. La plupart des imprimantes nécessitant des images de 1BPP prendront en charge cette image (testées sur l'une de ces :)). Ici, vous pouvez trouver une bibliothèque ainsi qu'un projet de test qui l'utilise pour créer une image monochrome à canal unique. N'hésitez pas à le changer .. :)

https://github.com/acdevs/1bpp-monochrome-android

Prendre plaisir..!! :)

11
chetan

Conversion en monochrome avec exactement la même taille que le bitmap d'origine est pas assez à imprimer.

Les imprimantes ne peuvent imprimer que chaque "pixel" (point) comme monochrome, car chaque spot d'encre n'a que 1 couleur, ils doivent donc utiliser beaucoup plus de points que suffisamment et ajuster leur taille, leur densité ... pour émuler la sensation de type grisalcale. Cette technique s'appelle Halftoning . Vous pouvez voir que les imprimantes ont souvent une résolution au moins 600 dpi, normalement 1200-4800DPI, tandis que l'écran d'affichage est souvent en tête à 200-300PPI.

Halftone

Donc, votre bitmap monochrome devrait être au moins 3 fois la résolution d'origine de chaque côté.

5
phuclv

Vous devez convertir chaque pixel en espace HSV et utiliser la valeur pour déterminer si le pixel sur l'image cible doit être noir ou blanc:

  Bitmap bwBitmap = Bitmap.createBitmap( bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565 );
  float[] hsv = new float[ 3 ];
  for( int col = 0; col < bitmap.getWidth(); col++ ) {
    for( int row = 0; row < bitmap.getHeight(); row++ ) {
      Color.colorToHSV( bitmap.getPixel( col, row ), hsv );
      if( hsv[ 2 ] > 0.5f ) {
        bwBitmap.setPixel( col, row, 0xffffffff );
      } else {
        bwBitmap.setPixel( col, row, 0xff000000 );
      }
    }
  }
  return bwBitmap;
5
Moritz