[SDL] SDL_CreateRGBSurface errors [SOLVED]

Started by
3 comments, last by Zeophlite 18 years, 8 months ago
I'm trying to convert an existing image to a new file that contains map data I take 2 images, one of map data, and another of the actual image This code converts the image to the map

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "SDL.h"

Uint32 getpixel(SDL_Surface *surface, int x, int y) {
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        return *p;

    case 2:
        return *(Uint16 *)p;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;

    case 4:
        return *(Uint32 *)p;

    default:
        return 0;       /* shouldn't happen, but avoids warnings */
    }
}

void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) {
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;
    }
}

void SLock(SDL_Surface *screen) {
	if(SDL_MUSTLOCK(screen)) {
		if(SDL_LockSurface(screen) < 0 ) {
			return;
		}
	}
}

void SUnlock(SDL_Surface *screen) {
	if(SDL_MUSTLOCK(screen)) {
		SDL_UnlockSurface(screen);
	}
}

void DrawIMG(SDL_Surface *img, SDL_Surface *screen, int x, int y) {
	SDL_Rect dest;
	dest.x = x;
	dest.y = y;
	SDL_BlitSurface(img, NULL, screen, &dest);
}

SDL_Surface * ImageLoad(std::string file) {
	return ImageLoad(file, -1, 0, 0, 255);
}

SDL_Surface * ImageLoad(std::string file, Uint8 alpha) {
	return ImageLoad(file, -1, 0, 0, alpha);
}

SDL_Surface * ImageLoad(std::string file, int r, int g, int b) {
	return ImageLoad(file, r, g, b, 255);
}

SDL_Surface * ImageLoad(std::string file, int r, int g, int b, Uint8 alpha) {
	LogTxt("Loading Image: " + file);
	SDL_Surface *temp1, *temp2;
	temp1 = SDL_LoadBMP(file.c_str());
	
	if(r >= 0) {
		SDL_SetColorKey(temp1, SDL_SRCCOLORKEY, SDL_MapRGB(temp1->format, r, g, b));
	}
	
	if(alpha < 255) {
		SDL_SetAlpha(temp1, SDL_SRCALPHA, alpha);
		temp2 = SDL_DisplayFormatAlpha(temp1);
	} else {
		temp2 = SDL_DisplayFormat(temp1);
	}
	
	SDL_FreeSurface(temp1);
	return temp2;
}



SDL_Surface *screen, *mapfile, *datafile;


int main(int argc, char *argv[]) {
	if(argc != 2) {
		printf("Bounce Map Maker:\nUsage\n%s [mapname]\n", argv[0]);
		exit(1);
	}
	
	if(SDL_Init(SDL_INIT_VIDEO) < 0) {
		printf("Couldn't initialize SDL: %s\n", SDL_GetError ());
		exit(1);
	}
	atexit(SDL_Quit);
	
	screen = SDL_SetVideoMode (640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
	if(screen == NULL) {
		printf("Couldn't set 640x480x32 video mode: %s\n", SDL_GetError ());
		exit(1);
	}
	SDL_WM_SetCaption ("Bounce Map Maker", NULL);
	
	std::string outfile;
	outfile = argv[1];
	outfile = outfile + ".map.bmp";
	mapfile = ImageLoad(outfile.c_str());
	DrawIMG(mapfile, screen, 0, 0);
	SDL_Flip(screen);
	outfile = argv[1];
	outfile = outfile + ".data.bmp";
	datafile = ImageLoad(outfile.c_str());
	
	int width = mapfile->w;
	int height = mapfile->h;
	
	unsigned char r = 0, g = 0, b = 0;
	Uint32 pix;
	
	FILE *fp;
	outfile = argv[1];
	outfile = outfile + ".mfb";
	if((fp = fopen(outfile.c_str(), "w")) == NULL) {
		printf("Couldn't open output file");
		exit(1);
	}
	
	fwrite(&width, sizeof(int), 1, fp);
	fwrite(&height, sizeof(int), 1, fp);
	
	SLock(mapfile);
	SLock(datafile);
	int i, j;
	for(i = 0; i < width; i++) {
		for(j = 0; j < height; j++) {
			pix = getpixel(mapfile, i, j);
			SDL_GetRGB(pix, mapfile->format, &r, &g, &b);
			
			fwrite(&r, sizeof(unsigned char), 1, fp);
			fwrite(&g, sizeof(unsigned char), 1, fp);
			fwrite(&b, sizeof(unsigned char), 1, fp);
			
			pix = getpixel(datafile, i, j);
			SDL_GetRGB(pix, datafile->format, &r, &g, &b);
			
			fwrite(&r, sizeof(unsigned char), 1, fp); // PixelData
		}
	}
	
	SUnlock(datafile);
	SUnlock(mapfile);
	
	fclose(fp);
	
	if(screen != NULL) {
		SDL_FreeSurface(screen);
	}
	if(mapfile != NULL) {
		SDL_FreeSurface(mapfile);
	}
	if(datafile != NULL) {
		SDL_FreeSurface(datafile);
	}
	
	return 0;
}



And this code converts the data back


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <vector>
#include <string>

#include "SDL.h"
#include "Tools/sdl-common.h"

class CMap {
	public:
		bool init(std::string mapfile, SDL_Surface *m_screen);
	
	protected:
		SDL_Surface *mapImage, *screen;
		std::vector<std::vector<bool> > solid;
		int width, height;
};

bool CMap::init(std::string mapfile, SDL_Surface *m_screen) {
	screen = m_screen;
	
	FILE *fp;
	if((fp = fopen(mapfile.c_str(), "r")) == NULL) {
		LogTxt("Couldn't open mapfile: " + mapfile + "\n");
		return false;
	}
	
	fread(&width, sizeof(int), 1, fp);
	fread(&height, sizeof(int), 1, fp);
	
	SDL_Surface *tmpmap;
	unsigned char data[width*height*4];
	unsigned char pixdata;
	
	solid.resize(width);
	int i, j;
	for(i = 0; i < width; i++) {
		for(j = 0; j < height; j++) {
			solid.push_back(false);
		}
	}
	
	for(i = 0; i < width; i++) {
		for(j = 0; j < height; j++) {
			fread(&data[(i*height+j)*4], sizeof(unsigned char), 1, fp); // red
			fread(&data[(i*height+j)*4+1], sizeof(unsigned char), 1, fp); // green
			fread(&data[(i*height+j)*4+2], sizeof(unsigned char), 1, fp); // blue
			data[(i*height+j)*4+3] = 255;
			fread(&pixdata, sizeof(unsigned char), 1, fp); // PixelData
			if(pixdata == 128) {
				solid[j] = true;
			} else {
				solid[j] = false;
			}
		}
	}
	
	fclose(fp);
	
	Uint32 rmask,gmask,bmask,amask;
	if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
		rmask = 0xff000000;
		gmask = 0x00ff0000;
		bmask = 0x0000ff00;
		amask = 0x000000ff;
	} else {
		rmask = 0x000000ff;
		gmask = 0x0000ff00;
		bmask = 0x00ff0000;
		amask = 0xff000000;
	}
	
	if((tmpmap = SDL_CreateRGBSurfaceFrom(&data, width, height, 32, width*4, rmask, gmask, bmask, amask)) == NULL) {
		LogTxt("tmpmap == NULL - Bad"); // + mkstr(
	} else {
		LogTxt("tmpmap != NULL - Good"); // + mkstr(
	}
	if((mapImage = SDL_DisplayFormat(tmpmap)) == NULL) {
		LogTxt("mapImage == NULL - Bad"); // + mkstr(
	} else {
		LogTxt("mapImage != NULL - Good"); // + mkstr(
	}
	SDL_FreeSurface(tmpmap);
	
	if(mapImage == NULL) {
		LogTxt("mapImage == NULL - Bad"); // + mkstr(
	} else {
		LogTxt("mapImage != NULL - Good"); // + mkstr(
	}
	
	DrawIMG(mapImage, m_screen, 0, 0);
	SDL_Flip(m_screen);
	SDL_Delay(5000);
	
	return true;
}



The original map picture is here: http://vicious.sixlabs.org/test.map.bmp and the map data is here: http://vicious.sixlabs.org/test.data.bmp My output is this: http://vicious.sixlabs.org/output.bmp Basically the first image is meant to be the same as the third I'm thinking that the problem is to do with (i*height+j)*4 [Edited by - Zeophlite on August 12, 2005 6:46:12 AM]
Advertisement
I don't think your links are working.
I like the DARK layout!
Sorry about that, the post has been edited to fix those links
You don't tell what the problem is and your images aren't loading properly, but you might change the part of code like this and see if it helps:

unsigned int pos;for(i = 0; i < height; i++) { //note: height comes first	for(j = 0; j < width; j++) {	pos=(i*width+j)*4;	fread(&data[pos], sizeof(unsigned char)*3, 1, fp); // red, green & blue	data[pos+3] = 255;

Thanks all,
The correct code is now:
	for(i = 0; i < width; i++) {		for(j = 0; j < height; j++) {			fread(&data[(j*width+i)*4], sizeof(unsigned char), 1, fp); // red			fread(&data[(j*width+i)*4+1], sizeof(unsigned char), 1, fp); // green			fread(&data[(j*width+i)*4+2], sizeof(unsigned char), 1, fp); // blue			data[(j*width+i)*4+3] = 255;			fread(&pixdata, sizeof(unsigned char), 1, fp); // PixelData

This topic is closed to new replies.

Advertisement