Extension for creating transparent spritesheets (RGBA) from two JPG files

Forums Programming cocos2d 3rd party extensions Extension for creating transparent spritesheets (RGBA) from two JPG files

This topic contains 12 replies, has 5 voices, and was last updated by  Kidstamatic 2 years ago.

Viewing 13 posts - 1 through 13 (of 13 total)
Author Posts
Author Posts
March 12, 2012 at 3:44 pm #239872

Kidstamatic
@sergscout

Hi!

While updating my game graphics for retina iPad, I was deeply stressed with the HUGE file sizes for RGBA PNG’s needed for new screen. So I wrote an extension which helps you shrink down the needed space by using two JPG – one with spritesheet image and one with alpha channel – to create transparent sprite frames on the fly.

It’s an category extending CCSpriteFrameCache.

Usage:

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName;

-plist is the name of a usial plist file for spritesheet – say, from TexturePacker.

-textureFileName is the name of jpg (or any other format supported by UIImage) file with spritesheet RGB picture (no alpha)

-maskFileName is thename of jpg (or any other format supported by UIImage) file with spritesheet alpha.

Mask uses black for fully transperent areas and white for fully opaque – not the usial CGImageMask behaviour, but I use this as TexturePacker produces alpha images in this format.

So how to prepare sprite sheet (using TexturePacker):

1) Combine all your sprites as usial. Make sure to turn off “Crop” or “Trim”, or TP may create different layouts for RGB and alpha images.

2) Select “Texture format – JPG”, “Image format – RGBA8888″, enter the names for plist file and texture file, set JPEG compression options in “Advanced” panel and publish the spritesheet.

3) Now select “Image format – Alpha”, alter the name for texture mask file (I suppose just adding “Mask”) and publish again.

So you’ll have three file: spriteSheet.plist, texture.jpg and textureMask.jpg. Add them to xCode and use the following in your init:

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"spriteSheet.plist" textureFile:@"texture.jpg" maskFile:@"textureMask.jpg"];

And then just create your sprites from frames as usial. Profit! :)

The new spritesheet texture is given the “<textureFileName>_maskedBy_<maskFileName>” key in sharedTextureCache.

For me, it saved a few megabytes of space.

I didn’t do any speed test, so if somebody have a bit of time – try to measure time for loading spritesheet into cache from usial RGBA8888 PNG and from identical JPG pack.

Here is the code:

CCSpriteFrameCacheExtentions.h :

/*
* Created by SergScout.
* Copyright (c) 2012 Kidstamatic. All rights reserved.
*
* It uses code from http://iphonedevelopertips.com/cocoa/how-to-mask-an-image.html
* and http://pastie.org/418627
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#import "CCSpriteFrameCache.h"

@interface CCSpriteFrameCache (SSKExtentions)
-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName;
@end

CCSpriteFrameCacheExtentions.m

/*
* Created by SergScout on 11.03.12.
* Copyright (c) 2012 Kidstamatic. All rights reserved.
*
* It uses code from http://iphonedevelopertips.com/cocoa/how-to-mask-an-image.html
* and http://pastie.org/418627
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#import "CCSpriteFrameCacheExtentions.h"

@implementation CCSpriteFrameCache (SSKExtentions)

CGImageRef CopyImageAndAddAlphaChannel(CGImageRef sourceImage) {
CGImageRef retVal = NULL;

size_t width = CGImageGetWidth(sourceImage);
size_t height = CGImageGetHeight(sourceImage);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height,
8, 0, colorSpace, kCGImageAlphaPremultipliedFirst);

if (offscreenContext != NULL) {
CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), sourceImage);

retVal = CGBitmapContextCreateImage(offscreenContext);
CGContextRelease(offscreenContext);
}

CGColorSpaceRelease(colorSpace);

return retVal;
}

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName
{
NSAssert( textureFileName, @"Invalid texture file name");
NSAssert( maskFileName, @"Invalid mask file name");
NSString *texturePath = [CCFileUtils fullPathFromRelativePath:textureFileName];
NSString *maskPath = [CCFileUtils fullPathFromRelativePath:maskFileName];

UIImage *textureImage = [UIImage imageWithContentsOfFile:texturePath];
UIImage *maskImage = [UIImage imageWithContentsOfFile:maskPath];

CGImageRef maskRef = maskImage.CGImage;

CGFloat decode[2] = {1 , 0}; //Use it to invert alpha mask got from texturePacker.

CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), decode, false); //if you don'n need to invert mask, pass NULL instead of decode

CGImageRef sourceImage = textureImage.CGImage;
CGImageRef imageWithAlpha = sourceImage;
//add alpha channel for images that don't have one (ie GIF, JPEG, etc...)
//this however has a computational cost
if ((CGImageGetAlphaInfo(sourceImage) == kCGImageAlphaNone)
|| (CGImageGetAlphaInfo(sourceImage) == kCGImageAlphaNoneSkipFirst)
|| (CGImageGetAlphaInfo(sourceImage) == kCGImageAlphaNoneSkipLast))
{
imageWithAlpha = CopyImageAndAddAlphaChannel(sourceImage);
}

CGImageRef masked = CGImageCreateWithMask(imageWithAlpha, mask);
CGImageRelease(mask);

//release imageWithAlpha if it was created by CopyImageAndAddAlphaChannel
if (sourceImage != imageWithAlpha) {
CGImageRelease(imageWithAlpha);
}

CCTexture2D *maskedTexture = CCTextureCache sharedTextureCache] addCGImage:masked forKey:[NSString stringWithFormat:@"%@_maskedBy_%@", textureFileName, maskFileName;

CGImageRelease(masked);

[self addSpriteFramesWithFile:plist texture:maskedTexture];
}

@end

P.S. BTW, how can I change my userpic here?

March 13, 2012 at 1:07 pm #368559

Stepan Generalov
Moderator
@ipsi

If you want to change userpic on this forum – you need to set one on gravatar for same e-mail, as you registered here. gravatar.com

I think that ability to use JPGs with aditional file for alpha channel can be very usefull to make smaller distributions.

What restrictions does your code have? What versions of cocos2d are supported, iOS/Mac versions?

Could you fork an extensions repo & provide a pull request from feature branch to develop with this extension & sample?

March 13, 2012 at 1:28 pm #368560

Kidstamatic
@sergscout

Well, I should check out the restrictions and find out how to do all the stuff you wrote :), as i never used github before. For the moment this extension works on cocos2d v1.0.1 iOS. As it doesn’t use any specific calls, I think it will work with any cocos for iOs version which have -fullPathFromRelativePath and -addSpriteFramesWithFile: texture:

methods implemented. I’m not sure about Mac version.

March 15, 2012 at 6:59 pm #368561

Kidstamatic
@sergscout

Some filesize and time profiling information for this extention.

I use 3 spritesheets: one for Retina iPad, one for iPad and Retina iPhone and one for non-Retina iPhone.

File sizes for RGBA8888 PNG and texture+mask jpg pack:

/*****************************************************************************/
- iPhone:
/*****************************************************************************/
PNG : 1 110 016 bytes
2*JPG : 248 372 bytes

Load time on iPhone 4, 62 sprite frames:
PNG : 796.0ms
2*JPG : 1247.0ms

/*****************************************************************************/
- iPhone Retina:
/*****************************************************************************/
PNG : 4 960 256 bytes
2*JPG : 853 960 bytes

Load time on iPhone 4, 70 sprite frames:
PNG : 819.0ms
2*JPG : 1371.0ms

/*****************************************************************************/
- iPad
/*****************************************************************************/
PNG : 4 960 256 bytes
2*JPG : 853 960 bytes

Load time on iPad, 70 sprite frames:
PNG : 669.0ms
2*JPG : 1081.0ms

Load time on iPad 2, 70 sprite frames:
PNG : 535.0ms
2*JPG : 777.0ms

/*****************************************************************************/
- iPad Retina
/*****************************************************************************/
PNG :17 821 714 bytes
2*JPG : 1 961 765 bytes

Load time on iPad 2 (!), 70 sprite frames:
PNG : 2032.0ms
2*JPG : 2616.0ms

I think it could be further optimized, as two most time-hungry operations are -[CCTextureCache addCGImage:forKey:] (approx. 75%) and -CopyImageAndAddAlphaChannel (approx. 20%). If anybody have good ideas about optimizing it – welcome.

March 15, 2012 at 9:20 pm #368562

Panajev
Participant
@panajev

Nice idea :).

March 16, 2012 at 12:17 pm #368563

Kidstamatic
@sergscout

I totally rewrote the implementation. Now it’s approx. 25% quicker.

It’s compatible with Cocos2d 1.1 for both iOS and MacOS (untested! but should work, as the Mac-oriented code copied from CCtextureCache).

Now it DOESN’T add masked texture to sharedTextureCache. If you need to create a Batch Node with texture, get it from your sprite. But if someone need this to be added -just ask.

I also added method

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName maskInverted:(BOOL)isMaskInverted;

By setting maskInverted: you can explicitely define whether to invert mask. Method

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName

uses it with isMaskInverted = YES to automatically invert mask created by TexturePacker.

/*****************************************************************************/

Here is some explanaition about masks:

1) If you supply grayscale image for the mask, it’s never converted. In this case mask uses black for fully transperent areas and white for fully opaque.

2) But! If you create alpha jpg from TexturePacker, it will save it as RGB, not Grayscale, JPG. This also possible with come other image creation software. If the supplied mask is in any but Grayscale mode, it has to be converted to CGImageMask. And CGImageMask behaves quite opposite – it uses white for fully transparent areas and black for fully opaque.

3) So…

- If you just save a mask from TexturePacker, it will be in RGB. Then use

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName

- If you have a grayscale mask (say, you converted TP mask into grayscale mode), also use

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName

- If you have RGB mask and want to use white for transparent areas and black for opaque (I don’t know for what reason, but maybe you have one), use

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName maskInverted:NO;

/*****************************************************************************/

And some more about TexturePacker. You should uncheck “Crop”, “Trim” and “Enable auto alias” to get matching RGB and alpha images. I’ll ask TP author to add convenient method for saving pairs of RGB+alpha JPGs, but for the moment use this algorythm or export transparent PNG and take it apart yourself.

Oh, I almost forgot the code!

CCSpriteFrameCacheExtentions.h :

/*
* Created by SergScout on 11.03.12.
* Copyright (c) 2012 Kidstamatic. All rights reserved.
*
* It uses ideas from http://iphonedevelopertips.com/cocoa/how-to-mask-an-image.html
* and http://pastie.org/418627
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import "CCSpriteFrameCache.h"

@interface CCSpriteFrameCache (SSKExtentions)
-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName;

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName maskInverted:(BOOL)isMaskInverted;

@end

CCSpriteFrameCacheExtentions.m :

/*
* Created by SergScout on 11.03.12.
* Copyright (c) 2012 Kidstamatic. All rights reserved.
*
* It uses ideas from http://iphonedevelopertips.com/cocoa/how-to-mask-an-image.html
* and http://pastie.org/418627
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#import "CCSpriteFrameCacheExtentions.h"

@implementation CCTexture2D (SSKExtentions)
/***********************************************************/
// - setHasPremultipliedAlpha:
/***********************************************************/
- (void)setHasPremultipliedAlpha:(BOOL)flag
{
if (hasPremultipliedAlpha_ != flag)
{
hasPremultipliedAlpha_ = flag;
}
}

/***********************************************************/
// - setResolutionType:
/***********************************************************/
- (void)setResolutionType:(ccResolutionType)aResolutionType
{
if (resolutionType_ != aResolutionType)
{
resolutionType_ = aResolutionType;
}
}

@end

@implementation CCSpriteFrameCache (SSKExtentions)

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName
{
[self addSpriteFramesWithFile:plist textureFile:textureFileName maskFile:maskFileName maskInverted:YES];
}

-(void) addSpriteFramesWithFile:(NSString*)plist textureFile:(NSString*)textureFileName maskFile:(NSString*)maskFileName maskInverted:(BOOL)isMaskInverted;
{
NSAssert( plist, @"Invalid plist file name");
NSAssert( textureFileName, @"Invalid texture file name");
NSAssert( maskFileName, @"Invalid mask file name");

NSUInteger POTWide, POTHigh;
CGImageRef mask = nil;
void* data = nil;
CGContextRef context = nil;
CCTexture2D* maskedTexture = nil;
ccResolutionType resolution = kCCResolutionUnknown;
CGFloat invertMask[2] = {1 , 0};

#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
NSString *texturePath = [CCFileUtils fullPathFromRelativePath:textureFileName resolutionType:&resolution];
NSString *maskPath = [CCFileUtils fullPathFromRelativePath:maskFileName];
UIImage *textureImage = [UIImage imageWithContentsOfFile:texturePath];
UIImage *maskImage = [UIImage imageWithContentsOfFile:maskPath];

#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
NSString *texturePath = [CCFileUtils fullPathFromRelativePath:textureFileName];
NSString *maskPath = [CCFileUtils fullPathFromRelativePath:maskFileName];

NSData *textureData = [NSData dataWithContentsOfFile:texturePath];
NSBitmapImageRep *textureImage = [NSBitmapImageRep imageWithData:textureData];
NSData *maskData = [NSData dataWithContentsOfFile:maskPath];
NSBitmapImageRep *maskImage = [NSBitmapImageRep imageWithData:maskData];

#endif

CGImageRef maskRef = maskImage.CGImage;
CGImageRef sourceImage = textureImage.CGImage;

CCConfiguration *conf = [CCConfiguration sharedConfiguration];
CGRect imageRect = CGRectMake(0, 0, CGImageGetWidth(sourceImage), CGImageGetHeight(sourceImage));

#if CC_TEXTURE_NPOT_SUPPORT
if( [conf supportsNPOT] ) {
POTWide = imageRect.size.width;
POTHigh = imageRect.size.height;
} else
#endif
{
POTWide = ccNextPOT(imageRect.size.width);
POTHigh = ccNextPOT(imageRect.size.height);
}

NSUInteger maxTextureSize = [conf maxTextureSize];
if( POTHigh > maxTextureSize || POTWide > maxTextureSize ) {
CCLOG(@"cocos2d: WARNING: Image (%lu x %lu) is bigger than the supported %ld x %ld",
(long)POTWide, (long)POTHigh,
(long)maxTextureSize, (long)maxTextureSize);
return;
}

CGColorSpaceRef colorSpace = CGImageGetColorSpace(maskRef);
CGColorSpaceRef deviceGray = CGColorSpaceCreateDeviceGray();

//creating Mask or using supplied image as a mask if it is in grayscale
if ((colorSpace != deviceGray) || !colorSpace)
{
//creating mask
if (isMaskInverted)
{
mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), invertMask, false);
}
else
{
mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
}
}
else
{
//using supplied mask
mask = maskRef;
}
CGColorSpaceRelease(deviceGray);

colorSpace = CGColorSpaceCreateDeviceRGB();
data = malloc(POTHigh * POTWide * 4);
CGRect contextRect = CGRectMake(0,0, POTWide, POTHigh);
context = CGBitmapContextCreate(data,
POTWide, POTHigh, 8,4 * POTWide,
colorSpace, kCGImageAlphaPremultipliedLast);

if (context != NULL) {
CGContextClearRect(context, contextRect);
CGContextTranslateCTM(context, 0, POTHigh - imageRect.size.height);
CGContextClipToMask(context, imageRect, mask);
CGContextDrawImage(context, imageRect, sourceImage);
}

maskedTexture = [[CCTexture2D alloc] initWithData:data pixelFormat:kCCTexture2DPixelFormat_RGBA8888 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:imageRect.size];
maskedTexture.hasPremultipliedAlpha = YES;
maskedTexture.resolutionType = resolution;

CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(data);

[self addSpriteFramesWithFile:plist texture:maskedTexture];
[maskedTexture release];

if (mask != maskRef)
{
CGImageRelease(mask);
}

}

@end

And sorry guys – I have totally no time for creating samples or putting it to github now. So if you like it – just use as is. “But maybe someday…”

March 17, 2012 at 12:14 am #368564

Kidstamatic
@sergscout

Just made some time-profiling tests.

Loading really HUGE spritesheet – 3600×4000 px.

- from RGBA8888 PNG – 2 061 ms (file size 19 181 568 bytes)

- from RGB+Alpha JPG by my extension – 2 548 ms (summary file sizes are 3 223 552 bytes)

- finally, from RGB+Alpha JPG by using CCRenderTexture as in CCMask (http://www.cocos2d-iphone.org/forum/topic/15890)

…drums….

21 155 ms!

My extension is 8 times faster!

That inspires.

I think about some more masking extensions – say, for creating masked sprites just from two files, for color masking and for clipping paths. Stay tuned!

March 17, 2012 at 12:26 am #368565

riq
Keymaster
@admin

it looks promising.

March 20, 2012 at 10:38 am #368566

Kidstamatic
@sergscout

Color masking is also working, but has some issues. Will solve them in a while.

_______________________________________________________________________________

- For more information, follow me: http://twitter.com/KidstamaticApps

March 22, 2012 at 1:42 am #368567

Kidstamatic
@sergscout

Well, finally I crafted methods for creating sprites from vector. Any size, any scale, no jagged edges, small file sizes. Just save any graphics to PDF and go.

I time-profiled loading and rendering of full-screen iPad2 sprite from PDF picture and from PNG saved from this PDF.

PNG size after optimization was 106 496 bytes, PDF with object compression – 122 880 bytes, without compression – 245 760 bytes.

Load time:

PNG – 77ms

PDF – 25-27 ms!

There still a lot of work to do, but i hope to finish extensions for masking sprites and using vector sprites in a few weeks (actually, I have a lot of other work to do). Hope you need it as I do :)

_______________________________________________________________________________

- For more information, follow me: http://twitter.com/KidstamaticApps

March 22, 2012 at 1:53 am #368568

Kidstamatic
@sergscout
April 23, 2012 at 5:13 pm #368569

TechnologySolutionsGroup
@technologysolutionsgroup

Have you had any further work on this?

April 23, 2012 at 6:04 pm #368570

Kidstamatic
@sergscout

Yes, I’ve been working hard on this.

For the moment I have implemented the following:

Masking:

1) Masking picture with picture. There is main method as extension if CCtexture2d and many wrappers for other classes (i.e., for creating spritesheets with two pictures and plist, for creating sprites and spriteframes, etc.)

2) Masking color from picture. You can specify array of colors to make them transparent or to leave only them and to make all other colors transparent

3) Feathering frame of a sprite – an edge of sprite rectangle is dissolved to transparent for a given radius.

vector:

1) Creating sprites from pdf. You can select a page in multipage pdf, select an area of the page to render to sprite, select scale, etc – very many settings.

2) Creating spritesheets from multipage pdf (one page – one sprite). You get one texture with all sprites packed into it. This helps you combine both raster and vector graphics.

3) Creating spritesheets from picture and mask pdf (one picture for texture as in texturepacker and vector masks to cut it to sprites in pdf. One page – one mask)

4) And some other stuff…

A bit later I’m going to implement on-the-fly rendering of bitmap fonts from vector fonts, to create fully resolution-independent solution for cocos 2d.

now I’m testing all this stuff throughly and making a site with manuals and tutorials for it – http://kidstamatic.com/

You may follow me on Twitter to get the latest info.

And i transferred the discussion here:

http://www.cocos2d-iphone.org/forum/topic/30494/

_______________________________________________________________________________

- For more information, follow me: http://twitter.com/KidstamaticApps

Viewing 13 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic.