On 10/20/2009 10:02 PM, D. Zimmer wrote:
>>> On 10/19/2009 11:16 PM, D. Zimmer wrote:
>>>>>> Hello all,
>>>>>>
>>>>>> probably this has come up before, but I can't find it:
>>>>>>
>>>>>> my application has to display JPEG images, but does not load
>>>>>> them from disk files. They come in as blobs from a remote database.
>>>>>>
>>>>>> Is there a way to load these into an Fl_JPEG_image?
>>>>>>
>>>>>> Right now I am reduced to writing them to a temp file, and then reading 
>>>>>> that into the image. But that is a bad solution: it assumes that I can 
>>>>>> write to disk in this application.
>>>>>>
>>>>>> I read the code (fltk 1.1.9), there doesn't seem to be a straightforward 
>>>>>> way, can't just hook up an istream, or something of that nature.
>>>>>>
>>>>>> Any advice?
>>>>>>
>>>>>>
>>>>>
>>>>> I expect you will have to modify Fl_JPEG_Image.  FLTK 1.1.9 has 
>>>>> Fl_JPEG_Image(const char *jpeg) which is hard-coded to expect a filename. 
>>>>>  Write a new constructor that takes your blob of JPEG data instead, and 
>>>>> base it on the existing code from Fl_JPEG_Image.
>>>>>
>>>>> I'm pretty sure this can be done, and I think you will need to make the 
>>>>> following changes:
>>>>>
>>>>> 1. get rid of references to the FILE pointer in the function 
>>>>> (declaration, fopen(), flose()).
>>>>>
>>>>> 2. replace the call to jpeg_stdio_src() with code to fill the 
>>>>> jpeg_decompress_struct with function pointers that will operate on your 
>>>>> blob of JPEG data rather than a FILE pointer.
>>>>>
>>>>> I've never done it, but I expect you should be able to find examples on 
>>>>> the internet... if not, how hard could it be (memcpy(), current position 
>>>>> pointer, etc.)?  If you download the actual jpeglib full source, the file 
>>>>> djpeg.c provides function pointers for setting up the library to handle 
>>>>> FILE pointer streams... work from that.
>>>>>
>>>>> You're probably in for a a few hours coding and testing though.
>>>>>
>>>>> good luck,
>>>>> Don.
>>>>>
>>>>>
>>>>>
>>>>
>>>> sorry, not djpeg.c but jdatasrc.c, which is part of the jpeg library 
>>>> included with FLTK.
>>>>
>>>
>>> Thanks Don,
>>>
>>> Yes I saw that. On first reading, it seems that jdatasrc.c needs to be
>>> modified in maybe 2 lines of code. Where the data come from doesn't
>>> seem to make much difference, except for 2 calls to read(). But I'll try
>>> that in the day :)
>>>
>>> Probably I will make a new class, parallel to Fl_JPEG_image.
>>> FL_JPEG_image only provides a constructor (at least in 1.1.9), nothing
>>> else. That's reasonably clean. The uglier part is ending up with
>>> something new that is more part of jpeglib than of fltk. Which is
>>> probably why this hasn't been done yet, at least in public.
>>>
>>>
>>> Bernd
>>>
>>>
>>>
>>
>> I wouldn't think that the library would need to be changed... I think the 
>> library allows you to do what you want to achieve, as-is.  I meant to use 
>> jdatasrc.c as a possible quide for your class.
>>
>> Don.
>>
>> Here is a quick modfication of code from jdatasrc.c, that you would add to 
>> your modified class, then just call jpeg_blob_src() in place of 
>> jpeg_stdio_src() in the constructor... never tested or compiled, or really 
>> thought out for that matter.
>>
>> // most comments striped
>> #include "jinclude.h"
>> #include "jpeglib.h"
>> #include "jerror.h"
>>
>> typedef struct {
>>    struct jpeg_source_mgr pub;       /* public fields */
>>    void *blob;                 /* address of blob */
>>    size_t size;                    /* size into blob */
>>    size_t pos;                     /* index into blob */
>>    JOCTET * buffer;          /* start of buffer */
>>    boolean start_of_file;    /* have we gotten any data yet? */
>> } my_source_mgr;
>>
>> typedef my_source_mgr * my_src_ptr;
>>
>> #define INPUT_BUF_SIZE  4096 /* choose an efficiently fread'able size */
>>
>> static void init_source (j_decompress_ptr cinfo)
>> {
>>    my_src_ptr src = (my_src_ptr) cinfo->src;
>>    src->start_of_file = TRUE;
>> }
>>
>> static boolean fill_input_buffer (j_decompress_ptr cinfo)
>> {
>>    my_src_ptr src = (my_src_ptr) cinfo->src;
>>    size_t nbytes;
>>
>>    nbytes = MAX(src->size - src->pos, INPUT_BUF_SIZE);
>>    src->size -= nbytes;
>>
>>    if (nbytes<= 0) {
>>      if (src->start_of_file) /* Treat empty input file as fatal error */
>>        ERREXIT(cinfo, JERR_INPUT_EMPTY);
>>      WARNMS(cinfo, JWRN_JPEG_EOF);
>>      /* Insert a fake EOI marker */
>>      src->buffer[0] = (JOCTET) 0xFF;
>>      src->buffer[1] = (JOCTET) JPEG_EOI;
>>      nbytes = 2;
>>    }
>>
>>    src->pub.next_input_byte = src->buffer;
>>    src->pub.bytes_in_buffer = nbytes;
>>    src->start_of_file = FALSE;
>>
>>    return TRUE;
>> }
>>
>>
>> static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
>> {
>>    my_src_ptr src = (my_src_ptr) cinfo->src;
>>
>>    if (num_bytes>  0) {
>>      while (num_bytes>  (long) src->pub.bytes_in_buffer) {
>>        num_bytes -= (long) src->pub.bytes_in_buffer;
>>        (void) fill_input_buffer(cinfo);
>>        /* note we assume that fill_input_buffer will never return FALSE,
>>         * so suspension need not be handled.
>>         */
>>      }
>>      src->pub.next_input_byte += (size_t) num_bytes;
>>      src->pub.bytes_in_buffer -= (size_t) num_bytes;
>>    }
>> }
>>
>>
>> static void term_source (j_decompress_ptr cinfo)
>> {
>>    /* no work necessary here */
>> }
>>
>>
>> extern void jpeg_blob_src (j_decompress_ptr cinfo, void *blob, size_t size)
>> {
>>    my_src_ptr src;
>>
>>    if (cinfo->src == NULL) { /* first time for this JPEG object? */
>>      cinfo->src = (struct jpeg_source_mgr *)
>>        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
>>                                SIZEOF(my_source_mgr));
>>      src = (my_src_ptr) cinfo->src;
>>      src->buffer = (JOCTET *)
>>        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
>>                                INPUT_BUF_SIZE * SIZEOF(JOCTET));
>>    }
>>
>>    src = (my_src_ptr) cinfo->src;
>>    src->pub.init_source = init_source;
>>    src->pub.fill_input_buffer = fill_input_buffer;
>>    src->pub.skip_input_data = skip_input_data;
>>    src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default 
>> method */
>>    src->pub.term_source = term_source;
>>    src->blob = blob;
>>    src->size = size;
>>    src->pos = 0;
>>    src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
>>    src->pub.next_input_byte = NULL; /* until buffer loaded */
>> }
>>
>>
>>
>>
> oops:
>
>    nbytes = MAX(src->size - src->pos, INPUT_BUF_SIZE);
>    //src->size -= nbytes;
>    src->pos += nbytes;
>
>
>
>
>
Thanks,

I did basically the same, except I packaged the blob pointer and length 
in a struct.  It is true that strictly speaking the setup function for 
the data source is not part of jpeglib. But for purposes of linking, it 
might as well be, have to make sure that the versions match precisely.
And of course they assume that FILE is defined, without including 
stdio.h, a very common feature.

So I ended up making my own Blob_Image class, which does nothing more 
than decompress into an Fl_RGB_Image. Then I don't have to care what the 
rest of the code does with it. Now to get this version to run in Windows...

Thanks again folks,

Bernd


_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to