25

我想将位图打印到移动蓝牙打印机 (Bixolon SPP-R200) - SDK 不提供打印内存图像的直接方法。所以我想像这样转换位图:

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

到单色位图。我正在使用画布在上面给定的位图上绘制黑色文本,效果很好。但是,当我将上述位图转换为 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”参数传递是否有意义?
  • 我想我必须评估每个像素的颜色信息并将其切换为黑色或白色(我会将此值写入一个新的目标字节数组中,最终将其传递给打印机)?
  • 如何最好地评估每个像素的颜色信息以确定它应该是黑色还是白色?(渲染的位图是白色背景上的黑色疼痛)

这种方法是否有意义?有没有更简单的方法?仅使位图黑白是不够的,主要问题是将每个像素的颜色信息减少到一位。

更新

正如 Reuben 所建议的,我将首先将位图转换为单色位图。然后我将遍历每个像素:

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

现在 Reuben 建议“读取每个 32 位像素的最低字节”——这与我关于如何评估像素颜色的问题有关。我在这方面的最后一个问题:我是否只需这样做就可以获得最低字节:

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

4 回答 4

32

您可以使用 ColorMatrix 将图像转换为单色 32bpp。

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。

于 2012-02-21T12:52:25.787 回答
12

好吧,我认为现在回复这个帖子已经很晚了,但我有时也在研究这些东西,并决定建立自己的库,将任何 jpg 或 png 图像转换为 1bpp .bmp。大多数需要 1bpp 图像的打印机都将支持此图像(在其中一个上进行了测试:))。在这里您可以找到库以及使用它制作单色单通道图像的测试项目。随意更改它..:)

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

享受..!!:)

于 2013-03-20T09:19:55.350 回答
9

您应该将每个像素转换为 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;
于 2016-07-28T11:37:30.703 回答
5

转换为与原始位图大小完全相同的单色不足以 打印。

打印机只能将每个“像素”(点)打印为单色,因为每个墨水点只有一种颜色,因此他们必须使用比足够多的点更多的点并调整它们的大小、密度……以模拟类似灰度的感觉。这种技术称为半色调。您可以看到打印机的分辨率通常至少为 600dpi,通常为 1200-4800dpi,而显示屏通常最高为 200-300ppi。

半色调

所以你的单色位图应该至少是每边原始分辨率的 3 倍。

于 2013-08-02T07:04:07.127 回答