0

I can't figure out what is wrong. When I try to write the PNG, I get an error: "Error during writing header".

Do I need to include something else? I took the .lib/.h files from here: http://www.eden.net.nz/7/20071024/

Edit: I finally managed to make this work.

The solution:

#pragma comment(lib, "zlib_s.lib") // must be before libpng!
#pragma comment(lib, "libpng_s.lib") // must be after zlib!

Weird, huh?

Here is the working code, it's a slightly modified version of: http://zarb.org/~gc/html/libpng.html
Future note: this must be compiled as C code!

#pragma comment(lib, "zlib_s.lib") // must be before libpng!
#pragma comment(lib, "libpng_s.lib") // must be after zlib!

#define PNG_DEBUG 0
#include "png.h"

int x, y;

int width, height;
png_byte color_type;
png_byte bit_depth;

png_structp png_ptr;
png_infop info_ptr;
int number_of_passes;
png_bytep *row_pointers;


char *save_png(char *savefile, void *data_in, int w, int h, int BPP){
    unsigned char *data = (unsigned char *)*data_in;
    int p = 0;
    FILE *fp;

    width = w;
    height = h;
    color_type = 2;
    bit_depth = 8;

    // create file 
    fp = fopen(savefile, "wb");
    if(!fp) return "[write_png_file] File %s could not be opened for writing";

    // initialize stuff 
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if(!png_ptr) return "[write_png_file] png_create_write_struct failed";

    info_ptr = png_create_info_struct(png_ptr);
    if(!info_ptr) return "[write_png_file] png_create_info_struct failed";
    if(setjmp(png_jmpbuf(png_ptr))) return "[write_png_file] Error during init_io";

    png_init_io(png_ptr, fp);
    // write header 
    if(setjmp(png_jmpbuf(png_ptr))) return "[write_png_file] Error during writing header";

    png_set_IHDR(
        png_ptr, info_ptr, width, height,
        bit_depth, color_type, PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
    );

    png_write_info(png_ptr, info_ptr);

    row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
    for(y = 0; y < height; y++){
        row_pointers[y] = (png_byte*)malloc(width*BPP);//png_get_rowbytes(png_ptr,info_ptr));
        for(x = 0; x < width; x++){
            row_pointers[y][x*BPP+0] = data[p++];
            row_pointers[y][x*BPP+1] = data[p++];
            row_pointers[y][x*BPP+2] = data[p++];
        }
    }
    // write bytes 
    if(setjmp(png_jmpbuf(png_ptr))) return "[write_png_file] Error during writing bytes";

    png_write_image(png_ptr, row_pointers);

    // end write 
    if(setjmp(png_jmpbuf(png_ptr))) return "[write_png_file] Error during end of write";

    png_write_end(png_ptr, NULL);

    // cleanup heap allocation 
    for(y = 0; y < height; y++){
        free(row_pointers[y]);
    }
    free(row_pointers);

    fclose(fp);

    return "0";
}
Rookie
  • 4,064
  • 6
  • 54
  • 86
  • 2
    You're writing plain C here, so you should compile it as C. *Never* use `setjmp`/`longjmp` or other C functions with side effects in C++ code. That's what the first warning is about. – Fabian Knorr Aug 21 '12 at 19:21
  • @trion, i see... is it anyhow possible to compile it as c++ code ? – Rookie Aug 21 '12 at 19:44
  • @trion, i get thousand of absurd errors when i try to compile it as .c file. Is it even possible to compile c files in a c++ project (i couldnt see a .c file add option, so i just renamed .cpp to .c)? and i get weird errors, such as: "y not declared" even if it is declared! – Rookie Aug 21 '12 at 19:58
  • Why would you want to? You are not using any C++ features here. If you want to use C++ in another part of your project, create a header declaring `extern "C" void write_png_file(char *file_name)`, compile your source file as C, and use `write_png_file` from a C++ file. – Fabian Knorr Aug 21 '12 at 19:59
  • @trion, i want to convert it to c++ because i cant compile C, as i told: i get thousand of absurd errors. so im wondering if visual studio 2008 even supports it, because i cant find .c file extension when i want to create new source file. currently i just renamed .cpp into .c, and now it throws "thousand of absurd errors" that i have no clue what is wrong... they make no sense. – Rookie Aug 21 '12 at 20:04
  • Looks like you are depending on certain features not available in C++89, such as declaring variables in for loops (the `y`). If you depend on them, modify your compiler settings to compile in C99 mode, or move the parts using C library functions to a C source file and compile the rest using your C++ compiler. – Fabian Knorr Aug 21 '12 at 20:05
  • @trion, i have declared variables in for loops for years... it is supported in the c++ i am using. check my edits. i did move all the C stuff into C source file already. – Rookie Aug 21 '12 at 20:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/15624/discussion-between-trion-and-rookie) – Fabian Knorr Aug 21 '12 at 20:12

1 Answers1

0

The problem was in the order of the libraries:

#pragma comment(lib, "zlib_s.lib") // must be before libpng!
#pragma comment(lib, "libpng_s.lib") // must be after zlib!

Weird, but that fixed the problem!

Rookie
  • 4,064
  • 6
  • 54
  • 86