]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - jpeg.c
reworked newmouseparms[] code
[xonotic/darkplaces.git] / jpeg.c
1 /*
2         Copyright (C) 2002  Mathieu Olivier
3
4         This program is free software; you can redistribute it and/or
5         modify it under the terms of the GNU General Public License
6         as published by the Free Software Foundation; either version 2
7         of the License, or (at your option) any later version.
8
9         This program is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13         See the GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to:
17
18                 Free Software Foundation, Inc.
19                 59 Temple Place - Suite 330
20                 Boston, MA  02111-1307, USA
21
22 */
23
24
25 #include "quakedef.h"
26 #include "image.h"
27 #include "jpeg.h"
28
29
30 /*
31 =================================================================
32
33   Minimal set of definitions from the JPEG lib
34
35   WARNING: for a matter of simplicity, several pointer types are
36   casted to "void*", and most enumerated values are not included
37
38 =================================================================
39 */
40
41 // jboolean is unsigned char instead of int on Win32
42 #ifdef WIN32
43 typedef unsigned char jboolean;
44 #else
45 typedef int jboolean;
46 #endif
47
48 #define JPEG_LIB_VERSION  62  // Version 6b
49
50 typedef void *j_common_ptr;
51 typedef struct jpeg_compress_struct *j_compress_ptr;
52 typedef struct jpeg_decompress_struct *j_decompress_ptr;
53 typedef enum
54 {
55         JCS_UNKNOWN,
56         JCS_GRAYSCALE,
57         JCS_RGB,
58         JCS_YCbCr,
59         JCS_CMYK,
60         JCS_YCCK
61 } J_COLOR_SPACE;
62 typedef enum {JPEG_DUMMY1} J_DCT_METHOD;
63 typedef enum {JPEG_DUMMY2} J_DITHER_MODE;
64 typedef unsigned int JDIMENSION;
65
66 #define JPOOL_PERMANENT 0       // lasts until master record is destroyed
67 #define JPOOL_IMAGE             1       // lasts until done with image/datastream
68
69 #define JPEG_EOI        0xD9  // EOI marker code
70
71 #define JMSG_STR_PARM_MAX  80
72
73 #define DCTSIZE2 64
74 #define NUM_QUANT_TBLS 4
75 #define NUM_HUFF_TBLS 4
76 #define NUM_ARITH_TBLS 16
77 #define MAX_COMPS_IN_SCAN 4
78 #define C_MAX_BLOCKS_IN_MCU 10
79 #define D_MAX_BLOCKS_IN_MCU 10
80
81 struct jpeg_memory_mgr
82 {
83   void* (*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject);
84   void (*alloc_large) ();
85   void (*alloc_sarray) ();
86   void (*alloc_barray) ();
87   void (*request_virt_sarray) ();
88   void (*request_virt_barray) ();
89   void (*realize_virt_arrays) ();
90   void (*access_virt_sarray) ();
91   void (*access_virt_barray) ();
92   void (*free_pool) ();
93   void (*self_destruct) ();
94
95   long max_memory_to_use;
96   long max_alloc_chunk;
97 };
98
99 struct jpeg_error_mgr
100 {
101         void (*error_exit) (j_common_ptr cinfo);
102         void (*emit_message) (j_common_ptr cinfo, int msg_level);
103         void (*output_message) (j_common_ptr cinfo);
104         void (*format_message) (j_common_ptr cinfo, char * buffer);
105         void (*reset_error_mgr) (j_common_ptr cinfo);
106         int msg_code;
107         union {
108                 int i[8];
109                 char s[JMSG_STR_PARM_MAX];
110         } msg_parm;
111         int trace_level;
112         long num_warnings;
113         const char * const * jpeg_message_table;
114         int last_jpeg_message;
115         const char * const * addon_message_table;
116         int first_addon_message;
117         int last_addon_message;
118 };
119
120 struct jpeg_source_mgr
121 {
122         const unsigned char *next_input_byte;
123         size_t bytes_in_buffer;
124
125         void (*init_source) (j_decompress_ptr cinfo);
126         jboolean (*fill_input_buffer) (j_decompress_ptr cinfo);
127         void (*skip_input_data) (j_decompress_ptr cinfo, long num_bytes);
128         jboolean (*resync_to_restart) (j_decompress_ptr cinfo, int desired);
129         void (*term_source) (j_decompress_ptr cinfo);
130 };
131
132 struct jpeg_decompress_struct
133 {
134         struct jpeg_error_mgr *err;             // USED
135         struct jpeg_memory_mgr *mem;    // USED
136
137         void *progress;
138         void *client_data;
139         jboolean is_decompressor;
140         int global_state;
141
142         struct jpeg_source_mgr *src;    // USED
143         JDIMENSION image_width;                 // USED
144         JDIMENSION image_height;                // USED
145
146         int num_components;
147         J_COLOR_SPACE jpeg_color_space;
148         J_COLOR_SPACE out_color_space;
149         unsigned int scale_num, scale_denom;
150         double output_gamma;
151         jboolean buffered_image;
152         jboolean raw_data_out;
153         J_DCT_METHOD dct_method;
154         jboolean do_fancy_upsampling;
155         jboolean do_block_smoothing;
156         jboolean quantize_colors;
157         J_DITHER_MODE dither_mode;
158         jboolean two_pass_quantize;
159         int desired_number_of_colors;
160         jboolean enable_1pass_quant;
161         jboolean enable_external_quant;
162         jboolean enable_2pass_quant;
163         JDIMENSION output_width;
164
165         JDIMENSION output_height;       // USED
166
167         int out_color_components;
168
169         int output_components;          // USED
170
171         int rec_outbuf_height;
172         int actual_number_of_colors;
173         void *colormap;
174
175         JDIMENSION output_scanline;     // USED
176
177         int input_scan_number;
178         JDIMENSION input_iMCU_row;
179         int output_scan_number;
180         JDIMENSION output_iMCU_row;
181         int (*coef_bits)[DCTSIZE2];
182         void *quant_tbl_ptrs[NUM_QUANT_TBLS];
183         void *dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
184         void *ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
185         int data_precision;
186         void *comp_info;
187         jboolean progressive_mode;
188         jboolean arith_code;
189         unsigned char arith_dc_L[NUM_ARITH_TBLS];
190         unsigned char arith_dc_U[NUM_ARITH_TBLS];
191         unsigned char arith_ac_K[NUM_ARITH_TBLS];
192         unsigned int restart_interval;
193         jboolean saw_JFIF_marker;
194         unsigned char JFIF_major_version;
195         unsigned char JFIF_minor_version;
196         unsigned char density_unit;
197         unsigned short X_density;
198         unsigned short Y_density;
199         jboolean saw_Adobe_marker;
200         unsigned char Adobe_transform;
201         jboolean CCIR601_sampling;
202         void *marker_list;
203         int max_h_samp_factor;
204         int max_v_samp_factor;
205         int min_DCT_scaled_size;
206         JDIMENSION total_iMCU_rows;
207         void *sample_range_limit;
208         int comps_in_scan;
209         void *cur_comp_info[MAX_COMPS_IN_SCAN];
210         JDIMENSION MCUs_per_row;
211         JDIMENSION MCU_rows_in_scan;
212         int blocks_in_MCU;
213         int MCU_membership[D_MAX_BLOCKS_IN_MCU];
214         int Ss, Se, Ah, Al;
215         int unread_marker;
216         void *master;
217         void *main;
218         void *coef;
219         void *post;
220         void *inputctl;
221         void *marker;
222         void *entropy;
223         void *idct;
224         void *upsample;
225         void *cconvert;
226         void *cquantize;
227 };
228
229
230 struct jpeg_compress_struct
231 {
232         struct jpeg_error_mgr *err;
233         struct jpeg_memory_mgr *mem;
234         void *progress;
235         void *client_data;
236         jboolean is_decompressor;
237         int global_state;
238
239         void *dest;
240         JDIMENSION image_width;
241         JDIMENSION image_height;
242         int input_components;
243         J_COLOR_SPACE in_color_space;
244         double input_gamma;
245         int data_precision;
246
247         int num_components;
248         J_COLOR_SPACE jpeg_color_space;
249         void *comp_info;
250         void *quant_tbl_ptrs[NUM_QUANT_TBLS];
251         void *dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
252         void *ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
253         unsigned char arith_dc_L[NUM_ARITH_TBLS];
254         unsigned char arith_dc_U[NUM_ARITH_TBLS];
255         unsigned char arith_ac_K[NUM_ARITH_TBLS];
256
257         int num_scans;
258         const void *scan_info;
259         jboolean raw_data_in;
260         jboolean arith_code;
261         jboolean optimize_coding;
262         jboolean CCIR601_sampling;
263         int smoothing_factor;
264         J_DCT_METHOD dct_method;
265
266         unsigned int restart_interval;
267         int restart_in_rows;
268
269         jboolean write_JFIF_header;
270         unsigned char JFIF_major_version;
271         unsigned char JFIF_minor_version;
272         unsigned char density_unit;
273         unsigned short X_density;
274         unsigned short Y_density;
275         jboolean write_Adobe_marker;
276         JDIMENSION next_scanline;
277
278         jboolean progressive_mode;
279         int max_h_samp_factor;
280         int max_v_samp_factor;
281         JDIMENSION total_iMCU_rows;
282         int comps_in_scan;
283         void *cur_comp_info[MAX_COMPS_IN_SCAN];
284         JDIMENSION MCUs_per_row;
285         JDIMENSION MCU_rows_in_scan;
286         int blocks_in_MCU;
287         int MCU_membership[C_MAX_BLOCKS_IN_MCU];
288         int Ss, Se, Ah, Al;
289
290         void *master;
291         void *main;
292         void *prep;
293         void *coef;
294         void *marker;
295         void *cconvert;
296         void *downsample;
297         void *fdct;
298         void *entropy;
299         void *script_space;
300         int script_space_size;
301 };
302
303 struct jpeg_destination_mgr
304 {
305         unsigned char* next_output_byte;
306         size_t free_in_buffer;
307
308         void (*init_destination) (j_compress_ptr cinfo);
309         jboolean (*empty_output_buffer) (j_compress_ptr cinfo);
310         void (*term_destination) (j_compress_ptr cinfo);
311 };
312
313
314 /*
315 =================================================================
316
317   DarkPlaces definitions
318
319 =================================================================
320 */
321
322 // Functions exported from libjpeg
323 #define qjpeg_create_compress(cinfo) \
324         qjpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_compress_struct))
325 #define qjpeg_create_decompress(cinfo) \
326         qjpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct))
327
328 static void (*qjpeg_CreateCompress) (j_compress_ptr cinfo, int version, size_t structsize);
329 static void (*qjpeg_CreateDecompress) (j_decompress_ptr cinfo, int version, size_t structsize);
330 static void (*qjpeg_destroy_compress) (j_compress_ptr cinfo);
331 static void (*qjpeg_destroy_decompress) (j_decompress_ptr cinfo);
332 static void (*qjpeg_finish_compress) (j_compress_ptr cinfo);
333 static jboolean (*qjpeg_finish_decompress) (j_decompress_ptr cinfo);
334 static jboolean (*qjpeg_resync_to_restart) (j_decompress_ptr cinfo, int desired);
335 static int (*qjpeg_read_header) (j_decompress_ptr cinfo, jboolean require_image);
336 static JDIMENSION (*qjpeg_read_scanlines) (j_decompress_ptr cinfo, unsigned char** scanlines, JDIMENSION max_lines);
337 static void (*qjpeg_set_defaults) (j_compress_ptr cinfo);
338 static void (*qjpeg_set_quality) (j_compress_ptr cinfo, int quality, jboolean force_baseline);
339 static jboolean (*qjpeg_start_compress) (j_compress_ptr cinfo, jboolean write_all_tables);
340 static jboolean (*qjpeg_start_decompress) (j_decompress_ptr cinfo);
341 static struct jpeg_error_mgr* (*qjpeg_std_error) (struct jpeg_error_mgr *err);
342 static JDIMENSION (*qjpeg_write_scanlines) (j_compress_ptr cinfo, unsigned char** scanlines, JDIMENSION num_lines);
343
344 static dllfunction_t jpegfuncs[] =
345 {
346         {"jpeg_CreateCompress",         (void **) &qjpeg_CreateCompress},
347         {"jpeg_CreateDecompress",       (void **) &qjpeg_CreateDecompress},
348         {"jpeg_destroy_compress",       (void **) &qjpeg_destroy_compress},
349         {"jpeg_destroy_decompress",     (void **) &qjpeg_destroy_decompress},
350         {"jpeg_finish_compress",        (void **) &qjpeg_finish_compress},
351         {"jpeg_finish_decompress",      (void **) &qjpeg_finish_decompress},
352         {"jpeg_resync_to_restart",      (void **) &qjpeg_resync_to_restart},
353         {"jpeg_read_header",            (void **) &qjpeg_read_header},
354         {"jpeg_read_scanlines",         (void **) &qjpeg_read_scanlines},
355         {"jpeg_set_defaults",           (void **) &qjpeg_set_defaults},
356         {"jpeg_set_quality",            (void **) &qjpeg_set_quality},
357         {"jpeg_start_compress",         (void **) &qjpeg_start_compress},
358         {"jpeg_start_decompress",       (void **) &qjpeg_start_decompress},
359         {"jpeg_std_error",                      (void **) &qjpeg_std_error},
360         {"jpeg_write_scanlines",        (void **) &qjpeg_write_scanlines},
361         {NULL, NULL}
362 };
363
364 // Handle for JPEG DLL
365 dllhandle_t jpeg_dll = NULL;
366
367 static unsigned char jpeg_eoi_marker [2] = {0xFF, JPEG_EOI};
368 static qboolean error_in_jpeg;
369
370 // Our own output manager for JPEG compression
371 typedef struct
372 {
373         struct jpeg_destination_mgr pub;
374
375         qfile_t* outfile;
376         unsigned char* buffer;
377 } my_destination_mgr;
378 typedef my_destination_mgr* my_dest_ptr;
379
380
381 /*
382 =================================================================
383
384   DLL load & unload
385
386 =================================================================
387 */
388
389 /*
390 ====================
391 JPEG_OpenLibrary
392
393 Try to load the JPEG DLL
394 ====================
395 */
396 qboolean JPEG_OpenLibrary (void)
397 {
398         const char* dllnames [] =
399         {
400 #if defined(WIN64)
401                 "libjpeg64.dll",
402 #elif defined(WIN32)
403                 "libjpeg.dll",
404 #elif defined(MACOSX)
405                 "libjpeg.62.dylib",
406 #else
407                 "libjpeg.so.62",
408                 "libjpeg.so",
409 #endif
410                 NULL
411         };
412
413         // Already loaded?
414         if (jpeg_dll)
415                 return true;
416
417         // Load the DLL
418         if (! Sys_LoadLibrary (dllnames, &jpeg_dll, jpegfuncs))
419         {
420                 Con_Printf ("JPEG support disabled\n");
421                 return false;
422         }
423
424         Con_Printf ("JPEG support enabled\n");
425         return true;
426 }
427
428
429 /*
430 ====================
431 JPEG_CloseLibrary
432
433 Unload the JPEG DLL
434 ====================
435 */
436 void JPEG_CloseLibrary (void)
437 {
438         Sys_UnloadLibrary (&jpeg_dll);
439 }
440
441
442 /*
443 =================================================================
444
445         JPEG decompression
446
447 =================================================================
448 */
449
450 static void JPEG_Noop (j_decompress_ptr cinfo) {}
451
452 static jboolean JPEG_FillInputBuffer (j_decompress_ptr cinfo)
453 {
454     // Insert a fake EOI marker
455     cinfo->src->next_input_byte = jpeg_eoi_marker;
456     cinfo->src->bytes_in_buffer = 2;
457
458         return TRUE;
459 }
460
461 static void JPEG_SkipInputData (j_decompress_ptr cinfo, long num_bytes)
462 {
463     if (cinfo->src->bytes_in_buffer <= (unsigned long)num_bytes)
464         {
465                 cinfo->src->bytes_in_buffer = 0;
466                 return;
467         }
468
469     cinfo->src->next_input_byte += num_bytes;
470     cinfo->src->bytes_in_buffer -= num_bytes;
471 }
472
473 static void JPEG_MemSrc (j_decompress_ptr cinfo, const unsigned char *buffer, size_t filesize)
474 {
475         cinfo->src = (struct jpeg_source_mgr *)cinfo->mem->alloc_small ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr));
476
477         cinfo->src->next_input_byte = buffer;
478         cinfo->src->bytes_in_buffer = filesize;
479
480         cinfo->src->init_source = JPEG_Noop;
481         cinfo->src->fill_input_buffer = JPEG_FillInputBuffer;
482         cinfo->src->skip_input_data = JPEG_SkipInputData;
483         cinfo->src->resync_to_restart = qjpeg_resync_to_restart; // use the default method
484         cinfo->src->term_source = JPEG_Noop;
485 }
486
487 static void JPEG_ErrorExit (j_common_ptr cinfo)
488 {
489         ((struct jpeg_decompress_struct*)cinfo)->err->output_message (cinfo);
490         error_in_jpeg = true;
491 }
492
493
494 /*
495 ====================
496 JPEG_LoadImage
497
498 Load a JPEG image into a RGBA buffer
499 ====================
500 */
501 unsigned char* JPEG_LoadImage (const unsigned char *f, int filesize, int matchwidth, int matchheight)
502 {
503         struct jpeg_decompress_struct cinfo;
504         struct jpeg_error_mgr jerr;
505         unsigned char *image_rgba, *scanline;
506         unsigned int line;
507
508         // No DLL = no JPEGs
509         if (!jpeg_dll)
510                 return NULL;
511
512         cinfo.err = qjpeg_std_error (&jerr);
513         qjpeg_create_decompress (&cinfo);
514         JPEG_MemSrc (&cinfo, f, filesize);
515         qjpeg_read_header (&cinfo, TRUE);
516         qjpeg_start_decompress (&cinfo);
517
518         image_width = cinfo.image_width;
519         image_height = cinfo.image_height;
520
521         if ((matchwidth && image_width != matchwidth) || (matchheight && image_height != matchheight))
522         {
523                 qjpeg_finish_decompress (&cinfo);
524                 qjpeg_destroy_decompress (&cinfo);
525                 return NULL;
526         }
527         if (image_width > 4096 || image_height > 4096 || image_width <= 0 || image_height <= 0)
528         {
529                 Con_Printf("JPEG_LoadImage: invalid image size %ix%i\n", image_width, image_height);
530                 return NULL;
531         }
532
533         image_rgba = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
534         scanline = (unsigned char *)Mem_Alloc(tempmempool, image_width * cinfo.output_components);
535         if (!image_rgba || !scanline)
536         {
537                 if (image_rgba)
538                         Mem_Free (image_rgba);
539                 if (scanline)
540                         Mem_Free (scanline);
541
542                 Con_Printf("JPEG_LoadImage: not enough memory for %i by %i image\n", image_width, image_height);
543                 qjpeg_finish_decompress (&cinfo);
544                 qjpeg_destroy_decompress (&cinfo);
545                 return NULL;
546         }
547
548         // Decompress the image, line by line
549         line = 0;
550         while (cinfo.output_scanline < cinfo.output_height)
551         {
552                 unsigned char *buffer_ptr;
553                 int ind;
554
555                 qjpeg_read_scanlines (&cinfo, &scanline, 1);
556
557                 // Convert the image to RGBA
558                 switch (cinfo.output_components)
559                 {
560                         // RGB images
561                         case 3:
562                                 buffer_ptr = &image_rgba[image_width * line * 4];
563                                 for (ind = 0; ind < image_width * 3; ind += 3, buffer_ptr += 4)
564                                 {
565                                         buffer_ptr[0] = scanline[ind];
566                                         buffer_ptr[1] = scanline[ind + 1];
567                                         buffer_ptr[2] = scanline[ind + 2];
568                                         buffer_ptr[3] = 255;
569                                 }
570                                 break;
571
572                         // Greyscale images (default to it, just in case)
573                         case 1:
574                         default:
575                                 buffer_ptr = &image_rgba[image_width * line * 4];
576                                 for (ind = 0; ind < image_width; ind++, buffer_ptr += 4)
577                                 {
578                                         buffer_ptr[0] = scanline[ind];
579                                         buffer_ptr[1] = scanline[ind];
580                                         buffer_ptr[2] = scanline[ind];
581                                         buffer_ptr[3] = 255;
582                                 }
583                 }
584
585                 line++;
586         }
587         Mem_Free (scanline);
588
589         qjpeg_finish_decompress (&cinfo);
590         qjpeg_destroy_decompress (&cinfo);
591
592         return image_rgba;
593 }
594
595
596 /*
597 =================================================================
598
599   JPEG compression
600
601 =================================================================
602 */
603
604 #define JPEG_OUTPUT_BUF_SIZE 4096
605 static void JPEG_InitDestination (j_compress_ptr cinfo)
606 {
607         my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
608         dest->buffer = (unsigned char*)cinfo->mem->alloc_small ((j_common_ptr) cinfo, JPOOL_IMAGE, JPEG_OUTPUT_BUF_SIZE * sizeof(unsigned char));
609         dest->pub.next_output_byte = dest->buffer;
610         dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE;
611 }
612
613 static jboolean JPEG_EmptyOutputBuffer (j_compress_ptr cinfo)
614 {
615         my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
616
617         if (FS_Write (dest->outfile, dest->buffer, JPEG_OUTPUT_BUF_SIZE) != (size_t) JPEG_OUTPUT_BUF_SIZE)
618         {
619                 error_in_jpeg = true;
620                 return false;
621         }
622
623         dest->pub.next_output_byte = dest->buffer;
624         dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE;
625         return true;
626 }
627
628 static void JPEG_TermDestination (j_compress_ptr cinfo)
629 {
630         my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
631         size_t datacount = JPEG_OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
632
633         // Write any data remaining in the buffer
634         if (datacount > 0)
635                 if (FS_Write (dest->outfile, dest->buffer, datacount) != (fs_offset_t)datacount)
636                         error_in_jpeg = true;
637 }
638
639 static void JPEG_MemDest (j_compress_ptr cinfo, qfile_t* outfile)
640 {
641         my_dest_ptr dest;
642
643         // First time for this JPEG object?
644         if (cinfo->dest == NULL)
645                 cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_destination_mgr));
646
647         dest = (my_dest_ptr)cinfo->dest;
648         dest->pub.init_destination = JPEG_InitDestination;
649         dest->pub.empty_output_buffer = JPEG_EmptyOutputBuffer;
650         dest->pub.term_destination = JPEG_TermDestination;
651         dest->outfile = outfile;
652 }
653
654
655 /*
656 ====================
657 JPEG_SaveImage_preflipped
658
659 Save a preflipped JPEG image to a file
660 ====================
661 */
662 qboolean JPEG_SaveImage_preflipped (const char *filename, int width, int height, unsigned char *data)
663 {
664         struct jpeg_compress_struct cinfo;
665         struct jpeg_error_mgr jerr;
666         unsigned char *scanline;
667         unsigned int offset, linesize;
668         qfile_t* file;
669
670         // No DLL = no JPEGs
671         if (!jpeg_dll)
672         {
673                 Con_Print("You need the libjpeg library to save JPEG images\n");
674                 return false;
675         }
676
677         // Open the file
678         file = FS_Open (filename, "wb", true, false);
679         if (!file)
680                 return false;
681
682         cinfo.err = qjpeg_std_error (&jerr);
683         cinfo.err->error_exit = JPEG_ErrorExit;
684         error_in_jpeg = false;
685
686         qjpeg_create_compress (&cinfo);
687         JPEG_MemDest (&cinfo, file);
688
689         // Set the parameters for compression
690         cinfo.image_width = width;
691         cinfo.image_height = height;
692         cinfo.in_color_space = JCS_RGB;
693         cinfo.input_components = 3;
694         qjpeg_set_defaults (&cinfo);
695         qjpeg_set_quality (&cinfo, (int)(scr_screenshot_jpeg_quality.value * 100), TRUE);
696         qjpeg_start_compress (&cinfo, true);
697
698         // Compress each scanline
699         linesize = cinfo.image_width * 3;
700         offset = linesize * (cinfo.image_height - 1);
701         while (cinfo.next_scanline < cinfo.image_height)
702         {
703                 scanline = &data[offset - cinfo.next_scanline * linesize];
704
705                 qjpeg_write_scanlines (&cinfo, &scanline, 1);
706                 if (error_in_jpeg)
707                         break;
708         }
709
710         qjpeg_finish_compress (&cinfo);
711         qjpeg_destroy_compress (&cinfo);
712
713         FS_Close (file);
714         return true;
715 }