Click here to Skip to main content
15,881,559 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
So I'm working on a WinRT app in VB.NET that takes images and makes a video (.wmv) out of them.
Since this is not achievable from .NET alone, I'm using a C++ library from here: blogs.msdn.com[^]
I finally got a video file outputted but was disturbed to note a discoloring of the frames.
(See pictures)
Original Image[^]
Video Frame[^]

I believe the problem is with the library but since I'm not at all familiar with C++, I can't figure out what's going on.

Here's my .NET code:
VB
Dim VidGen As New VideoTools.VideoGenerator(640, 480, stream, 33)
Dim imgfile As StorageFile
Dim imgstream As IRandomAccessStream = Await imgfile.OpenAsync(FileAccessMode.Read)
Dim img As New WriteableBitmap(640, 480)
img.SetSource(imgstream)
ImgTest.Source = img
Try
  Dim arr As Byte() = img.ToByteArray()
  VidGen.AppendNewFrame(arr)
...

Here's the C++ code that I'm most directly calling:
C++
void VideoGenerator::AppendNewFrame(const Platform::Array<byte> ^videoFrameBuffer)
{
	auto length = videoFrameBuffer->Length / sizeof(DWORD);
	DWORD *buffer = (DWORD *)(videoFrameBuffer->Data);
	std::unique_ptr<DWORD[]> target(new DWORD[length]);

	for (UINT32 index = 0; index < length; index++)
	{
		DWORD color = buffer[index];
		BYTE b = (BYTE)((color & 0x00FF0000) >> 16);
		BYTE g = (BYTE)((color & 0x0000FF00) >> 8);
		BYTE r = (BYTE)((color & 0x000000FF));

#if ARM
		auto row = index / videoWidth;
		auto targetRow = videoHeight - row - 1;
		auto column = index - (row * videoWidth);
		target[(targetRow * videoWidth) + column] = (r << 16) + (g << 8) + b;
#else
		target[index] = (r << 16) + (g << 8) + b;
#endif
	}

	// Send frame to the sink writer.
	HRESULT hr = WriteFrame(target.get(), rtStart, rtDuration);
	if (FAILED(hr))
	{
		throw Platform::Exception::CreateException(hr);
	}
	rtStart += rtDuration;
}

Any ideas on what's causing the discoloration and how to fix it? Thanks.
Posted

I finally found an alternative to using WriteableBitmap to export to a byte array.
I started using this function to do that:
VB
Public Async Function ImageFileToByteArray(file As StorageFile) As Task(Of [Byte]())
        Dim stream As IRandomAccessStream = Await file.OpenAsync(Windows.Storage.FileAccessMode.Read)
        Dim decoder As BitmapDecoder = Await BitmapDecoder.CreateAsync(stream)
        Dim pixelData As PixelDataProvider = Await decoder.GetPixelDataAsync()
        Return pixelData.DetachPixelData()
End Function

This proved to be highly enlightening as I was able to look at the pixel format of the decoder. It told me that the file I was reading was in BGRA8 format. Armed with this knowledge, I rewrote my blue-red swapper and, voila: success!

So my final code was:
VB
Dim arr As Byte() = Await ImageFileToByteArray(imgfile)
Dim newarr(arr.Length - 1) As Byte
For i As Integer = 0 To arr.Length - 1 Step 4
   'i = B
   'i + 1 = G
   'i + 2 = R
   'i + 3 = A
   newarr(i) = arr(i + 2)
   newarr(i + 1) = arr(i + 1)
   newarr(i + 2) = arr(i)
   newarr(i + 3) = arr(i + 3)
Next
VidGen.AppendNewFrame(newarr)

Thank you, Bill for your help! You set me on the right track!
 
Share this answer
 
It appears that red and blue are swapped.

Some image formats, such as the BMP format, store 8-bit colors in BGR order.
Other formats are RGB.

Try swapping the red and blue colors.
 
Share this answer
 
Comments
Casey Sheridan 4-Nov-13 20:02pm    
I had previously held such a theory but have not yet gotten the right effect.
More background: my pictures are being made into ARGB byte arrays.

Here's what it looks like with red and blue swapped and leaving A and G in place:
https://skydrive.live.com/redir?resid=6A7E013B8B8FE514!2443&authkey=!AEJszMtaRMLYUQM&v=3
Bill_Hallahan 4-Nov-13 22:04pm    
The code you have posted has red and blue swapped already, so I should have written they need to be unswapped to be clearer! Since there's a lot of blue in the original image, with the colors swapped, there should be a considerable red tinge to the image, so if you swapped the colors correctly, there's more going on. I suspect the video doesn't use 8 bits per color component. It could be either 555 or 565 color format. For the second format, that's 6 bits for green and 5 bits for the red and blue, in either rgb or bgr order.

However, i'm just guessing.

Also, in your last message, I have no idea what you mean by A and G in place. There is no A color component.

Please post the code with the red and blue colors swapped.
Bill_Hallahan 4-Nov-13 22:05pm    
Perhaps by ARBG, you meant 32-bits, with an Alpha channel?
Casey Sheridan 4-Nov-13 22:10pm    
Yes, that's exactly what I meant.

I have, however, figured it out now. I detailed what I did in the solution I posted.
I do want to thank you, though, for pointing me in the right direction. You showed me that I wasn't really off my rocker like I thought I was :)
Bill_Hallahan 5-Nov-13 18:48pm    
Great. Of course, I had no idea what the solution was!

I'm glad me being a sounding board helped! :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900