CGImageRef CreateCGImage(void *aInfo, const void *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) { //XXX: we should avoid creating this colorspace everytime CGColorSpaceRef colorSpace = nullptr; CGBitmapInfo bitinfo = 0; int bitsPerComponent = 0; int bitsPerPixel = 0; switch (aFormat) { case SurfaceFormat::B8G8R8A8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case SurfaceFormat::B8G8R8X8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case SurfaceFormat::A8: // XXX: why don't we set a colorspace here? bitsPerComponent = 8; bitsPerPixel = 8; break; default: MOZ_CRASH(); } size_t bufLen = BufferSizeFromStrideAndHeight(aStride, aSize.height); if (bufLen == 0) { return nullptr; } CGDataProviderRef dataProvider = CGDataProviderCreateWithData(aInfo, aData, bufLen, releaseCallback); CGImageRef image; if (aFormat == SurfaceFormat::A8) { CGFloat decode[] = {1.0, 0.0}; image = CGImageMaskCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, dataProvider, decode, true); } else { image = CGImageCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, colorSpace, bitinfo, dataProvider, nullptr, true, kCGRenderingIntentDefault); } CGDataProviderRelease(dataProvider); CGColorSpaceRelease(colorSpace); return image; }
bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) { UniChar uni_char; CGGlyph glyph; CTFontRef ct_font = (CTFontRef)font; const CFIndex count = 1; CGRect bounding_rect, success_rect; CGContextRef context_ref; if( chnum == ' ' ) { uni_char = 'n'; CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count ); success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count ); uni_char = chnum; CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count ); } else { uni_char = chnum; CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count ); success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count ); } if( CGRectEqualToRect( success_rect, CGRectNull ) == false ) { size_t bitmap_width; size_t bitmap_height; bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH); bitmap_width = bitmap_width == 0 ? 1 : bitmap_width; bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT); xoffs = yoffs = 0; width = bitmap_width; size_t bits_per_component; CGColorSpaceRef color_space; CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst; color_space = CGColorSpaceCreateDeviceRGB(); bits_per_component = 8; bitmap.allocate(bitmap_width, bitmap_height); context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info ); if( context_ref != NULL ) { CGFontRef font_ref; font_ref = CTFontCopyGraphicsFont( ct_font, NULL ); CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) ); CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0); CGContextSetFont( context_ref, font_ref ); CGContextSetFontSize( context_ref, POINT_SIZE ); CGContextShowGlyphs( context_ref, &glyph, count ); CGFontRelease( font_ref ); CGContextRelease( context_ref ); } CGColorSpaceRelease( color_space ); } return bitmap.valid(); }
bool GCPVideoRenderer::OnWindowRefresh(FB::RefreshEvent* pEvt) { FB::CoreGraphicsDraw* pCgDrawEvt(static_cast<FB::CoreGraphicsDraw*>(pEvt)); CGContextRef pContext = pCgDrawEvt->context; boost::mutex::scoped_lock winLock(m_winMutex); const int stride = m_width*4; const int frameBufferSize = m_height*stride; static SInt32 osMajorVersion = 0; static SInt32 osMinorVersion = 0; static CGInterpolationQuality interpolationMode = kCGInterpolationNone; if(0 == osMajorVersion || 0 == osMinorVersion) { if(noErr != Gestalt(gestaltSystemVersionMajor, &osMajorVersion)) { osMajorVersion = 10; } if(noErr != Gestalt(gestaltSystemVersionMinor, &osMinorVersion)) { osMinorVersion = 6; } if(10 <= osMajorVersion && 7 <= osMinorVersion) { interpolationMode = kCGInterpolationDefault; } } if(NULL == pContext || NULL == m_pFrameBuffer) { return false; } int winWidth = pCgDrawEvt->bounds.right - pCgDrawEvt->bounds.left; int winHeight = pCgDrawEvt->bounds.bottom - pCgDrawEvt->bounds.top; if(winWidth<=1 || winHeight<=1) return false; CGContextSaveGState(pContext); CGContextSetShouldAntialias(pContext, true); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGImageRef cgImage = CGImageCreate(m_width, m_height, 8, 32, stride, colorSpace, kCGImageAlphaNoneSkipLast, CGDataProviderCreateWithData(NULL, m_pFrameBuffer, frameBufferSize, NULL), NULL, false, kCGRenderingIntentDefault); if(NULL == cgImage) { CGColorSpaceRelease(colorSpace); CGContextRestoreGState(pContext); return false; } CGContextSetInterpolationQuality(pContext, interpolationMode); CGContextTranslateCTM(pContext, 0, winHeight); CGContextScaleCTM(pContext, 1, -1); CGContextDrawImage(pContext, CGRectMake(0, 0, winWidth, winHeight), cgImage); CGImageRelease(cgImage); CGColorSpaceRelease(colorSpace); CGContextRestoreGState(pContext); return true; }
static mblk_t *jpeg2yuv(uint8_t *jpgbuf, int bufsize, MSVideoSize *reqsize) { #ifndef NO_FFMPEG AVCodecContext av_context; int got_picture=0; AVFrame orig; mblk_t *ret; struct SwsContext *sws_ctx; AVPacket pkt; MSPicture dest; AVCodec *codec=avcodec_find_decoder(CODEC_ID_MJPEG); if (codec==NULL) { ms_error("Could not find MJPEG decoder in ffmpeg."); return NULL; } avcodec_get_context_defaults3(&av_context,NULL); if (avcodec_open2(&av_context,codec,NULL)<0) { ms_error("jpeg2yuv: avcodec_open failed"); return NULL; } av_init_packet(&pkt); pkt.data=jpgbuf; pkt.size=bufsize; memset(&orig, 0, sizeof(orig)); if (avcodec_decode_video2(&av_context,&orig,&got_picture,&pkt) < 0) { ms_error("jpeg2yuv: avcodec_decode_video failed"); avcodec_close(&av_context); return NULL; } ret=ms_yuv_buf_alloc(&dest, reqsize->width,reqsize->height); /* not using SWS_FAST_BILINEAR because it doesn't play well with * av_context.pix_fmt set to PIX_FMT_YUVJ420P by jpeg decoder */ sws_ctx=sws_getContext(av_context.width,av_context.height,av_context.pix_fmt, reqsize->width,reqsize->height,PIX_FMT_YUV420P,SWS_BILINEAR, NULL, NULL, NULL); if (sws_ctx==NULL) { ms_error("jpeg2yuv: ms_sws_getContext() failed."); avcodec_close(&av_context); freemsg(ret); return NULL; } #if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0,9,0) if (sws_scale(sws_ctx,(const uint8_t* const *)orig.data,orig.linesize,0,av_context.height,dest.planes,dest.strides)<0) { #else if (sws_scale(sws_ctx,(uint8_t**)orig.data,orig.linesize,0,av_context.height,dest.planes,dest.strides)<0) { #endif ms_error("jpeg2yuv: ms_sws_scale() failed."); sws_freeContext(sws_ctx); avcodec_close(&av_context); freemsg(ret); return NULL; } sws_freeContext(sws_ctx); avcodec_close(&av_context); return ret; #elif TARGET_OS_IPHONE MSPicture dest; CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, jpgbuf, bufsize, NULL); // use the data provider to get a CGImage; release the data provider CGImageRef image = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, FALSE, kCGRenderingIntentDefault); CGDataProviderRelease(dataProvider); reqsize->width = CGImageGetWidth(image); reqsize->height = CGImageGetHeight(image); uint8_t* tmp = (uint8_t*) malloc(reqsize->width * reqsize->height * 4); mblk_t* ret=ms_yuv_buf_alloc(&dest, reqsize->width, reqsize->height); CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef imageContext = CGBitmapContextCreate(tmp, reqsize->width, reqsize->height, 8, reqsize->width*4, colourSpace, kCGImageAlphaNoneSkipLast); CGColorSpaceRelease(colourSpace); // draw the image to the context, release it CGContextDrawImage(imageContext, CGRectMake(0, 0, reqsize->width, reqsize->height), image); CGImageRelease(image); /* convert tmp/RGB -> ret/YUV */ for(int y=0; y<reqsize->height; y++) { for(int x=0; x<reqsize->width; x++) { uint8_t r = tmp[y * reqsize->width * 4 + x * 4 + 0]; uint8_t g = tmp[y * reqsize->width * 4 + x * 4 + 1]; uint8_t b = tmp[y * reqsize->width * 4 + x * 4 + 2]; // Y *dest.planes[0]++ = (uint8_t)((0.257 * r) + (0.504 * g) + (0.098 * b) + 16); // U/V subsampling if ((y % 2==0) && (x%2==0)) { uint32_t r32=0, g32=0, b32=0; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { r32 += tmp[(y+i) * reqsize->width * 4 + (x+j) * 4 + 0]; g32 += tmp[(y+i) * reqsize->width * 4 + (x+j) * 4 + 1]; b32 += tmp[(y+i) * reqsize->width * 4 + (x+j) * 4 + 2]; } } r32 = (uint32_t)(r32 * 0.25f); g32 = (uint32_t)(g32 * 0.25f); b32 = (uint32_t) (b32 * 0.25f); // U *dest.planes[1]++ = (uint8_t)(-(0.148 * r32) - (0.291 * g32) + (0.439 * b32) + 128); // V *dest.planes[2]++ = (uint8_t)((0.439 * r32) - (0.368 * g32) - (0.071 * b32) + 128); } } } free(tmp); return ret; #else return NULL; #endif } mblk_t *ms_load_jpeg_as_yuv(const char *jpgpath, MSVideoSize *reqsize) { #if defined(WIN32) mblk_t *m=NULL; DWORD st_sizel; DWORD st_sizeh; uint8_t *jpgbuf; DWORD err; HANDLE fd; #ifdef UNICODE WCHAR wUnicode[1024]; MultiByteToWideChar(CP_UTF8, 0, jpgpath, -1, wUnicode, 1024); fd = CreateFile(wUnicode, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); #else fd = CreateFile(jpgpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); #endif if (fd==INVALID_HANDLE_VALUE) { ms_error("Failed to open %s",jpgpath); return NULL; } st_sizel=0; st_sizeh=0; st_sizel = GetFileSize(fd, &st_sizeh); if (st_sizeh>0 || st_sizel<=0) { CloseHandle(fd); ms_error("Can't load file %s",jpgpath); return NULL; } jpgbuf=(uint8_t*)ms_malloc0(st_sizel); if (jpgbuf==NULL) { CloseHandle(fd); ms_error("Cannot allocate buffer for %s",jpgpath); return NULL; } err=0; ReadFile(fd, jpgbuf, st_sizel, &err, NULL) ; if (err!=st_sizel) { ms_error("Could not read as much as wanted !"); } m=jpeg2yuv(jpgbuf,st_sizel,reqsize); ms_free(jpgbuf); if (m==NULL) { CloseHandle(fd); ms_error("Cannot load image from buffer for %s",jpgpath); return NULL; } CloseHandle(fd); return m; #else mblk_t *m=NULL; struct stat statbuf; uint8_t *jpgbuf; int err; int fd=open(jpgpath,O_RDONLY); if (fd!=-1) { fstat(fd,&statbuf); if (statbuf.st_size<=0) { close(fd); ms_error("Cannot load %s",jpgpath); return NULL; } jpgbuf=(uint8_t*)ms_malloc0(statbuf.st_size + FF_INPUT_BUFFER_PADDING_SIZE); if (jpgbuf==NULL) { close(fd); ms_error("Cannot allocate buffer for %s",jpgpath); return NULL; } err=read(fd,jpgbuf,statbuf.st_size); if (err!=statbuf.st_size) { ms_error("Could not read as much as wanted: %i<>%li !",err,(long)statbuf.st_size); } m=jpeg2yuv(jpgbuf,statbuf.st_size,reqsize); ms_free(jpgbuf); if (m==NULL) { close(fd); ms_error("Cannot load image from buffer for %s",jpgpath); return NULL; } } else { ms_error("Cannot load %s",jpgpath); return NULL; } close(fd); return m; #endif }
bool SourceSurfaceCG::InitFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) { //XXX: we should avoid creating this colorspace everytime CGColorSpaceRef colorSpace = NULL; CGBitmapInfo bitinfo = 0; CGDataProviderRef dataProvider = NULL; int bitsPerComponent = 0; int bitsPerPixel = 0; switch (aFormat) { case B8G8R8A8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case B8G8R8X8: colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case A8: // XXX: why don't we set a colorspace here? bitsPerComponent = 8; bitsPerPixel = 8; }; void *data = malloc(aStride * aSize.height); memcpy(aData, data, aStride * aSize.height); mFormat = aFormat; dataProvider = CGDataProviderCreateWithData (data, data, aSize.height * aStride, releaseCallback); if (aFormat == A8) { CGFloat decode[] = {1.0, 0.0}; mImage = CGImageMaskCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, dataProvider, decode, true); } else { mImage = CGImageCreate (aSize.width, aSize.height, bitsPerComponent, bitsPerPixel, aStride, colorSpace, bitinfo, dataProvider, NULL, true, kCGRenderingIntentDefault); } CGDataProviderRelease(dataProvider); CGColorSpaceRelease (colorSpace); if (mImage) { return false; } return true; }
CGColorSpaceRef colorSpaceFromPDFArray(CGPDFArrayRef colorSpaceArray){ CGColorSpaceRef cgColorSpace = NULL, alternateColorSpace = NULL; CGPDFStreamRef stream; const char *colorSpaceName = NULL, *alternateColorSpaceName = NULL; CGPDFInteger numberOfComponents; CGPDFDictionaryRef dict; bool retrieved; CGFloat *range; CGPDFArrayRef rangeArray; if (CGPDFArrayGetName(colorSpaceArray, 0, &colorSpaceName)) { if (strcmp(colorSpaceName, "ICCBased") == 0) { if (CGPDFArrayGetStream(colorSpaceArray, 1, &stream)) { dict = CGPDFStreamGetDictionary(stream); // First obtain the alternate color space if present if (CGPDFDictionaryGetName(dict, "Alternate", &alternateColorSpaceName)) { if (strcmp(alternateColorSpaceName, "DeviceRGB") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceRGB(); } else if (strcmp(alternateColorSpaceName, "DeviceGray") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceGray(); } else if (strcmp(alternateColorSpaceName, "DeviceCMYK") == 0) { alternateColorSpace = CGColorSpaceCreateDeviceCMYK(); } } // Obtain the preferential color space CGPDFDataFormat dataFormat; CFDataRef colorSpaceDataPtr = CGPDFStreamCopyData(stream, &dataFormat); if (dataFormat == CGPDFDataFormatRaw) { CGDataProviderRef profile = CGDataProviderCreateWithCFData(colorSpaceDataPtr); retrieved = CGPDFDictionaryGetInteger(dict, "N", &numberOfComponents); // Deduce an alternate color space if we don't have one //already if (alternateColorSpace == NULL) { switch (numberOfComponents) { case 1: alternateColorSpace = CGColorSpaceCreateDeviceGray(); break; case 3: alternateColorSpace = CGColorSpaceCreateDeviceRGB(); break; case 4: alternateColorSpace = CGColorSpaceCreateDeviceCMYK(); break; default: break; } } range = malloc(numberOfComponents * 2 * sizeof(CGFloat)); if (!CGPDFDictionaryGetArray(dict, "Range", &rangeArray)) { int i = 0; for (; i < numberOfComponents * 2; i += 2) { range[i] = (i % 2 == 0) ? 0.0 : 1.0; } } else { size_t count = CGPDFArrayGetCount(rangeArray); int i = 0; for (; i < count; i++) { (void)CGPDFArrayGetNumber(rangeArray, i, &range[i]); } } cgColorSpace = CGColorSpaceCreateICCBased(numberOfComponents, range, profile, alternateColorSpace); CGDataProviderRelease(profile); free(range); if (cgColorSpace) { // Since we have a preferential color space, we no //longer need the hang on to the alternate color space CGColorSpaceRelease(alternateColorSpace); } else { cgColorSpace = alternateColorSpace; } } else if (dataFormat == CGPDFDataFormatJPEGEncoded) { // } else if (dataFormat == CGPDFDataFormatJPEG2000) { // } } } else if (strcmp(colorSpaceName, "Indexed") == 0) { CGColorSpaceRef baseSpace; CGPDFArrayRef base = NULL; CGPDFInteger highValue = 0; CGPDFStreamRef stream = NULL; CGPDFStringRef string; const unsigned char *chars; const char *namedColorSpaceName; if (CGPDFArrayGetArray(colorSpaceArray, 1, &base)) { baseSpace = colorSpaceFromPDFArray(base); } else if (CGPDFArrayGetName(colorSpaceArray, 1, &namedColorSpaceName)) { if (strcmp(namedColorSpaceName, "DeviceRGB") == 0) { baseSpace = CGColorSpaceCreateDeviceRGB(); } else if (strcmp(namedColorSpaceName, "DeviceGray") == 0) { baseSpace = CGColorSpaceCreateDeviceGray(); } else if (strcmp(namedColorSpaceName, "DeviceCMYK") == 0) { baseSpace = CGColorSpaceCreateDeviceCMYK(); } } retrieved = CGPDFArrayGetInteger(colorSpaceArray, 2, &highValue); if (CGPDFArrayGetStream(colorSpaceArray, 3, &stream)) { chars = CFDataGetBytePtr(CGPDFStreamCopyData(stream, NULL)); } else if (CGPDFArrayGetString(colorSpaceArray, 3, &string)) { chars = CGPDFStringGetBytePtr(string); } else { // TODO: Raise some error state? } cgColorSpace = CGColorSpaceCreateIndexed(baseSpace, highValue, chars); } } return (CGColorSpaceRef)CFMakeCollectable(cgColorSpace); }
// save the image void save_image (vImage_Buffer *src_i, img_prop o, float compression, char *o_file) { // Create a CFDataRef from the rotated data in the destination vImage_Buffer CFDataRef output_Data = CFDataCreate (NULL, src_i->data, src_i->height * src_i->rowBytes); if (o->bits_ppixel == 32) { // convert from 24bit to 32bit by adding the alpha channel. output_Data = convert32_24bit (output_Data, o); src_i->rowBytes = src_i->width * 3; } // Check for a NULL value. if (NULL == output_Data) { printf ("Could not create CFDataRef from vImage_Buffer.\n"); exit (0); } // Create a Data provider from the rotated data CGDataProviderRef destination_data_provider = CGDataProviderCreateWithCFData (output_Data); // Check for null if (NULL == destination_data_provider) { printf ("Could not create CGDataProviderRef from CGDataRef.\n"); exit (0); } CGImageRef processed_image; // Create the image with sRGB for the colour space processed_image = CGImageCreate (src_i->width, // 1 width src_i->height, // 2 height (size_t)o->bits_ppixel/ (o->bits_ppixel/8), // bitsPerComponent (size_t)o->bits_ppixel, //bitsPerPixel src_i->rowBytes, // bytesPerRow CGColorSpaceCreateDeviceRGB(), // Generic ColourSpace kCGBitmapByteOrder32Big, // bitmapInfo destination_data_provider, // Data provider ** DataProviderRef NULL, // decode 0, // Interpolate kCGRenderingIntentSaturation); // rendering intent if (NULL == processed_image) exit (0); /* } else { // release the reference colour space CGColorSpaceRelease(rgb); // Create the image with sRGB for the colour space processed_image = CGImageCreate (src_i->width, // 1 width src_i->height, // 2 height (size_t)o->bits_ppixel/ (o->bits_ppixel/8), // bitsPerComponent (size_t)o->bits_ppixel, //bitsPerPixel src_i->rowBytes, // bytesPerRow o->colorSpace, // ColourSpace of original kCGBitmapByteOrder32Big, // bitmapInfo destination_data_provider, // Data provider ** DataProviderRef NULL, // decode 0, // Interpolate kCGRenderingIntentSaturation); // rendering intent if (NULL == processed_image) exit (0); }*/ // create a CFStringRef from the C string CFStringRef fn = CFStringCreateWithCString (NULL, o_file, kCFStringEncodingUTF8); if (NULL == fn) exit (0); // Convert the CFStringRef to a CFURLRef CFURLRef fon = CFURLCreateWithFileSystemPath (NULL, fn, kCFURLPOSIXPathStyle, false); if (NULL == fon) exit (0); // Create an image destination CGImageDestinationRef image_destination = CGImageDestinationCreateWithURL (fon, kUTTypeJPEG, 1, NULL); // Release the CFURLRef CFRelease (fon); fon = NULL; // release the CFStringRef CFRelease (fn); fn = NULL; // Check for a NULL value in image_destination if (NULL == image_destination) { printf ("Null Image_destination: Could not create the CGImageDestinationRef from the supplied URL.\n"); exit (0); } // Set the compression factor for the images CFStringRef keys[1]; CFTypeRef value[1]; // Use compression key keys[0] = kCGImageDestinationLossyCompressionQuality; // set the compression amount. 1 = no compression 0 = max compression value[0] = CFNumberCreate (NULL, kCFNumberFloatType, &compression); // Pointer to the image attribs dictionary CFDictionaryRef options; // create the dictionary options = CFDictionaryCreate (kCFAllocatorDefault, (void *)keys, (void *)value, 1, NULL, NULL); // Copy data to the output information to the destination CGImageDestinationAddImage (image_destination, processed_image, options); // Check for a NULL value in image_destination if (NULL == image_destination) { printf ("Null Image_destination: Could not add the rotated image.\n"); exit (0); } // Write the image to disk if (!CGImageDestinationFinalize (image_destination)) { // Could not write the file for some reason printf ("Could not write the file to disk.\n"); exit (1); } // Release the pointer the the scaled buffer CFRelease (output_Data); output_Data = NULL; // Release the dictionary CFRelease (keys[0]); CFRelease (value[0]); CFRelease (options); options = NULL; // Release the rotated image. CGImageRelease (processed_image); processed_image = NULL; // Release a data provider CGDataProviderRelease (destination_data_provider); destination_data_provider = NULL; // Release the image destination CFRelease (image_destination); image_destination = NULL; } // save_image
bool ImageIOEncoder::write( const Mat& img, const vector<int>& params ) { int width = img.cols, height = img.rows; int _channels = img.channels(); const uchar* data = img.data; int step = img.step; // Determine the appropriate UTI based on the filename extension CFStringRef imageUTI = FilenameToUTI( m_filename.c_str() ); // Determine the Bytes Per Pixel int bpp = (_channels == 1) ? 1 : 4; // Write the data into a bitmap context CGContextRef context; CGColorSpaceRef colorSpace; uchar* bitmapData = NULL; if( bpp == 1 ) { #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR colorSpace = CGColorSpaceCreateDeviceGray(); #else colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray ); #endif } else if( bpp == 4 ) { #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR colorSpace = CGColorSpaceCreateDeviceRGB(); #else colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear ); #endif } if( !colorSpace ) return false; bitmapData = (uchar*)malloc( bpp * height * width ); if( !bitmapData ) { CGColorSpaceRelease( colorSpace ); return false; } context = CGBitmapContextCreate( bitmapData, width, height, 8, bpp * width, colorSpace, (bpp == 1) ? kCGImageAlphaNone : kCGImageAlphaNoneSkipLast ); CGColorSpaceRelease( colorSpace ); if( !context ) { free( bitmapData ); return false; } // Copy pixel information from data into bitmapData if (bpp == 4) { int bitmapIndex = 0; const uchar * base = data; for (int y = 0; y < height; y++) { const uchar * line = base + y * step; for (int x = 0; x < width; x++) { // Blue channel bitmapData[bitmapIndex + 2] = line[0]; // Green channel bitmapData[bitmapIndex + 1] = line[1]; // Red channel bitmapData[bitmapIndex + 0] = line[2]; line += 3; bitmapIndex += bpp; } } } else if (bpp == 1) { for (int y = 0; y < height; y++) memcpy (bitmapData + y * width, data + y * step, width); } // Turn the bitmap context into an imageRef CGImageRef imageRef = CGBitmapContextCreateImage( context ); CGContextRelease( context ); if( !imageRef ) { free( bitmapData ); return false; } // Write the imageRef to a file based on the UTI CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL, (const UInt8*)m_filename.c_str(), m_filename.size(), false ); if( !imageURLRef ) { CGImageRelease( imageRef ); free( bitmapData ); return false; } CGImageDestinationRef destRef = CGImageDestinationCreateWithURL( imageURLRef, imageUTI, 1, NULL); CFRelease( imageURLRef ); if( !destRef ) { CGImageRelease( imageRef ); free( bitmapData ); fprintf(stderr, "!destRef\n"); return false; } CGImageDestinationAddImage(destRef, imageRef, NULL); if( !CGImageDestinationFinalize(destRef) ) { fprintf(stderr, "Finalize failed\n"); return false; } CFRelease( destRef ); CGImageRelease( imageRef ); free( bitmapData ); return true; }
bool ImageIODecoder::readData( Mat& img ) { uchar* data = img.data; int step = img.step; bool color = img.channels() > 1; int bpp; // Bytes per pixel int bit_depth = 8; // Get Height, Width, and color information if( !readHeader() ) return false; CGContextRef context = NULL; // The bitmap context CGColorSpaceRef colorSpace = NULL; uchar* bitmap = NULL; CGImageAlphaInfo alphaInfo; // CoreGraphics will take care of converting to grayscale and back as long as the // appropriate colorspace is set if( color == CV_LOAD_IMAGE_GRAYSCALE ) { colorSpace = CGColorSpaceCreateDeviceGray(); bpp = 1; alphaInfo = kCGImageAlphaNone; } else if( color == CV_LOAD_IMAGE_COLOR ) { #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR colorSpace = CGColorSpaceCreateDeviceRGB(); #else colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear ); #endif bpp = 4; /* CG only has 8 and 32 bit color spaces, so we waste a byte */ alphaInfo = kCGImageAlphaNoneSkipLast; } if( !colorSpace ) return false; bitmap = (uchar*)malloc( bpp * m_height * m_width ); if( !bitmap ) { CGColorSpaceRelease( colorSpace ); return false; } context = CGBitmapContextCreate( (void *)bitmap, m_width, /* width */ m_height, /* height */ bit_depth, /* bit depth */ bpp * m_width, /* bytes per row */ colorSpace, /* color space */ alphaInfo); CGColorSpaceRelease( colorSpace ); if( !context ) { free( bitmap ); return false; } // Copy the image data into the bitmap region CGRect rect = {{0,0},{m_width,m_height}}; CGContextDrawImage( context, rect, imageRef ); uchar* bitdata = (uchar*)CGBitmapContextGetData( context ); if( !bitdata ) { free( bitmap); CGContextRelease( context ); return false; } // Move the bitmap (in RGB) into data (in BGR) int bitmapIndex = 0; if( color == CV_LOAD_IMAGE_COLOR ) { uchar * base = data; for (int y = 0; y < m_height; y++) { uchar * line = base + y * step; for (int x = 0; x < m_width; x++) { // Blue channel line[0] = bitdata[bitmapIndex + 2]; // Green channel line[1] = bitdata[bitmapIndex + 1]; // Red channel line[2] = bitdata[bitmapIndex + 0]; line += 3; bitmapIndex += bpp; } } } else if( color == CV_LOAD_IMAGE_GRAYSCALE ) { for (int y = 0; y < m_height; y++) memcpy (data + y * step, bitmap + y * m_width, m_width); } free( bitmap ); CGContextRelease( context ); return true; }
// ----------------------------------------------------------------------------- // CreateCGImageWithQTFromFile // ----------------------------------------------------------------------------- // OSStatus CreateCGImageWithQTFromFile( FSRef* inFSRef, CGImageRef* outImage ) { OSStatus err; GraphicsImportComponent importer; FSSpec fileSpec; GWorldPtr gWorld = NULL; Rect bounds; CGDataProviderRef provider; CGColorSpaceRef colorspace; long width; long height; long rowbytes; Ptr dataPtr; // Make an FSRef into an FSSpec err = FSGetCatalogInfo( inFSRef, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL ); require_noerr( err, CantMakeFSSpec ); err = GetGraphicsImporterForFile( &fileSpec, &importer ); require_noerr( err, CantGetImporter ); err = GraphicsImportGetNaturalBounds( importer, &bounds ); require_noerr( err, CantGetBounds ); // Allocate the buffer width = RECT_WIDTH( bounds ); height = RECT_HEIGHT( bounds ); rowbytes = width * 4; dataPtr = NewPtr( height * rowbytes ); require_action( dataPtr != NULL, CantAllocBuffer, err = memFullErr ); err = NewGWorldFromPtr( &gWorld, 32, &bounds, NULL, NULL, NULL, dataPtr, rowbytes ); require_noerr( err, CantCreateGWorld ); err = GraphicsImportSetGWorld( importer, gWorld, GetGWorldDevice( gWorld) ); require_noerr( err, CantSetGWorld ); err = GraphicsImportDraw( importer ); require_noerr( err, CantDraw ); provider = CGDataProviderCreateWithData( NULL, dataPtr, height * rowbytes, GWorldImageBufferRelease ); require_action( provider != NULL, CantCreateProvider, err = memFullErr ); colorspace = CGColorSpaceCreateDeviceRGB(); require_action( colorspace != NULL, CantCreateColorSpace, err = memFullErr ); *outImage = CGImageCreate( width, height, 8, 32, rowbytes, colorspace, kCGImageAlphaPremultipliedFirst, provider, NULL, false, kCGRenderingIntentDefault ); require_action( *outImage != NULL, CantCreateImage, err = memFullErr ); CantCreateImage: CGColorSpaceRelease( colorspace ); CantCreateColorSpace: CGDataProviderRelease( provider ); CantCreateProvider: CantDraw: CantSetGWorld: if ( gWorld != NULL ) DisposeGWorld( gWorld ); CantCreateGWorld: CantAllocBuffer: CantGetBounds: CantGetImporter: CantMakeFSSpec: return err; }
PsychError SCREENTestTexture(void) { #if PSYCH_SYSTEM == PSYCH_OSX PsychWindowRecordType *winRec; CGContextRef cgContext; unsigned int memoryTotalSizeBytes, memoryRowSizeBytes; UInt32 *textureMemory; int stringLength, totalTexels, i; GLuint myTexture; CGColorSpaceRef cgColorSpace; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //Get the window structure for the onscreen window. It holds the onscreein GL context which we will need in the //final step when we copy the texture from system RAM onto the screen. PsychErrorExit(PsychCapNumInputArgs(1)); PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumOutputArgs(1)); PsychAllocInWindowRecordArg(1, TRUE, &winRec); if(!PsychIsOnscreenWindow(winRec)) PsychErrorExitMsg(PsychError_user, "Onscreen window pointer required"); //allocate memory for the surface memoryRowSizeBytes=sizeof(UInt32) * textureSizeX; memoryTotalSizeBytes= memoryRowSizeBytes * textureSizeY; textureMemory=(UInt32 *)malloc(memoryTotalSizeBytes); if(!textureMemory) PsychErrorExitMsg(PsychError_internal, "Failed to allocate surface memory\n"); if(useQuartz){ //Create the Core Graphics bitmap graphics context. We have to be careful to specify arguments which will allow us to store the texture as an OpenGL texture. //The choice of color space needs to be checked. cgColorSpace=CGColorSpaceCreateDeviceRGB(); cgContext= CGBitmapContextCreate(textureMemory, textureSizeX, textureSizeY, cg_RGBA_32_BitsPerComponent, memoryRowSizeBytes, cgColorSpace, cg_RGBA_32_AlphaOption); if(!cgContext){ free((void *)textureMemory); PsychErrorExitMsg(PsychError_internal, "Failed to allocate CG Bimap Context\n"); } // Draw some text into the bitmap context. We need to set font, size, pen (drawing mode), color, alpha, text position. // There are two ways to select the font in a Core Graphics Quartz context depending on the type of font. // 1) CGContextSetFont() for Apple Type Services (ATS) font aka "The Right Way" // A) call CGFontCreateWithPlatformFont() which returns a CGFontRef // B) call CGContextSetFont() to set the font to be the drawing font within a context. // 2) CGContextSelectFont() for MacRoman aka "How We Do It" // // Using MacRoman seems to mean that we just change the coding, though CGContextSelectFont(). For info on using ATS fonts see: // http://developer.apple.com/documentation/Carbon/Reference/ATS/ CGContextSelectFont(cgContext, "Helvetica", (float)24, kCGEncodingMacRoman); //set the font and its size. CGContextSetTextDrawingMode(cgContext, kCGTextFill); //set the pen to be a filled pen CGContextSetRGBStrokeColor(cgContext, (float)0.5, (float)0.5, (float)0.0, (float)1.0); //set the stroke color and alpha CGContextSetRGBFillColor(cgContext, (float)0.5, (float)0.5, (float)0.0, (float)1.0); //set the fill color and alpha stringLength=strlen(textString); CGContextShowTextAtPoint(cgContext, (float)textPositionX, (float)textPositionY, textString, stringLength); //draw at specified location. CGContextFlush(cgContext); //this might not be necessary but do it just in case. }else{ //fill the texture memory by poking bits in the array which will be turned into a texture. totalTexels=textureSizeX * textureSizeY; for(i=0;i<totalTexels;i++) textureMemory[i]= redFill << 24 | greenFill | 16 << blueFill << 8 | alphaFill; } //Convert the CG graphics bitmap (Quartz surface) into a CG texture. GL thinks we are loading the texture from memory we indicate to glTexImage2D, but really //we are just setting the texture to share the same memory as the Quartz surface. PsychSetGLContext(winRec); glEnable(GL_TEXTURE_RECTANGLE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glGenTextures(1, &myTexture); //create an index "name" for our texture glBindTexture(GL_TEXTURE_RECTANGLE_EXT, myTexture); //instantiate a texture of type associated with the index and set it to be the target for subsequent gl texture operators. glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1); //tell gl how to unpack from our memory when creating a surface, namely don't really unpack it but use it for texture storage. glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //specify interpolation scaling rule for copying from texture. glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //specify interpolation scaling rule from copying from texture. glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, textureSizeX, textureSizeY, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, textureMemory); //Copy the texture to the display. What are the s and t indices of the first pixel of the texture ? 0 or 1 ? //set the GL context to be the onscreen window glBegin(GL_QUADS); glTexCoord2d(0.0, 0.0); glVertex2d(0.0, 0.0); glTexCoord2d(textureSizeX, 0.0 ); glVertex2d(textureSizeX, 0.0); glTexCoord2d(textureSizeX, textureSizeY); glVertex2d(textureSizeX, textureSizeY); glTexCoord2d(0.0, textureSizeY); glVertex2d(0.0, textureSizeY); glEnd(); glFlush(); glDisable(GL_TEXTURE_RECTANGLE_EXT); //Close up shop. Unlike with normal textures is important to release the context before deallocating the memory which glTexImage2D() was given. //First release the GL context, then the CG context, then free the memory. glDeleteTextures(1, &myTexture); //Remove references from gl to the texture memory & free gl's associated resources if(useQuartz) CGContextRelease(cgContext); //Remove references from Core Graphics to the texture memory & free Core Graphics' associated resources. free((void *)textureMemory); //Free the memory #endif return(PsychError_none); }
Q_UNUSED(aglPixelFormat); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 GLint attributeCount = 2; #else long attributeCount = 2; #endif CGLPixelFormatAttribute pfa[attributeCount]; pfa[0] = kCGLPFAWindow; pfa[1] = (CGLPixelFormatAttribute) 0; err = CGLChoosePixelFormat(pfa, &cglPixelFormat, &attributeCount); BACKEND_ASSERT3(err == noErr, "Could not create pixel format (OpenGL)", FATAL_ERROR, false) } CFTypeRef keys[] = { kQTVisualContextWorkingColorSpaceKey }; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CFDictionaryRef textureContextAttributes = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)&colorSpace, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); err = QTOpenGLTextureContextCreate(kCFAllocatorDefault, cglContext, cglPixelFormat, textureContextAttributes, &m_visualContext); CFRelease(textureContextAttributes); BACKEND_ASSERT3(err == noErr, "Could not create visual context (OpenGL)", FATAL_ERROR, false) if (m_movieRef && m_visualContext) SetMovieVisualContext(m_movieRef, m_visualContext); return true; }
/* Create a CGImageRef from osg::Image. * Code adapted from * http://developer.apple.com/samplecode/OpenGLScreenSnapshot/listing2.html */ CGImageRef CreateCGImageFromOSGData(const osg::Image &osg_image) { size_t image_width = osg_image.s(); size_t image_height = osg_image.t(); /* From Apple's header for CGBitmapContextCreate() * Each row of the bitmap consists of `bytesPerRow' bytes, which must be at * least `(width * bitsPerComponent * number of components + 7)/8' bytes. */ size_t target_bytes_per_row; CGColorSpaceRef color_space; CGBitmapInfo bitmap_info; /* From what I can figure out so far... * We need to create a CGContext connected to the data we want to save * and then call CGBitmapContextCreateImage() on that context to get * a CGImageRef. * However, OS X only allows 4-component image formats (e.g. RGBA) and not * just RGB for the RGB-based CGContext. So for a 24-bit image coming in, * we need to expand the data to 32-bit. * The easiest and fastest way to do that is through the vImage framework * which is part of the Accelerate framework. * Also, the osg::Image data coming in is inverted from what we want, so * we need to invert the image too. Since the osg::Image is const, * we don't want to touch the data, so again we turn to the vImage framework * and invert the data. */ vImage_Buffer vimage_buffer_in = { (void*)osg_image.data(), // need to override const, but we don't modify the data so it's safe image_height, image_width, osg_image.getRowSizeInBytes() }; void *out_image_data; vImage_Buffer vimage_buffer_out = { NULL, // will fill-in in switch image_height, image_width, 0 // will fill-in in switch }; vImage_Error vimage_error_flag; // FIXME: Do I want to use format, type, or internalFormat? switch (osg_image.getPixelFormat()) { case GL_LUMINANCE: { bitmap_info = kCGImageAlphaNone; target_bytes_per_row = (image_width * 8 + 7) / 8; // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); color_space = CGColorSpaceCreateDeviceGray(); if (NULL == color_space) { return NULL; } // out_image_data = calloc(target_bytes_per_row, image_height); out_image_data = malloc(target_bytes_per_row * image_height); if (NULL == out_image_data) { OSG_WARN << "In CreateCGImageFromOSGData, malloc failed" << std::endl; CGColorSpaceRelease(color_space); return NULL; } vimage_buffer_out.data = out_image_data; vimage_buffer_out.rowBytes = target_bytes_per_row; // Now invert the image vimage_error_flag = vImageVerticalReflect_Planar8( &vimage_buffer_in, // since the osg_image is const... &vimage_buffer_out, // don't reuse the buffer kvImageNoFlags ); if (vimage_error_flag != kvImageNoError) { OSG_WARN << "In CreateCGImageFromOSGData for GL_LUMINANCE, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; free(out_image_data); CGColorSpaceRelease(color_space); return NULL; } break; } case GL_ALPHA: { bitmap_info = kCGImageAlphaOnly; target_bytes_per_row = (image_width * 8 + 7) / 8; // According to: // http://developer.apple.com/qa/qa2001/qa1037.html // colorSpace=NULL is for alpha only color_space = NULL; // out_image_data = calloc(target_bytes_per_row, image_height); out_image_data = malloc(target_bytes_per_row * image_height); if (NULL == out_image_data) { OSG_WARN << "In CreateCGImageFromOSGData, malloc failed" << std::endl; return NULL; } vimage_buffer_out.data = out_image_data; vimage_buffer_out.rowBytes = target_bytes_per_row; // Now invert the image vimage_error_flag = vImageVerticalReflect_Planar8( &vimage_buffer_in, // since the osg_image is const... &vimage_buffer_out, // don't reuse the buffer kvImageNoFlags ); if (vimage_error_flag != kvImageNoError) { OSG_WARN << "In CreateCGImageFromOSGData for GL_ALPHA, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; free(out_image_data); return NULL; } break; } /* case GL_LUMINANCE_ALPHA: { // I don't know if we can support this. // The qa1037 doesn't show both gray+alpha. break; } */ case GL_RGB: { bitmap_info = kCGImageAlphaNoneSkipFirst; target_bytes_per_row = (image_width * 8 * 4 + 7) / 8; // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); color_space = CGColorSpaceCreateDeviceRGB(); if (NULL == color_space) { OSG_WARN << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; return NULL; } // out_image_data = calloc(target_bytes_per_row, image_height); out_image_data = malloc(target_bytes_per_row * image_height); if (NULL == out_image_data) { OSG_WARN << "In CreateCGImageFromOSGData, malloc failed" << std::endl; CGColorSpaceRelease(color_space); return NULL; } // Use vImage to get an RGB buffer into ARGB. vimage_buffer_out.data = out_image_data; vimage_buffer_out.rowBytes = target_bytes_per_row; vimage_error_flag = vImageConvert_RGB888toARGB8888( &vimage_buffer_in, NULL, // we don't have a buffer containing alpha values 255, // The alpha value we want given to all pixels since we don't have a buffer &vimage_buffer_out, 0, // premultiply? kvImageNoFlags // Only responds to kvImageDoNotTile, but I think we want tiling/threading ); if (vimage_error_flag != kvImageNoError) { OSG_WARN << "In CreateCGImageFromOSGData, vImageConvert_RGB888toARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; free(out_image_data); CGColorSpaceRelease(color_space); return NULL; } // Now invert the image vimage_error_flag = vImageVerticalReflect_ARGB8888( &vimage_buffer_out, &vimage_buffer_out, // reuse the same buffer kvImageNoFlags ); if (vimage_error_flag != kvImageNoError) { OSG_WARN << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; free(out_image_data); CGColorSpaceRelease(color_space); return NULL; } break; } case GL_RGBA: { bitmap_info = kCGImageAlphaPremultipliedLast; target_bytes_per_row = osg_image.getRowSizeInBytes(); // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); color_space = CGColorSpaceCreateDeviceRGB(); if (NULL == color_space) { OSG_WARN << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; return NULL; } // out_image_data = calloc(target_bytes_per_row, image_height); out_image_data = malloc(target_bytes_per_row * image_height); if (NULL == out_image_data) { OSG_WARN << "In CreateCGImageFromOSGData, malloc failed" << std::endl; CGColorSpaceRelease(color_space); return NULL; } vimage_buffer_out.data = out_image_data; vimage_buffer_out.rowBytes = target_bytes_per_row; // Invert the image vimage_error_flag = vImageVerticalReflect_ARGB8888( &vimage_buffer_in, // since the osg_image is const... &vimage_buffer_out, // don't reuse the buffer kvImageNoFlags ); if (vimage_error_flag != kvImageNoError) { OSG_WARN << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; free(out_image_data); CGColorSpaceRelease(color_space); return NULL; } break; } case GL_BGRA: { if (GL_UNSIGNED_INT_8_8_8_8_REV == osg_image.getDataType()) { #if __BIG_ENDIAN__ bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif } else { // FIXME: Don't know how to handle this case bitmap_info = kCGImageAlphaPremultipliedLast; } target_bytes_per_row = osg_image.getRowSizeInBytes(); // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); color_space = CGColorSpaceCreateDeviceRGB(); if (NULL == color_space) { OSG_WARN << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; return NULL; } // out_image_data = calloc(target_bytes_per_row, image_height); out_image_data = malloc(target_bytes_per_row * image_height); if (NULL == out_image_data) { OSG_WARN << "In CreateCGImageFromOSGData, malloc failed" << std::endl; CGColorSpaceRelease(color_space); return NULL; } vimage_buffer_out.data = out_image_data; vimage_buffer_out.rowBytes = target_bytes_per_row; // Invert the image vimage_error_flag = vImageVerticalReflect_ARGB8888( &vimage_buffer_in, // since the osg_image is const... &vimage_buffer_out, // don't reuse the buffer kvImageNoFlags ); if (vimage_error_flag != kvImageNoError) { OSG_WARN << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; free(out_image_data); CGColorSpaceRelease(color_space); return NULL; } break; } // FIXME: Handle other cases. // Use vImagePermuteChannels_ARGB8888 to swizzle bytes default: { OSG_WARN << "In CreateCGImageFromOSGData: Sorry support for this format is not implemented." << std::endl; return NULL; break; } } CGContextRef bitmap_context = CGBitmapContextCreate( vimage_buffer_out.data, vimage_buffer_out.width, vimage_buffer_out.height, 8, vimage_buffer_out.rowBytes, color_space, bitmap_info ); /* Done with color space */ CGColorSpaceRelease(color_space); if (NULL == bitmap_context) { free(out_image_data); return NULL; } /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */ CGImageRef image_ref = CGBitmapContextCreateImage(bitmap_context); /* Done with data */ free(out_image_data); /* Done with bitmap_context */ CGContextRelease(bitmap_context); return image_ref; }
static bool image_coregraphics_load (fs_file_t *f, image_t *im, int *error) { CGDataProviderRef provider = fs_data_provider_of_file(f); CGColorSpaceRef color_space = NULL; CGContextRef context = NULL; CGImageRef image = NULL; void *data = NULL; bool ok = false; for (unsigned i = 0; i < G_N_ELEMENTS(providers); i++) { if ((image = providers[i](provider, NULL, true, kCGRenderingIntentDefault))) { break; } } if (!image) { *error = IMAGE_ERROR_INVALID_FORMAT; goto error; } int width = CGImageGetWidth(image); int height = CGImageGetHeight(image); if (!image_dimensions_valid(width, header)) { *error = IMAGE_ERROR_INVALID_SIZE; goto error; } if (!(data = mem_alloc(image_mem_pool, width * height * 4))) { *error = IMAGE_ERROR_ALLOC_FAILED; goto error; } if (!(color_space = CGColorSpaceCreateDeviceRGB())) { *error = IMAGE_ERROR_INTERNAL; goto error; } context = CGBitmapContextCreate(data, width, height, 8, width * 4, color_space, kCGImageAlphaPremultipliedLast); if (!context) { *error = IMAGE_ERROR_INTERNAL; goto error; } CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); im->width = width; im->height = height; im->format = IMAGE_DATA_FORMAT_BGRA; im->data = data; // convert to bgra for (int i = 0; i < width * height; i++) { uint8_t r = im->data[(i << 2) + 0]; im->data[(i << 2) + 0] = im->data[(i << 2) + 2]; im->data[(i << 2) + 2] = r; } ok = true; error: CGContextRelease(context); CGColorSpaceRelease(color_space); CGImageRelease(image); fs_data_provider_release(provider); if (!ok) { mem_free(data); } return ok; }
void JBGSetUpJumballGraphics() { CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); // 白色 CGFloat white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; kJBGWhite = CGColorCreate(color_space, white); // 浅蓝 204 224 244 CGFloat light_blue[4] = {204/255.0f, 224/255.0f, 244/255.0f, 1.0f}; kJBGLightBlue = CGColorCreate(color_space, light_blue); // 蓝 29 156 215 CGFloat blue[4] = {29/255.0f, 156/255.0f, 215/255.0f, 1.0f}; kJBGBlue = CGColorCreate(color_space, blue); // 深蓝 0 50 126 CGFloat dark_blue[4] = {0, 50/255.0f, 126/255.0f, 1.0f}; kJBGDarkBlue = CGColorCreate(color_space, dark_blue); // 深红 Firebrick3 205 38 38 CGFloat dark_red[4] = {205/255.0f, 38/255.0f, 38/255.0f, 1.0f}; kJBGDarkRed = CGColorCreate(color_space, dark_red); // 红 Firebrick2 238 44 44 CGFloat red[4] = {238/255.0f, 44/255.0f, 44/255.0f, 1.0f}; kJBGRed = CGColorCreate(color_space, red); // 深金 DarkGoldenrod3 205 149 12 CGFloat dark_gold[4] = {205/255.0f, 149/255.0f, 12/255.0f, 1.0f}; kJBGDarkGold = CGColorCreate(color_space, dark_gold); // 金 DarkGoldenrod2 238 173 14 (原来选的是255 215 0) CGFloat gold[4] = {238/255.0f, 173.0f/255.0f, 14/255.0f, 1.0f}; kJBGGold = CGColorCreate(color_space, gold); // 深绿 SpringGreen3 0 205 102 CGFloat dark_green[4] = {0, 205/255.0f, 102/255.0f, 1.0f}; kJBGDarkGreen = CGColorCreate(color_space, dark_green); // 绿 SpringGreen2 0 238 118 CGFloat green[4] = {0, 238/255.0f, 118/255.0f, 1.0f}; kJBGGreen = CGColorCreate(color_space, green); // 深紫 Purple3 125 38 205 CGFloat dark_purple[4] = {125/255.0f, 38/255.0f, 205/255.0f, 1.0f}; kJBGDarkPurple = CGColorCreate(color_space, dark_purple); // 紫 Purple2 145 44 238 CGFloat purple[4] = {145/255.0f, 44/255.0f, 238/255.0f, 1.0f}; kJBGPurple = CGColorCreate(color_space, purple); // 深粉红 Magenta3 205 0 205 CGFloat dark_pink[4] = {205/255.0f, 0/255.0f, 205/255.0f, 1.0f}; kJBGDarkPink = CGColorCreate(color_space, dark_pink); // 粉红 Magenta2 238 0 238 CGFloat pink[4] = {238/255.0f, 0/255.0f, 238/255.0f, 1.0f}; kJBGPink = CGColorCreate(color_space, pink); // 深黄 Yellow3 205 205 0 CGFloat dark_yellow[4] = {205, 205/255.0f, 0/255.0f, 1.0f}; kJBGDarkYellow = CGColorCreate(color_space, dark_yellow); // 黄 Yellow2 238 238 0 CGFloat yellow[4] = {238, 238/255.0f, 0/255.0f, 1.0f}; kJBGYellow = CGColorCreate(color_space, yellow); CGColorSpaceRelease(color_space); }
void drawGraphic( CGContextRef context, float x, float y ) { static GWorldPtr imageGW = NULL; static CGImageRef imageRef = NULL; static CGDataProviderRef dataProviderRef = NULL; Rect bounds; static size_t width; static size_t height; size_t bitsPerComponent; size_t bitsPerPixel; size_t bytesPerRow; PixMapHandle pmh; // Load the image if we haven't already if ( NULL == imageGW ) { // Load and create the GWorld imageGW = OpenImage(); if ( imageGW != NULL ) { GetPortBounds( imageGW, &bounds ); width = bounds.right - bounds.left; height = bounds.bottom - bounds.top; pmh = GetPortPixMap( imageGW ); bitsPerComponent = (**pmh).cmpSize; bitsPerPixel = (**pmh).pixelSize; bytesPerRow = GetPixRowBytes( pmh ); LockPixels( pmh ); dataProviderRef = CGDataProviderCreateWithData( NULL, GetPixBaseAddr( pmh ), height * bytesPerRow, releaseData ); // Create the imageRef for that GWorld imageRef = CGImageCreate( width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedFirst/*kCGImageAlphaNone*/, dataProviderRef, NULL, 0, kCGRenderingIntentDefault ); } } // Draw the image at 0,0 CGContextDrawImage( context, CGRectMake( x - 20, y, 40, 40 * height / width ), imageRef ); }
QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph) { const glyph_metrics_t br = boundingBox(glyph); QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32); im.fill(0); CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaNoneSkipFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) cgflags |= kCGBitmapByteOrder32Host; #endif #else CGImageAlphaInfo cgflags = kCGImageAlphaNoneSkipFirst; #endif CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), 8, im.bytesPerLine(), colorspace, cgflags); CGColorSpaceRelease(colorspace); CGContextSetFontSize(ctx, fontDef.pixelSize); CGContextSetShouldAntialias(ctx, fontDef.pointSize > qt_antialiasing_threshold && !(fontDef.styleStrategy & QFont::NoAntialias)); CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0); CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, multiEngine->transform); CGContextSetTextMatrix(ctx, cgMatrix); CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); CGContextSetTextDrawingMode(ctx, kCGTextFill); CGContextSetFont(ctx, cgFont); qreal pos_x = -br.x.toReal()+1, pos_y = im.height()+br.y.toReal(); CGContextSetTextPosition(ctx, pos_x, pos_y); CGSize advance; advance.width = 0; advance.height = 0; CGGlyph cgGlyph = glyph; CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); if (synthesisFlags & QFontEngine::SynthesizedBold) { CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); } CGContextRelease(ctx); QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); QVector<QRgb> colors(256); for (int i=0; i<256; ++i) colors[i] = qRgba(0, 0, 0, i); indexed.setColorTable(colors); for (int y=0; y<im.height(); ++y) { uint *src = (uint*) im.scanLine(y); uchar *dst = indexed.scanLine(y); for (int x=0; x<im.width(); ++x) { *dst = qGray(*src); ++dst; ++src; } } return indexed; }
BOOL MacWidgetPainter::DrawProgressbar(const OpRect &drawrect, double percent, INT32 progress_when_total_unknown, OpWidgetString* string, const char *skin_empty, const char *skin_full) { const char *full_skin = skin_full && *skin_full ? skin_full : "Progress Full Skin"; OpSkinElement *border_skin = g_skin_manager->GetSkinElement(full_skin); if(!g_skin_manager->GetCurrentSkin() || !border_skin || !border_skin->IsNative()) { return IndpWidgetPainter::DrawProgressbar(drawrect, percent, progress_when_total_unknown, string, skin_empty, skin_full); } UINT32 full_color = g_op_ui_info->GetUICSSColor(CSS_VALUE_HighlightText); g_skin_manager->GetTextColor(full_skin, &full_color); CGRect r = {{0, 0}, {drawrect.width, drawrect.height}}; CGContextRef context; OpBitmap* bitmap = NULL; int bmpwidth = drawrect.width; int bmpheight = drawrect.height; #ifdef PIXEL_SCALE_RENDERING_SUPPORT const PixelScaler& scaler = vd->GetVPScale(); bmpwidth = TO_DEVICE_PIXEL(scaler, bmpwidth); bmpheight = TO_DEVICE_PIXEL(scaler, bmpheight); #endif // PIXEL_SCALE_RENDERING_SUPPORT if(OpStatus::IsSuccess(OpBitmap::Create(&bitmap, bmpwidth, bmpheight, FALSE, TRUE, 0, 0, TRUE))) { int w = bitmap->Width(); int h = bitmap->Height(); int bpl = bitmap->GetBytesPerLine(); void *image_data = bitmap->GetPointer(OpBitmap::ACCESS_WRITEONLY); if (!image_data) { delete bitmap; return FALSE; } memset(image_data, 0, bpl*h); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo alpha = kCGBitmapByteOrderVegaInternal; context = CGBitmapContextCreate(image_data, w, h, 8, bpl, colorSpace, alpha); CGColorSpaceRelease(colorSpace); int win_height = drawrect.height; float scale = 1.0f; #ifdef PIXEL_SCALE_RENDERING_SUPPORT scale = TO_DEVICE_PIXEL(scaler, scale); #endif // PIXEL_SCALE_RENDERING_SUPPORT CGContextScaleCTM(context, scale, -scale); CGContextTranslateCTM(context, 0.0, -win_height); if (percent == 0 && progress_when_total_unknown) { HIThemeTrackDrawInfo drawInfo; SInt32 thickness = 0; SInt32 shadow = 0; if (noErr == GetThemeMetric(kThemeMetricLargeProgressBarThickness, &thickness) && (noErr == GetThemeMetric(kThemeMetricProgressBarShadowOutset, &shadow))) { SInt32 progressHeight = thickness + shadow; if((r.size.height) > progressHeight) { float f = (r.size.height - progressHeight); // / 2; r.origin.y += f; r.size.height -= f; } } else { float f = (r.size.height / 4) - 1; r.origin.y += f; r.size.height -= f; } drawInfo.version = 0; drawInfo.kind = kThemeIndeterminateBarLarge; drawInfo.bounds = r; drawInfo.min = 0; drawInfo.max = 100; drawInfo.value = 0; drawInfo.attributes = kThemeTrackHorizontal; drawInfo.enableState = widget->IsEnabled() ? kThemeTrackActive : kThemeTrackInactive; drawInfo.trackInfo.progress.phase = progress_when_total_unknown; HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal); } else { HIThemeTrackDrawInfo drawInfo; SInt32 thickness = 0; SInt32 shadow = 0; if (noErr == GetThemeMetric(kThemeMetricLargeProgressBarThickness, &thickness) && (noErr == GetThemeMetric(kThemeMetricProgressBarShadowOutset, &shadow))) { SInt32 progressHeight = thickness + shadow; if((r.size.height) > progressHeight) { float f = (r.size.height - progressHeight); // / 2; r.origin.y += f; r.size.height -= f; } } else { float f = (r.size.height / 4) - 1; r.origin.y += f; r.size.height -= f; } drawInfo.version = 0; drawInfo.kind = kThemeProgressBarLarge; drawInfo.bounds = r; drawInfo.min = 0; drawInfo.max = 100; drawInfo.value = (SInt32)(percent); drawInfo.attributes = kThemeTrackHorizontal; drawInfo.enableState = widget->IsEnabled() ? kThemeTrackActive : kThemeTrackInactive; drawInfo.trackInfo.progress.phase = floorf(GetCurrentEventTime()*16); HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal); } CGContextRelease(context); bitmap->ReleasePointer(); vd->BitmapOut(bitmap, OpRect(0, 0, bitmap->Width(), bitmap->Height()), drawrect); delete bitmap; } if (string) { widget->SetClipRect(drawrect); OpRect textRect = drawrect; textRect.y -= 1; string->Draw(textRect, vd, full_color); widget->RemoveClipRect(); } return TRUE; }
void myOperator_Do(CGPDFScannerRef s, void *info) { // Check to see if this is an image or not. const char *name; CGPDFObjectRef xobject; CGPDFDictionaryRef dict; CGPDFStreamRef stream; CGPDFContentStreamRef cs = CGPDFScannerGetContentStream(s); // The Do operator takes a name. Pop the name off the // stack. If this fails then the argument to the // Do operator is not a name and is therefore invalid! if(!CGPDFScannerPopName(s, &name)){ fprintf(stderr, "Couldn't pop name off stack!\n"); return; } // Get the resource with type "XObject" and the name // obtained from the stack. xobject = CGPDFContentStreamGetResource(cs, "XObject", name); if(!xobject){ fprintf(stderr, "Couldn't get XObject with name %s\n", name); return; } // An XObject must be a stream so obtain the value from the xobject // as if it were a stream. If this fails, the PDF is malformed. if (!CGPDFObjectGetValue(xobject, kCGPDFObjectTypeStream, &stream)){ fprintf(stderr, "XObject '%s' is not a stream!\n", name); return; } // Streams consist of a dictionary and the data associated // with the stream. This code only cares about the dictionary. dict = CGPDFStreamGetDictionary(stream); if(!dict){ fprintf(stderr, "Couldn't obtain dictionary from stream %s!\n", name); return; } // An XObject dict has a Subtype that indicates what kind it is. if(!CGPDFDictionaryGetName(dict, "Subtype", &name)){ fprintf(stderr, "Couldn't get SubType of dictionary object!\n"); return; } // This code is interested in the "Image" Subtype of an XObject. // Check whether this object has Subtype of "Image". printf("%s\n",name); if(strcmp(name, "Image") != 0){ // The Subtype is not "Image" so this must be a form // or other type of XObject. return; } else { CGPDFArrayRef colorSpaceArray; CGPDFDictionaryGetArray(dict,"ColorSpace" ,&colorSpaceArray); CGColorSpaceRef colorSpace=NULL; colorSpace=colorSpaceFromPDFArray(colorSpaceArray); CGPDFDataFormat format; const char *name = NULL, *colorSpaceName = NULL,*renderingIntentName = NULL;; CFDataRef data=CGPDFStreamCopyData(stream,&format); if (format == CGPDFDataFormatRaw){ CGColorSpaceRef cgColorSpace; CGPDFInteger width, height, bps, spp; CGColorRenderingIntent renderingIntent; CGPDFBoolean interpolation = 0; CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data); if (!CGPDFDictionaryGetInteger(dict, "Width", &width)) return ; if (!CGPDFDictionaryGetInteger(dict, "Height", &height)) return ; if (!CGPDFDictionaryGetInteger(dict, "BitsPerComponent", &bps)) return ; if (!CGPDFDictionaryGetBoolean(dict, "Interpolate", &interpolation)) interpolation = 0; if (!CGPDFDictionaryGetName(dict, "Intent", &renderingIntentName)) renderingIntent = kCGRenderingIntentDefault; else{ renderingIntent = kCGRenderingIntentDefault; // renderingIntent = renderingIntentFromName(renderingIntentName); } if (CGPDFDictionaryGetArray(dict, "ColorSpace", &colorSpaceArray)) { cgColorSpace = CGColorSpaceCreateDeviceRGB(); // cgColorSpace = colorSpaceFromPDFArray(colorSpaceArray); spp = CGColorSpaceGetNumberOfComponents(cgColorSpace); } else if (CGPDFDictionaryGetName(dict, "ColorSpace", &colorSpaceName)) { if (strcmp(colorSpaceName, "DeviceRGB") == 0) { cgColorSpace = CGColorSpaceCreateDeviceRGB(); // CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); spp = 3; } else if (strcmp(colorSpaceName, "DeviceCMYK") == 0) { cgColorSpace = CGColorSpaceCreateDeviceCMYK(); // CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK); spp = 4; } else if (strcmp(colorSpaceName, "DeviceGray") == 0) { cgColorSpace = CGColorSpaceCreateDeviceGray(); // CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); spp = 1; } else if (bps == 1) { // if there's no colorspace entry, there's still one we can infer from bps cgColorSpace = CGColorSpaceCreateDeviceGray(); // colorSpace = NSDeviceBlackColorSpace; spp = 1; } } CGFloat *decodeValues = NULL; decodeValues = decodeValuesFromImageDictionary(dict, cgColorSpace, bps); int rowBits = bps * spp * width; int rowBytes = rowBits / 8; // pdf image row lengths are padded to byte-alignment if (rowBits % 8 != 0) ++rowBytes; CGImageRef sourceImage = CGImageCreate(width, height, bps, bps * spp, rowBytes, cgColorSpace, 0, dataProvider, decodeValues, interpolation, renderingIntent); CGDataProviderRelease(dataProvider); CGDataProviderRef dataProvider2 = CGImageGetDataProvider(sourceImage); CFDataRef data = CGDataProviderCopyData(dataProvider2); int fd; findex; char file[256]; memset(file,0,sizeof(file)); sprintf(file,"%d.jpg",findex); fd=open(file, O_RDWR|O_CREAT); write(fd, CFDataGetBytePtr(data), CFDataGetLength(data)); findex++; close(fd); //[[NSImage alloc] initWithCGImage:sourceImage size:NSMakeSize(0, 0)]; }else { int fd; findex; char file[256]; memset(file,0,sizeof(file)); sprintf(file,"%d.jpg",findex); fd=open(file, O_RDWR|O_CREAT); write(fd, CFDataGetBytePtr(data), CFDataGetLength(data)); findex++; close(fd); } } // This is an Image so figure out what variety of image it is. checkImageType(dict, (MyDataScan *)info); }
BOOL MacWidgetPainter::DrawSlider(const OpRect& rect, BOOL horizontal, double min, double max, double pos, BOOL highlighted, BOOL pressed_knob, OpRect& out_knob_position, OpPoint& out_start_track, OpPoint& out_end_track) { // Opera 11.50: We are going to use special skinned (non-toolkit) sliders for zoom sliders // so we are not drawing with our painter in that case if (!widget || widget->GetType() == OpTypedObject::WIDGET_TYPE_ZOOM_SLIDER) return FALSE; OpSkinElement *border_skin = widget->GetBorderSkin()->GetSkinElement(); if(!g_skin_manager->GetCurrentSkin() || (border_skin && !border_skin->IsNative())) { return IndpWidgetPainter::DrawSlider(rect, horizontal, min, max, pos, highlighted, pressed_knob, out_knob_position, out_start_track, out_end_track); } CGRect r = {{0, 0}, {rect.width, rect.height}}; CGContextRef context; OpBitmap* bitmap = NULL; int bmpwidth = rect.width; int bmpheight = rect.height; #ifdef PIXEL_SCALE_RENDERING_SUPPORT const PixelScaler& scaler = vd->GetVPScale(); bmpwidth = TO_DEVICE_PIXEL(scaler, bmpwidth); bmpheight = TO_DEVICE_PIXEL(scaler, bmpheight); #endif // PIXEL_SCALE_RENDERING_SUPPORT if(OpStatus::IsSuccess(OpBitmap::Create(&bitmap, bmpwidth, bmpheight, FALSE, TRUE, 0, 0, TRUE))) { int w = bitmap->Width(); int h = bitmap->Height(); int bpl = bitmap->GetBytesPerLine(); void *image_data = bitmap->GetPointer(OpBitmap::ACCESS_WRITEONLY); if (!image_data) { delete bitmap; return FALSE; } memset(image_data, 0, bpl*h); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo alpha = kCGBitmapByteOrderVegaInternal; context = CGBitmapContextCreate(image_data, w, h, 8, bpl, colorSpace, alpha); CGColorSpaceRelease(colorSpace); int win_height = rect.height; float scale = 1.0f; #ifdef PIXEL_SCALE_RENDERING_SUPPORT scale = TO_DEVICE_PIXEL(scaler, scale); #endif // PIXEL_SCALE_RENDERING_SUPPORT CGContextScaleCTM(context, scale, -scale); CGContextTranslateCTM(context, 0.0, -win_height); HIThemeTrackDrawInfo drawInfo; SInt32 thickness = 0; SInt32 shadow = 0; if (noErr == GetThemeMetric(kThemeMetricLargeProgressBarThickness, &thickness) && (noErr == GetThemeMetric(kThemeMetricProgressBarShadowOutset, &shadow))) { SInt32 progressHeight = thickness + shadow; if (horizontal) { if((r.size.height) > progressHeight) { float f = (r.size.height - progressHeight); r.origin.y += f / 2; r.size.height -= f; } } else { if((r.size.width) > progressHeight) { float f = (r.size.width - progressHeight); r.origin.x += f / 2; r.size.width -= f; } } } else { if (horizontal) { float f = (r.size.height / 4) - 1; r.origin.y += f / 2; r.size.height -= f; } else { float f = (r.size.width / 4) - 1; r.origin.x += f / 2; r.size.width -= f; } } drawInfo.version = 0; drawInfo.kind = kThemeSliderSmall; drawInfo.bounds = r; drawInfo.min = 0; drawInfo.max = NUMBER_OF_STEPS; if (widget->GetRTL()) drawInfo.value = (max - pos) / (max - min) * NUMBER_OF_STEPS; else drawInfo.value = (pos - min) / (max - min) * NUMBER_OF_STEPS; drawInfo.attributes = kThemeTrackShowThumb; if (horizontal) { drawInfo.attributes |= kThemeTrackHorizontal; } else { drawInfo.attributes |= kThemeTrackRightToLeft; } drawInfo.enableState = widget->IsEnabled() ? kThemeTrackActive : kThemeTrackInactive; drawInfo.trackInfo.slider.thumbDir = kThemeThumbPlain; drawInfo.trackInfo.slider.pressState = 0; if (highlighted) drawInfo.attributes |= kThemeTrackHasFocus; HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal); HIShapeRef thumb_shape; HIRect thumb_bounds, track_bounds; HIThemeGetTrackThumbShape(&drawInfo, &thumb_shape); HIShapeGetBounds(thumb_shape, &thumb_bounds); HIThemeGetTrackBounds(&drawInfo, &track_bounds); CFRelease(thumb_shape); out_knob_position.Set(thumb_bounds.origin.x, thumb_bounds.origin.y, thumb_bounds.size.width, thumb_bounds.size.height); out_start_track.Set(track_bounds.origin.x, track_bounds.origin.y); out_end_track.Set(track_bounds.origin.x+track_bounds.size.width, track_bounds.origin.y+track_bounds.size.height); CGContextRelease(context); bitmap->ReleasePointer(); vd->BitmapOut(bitmap, OpRect(0, 0, bitmap->Width(), bitmap->Height()), rect); delete bitmap; } return TRUE; }
void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode& ec) { ASSERT(canvas); ec = 0; FloatRect srcCanvasRect = FloatRect(FloatPoint(), canvas->size()); if (!(srcCanvasRect.contains(srcRect) && srcRect.width() >= 0 && srcRect.height() >= 0 && dstRect.width() >= 0 && dstRect.height() >= 0)) { ec = INDEX_SIZE_ERR; return; } if (srcRect.isEmpty() || dstRect.isEmpty()) return; GraphicsContext* c = drawingContext(); if (!c) return; FloatRect sourceRect = c->roundToDevicePixels(srcRect); FloatRect destRect = c->roundToDevicePixels(dstRect); // FIXME: Do this through platform-independent GraphicsContext API. #if PLATFORM(CG) CGImageRef platformImage = canvas->createPlatformImage(); if (!platformImage) return; willDraw(destRect); float iw = CGImageGetWidth(platformImage); float ih = CGImageGetHeight(platformImage); if (sourceRect.x() == 0 && sourceRect.y() == 0 && iw == sourceRect.width() && ih == sourceRect.height()) { // Fast path, yay! CGContextDrawImage(c->platformContext(), destRect, platformImage); } else { // Slow path, boo! // Create a new bitmap of the appropriate size and then draw that into our context. size_t csw = static_cast<size_t>(ceilf(sourceRect.width())); size_t csh = static_cast<size_t>(ceilf(sourceRect.height())); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); size_t bytesPerRow = csw * 4; void* buffer = fastMalloc(csh * bytesPerRow); CGContextRef clippedSourceContext = CGBitmapContextCreate(buffer, csw, csh, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); CGContextTranslateCTM(clippedSourceContext, -sourceRect.x(), -sourceRect.y()); CGContextDrawImage(clippedSourceContext, CGRectMake(0, 0, iw, ih), platformImage); CGImageRef clippedSourceImage = CGBitmapContextCreateImage(clippedSourceContext); CGContextRelease(clippedSourceContext); CGContextDrawImage(c->platformContext(), destRect, clippedSourceImage); CGImageRelease(clippedSourceImage); fastFree(buffer); } CGImageRelease(platformImage); #elif PLATFORM(QT) QPixmap px = canvas->createPlatformImage(); if (px.isNull()) return; willDraw(dstRect); QPainter* painter = static_cast<QPainter*>(c->platformContext()); painter->drawPixmap(dstRect, px, srcRect); #endif }
BOOL MacWidgetPainter::DrawScrollbar(const OpRect &drawrect) { HIThemeTrackDrawInfo drawInfo; ThemeTrackPressState pressState = 0; OpScrollbar *scroll = (OpScrollbar*)widget; HIShapeRef thumbRgn; OpRect opBounds = scroll->GetBounds(); CGRect bounds = {{-drawrect.x, -drawrect.y}, {opBounds.width, opBounds.height}}; pressState = (ThemeTrackPressState)scroll->GetHitPart(); // hack to draw correctly, for some reason DrawThemeTrack needs this. if(pressState == kThemeTopInsideArrowPressed) pressState = kThemeBottomInsideArrowPressed; else if(pressState == kThemeBottomInsideArrowPressed) pressState = kThemeTopInsideArrowPressed; if(scroll->horizontal) { bounds.size.width++; } else { bounds.size.height++; } OpWindow *rootWindow; BOOL inActiveWindow = FALSE; if (vd->GetView()) { rootWindow = vd->GetView()->GetContainer()->GetOpView()->GetRootWindow(); inActiveWindow = rootWindow->IsActiveTopmostWindow() || rootWindow->GetStyle() == OpWindow::STYLE_POPUP; } drawInfo.version = 0; drawInfo.kind = kThemeMediumScrollBar; drawInfo.enableState = (scroll->IsEnabled() && inActiveWindow) ? kThemeTrackActive : kThemeTrackInactive; drawInfo.attributes = kThemeTrackShowThumb | (scroll->horizontal ? kThemeTrackHorizontal : 0); drawInfo.bounds = bounds; drawInfo.min = scroll->limit_min; drawInfo.max = scroll->limit_max; drawInfo.value = scroll->value; drawInfo.trackInfo.scrollbar.viewsize = scroll->limit_visible; drawInfo.trackInfo.scrollbar.pressState = pressState; int minSize = g_op_ui_info->GetHorizontalScrollbarHeight(); if (GetOSVersion() >= 0x1070) { minSize = 0; } else if (GetInfo()->GetScrollbarArrowStyle() == ARROWS_AT_BOTTOM_AND_TOP) { minSize *= 6; minSize -= 4; } else { minSize *= 4; } // Bail out if smaller than minSize if(scroll->horizontal) { if((bounds.size.width) < minSize) { return FALSE; } } else { if((bounds.size.height) < minSize) { return FALSE; } } // Ok, the thumb(knob) could have been changed, let's update if(noErr == HIThemeGetTrackThumbShape(&drawInfo, &thumbRgn)) { HIRect thumbRect; OpRect thumbOpRect; HIShapeGetBounds(thumbRgn, &thumbRect); CFRelease(thumbRgn); thumbOpRect.x = thumbRect.origin.x - bounds.origin.x; thumbOpRect.y = thumbRect.origin.y - bounds.origin.y; thumbOpRect.width = thumbRect.size.width; thumbOpRect.height = thumbRect.size.height; scroll->SetKnobRect(thumbOpRect); } if (OpStatus::IsError(MacCachedObjectFactory<MacWidgetBitmap, MacWidgetBitmapTraits>::Init())) return FALSE; int bmpwidth = drawrect.width; int bmpheight = drawrect.height; #ifdef PIXEL_SCALE_RENDERING_SUPPORT const PixelScaler& scaler = vd->GetVPScale(); bmpwidth = TO_DEVICE_PIXEL(scaler, bmpwidth); bmpheight = TO_DEVICE_PIXEL(scaler, bmpheight); #endif // PIXEL_SCALE_RENDERING_SUPPORT MacWidgetBitmap* bitmap = MacCachedObjectFactory<MacWidgetBitmap, MacWidgetBitmapTraits>::CreateObject(MacWidgetBitmapTraits::CreateParam(bmpwidth, bmpheight)); if (!bitmap) return FALSE; // Set clip and draw widget->SetClipRect(drawrect); OpBitmap* bmp = bitmap->GetOpBitmap(); void* image_data = bmp->GetPointer(OpBitmap::ACCESS_WRITEONLY); if (!image_data) { bitmap->DecRef(); widget->RemoveClipRect(); return FALSE; } bitmap->Lock(); const int bpl = bmp->GetBytesPerLine(); memset(image_data, 0, bpl * bmp->Height()); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo alpha = kCGBitmapByteOrderVegaInternal; // create the context at size of drawrect instead of bitmap itself. // we cache the bitmap to prevent create-destroy cycle and reallocation. // since we need the bitmap's memory only, we can create a much smaller context within that buffer. CGContextRef context = CGBitmapContextCreate(image_data, bmpwidth, bmpheight, 8, bpl, colorSpace, alpha); CGColorSpaceRelease(colorSpace); if (!context) { bitmap->DecRef(); bmp->ReleasePointer(FALSE); widget->RemoveClipRect(); bitmap->Unlock(); return FALSE; } const int win_height = drawrect.height; CGFloat scale = 1.0f; #ifdef PIXEL_SCALE_RENDERING_SUPPORT scale = CGFloat(scaler.GetScale()) / 100.0f; #endif // PIXEL_SCALE_RENDERING_SUPPORT CGContextScaleCTM(context, scale, -scale); CGContextTranslateCTM(context, 0.0f, -win_height); HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal); bmp->ReleasePointer(); vd->BitmapOut(bmp, OpRect(0, 0, bmp->Width(), bmp->Height()), drawrect); CGContextRelease(context); widget->RemoveClipRect(); bitmap->Unlock(); bitmap->DecRef(); return TRUE; }
/* 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-4Using 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.0f, 0.0f}, {static_cast<CGFloat>(the_width), static_cast<CGFloat>(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; }
void ContentLayerChromium::updateContents() { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); if (!backing || backing->paintingGoesToWindow()) return; ASSERT(drawsContent()); ASSERT(layerRenderer()); // FIXME: Remove this test when tiled layers are implemented. m_skipsDraw = false; if (!layerRenderer()->checkTextureSize(m_bounds)) { m_skipsDraw = true; return; } void* pixels = 0; IntRect dirtyRect(m_dirtyRect); IntSize requiredTextureSize; IntSize bitmapSize; requiredTextureSize = m_bounds; IntRect boundsRect(IntPoint(0, 0), m_bounds); // If the texture needs to be reallocated then we must redraw the entire // contents of the layer. if (requiredTextureSize != m_allocatedTextureSize) dirtyRect = boundsRect; else { // Clip the dirtyRect to the size of the layer to avoid drawing outside // the bounds of the backing texture. dirtyRect.intersect(boundsRect); } #if PLATFORM(SKIA) const SkBitmap* skiaBitmap = 0; OwnPtr<skia::PlatformCanvas> canvas; OwnPtr<PlatformContextSkia> skiaContext; OwnPtr<GraphicsContext> graphicsContext; canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); skiaContext.set(new PlatformContextSkia(canvas.get())); // This is needed to get text to show up correctly. // FIXME: Does this take us down a very slow text rendering path? skiaContext->setDrawingToImageBuffer(true); graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); // Bring the canvas into the coordinate system of the paint rect. canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); skiaBitmap = &bitmap; ASSERT(skiaBitmap); SkAutoLockPixels lock(*skiaBitmap); SkBitmap::Config skiaConfig = skiaBitmap->config(); // FIXME: do we need to support more image configurations? if (skiaConfig == SkBitmap::kARGB_8888_Config) { pixels = skiaBitmap->getPixels(); bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); } #elif PLATFORM(CG) Vector<uint8_t> tempVector; int rowBytes = 4 * dirtyRect.width(); tempVector.resize(rowBytes * dirtyRect.height()); memset(tempVector.data(), 0, tempVector.size()); RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(), dirtyRect.width(), dirtyRect.height(), 8, rowBytes, colorSpace.get(), kCGImageAlphaPremultipliedLast)); CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height()); CGContextScaleCTM(contextCG.get(), 1, -1); GraphicsContext graphicsContext(contextCG.get()); // Translate the graphics context into the coordinate system of the dirty rect. graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y()); m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect); pixels = tempVector.data(); bitmapSize = dirtyRect.size(); #else #error "Need to implement for your platform." #endif unsigned textureId = m_contentsTexture; if (!textureId) textureId = layerRenderer()->createLayerTexture(); if (pixels) updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId); }