2015-01-26 13 views
14

Io uso il seguente codice per prendere uno screenshot:C# screenshot bug?

var rc = SystemInformation.VirtualScreen; 
Bitmap bmp = new Bitmap(rc.Width, rc.Height); 
Graphics g = Graphics.FromImage(bmp); 
g.CopyFromScreen(rc.Left, rc.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy); 

Ora, questo funziona a meraviglia ed è facile da lavorare, però ho sempre incontrato po 'di puntini bianchi' in alcune delle schermate. Questo può essere molto fastidioso e distorcere l'immagine quando si verifica in grandi quantità.

sono riuscito a restringere il problema e quando cerco di prendere uno screenshot di questa immagine l'errore si è verificato:

bug-causing image

L'uscita della schermata si presenta così:

bug

Come si può risolvere questo? E per curiosità, come è spiegato?

Nel mio ambiente di test lo screenshot non è stato salvato. Io lo uso direttamente con il seguente codice:

pictureBox1.Image = bmp; 

tl; dr sto cercando di prendere screenshot e alcuni dei pixel vengono sostituiti con il bianco e falsare il risultato.

Grazie mille in anticipo.

EDIT: (! Bianco deriva dal colore di sfondo del modulo, grazie per l'avvistamento questo spender) Si scopre che il bitmap rende l'area trasparente

bug with different background

Ma ovviamente, come si può chiaramente vedere nella prima immagine; Non sto cercando di catturare alcun contenuto trasparente. Perché fa questo?

EDIT2:

Questa è tutta la classe che sto usando per selezionare il mio screenshot:

public partial class SnippingTool : Form 
{ 
    public static Image Snip() 
    { 
     var rc = SystemInformation.VirtualScreen; 

     Bitmap bmp = new Bitmap(rc.Width, rc.Height); 
     Graphics g = Graphics.FromImage(bmp); 
     g.CopyFromScreen(rc.Left, rc.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy); 

     var snipper = new SnippingTool(bmp); 

     if (snipper.ShowDialog() == DialogResult.OK) 
     { 
      return snipper.Image; 
     } 

     return null; 
    } 

    public SnippingTool(Image screenShot) 
    { 
     InitializeComponent(); 
     this.BackgroundImage = screenShot; 
     this.ShowInTaskbar = false; 
     this.FormBorderStyle = FormBorderStyle.None; 
     this.StartPosition = FormStartPosition.Manual; 

     int screenLeft = SystemInformation.VirtualScreen.Left; 
     int screenTop = SystemInformation.VirtualScreen.Top; 
     int screenWidth = SystemInformation.VirtualScreen.Width; 
     int screenHeight = SystemInformation.VirtualScreen.Height; 

     this.Size = new System.Drawing.Size(screenWidth, screenHeight); 
     this.Location = new System.Drawing.Point(screenLeft, screenTop); 


     this.DoubleBuffered = true; 
    } 

    public Image Image { get; set; } 

    private Rectangle rcSelect = new Rectangle(); 
    private Point pntStart; 

    protected override void OnMouseDown(MouseEventArgs e) 
    { 
     if (e.Button != MouseButtons.Left) return; 
     pntStart = e.Location; 
     rcSelect = new Rectangle(e.Location, new Size(0, 0)); 
     this.Invalidate(); 
    } 

    protected override void OnMouseMove(MouseEventArgs e) 
    { 
     if (e.Button != MouseButtons.Left) return; 
     int x1 = Math.Min(e.X, pntStart.X); 
     int y1 = Math.Min(e.Y, pntStart.Y); 
     int x2 = Math.Max(e.X, pntStart.X); 
     int y2 = Math.Max(e.Y, pntStart.Y); 
     rcSelect = new Rectangle(x1, y1, x2 - x1, y2 - y1); 
     this.Invalidate(); 
    } 

    protected override void OnMouseUp(MouseEventArgs e) 
    { 
     if (rcSelect.Width <= 0 || rcSelect.Height <= 0) return; 
     Image = new Bitmap(rcSelect.Width, rcSelect.Height); 
     using (Graphics gr = Graphics.FromImage(Image)) 
     { 
      gr.DrawImage(this.BackgroundImage, new Rectangle(0, 0, Image.Width, Image.Height), 
       rcSelect, GraphicsUnit.Pixel); 
     } 
     DialogResult = DialogResult.OK; 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     using (Brush br = new SolidBrush(Color.FromArgb(120, Color.Black))) 
     { 
      int x1 = rcSelect.X; int x2 = rcSelect.X + rcSelect.Width; 
      int y1 = rcSelect.Y; int y2 = rcSelect.Y + rcSelect.Height; 
      e.Graphics.FillRectangle(br, new Rectangle(0, 0, x1, this.Height)); 
      e.Graphics.FillRectangle(br, new Rectangle(x2, 0, this.Width - x2, this.Height)); 
      e.Graphics.FillRectangle(br, new Rectangle(x1, 0, x2 - x1, y1)); 
      e.Graphics.FillRectangle(br, new Rectangle(x1, y2, x2 - x1, this.Height - y2)); 
     } 
     using (Pen pen = new Pen(Color.Red, 3)) 
     { 
      e.Graphics.DrawRectangle(pen, rcSelect); 
     } 
    } 

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     if (keyData == Keys.Escape) this.DialogResult = DialogResult.Cancel; 
     return base.ProcessCmdKey(ref msg, keyData); 
    } 
} 

sulla mia forma ho poi andare:

pictureBox1.Image = SnippingTool.Snip(); 
+0

Sei risparmio come PNG? Sembra che tu sia. Prova a salvare come JPG –

+0

Come viene salvato il file? – James

+6

Questo coinvolge i lettori video? – CodesInChaos

risposta

3

Per chi si imbatte questa edizione; questa è la configurazione che ha finito per lavorando bene per me:

var rc = SystemInformation.VirtualScreen; 

using (Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppRgb)) 
{ 
    using (Graphics g = Graphics.FromImage(bmp)) 
    { 
     g.CopyFromScreen(rc.Left, rc.Top, 0, 0, bmp.Size); 
    } 
    using (var snipper = new SnippingTool(bmp)) 
    { 
     if (snipper.ShowDialog() == DialogResult.OK) 
     { 
      return snipper.Image; 
     } 
    } 
    return null; 
} 
+0

Nota il metodo di aiuto [SnippingTool.Snip()] (http://stackoverflow.com/a/3124252/17034). –

0

Il problema è che siamo stati catturare lo schermo in ARGB, e l'immagine catturata sarebbe venuto con la trasparenza.

Quindi lo salviamo come JPG e la trasparenza diventa bianca.

Per risolvere il problema, abbiamo solo bisogno di istanziare il bitmap con una PixelFormat esplicita che non include alfa:

Bitmap screenBmp = new Bitmap(width, height, PixelFormat.Format32bppRgb)