插入视频帧时修改了图片颜色 [英] Picture coloring modified when inserting into video frame

查看:94
本文介绍了插入视频帧时修改了图片颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在使用VB.NET中的WinRT应用程序来获取图像并制作视频(.wmv)。

由于单靠.NET无法实现,我从这里使用的是一个C ++库:blogs.msdn.com [ ^ ]

我终于输出了一个视频文件,但是注意到帧的变色是不安的。

(见图片)

原始图片 [ ^ ]

视频帧 [ ^ ]



我相信问题出在库中,但由于我对C ++一点都不熟悉,我无法弄清楚发生了什么。



这是我的.NET代码:

  Dim  VidGen 作为  VideoTools.VideoGenerator( 640  480 ,stream, 33 
Dim imgfile 作为 StorageFile
Dim imgstream As IRandomAccessStream = Await imgfile.OpenAsync(FileAccessMode.Read)
暗淡 img 作为 WriteableBitmap( 640 480
img.SetSource(imgstream)
ImgTest.Source = img
尝试
Dim arr As Byte ()= img.ToByteArray()
VidGen.AppendNewFrame(arr)
...



这是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)((颜色& 0x00FF0000)>> 16 );
BYTE g =(BYTE)((颜色& 0x0000FF00)>> 8 );
BYTE r =(BYTE)((颜色& 0x000000FF));

#if 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
}

// < span class =code-comment>将帧发送到接收器编写器。
HRESULT hr = WriteFrame(target.get(),rtStart,rtDuration);
if (FAILED(hr))
{
throw 平台::异常:: CreateException(小时);
}
rtStart + = rtDuration;
}



关于什么导致变色以及如何解决它的任何想法?谢谢。

解决方案

我终于找到了使用WriteableBitmap导出到字节数组的替代方法。

我开始使用这个函数来做到这一点:

 公共 异步 函数 ImageFileToByteArray(文件作为 StorageFile)作为任务(< span class =code-keyword>  [ Byte ]())
Dim stream As IRandomAccessStream = Await file.OpenAsync(Windows.Storage.FileAccessMode.Read)
Dim decoder As BitmapDecoder = 等待 BitmapDecoder.CreateAsync(stream)
Dim pixelData As PixelDataProvider = Await decoder.GetPixelDataAsync()
返回 pixelData.DetachPixelData()
结束 功能



这被证明是非常有启发性的,因为我能够看到解码器的像素格式。它告诉我,我正在阅读的文件是BGRA8格式。有了这些知识,我改写了我的蓝红色交换器,瞧:成功!



所以我的最终代码是:

  Dim  arr 作为 字节()=  Await  ImageFileToByteArray(imgfile)
Dim newarr(arr.Length - < span class =code-digit> 1 )作为 字节
< span class =code-keyword>对于 i 作为 整数 = 0 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
下一步
VidGen。 AppendNewFrame(newarr)



谢谢你,比尔的帮忙!你让我走在正确的轨道上!


看来红色和蓝色交换。



一些图像格式,如BMP格式,以BGR顺序存储8位颜色。

其他格式为RGB。



尝试交换红色和蓝色。

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:

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:

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.

解决方案

I finally found an alternative to using WriteableBitmap to export to a byte array.
I started using this function to do that:

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:

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!


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.


这篇关于插入视频帧时修改了图片颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆