Imagen de umbral Blanco-Blanco en tiempo real de Android

Tengo un código que convierte un mapa de bits que tiene los colores grises en un mapa de bits de colores en blanco y negro, utilizando este código:

// scan through all pixels for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { // get pixel color pixel = bitmap.getPixel(x, y); A = Color.alpha(pixel); R = Color.red(pixel); G = Color.green(pixel); B = Color.blue(pixel); int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B); // use 128 as threshold, above -> white, below -> black if (gray > 128) gray = 255; else gray = 0; // set new pixel color to output bitmap bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray)); } } 

Como puedes ver, viajo todos los puntos de píxeles del mapa de bits original y luego comparo los componentes del color con un umbral dado, en este caso 128, y luego si su anterior digo su blanco de lo contrario será un píxel negro.

Lo que quiero hacer ahora, es un Spinner que puede cambiar ese valor umbral, y luego la imagen BW será diferente.

Para hacer esto, tendría que dibujar toda la imagen de nuevo, y eso es muy cpu que cuesta el tiempo, su toma el tiempo para viajar todos los pixeles otra vez.

¿Hay alguna manera de cambiar la imagen usando un umbral de BW diferente en tiempo real?

Alguien me dijo que usar un GIF, y luego lo que yo haría, sólo estaba cambiando los valores de la tabla de búsqueda del GIF, ¿alguien tiene conocimiento sobre esto en Android?

Te recomiendo que mires usando la biblioteca OpenCV para Android. Una vez que lo tiene instalado puede utilizarlo para el umbral rápido entre muchas otras operaciones de uso común en las imágenes. El fragmento de código siguiente convertirá su bitamp de color en una imagen gris y umbral en el nivel de gris 128.

 // first convert bitmap into OpenCV mat object Mat imageMat = new Mat (bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8U, new Scalar(4)); Bitmap myBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); Utils.bitmapToMat(myBitmap, imageMat); // now convert to gray Mat grayMat = new Mat ( bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8U, new Scalar(1)); Imgproc.cvtColor(imageMat, grayMat, Imgproc.COLOR_RGB2GRAY, 1); // get the thresholded image Mat thresholdMat = new Mat ( bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8U, new Scalar(1)); Imgproc.threshold(grayMat, thresholdMat , 128, 255, Imgproc.THRESH_BINARY); // convert back to bitmap for displaying Bitmap resultBitmap = Bitmap.createBitmap(bitmap.cols(), bitmap.rows(), Bitmap.Config.ARGB_8888); thresholdMat.convertTo(thresholdMat, CvType.CV_8UC1); Utils.matToBitmap(thresholdMat, resultBitmap); 

Pasó un poco de tiempo desde que se hizo esta pregunta, pero me topé con esto buscando algo más y pasó a tener la solución. Puede lograr esto sin OpenCV o cualquier otra biblioteca de terceros, utilizando sólo ColorMatrixColorFilter disponible desde el nivel 1 de la API.

Aquí están las matrices que usted puede utilizar:

 //matrix that changes picture into gray scale public static ColorMatrix createGreyMatrix() { ColorMatrix matrix = new ColorMatrix(new float[] { 0.2989f, 0.5870f, 0.1140f, 0, 0, 0.2989f, 0.5870f, 0.1140f, 0, 0, 0.2989f, 0.5870f, 0.1140f, 0, 0, 0, 0, 0, 1, 0 }); return matrix; } // matrix that changes gray scale picture into black and white at given threshold. // It works this way: // The matrix after multiplying returns negative values for colors darker than threshold // and values bigger than 255 for the ones higher. // Because the final result is always trimed to bounds (0..255) it will result in bitmap made of black and white pixels only public static ColorMatrix createThresholdMatrix(int threshold) { ColorMatrix matrix = new ColorMatrix(new float[] { 85.f, 85.f, 85.f, 0.f, -255.f * threshold, 85.f, 85.f, 85.f, 0.f, -255.f * threshold, 85.f, 85.f, 85.f, 0.f, -255.f * threshold, 0f, 0f, 0f, 1f, 0f }); return matrix; } 

Y aquí es cómo usarlos:

 BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; //load source bitmap and prepare destination bitmap Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.thePicture, options); Bitmap result = Bitmap.createBitmap(pic.getWidth(), pic.getHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(result); //first convert bitmap to grey scale: bitmapPaint.setColorFilter(new ColorMatrixColorFilter(createGreyMatrix())); c.drawBitmap(pic, 0, 0, bitmapPaint); //then convert the resulting bitmap to black and white using threshold matrix bitmapPaint.setColorFilter(new ColorMatrixColorFilter(createThresholdMatrix(128))); c.drawBitmap(result, 0, 0, bitmapPaint); //voilà! You can now draw the result bitmap anywhere You want: bitmapPaint.setColorFilter(null); otherCanvas.drawBitmap(result, null, new Rect(x, y, x + size, y + size), bitmapPaint); 

Espero que esto ayude a alguien.

GIFs tienen una paleta de colores en la cabecera que asocia, para cada "valor", que color pertenece a ella ( entrada de Wikipedia ). La captura: en el día que pensaban que 256 colores sería suficiente, y que es tantas entradas de paleta que hay. Podrías usar la clase GifDecoder.java con una tabla de color local de 256 entradas y dos valores: tus dos salidas 0 y 255. Pero al final del día, hay un bucle que comprueba cada byte , qué valor asociar a través de la paleta ( Esta es la línea ). No es un poco más rápido que su código.

Una alternativa para hacer esto más rápido podría ser el uso de OpenGL para producir su umbral (dado que de todos modos usted va a dibujar el mapa de bits en la pantalla, ¿verdad?). Esto necesita un montón de código extra, afortunadamente este tutorial hace exactamente lo que quieres hacer, menos la parte de umbral.

Para el umbral, un programa OpenGL necesita ser compilado (en GlRenderer::onSurfaceChanged ) y utilizado cada vez (en GlRenderer::onDrawFrame ). El programa obtiene dos sombreadores que el umbral de cada píxel a la velocidad de la luz! (OK, tal vez un poco más lento, pero muy rápido!).

Los shaders serían como los siguientes. Déjeme saber si puedo ayudarle con conectarlos en el código de ejemplo.

 private static final String mVertexShader = "attribute vec4 aPosition;\n" + "attribute vec4 aTextureCoord;\n" + "varying vec2 vTextureCoord;\n" + "void main() {\n" + " gl_Position = aPosition;\n" + " vTextureCoord = aTextureCoord;\n" + "}\n"; private static final String mFragmentShader = "precision mediump float;\n" + "varying vec2 vTextureCoord;\n" + "uniform float threshold_in_range_0_to_1;\n" + "const vec4 coeff_y = vec4(0.256, 0.504, 0.097, 0.0625);\n" + "float y;\n" + "void main() {\n" + " y = dot(coeff_y, texture2D(sTexture, vTextureCoord));\n" + " if ( y > threshold_in_range_0_to_1)" + " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0)\n" + " else" + " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0)\n" + "}\n"; 
  • ¿Cómo posiciono mi mapa de bits en el lienzo usando una matriz?
  • Convertir la matriz de bytes de 4 bits en escala de grises a Bitmap Android
  • Widget de la aplicación Android con renderizado personalizado
  • Android obtiene la posición del mapa de bits en ImageView
  • Android cómo dibujar un mapa de bits sobre lienzo semi transparente
  • Dibujar texto en la parte superior de mapa de bits no
  • Android: BitmapDrawable.Draw (lienzo) no parece funcionar
  • Compartir Bitmap a través de Android Intent
  • Impresión POS / ESC Apex3 image SOS
  • Cargar imagen de contacto en mapa de bits
  • Android - Excepción de memoria
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.