load jpg from memory
Hello ppl.
I have a simple question to make.
I know how to load jpg images from files, but, I need to load them from memory instead. Any help?
How are you loading them from file? Most image loaders have support for loading from memory.
I am using the jpeg sdk and I'm not using any image loader like devIL or direct3DX. In fact, I'm developing my own image loader for my engine.
template<typename T>inline void SWAP(T& a, T& b){ T t = a; a = b; b = t;}struct tImage{ int channels; int sizeX; int sizeY; unsigned char *data;};GLuint LoadTextureJPG(const char* path){ struct jpeg_decompress_struct cinfo; tImage pImageData; FILE *pFile; //carregar imagem pFile = fopen(path, "rb"); if(!pFile)return 0; jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, pFile); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); pImageData.channels = cinfo.num_components; pImageData.sizeX = cinfo.image_width; pImageData.sizeY = cinfo.image_height; int rowSpan = cinfo.image_width * cinfo.num_components; pImageData.data = ((unsigned char*)malloc(sizeof(unsigned char)*rowSpan*pImageData.sizeY)); unsigned char** rowPtr = new unsigned char*[pImageData.sizeY]; for (int i = 0; i < pImageData.sizeY; i++) rowPtr = &(pImageData.data);<br> <span class="cpp-keyword">int</span> rowsRead = <span class="cpp-number">0</span>;<br> <span class="cpp-keyword">while</span> (cinfo.output_scanline &lt; cinfo.output_height)<br> rowsRead += jpeg_read_scanlines(&cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead);<br> <span class="cpp-keyword">delete</span> [] rowPtr;<br><br> jpeg_finish_decompress(&cinfo);<br> jpeg_destroy_decompress(&cinfo);<br> fclose(pFile);<br><br><span class="cpp-comment">/* for(int y=0; y &lt; pImageData.sizeY/2; y++){<br> for(int x=0; x &lt; pImageData.sizeX; x++){<br> int y1 = y;<br> int y2 = pImageData.sizeY - y - 1;<br> SWAP(pImageData.data[(x+y2*pImageData.sizeX)*3+0], pImageData.data[(x+y1*pImageData.sizeX)*3+0]);<br> SWAP(pImageData.data[(x+y2*pImageData.sizeX)*3+1], pImageData.data[(x+y1*pImageData.sizeX)*3+1]);<br> SWAP(pImageData.data[(x+y2*pImageData.sizeX)*3+2], pImageData.data[(x+y1*pImageData.sizeX)*3+2]);<br> }<br> }*/</span><br><br> <span class="cpp-comment">//criar textura</span><br> GLuint tex;<br> glGenTextures(<span class="cpp-number">1</span>, &tex);<br> glPixelStorei (GL_UNPACK_ALIGNMENT, <span class="cpp-number">1</span>);<br> glBindTexture(GL_TEXTURE_2D, tex);<br> <span class="cpp-keyword">int</span> textureType = GL_RGB;<br> gluBuild2DMipmaps(GL_TEXTURE_2D, pImageData.channels, pImageData.sizeX, pImageData.sizeY, textureType, GL_UNSIGNED_BYTE, pImageData.data);<br> glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);<br> glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);<br> <span class="cpp-keyword">return</span> tex;<br>}<br><br></pre></div><!–ENDSCRIPT–><br>This code was not taken in my engine since I did not implemented for it yet. It was taken from other application done by me that was using openGL. What I want to do is to copy this code to my engine to use in my own texture interface (thatis API independent). I need to load from memory and not from a file to be able to me more flexible. I'm thincking to integrate a file packer in my engine and I want to support loading from memory, form the package or from a file directly and the better way to do this is to load them all by memory. This way I only need to open the entire file to the memory and then load the texture.<br><br>But as you can see, the data source in this case is only a FILE* and I want it to read from a const char* ou from a void*.<br><br>Any help?
Got some full code for this, but it's infested with code for streaming and distributed work so I'll just give you the important bits:
There's info on how this works in the JPEG "SDK" as you called it, look for a txt-file called libjpeg.doc.gz or similar. I could've missed a few things so you better get hold of that doc and compare :)
/* Whatever floats your boat */#define JPEG_BUFFER_SIZE (8 << 10)static char jpegBuffer[JPEG_BUFFER_SIZE];typedef struct { struct jpeg_source_mgr pub; /* I call this 'file' even though it's in memory */ objptr file;} JPEGSource;static void init_sourceFunc(j_decompress_ptr cinfo) { ((JPEGSource*)cinfo->src)->pub.bytes_in_buffer = 0;}static boolean fill_input_bufferFunc(j_decompress_ptr cinfo) { JPEGSource *src = (JPEGSource*)cinfo->src; /* "somehow" is obviously your way of reading data from some source (you could just point jpegBuffer to the proper place I guess) */ somehow_read(jpegBuffer, JPEG_BUFFER_SIZE, src->file); src->pub.next_input_byte = jpegBuffer; src->pub.bytes_in_buffer = JPEG_BUFFER_SIZE; return TRUE;}void skip_input_dataFunc(j_decompress_ptr cinfo, long num_bytes) { JPEGSource *src = (JPEGSource*)cinfo->src; if (num_bytes > 0) { somehow_seek(src->file, FILE_SEEK_CUR, num_bytes); if (num_bytes > src->pub.bytes_in_buffer) src->pub.bytes_in_buffer = 0; else { src->pub.next_input_byte += num_bytes; src->pub.bytes_in_buffer -= num_bytes; } }}void term_sourceFunc(j_decompress_ptr cinfo) {}static JPEGSource jpegSource = { .pub.init_source = init_sourceFunc, .pub.fill_input_buffer = fill_input_bufferFunc, .pub.skip_input_data = skip_input_dataFunc, .pub.resync_to_restart = jpeg_resync_to_restart, .pub.term_source = term_sourceFunc };int jpeg_loader_thingy() { ... jpegInfo.src = (struct jpeg_source_mgr*)&jpegSource; jpegSource.file = file; jpegSource.pub.next_input_byte = NULL; jpegSource.pub.bytes_in_buffer = 0; ... the usual stuff return ret_code;}
There's info on how this works in the JPEG "SDK" as you called it, look for a txt-file called libjpeg.doc.gz or similar. I could've missed a few things so you better get hold of that doc and compare :)
thank you
I have tried that code but I had some problems. I have adapted your code to mine and I have got this:
I have tried that code but I had some problems. I have adapted your code to mine and I have got this:
#include "jpeglib.h"#pragma comment (lib, "jpeg.lib")void somehow_read(char* buffer, int maxSize){ FILE* file = fopen("teste.jpg", "rb"); fseek(file, SEEK_END, 0); long s = ftell(file); fseek(file, SEEK_SET, 0); fread(buffer, 1, s, file); fclose(file);}struct tImage{ int channels; int sizeX; int sizeY; unsigned char *data;};/* Whatever floats your boat */#define JPEG_BUFFER_SIZE (8 << 10)static char jpegBuffer[JPEG_BUFFER_SIZE];typedef struct { struct jpeg_source_mgr pub; /* I call this 'file' even though it's in memory */// objptr file;} JPEGSource;static void init_sourceFunc(j_decompress_ptr cinfo) { ((JPEGSource*)cinfo->src)->pub.bytes_in_buffer = 0;}static boolean fill_input_bufferFunc(j_decompress_ptr cinfo) { JPEGSource *src = (JPEGSource*)cinfo->src; /* "somehow" is obviously your way of reading data from some source (you could just point jpegBuffer to the proper place I guess) */ somehow_read(jpegBuffer, JPEG_BUFFER_SIZE /*, src->file*/); src->pub.next_input_byte = (const unsigned char*)jpegBuffer; src->pub.bytes_in_buffer = JPEG_BUFFER_SIZE; return TRUE;}void skip_input_dataFunc(j_decompress_ptr cinfo, long num_bytes) { JPEGSource *src = (JPEGSource*)cinfo->src; if (num_bytes > 0) {// somehow_seek(src->file, FILE_SEEK_CUR, num_bytes); if (num_bytes > src->pub.bytes_in_buffer) src->pub.bytes_in_buffer = 0; else { src->pub.next_input_byte += num_bytes; src->pub.bytes_in_buffer -= num_bytes; } }}void term_sourceFunc(j_decompress_ptr cinfo) {}static JPEGSource jpegSource;int jpeg_loader_thingy() { struct jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpegSource.pub.init_source = init_sourceFunc; jpegSource.pub.fill_input_buffer = fill_input_bufferFunc; jpegSource.pub.skip_input_data = skip_input_dataFunc; jpegSource.pub.resync_to_restart = jpeg_resync_to_restart; jpegSource.pub.term_source = term_sourceFunc; jpegSource.pub.next_input_byte = NULL; jpegSource.pub.bytes_in_buffer = 0; cinfo.src = (struct jpeg_source_mgr*)&jpegSource; tImage pImageData; jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); pImageData.channels = cinfo.num_components; pImageData.sizeX = cinfo.image_width; pImageData.sizeY = cinfo.image_height; int rowSpan = cinfo.image_width * cinfo.num_components; pImageData.data = ((unsigned char*)malloc(sizeof(unsigned char)*rowSpan*pImageData.sizeY)); unsigned char** rowPtr = new unsigned char*[pImageData.sizeY]; for (int i = 0; i < pImageData.sizeY; i++) rowPtr = &(pImageData.data);<br> <span class="cpp-keyword">int</span> rowsRead = <span class="cpp-number">0</span>;<br> <span class="cpp-keyword">while</span> (cinfo.output_scanline < cinfo.output_height)<br> rowsRead += jpeg_read_scanlines(&cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead);<br> <span class="cpp-keyword">delete</span> [] rowPtr;<br> jpeg_finish_decompress(&cinfo);<br> jpeg_destroy_decompress(&cinfo);<br><br> <span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;<br>}<br><br><br><br><span class="cpp-keyword">int</span> main(){<br> jpeg_loader_thingy();<br><br> <span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br></pre></div><!–ENDSCRIPT–><br><br>But this do not work preperly. The function 'fill_input_bufferFunc' is never called and when I pass the function 'jpeg_read_header(&cinfo, TRUE);' no data is filled in the image_width and height. The program then exists with code 1 in the 'jpeg_start_decompress(&cinfo);'. Any help?
Your code seemed to work for me (I ran it with no image and it crashed and gdb told me 'fill_input_bufferFunc' was called), but you had some rather risky things in there so here's my take on it:
#include <stdlib.h>#include <stdio.h>#include "jpeglib.h"#define JPEG_BUFFER_SIZE (8 << 10)static char jpegBuffer[JPEG_BUFFER_SIZE];static FILE *src;static int srcLen;int source_init(const char *filename) { src = fopen(filename, "rb"); if (src == NULL) return 0; fseek(src, 0, SEEK_END); srcLen = ftell(src); fseek(src, 0, SEEK_SET); return 1;}void source_close() { fclose(src);}int source_read(char* buffer) { int len = JPEG_BUFFER_SIZE; if (len > srcLen) len = srcLen; srcLen -= len; fread(buffer, len, 1, src); return len;}void source_seek(int num) { fseek(src, num, SEEK_CUR);}struct tImage{ int channels; int sizeX; int sizeY; unsigned char *data;};/* Slick... */typedef struct { struct jpeg_source_mgr pub;} JPEGSource;static void init_sourceFunc(j_decompress_ptr cinfo) { ((JPEGSource*)cinfo->src)->pub.bytes_in_buffer = 0;}static boolean fill_input_bufferFunc(j_decompress_ptr cinfo) { JPEGSource *src = (JPEGSource*)cinfo->src; src->pub.bytes_in_buffer = source_read(jpegBuffer); src->pub.next_input_byte = (const unsigned char*)jpegBuffer; return TRUE;}void skip_input_dataFunc(j_decompress_ptr cinfo, long num_bytes) { JPEGSource *src = (JPEGSource*)cinfo->src; if (num_bytes > 0) { source_seek(num_bytes); if (num_bytes > src->pub.bytes_in_buffer) src->pub.bytes_in_buffer = 0; else { src->pub.next_input_byte += num_bytes; src->pub.bytes_in_buffer -= num_bytes; } }}void term_sourceFunc(j_decompress_ptr cinfo) {}static JPEGSource jpegSource;int jpeg_loader_thingy() { struct jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; if (!source_init("tjof.jpg")) return 0; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpegSource.pub.init_source = init_sourceFunc; jpegSource.pub.fill_input_buffer = fill_input_bufferFunc; jpegSource.pub.skip_input_data = skip_input_dataFunc; jpegSource.pub.resync_to_restart = jpeg_resync_to_restart; jpegSource.pub.term_source = term_sourceFunc; jpegSource.pub.next_input_byte = NULL; jpegSource.pub.bytes_in_buffer = 0; cinfo.src = (struct jpeg_source_mgr*)&jpegSource; tImage pImageData; jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); pImageData.channels = cinfo.num_components; pImageData.sizeX = cinfo.image_width; pImageData.sizeY = cinfo.image_height; printf("%d %d\n", pImageData.sizeX, pImageData.sizeY); int rowSpan = cinfo.image_width * cinfo.num_components; pImageData.data = ((unsigned char*)malloc(sizeof(unsigned char)*rowSpan*pImageData.sizeY)); unsigned char** rowPtr = new unsigned char*[pImageData.sizeY]; for (int i = 0; i < pImageData.sizeY; i++) rowPtr = &(pImageData.data);<br> <span class="cpp-keyword">int</span> rowsRead = <span class="cpp-number">0</span>;<br> <span class="cpp-keyword">while</span> (cinfo.output_scanline < cinfo.output_height)<br> rowsRead += jpeg_read_scanlines(&cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead);<br> <span class="cpp-keyword">delete</span> [] rowPtr;<br> free(pImageData.data);<br> jpeg_finish_decompress(&cinfo);<br> jpeg_destroy_decompress(&cinfo);<br><br> source_close();<br><br> <span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;<br>}<br><br><br><br><span class="cpp-keyword">int</span> main(){<br> printf(<span class="cpp-literal">"%d\n"</span>, jpeg_loader_thingy());<br><br> <span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;<br>}<br><br></pre></div><!–ENDSCRIPT–><br><br>Probably not fool-proof, just some minute-scale addendums. I threw in a "source-module" near the top which could act as any source for your data later on. I tried with one image and it reported the proper dimensions, didn't bother to see what was loaded though.<br><br>I would strongly advice you to read libjpeg.doc.gz about the JPEG buffer-thingy, it's simply a middle-hand between the source data and the JPEG library and it must be continuously filled until the file ends.<br><br>And I do hope you plan on replacing the error-handlers [smile]
I have used the code you posted as is and it didn't worked :(
Its strange because I thinck it should work right now.
Its strange because I thinck it should work right now.
Have you read libjpeg.doc.gz yet?
A little more information from some debugging-efforts would be helpful too. Considering the pragma-lib thingies you had first, it looks as if you're using vc++ which I don't so I can't test the sample in your place.
A little more information from some debugging-efforts would be helpful too. Considering the pragma-lib thingies you had first, it looks as if you're using vc++ which I don't so I can't test the sample in your place.
I would use boutell.com's gd library:
http://www.boutell.com/gd/manual2.0.33.html
I used it today, and it works great. I'm quite pleased.
By the way, you want this function:
gdImageCreateFromJpegPtr(int size, void *data) (FUNCTION)
Mike C.
http://www.coolgroups.com/zoomer
http://www.boutell.com/gd/manual2.0.33.html
I used it today, and it works great. I'm quite pleased.
By the way, you want this function:
gdImageCreateFromJpegPtr(int size, void *data) (FUNCTION)
Mike C.
http://www.coolgroups.com/zoomer
As I remember it, the jpeg library from Independent JPEG Group has no functions
for loading jpegs from memory, just from file. You might have to hack the function
called fill_input_buffer() in jdatasrc.c to get it to work.
You might do better with the jpeg library from Intel if you want a straight-forward
approach.
for loading jpegs from memory, just from file. You might have to hack the function
called fill_input_buffer() in jdatasrc.c to get it to work.
You might do better with the jpeg library from Intel if you want a straight-forward
approach.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement