First public contribution.
1 /* Copyright (c) 2009-2010 The Khronos Group Inc.
2 * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and/or associated documentation files (the
6 * "Materials"), to deal in the Materials without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Materials, and to
9 * permit persons to whom the Materials are furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Materials.
15 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
34 #include "owfobject.h"
37 #include "owfmemory.h"
39 #include "owfdisplaycontextgeneral.h"
41 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
42 #define roundSubPixel(p) ((OWFuint32)((p) + 0.5f))
44 #define roundSubPixel(p) (p)
48 /*----------------------------------------------------------------------------*/
50 OWF_IMAGE_Ctor(void* self)
52 DPRINT(("OWF_IMAGE_Ctor"));
57 /*----------------------------------------------------------------------------*/
59 OWF_IMAGE_Dtor(void* self)
63 DPRINT(("OWF_IMAGE_Dtor"));
65 image = (OWF_IMAGE*)self;
67 if (image && image->data)
71 OWF_Image_FreeData(0, &image->data);
77 memset(image, 0, sizeof(OWF_IMAGE));
81 /*----------------------------------------------------------------------------*/
89 return 1.0556f * pow(x, 1.f/2.4f) - 0.0556f;
92 /*----------------------------------------------------------------------------*/
100 return pow((x + 0.0556f) / 1.0556f, 2.4f);
103 /*----------------------------------------------------------------------------*/
105 OWF_Image_NonLinearizeData(OWF_IMAGE* image)\
110 DPRINT(("OWF_Image_NonLinearizeData"));
112 OWF_ASSERT(image != NULL && image->data != NULL);
113 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
115 if (!image->format.linear)
120 ptr = (OWFpixel*) image->data;
121 count = image->width * image->height;
125 ptr->color.red = (OWFsubpixel) NonLinear(ptr->color.red /
126 OWF_RED_MAX_VALUE) * OWF_RED_MAX_VALUE;
127 ptr->color.green = (OWFsubpixel) NonLinear(ptr->color.green /
128 OWF_GREEN_MAX_VALUE) * OWF_GREEN_MAX_VALUE;
129 ptr->color.blue = (OWFsubpixel) NonLinear(ptr->color.blue /
130 OWF_BLUE_MAX_VALUE) * OWF_BLUE_MAX_VALUE;
136 image->format.linear = OWF_FALSE;
139 /*----------------------------------------------------------------------------*/
141 OWF_Image_LinearizeData(OWF_IMAGE* image)
146 DPRINT(("OWF_Image_LinearizeData"));
148 OWF_ASSERT(image != NULL && image->data != NULL);
149 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
151 if (image->format.linear)
156 ptr = (OWFpixel*) image->data;
157 count = image->width * image->height;
161 ptr->color.red = (OWFsubpixel) Linear(ptr->color.red /
162 OWF_RED_MAX_VALUE) * OWF_RED_MAX_VALUE;
163 ptr->color.green = (OWFsubpixel) Linear(ptr->color.green /
164 OWF_GREEN_MAX_VALUE) * OWF_GREEN_MAX_VALUE;
165 ptr->color.blue = (OWFsubpixel) Linear(ptr->color.blue /
166 OWF_BLUE_MAX_VALUE) * OWF_BLUE_MAX_VALUE;
169 ptr += image->pixelSize;
172 image->format.linear = OWF_TRUE;
176 /*----------------------------------------------------------------------------*/
177 #define GAMMA(color, max, gamma) (max * pow(color/max, gamma))
180 OWF_Image_Gamma(OWF_IMAGE* image, OWFfloat gamma)
185 DPRINT(("OWF_Image_Gamma"));
187 OWF_ASSERT(image != NULL && image->data != NULL);
188 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
195 ptr = (OWFpixel*) image->data;
196 count = image->width * image->height;
201 (OWFsubpixel) GAMMA(ptr->color.red, OWF_RED_MAX_VALUE, gamma);
203 (OWFsubpixel) GAMMA(ptr->color.green, OWF_GREEN_MAX_VALUE, gamma);
205 (OWFsubpixel) GAMMA(ptr->color.blue, OWF_BLUE_MAX_VALUE, gamma);
212 /*----------------------------------------------------------------------------*/
214 OWF_Image_EdgeReplication(OWF_IMAGE* image)
218 OWFuint8* srcPtr = NULL;
219 OWFuint8* dstPtr = NULL;
221 DPRINT(("OWF_Image_EdgeReplication"));
224 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
225 OWF_ASSERT(image->width >= 3 && image->height >= 3);
227 copyStride = OWF_Image_GetStride(image->width, &image->format, 0);
229 /* top side replication */
230 srcPtr = (OWFuint8*) image->data;
231 srcPtr += 1 * image->stride + 0 * image->pixelSize;
232 dstPtr = (OWFuint8*) image->data;
234 memcpy(dstPtr, srcPtr, copyStride);
236 /* bottom side replication */
237 srcPtr = (OWFuint8*) image->data;
238 srcPtr += (image->height-2) * image->stride + 0 * image->pixelSize;
239 dstPtr = (OWFuint8*) image->data;
240 dstPtr += (image->height-1) * image->stride + 0 * image->pixelSize;
242 memcpy(dstPtr, srcPtr, copyStride);
244 /* left side replication */
245 for (y = 0; y < image->height; y++)
247 OWF_Image_SetPixel(image, 0, y, OWF_Image_GetPixelPtr(image, 1, y));
250 /* right side replication */
251 for (y = 0; y < image->height; y++)
253 OWF_Image_SetPixel(image, image->width-1, y, OWF_Image_GetPixelPtr(image,
260 /*----------------------------------------------------------------------------*/
261 OWF_API_CALL OWFboolean
262 OWF_Image_SourceFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src)
264 OWFint countY, widthDiff, heightDiff;
266 OWFpixel* dstLinePtr;
267 OWFboolean replicateEdges = OWF_FALSE;
268 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
272 DPRINT(("OWF_Image_SourceFormatConversion"));
274 OWF_ASSERT(dst != 0 && dst->data != NULL);
275 OWF_ASSERT(src != 0 && src->data != NULL);
276 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
277 OWF_ASSERT(dst->stride == OWF_Image_GetStride(dst->width, &dst->format, 0));
279 srcLinePtr = src->data;
280 dstLinePtr = (OWFpixel*) dst->data;
282 /* dst image must either be the same size as the src image or 2 pixels
283 bigger (enough space to perform edge replication) */
284 if (dst->width != src->width || dst->height != src->height)
286 widthDiff = dst->width - src->width;
287 heightDiff = dst->height - src->height;
289 if (widthDiff == 2 && heightDiff == 2)
291 replicateEdges = OWF_TRUE;
292 /* start of the destination buffer should have a 1 pixel offset */
293 dstLinePtr = (OWFpixel*) dst->data + 1 * dst->width + 1;
301 if (dst->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
306 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
307 widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
310 for (countY = src->height; countY; countY--)
312 OWFint count = src->width;
313 OWFpixel* dstPtr = dstLinePtr;
315 switch (src->format.pixelFormat)
317 case OWF_IMAGE_ARGB8888:
319 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
320 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr;
324 dstPtr->color.alpha = (OWFsubpixel)
325 OWF_ALPHA_MAX_VALUE * ((*srcPtr & ARGB8888_ALPHA_MASK) >> ARGB8888_ALPHA_SHIFT) / OWF_BYTE_MAX_VALUE;
326 dstPtr->color.red = (OWFsubpixel)
327 OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE;
328 dstPtr->color.green = (OWFsubpixel)
329 OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK)>> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE;
330 dstPtr->color.blue = (OWFsubpixel)
331 OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE;
337 memcpy(dstLinePtr, srcLinePtr, widthBytes);
342 case OWF_IMAGE_XRGB8888:
344 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr;
348 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
349 dstPtr->color.alpha = OWF_FULLY_OPAQUE;
350 dstPtr->color.red = (OWFsubpixel)
351 OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE;
352 dstPtr->color.green = (OWFsubpixel)
353 OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK) >> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE;
354 dstPtr->color.blue = (OWFsubpixel)
355 OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE;
357 *(OWFuint32*)dstPtr = *srcPtr | ARGB8888_ALPHA_MASK;
366 case OWF_IMAGE_RGB565:
369 OWFuint16* srcPtr = (OWFuint16*) srcLinePtr;
374 * Formula for converting channel value is:
375 * Each channel is multiplied by (2^d - 1)/(2^s -1)
376 * where d is dest channel bits and s is source channel bits.
378 dstPtr->color.alpha = (OWFsubpixel) OWF_FULLY_OPAQUE;
380 tmp = (OWFfloat)((*srcPtr & RGB565_RED_MASK) >> RGB565_RED_SHIFT);
381 dstPtr->color.red = (OWFsubpixel)OWF_RED_MAX_VALUE * tmp / 31.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
383 tmp = (OWFfloat)((*srcPtr & RGB565_GREEN_MASK) >> RGB565_GREEN_SHIFT);
384 dstPtr->color.green = (OWFsubpixel)OWF_GREEN_MAX_VALUE * tmp / 63.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
386 tmp = (OWFfloat)(*srcPtr & RGB565_BLUE_MASK);
387 dstPtr->color.blue = (OWFsubpixel)OWF_BLUE_MAX_VALUE * tmp / 31.0f + OWF_SOURCE_CONVERSION_ROUNDING_VALUE;
398 return OWF_FALSE; /* source format not supported */
402 dstLinePtr+=dst->width;
403 srcLinePtr=(OWFuint8*)srcLinePtr+src->stride;
408 OWF_Image_EdgeReplication(dst);
414 /*----------------------------------------------------------------------------*/
416 OWF_Image_GetStride(OWFint width, const OWF_IMAGE_FORMAT* format, OWFint minimumStride)
421 DPRINT(("OWF_Image_GetStride"));
425 pixelSize = OWF_Image_GetFormatPixelSize(format->pixelFormat);
429 /* negative pixelSize means that pixel size is a fraction
430 * (1/-pixelSize) of a byte, e.g. -8 means pixel has size
433 size = (width + 1) / -pixelSize;
437 size = width * pixelSize;
439 if (size<minimumStride)
443 if (format->rowPadding)
445 size += format->rowPadding - 1;
446 size -= size % format->rowPadding;
451 /*----------------------------------------------------------------------------*/
452 OWF_API_CALL OWFboolean
453 OWF_Image_IsValidDestinationFormat(OWF_IMAGE_FORMAT* format)
455 DPRINT(("OWF_Image_IsValidDestinationFormat"));
457 switch (format->pixelFormat)
459 case OWF_IMAGE_ARGB8888:
463 case OWF_IMAGE_XRGB8888:
467 #ifdef SUPPORT_565_OUTPUT
468 case OWF_IMAGE_RGB565:
475 return OWF_FALSE; /* destination format not supported */
480 /*----------------------------------------------------------------------------*/
481 OWF_API_CALL OWFboolean
482 OWF_Image_DestinationFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src)
487 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
491 DPRINT(("OWF_Image_DestinationFormatConversion"));
493 OWF_ASSERT(dst != 0 && dst->data != NULL);
494 OWF_ASSERT(src != 0 && src->data != NULL);
495 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
496 /* Note: src->stride cannot be relied upon to be correct. Assume lines are contiguous. */
498 if (src->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
503 /* src and data must have equal amount of pixels */
504 if (dst->width != src->width || dst->height != src->height)
509 dstPtr = (OWFuint32*) dst->data;
510 srcPtr = (OWFpixel*) src->data;
512 if (dst->format.premultiplied && !src->format.premultiplied)
514 OWF_Image_PremultiplyAlpha(src);
516 else if (!dst->format.premultiplied && src->format.premultiplied)
518 OWF_Image_UnpremultiplyAlpha(src);
521 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
522 widthBytes = OWF_Image_GetStride(src->width, &src->format, 0);
525 for (countY = 0; countY < src->height; countY++)
527 OWFuint8* destination = (OWFuint8*) dst->data;
528 destination += countY*dst->stride;
529 dstPtr = (OWFuint32*) destination;
531 switch (dst->format.pixelFormat)
533 case OWF_IMAGE_ARGB8888:
535 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
537 OWFuint32 dstPixel = 0;
539 for (countX = 0; countX < src->width; countX++)
541 dstPixel = ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.alpha / OWF_ALPHA_MAX_VALUE)) <<
542 ARGB8888_ALPHA_SHIFT);
543 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE)) <<
545 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) <<
546 ARGB8888_GREEN_SHIFT);
547 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE)) <<
548 ARGB8888_BLUE_SHIFT);
554 memcpy(dstPtr, srcPtr, widthBytes);
555 srcPtr = (OWFpixel*)((OWFuint8*)srcPtr + widthBytes);
560 case OWF_IMAGE_XRGB8888:
563 OWFuint32 dstPixel = 0;
565 for (countX = 0; countX < src->width; countX++)
567 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
568 dstPixel = ARGB8888_ALPHA_MASK;
569 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE)) <<
571 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) <<
572 ARGB8888_GREEN_SHIFT);
573 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE)) <<
574 ARGB8888_BLUE_SHIFT);
576 dstPixel = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK;
587 return OWF_FALSE; /* destination format not supported */
595 /*----------------------------------------------------------------------------*/
597 OWF_Image_Init(OWF_IMAGE* image)
599 DPRINT(("OWF_Image_Init"));
601 OWF_ASSERT(NULL != image);
602 memset(image, 0, sizeof(OWF_IMAGE));
605 /*----------------------------------------------------------------------------*/
606 OWF_PUBLIC OWF_IMAGE*
607 OWF_Image_Create(OWFint width,
609 const OWF_IMAGE_FORMAT* format,
616 DPRINT(("OWF_Image_Create"));
618 image = CREATE(OWF_IMAGE);
623 image->format.pixelFormat = format->pixelFormat;
624 image->format.linear = format->linear;
625 image->format.premultiplied = format->premultiplied;
626 image->format.rowPadding = format->rowPadding;
628 image->pixelSize = OWF_Image_GetFormatPixelSize(format->pixelFormat);
629 image->width = width;
630 image->height = height;
632 /* stride is row length in bytes (aligned according to image format) */
633 image->stride = OWF_Image_GetStride(width, &image->format, minimumStride);
634 image->foreign = (buffer) ? OWF_TRUE : OWF_FALSE;
635 image->dataMax = image->stride * height;
637 DPRINT(("OWF_Image_Create:"));
638 DPRINT((" Pixel format = %x", format->pixelFormat));
639 DPRINT((" Linear = %d", format->linear));
640 DPRINT((" Premultiplied = %d", format->premultiplied));
641 DPRINT((" Row alignment = %d bytes", format->rowPadding));
642 DPRINT((" Pixel size = %d", image->pixelSize));
643 DPRINT((" Width = %d", image->width));
644 DPRINT((" Height = %d", image->height));
645 DPRINT((" Stride = %d", image->stride));
646 DPRINT((" Foreign data = %d", image->foreign));
647 DPRINT((" Data size = %d", image->dataMax));
648 if (image->dataMax > 0)
650 image->data = (image->foreign) ? (buffer) :
651 OWF_Image_AllocData(0, width, height, format->pixelFormat);
655 /* either overflow occured or width/height is zero */
658 DPRINT(("OWF_Image_Create: Overflow in image size calculation."));
662 DPRINT(("OWF_Image_Create: width or height is zero."));
667 if (!(image && image->data && (image->dataMax > 0)))
669 DPRINT(("OWF_Image_Create: Image creation failed (image = %p, "
670 "data = %p, dataSize = %d)",
671 image, image ? (void*)(image->data) : (void*)NULL, image?image->dataMax:-1));
678 /*----------------------------------------------------------------------------*/
679 OWF_PUBLIC void OWF_Image_Destroy(OWF_IMAGE* image)
688 /*----------------------------------------------------------------------------*/
689 OWF_API_CALL OWF_IMAGE*
690 OWF_Image_Copy(const OWF_IMAGE* image)
692 OWF_IMAGE* newImage = NULL;
694 DPRINT(("OWF_Image_Copy"));
698 newImage = CREATE(OWF_IMAGE);
701 memcpy(newImage, image, sizeof(*newImage));
704 newImage->data = xalloc(1, image->dataMax);
707 memcpy(newImage->data,
709 image->height*image->stride);
717 /*----------------------------------------------------------------------------*/
718 OWF_API_CALL OWFboolean
719 OWF_Image_SetSize(OWF_IMAGE* image,
726 DPRINT(("OWF_Image_SetSize"));
729 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL ||
730 image->format.pixelFormat==OWF_IMAGE_L32);
732 /** note that this setsize ignores any specialised stride **/
733 stride = OWF_Image_GetStride(width, &image->format, 0);
734 size = height * stride;
736 /* change source size if buffer have enough space */
737 if (size > 0 && size <= image->dataMax)
739 image->height = height;
740 image->width = width;
741 image->stride = stride;
746 /*----------------------------------------------------------------------------*/
748 OWF_Image_SetFlags(OWF_IMAGE* image,
749 OWFboolean premultiply,
752 DPRINT(("OWF_Image_SetFlags"));
755 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL ||
756 image->format.pixelFormat==OWF_IMAGE_L32);
757 image->format.linear=linear;
758 image->format.premultiplied=premultiply;
761 /*----------------------------------------------------------------------------*/
763 OWF_Image_SetPixelBuffer(OWF_IMAGE* image, void* buffer)
765 DPRINT(("OWF_Image_SetPixelBuffer"));
769 OWF_ASSERT(image->foreign);
775 /*----------------------------------------------------------------------------*/
777 OWF_API_CALL OWFboolean
778 OWF_Image_SetPixelData(OWF_IMAGE* image,
781 const OWF_IMAGE_FORMAT* format,
787 OWF_ASSERT(image && format);
789 stride = OWF_Image_GetStride(width, format);
790 size = height * stride;
799 OWF_Image_FreeData(0, &image->data);
802 image->format.pixelFormat = format->pixelFormat;
803 image->format.linear = format->linear;
804 image->format.premultiplied = format->premultiplied;
805 image->format.rowPadding = format->rowPadding;
807 image->pixelSize = OWF_Image_GetFormatPixelSize(format->pixelFormat);
808 image->width = width;
809 image->height = height;
810 image->stride = stride;
811 image->foreign = OWF_TRUE;
812 image->dataMax = size;
813 image->data = buffer;
818 /*----------------------------------------------------------------------------*/
819 OWF_API_CALL OWFboolean
820 OWF_Image_Blit(OWF_IMAGE* dst,
821 OWF_RECTANGLE const* dstRect,
822 OWF_IMAGE const* src,
823 OWF_RECTANGLE const* srcRect)
825 OWF_RECTANGLE bounds, rect, drect, srect;
826 OWFint lineCount = 0;
827 OWFint copyStride = 0;
828 OWFuint8* srcPtr = NULL;
829 OWFuint8* dstPtr = NULL;
831 DPRINT(("OWF_Image_Blit"));
833 OWF_ASSERT(dst != 0 && dst->data != NULL);
834 OWF_ASSERT(src != 0 && src->data != NULL);
835 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
836 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
838 OWF_Rect_Set(&bounds, 0, 0, dst->width, dst->height);
840 dstRect->x, dstRect->y,
841 srcRect->width, srcRect->height);
843 srcRect->x, srcRect->y,
844 srcRect->width, srcRect->height);
846 /* clip destination rectangle against bounds */
847 if (!OWF_Rect_Clip(&drect, &rect, &bounds))
852 if (src->pixelSize != dst->pixelSize)
854 DPRINT(("OWF_Image_Blit(): pixels sizes differ\n"));
858 lineCount = srect.height;
859 copyStride = srect.width * src->pixelSize;
861 /* use bytepointers in copy - generic */
862 srcPtr = (OWFuint8*) src->data;
863 srcPtr += srect.y * src->stride + srect.x * src->pixelSize;
864 dstPtr = (OWFuint8*)dst->data;
865 dstPtr += drect.y * dst->stride + drect.x * src->pixelSize;
867 while (lineCount > 0)
871 memcpy(dstPtr, srcPtr, copyStride);
873 srcPtr += src->stride;
874 dstPtr += dst->stride;
880 /*----------------------------------------------------------------------------*/
881 OWF_API_CALL OWFpixel*
882 OWF_Image_GetPixelPtr(OWF_IMAGE* image,
886 OWF_ASSERT(image && image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
887 if (!(image && image->data))
892 x = CLAMP(x, 0, image->width-1);
893 y = CLAMP(y, 0, image->height-1);
895 return (OWFpixel*)image->data + y * image->width + x ;
898 /*----------------------------------------------------------------------------*/
900 OWF_Image_GetPixel(OWF_IMAGE* image,
905 OWFpixel* temp = NULL;
909 if (!(image && image->data))
913 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
915 pixel->color.alpha = 0;
916 pixel->color.red = 0;
917 pixel->color.green = 0;
918 pixel->color.blue = 0;
920 if (x < 0 || y < 0 || x >= image->width || y >= image->height)
925 temp = (OWFpixel*)image->data + y * image->width + x;
927 pixel->color.alpha = temp->color.alpha;
928 pixel->color.red = temp->color.red;
929 pixel->color.green = temp->color.green;
930 pixel->color.blue = temp->color.blue;
933 /*----------------------------------------------------------------------------*/
935 OWF_Image_SetPixel(OWF_IMAGE* image,
938 OWFpixel const* pixel)
940 OWFpixel* data = NULL;
942 if (!(image && image->data))
946 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
948 if(x < 0 || y < 0 || x >= image->width || y >= image->height)
954 data = (OWFpixel*)image->data + y * image->width + x;
956 data->color.red = pixel->color.red;
957 data->color.green = pixel->color.green;
958 data->color.blue = pixel->color.blue;
959 data->color.alpha = pixel->color.alpha;
962 /*----------------------------------------------------------------------------*/
963 OWF_API_CALL OWFboolean
964 OWF_Image_PointSamplingStretchBlit(OWF_IMAGE* dst,
965 OWF_RECTANGLE* dstRect,
969 OWFint ox = 0, oy = 0;
972 DPRINT(("OWF_Image_PointSamplingStretchBlit"));
974 /* images must be valid */
975 if (!((src != NULL) && (src->data != NULL) &&
976 (dst != NULL) && (dst->data != NULL)))
980 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
981 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
983 /* ditto with rectangles, too */
984 if (!((dstRect != NULL) && (dstRect->width && dstRect->height) &&
985 (srcRect != NULL) && (srcRect[2] && srcRect[3])))
990 /* Note: bounds check missing */
992 if (src->pixelSize != dst->pixelSize)
997 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
999 OWFfloat dx = 0.f, dy = 0.f;
1001 /* solve scaling ratios for image */
1002 dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width;
1003 dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height;
1005 for (y = 0; y < dstRect->height; y++)
1007 for (x = 0; x < dstRect->width; x++)
1011 /* NOTE This code uses pixel center points to calculate distances
1012 and factors. Results can differ slightly when pixel corner
1013 coordinates are used */
1015 /* coordinates of nearest pixel in original image */
1016 ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]);
1017 oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]);
1019 pixel = OWF_Image_GetPixelPtr(src,
1023 OWF_Image_SetPixel(dst,
1032 if (srcRect[0] < 0 || (srcRect[0] + srcRect[2]) > src->width ||
1033 srcRect[1] < 0 || (srcRect[1] + srcRect[3]) > src->height)
1035 /* Source rectangle out of bounds */
1039 if (dstRect->x < 0 || (dstRect->x + dstRect->width) > dst->width ||
1040 dstRect->y < 0 || (dstRect->y + dstRect->height) > dst->height)
1042 /* Destination rectangle out of bounds */
1047 OWFint dxFix, dyFix;
1048 OWFint xFixStart, yFix;
1049 OWFuint32 *dstPtr, *srcLinePtr;
1051 /* Integer <-> 16.16 fixed point conversion macros */
1052 #define INT_TO_FIXED_PT(X) ((X) << 16)
1053 #define FIXED_PT_TO_INT(X) ((X) >> 16)
1055 /* Calculate scaling factors in fixed point (with rounding). */
1056 dxFix = (OWFint)((srcRect[2] * INT_TO_FIXED_PT(1) + (dstRect->width >> 1)) / dstRect->width);
1057 dyFix = (OWFint)((srcRect[3] * INT_TO_FIXED_PT(1) + (dstRect->height >> 1)) / dstRect->height);
1059 /* Calculate fixed point location in source, with half-pixel offset */
1060 xFixStart = (OWFint)(srcRect[0] * INT_TO_FIXED_PT(1) + (dxFix >> 1));
1061 yFix = (OWFint)(srcRect[1] * INT_TO_FIXED_PT(1) + (dyFix >> 1));
1063 /* Initial target address. */
1064 dstPtr = (OWFuint32*)dst->data + dstRect->y * dst->width + dstRect->x;
1066 for (y = 0; y < dstRect->height; y++)
1068 OWFint xFix = xFixStart;
1070 oy = FIXED_PT_TO_INT(yFix);
1071 srcLinePtr = (OWFuint32*)src->data + oy * src->width;
1073 for (x = 0; x < dstRect->width; x++)
1075 ox = FIXED_PT_TO_INT(xFix);
1076 dstPtr[x] = srcLinePtr[ox];
1080 dstPtr += dst->width;
1088 /*----------------------------------------------------------------------------*/
1089 OWF_API_CALL OWFboolean
1090 OWF_Image_BilinearStretchBlit(OWF_IMAGE* dst,
1091 OWF_RECTANGLE* dstRect,
1095 OWFint x = 0, y = 0;
1096 OWFint ox = 0, oy = 0;
1097 OWFfloat dx = 0.f, dy = 0.f, wx = 0.f, wy = 0.f;
1099 OWFpixel* sample[4];
1100 OWFpixel* pixel = NULL;
1102 DPRINT(("OWF_Image_BilinearStretchBlit"));
1104 /* images must be valid */
1105 if (!((src != NULL) && (src->data != NULL) &&
1106 (dst != NULL) && (dst->data != NULL)))
1110 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
1111 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
1113 /* ditto with rectangles, too */
1114 if (!((dstRect != NULL) && (dstRect->width && dstRect->height) &&
1115 (srcRect != NULL) && (srcRect[2] && srcRect[3])))
1120 if (src->pixelSize != dst->pixelSize)
1125 /* solve scaling ratios for image */
1126 dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width;
1127 dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height;
1129 for (y = 0; y < dstRect->height; y++)
1131 for (x = 0; x < dstRect->width; x++)
1133 OWFfloat tempOx, tempOy;
1135 /* NOTE This code uses pixel center points to calculate distances
1136 and factors. Results can differ slightly when pixel corner
1137 coordinates are used */
1139 /* coordinates of nearest pixel in original image */
1140 tempOx = (((OWFfloat) x + 0.5) * dx) + srcRect[0];
1141 tempOy = (((OWFfloat) y + 0.5) * dy) + srcRect[1];
1143 ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]);
1144 oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]);
1146 /* Distances to nearest pixel, eg. fractional part of coordinate */
1147 wx = (OWFfloat) ox + 0.5 - tempOx;
1148 wy = (OWFfloat) oy + 0.5 - tempOy;
1150 /* If distance is positive, we should use left or upper pixel for
1151 * second nearest pixel. */
1172 /* Calculate weights for samples */
1173 w[0] = (1.0 - wx) * (1.0 - wy);
1174 w[1] = wx * (1.0 - wy);
1175 w[2] = (1.0 - wx) * wy;
1179 sample[0] = OWF_Image_GetPixelPtr(src, ox + 0, oy + 0);
1180 sample[1] = OWF_Image_GetPixelPtr(src, ox + 1, oy + 0);
1181 sample[2] = OWF_Image_GetPixelPtr(src, ox + 0, oy + 1);
1182 sample[3] = OWF_Image_GetPixelPtr(src, ox + 1, oy + 1);
1185 /* get result pixel */
1186 pixel = OWF_Image_GetPixelPtr(dst, x, y);
1188 /* calculate final color */
1190 sample[0]->color.red * w[0] + sample[1]->color.red * w[1] +
1191 sample[2]->color.red * w[2] + sample[3]->color.red * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
1193 pixel->color.green =
1194 sample[0]->color.green * w[0] + sample[1]->color.green * w[1] +
1195 sample[2]->color.green * w[2] + sample[3]->color.green * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
1198 sample[0]->color.blue * w[0] + sample[1]->color.blue * w[1] +
1199 sample[2]->color.blue * w[2] + sample[3]->color.blue * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
1201 pixel->color.alpha =
1202 sample[0]->color.alpha * w[0] + sample[1]->color.alpha * w[1] +
1203 sample[2]->color.alpha * w[2] + sample[3]->color.alpha * w[3] + OWF_BILINEAR_ROUNDING_VALUE;
1210 /*----------------------------------------------------------------------------*/
1211 OWF_API_CALL OWFboolean
1212 OWF_Image_Stretch(OWF_IMAGE* dst,
1213 OWF_RECTANGLE* dstRect,
1216 OWF_FILTERING filter)
1218 OWFboolean result = OWF_FALSE;
1222 case OWF_FILTER_POINT_SAMPLING:
1224 result = OWF_Image_PointSamplingStretchBlit(dst, dstRect, src,
1228 case OWF_FILTER_BILINEAR:
1230 result = OWF_Image_BilinearStretchBlit(dst, dstRect, src, srcRect);
1238 /*----------------------------------------------------------------------------*/
1240 OWF_Image_Clear(OWF_IMAGE* image,
1246 OWFint i, numPixels;
1249 DPRINT(("OWF_Image_Clear"));
1251 OWF_ASSERT(image != 0);
1252 OWF_ASSERT(image->data != 0);
1253 OWF_ASSERT(image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
1254 /* Note: image->stride cannot be relied upon to be correct. Assume lines are contiguous. */
1256 numPixels = image->width * image->height;
1257 pixels = (OWFpixel*) image->data;
1259 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
1260 for (i = 0; i < numPixels; i++)
1262 pixels[i].color.red = (OWFsubpixel) red;
1263 pixels[i].color.green = (OWFsubpixel) green;
1264 pixels[i].color.blue = (OWFsubpixel) blue;
1265 pixels[i].color.alpha = (OWFsubpixel) alpha;
1268 if (alpha == red && alpha == green && alpha == blue)
1270 /* If all four bytes are the same, just use memset */
1271 OWFuint32 clearBytes = numPixels * sizeof(OWFuint32);
1273 memset(pixels, alpha, clearBytes);
1277 /* Otherwise assign each pixel the packed value */
1278 OWFuint32* pixelPtr = (OWFuint32*)pixels;
1281 pixel = (alpha << ARGB8888_ALPHA_SHIFT) | (red << ARGB8888_RED_SHIFT) |
1282 (green << ARGB8888_GREEN_SHIFT) | (blue << ARGB8888_BLUE_SHIFT);
1284 for (i = 0; i < numPixels; i++)
1286 pixelPtr[i] = pixel;
1292 /*----------------------------------------------------------------------------*/
1294 OWF_Image_PremultiplyAlpha(OWF_IMAGE* image)
1298 DPRINT(("OWF_Image_PremultiplyAlpha"));
1300 OWF_ASSERT(image != 0);
1302 if (image->format.premultiplied)
1307 /* only for internal format */
1308 if (image->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
1313 for (y = 0; y < image->height; y++)
1315 for (x = 0; x < image->width; x++)
1320 pixel = OWF_Image_GetPixelPtr(image, x, y);
1322 alpha = pixel->color.alpha;
1327 pixel->color.green =
1328 pixel->color.blue = 0;
1332 pixel->color.red = (pixel->color.red * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
1333 OWF_ALPHA_MAX_VALUE;
1334 pixel->color.green = (pixel->color.green * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
1335 OWF_ALPHA_MAX_VALUE;
1336 pixel->color.blue = (pixel->color.blue * alpha + OWF_PREMUL_ROUNDING_FACTOR ) /
1337 OWF_ALPHA_MAX_VALUE;
1342 image->format.premultiplied = OWF_TRUE;
1345 /*----------------------------------------------------------------------------*/
1347 OWF_Image_UnpremultiplyAlpha(OWF_IMAGE* image)
1352 DPRINT(("OWF_Image_UnpremultiplyAlpha"));
1354 OWF_ASSERT(image != 0);
1356 if (!image->format.premultiplied)
1361 /* only for internal format */
1362 if (image->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL)
1367 count = image->width * image->height;
1368 pixelPtr = (OWFpixel*)image->data;
1373 OWFsubpixel a = pixelPtr->color.alpha;
1375 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
1376 OWF_ASSERT(a <= OWF_ALPHA_MAX_VALUE && a >= OWF_ALPHA_MIN_VALUE);
1379 if (a > OWF_ALPHA_MIN_VALUE)
1381 OWFsubpixel r = pixelPtr->color.red * OWF_RED_MAX_VALUE / a;
1382 OWFsubpixel g = pixelPtr->color.green * OWF_GREEN_MAX_VALUE / a;
1383 OWFsubpixel b = pixelPtr->color.blue * OWF_BLUE_MAX_VALUE / a;
1385 pixelPtr->color.red = r;
1386 pixelPtr->color.green = g;
1387 pixelPtr->color.blue = b;
1394 image->format.premultiplied = OWF_TRUE;
1397 /*----------------------------------------------------------------------------*/
1399 OWF_Image_Rotate(OWF_IMAGE* dst,
1401 OWF_ROTATION rotation)
1403 OWFint ox = 0, oy = 0,
1406 OWFint xx = 0, xy = 0,
1409 DPRINT(("OWF_Image_Rotate"));
1411 OWF_ASSERT(src && src->data);
1412 OWF_ASSERT(dst && dst->data);
1413 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
1414 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
1421 case OWF_ROTATION_0:
1436 case OWF_ROTATION_90:
1439 * origin: (height-1, 0)
1451 case OWF_ROTATION_180:
1454 * origin: (width-1, height-1)
1466 case OWF_ROTATION_270:
1469 * origin: (0, height-1)
1484 for (y = 0; y < h; y++)
1486 for (x = 0; x < w; x++)
1489 * O = [ox oy]' X = [xx xy]' Y = [yx yy]'
1491 * p_dst(x_src,y_src) = O + x_src*X + y_src*Y
1493 OWF_Image_SetPixel(dst,
1494 ox + x * xx + y * yx,
1495 oy + x * xy + y * yy,
1496 OWF_Image_GetPixelPtr(src, x, y));
1501 /*----------------------------------------------------------------------------*/
1503 OWF_Image_Flip(OWF_IMAGE* image,
1504 OWF_FLIP_DIRECTION dir)
1508 DPRINT(("OWF_Image_Flip"));
1514 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL);
1516 if (dir & OWF_FLIP_VERTICALLY)
1518 OWFint h = image->height/2;
1520 for (y = 0; y < h; y++)
1522 for (x = 0; x < image->width; x++)
1526 OWF_Image_GetPixel(image, x, y, &pix);
1527 OWF_Image_SetPixel(image, x, y,
1528 OWF_Image_GetPixelPtr(image,
1530 image->height - 1 - y
1532 OWF_Image_SetPixel(image, x, image->height - 1 - y, &pix);
1537 if (dir & OWF_FLIP_HORIZONTALLY)
1539 OWFint w = image->width/2;
1541 for (y = 0; y < image->height; y++)
1543 for (x = 0; x < w; x++)
1547 OWF_Image_GetPixel(image, x, y, &pix);
1548 OWF_Image_SetPixel(image, x, y,
1549 OWF_Image_GetPixelPtr(image,
1550 image->width - 1 - x,
1553 OWF_Image_SetPixel(image, image->width - 1 - x, y, &pix);
1559 /*----------------------------------------------------------------------------*/
1560 #define BLENDER_INNER_LOOP_BEGIN \
1561 OWFint rowCount = drect.height; \
1562 while (rowCount > 0) { \
1563 OWFint colCount = drect.width; \
1564 while (colCount > 0) {
1566 #define BLENDER_INNER_LOOP_END \
1572 srcPtr += srcLineDelta; \
1573 dstPtr += dstLineDelta; \
1574 maskPtr += maskLineDelta; \
1578 #define BLENDER_INNER_LOOP_END_NO_MASK \
1583 srcPtr += srcLineDelta; \
1584 dstPtr += dstLineDelta; \
1588 #define SA srcPtr->color.alpha
1589 #define SR srcPtr->color.red
1590 #define SG srcPtr->color.green
1591 #define SB srcPtr->color.blue
1593 #define DA dstPtr->color.alpha
1594 #define DR dstPtr->color.red
1595 #define DG dstPtr->color.green
1596 #define DB dstPtr->color.blue
1599 #define GA blend->globalAlpha
1602 OWF_Image_Blend(OWF_BLEND_INFO* blend,
1603 OWF_TRANSPARENCY transparency)
1608 OWF_RECTANGLE* srcRect;
1609 OWF_RECTANGLE* dstRect;
1610 OWF_RECTANGLE bounds, srect, drect, rect;
1611 OWFint srcLineDelta, dstLineDelta, maskLineDelta;
1614 OWFsubpixel* maskPtr;
1619 DPRINT(("OWF_Image_Blend: transparency = %d", transparency));
1620 /* Mask must be set if mask-transparency is used */
1621 OWF_ASSERT(((transparency & OWF_TRANSPARENCY_MASK) && blend->mask) ||
1622 !(transparency & OWF_TRANSPARENCY_MASK));
1624 OWF_ASSERT(blend->source.image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
1625 OWF_ASSERT(blend->destination.image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL);
1628 OWF_ASSERT(blend->mask->format.pixelFormat == OWF_IMAGE_L32);
1631 dst = blend->destination.image;
1632 src = blend->source.image;
1634 dstRect = blend->destination.rectangle;
1635 srcRect = blend->source.rectangle;
1637 /* this is actually asserted above */
1638 if (OWF_TRANSPARENCY_MASK == (transparency & OWF_TRANSPARENCY_MASK) &&
1644 OWF_Rect_Set(&bounds, 0, 0, dst->width, dst->height);
1645 /* NOTE: src and dst rects should be of same size!!! */
1647 dstRect->x, dstRect->y,
1648 dstRect->width, dstRect->height);
1649 OWF_Rect_Set(&srect,
1650 srcRect->x, srcRect->y,
1651 srcRect->width, srcRect->height);
1653 /* clip destination rectangle against bounds */
1654 if (!OWF_Rect_Clip(&drect, &rect, &bounds))
1659 /* adjust source rectangle if needed */
1660 if (drect.x > rect.x)
1662 OWFint dx = drect.x - rect.x;
1667 if (drect.y > rect.y)
1669 OWFint dy = drect.y - rect.y;
1674 if (drect.width < srect.width)
1676 srect.width = drect.width;
1679 if (drect.height < srect.height)
1681 srect.height = drect.height;
1685 srcPtr = (OWFpixel*) src->data;
1686 srcPtr += srect.y * src->width + srect.x;
1687 dstPtr = (OWFpixel*) dst->data;
1688 dstPtr += drect.y * dst->width + drect.x;
1692 maskPtr = (OWFsubpixel*) mask->data + srect.y * mask->width + srect.x;
1693 maskLineDelta = mask->width - drect.width;
1700 srcLineDelta = src->width - srect.width;
1701 dstLineDelta = dst->width - drect.width;
1704 switch (transparency)
1706 case OWF_TRANSPARENCY_NONE:
1712 BLENDER_INNER_LOOP_BEGIN;
1713 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
1717 DA = OWF_FULLY_OPAQUE;
1719 *(OWFuint32*)dstPtr = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK;
1721 BLENDER_INNER_LOOP_END_NO_MASK;
1725 case OWF_TRANSPARENCY_GLOBAL_ALPHA:
1728 rgb = src.rgb * elem.alpha + dst.rgb * (1 - elem.alpha)
1729 alpha = elem.alpha + dst.alpha * (1 - elem.alpha)
1731 BLENDER_INNER_LOOP_BEGIN;
1732 DR = (SR * GA + DR * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
1733 OWF_ALPHA_MAX_VALUE;
1734 DG = (SG * GA + DG * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
1735 OWF_ALPHA_MAX_VALUE;
1736 DB = (SB * GA + DB * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
1737 OWF_ALPHA_MAX_VALUE;
1738 DA = GA + (DA * (OWF_FULLY_OPAQUE - GA) + OWF_BLEND_ROUNDING_VALUE) /
1739 OWF_ALPHA_MAX_VALUE;
1740 BLENDER_INNER_LOOP_END_NO_MASK;
1744 case OWF_TRANSPARENCY_SOURCE_ALPHA:
1746 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
1747 OWFuint32 redBlueMask = (ARGB8888_RED_MASK | ARGB8888_BLUE_MASK);
1748 OWFuint32 alphaGreenMask = (ARGB8888_ALPHA_MASK | ARGB8888_GREEN_MASK);
1749 OWFuint32 halfRedBlue = 0x00800080;
1752 rgb = src.rgb + dst.rgb * (1 - src.alpha)
1753 alpha = src.alpha + dst.alpha * (1 - src.alpha)
1755 BLENDER_INNER_LOOP_BEGIN;
1756 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT
1757 DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
1758 DG = SG + (DG * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
1759 DB = SB + (DB * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
1760 DA = SA + (DA * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE;
1763 OWFuint32 srcP = *(OWFuint32*)srcPtr;
1764 OWFuint8 srcA = srcP >> ARGB8888_ALPHA_SHIFT;
1766 if (srcA == OWF_ALPHA_MAX_VALUE)
1768 /* Fully opaque source pixel */
1769 *(OWFuint32*)dstPtr = srcP;
1775 /* Not fully transparent source pixel. Algorithm after Jim Blinn */
1776 OWFuint32 mask = 0xFF - srcA;
1777 OWFuint32 dstP = *(OWFuint32*)dstPtr;
1780 blend = mask * (dstP & redBlueMask) + halfRedBlue;
1781 srcP += ((blend + ((blend >> 8) & redBlueMask) >> 8)) & redBlueMask;
1782 blend = mask * ((dstP >> 8) & redBlueMask) + halfRedBlue;
1783 srcP += (blend + ((blend >> 8) & redBlueMask)) & alphaGreenMask;
1785 *(OWFuint32*)dstPtr = srcP;
1790 BLENDER_INNER_LOOP_END_NO_MASK;
1794 case OWF_TRANSPARENCY_MASK:
1797 rgb = src.rgb * mask.alpha + dst.rgb * (1 - mask.alpha)
1798 alpha = mask.alpha + dst.alpha * (1 - mask.alpha)
1800 BLENDER_INNER_LOOP_BEGIN;
1801 DR = (SR * MA + DR * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
1802 OWF_ALPHA_MAX_VALUE;
1803 DG = (SG * MA + DG * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
1804 OWF_ALPHA_MAX_VALUE;
1805 DB = (SB * MA + DB * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
1806 OWF_ALPHA_MAX_VALUE;
1807 DA = MA + (DA * (OWF_FULLY_OPAQUE - MA) + OWF_BLEND_ROUNDING_VALUE) /
1808 OWF_ALPHA_MAX_VALUE;
1809 BLENDER_INNER_LOOP_END;
1813 case OWF_TRANSPARENCY_GLOBAL_ALPHA | OWF_TRANSPARENCY_SOURCE_ALPHA:
1816 rgb = src.rgb * elem.a + dst.rgb * (1 - src.a * elem.a)
1817 a = src.a * elem.a + dst.a * (1 - src.a * elem.a)
1821 BLENDER_INNER_LOOP_BEGIN;
1822 SAEA = SA * GA / OWF_ALPHA_MAX_VALUE;
1823 DR = (SR * GA + DR * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
1824 OWF_ALPHA_MAX_VALUE;
1825 DG = (SG * GA + DG * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
1826 OWF_ALPHA_MAX_VALUE;
1827 DB = (SB * GA + DB * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
1828 OWF_ALPHA_MAX_VALUE;
1829 DA = SAEA + (DA * (OWF_FULLY_OPAQUE - SAEA) + OWF_BLEND_ROUNDING_VALUE) /
1830 OWF_ALPHA_MAX_VALUE;
1831 BLENDER_INNER_LOOP_END_NO_MASK;
1835 case OWF_TRANSPARENCY_GLOBAL_ALPHA | OWF_TRANSPARENCY_MASK:
1838 rgb = src.rgb * mask.a * elem.a + dst.rgb * (1 - mask.a * elem.a)
1839 a = mask.a * elem.a + dest.a * (1 - mask.a * elem.a)
1843 BLENDER_INNER_LOOP_BEGIN;
1844 MAEA = MA * GA / OWF_ALPHA_MAX_VALUE;
1845 DR = (SR * MAEA + DR * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
1846 OWF_ALPHA_MAX_VALUE;
1847 DG = (SG * MAEA + DG * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
1848 OWF_ALPHA_MAX_VALUE;
1849 DB = (SB * MAEA + DB * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
1850 OWF_ALPHA_MAX_VALUE;
1851 DA = MAEA + (DA * (OWF_FULLY_OPAQUE - MAEA) + OWF_BLEND_ROUNDING_VALUE) /
1852 OWF_ALPHA_MAX_VALUE;
1853 //No need to check with OWF_ALPHA_MIN_VALUE as it is zero
1854 OWF_ASSERT(GA <= OWF_ALPHA_MAX_VALUE);
1855 BLENDER_INNER_LOOP_END;
1861 DPRINT(("OWF_Image_Blend: whooops. invalid blending mode\n"));
1868 /*----------------------------------------------------------------------------*/
1870 OWF_Image_AllocData(OWF_DISPCTX dc, OWFint width, OWFint height, OWF_PIXEL_FORMAT pixelFormat)
1872 OWF_IMAGE_FORMAT imgf;
1875 DPRINT(("OWF_Image_AllocData"));
1877 /* kludge. GetStride need pixelFormat. */
1878 imgf.pixelFormat = pixelFormat;
1879 imgf.rowPadding = OWF_Image_GetFormatPadding(pixelFormat);
1880 stride = OWF_Image_GetStride(width, &imgf, 0);
1882 OWF_ASSERT (width > 0 && height > 0);
1891 return OWF_DisplayContext_ScratchBuffer_Allocate(dc, height * stride);
1894 return xalloc(1, height * stride);
1897 /*----------------------------------------------------------------------------*/
1899 OWF_Image_FreeData(OWF_DISPCTX dc, void** data)
1901 DPRINT(("OWF_Image_FreeData"));
1907 OWF_DisplayContext_ScratchBuffer_Destroy(dc, *data);
1917 /*----------------------------------------------------------------------------*/
1919 OWF_Image_GetFormatPixelSize(OWF_PIXEL_FORMAT format)
1921 DPRINT(("OWF_Image_GetFormatPixelSize"));
1925 case OWF_IMAGE_ARGB_INTERNAL:
1927 return sizeof(OWFpixel);
1930 case OWF_IMAGE_ARGB8888:
1931 case OWF_IMAGE_XRGB8888:
1937 case OWF_IMAGE_RGB888:
1942 case OWF_IMAGE_RGB565:
1955 /* Use negative numbers for divisor, e.g., -8 = 1/8. */
1956 /* L1 is 1 bit alpha, LSB->MSB, each row padded to 32-bit
1967 /*----------------------------------------------------------------------------*/
1969 OWF_Image_GetFormatPadding(OWF_PIXEL_FORMAT format)
1973 DPRINT(("OWF_Image_GetFormatPadding"));
1977 case OWF_IMAGE_ARGB_INTERNAL:
1979 padding = sizeof(OWFpixel);
1983 case OWF_IMAGE_ARGB8888:
1984 case OWF_IMAGE_XRGB8888:
1992 case OWF_IMAGE_RGB888:
1998 case OWF_IMAGE_RGB565:
2013 /* Use negative numbers for divisor, e.g., -8 = 1/8. */
2014 /* L1 is 1 bit alpha, LSB->MSB, each row padded to 32-bit
2030 /*----------------------------------------------------------------------------*/
2032 OWF_Image_SwapWidthAndHeight(OWF_IMAGE* image)
2034 DPRINT(("OWF_Image_SwapWidthAndHeight"));
2036 /* swap w & h. Note that original stride is not restored if swap back. */
2037 image->width ^= image->height;
2038 image->height ^= image->width;
2039 image->width ^= image->height;
2041 image->stride = OWF_Image_GetStride(image->width, &image->format, 0);
2044 /*----------------------------------------------------------------------------*/
2045 OWF_API_CALL OWFboolean
2046 OWF_Image_ConvertMask(OWF_IMAGE* output, OWF_IMAGE* input)
2048 OWFboolean result = OWF_TRUE;
2050 OWFsubpixel* dstLinePtr;
2053 DPRINT(("OWF_Image_ConvertMask:"));
2054 DPRINT((" Converting mask from stream format to internal 8-bit"));
2059 srcLinePtr = input->data;
2060 dstLinePtr = (OWFsubpixel*) output->data;
2062 for (countY = input->height; countY; countY--)
2064 OWFsubpixel* dstData = dstLinePtr;
2066 switch (input->format.pixelFormat)
2071 OWFuint8* srcData = (OWFuint8*) srcLinePtr;
2073 DPRINT(("1-bit alpha, width = %d, height = %d",
2074 input->width, input->height));
2076 for (countX = 0; countX < input->width; countX++)
2079 * alpha pixel ordering is LSB -> MSB
2081 * byte# |----- byte 0 ----|----- byte 1-----|--
2082 * bit# | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
2083 * pix# | 7 6 5 4 3 2 1 0 | f e d c b a 9 8 | ...
2085 if (srcData[countX >> 3] & (1 << (countX & 7)))
2087 dstData[countX] = OWF_FULLY_OPAQUE;
2091 dstData[countX] = OWF_FULLY_TRANSPARENT;
2099 OWFuint8* srcData = (OWFuint8*) srcLinePtr;
2101 DPRINT(("8-bit alpha, width = %d, height = %d",
2102 input->width, input->height));
2104 for (countX = 0; countX < input->width; countX++)
2106 dstData[countX] = srcData[countX] * OWF_FULLY_OPAQUE /
2107 (OWFfloat) OWF_BYTE_MAX_VALUE;
2111 case OWF_IMAGE_ARGB8888:
2113 /* ARGB image - take the alpha channel and discard
2114 * everything else */
2116 OWFuint32* srcData = (OWFuint32*) srcLinePtr;
2118 DPRINT(("32-bit ARGB, width = %d, height = %d",
2119 input->width, input->height));
2121 for (countX = 0; countX < input->width; countX++)
2123 dstData[countX] = (srcData[countX] >> 24) * OWF_FULLY_OPAQUE /
2124 (OWFfloat) OWF_BYTE_MAX_VALUE;
2130 DPRINT(("Unsupported alpha format, ignoring mask"));
2137 dstLinePtr+=output->width;
2138 /* Presumes that the stride is always whole bytes - eg. a 2x2-pixel mono
2139 * image takes at least 2 bytes */
2140 srcLinePtr=(OWFuint8*)srcLinePtr+input->stride;