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