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

Setting the alpha channel

Adriaan_van_Os
New Contributor I
1,060 Views

I have a 16u RGBA image and a 16u one-channel grayscale image. The grayscale image must be set as the alpha channel of the RGBA image.

One would think this is an easy task, but the RGBA image is (and has to be) premultiplied, for compatibility with CoreGraphics on Mac OS X. In fact, I don't see a fast way to accomplish this using IPP. Any hints (or future new functions) are welcome.

For 8u images, I call vImageUnpremultiplyData_ARGB8888, ippiCopy_8u_C1C4R and vImagePremultiplyData_ARGB8888. For 32f images, I call vImageUnpremultiplyData_RGBAFFFF, ippiCopy_32f_C1C4R and vImagePremultiplyData_RGBAFFFF. This method works fast. The vImage functions are from Apple's vImage framework https://developer.apple.com/documentation/accelerate. There are no 16u vImage functions to do this.

The question remains how to do this with IPP and for 16u.

Regards,

Adriaan van Os

0 Kudos
10 Replies
Chao_Y_Intel
Moderator
1,060 Views

Hi,

For the premul with alpha value, can this function be used there?
https://software.intel.com/en-us/ipp-dev-reference-alphapremul

Thanks,
Chao

 

0 Kudos
Adriaan_van_Os
New Contributor I
1,060 Views

Yes, thanks, I hadn't seen that function. I will note that there are variants for 8u and 16u, but not for 32f. And how to do the preceding unpremultiply ?

Regards,

Adriaan van Os

 

0 Kudos
Igor_A_Intel
Employee
1,060 Views

Hi Adriaan van Os,

Could you explain what do you need in a more understandable form? I've taken a look into ippi.h:

IPPAPI( IppStatus, ippiCopy_16u_C4C1R,
                   ( const Ipp16u* pSrc, int srcStep,
                     Ipp16u* pDst, int dstStep, IppiSize roiSize ))

and into Apple alpha-composition:

vImageUnpremultiplyData_ARGB16U

Transforms an ARGB16U image in premultiplied alpha format into an image in nonpremultiplied alpha format.

regards, Igor
0 Kudos
Adriaan_van_Os
New Contributor I
1,060 Views

Unpremultiply is the inverse operation of premultiply. With a premultiply, every RGB channel is multiplied by the value of the A channel. With an unpremultiply, every RGB channel is divided by the value of the A channel, unless the A channel has value 0.

So, if an image is in premultiplied form, the RGB channels contain their proper value multiplied by the value of the A channel. So, if we change the A channel to another value, we must first unpremultiply (divide by the current value of the A channel), set the new value of the A channel and then premultiply (multiply with the new value of the A channel). If the A channel has value 0, then the proper RGB values are lost.

I am not fond about images that are in premultiplied form, but if the OS requires it, you have little choice.

Regards,

Adriaan van Os

 

0 Kudos
Igor_A_Intel
Employee
1,060 Views

Got it, thank you.

this operation is rather easy for 32f images (just divide new alpha by the old one and call premul once more time - with, as you already mentioned, - "0" exception). But for the integer images this approach doesn't work - you need "unpremul" support. Do you need any additional support from the IPP side?

regards, Igor

0 Kudos
Adriaan_van_Os
New Contributor I
1,058 Views

Thanks. For 8u and 16u images "unpremul" support, analog ippAlphaPremul, would suffice.

I welcome these functions (for premultiplication and unpremultiplication) also for 32f, unless I miss something. Can you elaborate what current ipp functions you have in mind for doing "this operation rather easy for 32f images" ?

Regards,

Adriaan van Os

P.S. Ah, I see now that vImageUnpremultiplyData_ARGB16U is a new (and very useful) function. Thanks for bringing that to my attention !

0 Kudos
Igor_A_Intel
Employee
1,058 Views

I had in mind the next: for 32f you don't need "un-premul" - you can divide "new" alpha by the "old" one and then call only "pre-mul".

regards, Igor.

0 Kudos
Adriaan_van_Os
New Contributor I
1,058 Views

One would have to allocate a one-channel image and copy the old alpha channel to it. Then, ippiDiv_32f_C1R could be called, but the description of this function (and of ippsDiv_32f) says

    ippStsDivByZero          A warning that a divisor value is zero,  the function execution is continued.

                             If a dividend is equal to zero,  then the result is NAN_32F;

                             if it is greater than zero,  then the result is INF_32F, 

                             if it is less than zero,  then the result is INF_NEG_32F

Rather, with unpremultiplication, the result should be 0.

As as sidebar and apart from the division-by-zero problem, note that many Apple accelerate functions have a stride parameter, see e.g. https://developer.apple.com/documentation/accelerate/1450412-vdsp_svdiv?language=objc . In many cases, this stride parameter is quite useful. Here it would make allocation and copy to a one-channel image unnecessary,

Regards,

Adriaan van Os

 

0 Kudos
Igor_A_Intel
Employee
1,058 Views

Hi Adriaan van Os,

agree, "un-premul"->"premul" may be easier in this case. As regarding NaNs - IPP provides API for their substitution:

IPPAPI(IppStatus, ippsReplaceNAN_32f_I, (Ipp32f* pSrcDst, int len, Ipp32f value))
IPPAPI(IppStatus, ippsReplaceNAN_64f_I, (Ipp64f* pSrcDst, int len, Ipp64f value))

as regarding stride - we supported strides for ippMX (small matrix) domain (removed, available in legacy only). It is hard to develop optimized code path for an arbitrary stride - guess Apple provides optimized solution for dense cases only. 

Regards, Igor

0 Kudos
Adriaan_van_Os
New Contributor I
1,058 Views

Here is an interesting proposal for strided memory access vectorization in LLVM https://reviews.llvm.org/D21363 Functions like ippiCopy_xx_C1C4R have to deal with strides anyway. But, as you say, they use a specific stride, not an arbitrary stride.

Thanks,

Adriaan van Os

 

0 Kudos
Reply