static UncompressedImage CGImageToUncompressedImage(CGImageRef image) { if (image == nullptr) return UncompressedImage(); size_t width = CGImageGetWidth(image); size_t height = CGImageGetHeight(image); if ((0 == width) || (0 == height)) return UncompressedImage(); size_t bits_per_pixel = CGImageGetBitsPerPixel(image); size_t bits_per_component = CGImageGetBitsPerComponent(image); CGColorSpaceRef colorspace = CGImageGetColorSpace(image); size_t row_size; UncompressedImage::Format format; CGColorSpaceRef bitmap_colorspace; CGBitmapInfo bitmap_info; if ((8 == bits_per_pixel) && (8 == bits_per_component) && (CGColorSpaceGetModel(colorspace) == kCGColorSpaceModelMonochrome)) { row_size = width; format = UncompressedImage::Format::GRAY; static CGColorSpaceRef grey_colorspace = CGColorSpaceCreateDeviceGray(); bitmap_colorspace = grey_colorspace; bitmap_info = 0; } else { static CGColorSpaceRef rgb_colorspace = CGColorSpaceCreateDeviceRGB(); bitmap_colorspace = rgb_colorspace; if ((24 == bits_per_pixel) && (8 == bits_per_component)) { row_size = width * 3; format = UncompressedImage::Format::RGB; bitmap_info = kCGBitmapByteOrder32Big; } else { row_size = width * 4; format = UncompressedImage::Format::RGBA; bitmap_info = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; } } std::unique_ptr<uint8_t[]> uncompressed(new uint8_t[height * row_size]); CGContextRef bitmap = CGBitmapContextCreate(uncompressed.get(), width, height, 8, row_size, bitmap_colorspace, bitmap_info); if (nullptr == bitmap) { return UncompressedImage(); } AtScopeExit(bitmap) { CFRelease(bitmap); }; CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), image); return UncompressedImage(format, row_size, width, height, std::move(uncompressed)); }
void CGImageLuminanceSource::init (CGImageRef cgimage, int left, int top, int width, int height) { data_ = 0; image_ = cgimage; left_ = left; top_ = top; width_ = width; height_ = height; dataWidth_ = (int)CGImageGetWidth(image_); dataHeight_ = (int)CGImageGetHeight(image_); if (left_ + width_ > dataWidth_ || top_ + height_ > dataHeight_ || top_ < 0 || left_ < 0) { throw IllegalArgumentException("Crop rectangle does not fit within image data."); } CGColorSpaceRef space = CGImageGetColorSpace(image_); CGColorSpaceModel model = CGColorSpaceGetModel(space); if (model != kCGColorSpaceModelMonochrome || CGImageGetBitsPerComponent(image_) != 8 || CGImageGetBitsPerPixel(image_) != 8) { CGColorSpaceRef gray = CGColorSpaceCreateDeviceGray(); CGContextRef ctx = CGBitmapContextCreate(0, width, height, 8, width, gray, kCGImageAlphaNone); CGColorSpaceRelease(gray); if (top || left) { CGContextClipToRect(ctx, CGRectMake(0, 0, width, height)); } CGContextDrawImage(ctx, CGRectMake(-left, -top, width, height), image_); image_ = CGBitmapContextCreateImage(ctx); bytesPerRow_ = width; top_ = 0; left_ = 0; dataWidth_ = width; dataHeight_ = height; CGContextRelease(ctx); } else { CGImageRetain(image_); } CGDataProviderRef provider = CGImageGetDataProvider(image_); data_ = CGDataProviderCopyData(provider); }
Image::Image(CGImageRef image) : _width(CGImageGetWidth(image)), _height(CGImageGetHeight(image)), _bitsPerComponent(CGImageGetBitsPerComponent(image)), _bytesPerRow(CGImageGetBytesPerRow(image)), _colorSpaceRef(CGImageGetColorSpace(image)), _bitmapInfo(CGImageGetBitmapInfo(image)), _pixels(new pixel3f[_width * _height]), _copy(new pixel3f[_width * _height]) { // Obtain mutable image data. CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(image)); _data = CFDataCreateMutableCopy(NULL, CFDataGetLength(data), data); // Release data from image. CFRelease(data); }
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; }
Screenshot* ScreenShooter::take_screenshot(const CFStringRef format, float compression) { CGImageRef* images = new CGImageRef[_dsp_count]; /* Grab the images */ for (unsigned int i = 0; i < _dsp_count; i++) { images[i] = CGDisplayCreateImage(_displays[i]); } /* Calculate size of image to produce */ CGSize finalSize = CGSizeMake(_top_right.x - _bottom_left.x, _bottom_left.y - _top_right.y); /* Round out the bitmap size information */ size_t bytesPerRow = finalSize.width * CGImageGetBitsPerPixel(images[0]) / 8; /* Create context around bitmap */ CGContextRef context = CGBitmapContextCreate( NULL, finalSize.width, finalSize.height, CGImageGetBitsPerComponent(images[0]), bytesPerRow, CGImageGetColorSpace(images[0]), CGImageGetBitmapInfo(images[0]) ); /* Draw images into the bitmap */ for (unsigned int i = 0; i < _dsp_count; i++) { /* Adjust the positions to account for coordinate system shifts (displays origin is at top left; image origin is at bottom left) */ CGRect adjustedPoint = CGRectMake(_display_bounds[i].origin.x - _bottom_left.x, _bottom_left.y - _display_bounds[i].size.height - _display_bounds[i].origin.y, _display_bounds[i].size.width, _display_bounds[i].size.height); CGContextDrawImage(context, adjustedPoint, images[i]); } delete [] images; return new Screenshot(context, format, compression); }
//============================================================================ // NCGImage::SetObject : Set the object. //---------------------------------------------------------------------------- bool NCGImage::SetObject(CGImageRef cfObject, bool takeOwnership) { size_t theWidth, theHeight, bitsPerPixel, bitsPerComponent; NCFObject theObject(cfObject, takeOwnership); NCFObject cgColorSpace, cgContext; CGBitmapInfo bitmapInfo; NImageFormat theFormat; NImage theImage; bool isValid; // Get the state we need theWidth = CGImageGetWidth( cfObject); theHeight = CGImageGetHeight( cfObject); bitsPerPixel = CGImageGetBitsPerPixel( cfObject); bitsPerComponent = CGImageGetBitsPerComponent(cfObject); // Select the image format if (bitsPerPixel == 8 && bitsPerComponent == 8) { // Convert indexed images to 32bpp without alpha theFormat = kNImageFormat_RGBX_8888; bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast; cgColorSpace = NCGColor::GetDeviceRGB(); } else if (bitsPerPixel == 24 && bitsPerComponent == 8) { // Convert 24bpp images to 32bpp without alpha theFormat = kNImageFormat_RGBX_8888; bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast; cgColorSpace = NCGColor::GetDeviceRGB(); } else if (bitsPerPixel == 32 && bitsPerComponent == 8) { // Convert 32bpp images to 32bpp with alpha theFormat = kNImageFormat_RGBA_8888; bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast; cgColorSpace = NCGColor::GetDeviceRGB(); } else { NN_LOG("Unknown image format: %d/%d", bitsPerPixel, bitsPerComponent); theFormat = kNImageFormatNone; bitmapInfo = kCGImageAlphaNone; } if (!cgColorSpace.IsValid()) return(false); // Set the object theImage = NImage(NSize(theWidth, theHeight), theFormat); isValid = cgContext.SetObject(CGBitmapContextCreate( theImage.GetPixels(), theWidth, theHeight, bitsPerComponent, theImage.GetBytesPerRow(), cgColorSpace, bitmapInfo)); if (isValid) { CGContextDrawImage(cgContext, ToCG(theImage.GetBounds()), cfObject); *this = theImage; } return(isValid); }
/* read image file */ int BIReadFile( const char *fileName, BIFileType fileType, BIPadMode padMode, unsigned padSize, BIImageInfo *imageInfo, /* RETURNED */ unsigned char **bitmap) /* mallocd and RETURNED; caller must free */ { CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (unsigned char*)fileName, strlen(fileName), FALSE); if(fileURL == NULL) { fprintf(stderr, "***BIReadFile: Error on CFURLCreateFromFileSystemRepresentation\n"); return -1; } CFStringRef keys[1] = {kCGImageSourceTypeIdentifierHint}; CFStringRef values[1] = {BIGetUTI(fileURL, fileType)}; if(values[0] == NULL) { return -1; } CFDictionaryRef optionsDict = NULL; CGImageSourceRef imageSourceRef = NULL; CGImageRef imageRef = NULL; CGColorSpaceRef rgbColorSpaceRef = NULL; CGContextRef bitmapContextRef = NULL; CGBitmapInfo bitmapInfo = 0; CGImageAlphaInfo alpha; unsigned bytesPerPixel = 4; optionsDict = CFDictionaryCreate( kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); /* subsequent errors to errOut: */ int ourRtn = 0; /* source file --> CGImageRef */ imageSourceRef = CGImageSourceCreateWithURL(fileURL, optionsDict); if(imageSourceRef == NULL) { fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateWithURL\n"); ourRtn = 1; goto errOut; } CFRELEASE(fileURL); imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, optionsDict ); if(imageRef == NULL) { fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateImageAtIndex\n"); ourRtn = 1; goto errOut; } imageInfo->imageWidth = CGImageGetWidth(imageRef); imageInfo->imageHeight = CGImageGetHeight(imageRef); imageInfo->bitsPerComponent = CGImageGetBitsPerComponent(imageRef); imageInfo->bitsPerPixel = CGImageGetBitsPerPixel(imageRef); if(imageInfo->bitsPerPixel == 8) { /* the image is gray */ rgbColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); imageInfo->bytesPerRow = imageInfo->imageWidth; alpha = kCGImageAlphaNone; bitmapInfo = CGImageGetBitmapInfo(imageRef); bytesPerPixel = 1; } else { rgbColorSpaceRef = CGColorSpaceCreateDeviceRGB(); imageInfo->bytesPerRow = imageInfo->imageWidth * 4; alpha = kCGImageAlphaPremultipliedLast; bitmapInfo = kCGBitmapByteOrder32Big | alpha; } if(rgbColorSpaceRef == NULL) { fprintf(stderr, "***BIReadFile: Error on CGColorSpaceCreateWithName\n"); ourRtn = 1; goto errOut; } /* optionally pad */ imageInfo->effectHeight = imageInfo->imageHeight; if(padMode != PM_None) { if(padSize == 0) { fprintf(stderr, "***Pad size of 0 invalid\n"); ourRtn = 1; goto errOut; } unsigned padSizeBytes = padSize; if(padMode == PM_Pixels) { padSizeBytes *= bytesPerPixel; } imageInfo->bytesPerRow = ROUND_TO(imageInfo->bytesPerRow, padSizeBytes); /* also round up row count */ imageInfo->effectHeight = ROUND_TO(imageInfo->imageHeight, padSize); } *bitmap = (unsigned char *)malloc(imageInfo->bytesPerRow * imageInfo->effectHeight); bitmapContextRef = CGBitmapContextCreate(*bitmap, imageInfo->imageWidth, imageInfo->imageHeight, imageInfo->bitsPerComponent, imageInfo->bytesPerRow, rgbColorSpaceRef, bitmapInfo); if(bitmapContextRef == NULL) { fprintf(stderr, "***BIReadFile: Error creating CGBitmapContext\n"); ourRtn = 1; goto errOut; } /* enable high quality interpolation */ CGContextSetInterpolationQuality(bitmapContextRef, kCGInterpolationHigh); /* Draw into the context */ CGContextDrawImage(bitmapContextRef, CGRectMake(0, 0, imageInfo->imageWidth, imageInfo->imageHeight), imageRef); errOut: CFRELEASE(optionsDict); CFRELEASE(imageSourceRef); CFRELEASE(imageRef); CFRELEASE(rgbColorSpaceRef); CFRELEASE(bitmapContextRef); if(ourRtn) { if(*bitmap) { free(*bitmap); *bitmap = NULL; } } return ourRtn; }
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; }