Search code examples
imagemagickimagemagick-convert

Convert YUY2 (YUYV) to png from the command line


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


Solution

  • 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