readPNG

glaze 20.11.07 15:36

Lataa ja näyttää PNG-kuvan käyttäen libpng:tä ja SDL:ää.

 Tekstiversio  Arvo: 2 (2 ääntä)  Äänestä: +  -
#include <iostream>
#include <string>
#include <cstdlib>
#include <SDL/SDL.h>
#include <png.h>

int* readPNG(const std::string& file) {
        FILE* fp = fopen(file.c_str(), "rb");
        png_byte header[8];
        png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                     NULL, NULL, NULL);
        png_infop info_ptr = png_create_info_struct(png_ptr);

        if (!png_ptr) {
                std::cout << "Error! png struct not ok." << std::endl;
                return NULL;
        }

        if (!info_ptr) {
                std::cout << "Error: info struct not ok." << std::endl;
                return NULL;
        }

        if (!fp) {
                std::cout << file << " not found!" << std::endl;
                return NULL;
        }

        fread(header, 1, 8, fp);
        bool is_png = !png_sig_cmp(header, 0, 8);

        if (!is_png) {
                std::cout << file << " is not a PNG file!" << std::endl;
                return NULL;
        }

        png_init_io(png_ptr, fp);
        png_set_sig_bytes(png_ptr, 8);

        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

        int width = info_ptr->width;
        int height = info_ptr->height;
        int ch = info_ptr->channels;

        int* image = new int[width * height];

        png_bytepp rows = png_get_rows(png_ptr, info_ptr);

        for (int y = 0; y < height; ++y) {
                for (int x = 0; x < width; ++x) {
                        image[y * width + x] = (rows[height-y-1][x*ch+0]<<16) |
                                                                (rows[height-y-1][x*ch+1]<<8) |
                                                                 rows[height-y-1][x*ch+2];
                }
        }
        return image;
}

int main() {
        SDL_Event e;
        int* image;

        if (!(image = readPNG("image.png"))) {
                return EXIT_FAILURE;
        }

        SDL_Surface* surface = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF);
        Uint32* fbuf = (Uint32*)surface->pixels;

        do {
                SDL_PollEvent(&e);

                // Tässä esimerkissä kuvan koko on tiedettävä etukäteen ja se on 256x256.
                for (int y = 0; y < 256; ++y) {
                        for (int x = 0; x < 256; ++x) {
                                fbuf[y * 640 + x] = image[y * 256 + x];
                        }
                }
                SDL_Flip(surface);
        } while (e.type != SDL_KEYDOWN);
        return EXIT_SUCCESS;
}

 

editoitu: 15:44 20.11.07
thefox 15:44 20.11.07 
Olisi hyvien tapojen mukaista vapauttaa tuo readPNG:n varaama ja palauttama puskuri jossain vaiheessa.

Myös #include <string> puuttuu.
Akheron 17:27 20.11.07 
Myös #include <cstdlib> puuttuu. EXIT_SUCCESS on määritelty siellä :P
Jaenis 17:38 20.11.07 
Hmm... Onko tää sit liian yksinkertaista:

C
#include <SDL/SDL_image.h>
...
SDL_Surface *Img = IMG_Load("image.png");
...
 

Vaatii kyl SDL_image.dll:n
glaze 17:42 20.11.07 
Korjasin #includet. SDL_imagea en tuossa esimerkissä käyttänyt, koska libpng on varmaan yleisemmin käytössä.
editoitu: 00:15 6.12.07
pierutyynykäs 00:14 6.12.07 
glaze kirjoitti:
Korjasin #includet. SDL_imagea en tuossa esimerkissä käyttänyt, koska libpng on varmaan yleisemmin käytössä.
Mutta jos esimerkissä käytetään SDL:ää muutenkin, eikä ole sama käyttää tuota SDL:n valmista funkkaria? Onhan tuo tosin esimerkkinä libpng:n käytöstä.
glaze 18:34 8.12.07 
SDL-image on eri paketti kuin SDL, ja esimerkin tarkoitus on opettaa nimenomaan libpng:n käyttöä.