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

Reply via email to