auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize& size, bool grayScale) { if (size.width() < 0 || size.height() < 0) return auto_ptr<ImageBuffer>(); unsigned int bytesPerRow = size.width(); if (!grayScale) { // Protect against overflow if (bytesPerRow > 0x3FFFFFFF) return auto_ptr<ImageBuffer>(); bytesPerRow *= 4; } void* imageBuffer = tryFastCalloc(size.height(), bytesPerRow); if (!imageBuffer) return auto_ptr<ImageBuffer>(); CGColorSpaceRef colorSpace = grayScale ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); CGContextRef cgContext = CGBitmapContextCreate(imageBuffer, size.width(), size.height(), 8, bytesPerRow, colorSpace, grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); if (!cgContext) { fastFree(imageBuffer); return auto_ptr<ImageBuffer>(); } auto_ptr<GraphicsContext> context(new GraphicsContext(cgContext)); context->scale(FloatSize(1, -1)); context->translate(0, -size.height()); CGContextRelease(cgContext); return auto_ptr<ImageBuffer>(new ImageBuffer(imageBuffer, size, context)); }
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)); }
static bool MCAlphaToCGImage(uindex_t p_width, uindex_t p_height, uint8_t* p_data, uindex_t p_stride, CGImageRef &r_image) { bool t_success = true; CGImageRef t_image = nil; CGColorSpaceRef t_colorspace = nil; CFDataRef t_data = nil; CGDataProviderRef t_dp = nil; if (t_success) t_success = nil != (t_data = CFDataCreate(kCFAllocatorDefault, (uint8_t*)p_data, p_stride * p_height)); if (t_success) t_success = nil != (t_dp = CGDataProviderCreateWithCFData(t_data)); if (t_success) t_success = nil != (t_colorspace = CGColorSpaceCreateDeviceGray()); if (t_success) t_success = nil != (t_image = CGImageCreate(p_width, p_height, 8, 8, p_stride, t_colorspace, kCGImageAlphaNone, t_dp, nil, false, kCGRenderingIntentDefault)); CGColorSpaceRelease(t_colorspace); CGDataProviderRelease(t_dp); CFRelease(t_data); if (t_success) r_image = t_image; return t_success; }
ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success) : m_data(size) , m_size(size) { success = false; // Make early return mean failure. unsigned bytesPerRow; if (size.width() < 0 || size.height() < 0) return; bytesPerRow = size.width(); if (!grayScale) { // Protect against overflow if (bytesPerRow > 0x3FFFFFFF) return; bytesPerRow *= 4; } m_data.m_data = tryFastCalloc(size.height(), bytesPerRow); ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0); CGColorSpaceRef colorSpace = grayScale ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); CGContextRef cgContext = CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow, colorSpace, grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); if (!cgContext) return; m_context.set(new GraphicsContext(cgContext)); m_context->scale(FloatSize(1, -1)); m_context->translate(0, -size.height()); CGContextRelease(cgContext); success = true; }
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); }
static void copyImageData_gray( CGImageRef imageRef, cv::Mat &image ) { size_t width = CGImageGetWidth(imageRef); size_t height = CGImageGetHeight(imageRef); image = cv::Mat( cv::Size( width, height ), CV_8UC1 ); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); unsigned char *rawData = image.data; size_t bytesPerPixel = 1; size_t bytesPerRow = bytesPerPixel * width; size_t bitsPerComponent = 8; CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaNone | kCGBitmapByteOrderDefault); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); CGContextRelease(context); }
void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel, float alpha) { state().m_shadowOffset = FloatSize(width, height); state().m_shadowBlur = blur; state().m_shadowColor = ""; GraphicsContext* c = drawingContext(); if (!c) return; // FIXME: Do this through platform-independent GraphicsContext API. #if PLATFORM(CG) const CGFloat components[2] = { grayLevel, alpha }; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGColorRef color = CGColorCreate(colorSpace, components); CGColorSpaceRelease(colorSpace); CGContextSetShadowWithColor(c->platformContext(), CGSizeMake(width, height), blur, color); CGColorRelease(color); #endif }
CGImageRef CGImageMaskCreateWithImageRef(CGImageRef imageRef) { size_t maskWidth = CGImageGetWidth(imageRef); size_t maskHeight = CGImageGetHeight(imageRef); size_t bytesPerRow = maskWidth; size_t bufferSize = maskWidth * maskHeight; CFMutableDataRef dataBuffer = CFDataCreateMutable(kCFAllocatorDefault, 0); CFDataSetLength(dataBuffer, bufferSize); CGColorSpaceRef greyColorSpaceRef = CGColorSpaceCreateDeviceGray(); CGContextRef ctx = CGBitmapContextCreate(CFDataGetMutableBytePtr(dataBuffer), maskWidth, maskHeight, 8, bytesPerRow, greyColorSpaceRef, kCGImageAlphaNone); CGContextDrawImage(ctx, CGRectMake(0, 0, maskWidth, maskHeight), imageRef); CGContextRelease(ctx); CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(dataBuffer); CGImageRef maskImageRef = CGImageMaskCreate(maskWidth, maskHeight, 8, 8, bytesPerRow, dataProvider, NULL, FALSE); CGDataProviderRelease(dataProvider); CGColorSpaceRelease(greyColorSpaceRef); CFRelease(dataBuffer); return maskImageRef; }
/* 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; }
//------------------------------------------------------------------------------ bool MacCarbFont::create( const char* name, U32 size, U32 charset) { String nameStr = name; nameStr = nameStr.trim(); // create and cache the style and layout. // based on apple sample code at http://developer.apple.com/qa/qa2001/qa1027.html // note: charset is ignored on mac. -- we don't need it to get the right chars. // But do we need it to translate encodings? hmm... CFStringRef cfsName; ATSUFontID atsuFontID; ATSFontRef atsFontRef; Fixed atsuSize; ATSURGBAlphaColor black; ATSFontMetrics fontMetrics; U32 scaledSize; bool isBold = false; bool isItalic = false; bool haveModifier; do { haveModifier = false; if( nameStr.compare( "Bold", 4, String::NoCase | String::Right ) == 0 ) { isBold = true; nameStr = nameStr.substr( 0, nameStr.length() - 4 ).trim(); haveModifier = true; } if( nameStr.compare( "Italic", 6, String::NoCase | String::Right ) == 0 ) { isItalic = true; nameStr = nameStr.substr( 0, nameStr.length() - 6 ).trim(); haveModifier = true; } } while( haveModifier ); // Look up the font. We need it in 2 differnt formats, for differnt Apple APIs. cfsName = CFStringCreateWithCString( kCFAllocatorDefault, nameStr.c_str(), kCFStringEncodingUTF8); if(!cfsName) Con::errorf("Error: could not make a cfstring out of \"%s\" ",nameStr.c_str()); atsFontRef = ATSFontFindFromName( cfsName, kATSOptionFlagsDefault); atsuFontID = FMGetFontFromATSFontRef( atsFontRef); // make sure we found it. ATSFontFindFromName() appears to return 0 if it cant find anything. Apple docs contain no info on error returns. if( !atsFontRef || !atsuFontID ) { Con::errorf("MacCarbFont::create - could not load font -%s-",name); return false; } // adjust the size. win dpi = 96, mac dpi = 72. 72/96 = .75 // Interestingly enough, 0.75 is not what makes things the right size. scaledSize = size - 2 - (int)((float)size * 0.1); mSize = scaledSize; // Set up the size and color. We send these to ATSUSetAttributes(). atsuSize = IntToFixed(scaledSize); black.red = black.green = black.blue = black.alpha = 1.0; // Three parrallel arrays for setting up font, size, and color attributes. ATSUAttributeTag theTags[] = { kATSUFontTag, kATSUSizeTag, kATSURGBAlphaColorTag}; ByteCount theSizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(ATSURGBAlphaColor) }; ATSUAttributeValuePtr theValues[] = { &atsuFontID, &atsuSize, &black }; // create and configure the style object. ATSUCreateStyle(&mStyle); ATSUSetAttributes( mStyle, 3, theTags, theSizes, theValues ); if( isBold ) { ATSUAttributeTag tag = kATSUQDBoldfaceTag; ByteCount size = sizeof( Boolean ); Boolean value = true; ATSUAttributeValuePtr valuePtr = &value; ATSUSetAttributes( mStyle, 1, &tag, &size, &valuePtr ); } if( isItalic ) { ATSUAttributeTag tag = kATSUQDItalicTag; ByteCount size = sizeof( Boolean ); Boolean value = true; ATSUAttributeValuePtr valuePtr = &value; ATSUSetAttributes( mStyle, 1, &tag, &size, &valuePtr ); } // create the layout object, ATSUCreateTextLayout(&mLayout); // we'll bind the layout to a bitmap context when we actually draw. // ATSUSetTextPointerLocation() - will set the text buffer // ATSUSetLayoutControls() - will set the cg context. // get font metrics, save our baseline and height ATSFontGetHorizontalMetrics(atsFontRef, kATSOptionFlagsDefault, &fontMetrics); mBaseline = scaledSize * fontMetrics.ascent; mHeight = scaledSize * ( fontMetrics.ascent - fontMetrics.descent + fontMetrics.leading ) + 1; // cache our grey color space, so we dont have to re create it every time. mColorSpace = CGColorSpaceCreateDeviceGray(); // and finally cache the font's name. We use this to cheat some antialiasing options below. mName = StringTable->insert(name); 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-4††Using a Quartz image as a texture source. * Unfortunately, this guide doesn't show what to do about * non-RGBA image formats so I'm making the rest up * (and it's probably all wrong). */ size_t the_width = CGImageGetWidth(image_ref); size_t the_height = CGImageGetHeight(image_ref); CGRect the_rect = {{0, 0}, {the_width, the_height}}; size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref); size_t bytes_per_row = CGImageGetBytesPerRow(image_ref); // size_t bits_per_component = CGImageGetBitsPerComponent(image_ref); size_t bits_per_component = 8; CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref); GLint internal_format; GLenum pixel_format; GLenum data_type; void* image_data = calloc(the_width * 4, the_height); CGColorSpaceRef color_space; CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref); switch(bits_per_pixel) { // Drat, if 8-bit, how do you distinguish // between a 256 color GIF, a LUMINANCE map // or an ALPHA map? case 8: { // I probably did the formats all wrong for this case, // especially the ALPHA case. if(kCGImageAlphaNone == alpha_info) { /* internal_format = GL_LUMINANCE; pixel_format = GL_LUMINANCE; */ internal_format = GL_RGBA8; pixel_format = GL_BGRA_EXT; data_type = GL_UNSIGNED_INT_8_8_8_8_REV; bytes_per_row = the_width*4; // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); color_space = CGColorSpaceCreateDeviceRGB(); // bitmap_info = kCGImageAlphaPremultipliedFirst; #if __BIG_ENDIAN__ bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif } else { internal_format = GL_ALPHA; pixel_format = GL_ALPHA; data_type = GL_UNSIGNED_BYTE; // bytes_per_row = the_width; // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); color_space = CGColorSpaceCreateDeviceGray(); } break; } case 24: { internal_format = GL_RGBA8; pixel_format = GL_BGRA_EXT; data_type = GL_UNSIGNED_INT_8_8_8_8_REV; bytes_per_row = the_width*4; // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); color_space = CGColorSpaceCreateDeviceRGB(); // bitmap_info = kCGImageAlphaNone; #if __BIG_ENDIAN__ bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif break; } // // Tatsuhiro Nishioka // 16 bpp grayscale (8 bit white and 8 bit alpha) causes invalid argument combination // in CGBitmapContextCreate. // I guess it is safer to handle 16 bit grayscale image as 32-bit RGBA image. // It works at least on FlightGear // case 16: case 32: case 48: case 64: { internal_format = GL_RGBA8; pixel_format = GL_BGRA_EXT; data_type = GL_UNSIGNED_INT_8_8_8_8_REV; bytes_per_row = the_width*4; // color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); color_space = CGColorSpaceCreateDeviceRGB(); // bitmap_info = kCGImageAlphaPremultipliedFirst; #if __BIG_ENDIAN__ bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif break; } default: { // OSG_WARN << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl; return NULL; break; } } // Sets up a context to be drawn to with image_data as the area to be drawn to CGContextRef bitmap_context = CGBitmapContextCreate( image_data, the_width, the_height, bits_per_component, bytes_per_row, color_space, bitmap_info ); CGContextTranslateCTM(bitmap_context, 0, the_height); CGContextScaleCTM(bitmap_context, 1.0, -1.0); // Draws the image into the context's image_data CGContextDrawImage(bitmap_context, the_rect, image_ref); CGContextRelease(bitmap_context); if (!image_data) return NULL; // alpha is premultiplied with rgba, undo it vImage_Buffer vb; vb.data = image_data; vb.height = the_height; vb.width = the_width; vb.rowBytes = the_width * 4; vImageUnpremultiplyData_RGBA8888(&vb, &vb, 0); // changing it to GL_UNSIGNED_BYTE seems working, but I'm not sure if this is a right way. // data_type = GL_UNSIGNED_BYTE; osg::Image* osg_image = new osg::Image; osg_image->setImage( the_width, the_height, 1, internal_format, pixel_format, data_type, (unsigned char*)image_data, osg::Image::USE_MALLOC_FREE // Assumption: osg_image takes ownership of image_data and will free ); return osg_image; }
CGImageRef _cairo_quartz_create_cgimage (cairo_format_t format, unsigned int width, unsigned int height, unsigned int stride, void *data, cairo_bool_t interpolate, CGColorSpaceRef colorSpaceOverride, CGDataProviderReleaseDataCallback releaseCallback, void *releaseInfo) { CGImageRef image = NULL; CGDataProviderRef dataProvider = NULL; CGColorSpaceRef colorSpace = colorSpaceOverride; CGBitmapInfo bitinfo; int bitsPerComponent, bitsPerPixel; switch (format) { case CAIRO_FORMAT_ARGB32: if (colorSpace == NULL) colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; case CAIRO_FORMAT_RGB24: if (colorSpace == NULL) colorSpace = CGColorSpaceCreateDeviceRGB(); bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; bitsPerComponent = 8; bitsPerPixel = 32; break; /* XXX -- should use CGImageMaskCreate! */ case CAIRO_FORMAT_A8: if (colorSpace == NULL) colorSpace = CGColorSpaceCreateDeviceGray(); bitinfo = kCGImageAlphaNone; bitsPerComponent = 8; bitsPerPixel = 8; break; case CAIRO_FORMAT_A1: default: return NULL; } dataProvider = CGDataProviderCreateWithData (releaseInfo, data, height * stride, releaseCallback); if (!dataProvider) { // manually release if (releaseCallback) releaseCallback (releaseInfo, data, height * stride); goto FINISH; } image = CGImageCreate (width, height, bitsPerComponent, bitsPerPixel, stride, colorSpace, bitinfo, dataProvider, NULL, interpolate, kCGRenderingIntentDefault); FINISH: CGDataProviderRelease (dataProvider); if (colorSpace != colorSpaceOverride) CGColorSpaceRelease (colorSpace); return image; }
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 ) { colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear ); 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; }
FX_BOOL CFX_QuartzDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, FX_ARGB argb, const FX_RECT* srcRect, int dest_left, int dest_top, int blendType, int alphaFlag , void* iccTransform ) { SaveState(); CGFloat src_left, src_top, src_width, src_height; if (srcRect) { src_left = srcRect->left; src_top = srcRect->top; src_width = srcRect->Width(); src_height = srcRect->Height(); } else { src_left = src_top = 0; src_width = pBitmap->GetWidth(); src_height = pBitmap->GetHeight(); } CGAffineTransform ctm = CGContextGetCTM(_context); CGFloat scale_x = FXSYS_fabs(ctm.a); CGFloat scale_y = FXSYS_fabs(ctm.d); src_left /= scale_x; src_top /= scale_y; src_width /= scale_x; src_height /= scale_y; CGRect rect_fx = CGRectMake(dest_left, dest_top, src_width, src_height); CGRect rect_usr = CGRectApplyAffineTransform(rect_fx, _foxitDevice2User); CGContextBeginPath(_context); CGContextAddRect(_context, rect_usr); CGContextClip(_context); rect_usr.size = CGSizeMake(pBitmap->GetWidth() / scale_x, pBitmap->GetHeight() / scale_y); rect_usr = CGRectOffset(rect_usr, -src_left, -src_top); CG_SetImageTransform(dest_left, dest_top, src_width, src_height, &rect_usr); CFX_DIBitmap* pBitmap1 = NULL; if (pBitmap->IsAlphaMask()) { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData(NULL, pBitmap1->GetBuffer(), pBitmap1->GetPitch() * pBitmap1->GetHeight(), NULL); CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; CGImageRef pImage = CGImageCreate(pBitmap1->GetWidth(), pBitmap1->GetHeight(), pBitmap1->GetBPP(), pBitmap1->GetBPP(), pBitmap1->GetPitch(), pColorSpace, bitmapInfo, pBitmapProvider, NULL, true, kCGRenderingIntentDefault); CGContextClipToMask(_context, rect_usr, pImage); CGContextSetRGBFillColor(_context, FXARGB_R(argb) / 255.f, FXARGB_G(argb) / 255.f, FXARGB_B(argb) / 255.f, FXARGB_A(argb) / 255.f); CGContextFillRect(_context, rect_usr); CGImageRelease(pImage); CGColorSpaceRelease(pColorSpace); CGDataProviderRelease(pBitmapProvider); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; } if (pBitmap->GetBPP() < 32) { pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); } else { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } if (pBitmap1->HasAlpha()) { if (pBitmap1 == pBitmap) { pBitmap1 = pBitmap->Clone(); if (!pBitmap1) { RestoreState(FALSE); return FALSE; } } for (int row = 0; row < pBitmap1->GetHeight(); row ++) { FX_LPBYTE pScanline = (FX_LPBYTE)pBitmap1->GetScanline(row); for (int col = 0; col < pBitmap1->GetWidth(); col ++) { pScanline[0] = (FX_BYTE)(pScanline[0] * pScanline[3] / 255.f + .5f); pScanline[1] = (FX_BYTE)(pScanline[1] * pScanline[3] / 255.f + .5f); pScanline[2] = (FX_BYTE)(pScanline[2] * pScanline[3] / 255.f + .5f); pScanline += 4; } } } CGContextRef ctx = createContextWithBitmap(pBitmap1); CGImageRef image = CGBitmapContextCreateImage(ctx); int blend_mode = blendType; if (FXDIB_BLEND_HARDLIGHT == blendType) { blend_mode = kCGBlendModeSoftLight; } else if (FXDIB_BLEND_SOFTLIGHT == blendType) { blend_mode = kCGBlendModeHardLight; } else if (blendType >= FXDIB_BLEND_NONSEPARABLE && blendType <= FXDIB_BLEND_LUMINOSITY) { blend_mode = blendType - 9; } else if (blendType > FXDIB_BLEND_LUMINOSITY || blendType < 0) { blend_mode = kCGBlendModeNormal; } CGContextSetBlendMode(_context, (CGBlendMode)blend_mode); CGContextDrawImage(_context, rect_usr, image); CGImageRelease(image); CGContextRelease(ctx); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; }
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; }
vl::Image vl::ImageReader::read(const char * fileName, float * memory) { // intermediate buffer char unsigned * pixels = NULL ; int bytesPerPixel ; int bytesPerRow ; // Core graphics CGBitmapInfo bitmapInfo ; CFURLRef url = NULL ; CGImageSourceRef imageSourceRef = NULL ; CGImageRef imageRef = NULL ; CGContextRef contextRef = NULL ; CGColorSpaceRef sourceColorSpaceRef = NULL ; CGColorSpaceRef colorSpaceRef = NULL ; // initialize the image as null Image image ; image.width = 0 ; image.height = 0 ; image.depth = 0 ; image.memory = NULL ; image.error = 0 ; // get file url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)fileName, strlen(fileName), false) ; check(url) ; // get image source from file imageSourceRef = CGImageSourceCreateWithURL(url, NULL) ; check(imageSourceRef) ; // get image from image source imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, NULL); check(imageRef) ; sourceColorSpaceRef = CGImageGetColorSpace(imageRef) ; check(sourceColorSpaceRef) ; image.width = CGImageGetWidth(imageRef); image.height = CGImageGetHeight(imageRef); image.depth = CGColorSpaceGetNumberOfComponents(sourceColorSpaceRef) ; check(image.depth == 1 || image.depth == 3) ; // decode image to L (8 bits per pixel) or RGBA (32 bits per pixel) switch (image.depth) { case 1: colorSpaceRef = CGColorSpaceCreateDeviceGray(); bytesPerPixel = 1 ; bitmapInfo = kCGImageAlphaNone ; break ; case 3: colorSpaceRef = CGColorSpaceCreateDeviceRGB(); bytesPerPixel = 4 ; bitmapInfo = kCGImageAlphaPremultipliedLast || kCGBitmapByteOrder32Big ; /* this means pixels[0] = R pixels[1] = G pixels[2] = B pixels[3] = A */ break ; } check(colorSpaceRef) ; bytesPerRow = image.width * bytesPerPixel ; pixels = (char unsigned*)malloc(image.height * bytesPerRow) ; check(pixels) ; contextRef = CGBitmapContextCreate(pixels, image.width, image.height, 8, bytesPerRow, colorSpaceRef, bitmapInfo) ; check(contextRef) ; CGContextDrawImage(contextRef, CGRectMake(0, 0, image.width, image.height), imageRef); // copy pixels to MATLAB format if (memory == NULL) { image.memory = (float*)malloc(image.height * image.width * image.depth * sizeof(float)) ; check(image.memory) ; } else { image.memory = memory ; } switch (image.depth) { case 3: vl::impl::imageFromPixels<impl::pixelFormatRGBA>(image, pixels, image.width * bytesPerPixel) ; break ; case 1: vl::impl::imageFromPixels<impl::pixelFormatL>(image, pixels, image.width * bytesPerPixel) ; break ; } done: if (pixels) { free(pixels) ; } if (contextRef) { CFRelease(contextRef) ; } if (colorSpaceRef) { CFRelease(colorSpaceRef) ; } if (imageRef) { CFRelease(imageRef) ; } if (imageSourceRef) { CFRelease(imageSourceRef) ; } if (url) { CFRelease(url) ; } return image ; }
static cairo_int_status_t _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); cairo_image_surface_t *surface = NULL; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); int advance; CGRect bbox; double width, height; double xscale, yscale; double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); CGColorSpaceRef gray; CGContextRef cgContext = NULL; CGAffineTransform textMatrix; CGRect glyphRect, glyphRectInt; CGPoint glyphOrigin; //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface); /* Create blank 2x2 image if we don't have this character. * Maybe we should draw a better missing-glyph slug or something, * but this is ok for now. */ if (glyph == INVALID_GLYPH) { surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2); status = cairo_surface_status ((cairo_surface_t *) surface); if (status) return status; _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); return CAIRO_STATUS_SUCCESS; } if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) { return CAIRO_INT_STATUS_UNSUPPORTED; } status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale, &xscale, &yscale, 1); if (status) return status; textMatrix = CGAffineTransformMake (font->base.scale.xx, -font->base.scale.yx, -font->base.scale.xy, font->base.scale.yy, 0.0f, 0.0f); glyphRect = CGRectMake (bbox.origin.x / emscale, bbox.origin.y / emscale, bbox.size.width / emscale, bbox.size.height / emscale); glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix); /* Round the rectangle outwards, so that we don't have to deal * with non-integer-pixel origins or dimensions. */ glyphRectInt = CGRectIntegral (glyphRect); #if 0 fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); fprintf (stderr, "glyphRectInt: %f %f %f %f\n", glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height); #endif glyphOrigin = glyphRectInt.origin; //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm)); width = glyphRectInt.size.width; height = glyphRectInt.size.height; //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); if (surface->base.status) return surface->base.status; gray = CGColorSpaceCreateDeviceGray (); cgContext = CGBitmapContextCreate (surface->data, surface->width, surface->height, 8, surface->stride, gray, kCGImageAlphaNone); CGColorSpaceRelease (gray); CGContextSetFont (cgContext, font_face->cgFont); CGContextSetFontSize (cgContext, 1.0); CGContextSetTextMatrix (cgContext, textMatrix); CGContextClearRect (cgContext, CGRectMake (0.0f, 0.0f, width, height)); if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE) CGContextSetShouldAntialias (cgContext, false); CGContextSetRGBFillColor (cgContext, 1.0, 1.0, 1.0, 1.0); CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1); CGContextRelease (cgContext); cairo_surface_set_device_offset (&surface->base, - glyphOrigin.x, height + glyphOrigin.y); _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); return status; }
FX_BOOL CFX_QuartzDeviceDriver::StretchDIBits(const CFX_DIBSource* pBitmap, FX_ARGB argb, int dest_left, int dest_top, int dest_width, int dest_height, const FX_RECT* clipRect, FX_DWORD flags, int alphaFlag , void* iccTransform , int blend_type) { SaveState(); if (clipRect) { CGContextBeginPath(_context); CGRect rect_clip = CGRectMake(clipRect->left, clipRect->top, clipRect->Width(), clipRect->Height()); rect_clip = CGRectApplyAffineTransform(rect_clip, _foxitDevice2User); CGContextAddRect(_context, rect_clip); CGContextClip(_context); } CGRect rect = CGRectMake(dest_left, dest_top, dest_width, dest_height); rect = CGRectApplyAffineTransform(rect, _foxitDevice2User); if (FXDIB_BICUBIC_INTERPOL == flags) { CGContextSetInterpolationQuality(_context, kCGInterpolationHigh); } else if (FXDIB_DOWNSAMPLE == flags) { CGContextSetInterpolationQuality(_context, kCGInterpolationNone); } else { CGContextSetInterpolationQuality(_context, kCGInterpolationMedium); } CG_SetImageTransform(dest_left, dest_top, dest_width, dest_height); CFX_DIBitmap* pBitmap1 = NULL; if (pBitmap->IsAlphaMask()) { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } CGDataProviderRef pBitmapProvider = CGDataProviderCreateWithData(NULL, pBitmap1->GetBuffer(), pBitmap1->GetPitch() * pBitmap1->GetHeight(), NULL); CGColorSpaceRef pColorSpace = CGColorSpaceCreateDeviceGray(); CGBitmapInfo bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrderDefault; CGImageRef pImage = CGImageCreate(pBitmap1->GetWidth(), pBitmap1->GetHeight(), pBitmap1->GetBPP(), pBitmap1->GetBPP(), pBitmap1->GetPitch(), pColorSpace, bitmapInfo, pBitmapProvider, NULL, true, kCGRenderingIntentDefault); CGContextClipToMask(_context, rect, pImage); CGContextSetRGBFillColor(_context, FXARGB_R(argb) / 255.f, FXARGB_G(argb) / 255.f, FXARGB_B(argb) / 255.f, FXARGB_A(argb) / 255.f); CGContextFillRect(_context, rect); CGImageRelease(pImage); CGColorSpaceRelease(pColorSpace); CGDataProviderRelease(pBitmapProvider); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(FALSE); return TRUE; } if (pBitmap->GetBPP() < 32) { pBitmap1 = pBitmap->CloneConvert(FXDIB_Rgb32); } else { if (pBitmap->GetBuffer()) { pBitmap1 = (CFX_DIBitmap*)pBitmap; } else { pBitmap1 = pBitmap->Clone(); } } if (NULL == pBitmap1) { RestoreState(FALSE); return FALSE; } if (pBitmap1->HasAlpha()) { if (pBitmap1 == pBitmap) { pBitmap1 = pBitmap->Clone(); if (!pBitmap1) { RestoreState(FALSE); return FALSE; } } for (int row = 0; row < pBitmap1->GetHeight(); row ++) { FX_LPBYTE pScanline = (FX_LPBYTE)pBitmap1->GetScanline(row); for (int col = 0; col < pBitmap1->GetWidth(); col ++) { pScanline[0] = (FX_BYTE)(pScanline[0] * pScanline[3] / 255.f + .5f); pScanline[1] = (FX_BYTE)(pScanline[1] * pScanline[3] / 255.f + .5f); pScanline[2] = (FX_BYTE)(pScanline[2] * pScanline[3] / 255.f + .5f); pScanline += 4; } } } CGContextRef ctx = createContextWithBitmap(pBitmap1); CGImageRef image = CGBitmapContextCreateImage(ctx); CGContextDrawImage(_context, rect, image); CGImageRelease(image); CGContextRelease(ctx); if (pBitmap1 != pBitmap) { delete pBitmap1; } RestoreState(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); }
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); }