-1

How to convert bmp to png properly? I was using this code:

#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_DEPRECATE

#include <png.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

void GetDesktopResolution(int& horizontal, int& vertical)
{
    RECT desktop;
    // Get a handle to the desktop window
    const HWND hDesktop = GetDesktopWindow();
    // Get the size of screen to the variable desktop
    GetWindowRect(hDesktop, &desktop);
    // The top left corner will have coordinates (0,0)
    // and the bottom right corner will have coordinates
    // (horizontal, vertical)
    horizontal = desktop.right;
    vertical = desktop.bottom;
}

typedef struct _RGBPixel {
    uint8_t blue;
    uint8_t green;
    uint8_t red;
} RGBPixel;

/* Structure for containing decompressed bitmaps. */
typedef struct _RGBBitmap {
    RGBPixel *pixels;
    size_t width;
    size_t height;
    size_t bytewidth;
    uint8_t bytes_per_pixel;
} RGBBitmap;

/* Returns pixel of bitmap at given point. */
#define RGBPixelAtPoint(image, x, y) \
    *(((image)->pixels) + (((image)->bytewidth * (y)) \
                        + ((x) * (image)->bytes_per_pixel)))

/* Attempts to save PNG to file; returns 0 on success, non-zero on error. */
int save_png_to_file(RGBBitmap *bitmap, const char *path)
{
    FILE *fp = fopen(path, "wb");
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    size_t x, y;
    png_uint_32 bytes_per_row;
    png_byte **row_pointers = NULL;

    if (fp == NULL) return -1;

    /* Initialize the write struct. */
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        fclose(fp);
        return -1;
    }

    /* Initialize the info struct. */
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_write_struct(&png_ptr, NULL);
        fclose(fp);
        return -1;
    }

    /* Set up error handling. */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return -1;
    }

    /* Set image attributes. */
    png_set_IHDR(png_ptr,
                 info_ptr,
                 bitmap->width,
                 bitmap->height,
                 8,
                 PNG_COLOR_TYPE_RGB,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);

    /* Initialize rows of PNG. */
    bytes_per_row = bitmap->width * bitmap->bytes_per_pixel;
    png_malloc(png_ptr, bitmap->height * sizeof(png_byte *));
    for (y = 0; y < bitmap->height; ++y) {
        uint8_t *row = (uint8_t *)png_malloc(png_ptr, sizeof(uint8_t)* bitmap->bytes_per_pixel);
        row_pointers[y] = (png_byte *)row; /************* MARKED LINE ***************/
        for (x = 0; x < bitmap->width; ++x) {
            RGBPixel color = RGBPixelAtPoint(bitmap, x, y);
            *row++ = color.red;
            *row++ = color.green;
            *row++ = color.blue;
        }
    }

    /* Actually write the image data. */
    png_init_io(png_ptr, fp);
    png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    /* Cleanup. */
    for (y = 0; y < bitmap->height; y++) {
        png_free(png_ptr, row_pointers[y]);
    }
    png_free(png_ptr, row_pointers);

    /* Finish writing. */
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
    return 0;
}

int main()
{
        RGBBitmap rgbbitmap;
    int w, h;
    GetDesktopResolution(w, h);
    rgbbitmap.height = h;
    rgbbitmap.width = w;
    rgbbitmap.bytes_per_pixel = 1;
    rgbbitmap.bytewidth = w / 100;

    RGBPixel rgbpixel;
    rgbpixel.blue = 100;
    rgbpixel.green = 100;
    rgbpixel.red = 100;
    rgbbitmap.pixels = &rgbpixel;

    save_png_to_file(&rgbbitmap, "abc.bmp");

        return 0;
}

But at runtime, I'm getting this error on the marked line :

Unhandled exception at 0x01258F04 in ProjectName.exe: 0xC0000005: Access violation writing location 0x00000000.

I've searched in the net, I've found this interesting small code, but I wasn't able to found its mother lib. And, I think that using libpng gives you more control on your output image.

How do I fix this issue? Or, maybe it's a wrong way to convert? If so, how may I do that?

Glenn Randers-Pehrson
  • 11,940
  • 3
  • 37
  • 61
user3471387
  • 427
  • 3
  • 8
  • 10

1 Answers1

3

You never allocate memory for row_pointers, so it's NULL when you do row_pointers[y] = (png_byte *)row;.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thanks for your answer, would you please tell me how to initialize it properly? – user3471387 Mar 28 '14 at 09:11
  • @user3471387 You already *do* allocate this memory, you just don't assign it to the `row_pointers`. See the `png_malloc` call just above the `for` loop. – Some programmer dude Mar 28 '14 at 09:15
  • @user3471387 You should take this as a lesson to not blindly copy and use other peoples code before actually understanding what the code is doing. In fact, what if there was some kind of trojan hidden in the code? – Some programmer dude Mar 28 '14 at 09:16
  • because when I add `row_pointers = ` on the begin of that line I get `a value of type "png_voidp" cannot be assigned to an entity of type "png_byte **"` as error message on `=`. – user3471387 Mar 28 '14 at 09:19
  • @user3471387 Take a look at other lines using `png_malloc`, what are they doing with the return value? – Some programmer dude Mar 28 '14 at 09:23
  • thank you very much Joachim for all, but, casting that way `(png_byte**)` triggers access violation on `*row++ = color.green;` line. – user3471387 Mar 28 '14 at 09:27