javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/library/graphics/qt/imagebase.cpp
changeset 80 d6dafc5d983f
equal deleted inserted replaced
78:71ad690e91f5 80:d6dafc5d983f
       
     1 /*******************************************************************************
       
     2  * Copyright (c) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved. This program and the accompanying materials
       
     4  * are made available under the terms of the Eclipse Public License v1.0
       
     5  * which accompanies this distribution, and is available at
       
     6  * http://www.eclipse.org/legal/epl-v10.html
       
     7  *
       
     8  * Contributors:
       
     9  *     Nokia Corporation - initial API and implementation
       
    10  *******************************************************************************/
       
    11 
       
    12 #include "imagebase.h"
       
    13 #include "gfxlog.h"
       
    14 
       
    15 namespace Java { namespace GFX {
       
    16 
       
    17 ImageBase::ImageBase() : mAlpha(-1), mHasMask(false)
       
    18     {
       
    19     }
       
    20 
       
    21 ImageBase::~ImageBase()
       
    22     {
       
    23     }
       
    24 
       
    25 void ImageBase::doGetRgb(QImage& image, int* aRgbdata, int aOffset, int aScanlength, 
       
    26                          int aX, int aY, int aWidth, int aHeight)
       
    27     {
       
    28     GFX_LOG_FUNC_CALL();
       
    29 
       
    30     if(aX != 0 || aY != 0 || aWidth < image.width() || aHeight < image.height())
       
    31         {
       
    32         image = image.copy(aX, aY, aWidth, aHeight);
       
    33         if(image.isNull())
       
    34             {
       
    35             throw GfxException(EGfxErrorNoMemory, "copying from original image failed");
       
    36             }
       
    37         }
       
    38 
       
    39     // If image is not 32bpp we need to convert it
       
    40     if(image.format() != QImage::Format_RGB32 &&
       
    41        image.format() != QImage::Format_ARGB32)
       
    42         {
       
    43         image = image.convertToFormat(QImage::Format_ARGB32);
       
    44         if(image.isNull())
       
    45             {
       
    46             throw GfxException(EGfxErrorNoMemory, "format convertion to 32bpp failed");
       
    47             }
       
    48         }
       
    49 
       
    50     // Temporary storage for pixels
       
    51     QRgb* pixel = NULL;
       
    52 
       
    53     // dataArray index, start from offset
       
    54     int targetIndex = aOffset;
       
    55     // Iterate through lines
       
    56     for(int b = 0; b < aHeight; ++b)
       
    57         {
       
    58         // Obtain pointer to start of current line (y)
       
    59         const unsigned char* lineStart = image.scanLine(b);
       
    60         // Iterate through pixels on each line
       
    61         for (int a = 0; a < aWidth; ++a)
       
    62             {
       
    63             // Set the current pixel, relative to line start
       
    64             pixel = ((QRgb*)lineStart) + a;
       
    65             // Move target pointer to the next slot
       
    66             targetIndex = aOffset + a + (b * aScanlength);
       
    67             // Shift pixels to correct places, needed for 32-bit format
       
    68             // as the bits order in memory may vary between systems
       
    69             aRgbdata[targetIndex] =  ((qAlpha(*pixel) & 0xff) << 24) |
       
    70                                      ((qRed(*pixel)   & 0xff) << 16) |
       
    71                                      ((qGreen(*pixel) & 0xff) << 8 ) |
       
    72                                      ((qBlue(*pixel)  & 0xff));
       
    73             }
       
    74         }
       
    75     }
       
    76 
       
    77 void ImageBase::doGetRgb(QImage& image, char* aRgbdata, char* aTransparencyMask,int aOffset, 
       
    78                          int aScanlength, int aX, int aY, int aWidth, int aHeight, int aFormat)
       
    79     {
       
    80     GFX_LOG_FUNC_CALL();
       
    81 
       
    82     if(aX != 0 || aY != 0 || aWidth < image.width() || aHeight < image.height())
       
    83         {
       
    84         image = image.copy(aX, aY, aWidth, aHeight);
       
    85         if(image.isNull())
       
    86             {
       
    87             throw GfxException(EGfxErrorNoMemory, "copying from original image failed");
       
    88             }
       
    89         }
       
    90 
       
    91     if(aScanlength < 0)
       
    92         {
       
    93          image = image.mirrored(false, true);
       
    94          if(image.isNull())
       
    95              {
       
    96              throw GfxException(EGfxErrorNoMemory, "Mirroring failed");
       
    97              }
       
    98         }
       
    99 
       
   100     // If image is not monochrome we need to convert it
       
   101     if(image.format() != QImage::Format_Mono)
       
   102     {
       
   103         image = image.convertToFormat(QImage::Format_Mono);
       
   104         if(image.isNull())
       
   105         {
       
   106             throw GfxException(EGfxErrorNoMemory, "Format conversion to 8bpp failed");
       
   107         }
       
   108     }
       
   109 
       
   110     // dataArray index, start from offset
       
   111     int targetIndex = aOffset;
       
   112 
       
   113     const unsigned char* imageStart = image.bits();
       
   114     QImage mask = image.alphaChannel();
       
   115     const unsigned char* maskStart = mask.bits();
       
   116 
       
   117     // Find the number of full bytes
       
   118     int fullBytes = aWidth/8;
       
   119     int bpl = image.bytesPerLine();
       
   120 
       
   121     if(bpl == fullBytes)
       
   122         {
       
   123         memcpy(aRgbdata+targetIndex, imageStart, bpl*aHeight);
       
   124         memcpy(aTransparencyMask+targetIndex, maskStart, bpl*aHeight);
       
   125         }
       
   126     else
       
   127         {
       
   128         memcpy(aRgbdata+targetIndex, imageStart, fullBytes*aHeight + aHeight);
       
   129         memcpy(aTransparencyMask+targetIndex, maskStart, fullBytes*aHeight + aHeight);
       
   130         }
       
   131     }
       
   132 
       
   133 void ImageBase::doGetRgb(QImage& image, short* aRgbdata, int aOffset, int aScanlength, 
       
   134                          int aX, int aY, int aWidth, int aHeight, int aFormat)
       
   135     {
       
   136     GFX_LOG_FUNC_CALL();
       
   137 
       
   138     // Match format to QT
       
   139     int format;
       
   140     switch (aFormat) {
       
   141         case EFormatRGB555:
       
   142             format = QImage::Format_RGB555;
       
   143             break;
       
   144         case EFormatRGB16:
       
   145             format = QImage::Format_RGB16;
       
   146             break;
       
   147          case EFormatRGB444:
       
   148             format = QImage::Format_RGB444;
       
   149             break;
       
   150          case EFormatARGB4444Premultiplied:
       
   151             format = QImage::Format_ARGB4444_Premultiplied;
       
   152             break;
       
   153          default:
       
   154             format = QImage::Format_RGB16;
       
   155     }
       
   156 
       
   157     if(aX != 0 || aY != 0 || aWidth < image.width() || aHeight < image.height())
       
   158         {
       
   159         image = image.copy(aX, aY, aWidth, aHeight);
       
   160         if(image.isNull())
       
   161             {
       
   162             throw GfxException(EGfxErrorNoMemory, "copying from original image failed");
       
   163             }
       
   164         }
       
   165 
       
   166     // If image is not format we need, convert it
       
   167     if(image.format() != format)
       
   168         {
       
   169         image = image.convertToFormat((QImage::Format)format);
       
   170         if(image.isNull())
       
   171             {
       
   172             throw GfxException(EGfxErrorNoMemory, "format convertion to 16bpp failed");
       
   173             }
       
   174         }
       
   175 
       
   176     // Temporary storage for pixels
       
   177     short* pixel = NULL;
       
   178     // dataArray index, start from offset
       
   179     int targetIndex = aOffset;
       
   180 
       
   181     // Iterate through lines
       
   182     for(int b=0; b < aHeight; b++)
       
   183         {
       
   184         // Obtain pointer to start of current line (y)
       
   185         const unsigned char* lineStart = image.scanLine(b);
       
   186         // Iterate through pixels on each line
       
   187         for(int a=0; a < aWidth; a++)
       
   188             {
       
   189             // Set the current pixel, relative to line start
       
   190             pixel = ((short*)lineStart) + a;
       
   191             // Move target pointer to the next slot
       
   192             targetIndex = aOffset + a + (b * aScanlength);
       
   193             aRgbdata[targetIndex] =  *pixel;
       
   194             }
       
   195         }
       
   196     }
       
   197 
       
   198 QTransform ImageBase::generateTransformMatrix(TTransform aTransform)
       
   199     {
       
   200     GFX_LOG_FUNC_CALL();
       
   201 
       
   202     // In case there's both mirror and rotate is requested, the angle of rotation
       
   203     // must be negative since when the transform is applied the z-axis is processed
       
   204     // before y-axis, while the spec mandates reverse order. So by having negative  
       
   205     // degrees for rotation along z-axis here, gives correct output.
       
   206     QTransform transform;
       
   207     switch(aTransform) 
       
   208         {
       
   209         case ETransNone:
       
   210             // No transform or mirror
       
   211             break;
       
   212         case ETransRot90:
       
   213             transform.rotate(90, Qt::ZAxis);
       
   214             break;
       
   215         case ETransRot180:
       
   216             transform.rotate(180, Qt::ZAxis);
       
   217             break;
       
   218         case ETransRot270:
       
   219             transform.rotate(270, Qt::ZAxis);
       
   220             break;
       
   221         case ETransMirror:
       
   222             transform.rotate(180,Qt::YAxis);
       
   223             break;
       
   224         case ETransMirrorRot90:
       
   225             transform.rotate(180, Qt::YAxis);
       
   226             transform.rotate(-90, Qt::ZAxis);
       
   227             break;
       
   228         case ETransMirrorRot180:
       
   229             transform.rotate(180, Qt::YAxis);
       
   230             transform.rotate(-180, Qt::ZAxis);
       
   231             break;
       
   232         case ETransMirrorRot270:
       
   233             transform.rotate(180, Qt::YAxis);
       
   234             transform.rotate(-270, Qt::ZAxis);
       
   235             break;
       
   236         default:
       
   237             Q_ASSERT_X(false, "Graphics", "Transform type not recognized");
       
   238         }
       
   239     return transform;
       
   240     }
       
   241 
       
   242 int ImageBase::getAlpha() 
       
   243     {
       
   244     return mAlpha;
       
   245     }
       
   246 
       
   247 bool ImageBase::hasMask()
       
   248     {
       
   249     return mHasMask;
       
   250     }
       
   251 
       
   252 QImage ImageBase::imageDataToQImage(ImageDataWrapper* aData)
       
   253     {
       
   254     if(aData->getDepth() != 32)
       
   255         {
       
   256         // Java side always converts the ImageData to 32 bit before passing it
       
   257         // to native side, bail out if we get something else
       
   258         throw GfxException(EGfxErrorNoMemory, "Only 32 bit ImageData is supported in Image creation");
       
   259         }
       
   260 
       
   261     int bpp = 4; // bit depth = 32, 4 bytes per pixel
       
   262     int size = aData->getWidth()*aData->getHeight()*bpp;
       
   263     char* pixelData = aData->getData(ImageDataWrapper::EPixelData);
       
   264 
       
   265     for(int index = 0; index < size; index += bpp)
       
   266         {
       
   267         int pixel = *(reinterpret_cast<int*>(pixelData+index));
       
   268 
       
   269         pixelData[index]   = (uchar)(pixel >> 24) & 0xFF;
       
   270         pixelData[index+1] = (uchar)(pixel >> 16) & 0xFF;
       
   271         pixelData[index+2] = (uchar)(pixel >> 8) & 0xFF;
       
   272         pixelData[index+3] = 0xFF; // Set alpha to opaque here, alpha channel data will be handled later
       
   273         }
       
   274 
       
   275     QImage image(reinterpret_cast<uchar*>(aData->getData(ImageDataWrapper::EPixelData)),
       
   276                                               aData->getWidth(),
       
   277                                               aData->getHeight(),
       
   278                                               aData->getBytesPerLine(),
       
   279                                               QImage::Format_ARGB32);
       
   280     if(image.isNull())
       
   281         {
       
   282         throw GfxException(EGfxErrorNoMemory, "Image creation failed");
       
   283         }
       
   284 
       
   285     // Set indexed palette (if one is set)
       
   286     if(!aData->isDirect())
       
   287         {
       
   288         image.setColorTable(*aData->getPaletteData()->getIndexedPalette());
       
   289         }
       
   290 
       
   291     mHasMask = false;
       
   292     mAlpha = aData->getAlpha();
       
   293 
       
   294     if(aData->getData(ImageDataWrapper::EMaskData))
       
   295         {
       
   296         QImage mask(reinterpret_cast<uchar*>(aData->getData(ImageDataWrapper::EMaskData)),
       
   297                                              aData->getWidth(),
       
   298                                              aData->getHeight(),
       
   299                                              QImage::Format_Mono);
       
   300         if(mask.isNull())
       
   301             {
       
   302             throw GfxException(EGfxErrorNoMemory, "Image alpha channel creation failed");
       
   303             }
       
   304         image.setAlphaChannel(mask);
       
   305         mHasMask = true;
       
   306         }
       
   307     else if(mAlpha != -1)
       
   308         {
       
   309         // Global alpha is set, overrides alpha channel data
       
   310         QImage alpha(aData->getWidth(), aData->getHeight(), QImage::Format_Indexed8);
       
   311         if(alpha.isNull())
       
   312             {
       
   313             throw GfxException(EGfxErrorNoMemory, "Image alpha channel creation failed");
       
   314             }
       
   315 
       
   316         alpha.fill(aData->getAlpha());
       
   317         image.setAlphaChannel(alpha);
       
   318         }
       
   319     else if(aData->getData(ImageDataWrapper::EAlphaData))
       
   320         {
       
   321         // Alpha channel data is set
       
   322         const int w = aData->getWidth();
       
   323         QImage alpha(reinterpret_cast<uchar*>(aData->getData(ImageDataWrapper::EAlphaData)),
       
   324                                               w,
       
   325                                               aData->getHeight(),
       
   326                                               w,
       
   327                                               QImage::Format_Indexed8);
       
   328         QVector<QRgb> colors(255);
       
   329         for(int i=0; i<255; i++)
       
   330             {
       
   331             colors[i] = qRgb(i, i, i);
       
   332             }
       
   333         alpha.setColorTable(colors);
       
   334         colors.clear();
       
   335 
       
   336         if(alpha.isNull())
       
   337             {
       
   338             throw GfxException(EGfxErrorNoMemory, "Image alpha channel creation failed");
       
   339             }
       
   340         image.setAlphaChannel(alpha);
       
   341         }
       
   342     return image;
       
   343     }
       
   344 
       
   345 
       
   346 QImage::Format ImageBase::mapInternalFormatToQt(TImageFormat internalImageFormat)
       
   347     {
       
   348     switch (internalImageFormat) 
       
   349         {
       
   350         case EFormatARGB32:
       
   351             return QImage::Format_ARGB32;
       
   352         case EFormatRGB32:
       
   353             return QImage::Format_RGB32;
       
   354         case EFormatARGB32Premultiplied:
       
   355             return QImage::Format_ARGB32_Premultiplied;
       
   356          case EFormatRGB16:
       
   357             return QImage::Format_RGB16;
       
   358          case EFormatRGB555:
       
   359             return QImage::Format_RGB555;
       
   360          case EFormatRGB444:
       
   361             return QImage::Format_RGB444;
       
   362          case EFormatARGB4444Premultiplied:
       
   363             return QImage::Format_ARGB4444_Premultiplied;
       
   364          case EFormatMONO:
       
   365             return QImage::Format_Mono;
       
   366          default:
       
   367             return QImage::Format_Invalid;
       
   368         }
       
   369     }
       
   370 
       
   371 TImageFormat ImageBase::mapQtFormatToInternal(QImage::Format qtImageFormat)
       
   372     {
       
   373     switch (qtImageFormat) 
       
   374         {
       
   375         case QImage::Format_ARGB32:
       
   376             return EFormatARGB32;
       
   377         case QImage::Format_RGB32:
       
   378             return EFormatRGB32;
       
   379         case QImage::Format_ARGB32_Premultiplied:
       
   380             return EFormatARGB32Premultiplied;
       
   381          case QImage::Format_RGB16:
       
   382             return EFormatRGB16;
       
   383          case QImage::Format_RGB555:
       
   384             return EFormatRGB555;
       
   385          case QImage::Format_RGB444:
       
   386             return EFormatRGB444;
       
   387          case QImage::Format_ARGB4444_Premultiplied:
       
   388             return EFormatARGB4444Premultiplied;
       
   389          case QImage::Format_Mono:
       
   390             return EFormatMONO;
       
   391          default:
       
   392             return EFormatNone;
       
   393         }
       
   394     }
       
   395 
       
   396 } // namespace GFX
       
   397 } // namespace Java