[80] | 1 | /********************************************************************** <BR>
|
---|
| 2 | This file is part of Crack dot Com's free source code release of
|
---|
| 3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
| 4 | information about compiling & licensing issues visit this URL</a>
|
---|
| 5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
| 6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
| 7 | ***********************************************************************/
|
---|
| 8 |
|
---|
| 9 | #include "image/image.hh"
|
---|
| 10 | #include "file/file.hh"
|
---|
| 11 | #include "status/status.hh"
|
---|
| 12 | #include "loaders/jpg/jpeglib.h"
|
---|
| 13 |
|
---|
| 14 |
|
---|
| 15 | boolean i4_jpg_empty(j_compress_ptr cinfo);
|
---|
| 16 | void i4_jpg_null(j_compress_ptr cinfo) { }
|
---|
| 17 | void i4_jpg_fin(j_compress_ptr cinfo);
|
---|
| 18 |
|
---|
| 19 | enum { JPG_BUF_SIZE=10*1024 };
|
---|
| 20 |
|
---|
| 21 | struct i4_jpg_write_mgr : public jpeg_destination_mgr
|
---|
| 22 | {
|
---|
| 23 | w8 buf[JPG_BUF_SIZE];
|
---|
| 24 | int size;
|
---|
| 25 | i4_file_class *fp;
|
---|
| 26 |
|
---|
| 27 | i4_jpg_write_mgr(i4_file_class *fp) : fp(fp)
|
---|
| 28 | {
|
---|
| 29 | init_destination=i4_jpg_null;
|
---|
| 30 | empty_output_buffer=i4_jpg_empty;
|
---|
| 31 | term_destination=i4_jpg_fin;
|
---|
| 32 |
|
---|
| 33 | next_output_byte=(JOCTET *)buf;
|
---|
| 34 | free_in_buffer=JPG_BUF_SIZE;
|
---|
| 35 | }
|
---|
| 36 | } *i4_current_jpg_write_mgr;
|
---|
| 37 |
|
---|
| 38 | boolean i4_jpg_empty(j_compress_ptr cinfo)
|
---|
| 39 | {
|
---|
| 40 | i4_jpg_write_mgr *m=i4_current_jpg_write_mgr;
|
---|
| 41 |
|
---|
| 42 | int ws=JPG_BUF_SIZE;
|
---|
| 43 | i4_current_jpg_write_mgr->fp->write(m->buf, ws);
|
---|
| 44 |
|
---|
| 45 | m->size+=ws;
|
---|
| 46 | m->next_output_byte=(JOCTET *)i4_current_jpg_write_mgr->buf;
|
---|
| 47 | m->free_in_buffer=JPG_BUF_SIZE;
|
---|
| 48 |
|
---|
| 49 | return TRUE;
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 |
|
---|
| 53 | void i4_jpg_fin(j_compress_ptr cinfo)
|
---|
| 54 | {
|
---|
| 55 | i4_jpg_write_mgr *m=i4_current_jpg_write_mgr;
|
---|
| 56 | int ws=(w8 *)m->next_output_byte-m->buf;
|
---|
| 57 | i4_current_jpg_write_mgr->fp->write(m->buf, ws);
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | // return size of jpeg written
|
---|
| 61 | int i4_write_jpeg(i4_image_class *im,
|
---|
| 62 | i4_file_class *fp,
|
---|
| 63 | int quality, // 0..100
|
---|
| 64 | i4_status_class *status)
|
---|
| 65 | {
|
---|
| 66 | if (im->width()>4096)
|
---|
| 67 | return 0;
|
---|
| 68 |
|
---|
| 69 | /* This struct contains the JPEG compression parameters and pointers to
|
---|
| 70 | * working space (which is allocated as needed by the JPEG library).
|
---|
| 71 | * It is possible to have several such structures, representing multiple
|
---|
| 72 | * compression/decompression processes, in existence at once. We refer
|
---|
| 73 | * to any one struct (and its associated working data) as a "JPEG object".
|
---|
| 74 | */
|
---|
| 75 | struct jpeg_compress_struct cinfo;
|
---|
| 76 | /* This struct represents a JPEG error handler. It is declared separately
|
---|
| 77 | * because applications often want to supply a specialized error handler
|
---|
| 78 | * (see the second half of this file for an example). But here we just
|
---|
| 79 | * take the easy way out and use the standard error handler, which will
|
---|
| 80 | * print a message on stderr and call exit() if compression fails.
|
---|
| 81 | * Note that this struct must live as long as the main JPEG parameter
|
---|
| 82 | * struct, to avoid dangling-pointer problems.
|
---|
| 83 | */
|
---|
| 84 | struct jpeg_error_mgr jerr;
|
---|
| 85 | /* More stuff */
|
---|
| 86 |
|
---|
| 87 | /* Step 1: allocate and initialize JPEG compression object */
|
---|
| 88 |
|
---|
| 89 | /* We have to set up the error handler first, in case the initialization
|
---|
| 90 | * step fails. (Unlikely, but it could happen if you are out of memory.)
|
---|
| 91 | * This routine fills in the contents of struct jerr, and returns jerr's
|
---|
| 92 | * address which we place into the link field in cinfo.
|
---|
| 93 | */
|
---|
| 94 | cinfo.err = jpeg_std_error(&jerr);
|
---|
| 95 | /* Now we can initialize the JPEG compression object. */
|
---|
| 96 | jpeg_create_compress(&cinfo);
|
---|
| 97 |
|
---|
| 98 | /* Step 2: specify data destination (eg, a file) */
|
---|
| 99 | /* Note: steps 2 and 3 can be done in either order. */
|
---|
| 100 |
|
---|
| 101 |
|
---|
| 102 | i4_jpg_write_mgr write_mgr(fp);
|
---|
| 103 | i4_current_jpg_write_mgr=&write_mgr;
|
---|
| 104 |
|
---|
| 105 | cinfo.dest = &write_mgr;
|
---|
| 106 |
|
---|
| 107 |
|
---|
| 108 | /* Step 3: set parameters for compression */
|
---|
| 109 | /* First we supply a description of the input image.
|
---|
| 110 | * Four fields of the cinfo struct must be filled in:
|
---|
| 111 | */
|
---|
| 112 | cinfo.image_width = im->width(); /* image width and height, in pixels */
|
---|
| 113 | cinfo.image_height = im->height();
|
---|
| 114 | cinfo.input_components = 3; /* # of color components per pixel */
|
---|
| 115 | cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
---|
| 116 | /* Now use the library's routine to set default compression parameters.
|
---|
| 117 | * (You must set at least cinfo.in_color_space before calling this,
|
---|
| 118 | * since the defaults depend on the source color space.)
|
---|
| 119 | */
|
---|
| 120 | jpeg_set_defaults(&cinfo);
|
---|
| 121 | /* Now you can set any non-default parameters you wish to.
|
---|
| 122 | * Here we just illustrate the use of quality (quantization table) scaling:
|
---|
| 123 | */
|
---|
| 124 | jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
|
---|
| 125 |
|
---|
| 126 | /* Step 4: Start compressor */
|
---|
| 127 |
|
---|
| 128 | /* TRUE ensures that we will write a complete interchange-JPEG file.
|
---|
| 129 | * Pass TRUE unless you are very sure of what you're doing.
|
---|
| 130 | */
|
---|
| 131 | jpeg_start_compress(&cinfo, TRUE);
|
---|
| 132 |
|
---|
| 133 | /* Step 5: while (scan lines remain to be written) */
|
---|
| 134 | /* jpeg_write_scanlines(...); */
|
---|
| 135 |
|
---|
| 136 |
|
---|
| 137 | w8 buf[4096*3];
|
---|
| 138 |
|
---|
| 139 | int im_w=im->width();
|
---|
| 140 |
|
---|
| 141 | while (cinfo.next_scanline < cinfo.image_height)
|
---|
| 142 | {
|
---|
| 143 | if (status)
|
---|
| 144 | status->update((float)cinfo.next_scanline/cinfo.image_height);
|
---|
| 145 |
|
---|
| 146 | JSAMPROW scanline[1]={buf};
|
---|
| 147 | w8 *c=buf;
|
---|
| 148 |
|
---|
| 149 | for (int x=0; x<im_w; x++)
|
---|
| 150 | {
|
---|
| 151 | i4_color color=im->get_pixel(x, cinfo.next_scanline);
|
---|
| 152 | c[0]=(color>>16)&0xff;
|
---|
| 153 | c[1]=(color>>8)&0xff;
|
---|
| 154 | c[2]=(color)&0xff;
|
---|
| 155 | c+=3;
|
---|
| 156 | }
|
---|
| 157 | jpeg_write_scanlines(&cinfo, scanline, 1);
|
---|
| 158 | }
|
---|
| 159 |
|
---|
| 160 | /* Step 6: Finish compression */
|
---|
| 161 |
|
---|
| 162 | jpeg_finish_compress(&cinfo);
|
---|
| 163 |
|
---|
| 164 | /* Step 7: release JPEG compression object */
|
---|
| 165 |
|
---|
| 166 | /* This is an important step since it will release a good deal of memory. */
|
---|
| 167 | jpeg_destroy_compress(&cinfo);
|
---|
| 168 |
|
---|
| 169 |
|
---|
| 170 | return write_mgr.size;
|
---|
| 171 | /* And we're done! */
|
---|
| 172 | }
|
---|