Android: conversion D'une Bitmap en Bitmap Monochrome (1 Bit par Pixel))

je veux imprimer un Bitmap sur une imprimante Bluetooth mobile (Bixolon SPP-R200) - le SDK n'offre pas de méthodes direkt pour imprimer une image en mémoire. J'ai donc pensé à convertir une Bitmap comme celle-ci:

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

à un Bitmap Monochrome. Je dessine du texte noir sur un Bitmap donné ci-dessus à l'aide d'une toile, ce qui fonctionne bien. Cependant, lorsque je convertis le Bitmap ci-dessus en ByteArray, l'imprimante semble incapable de gérer ces octets. Je pense que j'ai besoin d'un tableau avec un Bit par Pixel (a Pixel serait soit blanc = 1 ou noir = 0).

comme il semble qu'il n'y ait pas de solution pratique, une des idées que j'ai eu était d'utiliser:

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

pour Obtenir les pixels. Je suppose que je devrais 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 de savoir quelques petites choses:

  • dans getPixels - est-ce logique de simplement passer la largeur comme argument "Stride"?
  • je suppose que je devrais évaluer la couleur information de chaque pixel et soit le commuter en noir ou blanc (et j'écrirais cette valeur dans un nouveau tableau cible byte que je passerais finalement à l'imprimante)?
  • comment évaluer au mieux chaque information de couleur de pixel afin de décider qu'elle doit être en noir ou blanc? (Le Bitmap rendu est la douleur noire sur un fond blanc)

cette approche du sens à tout? Est-il un moyen plus facile? Il ne suffit pas de faire le bitmap noir et blanc, le principal problème est de réduire l'information de couleur pour chaque pixel dans un peu.

UPDATE

comme suggéré par Reuben je vais d'abord convertir le Bitmap en Bitmap monochrome. et puis je vais le répéter 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 le plus petit octet de chaque pixel 32 bits" - ce qui se rapporterait à ma question sur la façon d'évaluer la couleur du pixel. Ma dernière question à cet égard: est-ce que j'obtiens le plus bas byte en faisant simplement ceci:

// Using the pixel from bitmap.getPixel(x,y)
int lowestByte = pixel & 0xff;
19
demandé sur AgentKnopf 2012-02-21 16:38:08

4 réponses

Vous pouvez convertir l'image en monochrome 32bpp en utilisant un ColorMatrix.

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

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

21
répondu Reuben Scratton 2012-02-21 12:52:25

Eh bien je pense qu'il est assez tard maintenant pour répondre à ce fil, mais je travaillais aussi sur ce genre de choses parfois en arrière et j'ai décidé de construire ma propre bibliothèque qui convertira n'importe quelle image jpg ou png en 1bpp .bmp. La plupart des imprimantes qui nécessitent des images 1bpp supportent cette image (Testée sur l'une d'entre elles :)). Ici vous pouvez trouver la bibliothèque aussi bien qu'un projet de test qui l'utilise pour faire une image monochrome de canal simple. N'hésitez pas à changer il..:)

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

Profiter..!! :)

10
répondu chetan 2013-03-20 09:19:55

conversion en monochrome avec la même taille exacte que le bitmap original est pas assez d' imprimer.

les imprimantes ne peuvent imprimer chaque "pixel" (point) qu'en monochrome parce que chaque tache d'encre n'a qu'une seule couleur, de sorte qu'elles doivent utiliser beaucoup plus de points qu'il n'en faut et ajuster leur taille, leur densité... pour imiter la sensation en grayscale. Cette technique s'appelle demi-teintes. Vous pouvez voir que les imprimantes ont souvent une résolution d'au moins 600 dpi, normalement 1200-4800 dpi, alors que l'écran d'affichage souvent au sommet de 200-300ppi.

Halftone

votre bitmap monochrome doit donc être au moins 3 fois la résolution originale de chaque côté.

5
répondu phuclv 2013-08-02 07:04:07

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;
4
répondu Moritz 2016-07-28 11:37:30