Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: libgfx - Image file format (PNG) with custom data  (Read 5179 times)

0 Members and 1 Guest are viewing this topic.

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
libgfx - Image file format (PNG) with custom data
« on: March 16, 2014, 10:08:53 pm »
A long time ago, I started a topic about custom information in the PNG file format, which can be useful to store sprite animation data and other stuff, so you don't need extra data files or your own, possibly quite poor graphics file format, just to get these extra data stored.

Finally, I am working on a library for my current project, that is able to read and even write PNG files with custom chunks, named libgfx. It can even be used for loading and writing PNG files without the need of SFML/sfml-graphics (e.g., if you write a low-overhead console application, that shall read/write PNG files), and it will also convert the pixels data to your need (e.g. to 32-bit RGBA, no matter if the file format is 24-bit RGB or palette). And if I remember well, SFML does not support PNG based on palettes (did it change already?).

Download Beta (0.1.0)
https://github.com/tenry92/libgfx

Download Alpha (obsolete)
Source Code + Linux Compiled: libgfx-source-unix.tar.gz
Source Code + Windows Compiled: libgfx-source-win32.zip

Issues
  • This is still beta and currently designed for my personal used. This means, only a selected set of color formats and bit depths are supported at the moment. This includes, that it DOES load png files with palettes, but gives you the pixels in pre-converted rgba values at the moment.
Example writing PNG file with custom chunk:

GfxImage gfx;
gfx.colorFormat = GfxFormat_RGBA;
gfx.bitDepth = 8;
gfx.width = ...; gfx.height = ...;
/* allocate the memory based on the specs given above */
libgfx_createImage(&img);
/* now you can set your data in gfx.pixels */

libgfx_createChunk(&gfx, "isPR");
GfxChunk *myChunk = gfx.userChunks[gfx.nUserChunks - 1];

int err = libgfx_writeGfxFile(&gfx, "output.png");

libgfx_destroyImage(&gfx);

Example reading PNG file with custom chunk:

GfxImage gfx;

/* no matter what the input format is, give me 8-bit RGBA */
gfx.colorFormat = GfxFormat_RGBA;
gfx.bitDepth = 8;

int err = libgfx_loadGfxFile(&gfx, "input.png");
if(err != GfxError_None) return 1; // error occurred

if(gfx.nUserChunks > 0)
{
  GfxChunk *myChunk = gfx.userChunks[0];
  /* do something with the user chunk... */
}

libgfx_destroyImage(&gfx);


EDIT: This is, how I currently use libgfx for loading my graphics into OpenGL, might be useful for you:

GfxImage img;

int ret = libgfx_loadGfxFile(&img, filename);
switch(ret)
{
  case GfxError_None: break;
  default: throw std::runtime_error("Unknown error loading " + filename);
  case GfxError_ColorFormat: case GfxError_BitDepth:
    throw std::runtime_error(filename + ": Color format not supported");
  case GfxError_File: throw std::runtime_error(filename + ": Not found");
  case GfxError_FileFormat: throw std::runtime_error(filename + ": Unknown format");
}

if(img.bitDepth != 8)
  throw std::runtime_error(filename + ": Color format not supported (8-bit rgba expected)");


/* OpenGL usually only supports dimensions like 128x64 or 256x256. */
int nearestWidth = exp2(ceil(log2(img.width)));
int nearestHeight = exp2(ceil(log2(img.height)));

tex->actualWidth = img.width;
tex->actualHeight = img.height;
tex->textureWidth = nearestWidth;
tex->textureHeight = nearestHeight;

/* We need to resize the image to fit OpenGL's requirements. */
if(img.width < nearestWidth || img.height < nearestHeight)
{
  /* resize actual texture. note: pixels out of bounds may have random data */
  std::vector<uint8_t> pixels;
  pixels.resize(nearestWidth * nearestHeight * 4);
 
  for(int y = 0; y < img.height; ++y)
  {
    memcpy(&pixels[y * nearestWidth * 4], &img.pixels[y * img.width * 4],
      img.width * 4);
  }
 
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nearestWidth, nearestHeight,
    0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
}
/* The image's dimensions already fit the requirements, pass it already. */
else
{
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nearestWidth, nearestHeight,
    0, GL_RGBA, GL_UNSIGNED_BYTE, img.pixels);
}
« Last Edit: October 07, 2015, 08:27:39 pm by Tenry »
Please note that my previous display name was "Shy Guy".

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
libgfx Alpha released!
« Reply #1 on: April 02, 2014, 05:36:23 pm »
libgfx 0.0.1 (Alpha) released!

Linux (with source code): libgfx-source-unix.tar.gz
Windows (with source code): libgfx-source-win32.zip
Please note that my previous display name was "Shy Guy".

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Re: libgfx - Image file format (PNG) with custom data
« Reply #2 on: October 06, 2015, 10:15:14 pm »
libgfx 0.0.1 (Beta) released on github!

There have been minor changes and bugfixes in my library and I started using git and publishing it on github. I forgot to increase the version number, but as it is already working quite well in my projects, I consider it now being beta.

You can go to the github page and download the most recent version. It is currently designed to be compiled and installed on a unix or unix-like environment, i.e., it depends (by default) on /usr/local, pkg-config and pre-installed libpng.
Please note that my previous display name was "Shy Guy".

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: libgfx - Image file format (PNG) with custom data
« Reply #3 on: October 07, 2015, 10:01:38 am »
That looks interesting! It's surprising that existing PNG libraries don't handle metadata or at least not easily. The feature is probably too rarely used.

Your API uses a strong C style. Don't you want to write it in C directly? It seems like you're hardly using any C++ features anyway. Such low-level libraries are likely to become much more popular when written in C, as they can be used in C code and easily be invoked from other languages.

It would still be fairly trivial to write a C++ wrapper on top. But the current state is not ideal: C++ developers have to use a mix of C and C++ style interfaces, but C developers are not able to work with libgfx because it's written in C++.

By the way, isn't "libgfx" a rather generic name, especially since it doesn't express anything about PNG and metadata? I'd choose something more precise, also to make it easier to search and distinguish your library from other projects named the same.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Re: libgfx - Image file format (PNG) with custom data
« Reply #4 on: October 07, 2015, 06:35:26 pm »
Thank you for your feedback :)

It's surprising that existing PNG libraries don't handle metadata or at least not easily. The feature is probably too rarely used.
I'm not sure, if that, what my lib does, can be considered "handling metadata", as it does not handle the author, creation date, comments etc. yet. It only handles the actual image data and private chunks with arbitrary data in it, where you define its format yourself.

Your API uses a strong C style. Don't you want to write it in C directly? It seems like you're hardly using any C++ features anyway. Such low-level libraries are likely to become much more popular when written in C, as they can be used in C code and easily be invoked from other languages.

It would still be fairly trivial to write a C++ wrapper on top. But the current state is not ideal: C++ developers have to use a mix of C and C++ style interfaces, but C developers are not able to work with libgfx because it's written in C++.
I guess, when I started this library, I considered writing it as a pure C library, hence this overall design. Then I wanted to use std::vector for pixels, chunks etc., and you see what happened :D
After reading your response, I reconsidered it, and yeah, pure C would definitely better. So, I'm going to change the implementation a bit, so that it is really pure C then.

By the way, isn't "libgfx" a rather generic name, especially since it doesn't express anything about PNG and metadata? I'd choose something more precise, also to make it easier to search and distinguish your library from other projects named the same.
When developing games, I liked the idea of using my very own graphics format, that exactly fits the needs of my games, and I would have given it the file name extension ".gfx". But why making another graphics format, possibly with poor or no compression, if PNG is already good at it and even officially support private data (chunks), you can embed in your PNG file?
That's where the name comes from. You may even handle the file signature yourself, so I could replace the usual PNG signature with my very own one, disallowing others to open my graphics in an image program that easy :P
So, it could be possible that I will really use that feature of using my own signature and use the .gfx extension, so that not everybody immediately sees, that it's actually a PNG file.

Anyways, do you have an idea for another name? Maybe "metapng", but... as mentioned above, my library is not intended to handle "meta" data, but private chunks and the actual image data.
Please note that my previous display name was "Shy Guy".

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: libgfx - Image file format (PNG) with custom data
« Reply #5 on: October 07, 2015, 07:06:21 pm »
There are many sources talking about "metadata", but it seems like "chunks" is the official term [1] [2].

About names... Some ideas:
  • "png" + something along "chunk" or "meta"
  • "png" + adjective expressing the versatility or self-containedness
  • use cases in games... something along "attribute", "property", "trait", or better more specific ones
  • names (like I did with Thor). Just don't choose one that will be a movie in the future :P
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Re: libgfx - Image file format (PNG) with custom data
« Reply #6 on: October 07, 2015, 08:19:20 pm »
There are many sources talking about "metadata", but it seems like "chunks" is the official term [1] [2].

About names... Some ideas:
  • "png" + something along "chunk" or "meta"
  • "png" + adjective expressing the versatility or self-containedness
  • use cases in games... something along "attribute", "property", "trait", or better more specific ones
  • names (like I did with Thor). Just don't choose one that will be a movie in the future :P
Thanks for these ideas, I might think about it later.

It's fully ported to C now and my existing project (after minor updates) still loads my png files successfully :)
Please note that my previous display name was "Shy Guy".