     for (int ix=threadIdx.x; ix<width; ix+=blockDim.x)
     {
         uchar4 *dest = img + line*width+ix;
-        uchar4 c = *dest;
-#ifdef FLOATIMG
-        *dest = make_uchar4(imgLine[ix].x * 255.f + c.x*imgLine[ix].w,
-                imgLine[ix].y * 255.f + c.y*imgLine[ix].w,
-                imgLine[ix].z * 255.f + c.z*imgLine[ix].w,
-                (1.f-imgLine[ix].w) * (255-c.w) + c.w);
-#else
-        const float w= imgLine[ix].w/255.f;
-        imgLine[ix].w = 255 - imgLine[ix].w;
-        *dest = make_uchar4(imgLine[ix].x + c.x*w,
-                imgLine[ix].y + c.y*w,
-                imgLine[ix].z + c.z*w,
-                (1.f-w) * (255-c.w) + c.w);
-#endif
+        blend(dest, imgLine[ix]);
     }
 }
 #endif

        // the voxel row of the current slice corresponding to this image line
#ifndef NOLOAD
#ifndef CONSTLOAD
        const Scalar *voxLine = (Scalar *)(((uchar *)voxels) + pitch * ((slice+1)*c_vox[principal+1] + (iPosY-line-1)));
#endif

#ifdef SHMLOAD
        for (int ix=threadIdx.x; ix<c_vox[principal+0]; ix+=blockDim.x)
        {
#ifdef SHMCLASS
#ifdef FLOATDATA
            voxel[ix] = tex1Dfetch(tex_tf, voxLine[ix]*255.f);
#else
            voxel[ix] = tex1Dfetch(tex_tf, voxLine[ix]);
#endif
#else
            voxel[ix] = voxLine[ix];
#endif

            const int iidx = ix;

            // pointer to destination pixel
            Pixel *pix = imgLine + iidx;
            Pixel d = *pix;
#ifdef EARLYRAYTERM
            if(isOpaque(d))
                continue;
#endif

            const float x = c_tcStart[slice].x + c_tcStep[slice].x*vidx;
