Android:ビットマップをモノクロビットマップに変換する(ピクセルあたり1ビット)
-
28-10-2019 - |
質問
ビットマップをモバイルBluetoothプリンター(Bixolon SPP-R200)に印刷したい-SDKは、インメモリ画像を印刷するDiRektメソッドを提供していません。だから私はこのようなビットマップを変換することを考えました:
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
モノクロビットマップに。キャンバスを使用して、上記のビットマップで黒いテキストを描画しています。これはうまく機能します。ただし、上記のビットマップをbytearrayに変換すると、プリンターはそれらのバイトを処理できないようです。ピクセルごとに1ビットのアレイが必要だと思います(ピクセルは白= 1またはブラック= 0のいずれかです)。
便利ではないように思われるので、それを行うための箱のない方法で、私が持っていたアイデアの1つは使用することでした。
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-「ストライド」の引数として幅を単純に渡すことは理にかなっていますか?
- 各ピクセルの色情報を評価し、それを黒または白に切り替える必要があると思います(そして、最終的にプリンターに渡す新しいターゲットバイト配列にこの値を書きます)?
- 各ピクセルの色情報を最適に評価して、黒または白であるべきだと判断するにはどうすればよいですか? (レンダリングされたビットマップは、白い背景の黒い痛みです)
このアプローチはまったく理にかなっていますか?簡単な方法はありますか?ビットマップを白黒にするだけでは不十分です。主な問題は、各ピクセルの色情報を1ビットに減らすことです。
アップデート
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);
}
}
現在、ルーベンは「各32ビットピクセルの最低バイトを読む」ことを提案しました。これは、ピクセルの色を評価する方法についての私の質問に関連しています。この点での私の最後の質問:これを行うだけで最低のバイトを取得しますか:
// Using the pixel from bitmap.getPixel(x,y)
int lowestByte = pixel & 0xff;
解決
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です。
他のヒント
さて、このスレッドに返信するのはかなり遅れていると思いますが、時々このようなものに取り組んでいて、JPGまたはPNG画像を1BPP .BMPに変換する独自のライブラリを構築することにしました。 1BPP画像を必要とするほとんどのプリンターは、この画像をサポートします(それらのいずれかでテストされています:))。ここでは、ライブラリと、それを使用してモノクロシングルチャネル画像を作成するテストプロジェクトを見つけることができます。気軽に変更してください.. :)
https://github.com/acdevs/1bpp-monochrome-android
楽しみ..!! :)
元のビットマップとまったく同じサイズのモノクロに変換する 十分でない 印刷する。
プリンターは各「ピクセル」(DOT)をモノクロとしてのみ印刷できます。インクの各スポットには1色しかないため、グレースケールのような感触をエミュレートするために、十分なドットを使用してサイズ、密度を調整する必要があります。この手法は呼ばれます ハーフトン. 。多くの場合、プリンターには少なくとも600dpi、通常は1200-4800dpiの解像度があり、ディスプレイ画面は200-300PPIでトップになることがよくあります。
したがって、あなたのモノクロビットマップはそうあるべきです 少なくとも3回 両側の元の解像度。
各ピクセルを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;