1 /* Copyright (c) 2009-2010 The Khronos Group Inc. |
1 /* Copyright (c) 2009-2010 The Khronos Group Inc. |
2 * |
2 * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies) |
|
3 * |
3 * Permission is hereby granted, free of charge, to any person obtaining a |
4 * Permission is hereby granted, free of charge, to any person obtaining a |
4 * copy of this software and/or associated documentation files (the |
5 * copy of this software and/or associated documentation files (the |
5 * "Materials"), to deal in the Materials without restriction, including |
6 * "Materials"), to deal in the Materials without restriction, including |
6 * without limitation the rights to use, copy, modify, merge, publish, |
7 * without limitation the rights to use, copy, modify, merge, publish, |
7 * distribute, sublicense, and/or sell copies of the Materials, and to |
8 * distribute, sublicense, and/or sell copies of the Materials, and to |
46 |
47 |
47 /*----------------------------------------------------------------------------*/ |
48 /*----------------------------------------------------------------------------*/ |
48 OWF_API_CALL void |
49 OWF_API_CALL void |
49 OWF_IMAGE_Ctor(void* self) |
50 OWF_IMAGE_Ctor(void* self) |
50 { |
51 { |
|
52 DPRINT(("OWF_IMAGE_Ctor")); |
|
53 |
51 self = self; |
54 self = self; |
52 } |
55 } |
53 |
56 |
54 /*----------------------------------------------------------------------------*/ |
57 /*----------------------------------------------------------------------------*/ |
55 OWF_API_CALL void |
58 OWF_API_CALL void |
56 OWF_IMAGE_Dtor(void* self) |
59 OWF_IMAGE_Dtor(void* self) |
57 { |
60 { |
58 OWF_IMAGE* image; |
61 OWF_IMAGE* image; |
59 |
62 |
|
63 DPRINT(("OWF_IMAGE_Dtor")); |
|
64 |
60 image = (OWF_IMAGE*)self; |
65 image = (OWF_IMAGE*)self; |
61 |
66 |
62 if (image && image->data) |
67 if (image && image->data) |
63 { |
68 { |
64 if (!image->foreign) |
69 if (!image->foreign) |
205 OWFint y; |
216 OWFint y; |
206 OWFint copyStride; |
217 OWFint copyStride; |
207 OWFuint8* srcPtr = NULL; |
218 OWFuint8* srcPtr = NULL; |
208 OWFuint8* dstPtr = NULL; |
219 OWFuint8* dstPtr = NULL; |
209 |
220 |
|
221 DPRINT(("OWF_Image_EdgeReplication")); |
|
222 |
210 OWF_ASSERT(image); |
223 OWF_ASSERT(image); |
211 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
224 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
212 OWF_ASSERT(image->width >= 3 && image->height >= 3); |
225 OWF_ASSERT(image->width >= 3 && image->height >= 3); |
213 |
226 |
214 copyStride = image->width * image->pixelSize; |
227 copyStride = OWF_Image_GetStride(image->width, &image->format, 0); |
215 |
228 |
216 /* top side replication */ |
229 /* top side replication */ |
217 srcPtr = (OWFuint8*) image->data; |
230 srcPtr = (OWFuint8*) image->data; |
218 srcPtr += 1 * image->stride + 0 * image->pixelSize; |
231 srcPtr += 1 * image->stride + 0 * image->pixelSize; |
219 dstPtr = (OWFuint8*) image->data; |
232 dstPtr = (OWFuint8*) image->data; |
250 { |
263 { |
251 OWFint countY, widthDiff, heightDiff; |
264 OWFint countY, widthDiff, heightDiff; |
252 void* srcLinePtr; |
265 void* srcLinePtr; |
253 OWFpixel* dstLinePtr; |
266 OWFpixel* dstLinePtr; |
254 OWFboolean replicateEdges = OWF_FALSE; |
267 OWFboolean replicateEdges = OWF_FALSE; |
255 |
268 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
|
269 OWFint widthBytes; |
|
270 #endif |
|
271 |
|
272 DPRINT(("OWF_Image_SourceFormatConversion")); |
256 |
273 |
257 OWF_ASSERT(dst != 0 && dst->data != NULL); |
274 OWF_ASSERT(dst != 0 && dst->data != NULL); |
258 OWF_ASSERT(src != 0 && src->data != NULL); |
275 OWF_ASSERT(src != 0 && src->data != NULL); |
259 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
276 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
|
277 OWF_ASSERT(dst->stride == OWF_Image_GetStride(dst->width, &dst->format, 0)); |
260 |
278 |
261 srcLinePtr = src->data; |
279 srcLinePtr = src->data; |
262 dstLinePtr = (OWFpixel*) dst->data; |
280 dstLinePtr = (OWFpixel*) dst->data; |
263 |
281 |
264 /* dst image must either be the same size as the src image or 2 pixels |
282 /* dst image must either be the same size as the src image or 2 pixels |
283 if (dst->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL) |
301 if (dst->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL) |
284 { |
302 { |
285 return OWF_FALSE; |
303 return OWF_FALSE; |
286 } |
304 } |
287 |
305 |
|
306 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
|
307 widthBytes = OWF_Image_GetStride(src->width, &src->format, 0); |
|
308 #endif |
|
309 |
288 for (countY = src->height; countY; countY--) |
310 for (countY = src->height; countY; countY--) |
289 { |
311 { |
290 OWFint count = src->width; |
312 OWFint count = src->width; |
291 OWFpixel* dstPtr = dstLinePtr; |
313 OWFpixel* dstPtr = dstLinePtr; |
292 |
314 |
293 switch (src->format.pixelFormat) |
315 switch (src->format.pixelFormat) |
294 { |
316 { |
295 case OWF_IMAGE_ARGB8888: |
317 case OWF_IMAGE_ARGB8888: |
296 { |
318 { |
|
319 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
297 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr; |
320 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr; |
298 |
321 |
299 while (count > 0) |
322 while (count > 0) |
300 { |
323 { |
301 dstPtr->color.alpha = (OWFsubpixel) |
324 dstPtr->color.alpha = (OWFsubpixel) |
308 OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE; |
331 OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE; |
309 dstPtr ++; |
332 dstPtr ++; |
310 srcPtr ++; |
333 srcPtr ++; |
311 count--; |
334 count--; |
312 } |
335 } |
|
336 #else |
|
337 memcpy(dstLinePtr, srcLinePtr, widthBytes); |
|
338 #endif |
313 break; |
339 break; |
314 } |
340 } |
315 |
341 |
316 case OWF_IMAGE_XRGB8888: |
342 case OWF_IMAGE_XRGB8888: |
317 { |
343 { |
318 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr; |
344 OWFuint32* srcPtr = (OWFuint32*) srcLinePtr; |
319 |
345 |
320 while (count > 0) |
346 while (count > 0) |
321 { |
347 { |
|
348 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
322 dstPtr->color.alpha = OWF_FULLY_OPAQUE; |
349 dstPtr->color.alpha = OWF_FULLY_OPAQUE; |
323 dstPtr->color.red = (OWFsubpixel) |
350 dstPtr->color.red = (OWFsubpixel) |
324 OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE; |
351 OWF_RED_MAX_VALUE * ((*srcPtr & ARGB8888_RED_MASK) >> ARGB8888_RED_SHIFT) / OWF_BYTE_MAX_VALUE; |
325 dstPtr->color.green = (OWFsubpixel) |
352 dstPtr->color.green = (OWFsubpixel) |
326 OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK) >> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE; |
353 OWF_GREEN_MAX_VALUE * ((*srcPtr & ARGB8888_GREEN_MASK) >> ARGB8888_GREEN_SHIFT) / OWF_BYTE_MAX_VALUE; |
327 dstPtr->color.blue = (OWFsubpixel) |
354 dstPtr->color.blue = (OWFsubpixel) |
328 OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE; |
355 OWF_BLUE_MAX_VALUE * ((*srcPtr & ARGB8888_BLUE_MASK) >> ARGB8888_BLUE_SHIFT) / OWF_BYTE_MAX_VALUE; |
|
356 #else |
|
357 *(OWFuint32*)dstPtr = *srcPtr | ARGB8888_ALPHA_MASK; |
|
358 #endif |
329 dstPtr ++; |
359 dstPtr ++; |
330 srcPtr ++; |
360 srcPtr ++; |
331 count--; |
361 count--; |
332 } |
362 } |
333 break; |
363 break; |
448 OWF_Image_DestinationFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src) |
482 OWF_Image_DestinationFormatConversion(OWF_IMAGE* dst, OWF_IMAGE* src) |
449 { |
483 { |
450 OWFint countY; |
484 OWFint countY; |
451 OWFuint32* dstPtr; |
485 OWFuint32* dstPtr; |
452 OWFpixel* srcPtr; |
486 OWFpixel* srcPtr; |
|
487 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
|
488 OWFint widthBytes; |
|
489 #endif |
|
490 |
|
491 DPRINT(("OWF_Image_DestinationFormatConversion")); |
453 |
492 |
454 OWF_ASSERT(dst != 0 && dst->data != NULL); |
493 OWF_ASSERT(dst != 0 && dst->data != NULL); |
455 OWF_ASSERT(src != 0 && src->data != NULL); |
494 OWF_ASSERT(src != 0 && src->data != NULL); |
456 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
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. */ |
457 |
497 |
458 if (src->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL) |
498 if (src->format.pixelFormat != OWF_IMAGE_ARGB_INTERNAL) |
459 { |
499 { |
460 return OWF_FALSE; |
500 return OWF_FALSE; |
461 } |
501 } |
503 ARGB8888_BLUE_SHIFT); |
548 ARGB8888_BLUE_SHIFT); |
504 *dstPtr = dstPixel; |
549 *dstPtr = dstPixel; |
505 dstPtr ++; |
550 dstPtr ++; |
506 srcPtr ++; |
551 srcPtr ++; |
507 } |
552 } |
|
553 #else |
|
554 memcpy(dstPtr, srcPtr, widthBytes); |
|
555 srcPtr = (OWFpixel*)((OWFuint8*)srcPtr + widthBytes); |
|
556 #endif |
508 break; |
557 break; |
509 } |
558 } |
510 |
559 |
511 case OWF_IMAGE_XRGB8888: |
560 case OWF_IMAGE_XRGB8888: |
512 { |
561 { |
513 OWFint countX; |
562 OWFint countX; |
514 OWFuint32 dstPixel = 0; |
563 OWFuint32 dstPixel = 0; |
515 |
564 |
516 for (countX = 0; countX < src->width; countX++) |
565 for (countX = 0; countX < src->width; countX++) |
517 { |
566 { |
|
567 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
518 dstPixel = ARGB8888_ALPHA_MASK; |
568 dstPixel = ARGB8888_ALPHA_MASK; |
519 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE)) << |
569 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.red / OWF_RED_MAX_VALUE)) << |
520 ARGB8888_RED_SHIFT); |
570 ARGB8888_RED_SHIFT); |
521 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) << |
571 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.green / OWF_GREEN_MAX_VALUE)) << |
522 ARGB8888_GREEN_SHIFT); |
572 ARGB8888_GREEN_SHIFT); |
523 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE)) << |
573 dstPixel |= ((OWFuint8)(roundSubPixel(OWF_BYTE_MAX_VALUE * srcPtr->color.blue / OWF_BLUE_MAX_VALUE)) << |
524 ARGB8888_BLUE_SHIFT); |
574 ARGB8888_BLUE_SHIFT); |
|
575 #else |
|
576 dstPixel = *(OWFuint32*)srcPtr | ARGB8888_ALPHA_MASK; |
|
577 #endif |
525 *dstPtr = dstPixel; |
578 *dstPtr = dstPixel; |
526 dstPtr ++; |
579 dstPtr ++; |
527 srcPtr ++; |
580 srcPtr ++; |
528 } |
581 } |
529 break; |
582 break; |
686 OWF_API_CALL void |
747 OWF_API_CALL void |
687 OWF_Image_SetFlags(OWF_IMAGE* image, |
748 OWF_Image_SetFlags(OWF_IMAGE* image, |
688 OWFboolean premultiply, |
749 OWFboolean premultiply, |
689 OWFboolean linear) |
750 OWFboolean linear) |
690 { |
751 { |
|
752 DPRINT(("OWF_Image_SetFlags")); |
|
753 |
691 OWF_ASSERT(image); |
754 OWF_ASSERT(image); |
692 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL || |
755 OWF_ASSERT(image->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL || |
693 image->format.pixelFormat==OWF_IMAGE_L32); |
756 image->format.pixelFormat==OWF_IMAGE_L32); |
694 image->format.linear=linear; |
757 image->format.linear=linear; |
695 image->format.premultiplied=premultiply; |
758 image->format.premultiplied=premultiply; |
761 OWFint lineCount = 0; |
826 OWFint lineCount = 0; |
762 OWFint copyStride = 0; |
827 OWFint copyStride = 0; |
763 OWFuint8* srcPtr = NULL; |
828 OWFuint8* srcPtr = NULL; |
764 OWFuint8* dstPtr = NULL; |
829 OWFuint8* dstPtr = NULL; |
765 |
830 |
|
831 DPRINT(("OWF_Image_Blit")); |
|
832 |
766 OWF_ASSERT(dst != 0 && dst->data != NULL); |
833 OWF_ASSERT(dst != 0 && dst->data != NULL); |
767 OWF_ASSERT(src != 0 && src->data != NULL); |
834 OWF_ASSERT(src != 0 && src->data != NULL); |
768 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
835 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
769 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
836 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
770 |
837 |
898 OWF_RECTANGLE* dstRect, |
965 OWF_RECTANGLE* dstRect, |
899 OWF_IMAGE* src, |
966 OWF_IMAGE* src, |
900 OWFfloat* srcRect) |
967 OWFfloat* srcRect) |
901 { |
968 { |
902 OWFint ox = 0, oy = 0; |
969 OWFint ox = 0, oy = 0; |
903 OWFfloat dx = 0.f, dy = 0.f; |
|
904 OWFint x, y; |
970 OWFint x, y; |
|
971 |
|
972 DPRINT(("OWF_Image_PointSamplingStretchBlit")); |
905 |
973 |
906 /* images must be valid */ |
974 /* images must be valid */ |
907 if (!((src != NULL) && (src->data != NULL) && |
975 if (!((src != NULL) && (src->data != NULL) && |
908 (dst != NULL) && (dst->data != NULL))) |
976 (dst != NULL) && (dst->data != NULL))) |
909 { |
977 { |
924 if (src->pixelSize != dst->pixelSize) |
992 if (src->pixelSize != dst->pixelSize) |
925 { |
993 { |
926 return OWF_FALSE; |
994 return OWF_FALSE; |
927 } |
995 } |
928 |
996 |
929 /* solve scaling ratios for image */ |
997 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
930 dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width; |
998 { |
931 dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height; |
999 OWFfloat dx = 0.f, dy = 0.f; |
932 |
1000 |
933 for (y = 0; y < dstRect->height; y++) |
1001 /* solve scaling ratios for image */ |
934 { |
1002 dx = (OWFfloat) srcRect[2] / (OWFfloat) dstRect->width; |
935 for (x = 0; x < dstRect->width; x++) |
1003 dy = (OWFfloat) srcRect[3] / (OWFfloat) dstRect->height; |
936 { |
1004 |
937 OWFpixel* pixel; |
1005 for (y = 0; y < dstRect->height; y++) |
938 |
1006 { |
939 /* NOTE This code uses pixel center points to calculate distances |
1007 for (x = 0; x < dstRect->width; x++) |
940 and factors. Results can differ slightly when pixel corner |
1008 { |
941 coordinates are used */ |
1009 OWFpixel* pixel; |
942 |
1010 |
943 /* coordinates of nearest pixel in original image */ |
1011 /* NOTE This code uses pixel center points to calculate distances |
944 ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]); |
1012 and factors. Results can differ slightly when pixel corner |
945 oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]); |
1013 coordinates are used */ |
946 |
1014 |
947 pixel = OWF_Image_GetPixelPtr(src, |
1015 /* coordinates of nearest pixel in original image */ |
948 ox, |
1016 ox = (int) floor((((OWFfloat) x + 0.5) * dx) + srcRect[0]); |
949 oy); |
1017 oy = (int) floor((((OWFfloat) y + 0.5) * dy) + srcRect[1]); |
950 |
1018 |
951 OWF_Image_SetPixel(dst, |
1019 pixel = OWF_Image_GetPixelPtr(src, |
952 dstRect->x + x, |
1020 ox, |
953 dstRect->y + y, |
1021 oy); |
954 pixel); |
1022 |
955 |
1023 OWF_Image_SetPixel(dst, |
956 } |
1024 dstRect->x + x, |
957 } |
1025 dstRect->y + y, |
|
1026 pixel); |
|
1027 |
|
1028 } |
|
1029 } |
|
1030 } |
|
1031 #else |
|
1032 if (srcRect[0] < 0 || (srcRect[0] + srcRect[2]) > src->width || |
|
1033 srcRect[1] < 0 || (srcRect[1] + srcRect[3]) > src->height) |
|
1034 { |
|
1035 /* Source rectangle out of bounds */ |
|
1036 return OWF_FALSE; |
|
1037 } |
|
1038 |
|
1039 if (dstRect->x < 0 || (dstRect->x + dstRect->width) > dst->width || |
|
1040 dstRect->y < 0 || (dstRect->y + dstRect->height) > dst->height) |
|
1041 { |
|
1042 /* Destination rectangle out of bounds */ |
|
1043 return OWF_FALSE; |
|
1044 } |
|
1045 |
|
1046 { |
|
1047 OWFint dxFix, dyFix; |
|
1048 OWFint xFixStart, yFix; |
|
1049 OWFuint32 *dstPtr, *srcLinePtr; |
|
1050 |
|
1051 /* Integer <-> 16.16 fixed point conversion macros */ |
|
1052 #define INT_TO_FIXED_PT(X) ((X) << 16) |
|
1053 #define FIXED_PT_TO_INT(X) ((X) >> 16) |
|
1054 |
|
1055 /* Calculate scaling factors in fixed point (with rounding). */ |
|
1056 dxFix = (OWFint)((srcRect[2] * INT_TO_FIXED_PT(1) + (dstRect->width >> 1)) / dstRect->width); |
|
1057 dyFix = (OWFint)((srcRect[3] * INT_TO_FIXED_PT(1) + (dstRect->height >> 1)) / dstRect->height); |
|
1058 |
|
1059 /* Calculate fixed point location in source, with half-pixel offset */ |
|
1060 xFixStart = (OWFint)(srcRect[0] * INT_TO_FIXED_PT(1) + (dxFix >> 1)); |
|
1061 yFix = (OWFint)(srcRect[1] * INT_TO_FIXED_PT(1) + (dyFix >> 1)); |
|
1062 |
|
1063 /* Initial target address. */ |
|
1064 dstPtr = (OWFuint32*)dst->data + dstRect->y * dst->width + dstRect->x; |
|
1065 |
|
1066 for (y = 0; y < dstRect->height; y++) |
|
1067 { |
|
1068 OWFint xFix = xFixStart; |
|
1069 |
|
1070 oy = FIXED_PT_TO_INT(yFix); |
|
1071 srcLinePtr = (OWFuint32*)src->data + oy * src->width; |
|
1072 |
|
1073 for (x = 0; x < dstRect->width; x++) |
|
1074 { |
|
1075 ox = FIXED_PT_TO_INT(xFix); |
|
1076 dstPtr[x] = srcLinePtr[ox]; |
|
1077 xFix += dxFix; |
|
1078 } |
|
1079 |
|
1080 dstPtr += dst->width; |
|
1081 yFix += dyFix; |
|
1082 } |
|
1083 } |
|
1084 #endif |
958 return OWF_TRUE; |
1085 return OWF_TRUE; |
959 } |
1086 } |
960 |
1087 |
961 /*----------------------------------------------------------------------------*/ |
1088 /*----------------------------------------------------------------------------*/ |
962 OWF_API_CALL OWFboolean |
1089 OWF_API_CALL OWFboolean |
970 OWFfloat dx = 0.f, dy = 0.f, wx = 0.f, wy = 0.f; |
1097 OWFfloat dx = 0.f, dy = 0.f, wx = 0.f, wy = 0.f; |
971 OWFfloat w[2 * 2]; |
1098 OWFfloat w[2 * 2]; |
972 OWFpixel* sample[4]; |
1099 OWFpixel* sample[4]; |
973 OWFpixel* pixel = NULL; |
1100 OWFpixel* pixel = NULL; |
974 |
1101 |
|
1102 DPRINT(("OWF_Image_BilinearStretchBlit")); |
|
1103 |
975 /* images must be valid */ |
1104 /* images must be valid */ |
976 if (!((src != NULL) && (src->data != NULL) && |
1105 if (!((src != NULL) && (src->data != NULL) && |
977 (dst != NULL) && (dst->data != NULL))) |
1106 (dst != NULL) && (dst->data != NULL))) |
978 { |
1107 { |
979 return OWF_FALSE; |
1108 return OWF_FALSE; |
1115 OWFsubpixel alpha) |
1244 OWFsubpixel alpha) |
1116 { |
1245 { |
1117 OWFint i, numPixels; |
1246 OWFint i, numPixels; |
1118 OWFpixel* pixels; |
1247 OWFpixel* pixels; |
1119 |
1248 |
|
1249 DPRINT(("OWF_Image_Clear")); |
|
1250 |
1120 OWF_ASSERT(image != 0); |
1251 OWF_ASSERT(image != 0); |
1121 OWF_ASSERT(image->data != 0); |
1252 OWF_ASSERT(image->data != 0); |
1122 OWF_ASSERT(image->format.pixelFormat == OWF_IMAGE_ARGB_INTERNAL); |
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. */ |
1123 |
1255 |
1124 numPixels = image->width * image->height; |
1256 numPixels = image->width * image->height; |
1125 pixels = (OWFpixel*) image->data; |
1257 pixels = (OWFpixel*) image->data; |
1126 |
1258 |
|
1259 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
1127 for (i = 0; i < numPixels; i++) |
1260 for (i = 0; i < numPixels; i++) |
1128 { |
1261 { |
1129 pixels[i].color.red = (OWFsubpixel) red; |
1262 pixels[i].color.red = (OWFsubpixel) red; |
1130 pixels[i].color.green = (OWFsubpixel) green; |
1263 pixels[i].color.green = (OWFsubpixel) green; |
1131 pixels[i].color.blue = (OWFsubpixel) blue; |
1264 pixels[i].color.blue = (OWFsubpixel) blue; |
1132 pixels[i].color.alpha = (OWFsubpixel) alpha; |
1265 pixels[i].color.alpha = (OWFsubpixel) alpha; |
1133 } |
1266 } |
|
1267 #else |
|
1268 if (alpha == red && alpha == green && alpha == blue) |
|
1269 { |
|
1270 /* If all four bytes are the same, just use memset */ |
|
1271 OWFuint32 clearBytes = numPixels * sizeof(OWFuint32); |
|
1272 |
|
1273 memset(pixels, alpha, clearBytes); |
|
1274 } |
|
1275 else |
|
1276 { |
|
1277 /* Otherwise assign each pixel the packed value */ |
|
1278 OWFuint32* pixelPtr = (OWFuint32*)pixels; |
|
1279 OWFuint32 pixel; |
|
1280 |
|
1281 pixel = (alpha << ARGB8888_ALPHA_SHIFT) | (red << ARGB8888_RED_SHIFT) | |
|
1282 (green << ARGB8888_GREEN_SHIFT) | (blue << ARGB8888_BLUE_SHIFT); |
|
1283 |
|
1284 for (i = 0; i < numPixels; i++) |
|
1285 { |
|
1286 pixelPtr[i] = pixel; |
|
1287 } |
|
1288 } |
|
1289 #endif |
1134 } |
1290 } |
1135 |
1291 |
1136 /*----------------------------------------------------------------------------*/ |
1292 /*----------------------------------------------------------------------------*/ |
1137 OWF_API_CALL void |
1293 OWF_API_CALL void |
1138 OWF_Image_PremultiplyAlpha(OWF_IMAGE* image) |
1294 OWF_Image_PremultiplyAlpha(OWF_IMAGE* image) |
1139 { |
1295 { |
1140 OWFint x, y; |
1296 OWFint x, y; |
|
1297 |
|
1298 DPRINT(("OWF_Image_PremultiplyAlpha")); |
1141 |
1299 |
1142 OWF_ASSERT(image != 0); |
1300 OWF_ASSERT(image != 0); |
1143 |
1301 |
1144 if (image->format.premultiplied) |
1302 if (image->format.premultiplied) |
1145 { |
1303 { |
1243 OWFint ox = 0, oy = 0, |
1403 OWFint ox = 0, oy = 0, |
1244 w = 0, h = 0, |
1404 w = 0, h = 0, |
1245 x = 0, y = 0; |
1405 x = 0, y = 0; |
1246 OWFint xx = 0, xy = 0, |
1406 OWFint xx = 0, xy = 0, |
1247 yx = 0, yy = 0; |
1407 yx = 0, yy = 0; |
|
1408 |
|
1409 DPRINT(("OWF_Image_Rotate")); |
1248 |
1410 |
1249 OWF_ASSERT(src && src->data); |
1411 OWF_ASSERT(src && src->data); |
1250 OWF_ASSERT(dst && dst->data); |
1412 OWF_ASSERT(dst && dst->data); |
1251 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
1413 OWF_ASSERT(src->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
1252 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
1414 OWF_ASSERT(dst->format.pixelFormat==OWF_IMAGE_ARGB_INTERNAL); |
1395 /*----------------------------------------------------------------------------*/ |
1559 /*----------------------------------------------------------------------------*/ |
1396 #define BLENDER_INNER_LOOP_BEGIN \ |
1560 #define BLENDER_INNER_LOOP_BEGIN \ |
1397 OWFint rowCount = drect.height; \ |
1561 OWFint rowCount = drect.height; \ |
1398 while (rowCount > 0) { \ |
1562 while (rowCount > 0) { \ |
1399 OWFint colCount = drect.width; \ |
1563 OWFint colCount = drect.width; \ |
1400 while (colCount > 0) { \ |
1564 while (colCount > 0) { |
1401 if (!(blend->tsColor && COLOR_MATCH(SC, TSC))) \ |
|
1402 { \ |
|
1403 |
1565 |
1404 #define BLENDER_INNER_LOOP_END \ |
1566 #define BLENDER_INNER_LOOP_END \ |
1405 DA = blend->destinationFullyOpaque ? OWF_FULLY_OPAQUE : DA; \ |
|
1406 } /* end tsColor check */ \ |
|
1407 srcPtr ++; \ |
1567 srcPtr ++; \ |
1408 dstPtr ++; \ |
1568 dstPtr ++; \ |
1409 maskPtr++; \ |
1569 maskPtr++; \ |
1410 --colCount; \ |
1570 --colCount; \ |
1411 } \ |
1571 } \ |
1414 maskPtr += maskLineDelta; \ |
1574 maskPtr += maskLineDelta; \ |
1415 --rowCount; \ |
1575 --rowCount; \ |
1416 } |
1576 } |
1417 |
1577 |
1418 #define BLENDER_INNER_LOOP_END_NO_MASK \ |
1578 #define BLENDER_INNER_LOOP_END_NO_MASK \ |
1419 DA = blend->destinationFullyOpaque ? OWF_FULLY_OPAQUE : DA; \ |
|
1420 } /* end tsColor check */ \ |
|
1421 srcPtr ++; \ |
1579 srcPtr ++; \ |
1422 dstPtr ++; \ |
1580 dstPtr ++; \ |
1423 --colCount; \ |
1581 --colCount; \ |
1424 } \ |
1582 } \ |
1425 srcPtr += srcLineDelta; \ |
1583 srcPtr += srcLineDelta; \ |
1426 dstPtr += dstLineDelta; \ |
1584 dstPtr += dstLineDelta; \ |
1427 --rowCount; \ |
1585 --rowCount; \ |
1428 } |
1586 } |
1429 |
|
1430 #define TSC blend->tsColor->color |
|
1431 #define SC srcPtr->color |
|
1432 |
|
1433 /* Note: actually would be better to compare integer values |
|
1434 * for TSC match -> eliminate float arithmetic pitfalls |
|
1435 */ |
|
1436 #define COLOR_MATCH(x, y) (x.red==y.red && x.green==y.green && x.blue==y.blue) |
|
1437 |
1587 |
1438 #define SA srcPtr->color.alpha |
1588 #define SA srcPtr->color.alpha |
1439 #define SR srcPtr->color.red |
1589 #define SR srcPtr->color.red |
1440 #define SG srcPtr->color.green |
1590 #define SG srcPtr->color.green |
1441 #define SB srcPtr->color.blue |
1591 #define SB srcPtr->color.blue |
1587 break; |
1741 break; |
1588 } |
1742 } |
1589 |
1743 |
1590 case OWF_TRANSPARENCY_SOURCE_ALPHA: |
1744 case OWF_TRANSPARENCY_SOURCE_ALPHA: |
1591 { |
1745 { |
|
1746 #ifndef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
|
1747 OWFuint32 redBlueMask = (ARGB8888_RED_MASK | ARGB8888_BLUE_MASK); |
|
1748 OWFuint32 alphaGreenMask = (ARGB8888_ALPHA_MASK | ARGB8888_GREEN_MASK); |
|
1749 OWFuint32 halfRedBlue = 0x00800080; |
|
1750 #endif |
1592 /* |
1751 /* |
1593 rgb = src.rgb + dst.rgb * (1 - src.alpha) |
1752 rgb = src.rgb + dst.rgb * (1 - src.alpha) |
1594 alpha = src.alpha + dst.alpha * (1 - src.alpha) |
1753 alpha = src.alpha + dst.alpha * (1 - src.alpha) |
1595 */ |
1754 */ |
1596 BLENDER_INNER_LOOP_BEGIN; |
1755 BLENDER_INNER_LOOP_BEGIN; |
1597 DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE; |
1756 #ifdef OWF_IMAGE_INTERNAL_PIXEL_IS_FLOAT |
1598 DG = SG + (DG * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE; |
1757 DR = SR + (DR * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE; |
1599 DB = SB + (DB * (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; |
1600 DA = SA + (DA * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE; |
1759 DB = SB + (DB * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE; |
|
1760 DA = SA + (DA * (OWF_FULLY_OPAQUE - SA) + OWF_BLEND_ROUNDING_VALUE) / OWF_ALPHA_MAX_VALUE; |
|
1761 #else |
|
1762 { |
|
1763 OWFuint32 srcP = *(OWFuint32*)srcPtr; |
|
1764 OWFuint8 srcA = srcP >> ARGB8888_ALPHA_SHIFT; |
|
1765 |
|
1766 if (srcA == OWF_ALPHA_MAX_VALUE) |
|
1767 { |
|
1768 /* Fully opaque source pixel */ |
|
1769 *(OWFuint32*)dstPtr = srcP; |
|
1770 } |
|
1771 else |
|
1772 { |
|
1773 if (srcA) |
|
1774 { |
|
1775 /* Not fully transparent source pixel. Algorithm after Jim Blinn */ |
|
1776 OWFuint32 mask = 0xFF - srcA; |
|
1777 OWFuint32 dstP = *(OWFuint32*)dstPtr; |
|
1778 OWFuint32 blend; |
|
1779 |
|
1780 blend = mask * (dstP & redBlueMask) + halfRedBlue; |
|
1781 srcP += ((blend + ((blend >> 8) & redBlueMask) >> 8)) & redBlueMask; |
|
1782 blend = mask * ((dstP >> 8) & redBlueMask) + halfRedBlue; |
|
1783 srcP += (blend + ((blend >> 8) & redBlueMask)) & alphaGreenMask; |
|
1784 |
|
1785 *(OWFuint32*)dstPtr = srcP; |
|
1786 } |
|
1787 } |
|
1788 } |
|
1789 #endif |
1601 BLENDER_INNER_LOOP_END_NO_MASK; |
1790 BLENDER_INNER_LOOP_END_NO_MASK; |
1602 break; |
1791 break; |
1603 } |
1792 } |
1604 |
1793 |
1605 case OWF_TRANSPARENCY_MASK: |
1794 case OWF_TRANSPARENCY_MASK: |
1681 OWF_Image_AllocData(OWF_DISPCTX dc, OWFint width, OWFint height, OWF_PIXEL_FORMAT pixelFormat) |
1870 OWF_Image_AllocData(OWF_DISPCTX dc, OWFint width, OWFint height, OWF_PIXEL_FORMAT pixelFormat) |
1682 { |
1871 { |
1683 OWF_IMAGE_FORMAT imgf; |
1872 OWF_IMAGE_FORMAT imgf; |
1684 OWFint stride; |
1873 OWFint stride; |
1685 |
1874 |
|
1875 DPRINT(("OWF_Image_AllocData")); |
|
1876 |
1686 /* kludge. GetStride need pixelFormat. */ |
1877 /* kludge. GetStride need pixelFormat. */ |
1687 imgf.pixelFormat = pixelFormat; |
1878 imgf.pixelFormat = pixelFormat; |
1688 imgf.rowPadding = OWF_Image_GetFormatPadding(pixelFormat); |
1879 imgf.rowPadding = OWF_Image_GetFormatPadding(pixelFormat); |
1689 stride = OWF_Image_GetStride(width, &imgf, 0); |
1880 stride = OWF_Image_GetStride(width, &imgf, 0); |
1690 |
1881 |
1832 |
2029 |
1833 /*----------------------------------------------------------------------------*/ |
2030 /*----------------------------------------------------------------------------*/ |
1834 OWF_API_CALL void |
2031 OWF_API_CALL void |
1835 OWF_Image_SwapWidthAndHeight(OWF_IMAGE* image) |
2032 OWF_Image_SwapWidthAndHeight(OWF_IMAGE* image) |
1836 { |
2033 { |
|
2034 DPRINT(("OWF_Image_SwapWidthAndHeight")); |
|
2035 |
1837 /* swap w & h. Note that original stride is not restored if swap back. */ |
2036 /* swap w & h. Note that original stride is not restored if swap back. */ |
1838 image->width ^= image->height; |
2037 image->width ^= image->height; |
1839 image->height ^= image->width; |
2038 image->height ^= image->width; |
1840 image->width ^= image->height; |
2039 image->width ^= image->height; |
1841 |
2040 |