Android: преобразование растрового изображения в монохромное растровое изображение (1 бит на пиксель) - PullRequest
21 голосов
/ 21 февраля 2012

Я хочу напечатать растровое изображение на мобильном Bluetooth-принтере (Bixolon SPP-R200) ​​- SDK не предлагает прямых методов для печати изображения в памяти. Поэтому я подумал о преобразовании растрового изображения следующим образом:

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

К монохромному растровому изображению. Я рисую черный текст на приведенном выше растровом изображении, используя холст, который хорошо работает. Однако, когда я преобразую вышеупомянутый Bitmap в ByteArray, принтер, кажется, не в состоянии обрабатывать эти байты. Я подозреваю, что мне нужен массив с одним битом на пиксель (пиксель будет либо белым = 1, либо черным = 0).

Поскольку кажется, что из коробки не было удобного способа сделать это, я использовал одну идею:

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

Получить пиксели. Я полагаю, мне придется использовать его следующим образом:

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

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

Однако - я не уверен в нескольких вещах:

  • В getPixels - имеет ли смысл просто передавать ширину в качестве аргумента "Stride"?
  • Полагаю, мне нужно было бы оценить информацию о цвете каждого пикселя и переключить ее на черный или белый (и я бы записал это значение в новый массив целевых байтов, который я в конечном итоге передал бы в принтер)?
  • Как наилучшим образом оценить информацию о цвете каждого пикселя, чтобы определить, должен ли он быть черным или белым? (Рендеринг растрового изображения - черная боль на белом фоне)

Имеет ли этот подход смысл? Есть ли более простой способ? Недостаточно просто сделать растровое изображение черно-белым, основная проблема заключается в уменьшении информации о цвете для каждого пикселя в один бит.

UPDATE

По предложению Рувима я сначала преобразую растровое изображение в монохромное растровое изображение. и затем я буду перебирать каждый пиксель:

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

Теперь Рувим предложил «прочитать младший байт каждого 32-битного пикселя» - это будет связано с моим вопросом о том, как оценивать цвет пикселя. Мой последний вопрос в этом отношении: получаю ли я младший байт, просто выполнив следующее:

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

Ответы [ 4 ]

26 голосов
/ 21 февраля 2012

Вы можете конвертировать изображение в монохромный 32bpp, используя 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);

Это упрощает преобразование цвета-> монохромный.Теперь вы можете просто выполнить getPixels () и прочитать младший байт каждого 32-битного пикселя.Если это <128, это 0, в противном случае это 1. </p>

10 голосов
/ 20 марта 2013

Ну, я думаю, что уже слишком поздно, чтобы отвечать на эту тему, но я также иногда работал над этим материалом и решил создать свою собственную библиотеку, которая будет конвертировать любое изображение jpg или png в 1bpp .bmp.Большинство принтеров, которым требуются изображения размером 1 bpp, будут поддерживать это изображение (протестировано на одном из них :)).Здесь вы можете найти библиотеку, а также тестовый проект, который использует ее для создания монохромного одноканального изображения.Не стесняйтесь изменить его ..:)

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

Наслаждайтесь .. !!:)

5 голосов
/ 28 июля 2016

Вы должны преобразовать каждый пиксель в пространство HSV и использовать значение, чтобы определить, должен ли пиксель на целевом изображении быть черным или белым:

  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 голосов
/ 02 августа 2013

Преобразование в монохромное изображение с точно таким же размером, что и исходное растровое изображение, недостаточно для печати. ​​

Принтеры могут печатать только каждый «пиксель» (точку) как монохромный, потому что каждое пятно чернил имеет только 1 цвет, поэтому они должны использовать гораздо больше точек, чем достаточно, и регулировать их размер, плотность ... для эмуляции, подобной оттенкам серого. Чувствовать. Эта техника называется полутон . Вы можете видеть, что принтеры часто имеют разрешение не менее 600 точек на дюйм, обычно 1200-4800 точек на дюйм, в то время как экран дисплея часто достигает 200-300 точек на дюйм.

Halftone

Таким образом, ваше монохромное растровое изображение должно быть как минимум в 3 раза оригинальным разрешением с каждой стороны.

...