views:

2468

answers:

3

I am trying to apply some transformations on images using a CGContextRef. I am using CGContextTranslateCTM, CGContextScaleCTM and CGContextRotateCTM functions, but to keep things simple lets focus on just the first. I was wondering why the following code produces exactly the original image?! Am I missing something?

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef g = CGBitmapContextCreate((void*) pixelData, 
                         width, 
                         height, 
                         RGBA_8_BIT, 
                         bytesPerRow, 
                         colorSpace, 

                     kCGImageAlphaPremultipliedLast);

CGContextSetShouldAntialias(g, YES);

CGContextSetInterpolationQuality(g, kCGInterpolationHigh);

CGContextTranslateCTM( g,translateX, translateY );


CGImageRef tempImg  = CGBitmapContextCreateImage (g);
CGContextDrawImage( g, CGRectMake (0, 0, width, height), tempImg );
CGContextRelease(g);
CGColorSpaceRelease( colorSpace );

Also, after translating, how to draw another image over this one but with partial transparency (eg alpha = 0.5).

I searched alot but didn't find an answer, any help is appreciated... :)

Please note that I am creating the context from pixelData, and that tempImg is created after the translation. There is nothing wrong in the initialization, as the original image is being currently produced, but the issue is with the translation I suppose..

A: 

You have to call CGBitmapContextCreateImage() after you draw the image.

Then you can draw another image on top of the first one and call CGBitmapContextCreateImage() again to get the second image. You can set the alpha using CGContextSetAlpha(ctx, alphaValue);

Nikolai Ruhe
Please note that I am creating the context from pixelData, and that tempImg is created after the translation. There is nothing wrong in the initialization, as the original image is being currently produced, but the issue is with the translation I suppose..
Ah, I understand what you try to do now. You cannot modify what's in a context's buffer (or what's already been drawn) by using CGContextTranslateCTM. The context transformation is working only on what will be drawn afterwards. So if you want to transform the original image from your data you will have to draw it in a second context.
Nikolai Ruhe
+4  A: 

Hi Ann,

Transformations to the graphics state only affect subsequent drawing operations - they don't change the existing image data. If you want to apply transforms to an image, try something like this:

  1. Create an empty CGContext (on iPhone, use UIGraphicsBeginImageContext)
  2. Translate, scale, or rotate it's graphics state
  3. Draw existing image into it.
  4. Get image from new CGContext (on iPhone, use UIGraphicsGetImageFromCurrentImageContext)

When you perform step 3, the existing image is drawn into your new graphics context with the transformations applied. The trick here is that in order to apply the transformations, we have to actually draw something.

You can do some really cool things with transformations this way. You can draw half your image, apply some transforms, and draw some more.

Ben Gotow
You star! Your first sentence just cleared everything up for me, cheers :-)
Garry
+1  A: 

As noted in other answers, transformations only apply to subsequent drawing operations; they don't affect the pixel buffer you started with.

So you need a drawing operation. The solution is to create a CGImage; drawing that image is a drawing operation, so it will be subject to the current transformation matrix (CTM).

Step-by-step:

  1. Create the context with empty pixel data. (If you pass NULL for the buffers, Quartz should create them for you. That works on the Mac, anyway.)
  2. Create the image with the pixel data you want to draw transformed.
  3. Transform the CTM in the context.
  4. Draw the image.
Peter Hosey