forked from speed-dreams/speed-dreams-code
Added Jean-Phillipe image padding patch with minor fix
git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@1951 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: ec72f4d59380f7fdd7874e31093c7838e98dfa0a Former-commit-id: ce601058bc096c8174ea5a37c7e3bd78ffebb076
This commit is contained in:
parent
6044e9169e
commit
cebb5fae9e
8 changed files with 110 additions and 48 deletions
|
@ -214,7 +214,7 @@ int SplashScreen(void)
|
|||
sprintf(buf, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
|
||||
handle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
|
||||
screen_gamma = (float)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_GAMMA, (char*)NULL, 2.0);
|
||||
GLbyte *tex = (GLbyte*)GfImgReadPng(filename, &s_imgWidth, &s_imgHeight, screen_gamma);
|
||||
GLbyte *tex = (GLbyte*)GfImgReadPng(filename, &s_imgWidth, &s_imgHeight, screen_gamma, 0, 0);
|
||||
if (!tex)
|
||||
{
|
||||
GfParmReleaseHandle(handle);
|
||||
|
|
|
@ -172,47 +172,74 @@ GfuiDisplay(void)
|
|||
|
||||
if (GfuiScreen->bgColor.alpha != 0.0) {
|
||||
glClearColor(GfuiScreen->bgColor.red,
|
||||
GfuiScreen->bgColor.green,
|
||||
GfuiScreen->bgColor.blue,
|
||||
GfuiScreen->bgColor.alpha);
|
||||
GfuiScreen->bgColor.green,
|
||||
GfuiScreen->bgColor.blue,
|
||||
GfuiScreen->bgColor.alpha);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
if (GfuiScreen->bgImage != 0) {
|
||||
GLfloat tx1 = 0.0f, tx2 = 1.0f, ty1 = 0.0f, ty2 = 1.0f;
|
||||
|
||||
// All background images are 16:10 images which are stored as quadratic images.
|
||||
// Compute texture coordinates to ensure proper unskewed/unstretched display of
|
||||
// image content.
|
||||
tdble rfactor = (16.0f*ViewH)/(10.0f*ViewW);
|
||||
// Display backround image if any.
|
||||
if (GfuiScreen->bgImage) {
|
||||
|
||||
// Prepare texture display.
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glColor3f(GfuiColor[GFUI_BASECOLORBGIMAGE][0],
|
||||
GfuiColor[GFUI_BASECOLORBGIMAGE][1],
|
||||
GfuiColor[GFUI_BASECOLORBGIMAGE][2]);
|
||||
glBindTexture(GL_TEXTURE_2D, GfuiScreen->bgImage);
|
||||
|
||||
// Get real 2^N x 2^P texture size (may have been 0 padded at load time
|
||||
// if the original image was not 2^N x 2^P)
|
||||
// This 2^N x 2^P stuff is needed by some low-end OpenGL hardware/drivers.
|
||||
int bgQuadWidth = 1, bgQuadHeight = 1;
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &bgQuadWidth);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &bgQuadHeight);
|
||||
|
||||
// Compute the initial width of the right area and the height of the bottom area
|
||||
// of the texture that will not be displayed
|
||||
// (We display only the top left rectangle of the quad texture
|
||||
// that corresponds to the original image).
|
||||
GLfloat tx1 = 0.0f;
|
||||
GLfloat tx2 = GfuiScreen->bgWidth / (GLfloat)bgQuadWidth;
|
||||
|
||||
GLfloat ty1 = 1.0f-(GfuiScreen->bgHeight / (GLfloat)bgQuadHeight);
|
||||
GLfloat ty2 = 1.0;
|
||||
|
||||
// Compute the width/height of the symetrical left/right / top/bottom
|
||||
// areas of original image that will need to be clipped
|
||||
// in order to keep its aspect ratio.
|
||||
const GLfloat rfactor = GfuiScreen->bgWidth * (GLfloat)ViewH
|
||||
/ GfuiScreen->bgHeight / (GLfloat)ViewW;
|
||||
|
||||
if (rfactor >= 1.0f) {
|
||||
// Aspect ratio of view is smaller than 16:10, "cut off" sides
|
||||
tdble tdx = (1.0f-1.0f/rfactor)/2.0f;
|
||||
// If aspect ratio of view is smaller than image's one, "cut off" sides.
|
||||
GLfloat tdx = (1.0f - 1.0f / rfactor) / 2.0f;
|
||||
tx1 += tdx;
|
||||
tx2 -= tdx;
|
||||
} else {
|
||||
// Aspect ratio of view is larger than 16:10, "cut off" top and bottom
|
||||
tdble tdy = (1.0f-rfactor)/2.0f;
|
||||
// If aspect ratio of view is larger than image's one,
|
||||
// "cut off" top and bottom.
|
||||
GLfloat tdy = (1.0f - rfactor) / 2.0f;
|
||||
ty1 += tdy;
|
||||
ty2 -= tdy;
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glColor3f(GfuiColor[GFUI_BASECOLORBGIMAGE][0],GfuiColor[GFUI_BASECOLORBGIMAGE][1],GfuiColor[GFUI_BASECOLORBGIMAGE][2]);
|
||||
glBindTexture(GL_TEXTURE_2D, GfuiScreen->bgImage);
|
||||
// Display texture.
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(tx1, ty1); glVertex3f(0.0, 0.0, 0.0);
|
||||
glTexCoord2f(tx1, ty2); glVertex3f(0.0, GfuiScreen->height, 0.0);
|
||||
glTexCoord2f(tx2, ty2); glVertex3f(GfuiScreen->width, GfuiScreen->height, 0.0);
|
||||
glTexCoord2f(tx2, ty1); glVertex3f(GfuiScreen->width, 0.0, 0.0);
|
||||
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Display other screen objects
|
||||
curObj = GfuiScreen->objects;
|
||||
if (curObj) {
|
||||
do {
|
||||
|
@ -221,6 +248,7 @@ GfuiDisplay(void)
|
|||
} while (curObj != GfuiScreen->objects);
|
||||
}
|
||||
|
||||
// Display mouse cursor if needed/specified
|
||||
if (!GfuiMouseHW && GfuiMouseVisible && GfuiScreen->mouseAllowed) {
|
||||
GfuiDrawCursor();
|
||||
}
|
||||
|
@ -983,7 +1011,7 @@ GfuiScreenAddBgImg(void *scr, const char *filename)
|
|||
void *handle;
|
||||
float screen_gamma;
|
||||
GLbyte *tex;
|
||||
int w,h;
|
||||
int qw, qh;
|
||||
|
||||
if (screen->bgImage != 0) {
|
||||
glDeleteTextures(1, &screen->bgImage);
|
||||
|
@ -992,14 +1020,23 @@ GfuiScreenAddBgImg(void *scr, const char *filename)
|
|||
sprintf(buf, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
|
||||
handle = GfParmReadFile(buf, GFPARM_RMODE_STD);
|
||||
screen_gamma = (float)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_GAMMA, (char*)NULL, 2.0);
|
||||
tex = (GLbyte*)GfImgReadPng(filename, &w, &h, screen_gamma);
|
||||
// Note: Here, we save the original image size (may be not 2^n x 2^p)
|
||||
// in order to be able to hide padding pixels added in texture to enforce 2^n x 2^p.
|
||||
tex = (GLbyte*)GfImgReadPng(filename, &screen->bgWidth, &screen->bgHeight,
|
||||
screen_gamma, &qw, &qh);
|
||||
|
||||
if (!tex) {
|
||||
GfParmReleaseHandle(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
//Force Background image to power of 2
|
||||
GfScaleImagePowerof2((unsigned char*)tex,w,h,GL_RGBA,screen->bgImage);
|
||||
// GfScaleImagePowerof2((unsigned char*)tex,w,h,GL_RGBA,screen->bgImage);
|
||||
glGenTextures(1, &screen->bgImage);
|
||||
glBindTexture(GL_TEXTURE_2D, screen->bgImage);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, qw, qh, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)(tex));
|
||||
free(tex);
|
||||
|
||||
GfParmReleaseHandle(handle);
|
||||
|
|
|
@ -239,7 +239,8 @@ typedef struct
|
|||
{
|
||||
float width, height;
|
||||
Color bgColor; /* RGBA */
|
||||
GLuint bgImage;
|
||||
GLuint bgImage; /* Should always be 2^n x 2^p */
|
||||
int bgWidth, bgHeight; /* Original bg image size (may be not 2^n x 2^p) */
|
||||
|
||||
/* sub-objects */
|
||||
tGfuiObject *objects;
|
||||
|
|
|
@ -101,29 +101,32 @@ GfScaleImagePowerof2(unsigned char *pSrcImg,int srcW,int srcH,GLenum format,GLui
|
|||
}
|
||||
|
||||
/** Load an image from disk to a buffer in RGBA mode.
|
||||
@ingroup img
|
||||
=======/** Load an image from disk to a buffer in RGBA mode (if specified, enforce 2^N x 2^P size for the target buffer, to suit with low-end OpenGL hardwares/drivers poor texture support).
|
||||
>>>>>>> .theirs @ingroup img
|
||||
@param filename name of the image to load
|
||||
@param widthp width of the read image
|
||||
@param heightp height of the read image
|
||||
@param widthp original width of the read image (left aligned in target buffer)
|
||||
@param heightp original height of the read image (top aligned in target buffer)
|
||||
@param screen_gamma gamma correction value
|
||||
@param quad_widthp if not 0, pointer to 2^N width of the target image buffer
|
||||
@param quad_heightp if not 0, pointer to 2^N height of the target image buffer
|
||||
@return Pointer on the buffer containing the image
|
||||
<br>NULL Error
|
||||
*/
|
||||
unsigned char *
|
||||
GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma)
|
||||
GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma, int *quad_widthp, int *quad_heightp)
|
||||
{
|
||||
unsigned char buf[PNG_BYTES_TO_CHECK];
|
||||
FILE *fp;
|
||||
png_structp png_ptr;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type;
|
||||
png_uint_32 src_width, src_height;
|
||||
png_uint_32 tgt_width, tgt_height;
|
||||
int bit_depth, color_type, interlace_type;
|
||||
|
||||
/* png_color_16p image_background; */
|
||||
double gamma;
|
||||
png_bytep *row_pointers;
|
||||
unsigned char *image_ptr, *cur_ptr;
|
||||
png_uint_32 rowbytes;
|
||||
png_uint_32 src_rowbytes, tgt_rowbytes;
|
||||
png_uint_32 i;
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL) {
|
||||
|
@ -169,10 +172,28 @@ GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma
|
|||
png_init_io(png_ptr, fp);
|
||||
png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
|
||||
*widthp = (int)width;
|
||||
*heightp = (int)height;
|
||||
png_get_IHDR(png_ptr, info_ptr, &src_width, &src_height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
|
||||
*widthp = (int)src_width;
|
||||
*heightp = (int)src_height;
|
||||
|
||||
// Compute target quad image buffer size if specified.
|
||||
// Note: This 2^N x 2^P stuff is needed by some low-end OpenGL hardware/drivers
|
||||
// that don't support non 2^N x 2^P textures (or at extremely low frame rates).
|
||||
if (quad_widthp && quad_heightp) {
|
||||
tgt_width = 2;
|
||||
tgt_height = 2;
|
||||
while(tgt_width < src_width)
|
||||
tgt_width *= 2;
|
||||
//tgt_height = tgt_width;
|
||||
while(tgt_height < src_height)
|
||||
tgt_height *= 2;
|
||||
*quad_widthp = (int)tgt_width;
|
||||
*quad_heightp = (int)tgt_height;
|
||||
} else {
|
||||
tgt_width = (int)src_width;
|
||||
tgt_height = (int)src_height;
|
||||
}
|
||||
|
||||
if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) png_set_invert_mono(png_ptr);
|
||||
if (bit_depth == 16) {
|
||||
png_set_swap(png_ptr);
|
||||
|
@ -210,35 +231,39 @@ GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma
|
|||
}
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
src_rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
tgt_rowbytes = src_rowbytes;
|
||||
if (quad_widthp && quad_heightp)
|
||||
tgt_rowbytes = tgt_width * src_rowbytes / src_width;
|
||||
|
||||
// RGBA expected.
|
||||
if (rowbytes != (4 * width)) {
|
||||
GfTrace("%s bad byte count... %lu instead of %lu\n", filename, (unsigned long)rowbytes, (unsigned long)(4 * width));
|
||||
if (src_rowbytes != (4 * src_width)) {
|
||||
GfTrace("%s bad byte count... %lu instead of %lu\n", filename, (unsigned long)src_rowbytes, (unsigned long)(4 * src_width));
|
||||
fclose(fp);
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
return (unsigned char *)NULL;
|
||||
}
|
||||
|
||||
row_pointers = (png_bytep*)malloc(height * sizeof(png_bytep));
|
||||
row_pointers = (png_bytep*)malloc(tgt_height * sizeof(png_bytep));
|
||||
if (row_pointers == NULL) {
|
||||
fclose(fp);
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
return (unsigned char *)NULL;
|
||||
}
|
||||
|
||||
image_ptr = (unsigned char *)malloc(height * rowbytes);
|
||||
image_ptr = (unsigned char *)malloc(tgt_height * tgt_rowbytes);
|
||||
if (image_ptr == NULL) {
|
||||
fclose(fp);
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
return (unsigned char *)NULL;
|
||||
}
|
||||
|
||||
for (i = 0, cur_ptr = image_ptr + (height - 1) * rowbytes ; i < height; i++, cur_ptr -= rowbytes) {
|
||||
for (i = 0, cur_ptr = image_ptr + (tgt_height - 1) * tgt_rowbytes ; i < tgt_height; i++, cur_ptr -= tgt_rowbytes) {
|
||||
row_pointers[i] = cur_ptr;
|
||||
}
|
||||
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
free(row_pointers);
|
||||
|
||||
|
@ -246,7 +271,6 @@ GfImgReadPng(const char *filename, int *widthp, int *heightp, float screen_gamma
|
|||
return image_ptr;
|
||||
}
|
||||
|
||||
|
||||
/** Write a buffer to a png image on disk.
|
||||
@ingroup img
|
||||
@param img image data (RGB)
|
||||
|
@ -366,7 +390,7 @@ GfImgReadTex(const char *filename, int &width, int &height)
|
|||
sprintf(buf, "%s%s", GetLocalDir(), GFSCR_CONF_FILE);
|
||||
handle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
|
||||
screen_gamma = (float)GfParmGetNum(handle, GFSCR_SECT_PROP, GFSCR_ATT_GAMMA, (char*)NULL, 2.0);
|
||||
tex = (GLbyte*)GfImgReadPng(filename, &width, &height, screen_gamma);
|
||||
tex = (GLbyte*)GfImgReadPng(filename, &width, &height, screen_gamma, 0, 0);
|
||||
|
||||
if (!tex) {
|
||||
GfParmReleaseHandle(handle);
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
* Screen Interface *
|
||||
********************/
|
||||
|
||||
extern unsigned char *GfImgReadPng(const char *filename, int *widthp, int *heightp, float gamma);
|
||||
extern unsigned char *GfImgReadPng(const char *filename, int *widthp, int *heightp, float gamma, int *quad_widthp, int *quad_heightp);
|
||||
extern int GfImgWritePng(unsigned char *img, const char *filename, int width, int height);
|
||||
extern void GfImgFreeTex(GLuint tex);
|
||||
extern GLuint GfImgReadTex(const char *filename);
|
||||
|
|
|
@ -91,7 +91,7 @@ bool grLoadPngTexture (const char *fname, ssgTextureInfo* info)
|
|||
|
||||
TRACE_GL("Load: grLoadPngTexture start");
|
||||
|
||||
tex = (GLubyte*)GfImgReadPng(fname, &w, &h, 2.0);
|
||||
tex = (GLubyte*)GfImgReadPng(fname, &w, &h, 2.0, 0, 0);
|
||||
if (!tex) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ void LoadElevation(tTrack *track, void *TrackHandle, char *imgFile)
|
|||
tdble zmin, zmax;
|
||||
tdble xmin, xmax, ymin, ymax;
|
||||
|
||||
ElvImage = GfImgReadPng(imgFile, &width, &height, 2.0);
|
||||
ElvImage = GfImgReadPng(imgFile, &width, &height, 2.0, 0, 0);
|
||||
if (!ElvImage) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -459,7 +459,7 @@ GenerateObjects(tTrack *track, void *TrackHandle, void *CfgHandle, FILE *save_fd
|
|||
sprintf(buf, "tracks/%s/%s/%s", track->category, track->internalname, map);
|
||||
|
||||
printf("Processing object map %s\n", buf);
|
||||
MapImage = GfImgReadPng(buf, &width, &height, 2.0);
|
||||
MapImage = GfImgReadPng(buf, &width, &height, 2.0, 0, 0);
|
||||
if (!MapImage) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue