os/graphics/graphicscomposition/openwfcompositionengine/common/src/owfimage.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* Copyright (c) 2009-2010 The Khronos Group Inc.
     2  * Portions copyright (c) 2009-2010  Nokia Corporation and/or its subsidiary(-ies)
     3  * 
     4  * Permission is hereby granted, free of charge, to any person obtaining a
     5  * copy of this software and/or associated documentation files (the
     6  * "Materials"), to deal in the Materials without restriction, including
     7  * without limitation the rights to use, copy, modify, merge, publish,
     8  * distribute, sublicense, and/or sell copies of the Materials, and to
     9  * permit persons to whom the Materials are furnished to do so, subject to
    10  * the following conditions:
    11  *
    12  * The above copyright notice and this permission notice shall be included
    13  * in all copies or substantial portions of the Materials.
    14  *
    15  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    21  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    22  */
    23 
    24 #ifdef __cplusplus
    25 extern "C"
    26 {
    27 #endif
    28 
    29 #include <string.h>
    30 #include <stdlib.h>
    31 #include <stdio.h>
    32 #include <math.h>
    33 
    34 #include "owfobject.h"
    35 #include "owfimage.h"
    36 #include "owfutils.h"
    37 #include "owfmemory.h"
    38 #include "owfdebug.h"
    39 #include "owfdisplaycontextgeneral.h"
    40 
    41 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
    42 #define roundSubPixel(p) ((OWFuint32)((p) + 0.5f))
    43 #else
    44 #define roundSubPixel(p) (p)
    45 #endif
    46 
    47 
    48 /*----------------------------------------------------------------------------*/
    49 OWF_API_CALL void
    50 OWF_IMAGE_Ctor(void* self)
    51 {
    52     DPRINT(("OWF_IMAGE_Ctor"));
    53 
    54     self = self;
    55 }
    56 
    57 /*----------------------------------------------------------------------------*/
    58 OWF_API_CALL void
    59 OWF_IMAGE_Dtor(void* self)
    60 {
    61     OWF_IMAGE* image;
    62 
    63     DPRINT(("OWF_IMAGE_Dtor"));
    64 
    65     image = (OWF_IMAGE*)self;
    66 
    67     if (image && image->data)
    68     {
    69         if (!image->foreign)
    70         {
    71             OWF_Image_FreeData(0, &image->data);
    72         }
    73     }
    74 
    75     if (image)
    76     {
    77         memset(image, 0, sizeof(OWF_IMAGE));
    78     }
    79 }
    80 
    81 /*----------------------------------------------------------------------------*/
    82 static OWFfloat
    83 NonLinear(OWFfloat x)
    84 {
    85     if (x <= 0.00304f)
    86     {
    87         return 12.92f * x;
    88     }
    89     return 1.0556f * pow(x, 1.f/2.4f) - 0.0556f;
    90 }
    91 
    92 /*----------------------------------------------------------------------------*/
    93 static OWFfloat
    94 Linear(OWFfloat x)
    95 {
    96     if (x <= 0.03928)
    97     {
    98         return x / 12.92f;
    99     }
   100     return pow((x + 0.0556f) / 1.0556f, 2.4f);
   101 }
   102 
   103 /*----------------------------------------------------------------------------*/
   104 OWF_API_CALL void
   105 OWF_Image_NonLinearizeData(OWF_IMAGE* image)\
   106 {
   107     OWFpixel*            ptr;
   108     OWFint               count;
   109 
   110     DPRINT(("OWF_Image_NonLinearizeData"));
   111 
   112     OWF_ASSERT(image != NULL && image->data != NULL);
   113     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   114 
   115     if (!image->format.linear)
   116     {
   117         return;
   118     }
   119 
   120     ptr = (OWFpixel*) image->data;
   121     count = image->width * image->height;
   122 
   123     while (count > 0)
   124     {
   125         ptr->color.red   = (OWFsubpixel) NonLinear(ptr->color.red /
   126                                OWF_RED_MAX_VALUE) * OWF_RED_MAX_VALUE;
   127         ptr->color.green = (OWFsubpixel) NonLinear(ptr->color.green /
   128                                OWF_GREEN_MAX_VALUE) * OWF_GREEN_MAX_VALUE;
   129         ptr->color.blue  = (OWFsubpixel) NonLinear(ptr->color.blue /
   130                                OWF_BLUE_MAX_VALUE) * OWF_BLUE_MAX_VALUE;
   131 
   132         --count;
   133         ptr++;
   134     }
   135 
   136     image->format.linear = OWF_FALSE;
   137 }
   138 
   139 /*----------------------------------------------------------------------------*/
   140 OWF_API_CALL void
   141 OWF_Image_LinearizeData(OWF_IMAGE* image)
   142 {
   143     OWFpixel*               ptr;
   144     OWFuint                 count;
   145 
   146     DPRINT(("OWF_Image_LinearizeData"));
   147 
   148     OWF_ASSERT(image != NULL && image->data != NULL);
   149     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   150 
   151     if (image->format.linear)
   152     {
   153         return;
   154     }
   155 
   156     ptr = (OWFpixel*) image->data;
   157     count = image->width * image->height;
   158 
   159     while (count > 0)
   160     {
   161         ptr->color.red   = (OWFsubpixel) Linear(ptr->color.red /
   162                                OWF_RED_MAX_VALUE) * OWF_RED_MAX_VALUE;
   163         ptr->color.green = (OWFsubpixel) Linear(ptr->color.green /
   164                                OWF_GREEN_MAX_VALUE) * OWF_GREEN_MAX_VALUE;
   165         ptr->color.blue  = (OWFsubpixel) Linear(ptr->color.blue /
   166                                OWF_BLUE_MAX_VALUE) * OWF_BLUE_MAX_VALUE;
   167 
   168         --count;
   169         ptr += image->pixelSize;
   170     }
   171 
   172     image->format.linear = OWF_TRUE;
   173 
   174 }
   175 
   176 /*----------------------------------------------------------------------------*/
   177 #define GAMMA(color, max, gamma) (max * pow(color/max, gamma))
   178 
   179 OWF_API_CALL void
   180 OWF_Image_Gamma(OWF_IMAGE* image, OWFfloat gamma)
   181 {
   182     OWFpixel*            ptr;
   183     OWFint               count;
   184 
   185     DPRINT(("OWF_Image_Gamma"));
   186 
   187     OWF_ASSERT(image != NULL && image->data != NULL);
   188     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   189 
   190     if (gamma == 1.0f)
   191     {
   192         return;
   193     }
   194 
   195     ptr = (OWFpixel*) image->data;
   196     count = image->width * image->height;
   197 
   198     while (count > 0)
   199     {
   200         ptr->color.red   =
   201             (OWFsubpixel) GAMMA(ptr->color.red, OWF_RED_MAX_VALUE, gamma);
   202         ptr->color.green =
   203             (OWFsubpixel) GAMMA(ptr->color.green, OWF_GREEN_MAX_VALUE, gamma);
   204         ptr->color.blue  =
   205             (OWFsubpixel) GAMMA(ptr->color.blue, OWF_BLUE_MAX_VALUE, gamma);
   206 
   207         --count;
   208         ptr++;
   209     }
   210 }
   211 
   212 /*----------------------------------------------------------------------------*/
   213 OWF_API_CALL void
   214 OWF_Image_EdgeReplication(OWF_IMAGE* image)
   215 {
   216     OWFint          y;
   217     OWFint          copyStride;
   218     OWFuint8*       srcPtr      = NULL;
   219     OWFuint8*       dstPtr      = NULL;
   220     
   221     DPRINT(("OWF_Image_EdgeReplication"));
   222 
   223     OWF_ASSERT(image);
   224     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   225     OWF_ASSERT(image->width >= 3 && image->height >= 3);
   226     
   227     copyStride = OWF_Image_GetStride(image->width, &image->format, 0);
   228     
   229     /* top side replication */
   230     srcPtr = (OWFuint8*) image->data;
   231     srcPtr += 1 * image->stride + 0 * image->pixelSize;
   232     dstPtr = (OWFuint8*) image->data;
   233 
   234     memcpy(dstPtr, srcPtr, copyStride);
   235     
   236     /* bottom side replication */
   237     srcPtr = (OWFuint8*) image->data;
   238     srcPtr += (image->height-2) * image->stride + 0 * image->pixelSize;        
   239     dstPtr = (OWFuint8*) image->data;
   240     dstPtr += (image->height-1) * image->stride + 0 * image->pixelSize;
   241     
   242     memcpy(dstPtr, srcPtr, copyStride);
   243     
   244     /* left side replication */
   245     for (y = 0; y < image->height; y++)
   246     {
   247         OWF_Image_SetPixel(image, 0, y, OWF_Image_GetPixelPtr(image, 1, y));
   248     }
   249     
   250     /* right side replication */
   251     for (y = 0; y < image->height; y++)
   252     {
   253         OWF_Image_SetPixel(image, image->width-1, y, OWF_Image_GetPixelPtr(image,
   254                                                               image->width-2,
   255                                                               y));
   256     }   
   257     
   258 }
   259 
   260 /*----------------------------------------------------------------------------*/
   261 OWF_API_CALL OWFboolean
   262 OWF_Image_SourceFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src)
   263 {
   264     OWFint      countY, widthDiff, heightDiff;
   265     void*       srcLinePtr;
   266     OWFpixel*   dstLinePtr;
   267     OWFboolean  replicateEdges = OWF_FALSE;
   268 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   269     OWFint      widthBytes;
   270 #endif
   271 
   272     DPRINT(("OWF_Image_SourceFormatConversion"));
   273 
   274     OWF_ASSERT(dst != 0 && dst->data != NULL);
   275     OWF_ASSERT(src != 0 && src->data != NULL);
   276     OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   277     OWF_ASSERT(dst->stride == OWF_Image_GetStride(dst->width, &dst->format, 0));
   278     
   279     srcLinePtr = src->data;
   280     dstLinePtr = (OWFpixel*) dst->data;    
   281     
   282     /* dst image must either be the same size as the src image or 2 pixels 
   283        bigger (enough space to perform edge replication) */
   284     if (dst->width != src->width || dst->height != src->height)
   285     {
   286         widthDiff = dst->width - src->width;
   287         heightDiff = dst->height - src->height;
   288         
   289         if (widthDiff == 2 && heightDiff == 2)
   290         {
   291             replicateEdges = OWF_TRUE;   
   292             /* start of the destination buffer should have a 1 pixel offset */
   293             dstLinePtr = (OWFpixel*) dst->data + 1 * dst->width + 1;
   294         }
   295         else
   296         {
   297             return OWF_FALSE;
   298         }
   299     }
   300 
   301     if (dst->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
   302     {
   303         return OWF_FALSE;
   304     }
   305 
   306 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   307     widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
   308 #endif
   309 
   310     for (countY = src->height; countY; countY--)
   311     {
   312         OWFint count = src->width;
   313         OWFpixel* dstPtr = dstLinePtr;
   314     
   315         switch (src->format.pixelFormat)
   316         {
   317             case OWF_IMAGE_ARGB8888:
   318             {
   319 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   320                 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr;
   321     
   322                 while (count > 0)
   323                 {
   324                     dstPtr->color.alpha = (OWFsubpixel)
   325                         OWF_ALPHA_MAX_VALUE * ((*srcPtr & ARGB8888_ALPHA_MASK) >> ARGB8888_ALPHA_SHIFT) / OWF_BYTE_MAX_VALUE;
   326                     dstPtr->color.red   = (OWFsubpixel)
   327                         OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE;
   328                     dstPtr->color.green = (OWFsubpixel)
   329                         OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK)>> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE;
   330                     dstPtr->color.blue  = (OWFsubpixel)
   331                         OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE;
   332                     dstPtr ++;
   333                     srcPtr ++;
   334                     count--;
   335                 }
   336 #else
   337                 memcpy(dstLinePtr, srcLinePtr, widthBytes);
   338 #endif
   339                 break;
   340             }
   341     
   342             case OWF_IMAGE_XRGB8888:
   343             {
   344                 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr;
   345                 
   346                 while (count > 0)
   347                 {
   348 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   349                     dstPtr->color.alpha = OWF_FULLY_OPAQUE;
   350                     dstPtr->color.red   = (OWFsubpixel)
   351                         OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE;
   352                     dstPtr->color.green = (OWFsubpixel)
   353                         OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK) >> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE;
   354                     dstPtr->color.blue  = (OWFsubpixel)
   355                         OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE;
   356 #else
   357                     *(OWFuint32*)dstPtr = *srcPtr | ARGB8888_ALPHA_MASK;
   358 #endif
   359                     dstPtr ++;
   360                     srcPtr ++;
   361                     count--;
   362                 }
   363                 break;
   364             }
   365     
   366             case OWF_IMAGE_RGB565:
   367             {
   368                 OWFfloat tmp;
   369                 OWFuint16* srcPtr = (OWFuint16*) srcLinePtr;
   370                 
   371                 while (count > 0)
   372                 {
   373                     /*
   374                      * Formula for converting channel value is:
   375                      * Each channel is multiplied by (2^d - 1)/(2^s -1)
   376                      * where d is dest channel bits and s is source channel bits.
   377                      */
   378                     dstPtr->color.alpha = (OWFsubpixel) OWF_FULLY_OPAQUE;
   379     
   380                     tmp = (OWFfloat)((*srcPtr & RGB565_RED_MASK) >> RGB565_RED_SHIFT);
   381                     dstPtr->color.red   = (OWFsubpixel)OWF_RED_MAX_VALUE * tmp / 31.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
   382     
   383                     tmp = (OWFfloat)((*srcPtr & RGB565_GREEN_MASK) >> RGB565_GREEN_SHIFT);
   384                     dstPtr->color.green = (OWFsubpixel)OWF_GREEN_MAX_VALUE * tmp / 63.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
   385     
   386                     tmp = (OWFfloat)(*srcPtr & RGB565_BLUE_MASK);
   387                     dstPtr->color.blue  = (OWFsubpixel)OWF_BLUE_MAX_VALUE * tmp / 31.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
   388     
   389                     dstPtr ++;
   390                     srcPtr ++;
   391                     count--;
   392                 }
   393                 break;
   394             }
   395     
   396             default:
   397             {
   398                 return OWF_FALSE; /* source format not supported */
   399             }
   400         }
   401         
   402         dstLinePtr+=dst->width;
   403         srcLinePtr=(OWFuint8*)srcLinePtr+src->stride;
   404     }
   405     
   406     if (replicateEdges)
   407     {
   408         OWF_Image_EdgeReplication(dst);
   409     }
   410 
   411     return OWF_TRUE;
   412 }
   413 
   414 /*----------------------------------------------------------------------------*/
   415 OWF_PUBLIC OWFint
   416 OWF_Image_GetStride(OWFint width, const OWF_IMAGE_FORMAT* format, OWFint minimumStride)
   417 {
   418     OWFint                  size;
   419     OWFint                  pixelSize;
   420 
   421     DPRINT(("OWF_Image_GetStride"));
   422 
   423     OWF_ASSERT(format);
   424 
   425     pixelSize = OWF_Image_GetFormatPixelSize(format->pixelFormat);
   426 
   427     if (pixelSize < 0)
   428     {
   429         /* negative pixelSize means that pixel size is a fraction
   430          * (1/-pixelSize) of a byte, e.g. -8 means pixel has size
   431          * of one bit. */
   432 
   433         size = (width + 1) / -pixelSize;
   434     }
   435     else
   436     {
   437         size = width * pixelSize;
   438     }
   439     if (size<minimumStride)
   440     {
   441         size=minimumStride;
   442     }
   443     if (format->rowPadding)
   444     {
   445         size += format->rowPadding - 1;
   446         size -= size % format->rowPadding;
   447     }
   448     return size;
   449 }
   450 
   451 /*----------------------------------------------------------------------------*/
   452 OWF_API_CALL OWFboolean
   453 OWF_Image_IsValidDestinationFormat(OWF_IMAGE_FORMAT* format)
   454 {
   455     DPRINT(("OWF_Image_IsValidDestinationFormat"));
   456 
   457     switch (format->pixelFormat)
   458     {
   459         case OWF_IMAGE_ARGB8888:
   460         {
   461             return OWF_TRUE;
   462         }
   463         case OWF_IMAGE_XRGB8888:
   464         {
   465             return OWF_TRUE;
   466         }
   467 #ifdef SUPPORT_565_OUTPUT
   468         case OWF_IMAGE_RGB565:
   469         {
   470             return OWF_TRUE;
   471         }
   472 #endif
   473         default:
   474         {
   475             return OWF_FALSE; /* destination format not supported */
   476         }
   477     }
   478 }
   479 
   480 /*----------------------------------------------------------------------------*/
   481 OWF_API_CALL OWFboolean
   482 OWF_Image_DestinationFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src)
   483 {
   484     OWFint                  countY;
   485     OWFuint32*              dstPtr;
   486     OWFpixel*               srcPtr;
   487 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   488     OWFint                  widthBytes;
   489 #endif
   490 
   491     DPRINT(("OWF_Image_DestinationFormatConversion"));
   492 
   493     OWF_ASSERT(dst != 0 && dst->data != NULL);
   494     OWF_ASSERT(src != 0 && src->data != NULL);
   495     OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   496     /* Note: src->stride cannot be relied upon to be correct. Assume lines are contiguous. */
   497 
   498     if (src->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
   499     {
   500         return OWF_FALSE;
   501     }
   502 
   503     /* src and data must have equal amount of pixels */
   504     if (dst->width != src->width || dst->height != src->height)
   505     {
   506         return OWF_FALSE;
   507     }
   508 
   509     dstPtr = (OWFuint32*) dst->data;
   510     srcPtr = (OWFpixel*) src->data;
   511 
   512     if (dst->format.premultiplied && !src->format.premultiplied)
   513     {
   514         OWF_Image_PremultiplyAlpha(src);
   515     }
   516     else if (!dst->format.premultiplied && src->format.premultiplied)
   517     {
   518         OWF_Image_UnpremultiplyAlpha(src);
   519     }
   520 
   521 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   522     widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
   523 #endif
   524 
   525     for (countY = 0; countY < src->height; countY++)
   526     {   
   527         OWFuint8* destination = (OWFuint8*) dst->data;
   528         destination += countY*dst->stride;
   529         dstPtr = (OWFuint32*) destination;    
   530     
   531         switch (dst->format.pixelFormat)
   532         {
   533             case OWF_IMAGE_ARGB8888:
   534             {
   535 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   536                 OWFint countX;
   537                 OWFuint32 dstPixel = 0;               
   538                 
   539                 for (countX = 0; countX < src->width; countX++)
   540                 {
   541                     dstPixel  = ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.alpha / OWF_ALPHA_MAX_VALUE)) <<
   542                                 ARGB8888_ALPHA_SHIFT);
   543                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE))   <<
   544                                 ARGB8888_RED_SHIFT);
   545                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) <<
   546                                 ARGB8888_GREEN_SHIFT);
   547                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE))  <<
   548                                 ARGB8888_BLUE_SHIFT);
   549                     *dstPtr = dstPixel;
   550                     dstPtr ++;
   551                     srcPtr ++;
   552                 }
   553 #else
   554                 memcpy(dstPtr, srcPtr, widthBytes);
   555                 srcPtr = (OWFpixel*)((OWFuint8*)srcPtr + widthBytes);
   556 #endif
   557                 break;
   558             }
   559     
   560             case OWF_IMAGE_XRGB8888:
   561             {
   562                 OWFint countX;
   563                 OWFuint32 dstPixel = 0;
   564                 
   565                 for (countX = 0; countX < src->width; countX++)
   566                 {
   567 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   568                     dstPixel  = ARGB8888_ALPHA_MASK;
   569                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE))   <<
   570                                 ARGB8888_RED_SHIFT);
   571                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) <<
   572                                 ARGB8888_GREEN_SHIFT);
   573                     dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE))  <<
   574                                 ARGB8888_BLUE_SHIFT);
   575 #else
   576                     dstPixel = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK;
   577 #endif
   578                     *dstPtr = dstPixel;
   579                     dstPtr ++;
   580                     srcPtr ++;
   581                 }
   582                 break;
   583             }
   584     
   585             default:
   586             {
   587                 return OWF_FALSE; /* destination format not supported */
   588             }
   589         }
   590     }
   591 
   592     return OWF_TRUE;
   593 }
   594 
   595 /*----------------------------------------------------------------------------*/
   596 OWF_API_CALL void
   597 OWF_Image_Init(OWF_IMAGE* image)
   598 {
   599     DPRINT(("OWF_Image_Init"));
   600 
   601     OWF_ASSERT(NULL != image);
   602     memset(image, 0, sizeof(OWF_IMAGE));
   603 }
   604 
   605 /*----------------------------------------------------------------------------*/
   606 OWF_PUBLIC OWF_IMAGE*
   607 OWF_Image_Create(OWFint width,
   608                  OWFint height,
   609                  const OWF_IMAGE_FORMAT* format,
   610                  void* buffer,
   611                  OWFint minimumStride
   612                  )
   613 {
   614     OWF_IMAGE*      image;
   615 
   616     DPRINT(("OWF_Image_Create"));
   617 
   618     image = CREATE(OWF_IMAGE);
   619 
   620     if (image)
   621     {
   622 
   623         image->format.pixelFormat   = format->pixelFormat;
   624         image->format.linear        = format->linear;
   625         image->format.premultiplied = format->premultiplied;
   626         image->format.rowPadding    = format->rowPadding;
   627 
   628         image->pixelSize    = OWF_Image_GetFormatPixelSize(format->pixelFormat);
   629         image->width        = width;
   630         image->height       = height;
   631 
   632         /* stride is row length in bytes (aligned according to image format) */
   633         image->stride = OWF_Image_GetStride(width, &image->format, minimumStride);
   634         image->foreign  = (buffer) ? OWF_TRUE : OWF_FALSE;
   635         image->dataMax = image->stride * height;
   636 
   637         DPRINT(("OWF_Image_Create:"));
   638         DPRINT(("  Pixel format     = %x", format->pixelFormat));
   639         DPRINT(("  Linear           = %d", format->linear));
   640         DPRINT(("  Premultiplied    = %d", format->premultiplied));
   641         DPRINT(("  Row alignment    = %d bytes", format->rowPadding));
   642         DPRINT(("  Pixel size       = %d", image->pixelSize));
   643         DPRINT(("  Width            = %d", image->width));
   644         DPRINT(("  Height           = %d", image->height));
   645         DPRINT(("  Stride           = %d", image->stride));
   646         DPRINT(("  Foreign data     = %d", image->foreign));
   647         DPRINT(("  Data size        = %d", image->dataMax));
   648         if (image->dataMax > 0)
   649         {
   650             image->data = (image->foreign) ? (buffer) :
   651                 OWF_Image_AllocData(0, width, height, format->pixelFormat);
   652         }
   653         else
   654         {
   655             /* either overflow occured or width/height is zero */
   656             if (width && height)
   657             {
   658                 DPRINT(("OWF_Image_Create: Overflow in image size calculation."));
   659             }
   660             else
   661             {
   662                 DPRINT(("OWF_Image_Create: width or height is zero."));
   663             }
   664         }
   665     }
   666 
   667     if (!(image && image->data && (image->dataMax > 0)))
   668     {
   669         DPRINT(("OWF_Image_Create: Image creation failed (image = %p, "
   670                 "data = %p, dataSize = %d)",
   671                 image, image ? (void*)(image->data) : (void*)NULL, image?image->dataMax:-1));
   672         DESTROY(image);
   673         return NULL;
   674     }
   675     return image;
   676 }
   677 
   678 /*----------------------------------------------------------------------------*/
   679 OWF_PUBLIC void OWF_Image_Destroy(OWF_IMAGE* image)
   680 {
   681     if (image)
   682         {
   683         DESTROY(image);
   684         }
   685 }
   686 
   687 
   688 /*----------------------------------------------------------------------------*/
   689 OWF_API_CALL OWF_IMAGE*
   690 OWF_Image_Copy(const OWF_IMAGE* image)
   691 {
   692     OWF_IMAGE* newImage = NULL;
   693 
   694     DPRINT(("OWF_Image_Copy"));
   695 
   696     OWF_ASSERT(image);
   697 
   698     newImage = CREATE(OWF_IMAGE);
   699     if (newImage)
   700     {
   701         memcpy(newImage, image, sizeof(*newImage));
   702         if (!image->foreign)
   703         {
   704             newImage->data = xalloc(1, image->dataMax);
   705             if (newImage->data)
   706             {
   707                 memcpy(newImage->data,
   708                        image->data,
   709                        image->height*image->stride);
   710             }
   711         }
   712     }
   713 
   714     return newImage;
   715 }
   716 
   717 /*----------------------------------------------------------------------------*/
   718 OWF_API_CALL OWFboolean
   719 OWF_Image_SetSize(OWF_IMAGE* image,
   720                   OWFint width,
   721                   OWFint height)
   722 {
   723     OWFint                  size;
   724     OWFint                  stride;
   725 
   726     DPRINT(("OWF_Image_SetSize"));
   727 
   728     OWF_ASSERT(image);
   729     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL ||
   730             image->format.pixelFormat==OWF_IMAGE_L32);
   731     
   732     /** note that this setsize ignores any specialised stride **/
   733     stride = OWF_Image_GetStride(width, &image->format, 0);
   734     size = height * stride;
   735 
   736     /* change source size if buffer have enough space */
   737     if (size > 0 && size <= image->dataMax)
   738     {
   739         image->height = height;
   740         image->width  = width;
   741         image->stride = stride;
   742         return OWF_TRUE;
   743     }
   744     return OWF_FALSE;
   745 }
   746 /*----------------------------------------------------------------------------*/
   747 OWF_API_CALL void
   748 OWF_Image_SetFlags(OWF_IMAGE* image,
   749                   OWFboolean premultiply,
   750                   OWFboolean linear)
   751     {
   752     DPRINT(("OWF_Image_SetFlags"));
   753 
   754     OWF_ASSERT(image);
   755     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL ||
   756             image->format.pixelFormat==OWF_IMAGE_L32);
   757     image->format.linear=linear;
   758     image->format.premultiplied=premultiply;
   759     }
   760 
   761 /*----------------------------------------------------------------------------*/
   762 OWF_API_CALL void
   763 OWF_Image_SetPixelBuffer(OWF_IMAGE* image,      void* buffer)
   764     {
   765     DPRINT(("OWF_Image_SetPixelBuffer"));
   766 
   767     OWF_ASSERT(image);
   768     OWF_ASSERT(buffer);
   769     OWF_ASSERT(image->foreign);
   770     if (image->foreign)
   771         {
   772         image->data=buffer;
   773         }
   774     }
   775 /*----------------------------------------------------------------------------*/
   776 /* NEVER USED
   777 OWF_API_CALL OWFboolean
   778 OWF_Image_SetPixelData(OWF_IMAGE* image,
   779                        OWFint width,
   780                        OWFint height,
   781                        const OWF_IMAGE_FORMAT* format,
   782                        void* buffer)
   783 {
   784     OWFint                  size = 0,
   785                             stride = 0;
   786 
   787     OWF_ASSERT(image && format);
   788 
   789     stride  = OWF_Image_GetStride(width, format);
   790     size    = height * stride;
   791 
   792     if (size <= 0)
   793     {
   794         return OWF_FALSE; 
   795     }
   796 
   797     if (!image->foreign)
   798     {
   799         OWF_Image_FreeData(0, &image->data);
   800     }
   801 
   802     image->format.pixelFormat   = format->pixelFormat;
   803     image->format.linear        = format->linear;
   804     image->format.premultiplied = format->premultiplied;
   805     image->format.rowPadding    = format->rowPadding;
   806 
   807     image->pixelSize    = OWF_Image_GetFormatPixelSize(format->pixelFormat);
   808     image->width        = width;
   809     image->height       = height;
   810     image->stride       = stride;
   811     image->foreign      = OWF_TRUE;
   812     image->dataMax      = size;
   813     image->data         = buffer;
   814 
   815     return OWF_TRUE;
   816 }
   817 */
   818 /*----------------------------------------------------------------------------*/
   819 OWF_API_CALL OWFboolean
   820 OWF_Image_Blit(OWF_IMAGE* dst,
   821                OWF_RECTANGLE const* dstRect,
   822                OWF_IMAGE const* src,
   823                OWF_RECTANGLE const* srcRect)
   824 {
   825     OWF_RECTANGLE           bounds, rect, drect, srect;
   826     OWFint                  lineCount   = 0;
   827     OWFint                  copyStride  = 0;
   828     OWFuint8*               srcPtr      = NULL;
   829     OWFuint8*               dstPtr      = NULL;
   830 
   831     DPRINT(("OWF_Image_Blit"));
   832 
   833     OWF_ASSERT(dst != 0 && dst->data != NULL);
   834     OWF_ASSERT(src != 0 && src->data != NULL);
   835     OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   836     OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   837 
   838     OWF_Rect_Set(&bounds, 0, 0, dst->width, dst->height);
   839     OWF_Rect_Set(&rect,
   840                  dstRect->x, dstRect->y,
   841                  srcRect->width, srcRect->height);
   842     OWF_Rect_Set(&srect,
   843                  srcRect->x, srcRect->y,
   844                  srcRect->width, srcRect->height);
   845 
   846     /* clip destination rectangle against bounds */
   847     if (!OWF_Rect_Clip(&drect, &rect, &bounds))
   848     {
   849         return OWF_FALSE;
   850     }
   851 
   852     if (src->pixelSize != dst->pixelSize)
   853     {
   854         DPRINT(("OWF_Image_Blit(): pixels sizes differ\n"));
   855         return OWF_FALSE;
   856     }
   857 
   858     lineCount = srect.height;
   859     copyStride = srect.width * src->pixelSize;
   860 
   861     /* use bytepointers in copy  - generic */
   862     srcPtr = (OWFuint8*) src->data;
   863     srcPtr += srect.y * src->stride + srect.x * src->pixelSize;
   864     dstPtr = (OWFuint8*)dst->data;
   865     dstPtr += drect.y * dst->stride + drect.x * src->pixelSize;
   866 
   867     while (lineCount > 0)
   868     {
   869         --lineCount;
   870 
   871         memcpy(dstPtr, srcPtr, copyStride);
   872 
   873         srcPtr += src->stride;
   874         dstPtr += dst->stride;
   875     }
   876 
   877     return OWF_TRUE;
   878 }
   879 
   880 /*----------------------------------------------------------------------------*/
   881 OWF_API_CALL OWFpixel*
   882 OWF_Image_GetPixelPtr(OWF_IMAGE* image,
   883                       OWFint x,
   884                       OWFint y)
   885 {
   886     OWF_ASSERT(image && image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   887     if (!(image && image->data))
   888     {
   889         return 0;
   890     }
   891 
   892     x = CLAMP(x, 0, image->width-1);
   893     y = CLAMP(y, 0, image->height-1);
   894 
   895     return (OWFpixel*)image->data + y * image->width  + x ;
   896 }
   897 
   898 /*----------------------------------------------------------------------------*/
   899 OWF_API_CALL void
   900 OWF_Image_GetPixel(OWF_IMAGE* image,
   901                    OWFint x,
   902                    OWFint y,
   903                    OWFpixel* pixel)
   904 {
   905     OWFpixel*               temp = NULL;
   906 
   907     OWF_ASSERT(pixel);
   908 
   909     if (!(image && image->data))
   910     {
   911         return;
   912     }
   913     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   914 
   915     pixel->color.alpha = 0;
   916     pixel->color.red = 0;
   917     pixel->color.green = 0;
   918     pixel->color.blue = 0;
   919 
   920     if (x < 0 || y < 0 || x >= image->width || y >= image->height)
   921     {
   922         return;
   923     }
   924 
   925     temp = (OWFpixel*)image->data + y * image->width  + x;
   926 
   927     pixel->color.alpha = temp->color.alpha;
   928     pixel->color.red = temp->color.red;
   929     pixel->color.green = temp->color.green;
   930     pixel->color.blue = temp->color.blue;
   931 }
   932 
   933 /*----------------------------------------------------------------------------*/
   934 OWF_API_CALL void
   935 OWF_Image_SetPixel(OWF_IMAGE* image,
   936                    OWFint x,
   937                    OWFint y,
   938                    OWFpixel const* pixel)
   939 {
   940     OWFpixel*               data = NULL;
   941 
   942     if (!(image && image->data))
   943     {
   944         return;
   945     }
   946     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   947 
   948     if(x < 0 || y < 0 || x >= image->width || y >= image->height)
   949     {
   950         return;
   951     }
   952 
   953 
   954     data = (OWFpixel*)image->data + y * image->width + x;
   955 
   956     data->color.red = pixel->color.red;
   957     data->color.green = pixel->color.green;
   958     data->color.blue = pixel->color.blue;
   959     data->color.alpha = pixel->color.alpha;
   960 }
   961 
   962 /*----------------------------------------------------------------------------*/
   963 OWF_API_CALL OWFboolean
   964 OWF_Image_PointSamplingStretchBlit(OWF_IMAGE* dst,
   965                                    OWF_RECTANGLE* dstRect,
   966                                    OWF_IMAGE* src,
   967                                    OWFfloat* srcRect)
   968 {
   969     OWFint                  ox = 0, oy = 0;
   970     OWFint                  x, y;
   971 
   972     DPRINT(("OWF_Image_PointSamplingStretchBlit"));
   973 
   974     /* images must be valid */
   975     if (!((src != NULL) && (src->data != NULL) &&
   976           (dst != NULL) && (dst->data != NULL)))
   977     {
   978         return OWF_FALSE;
   979     }
   980     OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   981     OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   982 
   983     /* ditto with rectangles, too */
   984     if (!((dstRect != NULL) && (dstRect->width && dstRect->height) &&
   985           (srcRect != NULL) && (srcRect[2] && srcRect[3])))
   986     {
   987         return OWF_FALSE;
   988     }
   989 
   990     /* Note: bounds check missing */
   991 
   992     if (src->pixelSize != dst->pixelSize)
   993     {
   994         return OWF_FALSE;
   995     }
   996 
   997 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   998     {
   999         OWFfloat                dx = 0.f, dy = 0.f; 
  1000     
  1001         /* solve scaling ratios for image */
  1002         dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width;
  1003         dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height;
  1004     
  1005         for (y = 0; y < dstRect->height; y++)
  1006         {
  1007             for (x = 0; x < dstRect->width; x++) 
  1008             {
  1009                 OWFpixel*       pixel;         
  1010                 
  1011                 /* NOTE This code uses pixel center points to calculate distances
  1012                         and factors. Results can differ slightly when pixel corner
  1013                         coordinates are used */            
  1014                 
  1015                 /* coordinates of nearest pixel in original image */
  1016                 ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]);
  1017                 oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]);     
  1018                 
  1019                 pixel = OWF_Image_GetPixelPtr(src,
  1020                                               ox,
  1021                                               oy);
  1022                 
  1023                 OWF_Image_SetPixel(dst,
  1024                                    dstRect->x + x,
  1025                                    dstRect->y + y,
  1026                                    pixel);
  1027                 
  1028             }
  1029         }
  1030     }
  1031 #else
  1032     if (srcRect[0] < 0 || (srcRect[0] + srcRect[2]) > src->width ||
  1033             srcRect[1] < 0 || (srcRect[1] + srcRect[3]) > src->height)
  1034         {
  1035         /* Source rectangle out of bounds */
  1036         return OWF_FALSE;
  1037         }
  1038 
  1039     if (dstRect->x < 0 || (dstRect->x + dstRect->width) > dst->width ||
  1040             dstRect->y < 0 || (dstRect->y + dstRect->height) > dst->height)
  1041         {
  1042         /* Destination rectangle out of bounds */
  1043         return OWF_FALSE;
  1044         }
  1045 
  1046     {
  1047         OWFint dxFix, dyFix;
  1048         OWFint xFixStart, yFix;
  1049         OWFuint32 *dstPtr, *srcLinePtr;
  1050     
  1051 /* Integer <-> 16.16 fixed point conversion macros */
  1052 #define INT_TO_FIXED_PT(X) ((X) << 16)
  1053 #define FIXED_PT_TO_INT(X) ((X) >> 16)
  1054     
  1055         /* Calculate scaling factors in fixed point (with rounding). */
  1056         dxFix = (OWFint)((srcRect[2] * INT_TO_FIXED_PT(1) + (dstRect->width >> 1)) / dstRect->width);
  1057         dyFix = (OWFint)((srcRect[3] * INT_TO_FIXED_PT(1) + (dstRect->height >> 1)) / dstRect->height);
  1058     
  1059         /* Calculate fixed point location in source, with half-pixel offset */
  1060         xFixStart = (OWFint)(srcRect[0] * INT_TO_FIXED_PT(1) + (dxFix >> 1));
  1061         yFix = (OWFint)(srcRect[1] * INT_TO_FIXED_PT(1) + (dyFix >> 1));
  1062     
  1063         /* Initial target address. */
  1064         dstPtr = (OWFuint32*)dst->data + dstRect->y * dst->width + dstRect->x;
  1065     
  1066         for (y = 0; y < dstRect->height; y++)
  1067         {
  1068             OWFint xFix = xFixStart;
  1069     
  1070             oy = FIXED_PT_TO_INT(yFix);
  1071             srcLinePtr = (OWFuint32*)src->data + oy * src->width;
  1072     
  1073             for (x = 0; x < dstRect->width; x++) 
  1074             {
  1075                 ox = FIXED_PT_TO_INT(xFix);
  1076                 dstPtr[x] = srcLinePtr[ox];
  1077                 xFix += dxFix;
  1078             }
  1079     
  1080             dstPtr += dst->width;
  1081             yFix += dyFix;
  1082         }
  1083     }
  1084 #endif
  1085     return OWF_TRUE;
  1086 }
  1087 
  1088 /*----------------------------------------------------------------------------*/
  1089 OWF_API_CALL OWFboolean
  1090 OWF_Image_BilinearStretchBlit(OWF_IMAGE* dst,
  1091                               OWF_RECTANGLE* dstRect,
  1092                               OWF_IMAGE* src,
  1093                               OWFfloat* srcRect)
  1094 {
  1095     OWFint                  x = 0, y = 0;
  1096     OWFint                  ox = 0, oy = 0;
  1097     OWFfloat                dx = 0.f, dy = 0.f, wx = 0.f, wy = 0.f;
  1098     OWFfloat                w[2 * 2];
  1099     OWFpixel*               sample[4];
  1100     OWFpixel*               pixel = NULL;
  1101 
  1102     DPRINT(("OWF_Image_BilinearStretchBlit"));
  1103 
  1104     /* images must be valid */
  1105     if (!((src != NULL) && (src->data != NULL) &&
  1106           (dst != NULL) && (dst->data != NULL)))
  1107     {
  1108         return OWF_FALSE;
  1109     }
  1110     OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1111     OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1112 
  1113     /* ditto with rectangles, too */
  1114     if (!((dstRect != NULL) && (dstRect->width && dstRect->height) &&
  1115           (srcRect != NULL) && (srcRect[2] && srcRect[3])))
  1116     {
  1117         return OWF_FALSE;
  1118     }
  1119 
  1120     if (src->pixelSize != dst->pixelSize)
  1121     {
  1122         return OWF_FALSE;
  1123     }
  1124 
  1125     /* solve scaling ratios for image */
  1126     dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width;
  1127     dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height;
  1128 
  1129     for (y = 0; y < dstRect->height; y++)
  1130     {
  1131         for (x = 0; x < dstRect->width; x++)
  1132         {
  1133             OWFfloat tempOx, tempOy;            
  1134             
  1135             /* NOTE This code uses pixel center points to calculate distances
  1136                     and factors. Results can differ slightly when pixel corner
  1137                     coordinates are used */
  1138 
  1139             /* coordinates of nearest pixel in original image */
  1140             tempOx = (((OWFfloat) x + 0.5) * dx) + srcRect[0];
  1141             tempOy = (((OWFfloat) y + 0.5) * dy) + srcRect[1];            
  1142             
  1143             ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]);
  1144             oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]);    
  1145 
  1146             /* Distances to nearest pixel, eg. fractional part of coordinate */    
  1147             wx = (OWFfloat) ox + 0.5 - tempOx;
  1148             wy = (OWFfloat) oy + 0.5 - tempOy;
  1149 
  1150             /* If distance is positive, we should use left or upper pixel for
  1151              * second nearest pixel. */
  1152             if (wx > 0.0)
  1153             {
  1154                 ox--;
  1155                 wx = 1.0 - wx;
  1156             }
  1157             else
  1158             {
  1159                 wx = -wx; /* abs */
  1160             }
  1161 
  1162             if (wy > 0.0)
  1163             {
  1164                 oy--;
  1165                 wy = 1.0 - wy;
  1166             }
  1167             else
  1168             {
  1169                 wy = -wy;
  1170             }
  1171             
  1172             /* Calculate weights for samples */
  1173             w[0] = (1.0 - wx) * (1.0 - wy);
  1174             w[1] = wx * (1.0 - wy);
  1175             w[2] = (1.0 - wx) * wy;
  1176             w[3] = wx * wy;
  1177 
  1178             /* get sample */
  1179             sample[0] = OWF_Image_GetPixelPtr(src, ox + 0, oy + 0);
  1180             sample[1] = OWF_Image_GetPixelPtr(src, ox + 1, oy + 0);
  1181             sample[2] = OWF_Image_GetPixelPtr(src, ox + 0, oy + 1);
  1182             sample[3] = OWF_Image_GetPixelPtr(src, ox + 1, oy + 1);
  1183 
  1184             
  1185             /* get result pixel */
  1186             pixel = OWF_Image_GetPixelPtr(dst, x, y);
  1187 
  1188             /* calculate final color */
  1189             pixel->color.red   =
  1190                 sample[0]->color.red * w[0] + sample[1]->color.red * w[1] +
  1191                 sample[2]->color.red * w[2] + sample[3]->color.red * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1192 
  1193             pixel->color.green =
  1194                 sample[0]->color.green * w[0] + sample[1]->color.green * w[1] +
  1195                 sample[2]->color.green * w[2] + sample[3]->color.green * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1196 
  1197             pixel->color.blue  =
  1198                 sample[0]->color.blue * w[0] + sample[1]->color.blue * w[1] +
  1199                 sample[2]->color.blue * w[2] + sample[3]->color.blue * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1200 
  1201             pixel->color.alpha =
  1202                 sample[0]->color.alpha * w[0] + sample[1]->color.alpha * w[1] +
  1203                 sample[2]->color.alpha * w[2] + sample[3]->color.alpha * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1204         }
  1205     }
  1206     return OWF_TRUE;
  1207 
  1208 }
  1209 
  1210 /*----------------------------------------------------------------------------*/
  1211 OWF_API_CALL OWFboolean
  1212 OWF_Image_Stretch(OWF_IMAGE* dst,
  1213                   OWF_RECTANGLE* dstRect,
  1214                   OWF_IMAGE* src,
  1215                   OWFfloat* srcRect,
  1216                   OWF_FILTERING filter)
  1217 {
  1218     OWFboolean          result = OWF_FALSE;
  1219 
  1220     switch (filter)
  1221     {
  1222         case OWF_FILTER_POINT_SAMPLING:
  1223         {
  1224             result = OWF_Image_PointSamplingStretchBlit(dst, dstRect, src,
  1225                                                         srcRect);
  1226             break;
  1227         }
  1228         case OWF_FILTER_BILINEAR:
  1229         {
  1230             result = OWF_Image_BilinearStretchBlit(dst, dstRect, src, srcRect);
  1231             break;
  1232         }
  1233     }
  1234 
  1235     return result;
  1236 }
  1237 
  1238 /*----------------------------------------------------------------------------*/
  1239 OWF_API_CALL void
  1240 OWF_Image_Clear(OWF_IMAGE* image,
  1241                 OWFsubpixel red,
  1242                 OWFsubpixel green,
  1243                 OWFsubpixel blue,
  1244                 OWFsubpixel alpha)
  1245 {
  1246     OWFint                  i, numPixels;
  1247     OWFpixel*                pixels;
  1248 
  1249     DPRINT(("OWF_Image_Clear"));
  1250 
  1251     OWF_ASSERT(image != 0);
  1252     OWF_ASSERT(image->data != 0);
  1253     OWF_ASSERT(image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
  1254     /* Note: image->stride cannot be relied upon to be correct. Assume lines are contiguous. */
  1255 
  1256     numPixels = image->width * image->height;
  1257     pixels = (OWFpixel*) image->data;
  1258 
  1259 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1260     for (i = 0; i < numPixels; i++)
  1261     {
  1262         pixels[i].color.red   = (OWFsubpixel) red;
  1263         pixels[i].color.green = (OWFsubpixel) green;
  1264         pixels[i].color.blue  = (OWFsubpixel) blue;
  1265         pixels[i].color.alpha = (OWFsubpixel) alpha;
  1266     }
  1267 #else
  1268     if (alpha == red && alpha == green && alpha == blue)
  1269         {
  1270         /* If all four bytes are the same, just use memset */
  1271         OWFuint32 clearBytes = numPixels * sizeof(OWFuint32);
  1272 
  1273         memset(pixels, alpha, clearBytes);
  1274         }
  1275     else
  1276         {
  1277         /* Otherwise assign each pixel the packed value */
  1278         OWFuint32* pixelPtr = (OWFuint32*)pixels;
  1279         OWFuint32 pixel;
  1280     
  1281         pixel = (alpha << ARGB8888_ALPHA_SHIFT) | (red << ARGB8888_RED_SHIFT) |
  1282                 (green << ARGB8888_GREEN_SHIFT) | (blue << ARGB8888_BLUE_SHIFT);
  1283 
  1284         for (i = 0; i < numPixels; i++)
  1285             {
  1286             pixelPtr[i] = pixel;
  1287             }
  1288         }
  1289 #endif
  1290 }
  1291 
  1292 /*----------------------------------------------------------------------------*/
  1293 OWF_API_CALL void
  1294 OWF_Image_PremultiplyAlpha(OWF_IMAGE* image)
  1295 {
  1296     OWFint       x, y;
  1297 
  1298     DPRINT(("OWF_Image_PremultiplyAlpha"));
  1299 
  1300     OWF_ASSERT(image != 0);
  1301 
  1302     if (image->format.premultiplied)
  1303     {
  1304         return;
  1305     }
  1306 
  1307     /* only for internal format */
  1308     if (image->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
  1309     {
  1310         return;
  1311     }
  1312 
  1313     for (y = 0; y < image->height; y++)
  1314     {
  1315         for (x = 0; x < image->width; x++)
  1316         {
  1317             OWFpixel* pixel;
  1318             OWFsubpixel alpha;
  1319 
  1320             pixel = OWF_Image_GetPixelPtr(image, x, y);
  1321 
  1322             alpha = pixel->color.alpha;
  1323 
  1324             if (0 == alpha)
  1325             {
  1326                 pixel->color.red =
  1327                 pixel->color.green =
  1328                 pixel->color.blue = 0;
  1329             }
  1330             else
  1331             {
  1332                 pixel->color.red    = (pixel->color.red * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
  1333                                       OWF_ALPHA_MAX_VALUE;
  1334                 pixel->color.green  = (pixel->color.green * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
  1335                                       OWF_ALPHA_MAX_VALUE;
  1336                 pixel->color.blue   = (pixel->color.blue * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
  1337                                       OWF_ALPHA_MAX_VALUE;
  1338             }
  1339         }
  1340     }
  1341 
  1342     image->format.premultiplied = OWF_TRUE;
  1343 }
  1344 
  1345 /*----------------------------------------------------------------------------*/
  1346 OWF_API_CALL void
  1347 OWF_Image_UnpremultiplyAlpha(OWF_IMAGE* image)
  1348 {
  1349     OWFint       count;
  1350     OWFpixel*    pixelPtr;
  1351 
  1352     DPRINT(("OWF_Image_UnpremultiplyAlpha"));
  1353 
  1354     OWF_ASSERT(image != 0);
  1355 
  1356     if (!image->format.premultiplied)
  1357     {
  1358         return;
  1359     }
  1360 
  1361     /* only for internal format */
  1362     if (image->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
  1363     {
  1364         return;
  1365     }
  1366 
  1367     count = image->width * image->height;
  1368     pixelPtr = (OWFpixel*)image->data;
  1369 
  1370     while (count > 0)
  1371     {
  1372 
  1373         OWFsubpixel a = pixelPtr->color.alpha;
  1374 
  1375         #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1376 			OWF_ASSERT(a <= OWF_ALPHA_MAX_VALUE && a >= OWF_ALPHA_MIN_VALUE);
  1377 		#endif
  1378 
  1379         if (a > OWF_ALPHA_MIN_VALUE)
  1380         {
  1381             OWFsubpixel r = pixelPtr->color.red   * OWF_RED_MAX_VALUE / a;
  1382             OWFsubpixel g = pixelPtr->color.green * OWF_GREEN_MAX_VALUE / a;
  1383             OWFsubpixel b = pixelPtr->color.blue  * OWF_BLUE_MAX_VALUE / a;
  1384 
  1385             pixelPtr->color.red   = r;
  1386             pixelPtr->color.green = g;
  1387             pixelPtr->color.blue  = b;
  1388 
  1389             --count;
  1390             pixelPtr++;
  1391         }
  1392     }
  1393 
  1394     image->format.premultiplied = OWF_TRUE;
  1395 }
  1396 
  1397 /*----------------------------------------------------------------------------*/
  1398 OWF_API_CALL void
  1399 OWF_Image_Rotate(OWF_IMAGE* dst,
  1400                  OWF_IMAGE* src,
  1401                  OWF_ROTATION rotation)
  1402 {
  1403     OWFint                  ox = 0, oy = 0,
  1404                             w = 0, h = 0,
  1405                             x = 0, y = 0;
  1406     OWFint                  xx = 0, xy = 0,
  1407                             yx = 0, yy = 0;
  1408 
  1409     DPRINT(("OWF_Image_Rotate"));
  1410 
  1411     OWF_ASSERT(src && src->data);
  1412     OWF_ASSERT(dst && dst->data);
  1413     OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1414     OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1415 
  1416     w = src->width;
  1417     h = src->height;
  1418 
  1419     switch (rotation)
  1420     {
  1421         case OWF_ROTATION_0:
  1422         {
  1423             /*
  1424              * origin: (0, 0)
  1425              * x-axis: (1, 0)
  1426              * y-axis: (0, 1)
  1427              */
  1428             ox = 0;
  1429             oy = 0;
  1430             xx = 1;
  1431             xy = 0;
  1432             yx = 0;
  1433             yy = 1;
  1434             break;
  1435         }
  1436         case OWF_ROTATION_90:
  1437         {
  1438             /*
  1439              * origin: (height-1, 0)
  1440              * x-axis: (0, 1)
  1441              * y-axis: (-1, 0)
  1442              */
  1443             ox = h - 1;
  1444             oy = 0;
  1445             xx = 0;
  1446             xy = 1;
  1447             yx = -1;
  1448             yy = 0;
  1449             break;
  1450         }
  1451         case OWF_ROTATION_180:
  1452         {
  1453             /*
  1454              * origin: (width-1, height-1)
  1455              * x-axis: (-1, 0)
  1456              * y-axis: (0, -1)
  1457              */
  1458             ox = w - 1;
  1459             oy = h - 1;
  1460             xx = -1;
  1461             xy = 0;
  1462             yx = 0;
  1463             yy = -1;
  1464             break;
  1465         }
  1466         case OWF_ROTATION_270:
  1467         {
  1468             /*
  1469              * origin: (0, height-1)
  1470              * x-axis: (0, -1)
  1471              * y-axis: (1, 0)
  1472              */
  1473             ox = 0;
  1474             oy = w - 1;
  1475             xx = 0;
  1476             xy = -1;
  1477             yx = 1;
  1478             yy = 0;
  1479             break;
  1480 
  1481         }
  1482     }
  1483 
  1484     for (y = 0; y < h; y++)
  1485     {
  1486         for (x = 0; x < w; x++)
  1487         {
  1488         /*
  1489          * O = [ox oy]' X = [xx xy]' Y = [yx yy]'
  1490          *
  1491          * p_dst(x_src,y_src) = O + x_src*X + y_src*Y
  1492          */
  1493         OWF_Image_SetPixel(dst,
  1494                            ox + x * xx + y * yx,
  1495                            oy + x * xy + y * yy,
  1496                            OWF_Image_GetPixelPtr(src, x, y));
  1497         }
  1498     }
  1499 }
  1500 
  1501 /*----------------------------------------------------------------------------*/
  1502 OWF_API_CALL void
  1503 OWF_Image_Flip(OWF_IMAGE* image,
  1504                OWF_FLIP_DIRECTION dir)
  1505 {
  1506     OWFint                  x, y;
  1507 
  1508     DPRINT(("OWF_Image_Flip"));
  1509 
  1510     if (!image)
  1511     {
  1512         return;
  1513     }
  1514     OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1515 
  1516     if (dir & OWF_FLIP_VERTICALLY)
  1517     {
  1518         OWFint h = image->height/2;
  1519 
  1520         for (y = 0; y < h; y++)
  1521         {
  1522             for (x = 0; x < image->width; x++)
  1523             {
  1524                 OWFpixel        pix;
  1525 
  1526                 OWF_Image_GetPixel(image, x, y, &pix);
  1527                 OWF_Image_SetPixel(image, x, y,
  1528                                    OWF_Image_GetPixelPtr(image,
  1529                                                          x,
  1530                                                          image->height - 1 - y
  1531                                                          ));
  1532                 OWF_Image_SetPixel(image, x, image->height - 1 - y, &pix);
  1533             }
  1534         }
  1535     }
  1536 
  1537     if (dir & OWF_FLIP_HORIZONTALLY)
  1538     {
  1539         OWFint w = image->width/2;
  1540 
  1541         for (y = 0; y < image->height; y++)
  1542         {
  1543             for (x = 0; x < w; x++)
  1544             {
  1545                 OWFpixel        pix;
  1546 
  1547                 OWF_Image_GetPixel(image, x, y, &pix);
  1548                 OWF_Image_SetPixel(image, x, y,
  1549                                    OWF_Image_GetPixelPtr(image,
  1550                                                          image->width - 1 - x,
  1551                                                          y
  1552                                                          ));
  1553                 OWF_Image_SetPixel(image, image->width - 1 - x, y, &pix);
  1554             }
  1555         }
  1556     }
  1557 }
  1558 
  1559 /*----------------------------------------------------------------------------*/
  1560 #define BLENDER_INNER_LOOP_BEGIN \
  1561     OWFint rowCount = drect.height; \
  1562     while (rowCount > 0) { \
  1563         OWFint colCount = drect.width; \
  1564         while (colCount > 0) {
  1565 
  1566 #define BLENDER_INNER_LOOP_END \
  1567             srcPtr ++; \
  1568             dstPtr ++; \
  1569             maskPtr++; \
  1570             --colCount; \
  1571         } \
  1572         srcPtr += srcLineDelta; \
  1573         dstPtr += dstLineDelta; \
  1574         maskPtr += maskLineDelta; \
  1575         --rowCount; \
  1576     }
  1577 	
  1578 #define BLENDER_INNER_LOOP_END_NO_MASK \
  1579             srcPtr ++; \
  1580             dstPtr ++; \
  1581             --colCount; \
  1582         } \
  1583         srcPtr += srcLineDelta; \
  1584         dstPtr += dstLineDelta; \
  1585         --rowCount; \
  1586     }
  1587 
  1588 #define SA srcPtr->color.alpha
  1589 #define SR srcPtr->color.red
  1590 #define SG srcPtr->color.green
  1591 #define SB srcPtr->color.blue
  1592 
  1593 #define DA dstPtr->color.alpha
  1594 #define DR dstPtr->color.red
  1595 #define DG dstPtr->color.green
  1596 #define DB dstPtr->color.blue
  1597 
  1598 #define MA *maskPtr
  1599 #define GA blend->globalAlpha
  1600 
  1601 OWF_API_CALL void
  1602 OWF_Image_Blend(OWF_BLEND_INFO* blend,
  1603                 OWF_TRANSPARENCY transparency)
  1604 {
  1605     OWF_IMAGE*              dst;
  1606     OWF_IMAGE*              src;
  1607     OWF_IMAGE*              mask;
  1608     OWF_RECTANGLE*          srcRect;
  1609     OWF_RECTANGLE*          dstRect;
  1610     OWF_RECTANGLE           bounds, srect, drect, rect;
  1611     OWFint                  srcLineDelta, dstLineDelta, maskLineDelta;
  1612     OWFpixel*               srcPtr;
  1613     OWFpixel*               dstPtr;
  1614     OWFsubpixel*            maskPtr;
  1615     
  1616     
  1617     /* preparation */
  1618     OWF_ASSERT(blend);
  1619     DPRINT(("OWF_Image_Blend: transparency = %d", transparency));
  1620     /* Mask must be set if mask-transparency is used */
  1621     OWF_ASSERT(((transparency & OWF_TRANSPARENCY_MASK) && blend->mask) ||
  1622            !(transparency & OWF_TRANSPARENCY_MASK));
  1623 
  1624     OWF_ASSERT(blend->source.image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
  1625     OWF_ASSERT(blend->destination.image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
  1626     if (blend->mask)
  1627     {
  1628         OWF_ASSERT(blend->mask->format.pixelFormat == OWF_IMAGE_L32);
  1629     }
  1630     
  1631     dst     = blend->destination.image;
  1632     src     = blend->source.image;
  1633     mask    = blend->mask;
  1634     dstRect = blend->destination.rectangle;
  1635     srcRect = blend->source.rectangle;    
  1636 
  1637     /* this is actually asserted above */
  1638     if (OWF_TRANSPARENCY_MASK == (transparency & OWF_TRANSPARENCY_MASK) &&
  1639         NULL == mask)
  1640     {
  1641         return;
  1642     }
  1643 
  1644     OWF_Rect_Set(&bounds, 0, 0, dst->width, dst->height);
  1645     /* NOTE: src and dst rects should be of same size!!! */
  1646     OWF_Rect_Set(&rect,
  1647                  dstRect->x, dstRect->y,
  1648                  dstRect->width, dstRect->height);
  1649     OWF_Rect_Set(&srect,
  1650                  srcRect->x, srcRect->y,
  1651                  srcRect->width, srcRect->height);
  1652 
  1653     /* clip destination rectangle against bounds */
  1654     if (!OWF_Rect_Clip(&drect, &rect, &bounds))
  1655     {
  1656         return;
  1657     }
  1658 
  1659     /* adjust source rectangle if needed */
  1660     if (drect.x > rect.x)
  1661     {
  1662         OWFint dx = drect.x - rect.x;
  1663         srect.x += dx;
  1664         srect.width -= dx;
  1665     }
  1666 
  1667     if (drect.y > rect.y)
  1668     {
  1669         OWFint dy = drect.y - rect.y;
  1670         srect.y += dy;
  1671         srect.height -= dy;
  1672     }
  1673 
  1674     if (drect.width < srect.width)
  1675     {
  1676         srect.width = drect.width;
  1677     }
  1678 
  1679     if (drect.height < srect.height)
  1680     {
  1681         srect.height = drect.height;
  1682     }
  1683 
  1684 
  1685     srcPtr  = (OWFpixel*) src->data;
  1686     srcPtr  += srect.y * src->width + srect.x;
  1687     dstPtr  = (OWFpixel*) dst->data;
  1688     dstPtr  += drect.y * dst->width + drect.x;
  1689 
  1690     if (mask)
  1691     {
  1692         maskPtr = (OWFsubpixel*) mask->data + srect.y * mask->width + srect.x;
  1693         maskLineDelta = mask->width - drect.width;
  1694     }
  1695     else
  1696     {
  1697         maskPtr = 0;
  1698         maskLineDelta = 0;
  1699     }
  1700     srcLineDelta = src->width - srect.width;
  1701     dstLineDelta = dst->width - drect.width;
  1702 
  1703     /* inner loops */
  1704     switch (transparency)
  1705     {
  1706         case OWF_TRANSPARENCY_NONE:
  1707         {
  1708             /*
  1709             rgb     = src.rgb
  1710             alpha    = 1
  1711             */
  1712             BLENDER_INNER_LOOP_BEGIN;
  1713 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1714                 DR = SR;
  1715                 DG = SG;
  1716                 DB = SB;
  1717                 DA = OWF_FULLY_OPAQUE;
  1718 #else
  1719                 *(OWFuint32*)dstPtr = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK;
  1720 #endif
  1721             BLENDER_INNER_LOOP_END_NO_MASK;
  1722             break;
  1723         }
  1724 
  1725         case OWF_TRANSPARENCY_GLOBAL_ALPHA:
  1726         {
  1727             /*
  1728             rgb        = src.rgb * elem.alpha + dst.rgb * (1 - elem.alpha)
  1729             alpha   = elem.alpha + dst.alpha * (1 - elem.alpha)
  1730             */
  1731             BLENDER_INNER_LOOP_BEGIN;
  1732                 DR = (SR * GA + DR * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
  1733                      OWF_ALPHA_MAX_VALUE;
  1734                 DG = (SG * GA + DG * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
  1735                      OWF_ALPHA_MAX_VALUE;
  1736                 DB = (SB * GA + DB * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
  1737                      OWF_ALPHA_MAX_VALUE;
  1738                 DA = GA + (DA * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) / 
  1739                      OWF_ALPHA_MAX_VALUE;
  1740             BLENDER_INNER_LOOP_END_NO_MASK;
  1741             break;
  1742         }
  1743 
  1744         case OWF_TRANSPARENCY_SOURCE_ALPHA:
  1745         {
  1746 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1747         OWFuint32 redBlueMask = (ARGB8888_RED_MASK | ARGB8888_BLUE_MASK);
  1748         OWFuint32 alphaGreenMask = (ARGB8888_ALPHA_MASK | ARGB8888_GREEN_MASK);
  1749         OWFuint32 halfRedBlue = 0x00800080;
  1750 #endif
  1751             /*
  1752             rgb     = src.rgb + dst.rgb * (1 - src.alpha)
  1753             alpha    = src.alpha + dst.alpha * (1 - src.alpha)
  1754             */
  1755             BLENDER_INNER_LOOP_BEGIN;
  1756 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1757             DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1758             DG = SG + (DG * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1759             DB = SB + (DB * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1760             DA = SA + (DA * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1761 #else
  1762             {
  1763                 OWFuint32 srcP = *(OWFuint32*)srcPtr;
  1764                 OWFuint8 srcA = srcP >> ARGB8888_ALPHA_SHIFT;
  1765 
  1766                 if (srcA == OWF_ALPHA_MAX_VALUE)
  1767                     {
  1768                     /* Fully opaque source pixel */
  1769                     *(OWFuint32*)dstPtr = srcP;
  1770                     }
  1771                 else
  1772                     {
  1773                     if (srcA)
  1774                         {
  1775                         /* Not fully transparent source pixel. Algorithm after Jim Blinn */
  1776                         OWFuint32 mask = 0xFF - srcA;
  1777                         OWFuint32 dstP = *(OWFuint32*)dstPtr;
  1778                         OWFuint32 blend;
  1779 
  1780                         blend = mask * (dstP & redBlueMask) + halfRedBlue;
  1781                         srcP += ((blend + ((blend >> 8) & redBlueMask) >> 8)) & redBlueMask;
  1782                         blend = mask * ((dstP >> 8) & redBlueMask) + halfRedBlue;
  1783                         srcP += (blend + ((blend >> 8) & redBlueMask)) & alphaGreenMask;
  1784 
  1785                         *(OWFuint32*)dstPtr = srcP;
  1786                         }
  1787                     }
  1788             }
  1789 #endif
  1790             BLENDER_INNER_LOOP_END_NO_MASK;
  1791             break;
  1792         }
  1793 
  1794         case OWF_TRANSPARENCY_MASK:
  1795         {
  1796             /*
  1797             rgb     = src.rgb * mask.alpha + dst.rgb * (1 - mask.alpha)
  1798             alpha    = mask.alpha + dst.alpha * (1 - mask.alpha)
  1799             */
  1800             BLENDER_INNER_LOOP_BEGIN;
  1801                 DR = (SR * MA + DR * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
  1802                      OWF_ALPHA_MAX_VALUE;
  1803                 DG = (SG * MA + DG * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
  1804                      OWF_ALPHA_MAX_VALUE;
  1805                 DB = (SB * MA + DB * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
  1806                      OWF_ALPHA_MAX_VALUE;
  1807                 DA = MA + (DA * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) / 
  1808                      OWF_ALPHA_MAX_VALUE;
  1809             BLENDER_INNER_LOOP_END;
  1810             break;
  1811         }
  1812 
  1813         case OWF_TRANSPARENCY_GLOBAL_ALPHA | OWF_TRANSPARENCY_SOURCE_ALPHA:
  1814         {
  1815             /*
  1816             rgb = src.rgb * elem.a + dst.rgb * (1 - src.a * elem.a)
  1817             a = src.a * elem.a + dst.a * (1 - src.a * elem.a)
  1818             */
  1819             OWFsubpixel         SAEA;
  1820 
  1821             BLENDER_INNER_LOOP_BEGIN;
  1822                 SAEA = SA * GA / OWF_ALPHA_MAX_VALUE;
  1823                 DR = (SR * GA + DR * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1824                      OWF_ALPHA_MAX_VALUE;
  1825                 DG = (SG * GA + DG * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1826                      OWF_ALPHA_MAX_VALUE;
  1827                 DB = (SB * GA + DB * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1828                      OWF_ALPHA_MAX_VALUE;
  1829                 DA = SAEA + (DA * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1830                          OWF_ALPHA_MAX_VALUE;
  1831             BLENDER_INNER_LOOP_END_NO_MASK;
  1832             break;
  1833         }
  1834 
  1835         case OWF_TRANSPARENCY_GLOBAL_ALPHA | OWF_TRANSPARENCY_MASK:
  1836         {
  1837             /*
  1838             rgb    = src.rgb * mask.a * elem.a + dst.rgb * (1 - mask.a * elem.a)
  1839             a     = mask.a * elem.a + dest.a * (1 - mask.a * elem.a)
  1840             */
  1841             OWFsubpixel             MAEA;
  1842 
  1843             BLENDER_INNER_LOOP_BEGIN;
  1844                 MAEA = MA * GA / OWF_ALPHA_MAX_VALUE;
  1845                 DR = (SR * MAEA + DR * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1846                      OWF_ALPHA_MAX_VALUE;
  1847                 DG = (SG * MAEA + DG * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1848                      OWF_ALPHA_MAX_VALUE;
  1849                 DB = (SB * MAEA + DB * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1850                      OWF_ALPHA_MAX_VALUE;
  1851                 DA = MAEA + (DA * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1852                      OWF_ALPHA_MAX_VALUE;
  1853                 //No need to check with OWF_ALPHA_MIN_VALUE as it is zero
  1854                 OWF_ASSERT(GA <= OWF_ALPHA_MAX_VALUE);
  1855             BLENDER_INNER_LOOP_END;
  1856             break;
  1857         }
  1858 
  1859         default:
  1860         {
  1861             DPRINT(("OWF_Image_Blend: whooops. invalid blending mode\n"));
  1862             abort();
  1863             break;
  1864         }
  1865     }
  1866 }
  1867 
  1868 /*----------------------------------------------------------------------------*/
  1869 OWF_API_CALL void*
  1870 OWF_Image_AllocData(OWF_DISPCTX dc, OWFint width, OWFint height, OWF_PIXEL_FORMAT pixelFormat)
  1871 {
  1872     OWF_IMAGE_FORMAT        imgf;
  1873     OWFint                  stride;
  1874 
  1875     DPRINT(("OWF_Image_AllocData"));
  1876 
  1877     /* kludge. GetStride need pixelFormat. */
  1878     imgf.pixelFormat = pixelFormat;
  1879     imgf.rowPadding = OWF_Image_GetFormatPadding(pixelFormat);
  1880     stride = OWF_Image_GetStride(width, &imgf, 0);
  1881 
  1882     OWF_ASSERT (width > 0 && height > 0);
  1883 
  1884     if (stride == 0)
  1885     {
  1886         return NULL;
  1887     }
  1888 
  1889     if (dc)
  1890         {
  1891         return OWF_DisplayContext_ScratchBuffer_Allocate(dc, height * stride);
  1892         }
  1893     
  1894     return xalloc(1, height * stride);
  1895 }
  1896 
  1897 /*----------------------------------------------------------------------------*/
  1898 OWF_API_CALL void
  1899 OWF_Image_FreeData(OWF_DISPCTX dc, void** data)
  1900 {
  1901     DPRINT(("OWF_Image_FreeData"));
  1902 
  1903     if (*data)
  1904     {
  1905     if (dc)
  1906         {
  1907         OWF_DisplayContext_ScratchBuffer_Destroy(dc, *data);
  1908         }
  1909     else
  1910         {
  1911         xfree(*data);
  1912         }
  1913     }
  1914     *data = NULL;
  1915 }
  1916 
  1917 /*----------------------------------------------------------------------------*/
  1918 OWF_API_CALL OWFint
  1919 OWF_Image_GetFormatPixelSize(OWF_PIXEL_FORMAT format)
  1920 {
  1921     DPRINT(("OWF_Image_GetFormatPixelSize"));
  1922 
  1923     switch (format)
  1924     {
  1925         case OWF_IMAGE_ARGB_INTERNAL:
  1926         {
  1927             return sizeof(OWFpixel);
  1928         }
  1929 
  1930         case OWF_IMAGE_ARGB8888:
  1931         case OWF_IMAGE_XRGB8888:
  1932         case OWF_IMAGE_L32:
  1933         {
  1934             return 4;
  1935         }
  1936 
  1937         case OWF_IMAGE_RGB888:
  1938         {
  1939             return 3;
  1940         }
  1941 
  1942         case OWF_IMAGE_RGB565:
  1943         case OWF_IMAGE_L16:
  1944         {
  1945             return 2;
  1946         }
  1947 
  1948         case OWF_IMAGE_L8:
  1949         {
  1950             return 1;
  1951         }
  1952 
  1953         case OWF_IMAGE_L1:
  1954         {
  1955             /* Use negative numbers for divisor, e.g., -8 = 1/8. */
  1956             /* L1 is 1 bit alpha, LSB->MSB, each row padded to 32-bit
  1957              * boundary. */
  1958             return -8;
  1959         }
  1960         default:
  1961         {
  1962             return 0;
  1963         }
  1964     }
  1965 }
  1966 
  1967 /*----------------------------------------------------------------------------*/
  1968 OWF_API_CALL OWFint
  1969 OWF_Image_GetFormatPadding(OWF_PIXEL_FORMAT format)
  1970 {
  1971     OWFint                  padding = 1;
  1972 
  1973     DPRINT(("OWF_Image_GetFormatPadding"));
  1974 
  1975     switch (format)
  1976     {
  1977         case OWF_IMAGE_ARGB_INTERNAL:
  1978         {
  1979             padding = sizeof(OWFpixel);
  1980             break;
  1981         }
  1982 
  1983         case OWF_IMAGE_ARGB8888:
  1984         case OWF_IMAGE_XRGB8888:
  1985         case OWF_IMAGE_L32:
  1986         {
  1987             padding = 4;
  1988             break;
  1989         }
  1990 
  1991         /*
  1992         case OWF_IMAGE_RGB888:
  1993         {
  1994             return 3;
  1995         }
  1996         */
  1997 
  1998         case OWF_IMAGE_RGB565:
  1999         case OWF_IMAGE_L16:
  2000         {
  2001             padding = 2;
  2002             break;
  2003         }
  2004 
  2005         case OWF_IMAGE_L8:
  2006         {
  2007             padding = 1;
  2008             break;
  2009         }
  2010 
  2011         case OWF_IMAGE_L1:
  2012         {
  2013             /* Use negative numbers for divisor, e.g., -8 = 1/8. */
  2014             /* L1 is 1 bit alpha, LSB->MSB, each row padded to 32-bit
  2015              * boundary. */
  2016             padding = 4;
  2017             break;
  2018         }
  2019         default:
  2020         {
  2021 			OWF_ASSERT(0);
  2022             break;
  2023         }
  2024     }
  2025 
  2026 
  2027     return padding;
  2028 }
  2029 
  2030 /*----------------------------------------------------------------------------*/
  2031 OWF_API_CALL void
  2032 OWF_Image_SwapWidthAndHeight(OWF_IMAGE* image)
  2033 {
  2034     DPRINT(("OWF_Image_SwapWidthAndHeight"));
  2035 
  2036     /* swap w & h. Note that original stride is not restored if swap back. */
  2037     image->width ^= image->height;
  2038     image->height ^= image->width;
  2039     image->width ^= image->height;
  2040 
  2041     image->stride = OWF_Image_GetStride(image->width, &image->format, 0);
  2042 }
  2043 
  2044 /*----------------------------------------------------------------------------*/
  2045 OWF_API_CALL OWFboolean
  2046 OWF_Image_ConvertMask(OWF_IMAGE* output, OWF_IMAGE* input)
  2047 {
  2048     OWFboolean              result = OWF_TRUE;
  2049     void*                   srcLinePtr;
  2050     OWFsubpixel*            dstLinePtr;
  2051     OWFint                  countY;
  2052 
  2053     DPRINT(("OWF_Image_ConvertMask:"));
  2054     DPRINT(("  Converting mask from stream format to internal 8-bit"));
  2055 
  2056     OWF_ASSERT(input);
  2057     OWF_ASSERT(output);
  2058     
  2059     srcLinePtr = input->data;
  2060     dstLinePtr = (OWFsubpixel*) output->data;    
  2061 
  2062     for (countY = input->height; countY; countY--)
  2063     {
  2064         OWFsubpixel* dstData = dstLinePtr;    
  2065     
  2066         switch (input->format.pixelFormat)
  2067         {
  2068             case OWF_IMAGE_L1:
  2069             {
  2070                 OWFint          countX;
  2071                 OWFuint8*       srcData = (OWFuint8*) srcLinePtr;
  2072     
  2073                 DPRINT(("1-bit alpha, width = %d, height = %d",
  2074                        input->width, input->height));
  2075                 
  2076                 for (countX = 0; countX < input->width; countX++)
  2077                 {
  2078                     /*
  2079                      * alpha pixel ordering is LSB -> MSB
  2080                      *
  2081                      * byte# |----- byte 0 ----|----- byte 1-----|--
  2082                      * bit#  | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
  2083                      * pix#  | 7 6 5 4 3 2 1 0 | f e d c b a 9 8 | ...
  2084                      */
  2085                     if (srcData[countX >> 3] & (1 << (countX & 7)))
  2086                     {
  2087                         dstData[countX] = OWF_FULLY_OPAQUE;
  2088                     }
  2089                     else
  2090                     {
  2091                         dstData[countX] = OWF_FULLY_TRANSPARENT;
  2092                     }
  2093                 }           
  2094                 break;
  2095             }
  2096             case OWF_IMAGE_L8:
  2097             {
  2098                 OWFint          countX;
  2099                 OWFuint8*       srcData = (OWFuint8*) srcLinePtr;
  2100     
  2101                 DPRINT(("8-bit alpha, width = %d, height = %d",
  2102                        input->width, input->height));
  2103                 
  2104                 for (countX = 0; countX < input->width; countX++)
  2105                 {
  2106                     dstData[countX] = srcData[countX] * OWF_FULLY_OPAQUE /
  2107                                  (OWFfloat) OWF_BYTE_MAX_VALUE;                
  2108                 }
  2109                 break;
  2110             }
  2111             case OWF_IMAGE_ARGB8888:
  2112             {
  2113                 /* ARGB image - take the alpha channel and discard
  2114                  * everything else */
  2115                 OWFint          countX;
  2116                 OWFuint32*      srcData = (OWFuint32*) srcLinePtr;
  2117     
  2118                 DPRINT(("32-bit ARGB, width = %d, height = %d",
  2119                        input->width, input->height));
  2120                 
  2121                 for (countX = 0; countX < input->width; countX++)
  2122                 {
  2123                     dstData[countX] = (srcData[countX] >> 24) * OWF_FULLY_OPAQUE /
  2124                                  (OWFfloat) OWF_BYTE_MAX_VALUE;          
  2125                 }
  2126                 break;
  2127             }
  2128             default:
  2129             {
  2130                 DPRINT(("Unsupported alpha format, ignoring mask"));
  2131     
  2132                 result = OWF_FALSE;
  2133                 break;
  2134             }
  2135         }
  2136         
  2137         dstLinePtr+=output->width;
  2138         /* Presumes that the stride is always whole bytes - eg. a 2x2-pixel mono 
  2139          * image takes at least 2 bytes */
  2140         srcLinePtr=(OWFuint8*)srcLinePtr+input->stride;        
  2141     }
  2142     return result;
  2143 }
  2144 
  2145 #ifdef __cplusplus
  2146 }
  2147 #endif