javauis/m3g_akn/src/jni/image2d.inl
changeset 21 2a9601315dfc
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 #include "javax_microedition_m3g_Image2D.h"
       
    18 
       
    19 JNIEXPORT void JNICALL Java_javax_microedition_m3g_Image2D__1set
       
    20 (JNIEnv* aEnv, jclass, jint aHImage2D, jint aX, jint aY, jint aWidth, jint aHeight, jbyteArray aImageArray)
       
    21 {
       
    22     jbyte* imageArray = NULL;
       
    23     if (aImageArray)
       
    24     {
       
    25         imageArray = aEnv->GetByteArrayElements(aImageArray, NULL);
       
    26         if (imageArray == NULL)
       
    27         {
       
    28             M3G_RAISE_EXCEPTION(aEnv, "java/lang/OutOfMemoryError");
       
    29             return;
       
    30         }
       
    31     }
       
    32     M3G_DO_LOCK
       
    33     m3gSetSubImage((M3GImage)aHImage2D, aX, aY, aWidth, aHeight, aImageArray ? aEnv->GetArrayLength(aImageArray) : NULL, imageArray);
       
    34     M3G_DO_UNLOCK(aEnv)
       
    35 
       
    36     if (imageArray)
       
    37     {
       
    38         aEnv->ReleaseByteArrayElements(aImageArray, imageArray, JNI_ABORT);
       
    39     }
       
    40 }
       
    41 
       
    42 static void getImageScanline(const ImageStruct *pImg,
       
    43                              M3Gint line,
       
    44                              M3Guint *pixels,
       
    45                              M3Gbool *trueAlpha)
       
    46 {
       
    47     const CFbsBitmap *bitmap = pImg->color;
       
    48     const int width = bitmap->SizeInPixels().iWidth;
       
    49     int count = width;
       
    50     M3G_ASSERT(count >= 0);
       
    51 
       
    52     M3Guint *dst = pixels;
       
    53 
       
    54     TDisplayMode mode = bitmap->DisplayMode();
       
    55     int stride = bitmap->ScanLineLength(count, mode);
       
    56     bitmap->LockHeap();
       
    57     const void *srcAddr = ((const char *) bitmap->DataAddress()) + line * stride;
       
    58 
       
    59     const CFbsBitmap *mask = pImg->mask;
       
    60 
       
    61     // Alpha data is stored in a separate bitmap if present, so first
       
    62     // just copy the RGB image data with a default full alpha
       
    63 
       
    64     if (mode == EColor16MU || mode == EColor16MA)
       
    65     {
       
    66         const unsigned char *src = (const unsigned char *) srcAddr;
       
    67         while (count--)
       
    68         {
       
    69             M3Guint argb;
       
    70             argb  = (M3Guint)(*src++);  // red -- "src" is a _byte_ pointer to the FbsBitmap's DataAddress
       
    71             argb |= ((M3Guint)(*src++)) <<  8;  // green
       
    72             argb |= ((M3Guint)(*src++)) << 16;      // blue
       
    73             if (mask)
       
    74             {
       
    75                 // if separate alpha bitmap is present, set full alpha and alpha informations
       
    76                 // will be copied in second pass
       
    77                 argb |= 0xFF000000L;    // alpha
       
    78             }
       
    79             else
       
    80             {
       
    81                 // if separate alpha is NULL alpha information must be copied from alpha channel
       
    82                 // of source bitmap to alpha channel of target bitmap
       
    83                 argb |= ((M3Guint)(*src)) << 24;    // alpha
       
    84             }
       
    85             src++;
       
    86             *dst++ = argb;
       
    87         }
       
    88     }
       
    89     else if (mode == EColor64K)
       
    90     {
       
    91         const unsigned short *src = (const unsigned short *) srcAddr;
       
    92         while (count--)
       
    93         {
       
    94             unsigned short pixel = *src++;
       
    95             *dst++ = 0xFF000000L
       
    96                      | (((pixel & 0x001F) >> 2) | ((pixel & 0x001F) << 3))
       
    97                      | (((pixel & 0x0600) >> 1) | ((pixel & 0x07E0) << 5))
       
    98                      | (((pixel & 0xE000) << 3) | ((pixel & 0xF800) << 8));
       
    99         }
       
   100     }
       
   101     else if (mode == EColor4K)
       
   102     {
       
   103         const unsigned short *src = (const unsigned short *) srcAddr;
       
   104         while (count--)
       
   105         {
       
   106             unsigned short pixel = *src++;
       
   107             *dst++ = 0xFF000000L
       
   108                      | ((pixel & 0x000F) | ((pixel & 0x000F) << 4))
       
   109                      | (((pixel & 0x00F0) | ((pixel & 0x00F0) << 4)) << 4)
       
   110                      | (((pixel & 0x0F00) | ((pixel & 0x0F00) << 4)) << 8);
       
   111         }
       
   112     }
       
   113     else
       
   114     {
       
   115         M3G_ASSERT(M3G_FALSE);
       
   116     }
       
   117     bitmap->UnlockHeap();
       
   118 
       
   119     // Check for the presence of an alpha mask, and if present, do a
       
   120     // second pass to mix that into the RGB values already copied
       
   121 
       
   122     *trueAlpha = (mask != NULL);
       
   123 
       
   124     if (mask)
       
   125     {
       
   126 
       
   127         mask->LockHeap();
       
   128 
       
   129         // NOTE: we assume that if the alpha mask is using an RGBA
       
   130         // display mode as the base bitmap, the alpha value is stored
       
   131         // in the red color channel of the mask only.
       
   132         //
       
   133 
       
   134         dst = pixels;
       
   135         count = width;
       
   136 
       
   137         mode = mask->DisplayMode();
       
   138         stride = mask->ScanLineLength(mask->SizeInPixels().iWidth, mode);
       
   139         srcAddr = ((const char *) mask->DataAddress()) + line * stride;
       
   140 
       
   141         if (mode == EColor16MU || mode == EColor16MA)
       
   142         {
       
   143             const unsigned long *src = (const unsigned long *) srcAddr;
       
   144             while (count--)
       
   145             {
       
   146                 unsigned short mask = *src++;
       
   147                 *dst++ = (*dst & 0x00FFFFFF) | ((mask & 0x00FF) << 24);
       
   148             }
       
   149         }
       
   150         else if (mode == EColor64K)
       
   151         {
       
   152             const unsigned short *src = (const unsigned short *) srcAddr;
       
   153             while (count--)
       
   154             {
       
   155                 unsigned short mask = *src++;
       
   156                 *dst++ = (*dst & 0x00FFFFFF) |
       
   157                          ((((mask & 0x001F) >> 2) | ((mask & 0x001F) << 3)) << 24);
       
   158             }
       
   159         }
       
   160         else if (mode == EColor4K)
       
   161         {
       
   162             const unsigned short *src = (const unsigned short *) srcAddr;
       
   163             while (count--)
       
   164             {
       
   165                 unsigned short mask = *src++;
       
   166                 *dst++ = (*dst & 0x00FFFFFF) | (((mask & 0x000F) | ((mask & 0x000F) << 4)) << 24);
       
   167             }
       
   168         }
       
   169         else if (mode == EGray256)
       
   170         {
       
   171             const unsigned char *src = (const unsigned char *) srcAddr;
       
   172             while (count--)
       
   173             {
       
   174                 *dst++ = (*dst & 0x00FFFFFF) | ((*src++) << 24);
       
   175             }
       
   176         }
       
   177         else if (mode == EGray2)
       
   178         {
       
   179 
       
   180             // Initialize src as byte type
       
   181             const unsigned char *src = (const unsigned char *) srcAddr;
       
   182 
       
   183             /* Go through each pixel in the stride one by one.
       
   184             /  Each src (EGray2 type bitmap) byte holds 8 pixels aplha mask, i.e 1 Bpp,
       
   185             /  so check each bit in the byte and set aplha for the dst bitmap either to 0xFF
       
   186             /  or to 0x00 depending source bit values 1/0.
       
   187             */
       
   188 
       
   189             /* Counter for the bits in one byte, i.e. 0-7 */
       
   190             int bit = 0;
       
   191 
       
   192             /* count = number of pixels in one stride */
       
   193             while (count)
       
   194             {
       
   195                 while (bit < 8)
       
   196                 {
       
   197                     *dst++ = (*dst & 0x00FFFFFF) | (((*src) & 0x01 << bit) ? 0xFF << 24 : 0x0);
       
   198                     bit++;
       
   199                     count--;
       
   200 
       
   201                     /* If we have processed all pixels in the image scanline,
       
   202                     /  exit and discard rest of the bits in the byte.
       
   203                     */
       
   204 
       
   205                     if (count <= 0) break;
       
   206                 }
       
   207                 /* reset bit counter as we move on to the next byte */
       
   208                 bit = 0;
       
   209                 *src++;
       
   210             }
       
   211         }
       
   212         else
       
   213         {
       
   214             M3G_ASSERT(M3G_FALSE);
       
   215         }
       
   216         mask->UnlockHeap();
       
   217     }
       
   218 }
       
   219 
       
   220 static void createImage(M3GInterface m3g,
       
   221                         M3GImage *img,
       
   222                         M3GImageFormat format,
       
   223                         ImageStruct *pImage)
       
   224 {
       
   225     M3GImage image;
       
   226 
       
   227     TSize sz = pImage->color->SizeInPixels();
       
   228     M3Gint width = sz.iWidth, height = sz.iHeight;
       
   229 
       
   230     image = m3gCreateImage(m3g, format, width, height, 0);
       
   231     if (image == NULL)
       
   232     {
       
   233         img = NULL;
       
   234         return;    // exception automatically raised
       
   235     }
       
   236 
       
   237     {
       
   238         M3Gint y;
       
   239 
       
   240         //M3Guint *tempPixels = (M3Guint *) User::Alloc(width * 4);
       
   241         M3Guint *tempPixels = (M3Guint *) malloc(width * 4);
       
   242         if (tempPixels == NULL)
       
   243         {
       
   244             m3gDeleteObject((M3GObject) image);
       
   245             *img = NULL;
       
   246             return;
       
   247         }
       
   248 
       
   249         for (y = 0; y < height; ++y)
       
   250         {
       
   251             M3Gbool trueAlpha;
       
   252             getImageScanline(pImage, y, tempPixels, &trueAlpha);
       
   253             m3gSetImageScanline(image, y, trueAlpha, tempPixels);
       
   254         }
       
   255         m3gCommitImage(image);
       
   256 
       
   257         //User::Free(tempPixels);
       
   258         free(tempPixels);
       
   259         *img = image;
       
   260     }
       
   261 }
       
   262 
       
   263 JNIEXPORT jint JNICALL Java_javax_microedition_m3g_Image2D__1ctorImage
       
   264 (JNIEnv* aEnv, jclass, jint aEventSourceHandle, jint aHM3g, jint aFormat, jint aImageHandle)
       
   265 {
       
   266     if (aImageHandle != NULL)
       
   267     {
       
   268         ImageStruct imageStruct;
       
   269         MMIDImage* image = JavaUnhand<MMIDImage>(aImageHandle);
       
   270         MMIDBitmapImage* bitmapImage = image->BitmapImage();
       
   271         if (!bitmapImage)
       
   272         {
       
   273             return NULL;
       
   274         }
       
   275         imageStruct.color = bitmapImage->ColorBitmap();
       
   276         imageStruct.mask = bitmapImage->AlphaBitmap();
       
   277         bitmapImage->RemoveRef();
       
   278 
       
   279         CJavaM3GEventSource* eventSource = JavaUnhand<CJavaM3GEventSource>(aEventSourceHandle);
       
   280         M3GInterface m3g = (M3GInterface)aHM3g;
       
   281 
       
   282         M3GImage img;
       
   283 
       
   284         M3G_DO_LOCK
       
   285         eventSource->ExecuteV(&createImage,
       
   286                               m3g, &img, (M3GImageFormat) aFormat, &imageStruct);
       
   287         M3G_DO_UNLOCK(aEnv)
       
   288 
       
   289         return (jint)img;
       
   290     }
       
   291 
       
   292     return 0;
       
   293 }
       
   294 
       
   295 JNIEXPORT jint JNICALL Java_javax_microedition_m3g_Image2D__1getFormat
       
   296 (JNIEnv* aEnv, jclass, jint aHImage2D)
       
   297 {
       
   298     M3G_DO_LOCK
       
   299     jint format = (jint)m3gGetFormat((M3GImage)aHImage2D);
       
   300     M3G_DO_UNLOCK(aEnv)
       
   301     return format;
       
   302 }
       
   303 
       
   304 JNIEXPORT jint JNICALL Java_javax_microedition_m3g_Image2D__1ctorSizePixelsPalette
       
   305 (JNIEnv* aEnv, jclass, jint aM3g, jint aFormat, jint aWidth, jint aHeight, jbyteArray aImage, jbyteArray aPalette)
       
   306 {
       
   307     M3GImageFormat format = (M3GImageFormat)aFormat;
       
   308 
       
   309     int bpp = jsr184BytesPerPixel(format);
       
   310 
       
   311     if (validateArray(aEnv, aImage, aWidth * aHeight))
       
   312     {
       
   313         if (aPalette == NULL)
       
   314         {
       
   315             M3G_RAISE_EXCEPTION(aEnv, "java/lang/NullPointerException");
       
   316             return 0;
       
   317         }
       
   318         int paletteLen = aEnv->GetArrayLength(aPalette);
       
   319         if ((paletteLen < 256 *(unsigned)bpp) &&
       
   320                 (paletteLen % (unsigned)bpp != 0))
       
   321         {
       
   322             M3G_RAISE_EXCEPTION(aEnv, "java/lang/IllegalArgumentException");
       
   323             return 0;
       
   324         }
       
   325         else
       
   326         {
       
   327             M3G_DO_LOCK
       
   328 
       
   329             M3GImage hImg = m3gCreateImage((M3GInterface)aM3g,
       
   330                                            format,
       
   331                                            aWidth, aHeight,
       
   332                                            M3G_PALETTED);
       
   333             if (hImg != NULL)
       
   334             {
       
   335                 jbyte* palette = NULL;
       
   336 
       
   337                 int numEntries = paletteLen / bpp;
       
   338                 if (numEntries > 256)
       
   339                 {
       
   340                     numEntries = 256;
       
   341                 }
       
   342 
       
   343                 jbyte* image = aEnv->GetByteArrayElements(aImage, NULL);
       
   344                 if (image == NULL)
       
   345                 {
       
   346                     M3G_RAISE_EXCEPTION(aEnv, "java/lang/OutOfMemoryError");
       
   347                     return 0;
       
   348                 }
       
   349 
       
   350                 m3gSetImage(hImg, image);
       
   351 
       
   352                 palette = aEnv->GetByteArrayElements(aPalette, NULL);
       
   353                 if (palette == NULL)
       
   354                 {
       
   355                     if (image)
       
   356                     {
       
   357                         aEnv->ReleaseByteArrayElements(aImage, image, JNI_ABORT);
       
   358                     }
       
   359                     M3G_RAISE_EXCEPTION(aEnv, "java/lang/OutOfMemoryError");
       
   360                     return 0;
       
   361                 }
       
   362 
       
   363                 m3gSetImagePalette(hImg, numEntries, palette);
       
   364                 m3gCommitImage(hImg);
       
   365 
       
   366                 if (image)
       
   367                 {
       
   368                     aEnv->ReleaseByteArrayElements(aImage, image, JNI_ABORT);
       
   369                 }
       
   370                 if (palette)
       
   371                 {
       
   372                     aEnv->ReleaseByteArrayElements(aPalette, palette, JNI_ABORT);
       
   373                 }
       
   374             }
       
   375             M3G_DO_UNLOCK(aEnv)
       
   376             return ((unsigned) hImg);
       
   377         }
       
   378     }
       
   379     return 0;
       
   380 }
       
   381 
       
   382 JNIEXPORT jboolean JNICALL Java_javax_microedition_m3g_Image2D__1isMutable
       
   383 (JNIEnv* aEnv, jclass, jint aHImage2D)
       
   384 {
       
   385     M3G_DO_LOCK
       
   386     jboolean isMutable = (jboolean)m3gIsMutable((M3GImage)aHImage2D);
       
   387     M3G_DO_UNLOCK(aEnv)
       
   388     return isMutable;
       
   389 }
       
   390 
       
   391 JNIEXPORT jint JNICALL Java_javax_microedition_m3g_Image2D__1getHeight
       
   392 (JNIEnv* aEnv, jclass, jint aHImage2D)
       
   393 {
       
   394     M3G_DO_LOCK
       
   395     jint height = (jint)m3gGetHeight((M3GImage)aHImage2D);
       
   396     M3G_DO_UNLOCK(aEnv)
       
   397     return height;
       
   398 }
       
   399 
       
   400 JNIEXPORT jint JNICALL Java_javax_microedition_m3g_Image2D__1ctorSize
       
   401 (JNIEnv* aEnv, jclass, jint aM3g, jint aFormat, jint aWidth, jint aHeight)
       
   402 {
       
   403     M3G_DO_LOCK
       
   404     jint handle = (M3Guint) m3gCreateImage((M3GInterface)aM3g,
       
   405                                            (M3GImageFormat)aFormat,
       
   406                                            aWidth, aHeight,
       
   407                                            M3G_DYNAMIC|M3G_RENDERING_TARGET);
       
   408     M3G_DO_UNLOCK(aEnv)
       
   409     return handle;
       
   410 }
       
   411 
       
   412 JNIEXPORT jint JNICALL Java_javax_microedition_m3g_Image2D__1getWidth
       
   413 (JNIEnv* aEnv, jclass, jint aHImage2D)
       
   414 {
       
   415     M3G_DO_LOCK
       
   416     jint width = (jint)m3gGetWidth((M3GImage)aHImage2D);
       
   417     M3G_DO_UNLOCK(aEnv)
       
   418     return width;
       
   419 }
       
   420 
       
   421 
       
   422 JNIEXPORT jint JNICALL Java_javax_microedition_m3g_Image2D__1ctorSizePixels
       
   423 (JNIEnv* aEnv, jclass, jint aM3g, jint aFormat, jint aWidth, jint aHeight, jbyteArray aImage)
       
   424 {
       
   425     M3GImageFormat format = (M3GImageFormat)aFormat;
       
   426 
       
   427     if (validateArray(aEnv, aImage, jsr184BytesPerPixel(format) * aWidth * aHeight))
       
   428     {
       
   429         M3G_DO_LOCK
       
   430 
       
   431         M3GImage hImg = m3gCreateImage((M3GInterface)aM3g, format, aWidth, aHeight, 0);
       
   432         if (hImg != NULL)
       
   433         {
       
   434             M3GImageFormat format = (M3GImageFormat)aFormat;
       
   435 
       
   436             int bpp = jsr184BytesPerPixel(format);
       
   437             jbyte* imageScanline = (jbyte*)malloc(aWidth * bpp);
       
   438             for (int i=0; i < aHeight; i++)
       
   439             {
       
   440                 aEnv->GetByteArrayRegion(aImage, aWidth * i * bpp, aWidth * bpp, imageScanline);
       
   441                 m3gSetSubImage(hImg, 0, i, aWidth, 1, aWidth * bpp, imageScanline);
       
   442             }
       
   443             m3gCommitImage(hImg);
       
   444 
       
   445             free(imageScanline);
       
   446         }
       
   447         M3G_DO_UNLOCK(aEnv)
       
   448         return (unsigned) hImg;
       
   449     }
       
   450     return 0;
       
   451 }