2011-01-12 19 views
5

Estoy tratando de aplicar filtros de mezcla en dos imágenes (en este caso, HardLight). HardLight no es compatible con la biblioteca base de Android, por lo tanto, lo hago a mano en cada píxel. La primera ejecución funciona, pero la velocidad es menos que estelar. Generar una imagen de 500x500 a partir de una imagen base de 500x500 y un filtro de 500x500 lleva demasiado tiempo. Este trozo de código se usa también para generar miniaturas (72x72), y es parte integrante del núcleo de la aplicación. Me gustaría algunos consejos y/o consejos sobre cómo acelerar esto.Optimización por fusión de píxeles en mapas de bits de Android

Si se pueden obtener grandes ganancias suponiendo que ninguna de las imágenes tendrá alfa, está bien. NOTA: BlendMode y alpha son valores no utilizados en el ejemplo (BlendMode elegirá el tipo de combinación, en este caso, hardLink HardLight).

public Bitmap blendedBitmap(Bitmap source, Bitmap layer, BlendMode blendMode, float alpha) { 
    Bitmap base = source.copy(Config.ARGB_8888, true); 
    Bitmap blend = layer.copy(Config.ARGB_8888, false); 

    IntBuffer buffBase = IntBuffer.allocate(base.getWidth() * base.getHeight()); 
    base.copyPixelsToBuffer(buffBase); 
    buffBase.rewind(); 

    IntBuffer buffBlend = IntBuffer.allocate(blend.getWidth() * blend.getHeight()); 
    blend.copyPixelsToBuffer(buffBlend); 
    buffBlend.rewind(); 

    IntBuffer buffOut = IntBuffer.allocate(base.getWidth() * base.getHeight()); 
    buffOut.rewind(); 

    while (buffOut.position() < buffOut.limit()) { 
     int filterInt = buffBlend.get(); 
     int srcInt = buffBase.get(); 

     int redValueFilter = Color.red(filterInt); 
     int greenValueFilter = Color.green(filterInt); 
     int blueValueFilter = Color.blue(filterInt); 

     int redValueSrc = Color.red(srcInt); 
     int greenValueSrc = Color.green(srcInt); 
     int blueValueSrc = Color.blue(srcInt); 

     int redValueFinal = hardlight(redValueFilter, redValueSrc); 
     int greenValueFinal = hardlight(greenValueFilter, greenValueSrc); 
     int blueValueFinal = hardlight(blueValueFilter, blueValueSrc); 

     int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal); 

     buffOut.put(pixel); 
    } 

    buffOut.rewind(); 

    base.copyPixelsFromBuffer(buffOut); 
    blend.recycle(); 

    return base; 
} 

private int hardlight(int in1, int in2) { 
    float image = (float)in2; 
    float mask = (float)in1; 
    return ((int)((image < 128) ? (2 * mask * image/255):(255 - 2 * (255 - mask) * (255 - image)/255))); 

} 
+0

Hola, ¿me pueden ayudar a utilizar alfa en esta función? –

Respuesta

0

No era una pregunta como ésta hace un tiempo (Link). No estoy seguro de que el OP alguna vez haya resuelto su problema.

Lo que hice en mi caso para lograr una "mezcla de photoshop" fue aplicando una superposición translúcida de sombras a un solo color. Era simplemente una cuestión de que mi diseñador gráfico descubriera cómo hacer la superposición de sombras. Funcionó muy bien e ignoré por completo el problema de tener que iterar a través de píxeles en un mapa de bits (estaba usando getPixels() y setPixels()). La parte difícil fue realmente del lado de mis diseñadores, pero una vez que lo descubrió, ha generado una serie de imágenes excelentes.

Básicamente utilicé una máscara alfa (para generar colores dinámicos) con la superposición de sombras. Me encantaría aprender sobre una solución a través de código, ¡así que buena suerte para ti!

Editar: Además, no estoy familiarizado con BlendMode. Nunca lo usaste en tu método. ¿Qué es esto, una clase personalizada?

+0

Lamentablemente, esta solución no funcionará en mi caso. – MarkPowell

2

Las operaciones de coma flotante son generalmente más lentas que un entero, aunque no puedo decir nada sobre Android específicamente. Me pregunto por qué estás convirtiendo la entrada a hardlight en coma flotante, cuando las operaciones parecen funcionar perfectamente como números enteros.

También puede obtener una aceleración al poner la fórmula en línea en el bucle, en lugar de llamar a una función. O tal vez no, pero vale la pena intentarlo y establecer una evaluación comparativa.

+0

Probando cosas diferentes, pude obtener un aumento del 40% en el rendimiento mediante el uso de matrices en lugar de búferes (usando 'getPixels()' y 'setPixels()') y no convirtiendo los valores en flotantes en 'hardlight' . Aparte de eso, creo que el mejor rendimiento que obtendrás es llevar ese cálculo al nivel nativo, tal vez implementar un Xfermode personalizado. –

+0

hmm, cambiando a getPixels()/setPixels() Vi un doble en el tiempo de cálculo, a menos que esté entendiendo mal lo que está diciendo? – MarkPowell

+0

@MarkPowell, creo que @Kevin estaba argumentando a favor de arreglos en int, y argumentando * contra * getPixels/setPixels. Tendrás que dirigir tu comentario a él comenzando con @Kevin si tienes más preguntas. –

1

Además, si se puede sacrificar 3 bits/píxel de final de la calidad de imagen/de precisión, - podemos ganar ganancia de alrededor de un 25% en función de hardlight(), volviendo a escribir con los operadores bit a bit:

int hardlight(int image, int mask) { 
    return (((image < 128) ? 
      ((((mask << 1) * image) >> 8)): 
      (255^((((255^mask) << 1) * (255^image)) >> 8)))); 
} 
+0

Gracias, viendo una mejora general de la velocidad del 10% con esto. Sin embargo, vamos a tener que ver si el sacrificio de 3 bits/píxel es factible. – MarkPowell

+0

Ok. Es una pena que la ganancia de rendimiento sea solo del 10% en lugar del 25% como en mi máquina de Windows.Sospecho que los operadores bit a bit de Android están menos optimizados que los compiladores de la plataforma Windows/MS VS C/C++. O tal vez el cuello de botella de rendimiento principal no está en la función hardlight sino en otro lugar. –

Cuestiones relacionadas