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