Beispiel #1
0
Image::Image(CGImageRef image) :
	_width(CGImageGetWidth(image)),
	_height(CGImageGetHeight(image)),
	_bitsPerComponent(CGImageGetBitsPerComponent(image)),
	_bytesPerRow(CGImageGetBytesPerRow(image)),
	_colorSpaceRef(CGImageGetColorSpace(image)),
	_bitmapInfo(CGImageGetBitmapInfo(image)),
	_pixels(new pixel3f[_width * _height]),
	_copy(new pixel3f[_width * _height])
{
	// Obtain mutable image data.
	CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(image));
	_data = CFDataCreateMutableCopy(NULL, CFDataGetLength(data), data);
	
	// Release data from image.
	CFRelease(data);
}
Screenshot* ScreenShooter::take_screenshot(const CFStringRef format, float compression) {
  CGImageRef* images = new CGImageRef[_dsp_count];
   
  /* Grab the images */
  for (unsigned int i = 0; i < _dsp_count; i++) {
     images[i] = CGDisplayCreateImage(_displays[i]);
  }

  /* Calculate size of image to produce */
  CGSize finalSize = CGSizeMake(_top_right.x - _bottom_left.x, _bottom_left.y - _top_right.y);

  /* Round out the bitmap size information */
  size_t bytesPerRow = finalSize.width * CGImageGetBitsPerPixel(images[0]) / 8;

  /* Create context around bitmap */
  CGContextRef context = CGBitmapContextCreate(
    NULL, finalSize.width, finalSize.height,
    CGImageGetBitsPerComponent(images[0]), bytesPerRow,
    CGImageGetColorSpace(images[0]), CGImageGetBitmapInfo(images[0])
  );

  /* Draw images into the bitmap */
  for (unsigned int i = 0; i < _dsp_count; i++)
  {
      /* Adjust the positions to account for coordinate system shifts
         (displays origin is at top left; image origin is at bottom left) */
      CGRect adjustedPoint = CGRectMake(_display_bounds[i].origin.x - _bottom_left.x,
                                        _bottom_left.y - _display_bounds[i].size.height - _display_bounds[i].origin.y,
                                        _display_bounds[i].size.width,
                                        _display_bounds[i].size.height);
      CGContextDrawImage(context, adjustedPoint, images[i]);
  }
  
  delete [] images;

  return new Screenshot(context, format, compression);
}
Beispiel #3
0
/* Once we have our image (CGImageRef), we need to get it into an osg::Image */
osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref)
{
    /* This code is adapted from Apple's Documentation found here:
     * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html
     * Listing 9-4††Using a Quartz image as a texture source.
     * Unfortunately, this guide doesn't show what to do about
     * non-RGBA image formats so I'm making the rest up
     * (and it's probably all wrong).
     */

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

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

    CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref);

    GLint internal_format;
    GLenum pixel_format;
    GLenum data_type;

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

    CGColorSpaceRef color_space;
    CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref);

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

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

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

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

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

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

    }
    

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

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

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

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

    return osg_image;



}
/* the error does not contain the filename as the caller already has it */
gboolean
_cogl_bitmap_from_file (CoglBitmap  *bmp,
			const gchar *filename,
			GError     **error)
{
  g_assert (bmp != NULL);
  g_assert (filename != NULL);
  g_assert (error == NULL || *error == NULL);

  CFURLRef url = CFURLCreateFromFileSystemRepresentation (NULL, (guchar*)filename, strlen(filename), false);
  CGImageSourceRef image_source = CGImageSourceCreateWithURL (url, NULL);
  int save_errno = errno;
  CFRelease (url);
  if (image_source == NULL)
    {
      /* doesn't exist, not readable, etc. */
      g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
                   "%s", g_strerror (save_errno));
      return FALSE;
    }

  /* Unknown images would be cleanly caught as zero width/height below, but try
   * to provide better error message
   */
  CFStringRef type = CGImageSourceGetType (image_source);
  if (type == NULL)
    {
      CFRelease (image_source);
      g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_UNKNOWN_TYPE,
                   "Unknown image type");
      return FALSE;
    }
  CFRelease (type);

  CGImageRef image = CGImageSourceCreateImageAtIndex (image_source, 0, NULL);
  CFRelease (image_source);

  size_t width = CGImageGetWidth (image);
  size_t height = CGImageGetHeight (image);
  if (width == 0 || height == 0)
    {
      /* incomplete or corrupt */
      CFRelease (image);
      g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_CORRUPT_IMAGE,
                   "Image has zero width or height");
      return FALSE;
    }

  /* allocate buffer big enough to hold pixel data */
  size_t rowstride;
  CGBitmapInfo bitmap_info = CGImageGetBitmapInfo (image);
  if ((bitmap_info & kCGBitmapAlphaInfoMask) == kCGImageAlphaNone)
    {
      bitmap_info = kCGImageAlphaNone;
      rowstride = 3 * width;
    }
  else
    {
      bitmap_info = kCGImageAlphaPremultipliedFirst;
      rowstride = 4 * width;
    }
  guint8 *out_data = g_malloc0 (height * rowstride);

  /* render to buffer */
  CGColorSpaceRef color_space = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
  CGContextRef bitmap_context = CGBitmapContextCreate (out_data,
                                                       width, height, 8,
                                                       rowstride, color_space,
                                                       bitmap_info);
  CGColorSpaceRelease (color_space);

  const CGRect rect = {{0, 0}, {width, height}};
  CGContextDrawImage (bitmap_context, rect, image);

  CGImageRelease (image);
  CGContextRelease (bitmap_context);

  /* store bitmap info */
  bmp->data = out_data;
  bmp->format = bitmap_info == kCGImageAlphaPremultipliedFirst
                ? COGL_PIXEL_FORMAT_ARGB_8888
                : COGL_PIXEL_FORMAT_RGB_888;
  bmp->width = width;
  bmp->height = height;
  bmp->rowstride = rowstride;

  return TRUE;
}
/* read image file */
int BIReadFile(
	const char			*fileName,
	BIFileType			fileType,
	BIPadMode			padMode,
	unsigned			padSize,
	BIImageInfo			*imageInfo,		/* RETURNED */
	unsigned char		**bitmap)		/* mallocd and RETURNED; caller must free */
{
	CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, 
		(unsigned char*)fileName, strlen(fileName), FALSE);
	if(fileURL == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CFURLCreateFromFileSystemRepresentation\n");
		return -1;
	}

	CFStringRef keys[1] = {kCGImageSourceTypeIdentifierHint};
	CFStringRef values[1] = {BIGetUTI(fileURL, fileType)};
	
	if(values[0] == NULL) {
		return -1;
	}
	
	CFDictionaryRef		optionsDict = NULL;
	CGImageSourceRef	imageSourceRef = NULL;
	CGImageRef			imageRef = NULL;
	CGColorSpaceRef		rgbColorSpaceRef = NULL;
	CGContextRef		bitmapContextRef = NULL;
	CGBitmapInfo		bitmapInfo = 0;
	CGImageAlphaInfo	alpha;
	unsigned			bytesPerPixel = 4;
	
	optionsDict = CFDictionaryCreate( kCFAllocatorDefault, 
		(const void **)keys, (const void **)values, 1,  
		&kCFTypeDictionaryKeyCallBacks,  &kCFTypeDictionaryValueCallBacks );
	/* subsequent errors to errOut: */
	
	int ourRtn = 0;
	
	/* source file --> CGImageRef */
	imageSourceRef = CGImageSourceCreateWithURL(fileURL, optionsDict);
	if(imageSourceRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateWithURL\n");
		ourRtn = 1;
		goto errOut;
	}
	CFRELEASE(fileURL);
	imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, optionsDict );
	if(imageRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CGImageSourceCreateImageAtIndex\n");
		ourRtn = 1;
		goto errOut;
	}
	
	imageInfo->imageWidth			= CGImageGetWidth(imageRef);
	imageInfo->imageHeight			= CGImageGetHeight(imageRef);
	imageInfo->bitsPerComponent		= CGImageGetBitsPerComponent(imageRef);
	imageInfo->bitsPerPixel			= CGImageGetBitsPerPixel(imageRef);
	
	if(imageInfo->bitsPerPixel == 8) {
		/* the image is gray */
		rgbColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
		imageInfo->bytesPerRow = imageInfo->imageWidth; 
		alpha = kCGImageAlphaNone;
		bitmapInfo = CGImageGetBitmapInfo(imageRef);
		bytesPerPixel = 1;
	}
	else {
        rgbColorSpaceRef = CGColorSpaceCreateDeviceRGB();
		imageInfo->bytesPerRow = imageInfo->imageWidth * 4;
		alpha = kCGImageAlphaPremultipliedLast;
		bitmapInfo = kCGBitmapByteOrder32Big | alpha;
	}
	if(rgbColorSpaceRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error on CGColorSpaceCreateWithName\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* optionally pad */
	imageInfo->effectHeight = imageInfo->imageHeight;
	if(padMode != PM_None) {
		if(padSize == 0) {
			fprintf(stderr, "***Pad size of 0 invalid\n");
			ourRtn = 1;
			goto errOut;
		}
		unsigned padSizeBytes = padSize;
		if(padMode == PM_Pixels) {
			padSizeBytes *= bytesPerPixel;
		}
		imageInfo->bytesPerRow = ROUND_TO(imageInfo->bytesPerRow, padSizeBytes);
		/* also round up row count */
		imageInfo->effectHeight = ROUND_TO(imageInfo->imageHeight, padSize);
	}

	*bitmap = (unsigned char *)malloc(imageInfo->bytesPerRow * imageInfo->effectHeight);
	
	bitmapContextRef = CGBitmapContextCreate(*bitmap, 
		imageInfo->imageWidth, imageInfo->imageHeight, 
		imageInfo->bitsPerComponent, imageInfo->bytesPerRow, 
		rgbColorSpaceRef, 
		bitmapInfo);
	if(bitmapContextRef == NULL) {
		fprintf(stderr, "***BIReadFile: Error creating CGBitmapContext\n");
		ourRtn = 1;
		goto errOut;
	}

	/* enable high quality interpolation */
	CGContextSetInterpolationQuality(bitmapContextRef, kCGInterpolationHigh);

	/* Draw into the context */
	CGContextDrawImage(bitmapContextRef, CGRectMake(0, 0, imageInfo->imageWidth, imageInfo->imageHeight), 
		imageRef);

errOut:
	CFRELEASE(optionsDict);
	CFRELEASE(imageSourceRef);
	CFRELEASE(imageRef);
	CFRELEASE(rgbColorSpaceRef);
	CFRELEASE(bitmapContextRef);
	if(ourRtn) {
		if(*bitmap) {
			free(*bitmap);
			*bitmap = NULL;
		}
	}
	return ourRtn;
}
Beispiel #6
0
result_t MMMaker_make(const char **sourceMaskDirs,
                      int          nSourceMaskDirs,
                      const char  *filename)
{
#define MAX_FILENAMES 500

  result_t           err;
  char             **sourceMaskFilenames;
  int                nSourceMaskFilenames = 0;
  char              *sourceMaskFilenamesBuffer = NULL;
  motionmaskmaker_t *maker = NULL;
  int                i;
  CGImageRef         makerSource[MAX_FILENAMES];
  CGBitmapInfo       bitmapInfo;
  pixelfmt_t         pixelfmt;
  bitmap_set_t       makerBitmaps;
  CFDataRef          pixels[MAX_FILENAMES];
  void              *makerBitmapBases[MAX_FILENAMES];

  err = findfilesbyregexp(sourceMaskDirs,
                          nSourceMaskDirs,
                          ".*\\.png",
                          &sourceMaskFilenames,
                          &nSourceMaskFilenames,
                          &sourceMaskFilenamesBuffer);
  if (err)
    goto failure;

  if (nSourceMaskFilenames <= 0 || nSourceMaskFilenames > MAX_FILENAMES)
  {
    err = result_TOO_BIG;
    goto failure;
  }

  for (i = 0; i < nSourceMaskFilenames; i++)
    pixels[i] = NULL;

  err = motionmaskmaker_create(&maker);
  if (err)
    goto failure;

  for (i = 0; i < nSourceMaskFilenames; i++)
  {
    logf_info("sourcing mask %d from %s", i, sourceMaskFilenames[i]);

    makerSource[i] = createCGImageFromPNGFile(sourceMaskFilenames[i]);

    bitmapInfo = CGImageGetBitmapInfo(makerSource[i]);
    pixelfmt = bitmapInfoToPixelfmt(bitmapInfo);
    if (pixelfmt == pixelfmt_unknown)
    {
      logf_error("MMMaker_make: Unknown pixelfmt.");
      return result_BAD_ARG;
    }

    // bodge pixelfmt to be something we can currently cope with

    if (pixelfmt == pixelfmt_rgba8888)
      pixelfmt = pixelfmt_rgbx8888;
    if (pixelfmt == pixelfmt_abgr8888)
      pixelfmt = pixelfmt_xbgr8888;

    // turn the image into greyscale if it's anything else

    if (pixelfmt != pixelfmt_y8)
    {
      CGImageRef greyCopy;

      greyCopy = BitmapTransform_createGreyscaleCopy(makerSource[i]);

      CGImageRelease(makerSource[i]);

      makerSource[i] = greyCopy;

      bitmapInfo = CGImageGetBitmapInfo(makerSource[i]);
      pixelfmt = bitmapInfoToPixelfmt(bitmapInfo);
      if (pixelfmt == pixelfmt_unknown)
        return result_BAD_ARG;
    }

    pixels[i] = copyImagePixels(makerSource[i]);
    if (pixels[i] == NULL)
      goto failure;

    makerBitmapBases[i] = (void *) CFDataGetBytePtr(pixels[i]);
  }

  makerBitmaps.width    = (int) CGImageGetWidth(makerSource[0]);
  makerBitmaps.height   = (int) CGImageGetHeight(makerSource[0]);
  makerBitmaps.format   = pixelfmt;
  makerBitmaps.rowbytes = (int) CGImageGetBytesPerRow(makerSource[0]);
  makerBitmaps.nbases   = nSourceMaskFilenames;
  makerBitmaps.bases    = makerBitmapBases;

  err = motionmaskmaker_pack(maker, &makerBitmaps);
  if (err)
    goto failure;

  err = motionmaskmaker_save(maker, filename);
  if (err)
    goto failure;

  /* cleanup */

failure:

  for (i = 0; i < nSourceMaskFilenames; i++)
    if (pixels[i])
      CFRelease(pixels[i]);

  motionmaskmaker_destroy(maker);
  maker = NULL;

  free(sourceMaskFilenamesBuffer);
  free(sourceMaskFilenames);

  return err;
}