Carsten Haitzler (The Rasterman) a �crit :
> On Tue, 19 Apr 2005 22:23:29 -0400 Jay Summet <[EMAIL PROTECTED]> babbled:
>
>
> imlib2 appears to store image data internally in ARGB format, which you can
> get
> a pointer to with a call such as:
> unsigned int *pImageData = imlib_image_get_data();
>
>
>> take a look at:
>> evas/src/lib/engines/gl_common/evas_gl_texture.c
>
>> evas uses the same pix format as imlib2 - and that converts the image to a
>> texture :) (handles nv_rect extensions, power of 2 padding etc.)
>
>> ie without alpha:
>> glTexImage2D(GL_TEXTURE_2D, 0,
>> GL_RGB8, w, h, 0,
>> GL_BGRA, GL_UNSIGNED_BYTE, pixels);
>
>> with alpha:
>> glTexImage2D(GL_TEXTURE_2D, 0,
>> GL_RGBA8, w, h, 0,
>> GL_BGRA, GL_UNSIGNED_BYTE, pixels);
>
>> check that code to see it handling power of 2 problems "properly" (it doesnt
>> handle texture meshes when max text size < image size though). it requires
>> no copy/transform before copying the pixels to the texture.
>
>
> OpenGL glTexImage2D() function wants data in RGBA format.
>
> You can do a manual conversion of each and every pixel with a double for loop
> enclosing the following:
>
> ~ GLdata[offset] = (pImageData[img_offset] >> 16) & 0xff;
> ~ GLdata[offset + 1] = (pImageData[img_offset] >> 8) & 0xff;
> ~ GLdata[offset + 2] = pImageData[img_offset] & 0xff;
> ~ GLdata[offset + 3] = (pImageData[img_offset] >> 24) & 0xff;
>
> But this is slow.
>
> Is there a better (faster) way to convert an imlib2 image to an OpenGL
> texture?
>
> Thanks,
> Jay
>
> I'm basically looking to load lots of images in various formats and render
> them
> as OpenGL textures, I don't think I'll need all of imlib2's image
> compositing/blending functionality, so perhaps another library would be a
> better
> choice? Suggestions?
take a look at my tlib.c file
best regards
Michel
/*
* $Id: eana_tlib.c,v 1.4 2005/01/29 14:29:30 michel Exp $
*
* description: Textures & images routines.
*
*/
#include "eana_tlib.h"
static const GLenum t_quality_tab[] = {
GL_NEAREST,
GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_LINEAR
};
GLenum t_quality(e_quality_t quality)
{
ASSERTE(quality>=0 && quality<=q_linear_mipmap_linear);
return t_quality_tab[quality];
}
s_image_t* t_image_load(const char *path, float gamma)
{
Imlib_Image imlib_image;
Imlib_Load_Error imlib_error;
s_image_t *image;
size_t sz_transfert;
DATA32 *transfert;
imlib_image = imlib_load_image_with_error_return(path, &imlib_error);
if ((imlib_error != IMLIB_LOAD_ERROR_NONE) || !imlib_image) {
TR(trError, "Imlib2 Error: %d\n", imlib_error);
return NULL;
}
image = xalloc(s_image_t);
image->name = strdup(path);
imlib_context_set_image(imlib_image);
image->width = imlib_image_get_width();
image->height = imlib_image_get_height();
image->alpha = imlib_image_has_alpha();
//imlib_image_flip_vertical();
sz_transfert = image->width * image->height * 4; // Imlib2 gives always 4 bytes / pixel
image->align = 4;
image->pixels = calloc(1, sz_transfert);
memset(image->pixels, 1, sz_transfert);
transfert = imlib_image_get_data_for_reading_only();
memcpy(image->pixels, transfert, sz_transfert);
t_image_gamma_adjust(image->align, image->width, image->height, image->pixels, gamma);
imlib_free_image();
return image;
}
void t_image_gamma_adjust(int align, int width, int height, void *pixels, float gamma)
{
float scale, temp;
float r, g, b;
uchar_t *pix;
uint_t i, npix;
npix = width * height;
pix = (uchar_t *) pixels;
for (i = 0; i < npix; i++, pix += align) {
scale = 1.0f;
temp = 0.0f;
r = g = b = 0;
r = (float) pix[0];
g = (float) pix[1];
b = (float) pix[2];
r = r * gamma / 255.0f;
g = g * gamma / 255.0f;
b = b * gamma / 255.0f;
if (r > 1.0f && (temp = (1.0f/r)) < scale) scale = temp;
if (g > 1.0f && (temp = (1.0f/g)) < scale) scale = temp;
if (b > 1.0f && (temp = (1.0f/b)) < scale) scale = temp;
scale *= 255.0f;
r *= scale; g *= scale; b *= scale;
pix[0] = (uchar_t) r;
pix[1] = (uchar_t) g;
pix[2] = (uchar_t) b;
}
}
bool_t t_image_write(s_image_t *image, const char *path)
{
Imlib_Image imlib_image;
imlib_image = imlib_create_image_using_data(image->width, image->height, (DATA32 *) image->pixels);
imlib_context_set_image(imlib_image);
imlib_save_image(path);
imlib_free_image();
return TRUE;
}
void t_image_destroy(s_image_t *image)
{
if (image->name)
free(image->name);
if (image->pixels)
free(image->pixels);
free(image);
}
int t_tex_create_mipmaps(int align, int width, int height, bool_t alpha, void *pixels, uint_t mipmaps, e_quality_t quality)
{
int tex;
GLenum gluError;
GLint internal_format;
GLenum format;
if (alpha) {
internal_format = GL_RGBA;
} else {
internal_format = GL_RGB;
}
if (align == 3) {
format = GL_BGR;
} else if (align == 4) {
format = GL_BGRA;
} else {
ERROR("fdr_tex_create: bad align %d\n", align);
return TEX_NO_TEX;
}
glGenTextures(1, &tex);
TEST_GL_ERROR("t_tex_create_mipmaps");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, tex);
if ((gluError = gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format,
width, height, format, GL_UNSIGNED_BYTE, pixels)) != 0) {
TR(trError, "GLU Error: %s\n", gluErrorString(gluError));
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, quality);
switch (quality) {
case q_nearest:
case q_nearest_mipmap_nearest:
case q_linear_mipmap_nearest:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
break;
case q_linear:
case q_nearest_mipmap_linear:
case q_linear_mipmap_linear:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
break;
}
TEST_GL_ERROR("t_tex_create_mipmaps");
return tex;
}
int t_tex_create(int align, int width, int height, bool_t alpha, void *pixels, e_quality_t quality)
{
int tex;
GLint internal_format;
GLenum format;
if ((width >> 1) & 1) {
ERROR("t_tex_create: image width (%d) is not 2n+2 !\n", width);
return TEX_NO_TEX;
}
if ((height >> 1) & 1) {
ERROR("t_tex_create: image height (%d) is not 2n+2 !\n", height);
return TEX_NO_TEX;
}
if (alpha) {
internal_format = GL_RGBA;
} else {
internal_format = GL_RGB;
}
if (align == 3) {
format = GL_BGR;
} else if (align == 4) {
format = GL_BGRA;
} else {
ERROR("fdr_tex_create: bad align %d\n", align);
return TEX_NO_TEX;
}
glGenTextures(1, &tex);
TEST_GL_ERROR("t_tex_create");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, pixels);
TEST_GL_ERROR("glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, t_quality(quality));
switch (quality) {
case q_nearest:
case q_nearest_mipmap_nearest:
case q_linear_mipmap_nearest:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
break;
case q_linear:
case q_nearest_mipmap_linear:
case q_linear_mipmap_linear:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
break;
}
TEST_GL_ERROR("t_tex_create");
return tex;
}
int t_tex_load(const char *path, float gamma, uint_t mipmaps, e_quality_t quality)
{
Imlib_Image imlib_image;
Imlib_Load_Error imlib_error;
int align, width, height, alpha;
void *pixels;
int tex;
imlib_image = imlib_load_image_with_error_return(path, &imlib_error);
if ((imlib_error != IMLIB_LOAD_ERROR_NONE) || !imlib_image) {
TR(trError, "Imlib2 Error: %d\n", imlib_error);
return TEX_NO_TEX;
}
imlib_context_set_image(imlib_image);
align = 4;
width = imlib_image_get_width();
height = imlib_image_get_height();
alpha = imlib_image_has_alpha();
pixels = imlib_image_get_data_for_reading_only();
t_image_gamma_adjust(align, width, height, pixels, gamma);
if (mipmaps)
tex = t_tex_create_mipmaps(align, width, height, alpha, pixels, mipmaps, quality);
else
tex = t_tex_create(align, width, height, alpha, pixels, quality);
imlib_free_image();
return tex;
}
s_image_t* t_viewport_get(int x, int y, int w, int h)
{
s_image_t *image;
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
TR(trDebug, "OpenGL viewport: (%d, %d, %d, %d)\n",
viewport[0], viewport[1], viewport[2], viewport[3]);
if (x > viewport[0]) viewport[0] = x;
if (y > viewport[1]) viewport[1] = y;
if (w < viewport[2]) viewport[2] = w;
if (h < viewport[3]) viewport[3] = h;
TR(trDebug, "Final rect: (%d,%d,%d,%d)\n",
viewport[0], viewport[1], viewport[2], viewport[3]);
image = xalloc(s_image_t);
image->bottom_top = TRUE;
image->alpha = TRUE;
image->width = viewport[2] - viewport[0];
image->height = viewport[3] - viewport[1];
image->pixels = (uchar_t *) calloc(4, image->width * image->height);
glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
TEST_GL_ERROR("glReadPixels");
return image;
}
bool_t t_viewport_write(const char *resource)
{
s_image_t *image;
image = t_viewport_get(glc.viewport[0], glc.viewport[1], glc.viewport[2], glc.viewport[2]);
TR(trTrace, "Saving chromatic buffer in %s...\n", resource);
t_image_write(image, resource);
t_image_destroy(image);
return TRUE;
}