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

Feature Request: ippiCopy_*_C2P2R and ippiCopy_*_P2C2R

yakov_galka
Beginner
371 Views

First, I understand that IPP tries to reduce bloat by excluding some rare staff and functions that can be easily implemented using the existing ones. And I see it as a positive thing. However, I believe that it should support conversions from otherwise unsupported formats to a workable form, so that when I encounter such format I could still efficiently convert and use IPP.

Now, one such thing is a conversion from 2-channel interleaved images to 2-channel planar (and vice versa). Such 2-channel images are sometimes used (for example for grayscale + alpha as in PNG), and are supported by other libraries (like OpenGL). IPP lacks ippiCopy_*_C2P2R and ippiCopy_*_P2C2R functions, and I couldn't find a way to bake them using other functions other than invoking ippiTranspose_*_C1R on each row.

Thank you in advance,
Yakov Galka
 

0 Kudos
3 Replies
Igor_A_Intel
Employee
371 Views

Hi Yakov,

for 16s,32f & 64f data you can use ipps functions with row-by-row access:

/* /////////////////////////////////////////////////////////////////////////////
//  Name:       ippsCplxToReal
//  Purpose:    form the real and imaginary parts of the input complex vector
//  Parameters:
//    pSrc       pointer to the input complex vector
//    pDstRe     pointer to output vector to store the real part
//    pDstIm     pointer to output vector to store the imaginary part
//    len        length of the vectors, number of items
//  Return:
//    ippStsNullPtrErr        pointer(s) to the data is NULL
//    ippStsSizeErr           length of the vectors is less or equal zero
//    ippStsNoErr             otherwise
*/

IPPAPI(IppStatus, ippsCplxToReal_64fc,( const Ipp64fc* pSrc, Ipp64f* pDstRe,
       Ipp64f* pDstIm, int len ))
IPPAPI(IppStatus, ippsCplxToReal_32fc,( const Ipp32fc* pSrc, Ipp32f* pDstRe,
       Ipp32f* pDstIm, int len ))
IPPAPI(IppStatus, ippsCplxToReal_16sc,( const Ipp16sc* pSrc, Ipp16s* pDstRe,
       Ipp16s* pDstIm, int len ))

/* /////////////////////////////////////////////////////////////////////////////
//  Name:       ippsRealToCplx
//  Purpose:    form complex vector from the real and imaginary components
//  Parameters:
//    pSrcRe     pointer to the input vector with real part, may be NULL
//    pSrcIm     pointer to the input vector with imaginary part, may be NULL
//    pDst       pointer to the output complex vector
//    len        length of the vectors
//  Return:
//    ippStsNullPtrErr        pointer to the destination data is NULL
//    ippStsSizeErr           length of the vectors is less or equal zero
//    ippStsNoErr             otherwise
//
//  Notes:      one of the two input pointers may be NULL. In this case
//              the corresponding values of the output complex elements is 0
*/

IPPAPI(IppStatus, ippsRealToCplx_64f,( const Ipp64f* pSrcRe,
       const Ipp64f* pSrcIm, Ipp64fc* pDst, int len ))
IPPAPI(IppStatus, ippsRealToCplx_32f,( const Ipp32f* pSrcRe,
       const Ipp32f* pSrcIm, Ipp32fc* pDst, int len ))
IPPAPI(IppStatus, ippsRealToCplx_16s,( const Ipp16s* pSrcRe,
       const Ipp16s* pSrcIm, Ipp16sc* pDst, int len ))

 

also it's not clear which format and data type you are going to convert - there are available for example the next conversions:

IPPAPI(IppStatus, ippiYCbCr422ToYCbCr420_8u_C2P2R,( const Ipp8u* pSrc, int srcStep, Ipp8u* pDstY, int dstYStep,Ipp8u* pDstCbCr,int dstCbCrStep, IppiSize roiSize ))
IPPAPI(IppStatus, ippiCbYCr422ToYCbCr420_8u_C2P2R,( const Ipp8u* pSrc, int srcStep, Ipp8u* pDstY, int dstYStep,Ipp8u* pDstCbCr,int dstCbCrStep, IppiSize roiSize ))
IPPAPI(IppStatus, ippiYCbCr420ToYCbCr422_8u_P2C2R,(const Ipp8u* pSrcY, int srcYStep,const Ipp8u* pSrcCbCr,
                  int srcCbCrStep, Ipp8u* pDst, int dstStep, IppiSize roiSize))
IPPAPI(IppStatus, ippiYCbCr420ToYCbCr422_Filter_8u_P2C2R,(const Ipp8u* pSrcY, int srcYStep,const Ipp8u* pSrcCbCr,
        int srcCbCrStep, Ipp8u* pDst, int dstStep, IppiSize roiSize,int layout))
and some other...

regards, Igor

0 Kudos
yakov_galka
Beginner
371 Views

Hi Igor,

Thank you for the CplxToReal/RealToCplx tip. It will indeed work for the 2, 4, and 8 byte types.

Yet, we do use images of 8-bit (most frequently), 16-bit (less frequently) and 32-bit (not for this specific conversion, but we are likely to do this in the future) data types.

Unfortunately the YCbCr422ToYCbCr420/YCbCr420ToYCbCr422 family you propose do a downscaling/upscaling in the vertical direction, which makes them inappropriate for the conversion I need. For example,

    static const int w = 4, h = 4;
    uint8_t src[w*h*2];
    for(int i = 0; i < w*h*2; ++i)
        src = i;

    uint8_t dest1[w*h], dest2[w*h];
    memset(dest1, 0xff, sizeof(dest1));
    memset(dest2, 0xff, sizeof(dest2));

    IppiSize roi = { w, h };
    ippiYCbCr422ToYCbCr420_8u_C2P2R(src, w*2, dest1, w, dest2, w, roi);

The contents of dest1 is, correctly,

    00 02 04 06
    08 0A 0C 0E
    10 12 14 16
    18 1A 1C 1E

whereas the contents of dest2 is

    01 03 05 07
    11 13 15 17
    FF FF FF FF
    FF FF FF FF

or

    01 03 05 07
    FF FF FF FF
    11 13 15 17
    FF FF FF FF

if I double the third stride.

Thanks,
Yakov

0 Kudos
Igor_A_Intel
Employee
371 Views

Hi Yakov,

ok, I see, so currently you don't have an appropriate workaround for C2P2 & P2C2 for 8u. We'll consider this feature request for one of the future releases.

regards, Igor

0 Kudos
Reply