MULTIMEDIA

iPhone 3D Programming : Textures and Image Capture - Generating and Transforming OpenGL Textures with Quartz

2/8/2011 4:10:07 PM
You can use Quartz to draw 2D paths into an OpenGL texture, resize the source image, convert from one format to another, and even generate text.

One way of loading textures into OpenGL is creating a Quartz surface using whatever format you’d like and then drawing the source image to it, as shown in Example 1.

Example 1. Texture loading with CGContextDrawImage
TextureDescription LoadImage(const string& file)
{
NSString* basePath = [NSString stringWithUTF8String:file.c_str()];
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
NSString* fullPath =
[resourcePath stringByAppendingPathComponent:basePath];
UIImage* uiImage = [UIImage imageWithContentsOfFile:fullPath];

TextureDescription description;
description.Size.x = CGImageGetWidth(uiImage.CGImage);
description.Size.y = CGImageGetHeight(uiImage.CGImage);
description.BitsPerComponent = 8;
description.Format = TextureFormatRgba;
description.MipCount = 1;
m_hasPvrHeader = false;

int bpp = description.BitsPerComponent / 2;
int byteCount = description.Size.x * description.Size.y * bpp;
unsigned char* data = (unsigned char*) calloc(byteCount, 1);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo =
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
CGContextRef context = CGBitmapContextCreate(data,
description.Size.x,
description.Size.y,
description.BitsPerComponent,
bpp * description.Size.x,
colorSpace,
bitmapInfo);
CGColorSpaceRelease(colorSpace);
CGRect rect = CGRectMake(0, 0, description.Size.x, description.Size.y);
CGContextDrawImage(context, rect, uiImage.CGImage);
CGContextRelease(context);

m_imageData = [NSData dataWithBytesNoCopy:data
length:byteCount
freeWhenDone:YES];
return description;
}

If you want to try the Quartz-loading code in the sample app, perform the following steps:

  1. Add Example 1 to ResourceManager.mm.

  2. Add the following method declaration to IResourceManager in Interfaces.hpp:

    virtual TextureDescription LoadImage(const string& file) = 0;

  3. In the SetPngTexture method in RenderingEngine.TexturedES2.cpp, change the LoadPngImage call to LoadImage.

  4. In your render engine’s Initialize method, make sure your minification filter is GL_LINEAR and that you’re calling SetPngTexture.

One advantage of loading images with Quartz is that you can have it do some transformations before uploading the image to OpenGL. For example, say you want to flip the image vertically. You could do so by simply adding the following two lines immediately before the line that calls CGContextDrawImage:

CGContextTranslateCTM(context, 0, description.Size.y);
CGContextScaleCTM(context, 1, -1);

Another neat thing you can do with Quartz is generate new images from scratch in real time. This can shrink your application, making it faster to download. This is particularly important if you’re trying to trim down to less than 10MB, the maximum size that Apple allows for downloading over the 3G network. Of course, you can do this only for textures that contain simple vector-based images, as opposed to truly artistic content.

For example, you could use Quartz to generate a 256×256 texture that contains a blue filled-in circle, as in Example 2. The code for creating the surface should look familiar; lines of interest are shown in bold.

Example 2. ResourceManager::GenerateCircle()
TextureDescription GenerateCircle()
{
TextureDescription description;
description.Size = ivec2(256, 256);
description.BitsPerComponent = 8;
description.Format = TextureFormatRgba;

int bpp = description.BitsPerComponent / 2;
int byteCount = description.Size.x * description.Size.y * bpp;
unsigned char* data = (unsigned char*) calloc(byteCount, 1);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
CGContextRef context = CGBitmapContextCreate(data,
description.Size.x,
description.Size.y,
description.BitsPerComponent,
bpp * description.Size.x,
colorSpace,
bitmapInfo);
CGColorSpaceRelease(colorSpace);

CGRect rect = CGRectMake(5, 5, 246, 246);
CGContextSetRGBFillColor(context, 0, 0, 1, 1);
CGContextFillEllipseInRect(context, rect);

CGContextRelease(context);

m_imageData = [NSData dataWithBytesNoCopy:data length:byteCount freeWhenDone:YES];
return description;
}

If you want to try the circle-generation code in the sample app, perform the following steps:

  1. Add Example 2 to ResourceManager.mm.

  2. Add the following method declaration to IResourceManager in Interfaces.hpp:

    virtual TextureDescription GenerateCircle() = 0;

  3. In the SetPngTexture method in RenderingEngine.TexturedES2.cpp, change the LoadImage call to GenerateCircle.

  4. In your render engine’s Initialize method, make sure your minification filter is GL_LINEAR and that you’re calling SetPngTexture.

Quartz is a rich 2D graphics API and could have a book all to itself, so I can’t cover it here; check out Apple’s online documentation for more information.

Other  
  •  iPhone 3D Programming : Textures and Image Capture - The PowerVR SDK and Low-Precision Textures
  •  Building LOB Applications : Using Visual Studio 2010 WCF Data Services Tooling
  •  Building LOB Applications : Accessing RESTful Data using OData
  •  Programming with DirectX : Additional Texture Mapping - Image Filters
  •  Microsoft XNA Game Studio 3.0 : Making a Game Program
  •  iPhone 3D Programming : Textures and Image Capture - Texture Compression with PVRTC
  •  iPhone 3D Programming : Textures and Image Capture - Texture Formats and Types
  •  iPhone 3D Programming : Textures and Image Capture - Fight Aliasing with Filtering
  •  iPhone 3D Programming : Textures and Image Capture - Texture Coordinates Revisited
  •  Programming with DirectX : Additional Texture Mapping - Sprites
  •  Programming with DirectX : Additional Texture Mapping - Alpha Mapping
  •  Microsoft XNA Game Studio 3.0 : Writing Your First Program (part 2) - Running the Same XNA Game on Different Devices
  •  Microsoft XNA Game Studio 3.0 : Writing Your First Program (part 1)
  •  Programming with DirectX : Shading and Surfaces - Additional Texturing Topics
  •  iPhone 3D Programming : Adding Textures to ModelViewer (part 4) - Enabling Textures with ES2::RenderingEngine
  •  iPhone 3D Programming : Adding Textures to ModelViewer (part 3) - Enabling Textures with ES1::RenderingEngine
  •  iPhone 3D Programming : Adding Textures to ModelViewer (part 2) - Generating Texture Coordinates
  •  iPhone 3D Programming : Adding Textures to ModelViewer (part 1) - Enhancing IResourceManager
  •  Programming with DirectX : Shading and Surfaces - Implementing Texture Mapping (part 2) - Multi Texture Demo
  •  Programming with DirectX : Shading and Surfaces - Implementing Texture Mapping (part 1) - 2D Texture Mapping Demo
  •  
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)