os/graphics/graphicscomposition/openwfcompositionengine/common/src/owfimage.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicscomposition/openwfcompositionengine/common/src/owfimage.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2147 @@
     1.4 +/* Copyright (c) 2009-2010 The Khronos Group Inc.
     1.5 + * Portions copyright (c) 2009-2010  Nokia Corporation and/or its subsidiary(-ies)
     1.6 + * 
     1.7 + * Permission is hereby granted, free of charge, to any person obtaining a
     1.8 + * copy of this software and/or associated documentation files (the
     1.9 + * "Materials"), to deal in the Materials without restriction, including
    1.10 + * without limitation the rights to use, copy, modify, merge, publish,
    1.11 + * distribute, sublicense, and/or sell copies of the Materials, and to
    1.12 + * permit persons to whom the Materials are furnished to do so, subject to
    1.13 + * the following conditions:
    1.14 + *
    1.15 + * The above copyright notice and this permission notice shall be included
    1.16 + * in all copies or substantial portions of the Materials.
    1.17 + *
    1.18 + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    1.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    1.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    1.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    1.24 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    1.25 + */
    1.26 +
    1.27 +#ifdef __cplusplus
    1.28 +extern "C"
    1.29 +{
    1.30 +#endif
    1.31 +
    1.32 +#include <string.h>
    1.33 +#include <stdlib.h>
    1.34 +#include <stdio.h>
    1.35 +#include <math.h>
    1.36 +
    1.37 +#include "owfobject.h"
    1.38 +#include "owfimage.h"
    1.39 +#include "owfutils.h"
    1.40 +#include "owfmemory.h"
    1.41 +#include "owfdebug.h"
    1.42 +#include "owfdisplaycontextgeneral.h"
    1.43 +
    1.44 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
    1.45 +#define roundSubPixel(p) ((OWFuint32)((p) + 0.5f))
    1.46 +#else
    1.47 +#define roundSubPixel(p) (p)
    1.48 +#endif
    1.49 +
    1.50 +
    1.51 +/*----------------------------------------------------------------------------*/
    1.52 +OWF_API_CALL void
    1.53 +OWF_IMAGE_Ctor(void* self)
    1.54 +{
    1.55 +    DPRINT(("OWF_IMAGE_Ctor"));
    1.56 +
    1.57 +    self = self;
    1.58 +}
    1.59 +
    1.60 +/*----------------------------------------------------------------------------*/
    1.61 +OWF_API_CALL void
    1.62 +OWF_IMAGE_Dtor(void* self)
    1.63 +{
    1.64 +    OWF_IMAGE* image;
    1.65 +
    1.66 +    DPRINT(("OWF_IMAGE_Dtor"));
    1.67 +
    1.68 +    image = (OWF_IMAGE*)self;
    1.69 +
    1.70 +    if (image && image->data)
    1.71 +    {
    1.72 +        if (!image->foreign)
    1.73 +        {
    1.74 +            OWF_Image_FreeData(0, &image->data);
    1.75 +        }
    1.76 +    }
    1.77 +
    1.78 +    if (image)
    1.79 +    {
    1.80 +        memset(image, 0, sizeof(OWF_IMAGE));
    1.81 +    }
    1.82 +}
    1.83 +
    1.84 +/*----------------------------------------------------------------------------*/
    1.85 +static OWFfloat
    1.86 +NonLinear(OWFfloat x)
    1.87 +{
    1.88 +    if (x <= 0.00304f)
    1.89 +    {
    1.90 +        return 12.92f * x;
    1.91 +    }
    1.92 +    return 1.0556f * pow(x, 1.f/2.4f) - 0.0556f;
    1.93 +}
    1.94 +
    1.95 +/*----------------------------------------------------------------------------*/
    1.96 +static OWFfloat
    1.97 +Linear(OWFfloat x)
    1.98 +{
    1.99 +    if (x <= 0.03928)
   1.100 +    {
   1.101 +        return x / 12.92f;
   1.102 +    }
   1.103 +    return pow((x + 0.0556f) / 1.0556f, 2.4f);
   1.104 +}
   1.105 +
   1.106 +/*----------------------------------------------------------------------------*/
   1.107 +OWF_API_CALL void
   1.108 +OWF_Image_NonLinearizeData(OWF_IMAGE* image)\
   1.109 +{
   1.110 +    OWFpixel*            ptr;
   1.111 +    OWFint               count;
   1.112 +
   1.113 +    DPRINT(("OWF_Image_NonLinearizeData"));
   1.114 +
   1.115 +    OWF_ASSERT(image != NULL && image->data != NULL);
   1.116 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.117 +
   1.118 +    if (!image->format.linear)
   1.119 +    {
   1.120 +        return;
   1.121 +    }
   1.122 +
   1.123 +    ptr = (OWFpixel*) image->data;
   1.124 +    count = image->width * image->height;
   1.125 +
   1.126 +    while (count > 0)
   1.127 +    {
   1.128 +        ptr->color.red   = (OWFsubpixel) NonLinear(ptr->color.red /
   1.129 +                               OWF_RED_MAX_VALUE) * OWF_RED_MAX_VALUE;
   1.130 +        ptr->color.green = (OWFsubpixel) NonLinear(ptr->color.green /
   1.131 +                               OWF_GREEN_MAX_VALUE) * OWF_GREEN_MAX_VALUE;
   1.132 +        ptr->color.blue  = (OWFsubpixel) NonLinear(ptr->color.blue /
   1.133 +                               OWF_BLUE_MAX_VALUE) * OWF_BLUE_MAX_VALUE;
   1.134 +
   1.135 +        --count;
   1.136 +        ptr++;
   1.137 +    }
   1.138 +
   1.139 +    image->format.linear = OWF_FALSE;
   1.140 +}
   1.141 +
   1.142 +/*----------------------------------------------------------------------------*/
   1.143 +OWF_API_CALL void
   1.144 +OWF_Image_LinearizeData(OWF_IMAGE* image)
   1.145 +{
   1.146 +    OWFpixel*               ptr;
   1.147 +    OWFuint                 count;
   1.148 +
   1.149 +    DPRINT(("OWF_Image_LinearizeData"));
   1.150 +
   1.151 +    OWF_ASSERT(image != NULL && image->data != NULL);
   1.152 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.153 +
   1.154 +    if (image->format.linear)
   1.155 +    {
   1.156 +        return;
   1.157 +    }
   1.158 +
   1.159 +    ptr = (OWFpixel*) image->data;
   1.160 +    count = image->width * image->height;
   1.161 +
   1.162 +    while (count > 0)
   1.163 +    {
   1.164 +        ptr->color.red   = (OWFsubpixel) Linear(ptr->color.red /
   1.165 +                               OWF_RED_MAX_VALUE) * OWF_RED_MAX_VALUE;
   1.166 +        ptr->color.green = (OWFsubpixel) Linear(ptr->color.green /
   1.167 +                               OWF_GREEN_MAX_VALUE) * OWF_GREEN_MAX_VALUE;
   1.168 +        ptr->color.blue  = (OWFsubpixel) Linear(ptr->color.blue /
   1.169 +                               OWF_BLUE_MAX_VALUE) * OWF_BLUE_MAX_VALUE;
   1.170 +
   1.171 +        --count;
   1.172 +        ptr += image->pixelSize;
   1.173 +    }
   1.174 +
   1.175 +    image->format.linear = OWF_TRUE;
   1.176 +
   1.177 +}
   1.178 +
   1.179 +/*----------------------------------------------------------------------------*/
   1.180 +#define GAMMA(color, max, gamma) (max * pow(color/max, gamma))
   1.181 +
   1.182 +OWF_API_CALL void
   1.183 +OWF_Image_Gamma(OWF_IMAGE* image, OWFfloat gamma)
   1.184 +{
   1.185 +    OWFpixel*            ptr;
   1.186 +    OWFint               count;
   1.187 +
   1.188 +    DPRINT(("OWF_Image_Gamma"));
   1.189 +
   1.190 +    OWF_ASSERT(image != NULL && image->data != NULL);
   1.191 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.192 +
   1.193 +    if (gamma == 1.0f)
   1.194 +    {
   1.195 +        return;
   1.196 +    }
   1.197 +
   1.198 +    ptr = (OWFpixel*) image->data;
   1.199 +    count = image->width * image->height;
   1.200 +
   1.201 +    while (count > 0)
   1.202 +    {
   1.203 +        ptr->color.red   =
   1.204 +            (OWFsubpixel) GAMMA(ptr->color.red, OWF_RED_MAX_VALUE, gamma);
   1.205 +        ptr->color.green =
   1.206 +            (OWFsubpixel) GAMMA(ptr->color.green, OWF_GREEN_MAX_VALUE, gamma);
   1.207 +        ptr->color.blue  =
   1.208 +            (OWFsubpixel) GAMMA(ptr->color.blue, OWF_BLUE_MAX_VALUE, gamma);
   1.209 +
   1.210 +        --count;
   1.211 +        ptr++;
   1.212 +    }
   1.213 +}
   1.214 +
   1.215 +/*----------------------------------------------------------------------------*/
   1.216 +OWF_API_CALL void
   1.217 +OWF_Image_EdgeReplication(OWF_IMAGE* image)
   1.218 +{
   1.219 +    OWFint          y;
   1.220 +    OWFint          copyStride;
   1.221 +    OWFuint8*       srcPtr      = NULL;
   1.222 +    OWFuint8*       dstPtr      = NULL;
   1.223 +    
   1.224 +    DPRINT(("OWF_Image_EdgeReplication"));
   1.225 +
   1.226 +    OWF_ASSERT(image);
   1.227 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.228 +    OWF_ASSERT(image->width >= 3 && image->height >= 3);
   1.229 +    
   1.230 +    copyStride = OWF_Image_GetStride(image->width, &image->format, 0);
   1.231 +    
   1.232 +    /* top side replication */
   1.233 +    srcPtr = (OWFuint8*) image->data;
   1.234 +    srcPtr += 1 * image->stride + 0 * image->pixelSize;
   1.235 +    dstPtr = (OWFuint8*) image->data;
   1.236 +
   1.237 +    memcpy(dstPtr, srcPtr, copyStride);
   1.238 +    
   1.239 +    /* bottom side replication */
   1.240 +    srcPtr = (OWFuint8*) image->data;
   1.241 +    srcPtr += (image->height-2) * image->stride + 0 * image->pixelSize;        
   1.242 +    dstPtr = (OWFuint8*) image->data;
   1.243 +    dstPtr += (image->height-1) * image->stride + 0 * image->pixelSize;
   1.244 +    
   1.245 +    memcpy(dstPtr, srcPtr, copyStride);
   1.246 +    
   1.247 +    /* left side replication */
   1.248 +    for (y = 0; y < image->height; y++)
   1.249 +    {
   1.250 +        OWF_Image_SetPixel(image, 0, y, OWF_Image_GetPixelPtr(image, 1, y));
   1.251 +    }
   1.252 +    
   1.253 +    /* right side replication */
   1.254 +    for (y = 0; y < image->height; y++)
   1.255 +    {
   1.256 +        OWF_Image_SetPixel(image, image->width-1, y, OWF_Image_GetPixelPtr(image,
   1.257 +                                                              image->width-2,
   1.258 +                                                              y));
   1.259 +    }   
   1.260 +    
   1.261 +}
   1.262 +
   1.263 +/*----------------------------------------------------------------------------*/
   1.264 +OWF_API_CALL OWFboolean
   1.265 +OWF_Image_SourceFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src)
   1.266 +{
   1.267 +    OWFint      countY, widthDiff, heightDiff;
   1.268 +    void*       srcLinePtr;
   1.269 +    OWFpixel*   dstLinePtr;
   1.270 +    OWFboolean  replicateEdges = OWF_FALSE;
   1.271 +#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.272 +    OWFint      widthBytes;
   1.273 +#endif
   1.274 +
   1.275 +    DPRINT(("OWF_Image_SourceFormatConversion"));
   1.276 +
   1.277 +    OWF_ASSERT(dst != 0 && dst->data != NULL);
   1.278 +    OWF_ASSERT(src != 0 && src->data != NULL);
   1.279 +    OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.280 +    OWF_ASSERT(dst->stride == OWF_Image_GetStride(dst->width, &dst->format, 0));
   1.281 +    
   1.282 +    srcLinePtr = src->data;
   1.283 +    dstLinePtr = (OWFpixel*) dst->data;    
   1.284 +    
   1.285 +    /* dst image must either be the same size as the src image or 2 pixels 
   1.286 +       bigger (enough space to perform edge replication) */
   1.287 +    if (dst->width != src->width || dst->height != src->height)
   1.288 +    {
   1.289 +        widthDiff = dst->width - src->width;
   1.290 +        heightDiff = dst->height - src->height;
   1.291 +        
   1.292 +        if (widthDiff == 2 && heightDiff == 2)
   1.293 +        {
   1.294 +            replicateEdges = OWF_TRUE;   
   1.295 +            /* start of the destination buffer should have a 1 pixel offset */
   1.296 +            dstLinePtr = (OWFpixel*) dst->data + 1 * dst->width + 1;
   1.297 +        }
   1.298 +        else
   1.299 +        {
   1.300 +            return OWF_FALSE;
   1.301 +        }
   1.302 +    }
   1.303 +
   1.304 +    if (dst->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
   1.305 +    {
   1.306 +        return OWF_FALSE;
   1.307 +    }
   1.308 +
   1.309 +#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.310 +    widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
   1.311 +#endif
   1.312 +
   1.313 +    for (countY = src->height; countY; countY--)
   1.314 +    {
   1.315 +        OWFint count = src->width;
   1.316 +        OWFpixel* dstPtr = dstLinePtr;
   1.317 +    
   1.318 +        switch (src->format.pixelFormat)
   1.319 +        {
   1.320 +            case OWF_IMAGE_ARGB8888:
   1.321 +            {
   1.322 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.323 +                OWFuint32* srcPtr = (OWFuint32*) srcLinePtr;
   1.324 +    
   1.325 +                while (count > 0)
   1.326 +                {
   1.327 +                    dstPtr->color.alpha = (OWFsubpixel)
   1.328 +                        OWF_ALPHA_MAX_VALUE * ((*srcPtr & ARGB8888_ALPHA_MASK) >> ARGB8888_ALPHA_SHIFT) / OWF_BYTE_MAX_VALUE;
   1.329 +                    dstPtr->color.red   = (OWFsubpixel)
   1.330 +                        OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE;
   1.331 +                    dstPtr->color.green = (OWFsubpixel)
   1.332 +                        OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK)>> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE;
   1.333 +                    dstPtr->color.blue  = (OWFsubpixel)
   1.334 +                        OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE;
   1.335 +                    dstPtr ++;
   1.336 +                    srcPtr ++;
   1.337 +                    count--;
   1.338 +                }
   1.339 +#else
   1.340 +                memcpy(dstLinePtr, srcLinePtr, widthBytes);
   1.341 +#endif
   1.342 +                break;
   1.343 +            }
   1.344 +    
   1.345 +            case OWF_IMAGE_XRGB8888:
   1.346 +            {
   1.347 +                OWFuint32* srcPtr = (OWFuint32*) srcLinePtr;
   1.348 +                
   1.349 +                while (count > 0)
   1.350 +                {
   1.351 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.352 +                    dstPtr->color.alpha = OWF_FULLY_OPAQUE;
   1.353 +                    dstPtr->color.red   = (OWFsubpixel)
   1.354 +                        OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE;
   1.355 +                    dstPtr->color.green = (OWFsubpixel)
   1.356 +                        OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK) >> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE;
   1.357 +                    dstPtr->color.blue  = (OWFsubpixel)
   1.358 +                        OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE;
   1.359 +#else
   1.360 +                    *(OWFuint32*)dstPtr = *srcPtr | ARGB8888_ALPHA_MASK;
   1.361 +#endif
   1.362 +                    dstPtr ++;
   1.363 +                    srcPtr ++;
   1.364 +                    count--;
   1.365 +                }
   1.366 +                break;
   1.367 +            }
   1.368 +    
   1.369 +            case OWF_IMAGE_RGB565:
   1.370 +            {
   1.371 +                OWFfloat tmp;
   1.372 +                OWFuint16* srcPtr = (OWFuint16*) srcLinePtr;
   1.373 +                
   1.374 +                while (count > 0)
   1.375 +                {
   1.376 +                    /*
   1.377 +                     * Formula for converting channel value is:
   1.378 +                     * Each channel is multiplied by (2^d - 1)/(2^s -1)
   1.379 +                     * where d is dest channel bits and s is source channel bits.
   1.380 +                     */
   1.381 +                    dstPtr->color.alpha = (OWFsubpixel) OWF_FULLY_OPAQUE;
   1.382 +    
   1.383 +                    tmp = (OWFfloat)((*srcPtr & RGB565_RED_MASK) >> RGB565_RED_SHIFT);
   1.384 +                    dstPtr->color.red   = (OWFsubpixel)OWF_RED_MAX_VALUE * tmp / 31.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
   1.385 +    
   1.386 +                    tmp = (OWFfloat)((*srcPtr & RGB565_GREEN_MASK) >> RGB565_GREEN_SHIFT);
   1.387 +                    dstPtr->color.green = (OWFsubpixel)OWF_GREEN_MAX_VALUE * tmp / 63.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
   1.388 +    
   1.389 +                    tmp = (OWFfloat)(*srcPtr & RGB565_BLUE_MASK);
   1.390 +                    dstPtr->color.blue  = (OWFsubpixel)OWF_BLUE_MAX_VALUE * tmp / 31.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
   1.391 +    
   1.392 +                    dstPtr ++;
   1.393 +                    srcPtr ++;
   1.394 +                    count--;
   1.395 +                }
   1.396 +                break;
   1.397 +            }
   1.398 +    
   1.399 +            default:
   1.400 +            {
   1.401 +                return OWF_FALSE; /* source format not supported */
   1.402 +            }
   1.403 +        }
   1.404 +        
   1.405 +        dstLinePtr+=dst->width;
   1.406 +        srcLinePtr=(OWFuint8*)srcLinePtr+src->stride;
   1.407 +    }
   1.408 +    
   1.409 +    if (replicateEdges)
   1.410 +    {
   1.411 +        OWF_Image_EdgeReplication(dst);
   1.412 +    }
   1.413 +
   1.414 +    return OWF_TRUE;
   1.415 +}
   1.416 +
   1.417 +/*----------------------------------------------------------------------------*/
   1.418 +OWF_PUBLIC OWFint
   1.419 +OWF_Image_GetStride(OWFint width, const OWF_IMAGE_FORMAT* format, OWFint minimumStride)
   1.420 +{
   1.421 +    OWFint                  size;
   1.422 +    OWFint                  pixelSize;
   1.423 +
   1.424 +    DPRINT(("OWF_Image_GetStride"));
   1.425 +
   1.426 +    OWF_ASSERT(format);
   1.427 +
   1.428 +    pixelSize = OWF_Image_GetFormatPixelSize(format->pixelFormat);
   1.429 +
   1.430 +    if (pixelSize < 0)
   1.431 +    {
   1.432 +        /* negative pixelSize means that pixel size is a fraction
   1.433 +         * (1/-pixelSize) of a byte, e.g. -8 means pixel has size
   1.434 +         * of one bit. */
   1.435 +
   1.436 +        size = (width + 1) / -pixelSize;
   1.437 +    }
   1.438 +    else
   1.439 +    {
   1.440 +        size = width * pixelSize;
   1.441 +    }
   1.442 +    if (size<minimumStride)
   1.443 +    {
   1.444 +        size=minimumStride;
   1.445 +    }
   1.446 +    if (format->rowPadding)
   1.447 +    {
   1.448 +        size += format->rowPadding - 1;
   1.449 +        size -= size % format->rowPadding;
   1.450 +    }
   1.451 +    return size;
   1.452 +}
   1.453 +
   1.454 +/*----------------------------------------------------------------------------*/
   1.455 +OWF_API_CALL OWFboolean
   1.456 +OWF_Image_IsValidDestinationFormat(OWF_IMAGE_FORMAT* format)
   1.457 +{
   1.458 +    DPRINT(("OWF_Image_IsValidDestinationFormat"));
   1.459 +
   1.460 +    switch (format->pixelFormat)
   1.461 +    {
   1.462 +        case OWF_IMAGE_ARGB8888:
   1.463 +        {
   1.464 +            return OWF_TRUE;
   1.465 +        }
   1.466 +        case OWF_IMAGE_XRGB8888:
   1.467 +        {
   1.468 +            return OWF_TRUE;
   1.469 +        }
   1.470 +#ifdef SUPPORT_565_OUTPUT
   1.471 +        case OWF_IMAGE_RGB565:
   1.472 +        {
   1.473 +            return OWF_TRUE;
   1.474 +        }
   1.475 +#endif
   1.476 +        default:
   1.477 +        {
   1.478 +            return OWF_FALSE; /* destination format not supported */
   1.479 +        }
   1.480 +    }
   1.481 +}
   1.482 +
   1.483 +/*----------------------------------------------------------------------------*/
   1.484 +OWF_API_CALL OWFboolean
   1.485 +OWF_Image_DestinationFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src)
   1.486 +{
   1.487 +    OWFint                  countY;
   1.488 +    OWFuint32*              dstPtr;
   1.489 +    OWFpixel*               srcPtr;
   1.490 +#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.491 +    OWFint                  widthBytes;
   1.492 +#endif
   1.493 +
   1.494 +    DPRINT(("OWF_Image_DestinationFormatConversion"));
   1.495 +
   1.496 +    OWF_ASSERT(dst != 0 && dst->data != NULL);
   1.497 +    OWF_ASSERT(src != 0 && src->data != NULL);
   1.498 +    OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.499 +    /* Note: src->stride cannot be relied upon to be correct. Assume lines are contiguous. */
   1.500 +
   1.501 +    if (src->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
   1.502 +    {
   1.503 +        return OWF_FALSE;
   1.504 +    }
   1.505 +
   1.506 +    /* src and data must have equal amount of pixels */
   1.507 +    if (dst->width != src->width || dst->height != src->height)
   1.508 +    {
   1.509 +        return OWF_FALSE;
   1.510 +    }
   1.511 +
   1.512 +    dstPtr = (OWFuint32*) dst->data;
   1.513 +    srcPtr = (OWFpixel*) src->data;
   1.514 +
   1.515 +    if (dst->format.premultiplied && !src->format.premultiplied)
   1.516 +    {
   1.517 +        OWF_Image_PremultiplyAlpha(src);
   1.518 +    }
   1.519 +    else if (!dst->format.premultiplied && src->format.premultiplied)
   1.520 +    {
   1.521 +        OWF_Image_UnpremultiplyAlpha(src);
   1.522 +    }
   1.523 +
   1.524 +#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.525 +    widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
   1.526 +#endif
   1.527 +
   1.528 +    for (countY = 0; countY < src->height; countY++)
   1.529 +    {   
   1.530 +        OWFuint8* destination = (OWFuint8*) dst->data;
   1.531 +        destination += countY*dst->stride;
   1.532 +        dstPtr = (OWFuint32*) destination;    
   1.533 +    
   1.534 +        switch (dst->format.pixelFormat)
   1.535 +        {
   1.536 +            case OWF_IMAGE_ARGB8888:
   1.537 +            {
   1.538 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.539 +                OWFint countX;
   1.540 +                OWFuint32 dstPixel = 0;               
   1.541 +                
   1.542 +                for (countX = 0; countX < src->width; countX++)
   1.543 +                {
   1.544 +                    dstPixel  = ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.alpha / OWF_ALPHA_MAX_VALUE)) <<
   1.545 +                                ARGB8888_ALPHA_SHIFT);
   1.546 +                    dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE))   <<
   1.547 +                                ARGB8888_RED_SHIFT);
   1.548 +                    dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) <<
   1.549 +                                ARGB8888_GREEN_SHIFT);
   1.550 +                    dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE))  <<
   1.551 +                                ARGB8888_BLUE_SHIFT);
   1.552 +                    *dstPtr = dstPixel;
   1.553 +                    dstPtr ++;
   1.554 +                    srcPtr ++;
   1.555 +                }
   1.556 +#else
   1.557 +                memcpy(dstPtr, srcPtr, widthBytes);
   1.558 +                srcPtr = (OWFpixel*)((OWFuint8*)srcPtr + widthBytes);
   1.559 +#endif
   1.560 +                break;
   1.561 +            }
   1.562 +    
   1.563 +            case OWF_IMAGE_XRGB8888:
   1.564 +            {
   1.565 +                OWFint countX;
   1.566 +                OWFuint32 dstPixel = 0;
   1.567 +                
   1.568 +                for (countX = 0; countX < src->width; countX++)
   1.569 +                {
   1.570 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
   1.571 +                    dstPixel  = ARGB8888_ALPHA_MASK;
   1.572 +                    dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE))   <<
   1.573 +                                ARGB8888_RED_SHIFT);
   1.574 +                    dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) <<
   1.575 +                                ARGB8888_GREEN_SHIFT);
   1.576 +                    dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE))  <<
   1.577 +                                ARGB8888_BLUE_SHIFT);
   1.578 +#else
   1.579 +                    dstPixel = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK;
   1.580 +#endif
   1.581 +                    *dstPtr = dstPixel;
   1.582 +                    dstPtr ++;
   1.583 +                    srcPtr ++;
   1.584 +                }
   1.585 +                break;
   1.586 +            }
   1.587 +    
   1.588 +            default:
   1.589 +            {
   1.590 +                return OWF_FALSE; /* destination format not supported */
   1.591 +            }
   1.592 +        }
   1.593 +    }
   1.594 +
   1.595 +    return OWF_TRUE;
   1.596 +}
   1.597 +
   1.598 +/*----------------------------------------------------------------------------*/
   1.599 +OWF_API_CALL void
   1.600 +OWF_Image_Init(OWF_IMAGE* image)
   1.601 +{
   1.602 +    DPRINT(("OWF_Image_Init"));
   1.603 +
   1.604 +    OWF_ASSERT(NULL != image);
   1.605 +    memset(image, 0, sizeof(OWF_IMAGE));
   1.606 +}
   1.607 +
   1.608 +/*----------------------------------------------------------------------------*/
   1.609 +OWF_PUBLIC OWF_IMAGE*
   1.610 +OWF_Image_Create(OWFint width,
   1.611 +                 OWFint height,
   1.612 +                 const OWF_IMAGE_FORMAT* format,
   1.613 +                 void* buffer,
   1.614 +                 OWFint minimumStride
   1.615 +                 )
   1.616 +{
   1.617 +    OWF_IMAGE*      image;
   1.618 +
   1.619 +    DPRINT(("OWF_Image_Create"));
   1.620 +
   1.621 +    image = CREATE(OWF_IMAGE);
   1.622 +
   1.623 +    if (image)
   1.624 +    {
   1.625 +
   1.626 +        image->format.pixelFormat   = format->pixelFormat;
   1.627 +        image->format.linear        = format->linear;
   1.628 +        image->format.premultiplied = format->premultiplied;
   1.629 +        image->format.rowPadding    = format->rowPadding;
   1.630 +
   1.631 +        image->pixelSize    = OWF_Image_GetFormatPixelSize(format->pixelFormat);
   1.632 +        image->width        = width;
   1.633 +        image->height       = height;
   1.634 +
   1.635 +        /* stride is row length in bytes (aligned according to image format) */
   1.636 +        image->stride = OWF_Image_GetStride(width, &image->format, minimumStride);
   1.637 +        image->foreign  = (buffer) ? OWF_TRUE : OWF_FALSE;
   1.638 +        image->dataMax = image->stride * height;
   1.639 +
   1.640 +        DPRINT(("OWF_Image_Create:"));
   1.641 +        DPRINT(("  Pixel format     = %x", format->pixelFormat));
   1.642 +        DPRINT(("  Linear           = %d", format->linear));
   1.643 +        DPRINT(("  Premultiplied    = %d", format->premultiplied));
   1.644 +        DPRINT(("  Row alignment    = %d bytes", format->rowPadding));
   1.645 +        DPRINT(("  Pixel size       = %d", image->pixelSize));
   1.646 +        DPRINT(("  Width            = %d", image->width));
   1.647 +        DPRINT(("  Height           = %d", image->height));
   1.648 +        DPRINT(("  Stride           = %d", image->stride));
   1.649 +        DPRINT(("  Foreign data     = %d", image->foreign));
   1.650 +        DPRINT(("  Data size        = %d", image->dataMax));
   1.651 +        if (image->dataMax > 0)
   1.652 +        {
   1.653 +            image->data = (image->foreign) ? (buffer) :
   1.654 +                OWF_Image_AllocData(0, width, height, format->pixelFormat);
   1.655 +        }
   1.656 +        else
   1.657 +        {
   1.658 +            /* either overflow occured or width/height is zero */
   1.659 +            if (width && height)
   1.660 +            {
   1.661 +                DPRINT(("OWF_Image_Create: Overflow in image size calculation."));
   1.662 +            }
   1.663 +            else
   1.664 +            {
   1.665 +                DPRINT(("OWF_Image_Create: width or height is zero."));
   1.666 +            }
   1.667 +        }
   1.668 +    }
   1.669 +
   1.670 +    if (!(image && image->data && (image->dataMax > 0)))
   1.671 +    {
   1.672 +        DPRINT(("OWF_Image_Create: Image creation failed (image = %p, "
   1.673 +                "data = %p, dataSize = %d)",
   1.674 +                image, image ? (void*)(image->data) : (void*)NULL, image?image->dataMax:-1));
   1.675 +        DESTROY(image);
   1.676 +        return NULL;
   1.677 +    }
   1.678 +    return image;
   1.679 +}
   1.680 +
   1.681 +/*----------------------------------------------------------------------------*/
   1.682 +OWF_PUBLIC void OWF_Image_Destroy(OWF_IMAGE* image)
   1.683 +{
   1.684 +    if (image)
   1.685 +        {
   1.686 +        DESTROY(image);
   1.687 +        }
   1.688 +}
   1.689 +
   1.690 +
   1.691 +/*----------------------------------------------------------------------------*/
   1.692 +OWF_API_CALL OWF_IMAGE*
   1.693 +OWF_Image_Copy(const OWF_IMAGE* image)
   1.694 +{
   1.695 +    OWF_IMAGE* newImage = NULL;
   1.696 +
   1.697 +    DPRINT(("OWF_Image_Copy"));
   1.698 +
   1.699 +    OWF_ASSERT(image);
   1.700 +
   1.701 +    newImage = CREATE(OWF_IMAGE);
   1.702 +    if (newImage)
   1.703 +    {
   1.704 +        memcpy(newImage, image, sizeof(*newImage));
   1.705 +        if (!image->foreign)
   1.706 +        {
   1.707 +            newImage->data = xalloc(1, image->dataMax);
   1.708 +            if (newImage->data)
   1.709 +            {
   1.710 +                memcpy(newImage->data,
   1.711 +                       image->data,
   1.712 +                       image->height*image->stride);
   1.713 +            }
   1.714 +        }
   1.715 +    }
   1.716 +
   1.717 +    return newImage;
   1.718 +}
   1.719 +
   1.720 +/*----------------------------------------------------------------------------*/
   1.721 +OWF_API_CALL OWFboolean
   1.722 +OWF_Image_SetSize(OWF_IMAGE* image,
   1.723 +                  OWFint width,
   1.724 +                  OWFint height)
   1.725 +{
   1.726 +    OWFint                  size;
   1.727 +    OWFint                  stride;
   1.728 +
   1.729 +    DPRINT(("OWF_Image_SetSize"));
   1.730 +
   1.731 +    OWF_ASSERT(image);
   1.732 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL ||
   1.733 +            image->format.pixelFormat==OWF_IMAGE_L32);
   1.734 +    
   1.735 +    /** note that this setsize ignores any specialised stride **/
   1.736 +    stride = OWF_Image_GetStride(width, &image->format, 0);
   1.737 +    size = height * stride;
   1.738 +
   1.739 +    /* change source size if buffer have enough space */
   1.740 +    if (size > 0 && size <= image->dataMax)
   1.741 +    {
   1.742 +        image->height = height;
   1.743 +        image->width  = width;
   1.744 +        image->stride = stride;
   1.745 +        return OWF_TRUE;
   1.746 +    }
   1.747 +    return OWF_FALSE;
   1.748 +}
   1.749 +/*----------------------------------------------------------------------------*/
   1.750 +OWF_API_CALL void
   1.751 +OWF_Image_SetFlags(OWF_IMAGE* image,
   1.752 +                  OWFboolean premultiply,
   1.753 +                  OWFboolean linear)
   1.754 +    {
   1.755 +    DPRINT(("OWF_Image_SetFlags"));
   1.756 +
   1.757 +    OWF_ASSERT(image);
   1.758 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL ||
   1.759 +            image->format.pixelFormat==OWF_IMAGE_L32);
   1.760 +    image->format.linear=linear;
   1.761 +    image->format.premultiplied=premultiply;
   1.762 +    }
   1.763 +
   1.764 +/*----------------------------------------------------------------------------*/
   1.765 +OWF_API_CALL void
   1.766 +OWF_Image_SetPixelBuffer(OWF_IMAGE* image,      void* buffer)
   1.767 +    {
   1.768 +    DPRINT(("OWF_Image_SetPixelBuffer"));
   1.769 +
   1.770 +    OWF_ASSERT(image);
   1.771 +    OWF_ASSERT(buffer);
   1.772 +    OWF_ASSERT(image->foreign);
   1.773 +    if (image->foreign)
   1.774 +        {
   1.775 +        image->data=buffer;
   1.776 +        }
   1.777 +    }
   1.778 +/*----------------------------------------------------------------------------*/
   1.779 +/* NEVER USED
   1.780 +OWF_API_CALL OWFboolean
   1.781 +OWF_Image_SetPixelData(OWF_IMAGE* image,
   1.782 +                       OWFint width,
   1.783 +                       OWFint height,
   1.784 +                       const OWF_IMAGE_FORMAT* format,
   1.785 +                       void* buffer)
   1.786 +{
   1.787 +    OWFint                  size = 0,
   1.788 +                            stride = 0;
   1.789 +
   1.790 +    OWF_ASSERT(image && format);
   1.791 +
   1.792 +    stride  = OWF_Image_GetStride(width, format);
   1.793 +    size    = height * stride;
   1.794 +
   1.795 +    if (size <= 0)
   1.796 +    {
   1.797 +        return OWF_FALSE; 
   1.798 +    }
   1.799 +
   1.800 +    if (!image->foreign)
   1.801 +    {
   1.802 +        OWF_Image_FreeData(0, &image->data);
   1.803 +    }
   1.804 +
   1.805 +    image->format.pixelFormat   = format->pixelFormat;
   1.806 +    image->format.linear        = format->linear;
   1.807 +    image->format.premultiplied = format->premultiplied;
   1.808 +    image->format.rowPadding    = format->rowPadding;
   1.809 +
   1.810 +    image->pixelSize    = OWF_Image_GetFormatPixelSize(format->pixelFormat);
   1.811 +    image->width        = width;
   1.812 +    image->height       = height;
   1.813 +    image->stride       = stride;
   1.814 +    image->foreign      = OWF_TRUE;
   1.815 +    image->dataMax      = size;
   1.816 +    image->data         = buffer;
   1.817 +
   1.818 +    return OWF_TRUE;
   1.819 +}
   1.820 +*/
   1.821 +/*----------------------------------------------------------------------------*/
   1.822 +OWF_API_CALL OWFboolean
   1.823 +OWF_Image_Blit(OWF_IMAGE* dst,
   1.824 +               OWF_RECTANGLE const* dstRect,
   1.825 +               OWF_IMAGE const* src,
   1.826 +               OWF_RECTANGLE const* srcRect)
   1.827 +{
   1.828 +    OWF_RECTANGLE           bounds, rect, drect, srect;
   1.829 +    OWFint                  lineCount   = 0;
   1.830 +    OWFint                  copyStride  = 0;
   1.831 +    OWFuint8*               srcPtr      = NULL;
   1.832 +    OWFuint8*               dstPtr      = NULL;
   1.833 +
   1.834 +    DPRINT(("OWF_Image_Blit"));
   1.835 +
   1.836 +    OWF_ASSERT(dst != 0 && dst->data != NULL);
   1.837 +    OWF_ASSERT(src != 0 && src->data != NULL);
   1.838 +    OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.839 +    OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.840 +
   1.841 +    OWF_Rect_Set(&bounds, 0, 0, dst->width, dst->height);
   1.842 +    OWF_Rect_Set(&rect,
   1.843 +                 dstRect->x, dstRect->y,
   1.844 +                 srcRect->width, srcRect->height);
   1.845 +    OWF_Rect_Set(&srect,
   1.846 +                 srcRect->x, srcRect->y,
   1.847 +                 srcRect->width, srcRect->height);
   1.848 +
   1.849 +    /* clip destination rectangle against bounds */
   1.850 +    if (!OWF_Rect_Clip(&drect, &rect, &bounds))
   1.851 +    {
   1.852 +        return OWF_FALSE;
   1.853 +    }
   1.854 +
   1.855 +    if (src->pixelSize != dst->pixelSize)
   1.856 +    {
   1.857 +        DPRINT(("OWF_Image_Blit(): pixels sizes differ\n"));
   1.858 +        return OWF_FALSE;
   1.859 +    }
   1.860 +
   1.861 +    lineCount = srect.height;
   1.862 +    copyStride = srect.width * src->pixelSize;
   1.863 +
   1.864 +    /* use bytepointers in copy  - generic */
   1.865 +    srcPtr = (OWFuint8*) src->data;
   1.866 +    srcPtr += srect.y * src->stride + srect.x * src->pixelSize;
   1.867 +    dstPtr = (OWFuint8*)dst->data;
   1.868 +    dstPtr += drect.y * dst->stride + drect.x * src->pixelSize;
   1.869 +
   1.870 +    while (lineCount > 0)
   1.871 +    {
   1.872 +        --lineCount;
   1.873 +
   1.874 +        memcpy(dstPtr, srcPtr, copyStride);
   1.875 +
   1.876 +        srcPtr += src->stride;
   1.877 +        dstPtr += dst->stride;
   1.878 +    }
   1.879 +
   1.880 +    return OWF_TRUE;
   1.881 +}
   1.882 +
   1.883 +/*----------------------------------------------------------------------------*/
   1.884 +OWF_API_CALL OWFpixel*
   1.885 +OWF_Image_GetPixelPtr(OWF_IMAGE* image,
   1.886 +                      OWFint x,
   1.887 +                      OWFint y)
   1.888 +{
   1.889 +    OWF_ASSERT(image && image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.890 +    if (!(image && image->data))
   1.891 +    {
   1.892 +        return 0;
   1.893 +    }
   1.894 +
   1.895 +    x = CLAMP(x, 0, image->width-1);
   1.896 +    y = CLAMP(y, 0, image->height-1);
   1.897 +
   1.898 +    return (OWFpixel*)image->data + y * image->width  + x ;
   1.899 +}
   1.900 +
   1.901 +/*----------------------------------------------------------------------------*/
   1.902 +OWF_API_CALL void
   1.903 +OWF_Image_GetPixel(OWF_IMAGE* image,
   1.904 +                   OWFint x,
   1.905 +                   OWFint y,
   1.906 +                   OWFpixel* pixel)
   1.907 +{
   1.908 +    OWFpixel*               temp = NULL;
   1.909 +
   1.910 +    OWF_ASSERT(pixel);
   1.911 +
   1.912 +    if (!(image && image->data))
   1.913 +    {
   1.914 +        return;
   1.915 +    }
   1.916 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.917 +
   1.918 +    pixel->color.alpha = 0;
   1.919 +    pixel->color.red = 0;
   1.920 +    pixel->color.green = 0;
   1.921 +    pixel->color.blue = 0;
   1.922 +
   1.923 +    if (x < 0 || y < 0 || x >= image->width || y >= image->height)
   1.924 +    {
   1.925 +        return;
   1.926 +    }
   1.927 +
   1.928 +    temp = (OWFpixel*)image->data + y * image->width  + x;
   1.929 +
   1.930 +    pixel->color.alpha = temp->color.alpha;
   1.931 +    pixel->color.red = temp->color.red;
   1.932 +    pixel->color.green = temp->color.green;
   1.933 +    pixel->color.blue = temp->color.blue;
   1.934 +}
   1.935 +
   1.936 +/*----------------------------------------------------------------------------*/
   1.937 +OWF_API_CALL void
   1.938 +OWF_Image_SetPixel(OWF_IMAGE* image,
   1.939 +                   OWFint x,
   1.940 +                   OWFint y,
   1.941 +                   OWFpixel const* pixel)
   1.942 +{
   1.943 +    OWFpixel*               data = NULL;
   1.944 +
   1.945 +    if (!(image && image->data))
   1.946 +    {
   1.947 +        return;
   1.948 +    }
   1.949 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.950 +
   1.951 +    if(x < 0 || y < 0 || x >= image->width || y >= image->height)
   1.952 +    {
   1.953 +        return;
   1.954 +    }
   1.955 +
   1.956 +
   1.957 +    data = (OWFpixel*)image->data + y * image->width + x;
   1.958 +
   1.959 +    data->color.red = pixel->color.red;
   1.960 +    data->color.green = pixel->color.green;
   1.961 +    data->color.blue = pixel->color.blue;
   1.962 +    data->color.alpha = pixel->color.alpha;
   1.963 +}
   1.964 +
   1.965 +/*----------------------------------------------------------------------------*/
   1.966 +OWF_API_CALL OWFboolean
   1.967 +OWF_Image_PointSamplingStretchBlit(OWF_IMAGE* dst,
   1.968 +                                   OWF_RECTANGLE* dstRect,
   1.969 +                                   OWF_IMAGE* src,
   1.970 +                                   OWFfloat* srcRect)
   1.971 +{
   1.972 +    OWFint                  ox = 0, oy = 0;
   1.973 +    OWFint                  x, y;
   1.974 +
   1.975 +    DPRINT(("OWF_Image_PointSamplingStretchBlit"));
   1.976 +
   1.977 +    /* images must be valid */
   1.978 +    if (!((src != NULL) && (src->data != NULL) &&
   1.979 +          (dst != NULL) && (dst->data != NULL)))
   1.980 +    {
   1.981 +        return OWF_FALSE;
   1.982 +    }
   1.983 +    OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.984 +    OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
   1.985 +
   1.986 +    /* ditto with rectangles, too */
   1.987 +    if (!((dstRect != NULL) && (dstRect->width && dstRect->height) &&
   1.988 +          (srcRect != NULL) && (srcRect[2] && srcRect[3])))
   1.989 +    {
   1.990 +        return OWF_FALSE;
   1.991 +    }
   1.992 +
   1.993 +    /* Note: bounds check missing */
   1.994 +
   1.995 +    if (src->pixelSize != dst->pixelSize)
   1.996 +    {
   1.997 +        return OWF_FALSE;
   1.998 +    }
   1.999 +
  1.1000 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1.1001 +    {
  1.1002 +        OWFfloat                dx = 0.f, dy = 0.f; 
  1.1003 +    
  1.1004 +        /* solve scaling ratios for image */
  1.1005 +        dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width;
  1.1006 +        dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height;
  1.1007 +    
  1.1008 +        for (y = 0; y < dstRect->height; y++)
  1.1009 +        {
  1.1010 +            for (x = 0; x < dstRect->width; x++) 
  1.1011 +            {
  1.1012 +                OWFpixel*       pixel;         
  1.1013 +                
  1.1014 +                /* NOTE This code uses pixel center points to calculate distances
  1.1015 +                        and factors. Results can differ slightly when pixel corner
  1.1016 +                        coordinates are used */            
  1.1017 +                
  1.1018 +                /* coordinates of nearest pixel in original image */
  1.1019 +                ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]);
  1.1020 +                oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]);     
  1.1021 +                
  1.1022 +                pixel = OWF_Image_GetPixelPtr(src,
  1.1023 +                                              ox,
  1.1024 +                                              oy);
  1.1025 +                
  1.1026 +                OWF_Image_SetPixel(dst,
  1.1027 +                                   dstRect->x + x,
  1.1028 +                                   dstRect->y + y,
  1.1029 +                                   pixel);
  1.1030 +                
  1.1031 +            }
  1.1032 +        }
  1.1033 +    }
  1.1034 +#else
  1.1035 +    if (srcRect[0] < 0 || (srcRect[0] + srcRect[2]) > src->width ||
  1.1036 +            srcRect[1] < 0 || (srcRect[1] + srcRect[3]) > src->height)
  1.1037 +        {
  1.1038 +        /* Source rectangle out of bounds */
  1.1039 +        return OWF_FALSE;
  1.1040 +        }
  1.1041 +
  1.1042 +    if (dstRect->x < 0 || (dstRect->x + dstRect->width) > dst->width ||
  1.1043 +            dstRect->y < 0 || (dstRect->y + dstRect->height) > dst->height)
  1.1044 +        {
  1.1045 +        /* Destination rectangle out of bounds */
  1.1046 +        return OWF_FALSE;
  1.1047 +        }
  1.1048 +
  1.1049 +    {
  1.1050 +        OWFint dxFix, dyFix;
  1.1051 +        OWFint xFixStart, yFix;
  1.1052 +        OWFuint32 *dstPtr, *srcLinePtr;
  1.1053 +    
  1.1054 +/* Integer <-> 16.16 fixed point conversion macros */
  1.1055 +#define INT_TO_FIXED_PT(X) ((X) << 16)
  1.1056 +#define FIXED_PT_TO_INT(X) ((X) >> 16)
  1.1057 +    
  1.1058 +        /* Calculate scaling factors in fixed point (with rounding). */
  1.1059 +        dxFix = (OWFint)((srcRect[2] * INT_TO_FIXED_PT(1) + (dstRect->width >> 1)) / dstRect->width);
  1.1060 +        dyFix = (OWFint)((srcRect[3] * INT_TO_FIXED_PT(1) + (dstRect->height >> 1)) / dstRect->height);
  1.1061 +    
  1.1062 +        /* Calculate fixed point location in source, with half-pixel offset */
  1.1063 +        xFixStart = (OWFint)(srcRect[0] * INT_TO_FIXED_PT(1) + (dxFix >> 1));
  1.1064 +        yFix = (OWFint)(srcRect[1] * INT_TO_FIXED_PT(1) + (dyFix >> 1));
  1.1065 +    
  1.1066 +        /* Initial target address. */
  1.1067 +        dstPtr = (OWFuint32*)dst->data + dstRect->y * dst->width + dstRect->x;
  1.1068 +    
  1.1069 +        for (y = 0; y < dstRect->height; y++)
  1.1070 +        {
  1.1071 +            OWFint xFix = xFixStart;
  1.1072 +    
  1.1073 +            oy = FIXED_PT_TO_INT(yFix);
  1.1074 +            srcLinePtr = (OWFuint32*)src->data + oy * src->width;
  1.1075 +    
  1.1076 +            for (x = 0; x < dstRect->width; x++) 
  1.1077 +            {
  1.1078 +                ox = FIXED_PT_TO_INT(xFix);
  1.1079 +                dstPtr[x] = srcLinePtr[ox];
  1.1080 +                xFix += dxFix;
  1.1081 +            }
  1.1082 +    
  1.1083 +            dstPtr += dst->width;
  1.1084 +            yFix += dyFix;
  1.1085 +        }
  1.1086 +    }
  1.1087 +#endif
  1.1088 +    return OWF_TRUE;
  1.1089 +}
  1.1090 +
  1.1091 +/*----------------------------------------------------------------------------*/
  1.1092 +OWF_API_CALL OWFboolean
  1.1093 +OWF_Image_BilinearStretchBlit(OWF_IMAGE* dst,
  1.1094 +                              OWF_RECTANGLE* dstRect,
  1.1095 +                              OWF_IMAGE* src,
  1.1096 +                              OWFfloat* srcRect)
  1.1097 +{
  1.1098 +    OWFint                  x = 0, y = 0;
  1.1099 +    OWFint                  ox = 0, oy = 0;
  1.1100 +    OWFfloat                dx = 0.f, dy = 0.f, wx = 0.f, wy = 0.f;
  1.1101 +    OWFfloat                w[2 * 2];
  1.1102 +    OWFpixel*               sample[4];
  1.1103 +    OWFpixel*               pixel = NULL;
  1.1104 +
  1.1105 +    DPRINT(("OWF_Image_BilinearStretchBlit"));
  1.1106 +
  1.1107 +    /* images must be valid */
  1.1108 +    if (!((src != NULL) && (src->data != NULL) &&
  1.1109 +          (dst != NULL) && (dst->data != NULL)))
  1.1110 +    {
  1.1111 +        return OWF_FALSE;
  1.1112 +    }
  1.1113 +    OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1.1114 +    OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1.1115 +
  1.1116 +    /* ditto with rectangles, too */
  1.1117 +    if (!((dstRect != NULL) && (dstRect->width && dstRect->height) &&
  1.1118 +          (srcRect != NULL) && (srcRect[2] && srcRect[3])))
  1.1119 +    {
  1.1120 +        return OWF_FALSE;
  1.1121 +    }
  1.1122 +
  1.1123 +    if (src->pixelSize != dst->pixelSize)
  1.1124 +    {
  1.1125 +        return OWF_FALSE;
  1.1126 +    }
  1.1127 +
  1.1128 +    /* solve scaling ratios for image */
  1.1129 +    dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width;
  1.1130 +    dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height;
  1.1131 +
  1.1132 +    for (y = 0; y < dstRect->height; y++)
  1.1133 +    {
  1.1134 +        for (x = 0; x < dstRect->width; x++)
  1.1135 +        {
  1.1136 +            OWFfloat tempOx, tempOy;            
  1.1137 +            
  1.1138 +            /* NOTE This code uses pixel center points to calculate distances
  1.1139 +                    and factors. Results can differ slightly when pixel corner
  1.1140 +                    coordinates are used */
  1.1141 +
  1.1142 +            /* coordinates of nearest pixel in original image */
  1.1143 +            tempOx = (((OWFfloat) x + 0.5) * dx) + srcRect[0];
  1.1144 +            tempOy = (((OWFfloat) y + 0.5) * dy) + srcRect[1];            
  1.1145 +            
  1.1146 +            ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]);
  1.1147 +            oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]);    
  1.1148 +
  1.1149 +            /* Distances to nearest pixel, eg. fractional part of coordinate */    
  1.1150 +            wx = (OWFfloat) ox + 0.5 - tempOx;
  1.1151 +            wy = (OWFfloat) oy + 0.5 - tempOy;
  1.1152 +
  1.1153 +            /* If distance is positive, we should use left or upper pixel for
  1.1154 +             * second nearest pixel. */
  1.1155 +            if (wx > 0.0)
  1.1156 +            {
  1.1157 +                ox--;
  1.1158 +                wx = 1.0 - wx;
  1.1159 +            }
  1.1160 +            else
  1.1161 +            {
  1.1162 +                wx = -wx; /* abs */
  1.1163 +            }
  1.1164 +
  1.1165 +            if (wy > 0.0)
  1.1166 +            {
  1.1167 +                oy--;
  1.1168 +                wy = 1.0 - wy;
  1.1169 +            }
  1.1170 +            else
  1.1171 +            {
  1.1172 +                wy = -wy;
  1.1173 +            }
  1.1174 +            
  1.1175 +            /* Calculate weights for samples */
  1.1176 +            w[0] = (1.0 - wx) * (1.0 - wy);
  1.1177 +            w[1] = wx * (1.0 - wy);
  1.1178 +            w[2] = (1.0 - wx) * wy;
  1.1179 +            w[3] = wx * wy;
  1.1180 +
  1.1181 +            /* get sample */
  1.1182 +            sample[0] = OWF_Image_GetPixelPtr(src, ox + 0, oy + 0);
  1.1183 +            sample[1] = OWF_Image_GetPixelPtr(src, ox + 1, oy + 0);
  1.1184 +            sample[2] = OWF_Image_GetPixelPtr(src, ox + 0, oy + 1);
  1.1185 +            sample[3] = OWF_Image_GetPixelPtr(src, ox + 1, oy + 1);
  1.1186 +
  1.1187 +            
  1.1188 +            /* get result pixel */
  1.1189 +            pixel = OWF_Image_GetPixelPtr(dst, x, y);
  1.1190 +
  1.1191 +            /* calculate final color */
  1.1192 +            pixel->color.red   =
  1.1193 +                sample[0]->color.red * w[0] + sample[1]->color.red * w[1] +
  1.1194 +                sample[2]->color.red * w[2] + sample[3]->color.red * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1.1195 +
  1.1196 +            pixel->color.green =
  1.1197 +                sample[0]->color.green * w[0] + sample[1]->color.green * w[1] +
  1.1198 +                sample[2]->color.green * w[2] + sample[3]->color.green * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1.1199 +
  1.1200 +            pixel->color.blue  =
  1.1201 +                sample[0]->color.blue * w[0] + sample[1]->color.blue * w[1] +
  1.1202 +                sample[2]->color.blue * w[2] + sample[3]->color.blue * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1.1203 +
  1.1204 +            pixel->color.alpha =
  1.1205 +                sample[0]->color.alpha * w[0] + sample[1]->color.alpha * w[1] +
  1.1206 +                sample[2]->color.alpha * w[2] + sample[3]->color.alpha * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
  1.1207 +        }
  1.1208 +    }
  1.1209 +    return OWF_TRUE;
  1.1210 +
  1.1211 +}
  1.1212 +
  1.1213 +/*----------------------------------------------------------------------------*/
  1.1214 +OWF_API_CALL OWFboolean
  1.1215 +OWF_Image_Stretch(OWF_IMAGE* dst,
  1.1216 +                  OWF_RECTANGLE* dstRect,
  1.1217 +                  OWF_IMAGE* src,
  1.1218 +                  OWFfloat* srcRect,
  1.1219 +                  OWF_FILTERING filter)
  1.1220 +{
  1.1221 +    OWFboolean          result = OWF_FALSE;
  1.1222 +
  1.1223 +    switch (filter)
  1.1224 +    {
  1.1225 +        case OWF_FILTER_POINT_SAMPLING:
  1.1226 +        {
  1.1227 +            result = OWF_Image_PointSamplingStretchBlit(dst, dstRect, src,
  1.1228 +                                                        srcRect);
  1.1229 +            break;
  1.1230 +        }
  1.1231 +        case OWF_FILTER_BILINEAR:
  1.1232 +        {
  1.1233 +            result = OWF_Image_BilinearStretchBlit(dst, dstRect, src, srcRect);
  1.1234 +            break;
  1.1235 +        }
  1.1236 +    }
  1.1237 +
  1.1238 +    return result;
  1.1239 +}
  1.1240 +
  1.1241 +/*----------------------------------------------------------------------------*/
  1.1242 +OWF_API_CALL void
  1.1243 +OWF_Image_Clear(OWF_IMAGE* image,
  1.1244 +                OWFsubpixel red,
  1.1245 +                OWFsubpixel green,
  1.1246 +                OWFsubpixel blue,
  1.1247 +                OWFsubpixel alpha)
  1.1248 +{
  1.1249 +    OWFint                  i, numPixels;
  1.1250 +    OWFpixel*                pixels;
  1.1251 +
  1.1252 +    DPRINT(("OWF_Image_Clear"));
  1.1253 +
  1.1254 +    OWF_ASSERT(image != 0);
  1.1255 +    OWF_ASSERT(image->data != 0);
  1.1256 +    OWF_ASSERT(image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
  1.1257 +    /* Note: image->stride cannot be relied upon to be correct. Assume lines are contiguous. */
  1.1258 +
  1.1259 +    numPixels = image->width * image->height;
  1.1260 +    pixels = (OWFpixel*) image->data;
  1.1261 +
  1.1262 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1.1263 +    for (i = 0; i < numPixels; i++)
  1.1264 +    {
  1.1265 +        pixels[i].color.red   = (OWFsubpixel) red;
  1.1266 +        pixels[i].color.green = (OWFsubpixel) green;
  1.1267 +        pixels[i].color.blue  = (OWFsubpixel) blue;
  1.1268 +        pixels[i].color.alpha = (OWFsubpixel) alpha;
  1.1269 +    }
  1.1270 +#else
  1.1271 +    if (alpha == red && alpha == green && alpha == blue)
  1.1272 +        {
  1.1273 +        /* If all four bytes are the same, just use memset */
  1.1274 +        OWFuint32 clearBytes = numPixels * sizeof(OWFuint32);
  1.1275 +
  1.1276 +        memset(pixels, alpha, clearBytes);
  1.1277 +        }
  1.1278 +    else
  1.1279 +        {
  1.1280 +        /* Otherwise assign each pixel the packed value */
  1.1281 +        OWFuint32* pixelPtr = (OWFuint32*)pixels;
  1.1282 +        OWFuint32 pixel;
  1.1283 +    
  1.1284 +        pixel = (alpha << ARGB8888_ALPHA_SHIFT) | (red << ARGB8888_RED_SHIFT) |
  1.1285 +                (green << ARGB8888_GREEN_SHIFT) | (blue << ARGB8888_BLUE_SHIFT);
  1.1286 +
  1.1287 +        for (i = 0; i < numPixels; i++)
  1.1288 +            {
  1.1289 +            pixelPtr[i] = pixel;
  1.1290 +            }
  1.1291 +        }
  1.1292 +#endif
  1.1293 +}
  1.1294 +
  1.1295 +/*----------------------------------------------------------------------------*/
  1.1296 +OWF_API_CALL void
  1.1297 +OWF_Image_PremultiplyAlpha(OWF_IMAGE* image)
  1.1298 +{
  1.1299 +    OWFint       x, y;
  1.1300 +
  1.1301 +    DPRINT(("OWF_Image_PremultiplyAlpha"));
  1.1302 +
  1.1303 +    OWF_ASSERT(image != 0);
  1.1304 +
  1.1305 +    if (image->format.premultiplied)
  1.1306 +    {
  1.1307 +        return;
  1.1308 +    }
  1.1309 +
  1.1310 +    /* only for internal format */
  1.1311 +    if (image->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
  1.1312 +    {
  1.1313 +        return;
  1.1314 +    }
  1.1315 +
  1.1316 +    for (y = 0; y < image->height; y++)
  1.1317 +    {
  1.1318 +        for (x = 0; x < image->width; x++)
  1.1319 +        {
  1.1320 +            OWFpixel* pixel;
  1.1321 +            OWFsubpixel alpha;
  1.1322 +
  1.1323 +            pixel = OWF_Image_GetPixelPtr(image, x, y);
  1.1324 +
  1.1325 +            alpha = pixel->color.alpha;
  1.1326 +
  1.1327 +            if (0 == alpha)
  1.1328 +            {
  1.1329 +                pixel->color.red =
  1.1330 +                pixel->color.green =
  1.1331 +                pixel->color.blue = 0;
  1.1332 +            }
  1.1333 +            else
  1.1334 +            {
  1.1335 +                pixel->color.red    = (pixel->color.red * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
  1.1336 +                                      OWF_ALPHA_MAX_VALUE;
  1.1337 +                pixel->color.green  = (pixel->color.green * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
  1.1338 +                                      OWF_ALPHA_MAX_VALUE;
  1.1339 +                pixel->color.blue   = (pixel->color.blue * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
  1.1340 +                                      OWF_ALPHA_MAX_VALUE;
  1.1341 +            }
  1.1342 +        }
  1.1343 +    }
  1.1344 +
  1.1345 +    image->format.premultiplied = OWF_TRUE;
  1.1346 +}
  1.1347 +
  1.1348 +/*----------------------------------------------------------------------------*/
  1.1349 +OWF_API_CALL void
  1.1350 +OWF_Image_UnpremultiplyAlpha(OWF_IMAGE* image)
  1.1351 +{
  1.1352 +    OWFint       count;
  1.1353 +    OWFpixel*    pixelPtr;
  1.1354 +
  1.1355 +    DPRINT(("OWF_Image_UnpremultiplyAlpha"));
  1.1356 +
  1.1357 +    OWF_ASSERT(image != 0);
  1.1358 +
  1.1359 +    if (!image->format.premultiplied)
  1.1360 +    {
  1.1361 +        return;
  1.1362 +    }
  1.1363 +
  1.1364 +    /* only for internal format */
  1.1365 +    if (image->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
  1.1366 +    {
  1.1367 +        return;
  1.1368 +    }
  1.1369 +
  1.1370 +    count = image->width * image->height;
  1.1371 +    pixelPtr = (OWFpixel*)image->data;
  1.1372 +
  1.1373 +    while (count > 0)
  1.1374 +    {
  1.1375 +
  1.1376 +        OWFsubpixel a = pixelPtr->color.alpha;
  1.1377 +
  1.1378 +        #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1.1379 +			OWF_ASSERT(a <= OWF_ALPHA_MAX_VALUE && a >= OWF_ALPHA_MIN_VALUE);
  1.1380 +		#endif
  1.1381 +
  1.1382 +        if (a > OWF_ALPHA_MIN_VALUE)
  1.1383 +        {
  1.1384 +            OWFsubpixel r = pixelPtr->color.red   * OWF_RED_MAX_VALUE / a;
  1.1385 +            OWFsubpixel g = pixelPtr->color.green * OWF_GREEN_MAX_VALUE / a;
  1.1386 +            OWFsubpixel b = pixelPtr->color.blue  * OWF_BLUE_MAX_VALUE / a;
  1.1387 +
  1.1388 +            pixelPtr->color.red   = r;
  1.1389 +            pixelPtr->color.green = g;
  1.1390 +            pixelPtr->color.blue  = b;
  1.1391 +
  1.1392 +            --count;
  1.1393 +            pixelPtr++;
  1.1394 +        }
  1.1395 +    }
  1.1396 +
  1.1397 +    image->format.premultiplied = OWF_TRUE;
  1.1398 +}
  1.1399 +
  1.1400 +/*----------------------------------------------------------------------------*/
  1.1401 +OWF_API_CALL void
  1.1402 +OWF_Image_Rotate(OWF_IMAGE* dst,
  1.1403 +                 OWF_IMAGE* src,
  1.1404 +                 OWF_ROTATION rotation)
  1.1405 +{
  1.1406 +    OWFint                  ox = 0, oy = 0,
  1.1407 +                            w = 0, h = 0,
  1.1408 +                            x = 0, y = 0;
  1.1409 +    OWFint                  xx = 0, xy = 0,
  1.1410 +                            yx = 0, yy = 0;
  1.1411 +
  1.1412 +    DPRINT(("OWF_Image_Rotate"));
  1.1413 +
  1.1414 +    OWF_ASSERT(src && src->data);
  1.1415 +    OWF_ASSERT(dst && dst->data);
  1.1416 +    OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1.1417 +    OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1.1418 +
  1.1419 +    w = src->width;
  1.1420 +    h = src->height;
  1.1421 +
  1.1422 +    switch (rotation)
  1.1423 +    {
  1.1424 +        case OWF_ROTATION_0:
  1.1425 +        {
  1.1426 +            /*
  1.1427 +             * origin: (0, 0)
  1.1428 +             * x-axis: (1, 0)
  1.1429 +             * y-axis: (0, 1)
  1.1430 +             */
  1.1431 +            ox = 0;
  1.1432 +            oy = 0;
  1.1433 +            xx = 1;
  1.1434 +            xy = 0;
  1.1435 +            yx = 0;
  1.1436 +            yy = 1;
  1.1437 +            break;
  1.1438 +        }
  1.1439 +        case OWF_ROTATION_90:
  1.1440 +        {
  1.1441 +            /*
  1.1442 +             * origin: (height-1, 0)
  1.1443 +             * x-axis: (0, 1)
  1.1444 +             * y-axis: (-1, 0)
  1.1445 +             */
  1.1446 +            ox = h - 1;
  1.1447 +            oy = 0;
  1.1448 +            xx = 0;
  1.1449 +            xy = 1;
  1.1450 +            yx = -1;
  1.1451 +            yy = 0;
  1.1452 +            break;
  1.1453 +        }
  1.1454 +        case OWF_ROTATION_180:
  1.1455 +        {
  1.1456 +            /*
  1.1457 +             * origin: (width-1, height-1)
  1.1458 +             * x-axis: (-1, 0)
  1.1459 +             * y-axis: (0, -1)
  1.1460 +             */
  1.1461 +            ox = w - 1;
  1.1462 +            oy = h - 1;
  1.1463 +            xx = -1;
  1.1464 +            xy = 0;
  1.1465 +            yx = 0;
  1.1466 +            yy = -1;
  1.1467 +            break;
  1.1468 +        }
  1.1469 +        case OWF_ROTATION_270:
  1.1470 +        {
  1.1471 +            /*
  1.1472 +             * origin: (0, height-1)
  1.1473 +             * x-axis: (0, -1)
  1.1474 +             * y-axis: (1, 0)
  1.1475 +             */
  1.1476 +            ox = 0;
  1.1477 +            oy = w - 1;
  1.1478 +            xx = 0;
  1.1479 +            xy = -1;
  1.1480 +            yx = 1;
  1.1481 +            yy = 0;
  1.1482 +            break;
  1.1483 +
  1.1484 +        }
  1.1485 +    }
  1.1486 +
  1.1487 +    for (y = 0; y < h; y++)
  1.1488 +    {
  1.1489 +        for (x = 0; x < w; x++)
  1.1490 +        {
  1.1491 +        /*
  1.1492 +         * O = [ox oy]' X = [xx xy]' Y = [yx yy]'
  1.1493 +         *
  1.1494 +         * p_dst(x_src,y_src) = O + x_src*X + y_src*Y
  1.1495 +         */
  1.1496 +        OWF_Image_SetPixel(dst,
  1.1497 +                           ox + x * xx + y * yx,
  1.1498 +                           oy + x * xy + y * yy,
  1.1499 +                           OWF_Image_GetPixelPtr(src, x, y));
  1.1500 +        }
  1.1501 +    }
  1.1502 +}
  1.1503 +
  1.1504 +/*----------------------------------------------------------------------------*/
  1.1505 +OWF_API_CALL void
  1.1506 +OWF_Image_Flip(OWF_IMAGE* image,
  1.1507 +               OWF_FLIP_DIRECTION dir)
  1.1508 +{
  1.1509 +    OWFint                  x, y;
  1.1510 +
  1.1511 +    DPRINT(("OWF_Image_Flip"));
  1.1512 +
  1.1513 +    if (!image)
  1.1514 +    {
  1.1515 +        return;
  1.1516 +    }
  1.1517 +    OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
  1.1518 +
  1.1519 +    if (dir & OWF_FLIP_VERTICALLY)
  1.1520 +    {
  1.1521 +        OWFint h = image->height/2;
  1.1522 +
  1.1523 +        for (y = 0; y < h; y++)
  1.1524 +        {
  1.1525 +            for (x = 0; x < image->width; x++)
  1.1526 +            {
  1.1527 +                OWFpixel        pix;
  1.1528 +
  1.1529 +                OWF_Image_GetPixel(image, x, y, &pix);
  1.1530 +                OWF_Image_SetPixel(image, x, y,
  1.1531 +                                   OWF_Image_GetPixelPtr(image,
  1.1532 +                                                         x,
  1.1533 +                                                         image->height - 1 - y
  1.1534 +                                                         ));
  1.1535 +                OWF_Image_SetPixel(image, x, image->height - 1 - y, &pix);
  1.1536 +            }
  1.1537 +        }
  1.1538 +    }
  1.1539 +
  1.1540 +    if (dir & OWF_FLIP_HORIZONTALLY)
  1.1541 +    {
  1.1542 +        OWFint w = image->width/2;
  1.1543 +
  1.1544 +        for (y = 0; y < image->height; y++)
  1.1545 +        {
  1.1546 +            for (x = 0; x < w; x++)
  1.1547 +            {
  1.1548 +                OWFpixel        pix;
  1.1549 +
  1.1550 +                OWF_Image_GetPixel(image, x, y, &pix);
  1.1551 +                OWF_Image_SetPixel(image, x, y,
  1.1552 +                                   OWF_Image_GetPixelPtr(image,
  1.1553 +                                                         image->width - 1 - x,
  1.1554 +                                                         y
  1.1555 +                                                         ));
  1.1556 +                OWF_Image_SetPixel(image, image->width - 1 - x, y, &pix);
  1.1557 +            }
  1.1558 +        }
  1.1559 +    }
  1.1560 +}
  1.1561 +
  1.1562 +/*----------------------------------------------------------------------------*/
  1.1563 +#define BLENDER_INNER_LOOP_BEGIN \
  1.1564 +    OWFint rowCount = drect.height; \
  1.1565 +    while (rowCount > 0) { \
  1.1566 +        OWFint colCount = drect.width; \
  1.1567 +        while (colCount > 0) {
  1.1568 +
  1.1569 +#define BLENDER_INNER_LOOP_END \
  1.1570 +            srcPtr ++; \
  1.1571 +            dstPtr ++; \
  1.1572 +            maskPtr++; \
  1.1573 +            --colCount; \
  1.1574 +        } \
  1.1575 +        srcPtr += srcLineDelta; \
  1.1576 +        dstPtr += dstLineDelta; \
  1.1577 +        maskPtr += maskLineDelta; \
  1.1578 +        --rowCount; \
  1.1579 +    }
  1.1580 +	
  1.1581 +#define BLENDER_INNER_LOOP_END_NO_MASK \
  1.1582 +            srcPtr ++; \
  1.1583 +            dstPtr ++; \
  1.1584 +            --colCount; \
  1.1585 +        } \
  1.1586 +        srcPtr += srcLineDelta; \
  1.1587 +        dstPtr += dstLineDelta; \
  1.1588 +        --rowCount; \
  1.1589 +    }
  1.1590 +
  1.1591 +#define SA srcPtr->color.alpha
  1.1592 +#define SR srcPtr->color.red
  1.1593 +#define SG srcPtr->color.green
  1.1594 +#define SB srcPtr->color.blue
  1.1595 +
  1.1596 +#define DA dstPtr->color.alpha
  1.1597 +#define DR dstPtr->color.red
  1.1598 +#define DG dstPtr->color.green
  1.1599 +#define DB dstPtr->color.blue
  1.1600 +
  1.1601 +#define MA *maskPtr
  1.1602 +#define GA blend->globalAlpha
  1.1603 +
  1.1604 +OWF_API_CALL void
  1.1605 +OWF_Image_Blend(OWF_BLEND_INFO* blend,
  1.1606 +                OWF_TRANSPARENCY transparency)
  1.1607 +{
  1.1608 +    OWF_IMAGE*              dst;
  1.1609 +    OWF_IMAGE*              src;
  1.1610 +    OWF_IMAGE*              mask;
  1.1611 +    OWF_RECTANGLE*          srcRect;
  1.1612 +    OWF_RECTANGLE*          dstRect;
  1.1613 +    OWF_RECTANGLE           bounds, srect, drect, rect;
  1.1614 +    OWFint                  srcLineDelta, dstLineDelta, maskLineDelta;
  1.1615 +    OWFpixel*               srcPtr;
  1.1616 +    OWFpixel*               dstPtr;
  1.1617 +    OWFsubpixel*            maskPtr;
  1.1618 +    
  1.1619 +    
  1.1620 +    /* preparation */
  1.1621 +    OWF_ASSERT(blend);
  1.1622 +    DPRINT(("OWF_Image_Blend: transparency = %d", transparency));
  1.1623 +    /* Mask must be set if mask-transparency is used */
  1.1624 +    OWF_ASSERT(((transparency & OWF_TRANSPARENCY_MASK) && blend->mask) ||
  1.1625 +           !(transparency & OWF_TRANSPARENCY_MASK));
  1.1626 +
  1.1627 +    OWF_ASSERT(blend->source.image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
  1.1628 +    OWF_ASSERT(blend->destination.image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
  1.1629 +    if (blend->mask)
  1.1630 +    {
  1.1631 +        OWF_ASSERT(blend->mask->format.pixelFormat == OWF_IMAGE_L32);
  1.1632 +    }
  1.1633 +    
  1.1634 +    dst     = blend->destination.image;
  1.1635 +    src     = blend->source.image;
  1.1636 +    mask    = blend->mask;
  1.1637 +    dstRect = blend->destination.rectangle;
  1.1638 +    srcRect = blend->source.rectangle;    
  1.1639 +
  1.1640 +    /* this is actually asserted above */
  1.1641 +    if (OWF_TRANSPARENCY_MASK == (transparency & OWF_TRANSPARENCY_MASK) &&
  1.1642 +        NULL == mask)
  1.1643 +    {
  1.1644 +        return;
  1.1645 +    }
  1.1646 +
  1.1647 +    OWF_Rect_Set(&bounds, 0, 0, dst->width, dst->height);
  1.1648 +    /* NOTE: src and dst rects should be of same size!!! */
  1.1649 +    OWF_Rect_Set(&rect,
  1.1650 +                 dstRect->x, dstRect->y,
  1.1651 +                 dstRect->width, dstRect->height);
  1.1652 +    OWF_Rect_Set(&srect,
  1.1653 +                 srcRect->x, srcRect->y,
  1.1654 +                 srcRect->width, srcRect->height);
  1.1655 +
  1.1656 +    /* clip destination rectangle against bounds */
  1.1657 +    if (!OWF_Rect_Clip(&drect, &rect, &bounds))
  1.1658 +    {
  1.1659 +        return;
  1.1660 +    }
  1.1661 +
  1.1662 +    /* adjust source rectangle if needed */
  1.1663 +    if (drect.x > rect.x)
  1.1664 +    {
  1.1665 +        OWFint dx = drect.x - rect.x;
  1.1666 +        srect.x += dx;
  1.1667 +        srect.width -= dx;
  1.1668 +    }
  1.1669 +
  1.1670 +    if (drect.y > rect.y)
  1.1671 +    {
  1.1672 +        OWFint dy = drect.y - rect.y;
  1.1673 +        srect.y += dy;
  1.1674 +        srect.height -= dy;
  1.1675 +    }
  1.1676 +
  1.1677 +    if (drect.width < srect.width)
  1.1678 +    {
  1.1679 +        srect.width = drect.width;
  1.1680 +    }
  1.1681 +
  1.1682 +    if (drect.height < srect.height)
  1.1683 +    {
  1.1684 +        srect.height = drect.height;
  1.1685 +    }
  1.1686 +
  1.1687 +
  1.1688 +    srcPtr  = (OWFpixel*) src->data;
  1.1689 +    srcPtr  += srect.y * src->width + srect.x;
  1.1690 +    dstPtr  = (OWFpixel*) dst->data;
  1.1691 +    dstPtr  += drect.y * dst->width + drect.x;
  1.1692 +
  1.1693 +    if (mask)
  1.1694 +    {
  1.1695 +        maskPtr = (OWFsubpixel*) mask->data + srect.y * mask->width + srect.x;
  1.1696 +        maskLineDelta = mask->width - drect.width;
  1.1697 +    }
  1.1698 +    else
  1.1699 +    {
  1.1700 +        maskPtr = 0;
  1.1701 +        maskLineDelta = 0;
  1.1702 +    }
  1.1703 +    srcLineDelta = src->width - srect.width;
  1.1704 +    dstLineDelta = dst->width - drect.width;
  1.1705 +
  1.1706 +    /* inner loops */
  1.1707 +    switch (transparency)
  1.1708 +    {
  1.1709 +        case OWF_TRANSPARENCY_NONE:
  1.1710 +        {
  1.1711 +            /*
  1.1712 +            rgb     = src.rgb
  1.1713 +            alpha    = 1
  1.1714 +            */
  1.1715 +            BLENDER_INNER_LOOP_BEGIN;
  1.1716 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1.1717 +                DR = SR;
  1.1718 +                DG = SG;
  1.1719 +                DB = SB;
  1.1720 +                DA = OWF_FULLY_OPAQUE;
  1.1721 +#else
  1.1722 +                *(OWFuint32*)dstPtr = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK;
  1.1723 +#endif
  1.1724 +            BLENDER_INNER_LOOP_END_NO_MASK;
  1.1725 +            break;
  1.1726 +        }
  1.1727 +
  1.1728 +        case OWF_TRANSPARENCY_GLOBAL_ALPHA:
  1.1729 +        {
  1.1730 +            /*
  1.1731 +            rgb        = src.rgb * elem.alpha + dst.rgb * (1 - elem.alpha)
  1.1732 +            alpha   = elem.alpha + dst.alpha * (1 - elem.alpha)
  1.1733 +            */
  1.1734 +            BLENDER_INNER_LOOP_BEGIN;
  1.1735 +                DR = (SR * GA + DR * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1736 +                     OWF_ALPHA_MAX_VALUE;
  1.1737 +                DG = (SG * GA + DG * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1738 +                     OWF_ALPHA_MAX_VALUE;
  1.1739 +                DB = (SB * GA + DB * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1740 +                     OWF_ALPHA_MAX_VALUE;
  1.1741 +                DA = GA + (DA * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) / 
  1.1742 +                     OWF_ALPHA_MAX_VALUE;
  1.1743 +            BLENDER_INNER_LOOP_END_NO_MASK;
  1.1744 +            break;
  1.1745 +        }
  1.1746 +
  1.1747 +        case OWF_TRANSPARENCY_SOURCE_ALPHA:
  1.1748 +        {
  1.1749 +#ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1.1750 +        OWFuint32 redBlueMask = (ARGB8888_RED_MASK | ARGB8888_BLUE_MASK);
  1.1751 +        OWFuint32 alphaGreenMask = (ARGB8888_ALPHA_MASK | ARGB8888_GREEN_MASK);
  1.1752 +        OWFuint32 halfRedBlue = 0x00800080;
  1.1753 +#endif
  1.1754 +            /*
  1.1755 +            rgb     = src.rgb + dst.rgb * (1 - src.alpha)
  1.1756 +            alpha    = src.alpha + dst.alpha * (1 - src.alpha)
  1.1757 +            */
  1.1758 +            BLENDER_INNER_LOOP_BEGIN;
  1.1759 +#ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
  1.1760 +            DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1.1761 +            DG = SG + (DG * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1.1762 +            DB = SB + (DB * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1.1763 +            DA = SA + (DA * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
  1.1764 +#else
  1.1765 +            {
  1.1766 +                OWFuint32 srcP = *(OWFuint32*)srcPtr;
  1.1767 +                OWFuint8 srcA = srcP >> ARGB8888_ALPHA_SHIFT;
  1.1768 +
  1.1769 +                if (srcA == OWF_ALPHA_MAX_VALUE)
  1.1770 +                    {
  1.1771 +                    /* Fully opaque source pixel */
  1.1772 +                    *(OWFuint32*)dstPtr = srcP;
  1.1773 +                    }
  1.1774 +                else
  1.1775 +                    {
  1.1776 +                    if (srcA)
  1.1777 +                        {
  1.1778 +                        /* Not fully transparent source pixel. Algorithm after Jim Blinn */
  1.1779 +                        OWFuint32 mask = 0xFF - srcA;
  1.1780 +                        OWFuint32 dstP = *(OWFuint32*)dstPtr;
  1.1781 +                        OWFuint32 blend;
  1.1782 +
  1.1783 +                        blend = mask * (dstP & redBlueMask) + halfRedBlue;
  1.1784 +                        srcP += ((blend + ((blend >> 8) & redBlueMask) >> 8)) & redBlueMask;
  1.1785 +                        blend = mask * ((dstP >> 8) & redBlueMask) + halfRedBlue;
  1.1786 +                        srcP += (blend + ((blend >> 8) & redBlueMask)) & alphaGreenMask;
  1.1787 +
  1.1788 +                        *(OWFuint32*)dstPtr = srcP;
  1.1789 +                        }
  1.1790 +                    }
  1.1791 +            }
  1.1792 +#endif
  1.1793 +            BLENDER_INNER_LOOP_END_NO_MASK;
  1.1794 +            break;
  1.1795 +        }
  1.1796 +
  1.1797 +        case OWF_TRANSPARENCY_MASK:
  1.1798 +        {
  1.1799 +            /*
  1.1800 +            rgb     = src.rgb * mask.alpha + dst.rgb * (1 - mask.alpha)
  1.1801 +            alpha    = mask.alpha + dst.alpha * (1 - mask.alpha)
  1.1802 +            */
  1.1803 +            BLENDER_INNER_LOOP_BEGIN;
  1.1804 +                DR = (SR * MA + DR * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1805 +                     OWF_ALPHA_MAX_VALUE;
  1.1806 +                DG = (SG * MA + DG * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1807 +                     OWF_ALPHA_MAX_VALUE;
  1.1808 +                DB = (SB * MA + DB * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1809 +                     OWF_ALPHA_MAX_VALUE;
  1.1810 +                DA = MA + (DA * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) / 
  1.1811 +                     OWF_ALPHA_MAX_VALUE;
  1.1812 +            BLENDER_INNER_LOOP_END;
  1.1813 +            break;
  1.1814 +        }
  1.1815 +
  1.1816 +        case OWF_TRANSPARENCY_GLOBAL_ALPHA | OWF_TRANSPARENCY_SOURCE_ALPHA:
  1.1817 +        {
  1.1818 +            /*
  1.1819 +            rgb = src.rgb * elem.a + dst.rgb * (1 - src.a * elem.a)
  1.1820 +            a = src.a * elem.a + dst.a * (1 - src.a * elem.a)
  1.1821 +            */
  1.1822 +            OWFsubpixel         SAEA;
  1.1823 +
  1.1824 +            BLENDER_INNER_LOOP_BEGIN;
  1.1825 +                SAEA = SA * GA / OWF_ALPHA_MAX_VALUE;
  1.1826 +                DR = (SR * GA + DR * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1827 +                     OWF_ALPHA_MAX_VALUE;
  1.1828 +                DG = (SG * GA + DG * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1829 +                     OWF_ALPHA_MAX_VALUE;
  1.1830 +                DB = (SB * GA + DB * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1831 +                     OWF_ALPHA_MAX_VALUE;
  1.1832 +                DA = SAEA + (DA * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1833 +                         OWF_ALPHA_MAX_VALUE;
  1.1834 +            BLENDER_INNER_LOOP_END_NO_MASK;
  1.1835 +            break;
  1.1836 +        }
  1.1837 +
  1.1838 +        case OWF_TRANSPARENCY_GLOBAL_ALPHA | OWF_TRANSPARENCY_MASK:
  1.1839 +        {
  1.1840 +            /*
  1.1841 +            rgb    = src.rgb * mask.a * elem.a + dst.rgb * (1 - mask.a * elem.a)
  1.1842 +            a     = mask.a * elem.a + dest.a * (1 - mask.a * elem.a)
  1.1843 +            */
  1.1844 +            OWFsubpixel             MAEA;
  1.1845 +
  1.1846 +            BLENDER_INNER_LOOP_BEGIN;
  1.1847 +                MAEA = MA * GA / OWF_ALPHA_MAX_VALUE;
  1.1848 +                DR = (SR * MAEA + DR * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1849 +                     OWF_ALPHA_MAX_VALUE;
  1.1850 +                DG = (SG * MAEA + DG * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1851 +                     OWF_ALPHA_MAX_VALUE;
  1.1852 +                DB = (SB * MAEA + DB * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1853 +                     OWF_ALPHA_MAX_VALUE;
  1.1854 +                DA = MAEA + (DA * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
  1.1855 +                     OWF_ALPHA_MAX_VALUE;
  1.1856 +                //No need to check with OWF_ALPHA_MIN_VALUE as it is zero
  1.1857 +                OWF_ASSERT(GA <= OWF_ALPHA_MAX_VALUE);
  1.1858 +            BLENDER_INNER_LOOP_END;
  1.1859 +            break;
  1.1860 +        }
  1.1861 +
  1.1862 +        default:
  1.1863 +        {
  1.1864 +            DPRINT(("OWF_Image_Blend: whooops. invalid blending mode\n"));
  1.1865 +            abort();
  1.1866 +            break;
  1.1867 +        }
  1.1868 +    }
  1.1869 +}
  1.1870 +
  1.1871 +/*----------------------------------------------------------------------------*/
  1.1872 +OWF_API_CALL void*
  1.1873 +OWF_Image_AllocData(OWF_DISPCTX dc, OWFint width, OWFint height, OWF_PIXEL_FORMAT pixelFormat)
  1.1874 +{
  1.1875 +    OWF_IMAGE_FORMAT        imgf;
  1.1876 +    OWFint                  stride;
  1.1877 +
  1.1878 +    DPRINT(("OWF_Image_AllocData"));
  1.1879 +
  1.1880 +    /* kludge. GetStride need pixelFormat. */
  1.1881 +    imgf.pixelFormat = pixelFormat;
  1.1882 +    imgf.rowPadding = OWF_Image_GetFormatPadding(pixelFormat);
  1.1883 +    stride = OWF_Image_GetStride(width, &imgf, 0);
  1.1884 +
  1.1885 +    OWF_ASSERT (width > 0 && height > 0);
  1.1886 +
  1.1887 +    if (stride == 0)
  1.1888 +    {
  1.1889 +        return NULL;
  1.1890 +    }
  1.1891 +
  1.1892 +    if (dc)
  1.1893 +        {
  1.1894 +        return OWF_DisplayContext_ScratchBuffer_Allocate(dc, height * stride);
  1.1895 +        }
  1.1896 +    
  1.1897 +    return xalloc(1, height * stride);
  1.1898 +}
  1.1899 +
  1.1900 +/*----------------------------------------------------------------------------*/
  1.1901 +OWF_API_CALL void
  1.1902 +OWF_Image_FreeData(OWF_DISPCTX dc, void** data)
  1.1903 +{
  1.1904 +    DPRINT(("OWF_Image_FreeData"));
  1.1905 +
  1.1906 +    if (*data)
  1.1907 +    {
  1.1908 +    if (dc)
  1.1909 +        {
  1.1910 +        OWF_DisplayContext_ScratchBuffer_Destroy(dc, *data);
  1.1911 +        }
  1.1912 +    else
  1.1913 +        {
  1.1914 +        xfree(*data);
  1.1915 +        }
  1.1916 +    }
  1.1917 +    *data = NULL;
  1.1918 +}
  1.1919 +
  1.1920 +/*----------------------------------------------------------------------------*/
  1.1921 +OWF_API_CALL OWFint
  1.1922 +OWF_Image_GetFormatPixelSize(OWF_PIXEL_FORMAT format)
  1.1923 +{
  1.1924 +    DPRINT(("OWF_Image_GetFormatPixelSize"));
  1.1925 +
  1.1926 +    switch (format)
  1.1927 +    {
  1.1928 +        case OWF_IMAGE_ARGB_INTERNAL:
  1.1929 +        {
  1.1930 +            return sizeof(OWFpixel);
  1.1931 +        }
  1.1932 +
  1.1933 +        case OWF_IMAGE_ARGB8888:
  1.1934 +        case OWF_IMAGE_XRGB8888:
  1.1935 +        case OWF_IMAGE_L32:
  1.1936 +        {
  1.1937 +            return 4;
  1.1938 +        }
  1.1939 +
  1.1940 +        case OWF_IMAGE_RGB888:
  1.1941 +        {
  1.1942 +            return 3;
  1.1943 +        }
  1.1944 +
  1.1945 +        case OWF_IMAGE_RGB565:
  1.1946 +        case OWF_IMAGE_L16:
  1.1947 +        {
  1.1948 +            return 2;
  1.1949 +        }
  1.1950 +
  1.1951 +        case OWF_IMAGE_L8:
  1.1952 +        {
  1.1953 +            return 1;
  1.1954 +        }
  1.1955 +
  1.1956 +        case OWF_IMAGE_L1:
  1.1957 +        {
  1.1958 +            /* Use negative numbers for divisor, e.g., -8 = 1/8. */
  1.1959 +            /* L1 is 1 bit alpha, LSB->MSB, each row padded to 32-bit
  1.1960 +             * boundary. */
  1.1961 +            return -8;
  1.1962 +        }
  1.1963 +        default:
  1.1964 +        {
  1.1965 +            return 0;
  1.1966 +        }
  1.1967 +    }
  1.1968 +}
  1.1969 +
  1.1970 +/*----------------------------------------------------------------------------*/
  1.1971 +OWF_API_CALL OWFint
  1.1972 +OWF_Image_GetFormatPadding(OWF_PIXEL_FORMAT format)
  1.1973 +{
  1.1974 +    OWFint                  padding = 1;
  1.1975 +
  1.1976 +    DPRINT(("OWF_Image_GetFormatPadding"));
  1.1977 +
  1.1978 +    switch (format)
  1.1979 +    {
  1.1980 +        case OWF_IMAGE_ARGB_INTERNAL:
  1.1981 +        {
  1.1982 +            padding = sizeof(OWFpixel);
  1.1983 +            break;
  1.1984 +        }
  1.1985 +
  1.1986 +        case OWF_IMAGE_ARGB8888:
  1.1987 +        case OWF_IMAGE_XRGB8888:
  1.1988 +        case OWF_IMAGE_L32:
  1.1989 +        {
  1.1990 +            padding = 4;
  1.1991 +            break;
  1.1992 +        }
  1.1993 +
  1.1994 +        /*
  1.1995 +        case OWF_IMAGE_RGB888:
  1.1996 +        {
  1.1997 +            return 3;
  1.1998 +        }
  1.1999 +        */
  1.2000 +
  1.2001 +        case OWF_IMAGE_RGB565:
  1.2002 +        case OWF_IMAGE_L16:
  1.2003 +        {
  1.2004 +            padding = 2;
  1.2005 +            break;
  1.2006 +        }
  1.2007 +
  1.2008 +        case OWF_IMAGE_L8:
  1.2009 +        {
  1.2010 +            padding = 1;
  1.2011 +            break;
  1.2012 +        }
  1.2013 +
  1.2014 +        case OWF_IMAGE_L1:
  1.2015 +        {
  1.2016 +            /* Use negative numbers for divisor, e.g., -8 = 1/8. */
  1.2017 +            /* L1 is 1 bit alpha, LSB->MSB, each row padded to 32-bit
  1.2018 +             * boundary. */
  1.2019 +            padding = 4;
  1.2020 +            break;
  1.2021 +        }
  1.2022 +        default:
  1.2023 +        {
  1.2024 +			OWF_ASSERT(0);
  1.2025 +            break;
  1.2026 +        }
  1.2027 +    }
  1.2028 +
  1.2029 +
  1.2030 +    return padding;
  1.2031 +}
  1.2032 +
  1.2033 +/*----------------------------------------------------------------------------*/
  1.2034 +OWF_API_CALL void
  1.2035 +OWF_Image_SwapWidthAndHeight(OWF_IMAGE* image)
  1.2036 +{
  1.2037 +    DPRINT(("OWF_Image_SwapWidthAndHeight"));
  1.2038 +
  1.2039 +    /* swap w & h. Note that original stride is not restored if swap back. */
  1.2040 +    image->width ^= image->height;
  1.2041 +    image->height ^= image->width;
  1.2042 +    image->width ^= image->height;
  1.2043 +
  1.2044 +    image->stride = OWF_Image_GetStride(image->width, &image->format, 0);
  1.2045 +}
  1.2046 +
  1.2047 +/*----------------------------------------------------------------------------*/
  1.2048 +OWF_API_CALL OWFboolean
  1.2049 +OWF_Image_ConvertMask(OWF_IMAGE* output, OWF_IMAGE* input)
  1.2050 +{
  1.2051 +    OWFboolean              result = OWF_TRUE;
  1.2052 +    void*                   srcLinePtr;
  1.2053 +    OWFsubpixel*            dstLinePtr;
  1.2054 +    OWFint                  countY;
  1.2055 +
  1.2056 +    DPRINT(("OWF_Image_ConvertMask:"));
  1.2057 +    DPRINT(("  Converting mask from stream format to internal 8-bit"));
  1.2058 +
  1.2059 +    OWF_ASSERT(input);
  1.2060 +    OWF_ASSERT(output);
  1.2061 +    
  1.2062 +    srcLinePtr = input->data;
  1.2063 +    dstLinePtr = (OWFsubpixel*) output->data;    
  1.2064 +
  1.2065 +    for (countY = input->height; countY; countY--)
  1.2066 +    {
  1.2067 +        OWFsubpixel* dstData = dstLinePtr;    
  1.2068 +    
  1.2069 +        switch (input->format.pixelFormat)
  1.2070 +        {
  1.2071 +            case OWF_IMAGE_L1:
  1.2072 +            {
  1.2073 +                OWFint          countX;
  1.2074 +                OWFuint8*       srcData = (OWFuint8*) srcLinePtr;
  1.2075 +    
  1.2076 +                DPRINT(("1-bit alpha, width = %d, height = %d",
  1.2077 +                       input->width, input->height));
  1.2078 +                
  1.2079 +                for (countX = 0; countX < input->width; countX++)
  1.2080 +                {
  1.2081 +                    /*
  1.2082 +                     * alpha pixel ordering is LSB -> MSB
  1.2083 +                     *
  1.2084 +                     * byte# |----- byte 0 ----|----- byte 1-----|--
  1.2085 +                     * bit#  | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
  1.2086 +                     * pix#  | 7 6 5 4 3 2 1 0 | f e d c b a 9 8 | ...
  1.2087 +                     */
  1.2088 +                    if (srcData[countX >> 3] & (1 << (countX & 7)))
  1.2089 +                    {
  1.2090 +                        dstData[countX] = OWF_FULLY_OPAQUE;
  1.2091 +                    }
  1.2092 +                    else
  1.2093 +                    {
  1.2094 +                        dstData[countX] = OWF_FULLY_TRANSPARENT;
  1.2095 +                    }
  1.2096 +                }           
  1.2097 +                break;
  1.2098 +            }
  1.2099 +            case OWF_IMAGE_L8:
  1.2100 +            {
  1.2101 +                OWFint          countX;
  1.2102 +                OWFuint8*       srcData = (OWFuint8*) srcLinePtr;
  1.2103 +    
  1.2104 +                DPRINT(("8-bit alpha, width = %d, height = %d",
  1.2105 +                       input->width, input->height));
  1.2106 +                
  1.2107 +                for (countX = 0; countX < input->width; countX++)
  1.2108 +                {
  1.2109 +                    dstData[countX] = srcData[countX] * OWF_FULLY_OPAQUE /
  1.2110 +                                 (OWFfloat) OWF_BYTE_MAX_VALUE;                
  1.2111 +                }
  1.2112 +                break;
  1.2113 +            }
  1.2114 +            case OWF_IMAGE_ARGB8888:
  1.2115 +            {
  1.2116 +                /* ARGB image - take the alpha channel and discard
  1.2117 +                 * everything else */
  1.2118 +                OWFint          countX;
  1.2119 +                OWFuint32*      srcData = (OWFuint32*) srcLinePtr;
  1.2120 +    
  1.2121 +                DPRINT(("32-bit ARGB, width = %d, height = %d",
  1.2122 +                       input->width, input->height));
  1.2123 +                
  1.2124 +                for (countX = 0; countX < input->width; countX++)
  1.2125 +                {
  1.2126 +                    dstData[countX] = (srcData[countX] >> 24) * OWF_FULLY_OPAQUE /
  1.2127 +                                 (OWFfloat) OWF_BYTE_MAX_VALUE;          
  1.2128 +                }
  1.2129 +                break;
  1.2130 +            }
  1.2131 +            default:
  1.2132 +            {
  1.2133 +                DPRINT(("Unsupported alpha format, ignoring mask"));
  1.2134 +    
  1.2135 +                result = OWF_FALSE;
  1.2136 +                break;
  1.2137 +            }
  1.2138 +        }
  1.2139 +        
  1.2140 +        dstLinePtr+=output->width;
  1.2141 +        /* Presumes that the stride is always whole bytes - eg. a 2x2-pixel mono 
  1.2142 +         * image takes at least 2 bytes */
  1.2143 +        srcLinePtr=(OWFuint8*)srcLinePtr+input->stride;        
  1.2144 +    }
  1.2145 +    return result;
  1.2146 +}
  1.2147 +
  1.2148 +#ifdef __cplusplus
  1.2149 +}
  1.2150 +#endif