Transparency when using WriteableBitmap and ClipBoard


  • I have an app which involves two features: Saving an image to a file, and Copying an image to the Clipboard. Since the same image will get used for both features, I have created a function that returns a WriteableBitmap. When I save the file, everything is great, and the saved file maintains the transparency. However, when I copy it to the Clipboard, transparency is lost when I paste it into another program (I have been testing using Paint). The WriteableBitmaps for both features are created using the same function (which has no parameters), so I know the problem is not in creating the WriteableBitmap. Why is the Clipboard losing the transparency, and how can I fix it? Thanks.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Friday, September 26, 2014 10:24 PM


All replies

  • How are you putting the bitmap on the clipboard? How are you saving it to file?

    I don't think Paint supports pasting in transparently: compare with painting a known transparent image copied from Word.

    It's been a while, but if I recall correctly CF_BITMAP doesn't support transparency, so putting a bitmap directly on the clipboard will lose its transparency. You can convert the bitmap to a file format which supports transparency (such as png) and put that on the clipboard and some applications will display it with transparency.



    Friday, September 26, 2014 10:55 PM
  • I think you might be right about the Paint pasting, but it didn't maintain the pasting when I tried pasting into other programs like Photoshop either. Since the converting to a file vs putting directly on the Clipboard is basically the only difference between the save and copy code, I guess I should see how your idea of putting it on the Clipboard in a file format works. But I am not exactly sure what I need to change in my code to do that. My current copy code is the following:
    Private Async Sub btnCopy_Click(sender As Object, e As RoutedEventArgs) Handles btnCopy.Click
    	Dim dp As New DataPackage()
    	dp.RequestedOperation = DataPackageOperation.Move
    	dp.SetBitmap(Await Me.GetBitmapStream(Me.CreateWriteableBitmap()))
    End Sub

    And my code for saving the bitmap as a file (which I am guessing the code at the end is the significant part here) is:
    Private Async Sub Save()
    	'Create the WriteableBitmap
    	Dim bmp As WriteableBitmap = Me.CreateWriteableBitmap()
    	'Create and modify a Byte array for the pixels
    	Dim pixelstream As Stream = bmp.PixelBuffer.AsStream()
    	Dim pixels(CInt(pixelstream.Length)) As Byte
    	Await pixelstream.ReadAsync(pixels, 0, pixels.Length)
    	Dim r, b As Byte
    	For row As Integer = 0 To bmp.PixelHeight - 1
    		For col As Integer = 0 To bmp.PixelWidth - 1
    			b = pixels(row * bmp.PixelWidth * 4 + col * 4)
    			r = pixels(row * bmp.PixelWidth * 4 + col * 4 + 2)
    			pixels(row * bmp.PixelWidth * 4 + col * 4) = r
    			pixels(row * bmp.PixelWidth * 4 + col * 4 + 2) = b
    	'Save the WriteableBitmap using the appropriate encoder
    	Dim picker As New FileSavePicker()
    	picker.DefaultFileExtension = ".png"
    	picker.FileTypeChoices.Add("BMP", {".bmp"})
    	picker.FileTypeChoices.Add("GIF", {".gif"})
    	picker.FileTypeChoices.Add("JPEG", {".jpeg"})
    	picker.FileTypeChoices.Add("JPG", {".jpg"})
    	picker.FileTypeChoices.Add("PNG", {".png"})
    	picker.FileTypeChoices.Add("TIF", {".tif"})
    	picker.FileTypeChoices.Add("TIFF", {".tiff"})
    	picker.SuggestedFileName = String.Format("CurvesGoneWild_{0}_{1}_{2}.png", Me.sldOuter.Value, Me.sldInner.Value, Me.sldFromInner.Value)
    	picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary
    	Dim tempfile As StorageFile = Await picker.PickSaveFileAsync()
    	If tempfile Is Nothing Then : Exit Sub
    		Dim encoderid As Guid = BitmapEncoder.PngEncoderId
    		If tempfile.Name.EndsWith(".bmp") Then : encoderid = BitmapEncoder.BmpEncoderId
    		ElseIf tempfile.Name.EndsWith(".jpg") OrElse tempfile.Name.EndsWith(".jpeg") Then : encoderid = BitmapEncoder.JpegEncoderId
    		ElseIf tempfile.Name.EndsWith(".gif") Then : encoderid = BitmapEncoder.GifEncoderId
    		ElseIf tempfile.Name.EndsWith(".tif") OrElse tempfile.Name.EndsWith(".tiff") Then : encoderid = BitmapEncoder.TiffEncoderId
    		Else : encoderid = BitmapEncoder.PngEncoderId
    		End If
    		Using s As IRandomAccessStream = Await tempfile.OpenAsync(FileAccessMode.ReadWrite)
    			Dim encoder As BitmapEncoder = Await BitmapEncoder.CreateAsync(encoderid, s)
    			encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied, CUInt(bmp.PixelWidth), CUInt(bmp.PixelHeight), 96, 96, pixels)
    			Await encoder.FlushAsync()
    			Await s.GetOutputStreamAt(0).FlushAsync()
    		End Using
    	End If
    End Sub
    NOTE: CreateWriteableBitmap and GetBitmapStream are functions I wrote and are declared as follows:
    Private Function CreateWriteableBitmap() As WriteableBitmap
    Private Async Function GetBitmapStream(bitmap As WriteableBitmap) As Task(Of RandomAccessStreamReference)
    How do I modify the copy code to use a file format? Thanks.

    Nathan Sokalski njsokalski@hotmail.com http://www.nathansokalski.com/

    Saturday, September 27, 2014 12:50 AM
  • Instead of adding calling SetBitmap to add the bitmap to the clipboard, call SetStorageItems with a StorageItem containing the encoded file. This is demonstrated in the Clipboard app sample 


    Friday, October 03, 2014 12:13 AM