data - Método de Javascript para detectar el área de un PNG que no es transparente
javascript save canvas content (1)
Qué necesitas hacer:
- Obtener el buffer
- Obtenga una referencia de 32 bits de ese búfer (si sus otros píxeles son transparentes, puede usar un búfer Uint32Array para iterar).
- Escanear 0 - ancho para encontrar el borde x1
- Ancho de escaneo: 0 para encontrar el borde x2
- Escanear 0 - altura para encontrar el borde y1
- Altura de escaneo - 0 para encontrar el borde y2
Estos escaneos se pueden combinar, pero por simplicidad mostraré cada paso por separado.
Demostración en línea de esto se puede encontrar aquí.
Resultado:
Cuando se carga la imagen, inclúyala (si la imagen es pequeña, el resto de este ejemplo sería un desperdicio, ya que sabría las coordenadas al dibujarlo, asumiendo que la imagen que dibuje es grande con una pequeña imagen dentro)
(nota: esta es una versión no optimizada por simplicidad)
ctx.drawImage(this, 0, 0, w, h);
var idata = ctx.getImageData(0, 0, w, h), // get image data for canvas
buffer = idata.data, // get buffer (unnes. step)
buffer32 = new Uint32Array(buffer.buffer), // get a 32-bit representation
x, y, // iterators
x1 = w, y1 = h, x2 = 0, y2 = 0; // min/max values
Luego escanea cada borde. Para el borde izquierdo, escanea de 0 a ancho para cada línea (no optimizada):
// get left edge
for(y = 0; y < h; y++) { // line by line
for(x = 0; x < w; x++) { // 0 to width
if (buffer32[x + y * w] > 0) { // non-transparent pixel?
if (x < x1) x1 = x; // if less than current min update
}
}
}
Para el borde derecho solo invierte x iterador:
// get right edge
for(y = 0; y < h; y++) { // line by line
for(x = w; x >= 0; x--) { // from width to 0
if (buffer32[x + y * w] > 0) {
if (x > x2) x2 = x;
}
}
}
Y lo mismo es para los bordes superiores e inferiores solo que los iteradores están invertidos:
// get top edge
for(x = 0; x < w; x++) {
for(y = 0; y < h; y++) {
if (buffer32[x + y * w] > 0) {
if (y < y1) y1 = y;
}
}
}
// get bottom edge
for(x = 0; x < w; x++) {
for(y = h; y >= 0; y--) {
if (buffer32[x + y * w] > 0) {
if (y > y2) y2 = y;
}
}
}
La región resultante es entonces:
ctx.strokeRect(x1, y1, x2-x1, y2-y1);
Hay varias optimizaciones que podría implementar pero dependen completamente del escenario, como si conoce la ubicación aproximada, entonces no tiene que iterar todas las líneas / columnas.
Podría hacer una estimación de la fuerza bruta de la ubicación omitiendo x número de píxeles y cuando encuentre un píxel no transparente podría hacer un área de búsqueda máxima en función de eso, etc., pero eso está fuera del alcance aquí.
¡Espero que esto ayude!
Estoy buscando un método de JavaScript para detectar una imagen dentro de un archivo PNG transparente. Por ejemplo, crearé un PNG con un lienzo transparente de 940x680, luego colocaré un objeto de opacidad completo en algún lugar dentro de ese lienzo.
Quiero ser capaz de detectar el tamaño (h / w) y la ubicación superior izquierda de ese objeto que no es transparente dentro del lienzo
Aquí hay un ejemplo de la imagen original Aquí hay un ejemplo de lo que me gustaría lograr. (Superposición de cuadro delimitador, con datos superiores + margen izquierdo)
He encontrado un recurso que detecta un poco la transparencia, pero no estoy seguro de cómo escalar algo así a lo que estoy buscando.
var imgData,
width = 200,
height = 200;
$(''#mask'').bind(''mousemove'', function(ev){
if(!imgData){ initCanvas(); }
var imgPos = $(this).offset(),
mousePos = {x : ev.pageX - imgPos.left, y : ev.pageY - imgPos.top},
pixelPos = 4*(mousePos.x + height*mousePos.y),
alpha = imgData.data[pixelPos+3];
$(''#opacity'').text(''Opacity = '' + ((100*alpha/255) << 0) + ''%'');
});
function initCanvas(){
var canvas = $(''<canvas width="''+width+''" height="''+height+''" />'')[0],
ctx = canvas.getContext(''2d'');
ctx.drawImage($(''#mask'')[0], 0, 0);
imgData = ctx.getImageData(0, 0, width, height);
}