Swaroop
Swaroop

Reputation: 1289

How to convert a jpg to yuv in C?

Even though a question of this nature sounds very similar, I am having problems in converting a jpg image to yuv in C (without using opencv).

This is what I have understood as of now, how to solve this problem :

  1. Identify the structure of file formats for jpg and yuv. i.e what each byte in the file actually contains. This is what I think jpg format looks like.

  2. With the above structure I tried to read a jpg file and tried to decipher its 18th and 19th bytes. I did type cast them to both char and int but I don`t get any meaningful values for width and height of the image.

  3. Once I have read these values, I should be able to convert them from jpg to yuv. I was looking at this resource.

  4. Appropriately, construct yuv image and write it to a (.yuv) file.

Kindly help me by pointing me to appropriate resources. I will keep updating my progress on this post. Thanks in advance.

Upvotes: 1

Views: 7144

Answers (3)

mousomer
mousomer

Reputation: 2848

Usually the image is already stored in YUV (or, to be more precise: YCbCr). When reading the file, the jpeg reader usually converts YUV to RGB. Converting back will reduce quality somewhat.

In libTurboJpeg (http://libjpeg-turbo.virtualgl.org/) you can read the jpeg without color conversion. Check https://github.com/libjpeg-turbo/libjpeg-turbo/blob/master/turbojpeg.h - it has the tjDecompressToYUV function which gives you the 3 colorspaces on 3 different output buffers.

Upvotes: 4

Mark Setchell
Mark Setchell

Reputation: 207465

Not sure what you have against opencv, maybe ImageMagick is acceptable to you? It is installed on most Linux distors and is available for OSX, and Windows. It has C bindings, and also a command-line version that I am showing here. So you can create an image like this:

# Create test image
convert -size 100x100                          \
   \( xc:red xc:lime xc:blue +append \)        \
   \( xc:cyan xc:magenta xc:yellow +append \)  \
  -append image.jpg

enter image description here

Now convert to YUV and write to 3 separate files:

convert image.jpg -colorspace yuv -separate bands.jpg

bands-0.jpg (Y)

enter image description here

bands-1.jpg (U)

enter image description here

bands-2.jpg(V)

enter image description here

Or, closer to what you ask, write all three bands YUV into a binary file:

convert image.jpg -colorspace yuv rgb:yuv.bin

Upvotes: 3

B. Nadolson
B. Nadolson

Reputation: 3058

Based on https://en.wikipedia.org/wiki/YUV#Y.27UV444_to_RGB888_conversion

yuv conversion

Decoding a JPEG, well in pure C without libraries ... the following code is somewhat straightforward ...

https://bitbucket.org/Halicery/firerainbow-progressive-jpeg-decoder/src

Assuming you have the jpeg decoded to rgb using the above or a library (using a library is likely easier).

int width = (width of the image);
int height = (height of the image);
byte *mydata = (pointer to rgb pixels);
byte *cursor;
size_t byte_count = (length of the pixels .... i.e. width x height x 3);
int n;
for (cursor = mydata, n = 0; n < byte_count; cursor += 3, n += 3) 
{
    int red = cursor[0], green = cursor[1], blue = cursor[2];
    int y = 0.299 * red + 0.587 * green + 0.114 * blue;
    int u = -0.147 * red + -0.289 * green + 0.436 * blue;
    int v = 0.615 * red + -0.515 * green + -0.100 * blue;

    cursor[0] = y, cursor[1] = u, cursor[2] = v;
}

// At this point, the entire image has been converted to yuv ...

And write that to file ...

FILE* fout = fopen ("myfile.yuv, "wb");

if (fout) {
    fwrite (mydata, 1, byte_count, fout);
    fclose (fout);
}

Upvotes: 2

Related Questions