I'm using v4l2-ctl(1)
to capture an image from my webcam and I'm trying to convert(1)
the raw format into a png.
Here are the commands I ran.
# This is the format my camera outputs.
$ v4l2-ctl --device /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[1]: 'YUYV' (YUYV 4:2:2)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
# This is how I'm capturing an image.
$ v4l2-ctl --device /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=YUYV
$ v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=frame.raw --stream-count=1
# This is how I tried to convert. (This didn't work.)
$ convert -size 640x480 -depth 8 -sampling-factor 4:2:2 -colorspace YUV yuv:frame.raw frame.png
This gives me a green and pink png.
I also tried to display the raw image with this command.
$ display -size 640x480 -depth 8 -sampling-factor 4:2:2 -colorspace yuv yuv:frame.raw
The image looks a little better there, but there is a blue filter over the entire image.
Here is a sample image from my webcam. http://s000.tinyupload.com/?file_id=36420855739943963603
I think I have the solution, but a correctly coloured reference image would help. The simplest seems to be to use ffmpeg
to convert raw YUYV with sampling factor 4:2:2 to a PNG as follows:
ffmpeg -f rawvideo -s 640x480 -pix_fmt yuyv422 -i frame.raw result.png
If you want to do it with ImageMagick, you need to use its uyvy
pixel format, but your bytes are swapped, so you need to swap them to the order ImageMagick expects before feeding them in - I use dd
and its conv=swab
option here:
dd if=frame.raw conv=swab | convert -sampling-factor 4:2:2 -size 640x480 -depth 8 uyvy:- result.png
If you need to swap and reorder bytes in some other, more complicated way, you can do it with xxd
and awk
fairly simply:
xxd -c2 frame.raw | awk '{print $1,substr($2,3,2),substr($2,1,2)}' | xxd -c2 -r - | convert -sampling-factor 4:2:2 -size 640x480 -depth 8 uyvy:- result.png
Keywords: ImageMagick, image processing, command line, sub-sampled, 4:2:2, YUYV, YUY2, YUV