Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

How can I resize a 352x288 frame into a 800x600 one?

Detlev_Petersen
Beginner
2,711 Views

Dear members,

at the moment I am bounded to the IPP 7.0.2. I decode a 352x288 MPEG2 video. With GetFrame() of the IPP I get a decoded 352x288 frame in UYVY format.

Then I use a ippiCbYCr422ToYcbCr422_8u_C2R call to do a conversion from UYVY to YUY2.

The next call is a resize call ippiResizeYUV422_8u_C2R.

At last a conversion from YUY2 to UYVY with ippiYCbCr422ToCbYCr422_8u_C2R.

This works as far as the boundaries of the 352x288 frame is used as source and destination. If I try to use the resize call to scale my 352x288 to a 800x600 frame it does not work.

I guess I have to put my decoded 352x288 frame without scaling into a 800x600 one so that the decoded frame is the upper left corner of the 800x600 frame. After this I can use my resize call above to scale my little frame to the full size of a 800x600 one.

But how can I put my 352x288 frame into a 800x600 one?

Best regards

Detlev

 

 

 

0 Kudos
24 Replies
Chao_Y_Intel
Moderator
2,243 Views

Hi Detlev,

Could you provided some details on the error you get when calling the ippiResizeYUV422_8u_C2R function? One simple test code may help to root the problem.

Regards,
Chao

0 Kudos
Sergey_K_Intel
Employee
2,243 Views

Detlev Petersen wrote:

But how can I put my 352x288 frame into a 800x600 one?

Hi Detlev,

Since UYVY is 16 bits-per-pixel format you can use ippiCopy_16u_C1R. I.e. <in pseudo-code>

   pDst=ippiMalloc_16u_C1(800, 600, &dstStep);
   ippiCopy_8u_C1R( pSrc, srcStep, pDst, dstStep, { 352, 288} );

Regards,
Sergey 

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Dear all,

please find attached my test video as ZIP archive. It is a 352x288 video, but you have to note which it is marked in a wrong way as interlaced one. I took regard to this fact, so that the decoder works with a non-interlaced one.

I have to clean-up my code to provide you a sample code cause I did various tests and experiments with different call parameters just to see what works and what does not work.

I try to implement the hint of Sergey. From my point of view this can help to solve my problem. Nevertheless I have to verify it at first.

In addition to that I try to upload one screenshot so that you see the result if the IPP resize function is set up to resize the small 352x288 frame to a bigger 800x600. As I written it before the resize works as long as source and destination frame are of the same size.

By the way I try to copy each line of the 352x288 frame to the beginning of a 800x600 frame. This didn't work but I do not know why. My idea was that I just have to copy 352x2 bytes for one line into one 800x2 line for the bigger frame. The result was a something like a green 352x288 image in the upper left corner of an black 800x600.

Best regards

Detlev

 

 

 

0 Kudos
Detlev_Petersen
Beginner
2,242 Views

Dear all,

please find attached one screenshot. This is the result if I use the resize call to scale the 352x288 source frame to a 800x600 target frame. As far as I use 352x288 the resize works and the frame looks like a frame out of my test video.

Sample code and further test results will follow.

Best regards

Detlev

0 Kudos
SergeyKostrov
Valued Contributor II
2,242 Views
>>...please find attached one screenshot. This is the result if I use the resize call to scale the 352x288 source frame to >>a 800x600 target frame... Could you attach a simple test-case? I saw on your screensot how the problem looks like and this is due to wrong image formats you've selected.
0 Kudos
SergeyKostrov
Valued Contributor II
2,243 Views
>>pDst = ippiMalloc_16u_C1(800, 600, &dstStep); >>ippiCopy_8u_C1R( pSrc, srcStep, pDst, dstStep, { 352, 288} ); I'm not sure that it will work since pDst is declared as Ipp8u *pDst: ... IPPAPI ( IppStatus, ippiCopy_8u_C1R, ( const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep,IppiSize roiSize )) ... and I think ippiConvert_8u16u_C1R has to be used instead.
0 Kudos
Sergey_K_Intel
Employee
2,243 Views

Yes, you right. Of course, ippiCopy_16u should be used, this is a typo. We must not convert it from 8u to 16u, Otherwise, we get image with black dots between real pixels. In this case ippiCopy_16u is just a simple way to place smaller array into bugger one without any conversion.

Regarding Detlev's snapshot, this is exactly how frame looks when wrong width and/or height is select during playback.

I will try to check this ippiYCbCr422ToCbYCr422_8u_C2R function in small test.

Regards,
Sergey 

0 Kudos
Sergey_K_Intel
Employee
2,242 Views

Hi Detlev,

I have attached test file, Isn't it what you want?

Regards,
Sergey 

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Hi Sergey,

I tested your first tip yesterday. The result was not as good as I expected. Please see my attached screen shot.

I did some further tests to see what does work or not. My problem is that I change a little bit and that the result turns to a bad one.

Now I have some further screenshots so that I can show you what runs with my software. Here I have to write a new comment so that you can get these screenshots.

At the moment I clean-up my software so that I can provide my InitScaling() method to you. After GetFrame() there follows converting and scaling stuff before the frame is copied to the screen with Blt().

I will try to do something with your last sample after the mentioned task above.

In addition to that I try to copy the 352x288 frame into a 800x600 one. I used a loop over the heigth of the little frame and copied 352*2 byte into the row of each row of the 800x600 frame. As result I get a 800x600 frame with a 352x288 rectangle in the upper left corner but the video frames cannot be identified anymore. I expected that the next row follows the previous one in the frame buffer. I didn't see a swap of bytes. Nevertheless my copy routine doesn't work.

Best regards

Detlev

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Hi Chao, Sergey and Sergey,

please find attached my InitScaling() method and some screenshots.

My resize works with factors 0.5, 2.0 and 1.0 as long as the source frame is left unchanged as 352x288 one.

I managed it only to use the last re-conversion back to UYVY to put the 352x288 frame into a 800x600 one.

It seems to be that the resize call needs a 800x600 frame as input so that I can get my wished 800x600 frame with the scaled small frame as result.

First trials to put the 352x288 frame into a 800x600 without scaling failed.

Now I can try to do something with the sample from Sergey.

I hope my sample will be helpful for you. Maybe you can see the root cause of my problem just faster than myself.

Best regards

Detlev

 

0 Kudos
SergeyKostrov
Valued Contributor II
2,243 Views
Hi everybody, >>...I have attached test file, Isn't it what you want? >> >>Attached: test.c It is a good example but it has two extra dependencies on Intel IPL ( Image Processing Library / predecessor of IPP ) and OpenCV ( Computer Vision ) libraries.
0 Kudos
Sergey_K_Intel
Employee
2,243 Views

Sergey Kostrov wrote:

It is a good example but it has two extra dependencies on Intel IPL ( Image Processing Library / predecessor of IPP ) and OpenCV ( Computer Vision ) libraries.

This (OpenCV render) is for visual check only. It can be commented away.

Regards,
Sergey 

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Hi all,

in Sergey sample I cannot see other values than the ones which I use. Ok, I have a video frame as input and Serge uses an RGB bitmap. The resize call is the same.

Now I have added another screenshot. As you see there is something destroyed from the genuine video frame in the upper left corner as 352x288 rectangle. I tried to use ippiCbYCr422ToYCbCr422_8u_C2R() to put the 352x288 video frame from GetFrame() in a bigger 800x600 one including the necessary color conversion for the following resize call.

I do not see any fault in my resolution values 352x288 and 800x600. From my point of view the step values with 352x2 and 800x2 bytes per row seems to be alright. The pitch values are 704 and 1600. Something goes wrong but I cannot see what. I seems to be that bigger rows are copied into a too small rectangle.

Best regards

Detlev

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Dear all,

if I use ippiCbYCr422ToYCbCr422_8u_C2R() with sizeDst instead of the source size as in my last test sample I get an exception. This means that this color conversion can work with the source size 352x288 only. With 800x600 as destination size were will be a memory exception cause of the source frame and its smaller size. This conversion function seems to iterate over 600 rows for an input frame of 288 rows.

This explains two things. At first that the frame of my last sample must be look like something which is destroyed. On the second the conversion call above cannot be used to put the 352x288 frame into a bigger 800x600 one.

In my experience the used resize call seems to have the same problem.

Only the last re-conversion back to UYVY can port a 352x288 frame to a 800x600, but this comes too late for me.

Now I can find two or three points for a solution:

1) It is possible to use the resize call in the wished or planned way

2) I copy the 352x288 frame into a 800x600 before the resize call by an extra function or by an iteration on my own. Both trials failed in the past.

3) I do some more conversion stuff to get the input frame for the resize call bigger. On the other hand it seems to be much overhead to reach this aim for the expected performance load of the player.

Best regards

Detlev

// converting UYVY to YUY2
    // accessing pDecodeBuffer
    // using new in buffer for YUY2
    stateUYVYtoYUY2=ippiCbYCr422ToYCbCr422_8u_C2R(
     // active if unscaled one have to be shown
     // (const Ipp8u*)pDecodeBuffer,
     // active if scaled one have to be shown
     (const Ipp8u*)p_frame_YUY2_in,
     m_videostreaminfo.clip_info.width*2,
     (Ipp8u*)p_frame_YUY2_4conv,
     sizeDst.width*2, // converts an make input frame bigger
     sizeDst
     );

 

0 Kudos
Sergey_K_Intel
Employee
2,243 Views

Hi Detlev,

1) Your CbYCr -> YCbCr conversion is not quite correct. You need to do this in small frame. So, 352x288 -> 352x288
2) Resize (in YCbCr colors) from small frame to large frame
3) Convert YCbCr -> CbYCr in large frame. 

Regards,
Sergey
P.S. I updated the sample to have your conversions as test core. Note: I used RGBs only as temporary pictures to generate source image and to check destination image, so you can skip this RGB stuff. Note 2: in my updated test case I got result picture with somehow twisted colors. It can be another problem in the future after you win resizing.

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Hi Sergey,

I checked the call parameters just in the way how they were used by yourself in your sample.

I didn't manage it to get the wished result.

Then I did some further tests. After decoding one frame my software creates and overwrites the complete decoded frame. I used a pattern of rows in a sequence where the odd and even ones have different colors.

Now I see, that Blt() as Windows call interprets 352x288 and 800x600 input frames as 352x288 frames for output. The green margin on the right site and on the bottom are generated by Blt() but are not out of the framebuffer 800x600, which were processed by the IPP calls.

I haven't found the root cause for this until yet. There must be a hidden command for my eyes which sets 352x288 as window output. My target window is set to 800x600 and the maximum size for the DirectDraw interface is 1280x720.

I think, I have to solve this DirectDraw problem at first before I can go on with the IPP's resize call. I guess all will work much better then and I will see on the screen what I want to see.

Best regards
Detlev

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Hi Sergey,

do you know an IPP function to convert my YUY2 and UYVY frame into a RGB one. 8bit per color R, G and B would be nice cause it is easier then to save it under Windows as bitmap without an extra header and color table.

Then I can verify that the IPP functions are okay and I can set my focus on the DirectDraw initialisation only.

Best regards

Detlev

0 Kudos
Sergey_K_Intel
Employee
2,243 Views

Hi Detlev,

Aren't YUV2 and UYVY the synonyms of YCbCr422 ? If yes, then ippiYCbCr422ToRGB could be used.

Regards,
Sergey 

0 Kudos
Detlev_Petersen
Beginner
2,243 Views

Hi Sergey,

I used the call ippiCbYCr422ToRGB_8u_C2C3R() and the code lines below to get my UYVY frame into a RGB bitmap. The colors are twisted somehow but I read that YUY uses another value for 0 and has a different value range in comparison with RGB which uses the values from 0 up to 255 of each byte. I guess this is the reason for the change colors. In addition to that I have something like a mirror effect within my bitmap. It was faster for me to use a copy of another 800x600 bitmap than to set up a genuine Windows bitmap header. It can be that this is the rootcause for the mirror effect. Please see attached frame 240 of my test video as bitmap which was saved in the way below after calling the resize and the last color conversion from YUY2 to UYVY and before calling Windows' Blt().

My current IPP sample for the resize after GetFrame will follow.

Best regards

Detlev

// just to control the result before Blt() copies it to the screen

// UYVY to RGB

if(m_dwDecodedFramesCount%10==0)

{

// do this every 10 frames

BYTE* pDstBmp;

inti_sizeBmp=sizeDst.height*sizeDst.width*3;

pDstBmp=

newBYTE[i_sizeBmp];

if(pDstBmp!=NULL)

{

// allocating the memor was successful

ippiCbYCr422ToRGB_8u_C2C3R(

(

constIpp8u*)pDecodeBuffer,

sizeDst.width*2,

(Ipp8u*)pDstBmp,

sizeDst.width*3,

sizeDst);

// copy the bitmap to file

FILE* hFile;

charfilename[1024];

charheader[54];

// set filename

sprintf(&filename[0],

"frame_%ld.bmp",m_dwDecodedFramesCount);

// set bitmap header

header[0]=0x42;

header[1]=0x4D;

header[2]=0x36;

header[3]=0xF9;

header[4]=0x15;

header[5]=0x00;

header[6]=0x00;

header[7]=0x00;

header[8]=0x00;

header[9]=0x00;

header[10]=0x36;

header[11]=0x00;

header[12]=0x00;

header[13]=0x00;

header[14]=0x28;

header[15]=0x00;

header[16]=0x00;

header[17]=0x00;

header[18]=0x20;

header[19]=0x03;

header[20]=0x00;

header[21]=0x00;

header[22]=0x58;

header[23]=0x02;

header[24]=0x00;

header[25]=0x00;

header[26]=0x01;

header[27]=0x00;

header[28]=0x18;

header[29]=0x00;

header[30]=0x00;

header[31]=0x00;

header[32]=0x00;

header[33]=0x00;

header[34]=0x00;

header[35]=0xF9;

header[36]=0x15;

header[37]=0x00;

header[38]=0x00;

header[39]=0x00;

header[40]=0x00;

header[41]=0x00;

header[42]=0x00;

header[43]=0x00;

header[44]=0x00;

header[45]=0x00;

header[46]=0x00;

header[47]=0x00;

header[48]=0x00;

header[49]=0x00;

header[50]=0x00;

header[51]=0x00;

header[52]=0x00;

header[53]=0x00;

if((hFile = _fsopen(&filename[0],"wb",_SH_DENYNO)) != NULL)

{

// size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

fwrite(&header[0],

sizeof(char),54,hFile);

fwrite(pDstBmp,

sizeof(BYTE),i_sizeBmp,hFile);

fclose(hFile);

}

deletepDstBmp;

}

}

0 Kudos
Sergey_K_Intel
Employee
2,138 Views

Hi Detlev,

It can be not a mirror. BMP files ares stored in bottom-up order, i.e. lowest raster line first.

Regards,
Sergey 

0 Kudos
Reply