Loading Textures from JPEGs

How do I use jpeglib.h to load textures from a .jpeg or .jpg image?

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

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.

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).]

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

well assuming that jpegs made good textures, does anybody have any experience using jpeglib.h?

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

Jan

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…)

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).]

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

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).]

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.

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

What is YOUR prefered file format to load textures from and why? What format do you dislike and why?

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.

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.

What are the pros and cons for TIFF?

TARGA rulez

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

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

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).]

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.