2010-07-17 9 views
5

Estoy tratando de eliminar todos los píxeles blancos o transparentes de una imagen, dejando la imagen real (recortada). He intentado algunas soluciones, pero ninguna parece funcionar. ¿Alguna sugerencia o voy a pasar la noche escribiendo código de recorte de imagen?C# - Crop Transparente/Espacio en blanco

+0

Así que hay otras personas que sueñan continuamente escribiendo la misma línea de código una y otra vez? Pensé que era el único :-) –

+1

ayudaría a la comunidad si detalla al menos uno de sus enfoques y explicó cómo no funcionó. –

Respuesta

3
public Bitmap CropBitmap(Bitmap original) 
{ 
    // determine new left 
    int newLeft = -1; 
    for (int x = 0; x < original.Width; x++) 
    { 
     for (int y = 0; y < original.Height; y++) 
     { 
      Color color = original.GetPixel(x, y); 
      if ((color.R != 255) || (color.G != 255) || (color.B != 255) || 
       (color.A != 0)) 
      { 
       // this pixel is either not white or not fully transparent 
       newLeft = x; 
       break; 
      } 
     } 
     if (newLeft != -1) 
     { 
      break; 
     } 

     // repeat logic for new right, top and bottom 

    } 

    Bitmap ret = new Bitmap(newRight - newLeft, newTop - newBottom); 
    using (Graphics g = Graphics.FromImage(ret) 
    { 
     // copy from the original onto the new, using the new coordinates as 
     // source coordinates for the original 
     g.DrawImage(...); 
    } 

    return ret 
} 

Tenga en cuenta que esta función será lenta como suciedad. GetPixel() es increíblemente lento, y el acceso a las propiedades Width y Height de Bitmap dentro de un bucle también es lento. LockBits sería la forma correcta de hacerlo; hay muchos ejemplos aquí en StackOverflow.

+1

Gracias, eso me consiguió a mitad de camino allí. El único problema es que también quiero cambiar el tamaño de la imagen si es más grande que un tamaño específico. Hay más códigos de los que caben en el cuadro de comentarios, pero la imagen original solo ocupa aproximadamente la mitad de la imagen final. El código está en http://pastebin.com/He3S8aCH – Echilon

+0

Transpuse dos variables: P. Problema solucionado, espere una publicación en el blog pronto (se enlazará aquí). – Echilon

+0

Creo que lo arruiné también. Los bits que dicen 'color.R! = 0' etc. en realidad deberían decir' color.R! = 255', ya que un píxel blanco tendrá valores R, G y B de 255 para cada uno (un RGB de 0,0, 0 es negro). Si la versión original funcionó para usted, probablemente solo recortó los píxeles transparentes (y negros). – MusiGenesis

2

La comprobación por píxel debería hacer el truco. Escanee cada línea para encontrar una línea vacía desde la parte superior & inferior, escanee cada fila para encontrar las restricciones de la derecha & (esto se puede hacer en una pasada con filas o columnas). Cuando se encuentra la restricción, copie la parte de la imagen en otro buffer.

9

Por lo tanto, lo que desea hacer es encontrar el píxel superior no más blanco/transparente y el píxel inferior no blanco/transparente más a la izquierda. Estas dos coordenadas le darán un rectángulo que luego puede extraer.

// Load the bitmap 
    Bitmap originalBitmap = Bitmap.FromFile("d:\\temp\\test.bmp") as Bitmap; 

    // Find the min/max non-white/transparent pixels 
    Point min = new Point(int.MaxValue, int.MaxValue); 
    Point max = new Point(int.MinValue, int.MinValue); 

    for (int x = 0; x < originalBitmap.Width; ++x) 
    { 
    for (int y = 0; y < originalBitmap.Height; ++y) 
    { 
     Color pixelColor = originalBitmap.GetPixel(x, y); 
     if (!(pixelColor.R == 255 && pixelColor.G == 255 && pixelColor.B == 255) 
     || pixelColor.A < 255) 
     { 
     if (x < min.X) min.X = x; 
     if (y < min.Y) min.Y = y; 

     if (x > max.X) max.X = x; 
     if (y > max.Y) max.Y = y; 
     } 
    } 
    } 

    // Create a new bitmap from the crop rectangle 
    Rectangle cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X, max.Y - min.Y); 
    Bitmap newBitmap = new Bitmap(cropRectangle.Width, cropRectangle.Height); 
    using (Graphics g = Graphics.FromImage(newBitmap)) 
    { 
    g.DrawImage(originalBitmap, 0, 0, cropRectangle, GraphicsUnit.Pixel); 
    } 
+0

¡Gran solución! Eliminé '|| pixelColor.A <255' para que funcione. – krlzlx

0

Encontré un método para procesar por lotes unos pocos miles de archivos .jpg en unos 10 minutos, pero no lo hice en el código. Usé la función Convertir del Editor Snag-It. No sé si esta es una opción para usted, si necesita hacer este recorte una vez o si su necesidad está en curso, pero por el precio del software, que no es mucho, lo consideré una solución decente. (no trabaja o representa Techsmith.)

Joey

Cuestiones relacionadas