예제 #1
0
bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleToFit) {
    const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth(image));
    const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHeight(image));
    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);

    SkBitmap tmp;
    if (!tmp.allocPixels(info)) {
        return false;
    }

    if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), image)) {
        return false;
    }

    CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image);
    switch (cgInfo) {
        case kCGImageAlphaNone:
        case kCGImageAlphaNoneSkipLast:
        case kCGImageAlphaNoneSkipFirst:
            SkASSERT(SkBitmap::ComputeIsOpaque(tmp));
            tmp.setAlphaType(kOpaque_SkAlphaType);
            break;
        default:
            // we don't know if we're opaque or not, so compute it.
            if (SkBitmap::ComputeIsOpaque(tmp)) {
                tmp.setAlphaType(kOpaque_SkAlphaType);
            }
    }

    *dst = tmp;
    return true;
}
예제 #2
0
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
    CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);

    if (NULL == imageSrc) {
        return false;
    }
    SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);

    CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL);
    if (NULL == image) {
        return false;
    }
    SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);

    const int width = SkToInt(CGImageGetWidth(image));
    const int height = SkToInt(CGImageGetHeight(image));

    bm->setInfo(SkImageInfo::MakeN32Premul(width, height));
    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
        return true;
    }

    if (!this->allocPixelRef(bm, NULL)) {
        return false;
    }

    SkAutoLockPixels alp(*bm);

    if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) {
        return false;
    }

    CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
    switch (info) {
        case kCGImageAlphaNone:
        case kCGImageAlphaNoneSkipLast:
        case kCGImageAlphaNoneSkipFirst:
            SkASSERT(SkBitmap::ComputeIsOpaque(*bm));
            bm->setAlphaType(kOpaque_SkAlphaType);
            break;
        default:
            // we don't know if we're opaque or not, so compute it.
            if (SkBitmap::ComputeIsOpaque(*bm)) {
                bm->setAlphaType(kOpaque_SkAlphaType);
            }
    }
    if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) {
        // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied.
        // Convert to unpremultiplied.
        for (int i = 0; i < width; ++i) {
            for (int j = 0; j < height; ++j) {
                uint32_t* addr = bm->getAddr32(i, j);
                *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr);
            }
        }
        bm->setAlphaType(kUnpremul_SkAlphaType);
    }
    return true;
}
예제 #3
0
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
    CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);

    if (NULL == imageSrc) {
        return false;
    }
    SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);

    CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL);
    if (NULL == image) {
        return false;
    }
    SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);

    const int width = CGImageGetWidth(image);
    const int height = CGImageGetHeight(image);
    bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
        return true;
    }

    if (!this->allocPixelRef(bm, NULL)) {
        return false;
    }

    bm->lockPixels();
    bm->eraseColor(SK_ColorTRANSPARENT);

    // use the same colorspace, so we don't change the pixels at all
    CGColorSpaceRef cs = CGImageGetColorSpace(image);
    CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO);
    if (NULL == cg) {
        // perhaps the image's colorspace does not work for a context, so try just rgb
        cs = CGColorSpaceCreateDeviceRGB();
        cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO);
        CFRelease(cs);
    }
    CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image);
    CGContextRelease(cg);

    CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
    switch (info) {
        case kCGImageAlphaNone:
        case kCGImageAlphaNoneSkipLast:
        case kCGImageAlphaNoneSkipFirst:
            SkASSERT(SkBitmap::ComputeIsOpaque(*bm));
            bm->setIsOpaque(true);
            break;
        default:
            // we don't know if we're opaque or not, so compute it.
            bm->computeAndSetOpaquePredicate();
    }
    bm->unlockPixels();
    return true;
}
예제 #4
0
cv::Mat &osx_cv::toMat(
        const CGImageRef &image,
        cv::Mat &out,
        osx::disp::RGBType destType
        ) {
    cv::Mat temp;

    size_t w = CGImageGetWidth(image), h = CGImageGetHeight(image);

    if (CGImageGetBitsPerPixel(image) != 32) {
        throw invalid_argument("`image` must be 32 bits per pixel");
    }

    temp.create(int(h), int(w), CV_8UC4);

    CGColorSpaceRef colorSpace = CGImageGetColorSpace(image);

    CGContextRef context = CGBitmapContextCreate(
            temp.data,
            w,
            h,
            CGImageGetBitsPerComponent(image),
            CGImageGetBytesPerRow(image),
            colorSpace,
            CGImageGetAlphaInfo(image)
    );

    CGContextDrawImage(
            context,
            CGRectMake(0, 0, (CGFloat)w, (CGFloat)h),
            image
            );

    _cvtRGBColor(temp, out, CGImageGetAlphaInfo(image), destType);

    CGContextRelease(context);

    return out;
}
예제 #5
0
CFX_QuartzDeviceDriver::CFX_QuartzDeviceDriver(CGContextRef context, FX_INT32 deviceClass)
{
    m_saveCount = 0;
    _context		= context;
    _deviceClass	= deviceClass;
    CGContextRetain(_context);
    CGRect r = CGContextGetClipBoundingBox(context);
    _width	= FXSYS_round(r.size.width);
    _height	= FXSYS_round(r.size.height);
    _renderCaps = FXRC_SOFT_CLIP | FXRC_BLEND_MODE |
                  FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
                  FXRC_BIT_MASK | FXRC_ALPHA_MASK;
    if (_deviceClass != FXDC_DISPLAY) {
    } else {
        CGImageRef image = CGBitmapContextCreateImage(_context);
        if (image) {
            _renderCaps |= FXRC_GET_BITS;
            _width = CGImageGetWidth(image);
            _height = CGImageGetHeight(image);
            CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(image);
            if (kCGImageAlphaPremultipliedFirst == alphaInfo ||
                    kCGImageAlphaPremultipliedLast == alphaInfo ||
                    kCGImageAlphaOnly == alphaInfo) {
                _renderCaps |= FXRC_ALPHA_OUTPUT;
            }
        }
        CGImageRelease(image);
    }
    CGAffineTransform ctm = CGContextGetCTM(_context);
    CGContextSaveGState(_context);
    m_saveCount++;
    if (ctm.d >= 0) {
        CGFloat offset_x, offset_y;
        offset_x = ctm.tx;
        offset_y = ctm.ty;
        CGContextTranslateCTM(_context, -offset_x, -offset_y);
        CGContextConcatCTM(_context, CGAffineTransformMake(1, 0, 0, -1, offset_x, _height + offset_y));
    }
    _foxitDevice2User = CGAffineTransformIdentity;
    _user2FoxitDevice = CGAffineTransformInvert(_foxitDevice2User);
}
예제 #6
0
/* Once we have our image (CGImageRef), we need to get it into an osg::Image */
osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref)
{
    /* This code is adapted from Apple's Documentation found here:
     * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html
     * Listing 9-4††Using a Quartz image as a texture source.
     * Unfortunately, this guide doesn't show what to do about
     * non-RGBA image formats so I'm making the rest up
     * (and it's probably all wrong).
     */

    size_t the_width = CGImageGetWidth(image_ref);
    size_t the_height = CGImageGetHeight(image_ref);
    CGRect the_rect = {{0, 0}, {the_width, the_height}};

    size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref);
    size_t bytes_per_row = CGImageGetBytesPerRow(image_ref);
//    size_t bits_per_component = CGImageGetBitsPerComponent(image_ref);
    size_t bits_per_component = 8;

    CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref);

    GLint internal_format;
    GLenum pixel_format;
    GLenum data_type;

    void* image_data = calloc(the_width * 4, the_height);

    CGColorSpaceRef color_space;
    CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref);

    switch(bits_per_pixel)
    {
        // Drat, if 8-bit, how do you distinguish
        // between a 256 color GIF, a LUMINANCE map
        // or an ALPHA map?
        case 8:
        {
            // I probably did the formats all wrong for this case,
            // especially the ALPHA case.
            if(kCGImageAlphaNone == alpha_info)
            {
                /*
                 internal_format = GL_LUMINANCE;
                 pixel_format = GL_LUMINANCE;
                 */
                internal_format = GL_RGBA8;
                pixel_format = GL_BGRA_EXT;
                data_type = GL_UNSIGNED_INT_8_8_8_8_REV;

                bytes_per_row = the_width*4;
//                color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
                color_space = CGColorSpaceCreateDeviceRGB();
//                bitmap_info = kCGImageAlphaPremultipliedFirst;
#if __BIG_ENDIAN__
                bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */
#else
                bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */
#endif
            }
            else
            {
                internal_format = GL_ALPHA;
                pixel_format = GL_ALPHA;
                data_type = GL_UNSIGNED_BYTE;
                //            bytes_per_row = the_width;
//                color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
                color_space = CGColorSpaceCreateDeviceGray();
            }

            break;
        }
        case 24:
        {
            internal_format = GL_RGBA8;
            pixel_format = GL_BGRA_EXT;
            data_type = GL_UNSIGNED_INT_8_8_8_8_REV;
            bytes_per_row = the_width*4;
//            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
            color_space = CGColorSpaceCreateDeviceRGB();
//            bitmap_info = kCGImageAlphaNone;
#if __BIG_ENDIAN__
            bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */
#else
            bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */
#endif
            break;
        }
        //
        // Tatsuhiro Nishioka
        // 16 bpp grayscale (8 bit white and 8 bit alpha) causes invalid argument combination
        // in CGBitmapContextCreate.
        // I guess it is safer to handle 16 bit grayscale image as 32-bit RGBA image.
        // It works at least on FlightGear
        //
        case 16:
        case 32:
        case 48:
        case 64:
        {

            internal_format = GL_RGBA8;
            pixel_format = GL_BGRA_EXT;
            data_type = GL_UNSIGNED_INT_8_8_8_8_REV;

            bytes_per_row = the_width*4;
//            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
            color_space = CGColorSpaceCreateDeviceRGB();
//            bitmap_info = kCGImageAlphaPremultipliedFirst;

#if __BIG_ENDIAN__
            bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */
#else
            bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */
#endif
            break;
        }
        default:
        {
            // OSG_WARN << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl;
            return NULL;
            break;
        }

    }
    

    // Sets up a context to be drawn to with image_data as the area to be drawn to
    CGContextRef bitmap_context = CGBitmapContextCreate(
        image_data,
        the_width,
        the_height,
        bits_per_component,
        bytes_per_row,
        color_space,
        bitmap_info
    );
    
    CGContextTranslateCTM(bitmap_context, 0, the_height);
    CGContextScaleCTM(bitmap_context, 1.0, -1.0);
    // Draws the image into the context's image_data
    CGContextDrawImage(bitmap_context, the_rect, image_ref);

    CGContextRelease(bitmap_context);
    
    if (!image_data)
        return NULL;

    // alpha is premultiplied with rgba, undo it
    
    vImage_Buffer vb;
    vb.data = image_data;
    vb.height = the_height;
    vb.width = the_width;
    vb.rowBytes = the_width * 4;
    vImageUnpremultiplyData_RGBA8888(&vb, &vb, 0);
    
    // changing it to GL_UNSIGNED_BYTE seems working, but I'm not sure if this is a right way.
    //
    data_type = GL_UNSIGNED_BYTE;
    osg::Image* osg_image = new osg::Image;

    osg_image->setImage(
        the_width,
        the_height,
        1,
        internal_format,
        pixel_format,
        data_type,
        (unsigned char*)image_data,
        osg::Image::USE_MALLOC_FREE // Assumption: osg_image takes ownership of image_data and will free
    );

    return osg_image;



}
예제 #7
0
파일: Texture.cpp 프로젝트: AWilco/xbmc
bool CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int maxWidth, unsigned int maxHeight,
                                bool autoRotate, unsigned int *originalWidth, unsigned int *originalHeight)
{
  if (URIUtils::GetExtension(texturePath).Equals(".dds"))
  { // special case for DDS images
    CDDSImage image;
    if (image.ReadFile(texturePath))
    {
      Update(image.GetWidth(), image.GetHeight(), 0, image.GetFormat(), image.GetData(), false);
      return true;
    }
    return false;
  }

#if defined(__APPLE__) && defined(__arm__)
  XFILE::CFile file;
  UInt8 *imageBuff      = NULL;
  int64_t imageBuffSize = 0;

  //open path and read data to buffer
  //this handles advancedsettings.xml pathsubstitution
  //and resulting networking
  if (file.Open(texturePath, 0))
  {
    imageBuffSize =file.GetLength();
    imageBuff = new UInt8[imageBuffSize];
    imageBuffSize = file.Read(imageBuff, imageBuffSize);
    file.Close();
  }
  else
  {
    CLog::Log(LOGERROR, "Texture manager unable to open file %s", texturePath.c_str());
    return false;
  }

  if (imageBuffSize <= 0)
  {
    CLog::Log(LOGERROR, "Texture manager read texture file failed.");
    delete [] imageBuff;
    return false;
  }

  // create the image from buffer;
  CGImageSourceRef imageSource;
  // create a CFDataRef using CFDataCreateWithBytesNoCopy and kCFAllocatorNull for deallocator.
  // this allows us to do a nocopy reference and we handle the free of imageBuff
  CFDataRef cfdata = CFDataCreateWithBytesNoCopy(NULL, imageBuff, imageBuffSize, kCFAllocatorNull);
  imageSource = CGImageSourceCreateWithData(cfdata, NULL);   
    
  if (imageSource == nil)
  {
    CLog::Log(LOGERROR, "Texture manager unable to load file: %s", CSpecialProtocol::TranslatePath(texturePath).c_str());
    CFRelease(cfdata);
    delete [] imageBuff;
    return false;
  }

  CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);

  int rotate = 0;
  if (autoRotate)
  { // get the orientation of the image for displaying it correctly
    CFDictionaryRef imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(imageSource,0, NULL);
    if (imagePropertiesDictionary != nil)
    {
      CFNumberRef orientation = (CFNumberRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyOrientation);
      if (orientation != nil)
      {
        int value = 0;
        CFNumberGetValue(orientation, kCFNumberIntType, &value);
        if (value)
          rotate = value - 1;
      }
      CFRelease(imagePropertiesDictionary);
    }
  }

  CFRelease(imageSource);

  unsigned int width  = CGImageGetWidth(image);
  unsigned int height = CGImageGetHeight(image);

  m_hasAlpha = (CGImageGetAlphaInfo(image) != kCGImageAlphaNone);

  if (originalWidth)
    *originalWidth = width;
  if (originalHeight)
    *originalHeight = height;

  // check texture size limits and limit to screen size - preserving aspectratio of image  
  if ( width > g_Windowing.GetMaxTextureSize() || height > g_Windowing.GetMaxTextureSize() )
  {
    float aspect;

    if ( width > height )
    {
      aspect = (float)width / (float)height;
      width  = g_Windowing.GetWidth();
      height = (float)width / (float)aspect;
    }
    else
    {
      aspect = (float)height / (float)width;
      height = g_Windowing.GetHeight();
      width  = (float)height / (float)aspect;
    }
    CLog::Log(LOGDEBUG, "Texture manager texture clamp:new texture size: %i x %i", width, height);
  }

  // use RGBA to skip swizzling
  Allocate(width, height, XB_FMT_RGBA8);
  m_orientation = rotate;
    
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

  // hw convert jmpeg to RGBA
  CGContextRef context = CGBitmapContextCreate(m_pixels,
    width, height, 8, GetPitch(), colorSpace,
    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

  CGColorSpaceRelease(colorSpace);

  // Flip so that it isn't upside-down
  //CGContextTranslateCTM(context, 0, height);
  //CGContextScaleCTM(context, 1.0f, -1.0f);
  #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
    CGContextClearRect(context, CGRectMake(0, 0, width, height));
  #else
    #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
    // (just a way of checking whether we're running in 10.5 or later)
    if (CGContextDrawLinearGradient == 0)
      CGContextClearRect(context, CGRectMake(0, 0, width, height));
    else
    #endif
      CGContextSetBlendMode(context, kCGBlendModeCopy);
  #endif
  //CGContextSetBlendMode(context, kCGBlendModeCopy);
  CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
  CGContextRelease(context);
  CGImageRelease(image);
  CFRelease(cfdata);
  delete [] imageBuff;
#else
  DllImageLib dll;
  if (!dll.Load())
    return false;

  ImageInfo image;
  memset(&image, 0, sizeof(image));

  unsigned int width = maxWidth ? std::min(maxWidth, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize();
  unsigned int height = maxHeight ? std::min(maxHeight, g_Windowing.GetMaxTextureSize()) : g_Windowing.GetMaxTextureSize();

  if(!dll.LoadImage(texturePath.c_str(), width, height, &image))
  {
    CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str());
    return false;
  }

  m_hasAlpha = NULL != image.alpha;

  Allocate(image.width, image.height, XB_FMT_A8R8G8B8);
  if (autoRotate && image.exifInfo.Orientation)
    m_orientation = image.exifInfo.Orientation - 1;
  if (originalWidth)
    *originalWidth = image.originalwidth;
  if (originalHeight)
    *originalHeight = image.originalheight;

  unsigned int dstPitch = GetPitch();
  unsigned int srcPitch = ((image.width + 1)* 3 / 4) * 4; // bitmap row length is aligned to 4 bytes

  unsigned char *dst = m_pixels;
  unsigned char *src = image.texture + (m_imageHeight - 1) * srcPitch;

  for (unsigned int y = 0; y < m_imageHeight; y++)
  {
    unsigned char *dst2 = dst;
    unsigned char *src2 = src;
    for (unsigned int x = 0; x < m_imageWidth; x++, dst2 += 4, src2 += 3)
    {
      dst2[0] = src2[0];
      dst2[1] = src2[1];
      dst2[2] = src2[2];
      dst2[3] = 0xff;
    }
    src -= srcPitch;
    dst += dstPitch;
  }

  if(image.alpha)
  {
    dst = m_pixels + 3;
    src = image.alpha + (m_imageHeight - 1) * m_imageWidth;

    for (unsigned int y = 0; y < m_imageHeight; y++)
    {
      unsigned char *dst2 = dst;
      unsigned char *src2 = src;

      for (unsigned int x = 0; x < m_imageWidth; x++,  dst2+=4, src2++)
        *dst2 = *src2;
      src -= m_imageWidth;
      dst += dstPitch;
    }
  }
  dll.ReleaseImage(&image);
#endif

  ClampToEdge();

  return true;
}
예제 #8
0
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
    CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);

    if (NULL == imageSrc) {
        return false;
    }
    SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);

    CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL);
    if (NULL == image) {
        return false;
    }
    SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);

    const int width = SkToInt(CGImageGetWidth(image));
    const int height = SkToInt(CGImageGetHeight(image));
    bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
        return true;
    }

    if (!this->allocPixelRef(bm, NULL)) {
        return false;
    }

    bm->lockPixels();
    bm->eraseColor(SK_ColorTRANSPARENT);

    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO);
    CFRelease(cs);

    CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image);
    CGContextRelease(cg);

    CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
    switch (info) {
        case kCGImageAlphaNone:
        case kCGImageAlphaNoneSkipLast:
        case kCGImageAlphaNoneSkipFirst:
            SkASSERT(SkBitmap::ComputeIsOpaque(*bm));
            bm->setAlphaType(kOpaque_SkAlphaType);
            break;
        default:
            // we don't know if we're opaque or not, so compute it.
            if (SkBitmap::ComputeIsOpaque(*bm)) {
                bm->setAlphaType(kOpaque_SkAlphaType);
            }
    }
    if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) {
        // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied.
        // Convert to unpremultiplied.
        for (int i = 0; i < width; ++i) {
            for (int j = 0; j < height; ++j) {
                uint32_t* addr = bm->getAddr32(i, j);
                *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr);
            }
        }
        bm->setAlphaType(kUnpremul_SkAlphaType);
    }
    bm->unlockPixels();
    return true;
}
예제 #9
0
// Once we have our image, we need to get it into an SDL_Surface
static SDL_Surface* Create_SDL_Surface_From_CGImage(CGImageRef image_ref)
{
	/* This code is adapted from Apple's Documentation found here:
	 * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html
	 * Listing 9-4††Using a Quartz image as a texture source.
	 * Unfortunately, this guide doesn't show what to do about
	 * non-RGBA image formats so I'm making the rest up.
	 * All this code should be scrutinized.
	 */

	size_t w = CGImageGetWidth(image_ref);
	size_t h = CGImageGetHeight(image_ref);
	CGRect rect = {{0, 0}, {w, h}};

	CGImageAlphaInfo alpha = CGImageGetAlphaInfo(image_ref);
	//size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref);
	size_t bits_per_component = 8;

	SDL_Surface* surface;
	Uint32 Amask;
	Uint32 Rmask;
	Uint32 Gmask;
	Uint32 Bmask;

	CGContextRef bitmap_context;
	CGBitmapInfo bitmap_info;
	CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();

	if (alpha == kCGImageAlphaNone ||
	    alpha == kCGImageAlphaNoneSkipFirst ||
	    alpha == kCGImageAlphaNoneSkipLast) {
		bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; /* XRGB */
		Amask = 0x00000000;
	} else {
		/* kCGImageAlphaFirst isn't supported */
		//bitmap_info = kCGImageAlphaFirst | kCGBitmapByteOrder32Host; /* ARGB */
		bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; /* ARGB */
		Amask = 0xFF000000;
	}

	Rmask = 0x00FF0000;
	Gmask = 0x0000FF00;
	Bmask = 0x000000FF;

	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, Rmask, Gmask, Bmask, Amask);
	if (surface)
	{
		// Sets up a context to be drawn to with surface->pixels as the area to be drawn to
		bitmap_context = CGBitmapContextCreate(
															surface->pixels,
															surface->w,
															surface->h,
															bits_per_component,
															surface->pitch,
															color_space,
															bitmap_info
															);

		// Draws the image into the context's image_data
		CGContextDrawImage(bitmap_context, rect, image_ref);

		CGContextRelease(bitmap_context);

		// FIXME: Reverse the premultiplied alpha
		if ((bitmap_info & kCGBitmapAlphaInfoMask) == kCGImageAlphaPremultipliedFirst) {
			int i, j;
			Uint8 *p = (Uint8 *)surface->pixels;
			for (i = surface->h * surface->pitch/4; i--; ) {
#if __LITTLE_ENDIAN__
				Uint8 A = p[3];
				if (A) {
					for (j = 0; j < 3; ++j) {
						p[j] = (p[j] * 255) / A;
					}
				}
#else
				Uint8 A = p[0];
				if (A) {
					for (j = 1; j < 4; ++j) {
						p[j] = (p[j] * 255) / A;
					}
				}
#endif /* ENDIAN */
				p += 4;
			}
		}
	}

	if (color_space)
	{
		CGColorSpaceRelease(color_space);			
	}

	return surface;
}
예제 #10
0
bool GraphicsContext3D::getImageData(Image* image,
                                     unsigned int format,
                                     unsigned int type,
                                     bool premultiplyAlpha,
                                     Vector<uint8_t>& outputVector)
{
    if (!image)
        return false;
    CGImageRef cgImage;
    RetainPtr<CGImageRef> decodedImage;
    if (image->data()) {
        ImageSource decoder(false);
        decoder.setData(image->data(), true);
        if (!decoder.frameCount())
            return false;
        decodedImage = decoder.createFrameAtIndex(0);
        cgImage = decodedImage.get();
    } else
        cgImage = image->nativeImageForCurrentFrame();
    if (!cgImage)
        return false;
    size_t width = CGImageGetWidth(cgImage);
    size_t height = CGImageGetHeight(cgImage);
    if (!width || !height)
        return false;
    size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
    size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
    if (bitsPerComponent != 8 && bitsPerComponent != 16)
        return false;
    if (bitsPerPixel % bitsPerComponent)
        return false;
    size_t componentsPerPixel = bitsPerPixel / bitsPerComponent;
    SourceDataFormat srcDataFormat = kSourceFormatRGBA8;
    AlphaOp neededAlphaOp = kAlphaDoNothing;
    switch (CGImageGetAlphaInfo(cgImage)) {
    case kCGImageAlphaPremultipliedFirst:
        // This path is only accessible for MacOS earlier than 10.6.4.
        // This is a special case for texImage2D with HTMLCanvasElement input,
        // in which case image->data() should be null.
        ASSERT(!image->data());
        if (!premultiplyAlpha)
            neededAlphaOp = kAlphaDoUnmultiply;
        switch (componentsPerPixel) {
        case 2:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatAR8;
            else
                srcDataFormat = kSourceFormatAR16;
            break;
        case 4:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatARGB8;
            else
                srcDataFormat = kSourceFormatARGB16;
            break;
        default:
            return false;
        }
        break;
    case kCGImageAlphaFirst:
        // This path is only accessible for MacOS earlier than 10.6.4.
        if (premultiplyAlpha)
            neededAlphaOp = kAlphaDoPremultiply;
        switch (componentsPerPixel) {
        case 1:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatA8;
            else
                srcDataFormat = kSourceFormatA16;
            break;
        case 2:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatAR8;
            else
                srcDataFormat = kSourceFormatAR16;
            break;
        case 4:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatARGB8;
            else
                srcDataFormat = kSourceFormatARGB16;
            break;
        default:
            return false;
        }
        break;
    case kCGImageAlphaNoneSkipFirst:
        // This path is only accessible for MacOS earlier than 10.6.4.
        switch (componentsPerPixel) {
        case 2:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatAR8;
            else
                srcDataFormat = kSourceFormatAR16;
            break;
        case 4:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatARGB8;
            else
                srcDataFormat = kSourceFormatARGB16;
            break;
        default:
            return false;
        }
        break;
    case kCGImageAlphaPremultipliedLast:
        // This is a special case for texImage2D with HTMLCanvasElement input,
        // in which case image->data() should be null.
        ASSERT(!image->data());
        if (!premultiplyAlpha)
            neededAlphaOp = kAlphaDoUnmultiply;
        switch (componentsPerPixel) {
        case 2:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatRA8;
            else
                srcDataFormat = kSourceFormatRA16;
            break;
        case 4:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatRGBA8;
            else
                srcDataFormat = kSourceFormatRGBA16;
            break;
        default:
            return false;
        }
        break;
    case kCGImageAlphaLast:
        if (premultiplyAlpha)
            neededAlphaOp = kAlphaDoPremultiply;
        switch (componentsPerPixel) {
        case 1:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatA8;
            else
                srcDataFormat = kSourceFormatA16;
            break;
        case 2:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatRA8;
            else
                srcDataFormat = kSourceFormatRA16;
            break;
        case 4:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatRGBA8;
            else
                srcDataFormat = kSourceFormatRGBA16;
            break;
        default:
            return false;
        }
        break;
    case kCGImageAlphaNoneSkipLast:
        switch (componentsPerPixel) {
        case 2:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatRA8;
            else
                srcDataFormat = kSourceFormatRA16;
            break;
        case 4:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatRGBA8;
            else
                srcDataFormat = kSourceFormatRGBA16;
            break;
        default:
            return false;
        }
        break;
    case kCGImageAlphaNone:
        switch (componentsPerPixel) {
        case 1:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatR8;
            else
                srcDataFormat = kSourceFormatR16;
            break;
        case 3:
            if (bitsPerComponent == 8)
                srcDataFormat = kSourceFormatRGB8;
            else
                srcDataFormat = kSourceFormatRGB16;
            break;
        default:
            return false;
        }
        break;
    default:
        return false;
    }
    RetainPtr<CFDataRef> pixelData;
    pixelData.adoptCF(CGDataProviderCopyData(CGImageGetDataProvider(cgImage)));
    if (!pixelData)
        return false;
    const UInt8* rgba = CFDataGetBytePtr(pixelData.get());
    outputVector.resize(width * height * 4);
    unsigned int srcUnpackAlignment = 0;
    size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
    unsigned int padding = bytesPerRow - bitsPerPixel / 8 * width;
    if (padding) {
        srcUnpackAlignment = padding + 1;
        while (bytesPerRow % srcUnpackAlignment)
            ++srcUnpackAlignment;
    }
    bool rt = packPixels(rgba, srcDataFormat, width, height, srcUnpackAlignment,
                         format, type, neededAlphaOp, outputVector.data());
    return rt;
}