2012-05-28 23 views
4

代碼:將帶有alpha通道的圖像複製到具有自定義背景色的剪貼板?

private void Foo(Canvas canvas) 
{ 
    // The content is a bit larger... 
    Size size = new Size(canvas.ActualWidth * 1.1, canvas.ActualHeight * 1.2); 

    // Create a render bitmap and push the surface to it 
    RenderTargetBitmap renderBitmap = 
     new RenderTargetBitmap(
     (int)size.Width, 
     (int)size.Height, 
     96d, 
     96d, 
     PixelFormats.Pbgra32 
    ); 
    renderBitmap.Render(canvas); 

    // Then copy to clipboard 
    Clipboard.SetImage(renderBitmap); 
} 

我需要什麼:

渲染透明背景圖像的畫布上,然後將其複製到剪貼板(退出簡單不是真的?)

問題:

粘貼時,我得到一個黑色背影的醜陋圖像地面

解決方案1:

canvas.Background = new SolidColorBrush(Colors.White); 

號這厚不工作的canvas背景將不會在未來renderBitmap.Render(canvas);

變化相反,我必須使用一個計時器,給WPF有時候需要改變背景,然後把它渲染到那個定時器的tick事件中。它的作品,但不幸的是,canvas的內容大於它的大小......所以白色背景只能覆蓋它的一部分,仍然是醜陋的結果。 (順便說一句,誰知道爲什麼需要一段時間來改變背景?我認爲它應該立即改變)

我做錯了什麼?如何在剪貼板中獲得白色背景的透明圖像?

更重要的是,我注意到一些PNG圖像的背景保持白色,如果你將它粘貼到不支持alpha通道的mspaint.exe中,但其他一些成爲黑色。

有沒有像alternative color這樣的東西,如果粘貼圖片的地方不支持alpha通道,它會用作背景嗎?我們可以定製它嗎?

現在我渲染另一個BitmapSource有白色的內容,如果有一種方法將其與renderBitmap爲背景,問題的解決結合起來,但我不知道怎麼...

int dWidth = (int)size.Width; 
int dHeight = (int)size.Height; 
int dStride = dWidth * 4; 
byte[] pixels = new byte[dHeight * dStride]; 
for (int i = 0; i < pixels.Length; i++) 
{ 
    pixels[i] = 0xFF; 
} 
BitmapSource bg = BitmapSource.Create(
    dWidth, 
    dHeight, 
    96, 
    96, 
    PixelFormats.Pbgra32, 
    null, 
    pixels, 
    dStride 
); 
// Combine bg with renderBitmap 
+0

它似乎在刪除Alpha通道而不是所有通道後保存位圖。剪貼板上的圖像是MS BMP嗎? –

+1

@ColeJohnson我不知道。由於我搜索的結果,似乎MS剪貼板圖像不支持透明通道。我試圖找到一種方法爲這個圖像添加一個白色背景,然後將其設置爲剪貼板 – Byzod

+0

您可以隨時base64對其進行編碼,base64在另一端進行解碼。但是這可能會破壞兼容性。對於具有圖像的應用程序,我不知道他們是如何做到的:'(' –

回答

2

這是我最後的解決方案,希望這將幫助其他有同樣問題

// Create a render bitmap and push the surface to it 
RenderTargetBitmap renderBitmap = 
    new RenderTargetBitmap(
    (int)size.Width, 
    (int)size.Height, 
    96d, 
    96d, 
    PixelFormats.Pbgra32 
); 
renderBitmap.Render(surface); 

// Create a white background render bitmap 
int dWidth = (int)size.Width; 
int dHeight = (int)size.Height; 
int dStride = dWidth * 4; 
byte[] pixels = new byte[dHeight * dStride]; 
for (int i = 0; i < pixels.Length; i++) 
{ 
    pixels[i] = 0xFF; 
} 
BitmapSource bg = BitmapSource.Create(
    dWidth, 
    dHeight, 
    96, 
    96, 
    PixelFormats.Pbgra32, 
    null, 
    pixels, 
    dStride 
); 

// Adding those two render bitmap to the same drawing visual 
DrawingVisual dv = new DrawingVisual(); 
DrawingContext dc = dv.RenderOpen(); 
dc.DrawImage(bg, new Rect(size)); 
dc.DrawImage(renderBitmap, new Rect(size)); 
dc.Close(); 

// Render the result 
RenderTargetBitmap resultBitmap = 
    new RenderTargetBitmap(
    (int)size.Width, 
    (int)size.Height, 
    96d, 
    96d, 
    PixelFormats.Pbgra32 
); 
resultBitmap.Render(dv); 

// Copy it to clipboard 
try 
{ 
    Clipboard.SetImage(resultBitmap); 
} catch { ... } 
0

我找到了一個更小,更好的閱讀解決方案,我發現它在https://social.msdn.microsoft.com/Forums/vstudio/en-US/a6972b7f-5ccb-422d-b203-134ef9f10084/how-to-capture-entire-usercontrol-image-to-clipboard?forum=wpf

// Create a render bitmap and push the surface to it 
RenderTargetBitmap renderBitmap = 
    new RenderTargetBitmap(
    (int)size.Width, 
    (int)size.Height, 
    96d, 
    96d, 
    PixelFormats.Pbgra32 
); 

// Render a white background into buffer for clipboard to avoid black background on some elements 
Rectangle vRect = new Rectangle() 
{ 
    Width = (int)size.Width, 
    Height = (int)size.Height, 
    Fill = Brushes.White, 
}; 
vRect.Arrange(new Rect(size)); 
renderBitmap.Render(vRect); 

// renderBitmap is now white, so render your object on it 
renderBitmap.Render(surface); 

// Copy it to clipboard 
try 
{ 
    Clipboard.SetImage(resultBitmap); 
} catch { ... } 
相關問題