Read Y U V planes from YUV file

Magick++ is an object-oriented C++ interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning Magick++.
Post Reply
francholi
Posts: 3
Joined: 2011-07-15T10:06:05-07:00
Authentication code: 8675308

Read Y U V planes from YUV file

Post by francholi » 2011-07-15T10:35:08-07:00

Hi, I'm new to Magick++ and I'm struggling a bit to get this to work.

I would like to read a raw UYVY 422 8bits (planar or interlaced) image
and get the Y U and V planes without any scaling from the original image.

Is there any way to access the real data that came from the file, before
any scaling or conversion to other color spaces is done (8 bit luma and chroma samples) ?

I've got something working with the following:
...
Image img;
img.colorSpace(MagickCore::YCbCrColorspace);
img.size("1920x1080");
img.depth(8);
img.magick("UYVY");
img.read(filename);

Magick::Color c = img.pixelColor(0,0);
cerr << c1.redQuantum() << " " << c1.greenQuantum() << " " << c1.blueQuantum() << endl;
...

redQuantum() is giving me (Y/255 * 65535)
greenQuantum() is giving me (U/255 * 65535)
but blueQuantum() doesn't match the same scaling scheme, and I can't find out how to get V.

I tried with ColorYUV as well, but the y(), v() and u() functions are already scaled and shifted values,
and I would like to access the unsigned 8 bit integer values coming from the file.

Any help would be appreciated,
Thanks!

User avatar
anthony
Posts: 8874
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Read Y U V planes from YUV file

Post by anthony » 2011-07-18T22:20:14-07:00

That is because in memory all images are stored using the compile time 'Quantum Range' or Q bit depth. Q16 in this case.

see IM examples, Quality vs Depth
http://www.imagemagick.org/Usage/basics/#quality
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
http://www.imagemagick.org/Usage/

francholi
Posts: 3
Joined: 2011-07-15T10:06:05-07:00
Authentication code: 8675308

Re: Read Y U V planes from YUV file

Post by francholi » 2011-07-21T02:10:36-07:00

Thanks for you reply Anthony,

then in the following code, what is exactly the meaning of "img.depth(8)" ?
...
Image img;
img.colorSpace(MagickCore::YCbCrColorspace);
img.size("1920x1080");
img.depth(8);
img.magick("UYVY");
img.read(filename);
...

Ok, this works in the command line, same Q16 build:
convert -depth 8 -size 1920x1080 -sampling-factor 4:2:2 -interlace plane -colorspace YUV file.yuv out.png

How can you reproduce the same command line in Magick++ ?


==============================================================

Coming back to my problem, if there is no solution to the previous problem,
now I am trying to feed an image with a blob with the data (again 8 bits YUV 422 planar data),
but the read method (or the constructor) keeps failing (throwing different exceptions depending
on the magick I use).

Let's assume that you have in a Blob, a 1920x1080 8 bits YUV frame, in 422 planar, which size is 4147200 bytes,
and you want to create a PNG version ?

I have tried:

Blob b((void*)data_ptr, size_bytes);
Image out(b,Geometry(w,h),8,"YUV"); // and "YUV:4:2:2" and with and without 8

someone asked this very same question in other thread, but no replies so far for a while...

Thanks,

User avatar
anthony
Posts: 8874
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Read Y U V planes from YUV file

Post by anthony » 2011-07-21T16:08:53-07:00

francholi wrote:Thanks for you reply Anthony,

then in the following code, what is exactly the meaning of "img.depth(8)" ?
...
Image img;
img.colorSpace(MagickCore::YCbCrColorspace);
img.size("1920x1080");
img.depth(8);
img.magick("UYVY");
img.read(filename);
...

Ok, this works in the command line, same Q16 build:
convert -depth 8 -size 1920x1080 -sampling-factor 4:2:2 -interlace plane -colorspace YUV file.yuv out.png
In that case the depth 8 is the depth for reading the raw data format. In other words that values are in bytes.
If it was depth 16, then you also have the option of specifying the 'enden' of the values (LSB or MBS, for least/most significate byte order).
How can you reproduce the same command line in Magick++ ?
You probably could do better than I could for that. I can read C++ code but have never needed to program in it :-)
I'm a little old fashioned. I like shell, C, Perl, and very occasionally PHP. I've never had a real use for C++, Ruby, Java, etc.

Code: Select all

Coming back to my problem, if there is no solution to the previous problem, 
now I am trying to feed an image with a blob with the data (again 8 bits YUV 422 planar data),
but the read method (or the constructor) keeps failing (throwing different exceptions depending
on the magick I use).
That does not suprise me. There was a bug report about the 'raw' data readers (the ones that specify the permutation of channel order) that was fixed a few years back. I don't remember the details though.

Others may be able to help you more than I can for this.

You could always look at the coder!
Very Old Programmers Motto wrote:Use the source Luke!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
http://www.imagemagick.org/Usage/

francholi
Posts: 3
Joined: 2011-07-15T10:06:05-07:00
Authentication code: 8675308

Re: Read Y U V planes from YUV file

Post by francholi » 2011-07-22T07:33:04-07:00

Thanks again for your reply,

I think I found some issues that I managed to solve with the conversion.

As you said, I went down the road to the yuv.c:98 ReadYUVImage() function, and the
thing is that it's doing 4:1:1 by default (at least with the bit of code
that I was using) and crashing my app because the blob is saying it's way
bigger (4:2:2).

So, if you don't specify anything, it's 4:1:1 unless I am missing something here.

The following code worked for me:

Code: Select all

Blob b(tempImage, size_bytes);  // blob with 8 bits data (full yuv planar image)
Image img;
img.size("1920x1080");
img.depth(8);
img.magick("YUV");
img.colorSpace(MagickCore::YUVColorspace);
MagickCore::ImageInfo *imInf = img.imageInfo();
char* s = new char[6];
strcpy(s,"4:2:2\0");
imInf->sampling_factor = s;
imInf->interlace = MagickCore::PlaneInterlace;
img.read(b);
img.magick("PNG");
img.write(filename);
imInf->sampling_factor will get "deleted" inside IM, so don't provide a "const char*" there.)

If you don't change the sampling factor and the interlace it will not work.
Is this a bug ?

Anyway, thanks for your time!

Post Reply