2

How can I accomplish this? A programmatic solution (Objective-c) is great, but even a non-progarmmatic one is good.

I have pixelmator -> But that doesn't give you the option. I can't seem to do it with Preview either.

I have tried googling, but haven't been able to find a solution so far. The only tool I have been able to use to do this is TexturePacker, but that creates a sprite sheet.

Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190
  • 1
    You are mixing apples and oranges. PNG is an archive format for images, RGB565 is a in-memory representation of raw images. Please explain what are you trying to do. – leonbloy Apr 12 '12 at 12:05
  • If you use texture packer, http://www.texturepacker.com/ , the tool allows you to specify a pixel format (RGB565). If you specify it as RGB565, the sprite sheet is much smaller than if you specify RGB8888. I am trying to do the same thing to individual images without using the texture packer tool. – Rahul Iyer Apr 13 '12 at 03:01
  • " the sprite sheet is much smaller " ... what's that? a saved PNG? PNG cannot pack RGB values as RGB565. If you convert a (in-memory) image to RGB565 and save it as PNG, it will be saved either as paletted or as RGB8 - which would be roughly equivalent to do a posterize on the original image – leonbloy Apr 13 '12 at 16:43
  • The sprite sheet is a png. I don't know how the compression works, or very much about the png format. I found a solution. See my answer if you are interested in texture packer or this solution. Thanks. – Rahul Iyer Apr 14 '12 at 08:40

5 Answers5

6

You can use libpng to convert the PNG image to three-byte (8:8:8) RGB. Then you can downsample to the 5:6:5 16-bit color values of RGB565. If r, g, and b are the respective 8-bit colors (stored in an unsigned char type), then the 16-bit RGB565 value is:

((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)

You can improve a tad on this by rounding instead of chopping, being careful to not overflow the values. You can also force the green value to be equal to the blue and red values when they are all equal in the original 8-bit values. Otherwise it is possible to have colors that were originally gray inadvertently take on color after conversion.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • 1
    Thanks Mark. I don't know how to do this downsampling :). Hence my question. I imagine someone else must have already done this, so I'm just looking for a programmatic way or tool. I don't want to roll my own. – Rahul Iyer Apr 13 '12 at 03:02
2

Create Bitmap Context with color RGB565 using Quartz, paint your PNG on this context, save this bitmap context to file.

Black Coder
  • 197
  • 1
  • 5
2

PNG does not support a RGB565 packing. You can always apply a posterize to the image (programatically or with ImageMagick or with any image editor), which amounts to discard the lower significant bits in each channel. When saving to PNG, you will still be saving 8 bits per channel (unless you use a palette), but even then you will get an appreciable reduction in size, because of the PNG compression.

A quick example: original:

enter image description here

after a simple posterize with 32 levels (equivalent to a RGB555) applied with XnView

enter image description here

The size goes from 89KB to 47KB, with a small quality loss. In case of synthetic images with gradients, the quality loss could be much more noticiable (banding).

leonbloy
  • 73,180
  • 20
  • 142
  • 190
  • Any chance someone can supply an ImageMagick command to implement what this post is saying? – mikemachado Jul 08 '14 at 23:53
  • See [-posterize](http://www.imagemagick.org/Usage/quantize/#posterize) and [-color](http://www.imagemagick.org/Usage/quantize/#colors) – leonbloy Jul 09 '14 at 00:14
2

I received this answer from the creator of texture packer:

you can do it from command line - see

http://www.texturepacker.com/uncategorized/batch-converting-images-to-pvr-or-pvr-ccz/

Just adjust the opt and set output to .png instead of pvr.ccz
Make sure that you do not overwrite your source images.
Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190
0

According to Wikipedia, which is always right, the only 16-bit PNG is a greyscale PNG. http://en.wikipedia.org/wiki/Portable_Network_Graphics

If you just add your 32-bit (alpha) or 24-bit (no alpha) PNG to your project as normal, and then set the texture format in Cocos2D, all should be fine. The code for that is:

[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB565];
Danyal Aytekin
  • 4,106
  • 3
  • 36
  • 44
  • There are also 1, 2, 4, 8 and 64-bit PNGs :) And also PNGs with a palette. – Sulthan Apr 12 '12 at 16:04
  • Thanks Danyal. I understand how to change the texture format in cocos2d, but I was trying to change the files themselves so I save space. When I used texture packer, the sprite sheets were much smaller when I saved them as RGB565. As I now need to shrink individual images, I was wondering if there is a way to do that besides texture packer. – Rahul Iyer Apr 13 '12 at 02:58
  • Hmm ok. I didn't know you could do that but I found out that apparently Paint.NET can do it. http://forums.getpaint.net/index.php?/topic/16747-rgb565-android-splash-screen-format/ – Danyal Aytekin Apr 13 '12 at 17:29