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:
briangr 2009-12-07 02:26:08 +00:00
parent 6044e9169e
commit cebb5fae9e
8 changed files with 110 additions and 48 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}