PNG repair tools?
-
Graf Zahl
- Lead GZDoom+Raze Developer

- Posts: 49252
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
PNG repair tools?
I have an annoying problem on my hand.
One tool I used at work was creating incorrect PNGs, it stores the transparency information before the palette, although the spec wants it after the palette.
For most software we are using this doesn't matter, it can just read them as it is. That's why we never noticed that something was wrong.
But today I had to read them into an older wxWidgets based application and wxWidgets, shitty as it is, not only performs a validation but also opens a MESSAGE BOX(!!!) each time one of these files gets opened making the application unusable because it's impossible to get it out of the loading code, I'd have to click away that stupid box for each single image.
I've been looking for a tool to fix this issue but no luck so far. Most do not see anything wrong and those which do strip out all custom chunks, which in this case render the 'repaired' files unusable because the custom chunks contain critical info.
So my question: Does anyone here know if such a tool exists or do I have to write my own? It's several 1000 images that need to be fixed so this is not something to be done manually.
One tool I used at work was creating incorrect PNGs, it stores the transparency information before the palette, although the spec wants it after the palette.
For most software we are using this doesn't matter, it can just read them as it is. That's why we never noticed that something was wrong.
But today I had to read them into an older wxWidgets based application and wxWidgets, shitty as it is, not only performs a validation but also opens a MESSAGE BOX(!!!) each time one of these files gets opened making the application unusable because it's impossible to get it out of the loading code, I'd have to click away that stupid box for each single image.
I've been looking for a tool to fix this issue but no luck so far. Most do not see anything wrong and those which do strip out all custom chunks, which in this case render the 'repaired' files unusable because the custom chunks contain critical info.
So my question: Does anyone here know if such a tool exists or do I have to write my own? It's several 1000 images that need to be fixed so this is not something to be done manually.
-
Caligari87
- Admin
- Posts: 6248
- Joined: Thu Feb 26, 2004 3:02 pm
- Preferred Pronouns: He/Him
Re: PNG repair tools?
Not sure if you've tried something like this already, but just a thought... Imagemagick includes a tool called mogrify that can easily batch-convert images. Perhaps you could you batch-convert them to transparent TIFF then back to PNG?
EDIT: Nevermind, that'll probably strip the custom chunks.
EDIT: Imagemagick actually does have a special option just for preserving or excluding PNG chunks: http://www.imagemagick.org/script/comma ... php#define dunno if that's helpful or not. Perhaps batch-converting the PNGs to new filenames then back to the old filenames while using the preservation option will do the trick?

EDIT: Nevermind, that'll probably strip the custom chunks.
EDIT: Imagemagick actually does have a special option just for preserving or excluding PNG chunks: http://www.imagemagick.org/script/comma ... php#define dunno if that's helpful or not. Perhaps batch-converting the PNGs to new filenames then back to the old filenames while using the preservation option will do the trick?
Last edited by Caligari87 on Thu Nov 10, 2016 2:30 pm, edited 1 time in total.
-
Graf Zahl
- Lead GZDoom+Raze Developer

- Posts: 49252
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: PNG repair tools?
No. I said they contain custom chunks. Mogrify destroys all of them. It also recompresses the image.
-
Rachael
- Posts: 13978
- Joined: Tue Jan 13, 2004 1:31 pm
- Preferred Pronouns: She/Her
Re: PNG repair tools?
Have you tried pngout? It basically rewrites PNG files. You can use the /k option to keep custom chunks and /f to force it even if the resulting file will be bigger.
You can use /s3 to do a standard-deflate compression, which is faster than Ken's custom super-deflate.
I don't know if that will help you, but it's worth a shot.
Also you can batch it in cmd.exe using this command:
You can use /s3 to do a standard-deflate compression, which is faster than Ken's custom super-deflate.
I don't know if that will help you, but it's worth a shot.
Also you can batch it in cmd.exe using this command:
Code: Select all
for %I in (*.png) do @pngout /k /s3 /f %I-
Tapwave
- Posts: 2096
- Joined: Sat Aug 20, 2011 8:54 am
- Preferred Pronouns: No Preference
- Graphics Processor: nVidia with Vulkan support
Re: PNG repair tools?
Probably a stupid answer, but. Does the tool you use allows saving in different formats? You could save it in something sufficiently loseless, then open it with another tool that saves png properly and convert it that way. But I understand you'd like to avoid conversion cycling as much as possible.
-
Caligari87
- Admin
- Posts: 6248
- Joined: Thu Feb 26, 2004 3:02 pm
- Preferred Pronouns: He/Him
Re: PNG repair tools?
@Graf: Dunno if you saw my edit, but imagemagick does have an option to preserve chunks and fiddle with compression settings, which mogrify should recognize. http://www.imagemagick.org/script/comma ... php#define Does that help at all?
Just throwing ideas.

Just throwing ideas.
-
Gez
-

- Posts: 17946
- Joined: Fri Jul 06, 2007 3:22 pm
Re: PNG repair tools?
The problem is preserving the custom chunks, something exceedingly few programs do despite the specs asking them to.Tapwave wrote:Probably a stupid answer, but. Does the tool you use allows saving in different formats? You could save it in something sufficiently loseless, then open it with another tool that saves png properly and convert it that way. But I understand you'd like to avoid conversion cycling as much as possible.
-
Graf Zahl
- Lead GZDoom+Raze Developer

- Posts: 49252
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: PNG repair tools?
Tapwave wrote:Probably a stupid answer, but. Does the tool you use allows saving in different formats? You could save it in something sufficiently loseless, then open it with another tool that saves png properly and convert it that way. But I understand you'd like to avoid conversion cycling as much as possible.
The tool is fixed now. But all the images we created over the last 6 months need to be corrected, too. Going back to the sources would cost even more time.
-
Graf Zahl
- Lead GZDoom+Raze Developer

- Posts: 49252
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: PNG repair tools?
Caligari87 wrote:@Graf: Dunno if you saw my edit, but imagemagick does have an option to preserve chunks and fiddle with compression settings, which mogrify should recognize. http://www.imagemagick.org/script/comma ... php#define Does that help at all?
Just throwing ideas.
Unfortunately, ImageMagick completely refuses to load the broken images.
Well, I think I have to write that thing myself. I already wasted several hours on this shit in which I could have done it myself. Grrrrr...
-
dpJudas
- Posts: 3177
- Joined: Sat May 28, 2016 1:01 pm
Re: PNG repair tools?
Code: Select all
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdint>
#include <stdlib.h>
struct PNGMagic { uint8_t magic[8]; };
struct PNGChunkStart { uint32_t size, uint32_t name; };
struct PNGChunkEnd { uint32_t crc; };
struct PNGChunk { PNGChunkStart start, std::vector<uint8_t> data; PNGChunkEnd end; };
#ifndef __BIG_ENDIAN__
#define MAKE_ID(a,b,c,d) ((uint32_t)((a)|((b)<<8)|((c)<<16)|((d)<<24)))
#else
#define MAKE_ID(a,b,c,d) ((uint32_t)((d)|((c)<<8)|((b)<<16)|((a)<<24)))
#endif
int main(int, char *args)
{
PNGMagic magic; std::vector<PNGChunk> chunks;
FILE *f = fopen(args[0], "rb");
fread(&magic, sizeof(PNGMagic), 1, f);
PNGChunk cur;
while (fread(&cur.start, sizeof(PNGChunkStart), 1, f) == 1)
{
uint32_t size = _byteswap_ulong(cur.start.size);
cur.data.resize(size);
fread(cur.data.data(), size, 1, f);
fread(&cur.end, sizeof(PNGChunkEnd), 1, f);
chunks.push_back(cur);
}
fclose(f);
auto itTrans = std::find(chunks.begin(), chunks.end(), [](PNGChunk &c) -> bool { return MAKE_ID('t', 'R', 'N', 'S') == c.name; });
auto itPal = std::find(chunks.begin(), chunks.end(), [](PNGChunk &c) -> bool { return MAKE_ID('P', 'L', 'T', 'E') == c.name; });
if (itTrans != chunks.end() && itPal != chunks.end()) std::swap(*itTrans, *itPal);
f = fopen(args[1], "wb");
fwrite(&magic, sizeof(PNGMagic), 1, f);
for (auto &chunk : chunks)
{
fwrite(&chunk.start, sizeof(PNGChunkStart), 1, f);
fwrite(chunk.data.data(), _byteswap_ulong(cur.start.size), 1, f);
fwrite(&chunk.end, sizeof(PNGChunkEnd), 1, f);
}
fclose(f);
}
-
Rachael
- Posts: 13978
- Joined: Tue Jan 13, 2004 1:31 pm
- Preferred Pronouns: She/Her
Re: PNG repair tools?
My cat has been killed many times thanks to your code.
She still has some of her 9 lives left, though...
-
dpJudas
- Posts: 3177
- Joined: Sat May 28, 2016 1:01 pm
Re: PNG repair tools?
Sorry about that. Did your PC burn down too? 
-
Rachael
- Posts: 13978
- Joined: Tue Jan 13, 2004 1:31 pm
- Preferred Pronouns: She/Her
Re: PNG repair tools?
No, just overheated a bit. 
-
Edward-san
- Posts: 1774
- Joined: Sat Oct 17, 2009 9:40 am
Re: PNG repair tools?
no checks for fopen possibly returning nullptr? Cat exterminator!dpJudas wrote:code snippet
-
Graf Zahl
- Lead GZDoom+Raze Developer

- Posts: 49252
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: PNG repair tools?
I already solved this yesterday by writing my own tool, after giving up on the shit the internet had to offer. It's truly amazing what bottom-feeding scum is trying to make some money off desperate people who trashed some data - and 90% of this stuff doesn't even work!
And my solution was quite similar to what dpJudas just posted. Read all image chunks, compare index of palette and trans, and if wrong swap them around and save the image back. Took me two hours to run this on all the affected images, though...
And my solution was quite similar to what dpJudas just posted. Read all image chunks, compare index of palette and trans, and if wrong swap them around and save the image back. Took me two hours to run this on all the affected images, though...