PDA

View Full Version : Loading Textures from JPEGs



reubenhwk
11-03-2003, 07:28 AM
How do I use jpeglib.h to load textures from a .jpeg or .jpg image?

I'm using either DEV-C++ or MSVC++.

mdog1234
11-03-2003, 10:10 AM
you dont want to do that because jpegs are bad textures and it reads the file from end to beginning which means it will be upside down using normal texture coords. This is really annoying and stupid. If someone could explain to me why libjpeg loads this way it would be greatly appreciated. So if you have a whole scene plan on fliping your texture coords or doing some adjustment to flip the data. However, I had trouble with this and no one could give a straight answer as to how to fix it. No good.

reubenhwk
11-03-2003, 10:15 AM
How about tiff then? Mainly what I'm looking for is a file format that I can edit on a windows and/or linux computer and easily open and make a texture out of it in C not using glaux.h...

[This message has been edited by reubenhwk (edited 11-03-2003).]

yakuza
11-03-2003, 10:30 AM
Targa (.tga) files would probably fit your needs.
http://www.google.com/search?hl=en&lr=&ie=UTF-8&oe=UTF-8&q=opengl+tga+file+loader

reubenhwk
11-03-2003, 01:47 PM
well assuming that jpegs made good textures, does anybody have any experience using jpeglib.h?

JanHH
11-03-2003, 05:08 PM
I am a little amazed about what the other people answered to your question. Of course you can load textures from jpeg images, and they do not neccessarily have to be bad quality, or upside down.

There's a good tutorial somewhere *g* about libjpeg (maybe on their home page), I wrote a texture loader for OpenGL under linux based on this, it's not very complicated. If neccessary I might post some code as well http://www.opengl.org/discussion_boards/ubb/wink.gif

Jan

JanHH
11-03-2003, 05:10 PM
mdog123 the jpeg lib does not create a texture, but basically loads the texture into a memory area, right? so you might just swap that area afterwards, to correct the upside down flipping (at least, so did I..)

reubenhwk
11-03-2003, 05:26 PM
Or why not just open the JPEG in mspaint.exe and flip/rotate the image and save it back to the file... It seems like JPEGs would be a good file format for textures for a few reasons... 1) So many images are stored in that format.. 2) High quality images can be stored in just a few k of disk space so that it could be loaded from the disk quickly.. 3) The jpeglib can (an I think in most cases now does) support MMX and can decode the image very quickly.

Am I incorrect in assuming that loading a texture from a JPEG would be faster than other formats?

I have some code that reads the header from a jpeg (width, height, bits, ect..) but I don't konw how to carry it further to generate a texture from it...

Thank you all for all your input.

[This message has been edited by reubenhwk (edited 11-03-2003).]

JanHH
11-03-2003, 06:08 PM
texture loading time is not an issue at all, and in facht jpeg is not the ideal texture format, as the compression is based on reduction of image quality, and you _can_ see this, formats like .gif or .png are much better. And loading jpegs and flipping them is not a good idea as well, as with every load and save, the image gets decompressed and compressed again, and quality gets worse and worse with every load/save even if you do not change anything. But still, it's easy to load an image with libjpeg, and for this reason, it's recommendable. even more easy and better quality (uncompressed) is .ppm, but the image files are very large, although this does not really affect loading time.

Jan

mdog1234
11-03-2003, 08:05 PM
i dont like jpegs lossy format. I dont know what kind of application you are writing but if you are concerned about space then you will want to think about jpegs. Space isnt really an issue for me so thats why i use .tga or .dds usually. Here is the code to load it but keep in mind this loads it upside down and i still havent gotten the flipping to work. If someone could take my code and try to make it flip right I would be greatful.

struct jpeg_decompress_struct CInfo;
ErrorManager jerr;
FILE *fp = NULL;
JSAMPARRAY buffer;
JSAMPLE *DataBuffer = NULL;
int RowStride;
long cont;
int i, j;

if(!(fp = fopen(filename, "rb")))
{
//cant open fp
return false;
}

CInfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = ErrorExit;

if(setjmp(jerr.setjmp_buffer))
{
jpeg_destroy_decompress(&CInfo);
fclose(fp);
return false;
}

jpeg_create_decompress(&CInfo);
jpeg_stdio_src(&CInfo, fp);
jpeg_read_header(&CInfo, TRUE);
jpeg_start_decompress(&CInfo);
RowStride = CInfo.output_width * CInfo.output_components;
buffer = (*CInfo.mem->alloc_sarray)((j_common_ptr) &CInfo, JPOOL_IMAGE, RowStride, 1);
DataBuffer = new JSAMPLE [CInfo.image_width * CInfo.image_height * CInfo.output_components];
cont = 0;

while(CInfo.output_scanline < CInfo.output_height)
{
jpeg_read_scanlines(&CInfo, buffer, 1);
memcpy(DataBuffer + CInfo.image_width * CInfo.output_components * cont, buffer[0], RowStride);
cont++;
}

jpeg_finish_decompress(&CInfo);
jpeg_destroy_decompress(&CInfo);

ImageWidth = CInfo.image_width;
ImageHeight = CInfo.image_height;
ImageData = new unsigned char [ImageWidth * ImageHeight * 4];



switch(CInfo.output_components)
{
case 1:
for(i = 0, j = 0; i < ImageWidth * ImageHeight; i++, j += 4)
{
ImageData[j] = ImageData[j + 1] = ImageData[j + 2] = DataBuffer[i];
ImageData[j + 3] = 255;
}
break;
case 3:
for(i = 0, j = 0; i < ImageWidth * ImageHeight * 3; i += 3, j += 4)
{
ImageData[j ] = DataBuffer[i];
ImageData[j + 1] = DataBuffer[i + 1];
ImageData[j + 2] = DataBuffer[i + 2];
ImageData[j + 3] = 255;
}
break;
default:
delete[] ImageData;
ImageData = NULL;
delete[] DataBuffer;
//error
return false;
}

free(DataBuffer);
fclose(fp);
}

basically ImageData which is unsigned char and ImageWidth and ImageHeight are really all you need to know about when using opengl for textures. I assume you know how to do that but if u dont here is a some admittedly rudimentary code:

glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);

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_RGB, ImageWidth, ImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, ImageData);

[This message has been edited by mdog1234 (edited 11-03-2003).]

Korval
11-03-2003, 08:17 PM
in facht jpeg is not the ideal texture format, as the compression is based on reduction of image quality, and you _can_ see this

This is half true. JPEG is a bad format for textures, but not because it is lossy. S3TC is lossy, but it's a pretty good texture format.

One of the principle reasons that JPEG is poor for textures is because of the difference between how a texture is used and how an image is used. JPEG is designed to store images that will be used for the purpose of display on a monitor. Because of this, as I understand it, the compressor changes the colorspace & gamma of the image.

While this is good for merely displaying an image, it is a bad idea for textures. Textures are designed to have lighting and various effects applied to them. The color space and gamma alterations that JPEG compression applies to an image creates artifacts that are very noticable when an image is used as a texture map.

MichaelK
11-04-2003, 06:13 AM
Is there a way to decode JPEGs directly from memory? When using jpeglib we must provide FILE pointer to the image. So I have to write the memory chunk to tmpfile() and pass it to the jpeglib. So, do You know the trick to not use disk files?

Pozdrawiam,
Michal Krol

reubenhwk
11-04-2003, 07:19 AM
What is YOUR prefered file format to load textures from and why? What format do you dislike and why?

mdog1234
11-04-2003, 07:36 AM
dds and tga are the best for me because they look good and none of the data is lost due to compression. Tgas are easy to load. DDS(direct draw surface) is good for mipmapping and 3d textures. They also seem to give me the highest quality image.

Ostsol
11-04-2003, 07:56 AM
Originally posted by reubenhwk:
Or why not just open the JPEG in mspaint.exe and flip/rotate the image and save it back to the file...
The problem there is that you're recompressing a previously compressed file. As such, you're potentially adding more compression artifacts to the image.

reubenhwk
11-04-2003, 10:48 AM
What are the pros and cons for TIFF?

Zengar
11-04-2003, 04:57 PM
TARGA rulez http://www.opengl.org/discussion_boards/ubb/biggrin.gif

The coolest think about TGA - you can write a loader in about 5 minutes.
Guess I will be moving to dds soon.

GT5
11-04-2003, 06:09 PM
quote:
--------------------------------------------------------------------------------
Originally posted by reubenhwk:
Or why not just open the JPEG in mspaint.exe and flip/rotate the image and save it back to the file...
--------------------------------------------------------------------------------


The problem there is that you're recompressing a previously compressed file. As such, you're potentially adding more compression artifacts to the image.


I guess you could first flip the UNCOMPRESSED image then save it as .jpg

Cyranose
11-04-2003, 06:18 PM
From my own experience:

JPEG -- small file size, lots of loaders (I found the free Intel lib to be very fast and flexible, even handling the y-flip and loading from memory buffers). con: "lossy" is too generic as term. It's very lossy for high-frequency images (think sharp contrasts between pixels), but often very appropriate for something like the base layer of terrain, with fairly gradual transitions. Not all loaders support 4 color channels for handling alpha. I wrote an app that had to page through many gigabytes (TB now) of terrain and jpeg was the easiest/fastest solution (even faster than raw!) until it was time to write something custom.

GIF -- simple, but only 8 bit, not 24, was proprietary but not anymore. Forget alpha, but one-bit transparency is common.

PNG -- the open replacement for GIF, but much better. Makes a good middle of the road solution.

Targa/Tiff -- often uncompressed, but almost never lossy. Both generally support 4 color channels. Good and simple, but I wouldn't use this for a large-scale project simply because I can't stand games or apps that install 600MB of crap to my hard disk.

By the way, on jpeg's appropriateness, one of the features of DCT-based codecs is they impliclty store multiple resolutions in the file. Now, most HW nowadays has mip-level generation essentially free. But many apps like to start with low resolutions of textures as they approach and only consume memory for higher-detail versions as needed. Jpeg and Jpeg2000 are very good for that.

Avi


[This message has been edited by Cyranose (edited 11-04-2003).]

pkaler
11-04-2003, 09:56 PM
Originally posted by Cyranose:

PNG -- the open replacement for GIF, but much better. Makes a good middle of the road solution.


I wouldn't call PNG middle of the road.

It supports transparency, gamma correction, lossless compression, progressive loading (although not really useful for textures), up to 48-bit colour, multiple CRC checks, and an open source implementation available in libpng.

Zengar
11-04-2003, 10:21 PM
PNG supports anything you like if you care about creating your own chunks. But it's not much more than a zip-pped tga.

mdog1234
11-05-2003, 04:31 AM
Cyranose, you must not play games. Any game that was only 600 megs would be a terrible game. Most games now are at least a gig. Plus with hard drives these days 600 megs is nothing. I can get a usb thumb drive with more space then that. I just installed a 6 gig game on my computer yesterday.

Ostsol
11-05-2003, 04:46 AM
I'm under the impression that massive installations can often be attributed to the developer simply not compressing any data, whether it be through compressed formats or compressed packages. Bitmaps and uncompressed .wav files are rediculous in retail products.

reubenhwk
11-05-2003, 09:00 AM
Here is my attempt at loading TIFF textures. Take a look if you have time. Comments appreciated. Thanks.
http://www.geocities.com/reubenhwk

[This message has been edited by reubenhwk (edited 11-05-2003).]

Cyranose
11-05-2003, 10:12 AM
Originally posted by mdog1234:
Cyranose, you must not play games. Any game that was only 600 megs would be a terrible game. Most games now are at least a gig. Plus with hard drives these days 600 megs is nothing. I can get a usb thumb drive with more space then that. I just installed a 6 gig game on my computer yesterday.

Funny. I don't measure the quality of my games by the size of their disk [usage].

I play lots of games but I try not to install the cut-scenes (often more than 1/2 the space). Still, when I look in the directories and see uncompressed targa files it makes me wince. Not only do I lose all that disk space but I have to wait for windows to load a million uncompressed files.

Avi

Mete Ciragan
11-06-2003, 11:56 AM
.dds is best in my opinion. tga and jpeg are good too. Lots of games use jpg, it doesn't really matter.

- Mete

MattS
11-07-2003, 03:45 AM
Originally posted by MichaelK:
Is there a way to decode JPEGs directly from memory? When using jpeglib we must provide FILE pointer to the image. So I have to write the memory chunk to tmpfile() and pass it to the jpeglib. So, do You know the trick to not use disk files?

Pozdrawiam,
Michal Krol

Yes this is possible to do.

You do this by setting the src (jpeg_source_mgr *) of the jpeg_decompress_struct struct. I did this by creating a struct which contained a jpeg_decompress_struct as the first variable. You can then add any other information in to your structure that you require. You can then provide your own methods to fill the buffer and so on. These will give you a j_decompress_ptr. Simply cast the src variable to your own data structure and fill the buffer (or whatever function is being called).

It is also possible to go go the other way and write a jpeg to memory which is similar just using different structures.

If this description is unclear I could try posting an example.

Hope this helps,

Matt

reccles
11-13-2003, 09:06 AM
If you would like to experiment yourself try using the DevIL libs.
http://openil.sourceforge.net/

These libs support a slew of formats including all of the ones discussed plus a few obscure ones. It also has an extension lib (i think its calk ilut) that can load textures into GL for your.


Yes, yes for the pure at heart nothing beats your own hand-crafted-assembly-uber-code. But for the origninal poster I suggest you imperically (sp?) test which texture you prefer. And as a bonus the DevIL libs can save as other formats if you find one that you like.

I've only begun to experiment with this lib and as it is open source if you don't think its running fast enough then help them out!

-R