graphicscomposition/openwfcompositionengine/common/src/owfimage.c
branchNewGraphicsArchitecture
changeset 39 a4b63488e0b0
parent 35 3aa07f06a4b7
child 61 4ac0d9f65e95
--- a/graphicscomposition/openwfcompositionengine/common/src/owfimage.c	Fri Apr 23 15:29:19 2010 +0100
+++ b/graphicscomposition/openwfcompositionengine/common/src/owfimage.c	Fri Apr 23 17:57:02 2010 +0100
@@ -211,7 +211,7 @@
     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
     OWF_ASSERT(image->width >= 3 && image->height >= 3);
     
-    copyStride = image->width * image->pixelSize;    
+    copyStride = OWF_Image_GetStride(image->width, &image->format, 0);
     
     /* top side replication */
     srcPtr = (OWFuint8*) image->data;
@@ -252,11 +252,15 @@
     void*       srcLinePtr;
     OWFpixel*   dstLinePtr;
     OWFboolean  replicateEdges = OWF_FALSE;
+#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
+    OWFint      widthBytes;
+#endif
     
 
     OWF_ASSERT(dst != 0 && dst->data != NULL);
     OWF_ASSERT(src != 0 && src->data != NULL);
     OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
+    OWF_ASSERT(dst->stride == OWF_Image_GetStride(dst->width, &dst->format, 0));
     
     srcLinePtr = src->data;
     dstLinePtr = (OWFpixel*) dst->data;    
@@ -285,6 +289,10 @@
         return OWF_FALSE;
     }
 
+#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
+    widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
+#endif
+
     for (countY = src->height; countY; countY--)
     {
         OWFint count = src->width;
@@ -294,7 +302,7 @@
         {
             case OWF_IMAGE_ARGB8888:
             {
-#ifdef USE_FLOAT_PIXEL
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
                 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr;
     
                 while (count > 0)
@@ -312,7 +320,7 @@
                     count--;
                 }
 #else
-                memcpy(dstLinePtr, srcLinePtr, src->stride);
+                memcpy(dstLinePtr, srcLinePtr, widthBytes);
 #endif
                 break;
             }
@@ -323,7 +331,7 @@
                 
                 while (count > 0)
                 {
-#ifdef USE_FLOAT_PIXEL
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
                     dstPtr->color.alpha = OWF_FULLY_OPAQUE;
                     dstPtr->color.red   = (OWFsubpixel)
                         OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE;
@@ -370,6 +378,7 @@
                 }
                 break;
             }
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
             case OWF_IMAGE_UYVY:
             {
                 OWFuint8* srcPtr = (OWFuint8*) srcLinePtr;
@@ -412,7 +421,7 @@
                 }
                 break;
             }
-                
+#endif     
             default:
             {
                 return OWF_FALSE; /* source format not supported */
@@ -501,10 +510,14 @@
     OWFuint32*              dstPtr;
     OWFpixel*               srcPtr;
     OWFuint8*               destination;
+#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
+    OWFint                  widthBytes;
+#endif
 
     OWF_ASSERT(dst != 0 && dst->data != NULL);
     OWF_ASSERT(src != 0 && src->data != NULL);
     OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
+    /* Note: src->stride cannot be relied upon to be correct. Assume lines are contiguous. */
 
     if (src->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
     {
@@ -530,6 +543,10 @@
     }
 
     destination = (OWFuint8*) dst->data;
+#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
+    widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
+#endif
+
     for (countY = 0; countY < src->height; countY++)
     {   
         dstPtr = (OWFuint32*) destination;    
@@ -539,7 +556,7 @@
         {
             case OWF_IMAGE_ARGB8888:
             {
-#ifdef USE_FLOAT_PIXEL
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
                 OWFint countX;
                 OWFuint32 dstPixel = 0;               
                 
@@ -558,20 +575,20 @@
                     srcPtr ++;
                 }
 #else
-                memcpy(dstPtr, srcPtr, src->stride);
-                srcPtr = (OWFpixel*)((OWFuint8*)srcPtr + src->stride);
+                memcpy(dstPtr, srcPtr, widthBytes);
+                srcPtr = (OWFpixel*)((OWFuint8*)srcPtr + widthBytes);
 #endif
                 break;
             }
     
             case OWF_IMAGE_XRGB8888:
             {
-#ifdef USE_FLOAT_PIXEL
                 OWFint countX;
                 OWFuint32 dstPixel = 0;
                 
                 for (countX = 0; countX < src->width; countX++)
                 {
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
                     dstPixel  = ARGB8888_ALPHA_MASK;
                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE))   <<
                                 ARGB8888_RED_SHIFT);
@@ -579,16 +596,17 @@
                                 ARGB8888_GREEN_SHIFT);
                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE))  <<
                                 ARGB8888_BLUE_SHIFT);
+#else
+                    dstPixel = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK;
+#endif
                     *dstPtr = dstPixel;
                     dstPtr ++;
                     srcPtr ++;
                 }
-#else
-                memcpy(dstPtr, srcPtr, src->stride);
-                srcPtr = (OWFpixel*)((OWFuint8*)srcPtr + src->stride);
-#endif
                 break;
             }
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
+			/* TODO: Fix this code! It should be converting from ARGB into YUV, not the other way around. */
             case OWF_IMAGE_UYVY:
             {
                 OWFuint8* srcPtr = (OWFuint8*) srcLinePtr;
@@ -631,6 +649,7 @@
                 }
                 break;
             }
+#endif
                 
             default:
             {
@@ -1223,10 +1242,12 @@
     OWF_ASSERT(image != 0);
     OWF_ASSERT(image->data != 0);
     OWF_ASSERT(image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
+    /* Note: image->stride cannot be relied upon to be correct. Assume lines are contiguous. */
 
     numPixels = image->width * image->height;
     pixels = (OWFpixel*) image->data;
 
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
     for (i = 0; i < numPixels; i++)
     {
         pixels[i].color.red   = (OWFsubpixel) red;
@@ -1234,6 +1255,29 @@
         pixels[i].color.blue  = (OWFsubpixel) blue;
         pixels[i].color.alpha = (OWFsubpixel) alpha;
     }
+#else
+    if (alpha == red && alpha == green && alpha == blue)
+        {
+        /* If all four bytes are the same, just use memset */
+        OWFuint32 clearBytes = numPixels * sizeof(OWFuint32);
+
+        memset(pixels, alpha, clearBytes);
+        }
+    else
+        {
+        /* Otherwise assign each pixel the packed value */
+        OWFuint32* pixelPtr = (OWFuint32*)pixels;
+        OWFuint32 pixel;
+    
+        pixel = (alpha << ARGB8888_ALPHA_SHIFT) | (red << ARGB8888_RED_SHIFT) |
+                (green << ARGB8888_GREEN_SHIFT) | (blue << ARGB8888_BLUE_SHIFT);
+
+        for (i = 0; i < numPixels; i++)
+            {
+            pixelPtr[i] = pixel;
+            }
+        }
+#endif
 }
 
 /*----------------------------------------------------------------------------*/
@@ -1500,25 +1544,9 @@
     OWFint rowCount = drect.height; \
     while (rowCount > 0) { \
         OWFint colCount = drect.width; \
-        while (colCount > 0) { \
-            if (!(blend->tsColor && COLOR_MATCH(SC, TSC))) \
-            { \
+        while (colCount > 0) {
 
 #define BLENDER_INNER_LOOP_END \
-                DA = blend->destinationFullyOpaque ? OWF_FULLY_OPAQUE : DA; \
-            } /* end tsColor check */ \
-            srcPtr ++; \
-            dstPtr ++; \
-            --colCount; \
-        } \
-        srcPtr += srcLineDelta; \
-        dstPtr += dstLineDelta; \
-        --rowCount; \
-    }
-
-#define BLENDER_INNER_LOOP_END_WITH_MASK \
-                DA = blend->destinationFullyOpaque ? OWF_FULLY_OPAQUE : DA; \
-            } /* end tsColor check */ \
             srcPtr ++; \
             dstPtr ++; \
             maskPtr++; \
@@ -1529,14 +1557,16 @@
         maskPtr += maskLineDelta; \
         --rowCount; \
     }
-
-#define TSC blend->tsColor->color
-#define SC srcPtr->color
-
-/* Note: actually would be better to compare integer values
- * for TSC match -> eliminate float arithmetic pitfalls
- */
-#define COLOR_MATCH(x, y) (x.red==y.red && x.green==y.green && x.blue==y.blue)
+	
+#define BLENDER_INNER_LOOP_END_NO_MASK \
+            srcPtr ++; \
+            dstPtr ++; \
+            --colCount; \
+        } \
+        srcPtr += srcLineDelta; \
+        dstPtr += dstLineDelta; \
+        --rowCount; \
+    }
 
 #define SA srcPtr->color.alpha
 #define SR srcPtr->color.red
@@ -1653,11 +1683,6 @@
     srcLineDelta = src->width - srect.width;
     dstLineDelta = dst->width - drect.width;
 
-    if ((transparency & OWF_TRANSPARENCY_GLOBAL_ALPHA) && (GA > (OWF_ALPHA_MAX_VALUE - OWF_ALPHA_MIN_STEP_VALUE)))
-        {
-        /* Fully opaque, so ignore global alpha */
-        transparency &= ~OWF_TRANSPARENCY_GLOBAL_ALPHA;
-        }
     /* inner loops */
     switch (transparency)
     {
@@ -1673,7 +1698,7 @@
                 DG = SG;
                 DB = SB;
                 DA = OWF_FULLY_OPAQUE;
-            BLENDER_INNER_LOOP_END;
+            BLENDER_INNER_LOOP_END_NO_MASK;
 #else
             memcpy(dstPtr, srcPtr, drect.height*drect.width*4);
 #endif
@@ -1695,40 +1720,57 @@
                      OWF_ALPHA_MAX_VALUE;
                 DA = GA + (DA * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) / 
                      OWF_ALPHA_MAX_VALUE;
-            BLENDER_INNER_LOOP_END;
+            BLENDER_INNER_LOOP_END_NO_MASK;
             break;
         }
 
         case OWF_TRANSPARENCY_SOURCE_ALPHA:
         {
+#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
+        OWFuint32 redBlueMask = (ARGB8888_RED_MASK | ARGB8888_BLUE_MASK);
+        OWFuint32 alphaGreenMask = (ARGB8888_ALPHA_MASK | ARGB8888_GREEN_MASK);
+        OWFuint32 halfRedBlue = 0x00800080;
+#endif
             /*
             rgb     = src.rgb + dst.rgb * (1 - src.alpha)
             alpha    = src.alpha + dst.alpha * (1 - src.alpha)
             */
             BLENDER_INNER_LOOP_BEGIN;
-                if (SA > (OWF_ALPHA_MAX_VALUE - OWF_ALPHA_MIN_STEP_VALUE))
+#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
+            DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
+            DG = SG + (DG * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
+            DB = SB + (DB * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
+            DA = SA + (DA * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
+#else
+            {
+                OWFuint32 srcP = *(OWFuint32*)srcPtr;
+                OWFuint8 srcA = srcP >> ARGB8888_ALPHA_SHIFT;
+
+                if (srcA == OWF_ALPHA_MAX_VALUE)
                     {
                     /* Fully opaque source pixel */
-                    DR = SR;
-                    DG = SG;
-                    DB = SB;
-                    DA = OWF_FULLY_OPAQUE;
+                    *(OWFuint32*)dstPtr = srcP;
                     }
                 else
                     {
-                    if (SA >= OWF_ALPHA_MIN_STEP_VALUE)
+                    if (srcA)
                         {
-                        /* Not fully transparent source pixel */
-                       /*
-                        * DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
-                        */ 
-                        DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) >> 8;
-                        DG = SG + (DG * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) >> 8;
-                        DB = SB + (DB * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) >> 8;
-                        DA = SA + (DA * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) >> 8;
+                        /* Not fully transparent source pixel. Algorithm after Jim Blinn */
+                        OWFuint32 mask = 0xFF - srcA;
+                        OWFuint32 dstP = *(OWFuint32*)dstPtr;
+                        OWFuint32 blend;
+
+                        blend = mask * (dstP & redBlueMask) + halfRedBlue;
+                        srcP += ((blend + ((blend >> 8) & redBlueMask) >> 8)) & redBlueMask;
+                        blend = mask * ((dstP >> 8) & redBlueMask) + halfRedBlue;
+                        srcP += (blend + ((blend >> 8) & redBlueMask)) & alphaGreenMask;
+
+                        *(OWFuint32*)dstPtr = srcP;
                         }
                     }
-            BLENDER_INNER_LOOP_END;
+            }
+#endif
+            BLENDER_INNER_LOOP_END_NO_MASK;
             break;
         }
 
@@ -1747,7 +1789,7 @@
                      OWF_ALPHA_MAX_VALUE;
                 DA = MA + (DA * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) / 
                      OWF_ALPHA_MAX_VALUE;
-            BLENDER_INNER_LOOP_END_WITH_MASK;
+            BLENDER_INNER_LOOP_END;
             break;
         }
 
@@ -1769,7 +1811,7 @@
                      OWF_ALPHA_MAX_VALUE;
                 DA = SAEA + (DA * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
                          OWF_ALPHA_MAX_VALUE;
-            BLENDER_INNER_LOOP_END;
+            BLENDER_INNER_LOOP_END_NO_MASK;
             break;
         }
 
@@ -1793,7 +1835,7 @@
                      OWF_ALPHA_MAX_VALUE;
                 //No need to check with OWF_ALPHA_MIN_VALUE as it is zero
                 OWF_ASSERT(GA <= OWF_ALPHA_MAX_VALUE);
-            BLENDER_INNER_LOOP_END_WITH_MASK;
+            BLENDER_INNER_LOOP_END;
             break;
         }
 
@@ -1876,12 +1918,12 @@
 
         case OWF_IMAGE_RGB565:
         case OWF_IMAGE_L16:
+        case OWF_IMAGE_UYVY:
         {
             return 2;
         }
 
         case OWF_IMAGE_L8:
-        case OWF_IMAGE_UYVY:
         {
             return 1;
         }
@@ -1917,6 +1959,7 @@
         case OWF_IMAGE_ARGB8888:
         case OWF_IMAGE_XRGB8888:
         case OWF_IMAGE_L32:
+        case OWF_IMAGE_UYVY:
         {
             padding = 4;
             break;
@@ -1937,7 +1980,6 @@
         }
 
         case OWF_IMAGE_L8:
-        case OWF_IMAGE_UYVY:
         {
             padding = 1;
             break;