On 10/20/2009 10:35 PM, Bernd Stramm wrote:
> 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
>
>

To summarize:

I made that small modification, feeding the char array to the 
decompression front end routines of jpeglib. So far so good.

A resulting problem was that a version disagreement came up between
what I used (jpeglib V7), what was on my system (6.something), and
what was in the FLTK jpeg libraries (6.something else). This got worse
on Windows. Plus if anyone else ever tries to integrate my code
the same thing will come up again.

So I finally gave up, packaged about 50% of jpeglib (the decompression
part) in C++ and include the whole thing in my code. Packaging it
in C++ allows me to separate from the polluted namespace.

If anyone wants it, the resulting decompression stuff is
part of what is in

www.bernd-stramm.com/miniscsim.php  (follow to the satview pages)
and in
www.github.com/berndhs/satview/dcomp

there is other FLTK stuff in there, basic things with a bunch
of buttons in a control window, and a separate image view window.


Bernd

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

Reply via email to