void (*term_source) (j_decompress_ptr cinfo);
};
+typedef struct {
+ /* These values are fixed over the whole image. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOF marker. */
+ int component_id; /* identifier for this component (0..255) */
+ int component_index; /* its index in SOF or cinfo->comp_info[] */
+ int h_samp_factor; /* horizontal sampling factor (1..4) */
+ int v_samp_factor; /* vertical sampling factor (1..4) */
+ int quant_tbl_no; /* quantization table selector (0..3) */
+ /* These values may vary between scans. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOS marker. */
+ /* The decompressor output side may not use these variables. */
+ int dc_tbl_no; /* DC entropy table selector (0..3) */
+ int ac_tbl_no; /* AC entropy table selector (0..3) */
+
+ /* Remaining fields should be treated as private by applications. */
+
+ /* These values are computed during compression or decompression startup: */
+ /* Component's size in DCT blocks.
+ * Any dummy blocks added to complete an MCU are not counted; therefore
+ * these values do not depend on whether a scan is interleaved or not.
+ */
+ JDIMENSION width_in_blocks;
+ JDIMENSION height_in_blocks;
+ /* Size of a DCT block in samples. Always DCTSIZE for compression.
+ * For decompression this is the size of the output from one DCT block,
+ * reflecting any scaling we choose to apply during the IDCT step.
+ * Values of 1,2,4,8 are likely to be supported. Note that different
+ * components may receive different IDCT scalings.
+ */
+ int DCT_scaled_size;
+ /* The downsampled dimensions are the component's actual, unpadded number
+ * of samples at the main buffer (preprocessing/compression interface), thus
+ * downsampled_width = ceil(image_width * Hi/Hmax)
+ * and similarly for height. For decompression, IDCT scaling is included, so
+ * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
+ */
+ JDIMENSION downsampled_width; /* actual width in samples */
+ JDIMENSION downsampled_height; /* actual height in samples */
+ /* This flag is used only for decompression. In cases where some of the
+ * components will be ignored (eg grayscale output from YCbCr image),
+ * we can skip most computations for the unused components.
+ */
+ jboolean component_needed; /* do we need the value of this component? */
+
+ /* These values are computed before starting a scan of the component. */
+ /* The decompressor output side may not use these variables. */
+ int MCU_width; /* number of blocks per MCU, horizontally */
+ int MCU_height; /* number of blocks per MCU, vertically */
+ int MCU_blocks; /* MCU_width * MCU_height */
+ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */
+ int last_col_width; /* # of non-dummy blocks across in last MCU */
+ int last_row_height; /* # of non-dummy blocks down in last MCU */
+
+ /* Saved quantization table for component; NULL if none yet saved.
+ * See jdinput.c comments about the need for this information.
+ * This field is currently used only for decompression.
+ */
+ void *quant_table;
+
+ /* Private per-component storage for DCT or IDCT subsystem. */
+ void * dct_table;
+} jpeg_component_info;
+
struct jpeg_decompress_struct
{
struct jpeg_error_mgr *err; // USED
void *dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
void *ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
int data_precision;
- void *comp_info;
+ jpeg_component_info *comp_info;
jboolean progressive_mode;
jboolean arith_code;
unsigned char arith_dc_L[NUM_ARITH_TBLS];
JDIMENSION total_iMCU_rows;
void *sample_range_limit;
int comps_in_scan;
- void *cur_comp_info[MAX_COMPS_IN_SCAN];
+ jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN];
JDIMENSION MCUs_per_row;
JDIMENSION MCU_rows_in_scan;
int blocks_in_MCU;
int num_components;
J_COLOR_SPACE jpeg_color_space;
- void *comp_info;
+ jpeg_component_info *comp_info;
void *quant_tbl_ptrs[NUM_QUANT_TBLS];
void *dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
void *ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
int max_v_samp_factor;
JDIMENSION total_iMCU_rows;
int comps_in_scan;
- void *cur_comp_info[MAX_COMPS_IN_SCAN];
+ jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN];
JDIMENSION MCUs_per_row;
JDIMENSION MCU_rows_in_scan;
int blocks_in_MCU;
return true;
// Load the DLL
- if (! Sys_LoadLibrary (dllnames, &jpeg_dll, jpegfuncs))
- {
- Con_Printf ("JPEG support disabled\n");
- return false;
- }
-
- Con_Printf ("JPEG support enabled\n");
- return true;
+ return Sys_LoadLibrary (dllnames, &jpeg_dll, jpegfuncs);
}
====================
JPEG_LoadImage
-Load a JPEG image into a RGBA buffer
+Load a JPEG image into a BGRA buffer
====================
*/
-unsigned char* JPEG_LoadImage (const unsigned char *f, int filesize, int matchwidth, int matchheight)
+unsigned char* JPEG_LoadImage_BGRA (const unsigned char *f, int filesize)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
- unsigned char *image_rgba, *scanline;
+ unsigned char *image_buffer, *scanline;
unsigned int line;
// No DLL = no JPEGs
image_width = cinfo.image_width;
image_height = cinfo.image_height;
- if ((matchwidth && image_width != matchwidth) || (matchheight && image_height != matchheight))
- {
- qjpeg_finish_decompress (&cinfo);
- qjpeg_destroy_decompress (&cinfo);
- return NULL;
- }
if (image_width > 4096 || image_height > 4096 || image_width <= 0 || image_height <= 0)
{
Con_Printf("JPEG_LoadImage: invalid image size %ix%i\n", image_width, image_height);
return NULL;
}
- image_rgba = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
+ image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
scanline = (unsigned char *)Mem_Alloc(tempmempool, image_width * cinfo.output_components);
- if (!image_rgba || !scanline)
+ if (!image_buffer || !scanline)
{
- if (!image_rgba)
- Mem_Free (image_rgba);
+ if (image_buffer)
+ Mem_Free (image_buffer);
+ if (scanline)
+ Mem_Free (scanline);
Con_Printf("JPEG_LoadImage: not enough memory for %i by %i image\n", image_width, image_height);
qjpeg_finish_decompress (&cinfo);
qjpeg_read_scanlines (&cinfo, &scanline, 1);
- // Convert the image to RGBA
+ // Convert the image to BGRA
switch (cinfo.output_components)
{
// RGB images
case 3:
- buffer_ptr = &image_rgba[image_width * line * 4];
+ buffer_ptr = &image_buffer[image_width * line * 4];
for (ind = 0; ind < image_width * 3; ind += 3, buffer_ptr += 4)
{
- buffer_ptr[0] = scanline[ind];
+ buffer_ptr[2] = scanline[ind];
buffer_ptr[1] = scanline[ind + 1];
- buffer_ptr[2] = scanline[ind + 2];
+ buffer_ptr[0] = scanline[ind + 2];
buffer_ptr[3] = 255;
}
break;
// Greyscale images (default to it, just in case)
case 1:
default:
- buffer_ptr = &image_rgba[image_width * line * 4];
+ buffer_ptr = &image_buffer[image_width * line * 4];
for (ind = 0; ind < image_width; ind++, buffer_ptr += 4)
{
buffer_ptr[0] = scanline[ind];
qjpeg_finish_decompress (&cinfo);
qjpeg_destroy_decompress (&cinfo);
- return image_rgba;
+ return image_buffer;
}
cinfo.in_color_space = JCS_RGB;
cinfo.input_components = 3;
qjpeg_set_defaults (&cinfo);
- qjpeg_set_quality (&cinfo, scr_screenshot_jpeg_quality.value * 100, TRUE);
+ qjpeg_set_quality (&cinfo, (int)(scr_screenshot_jpeg_quality.value * 100), TRUE);
+
+ // turn off subsampling (to make text look better)
+ cinfo.optimize_coding = 1;
+ cinfo.comp_info[0].h_samp_factor = 1;
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].h_samp_factor = 1;
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1;
+ cinfo.comp_info[2].v_samp_factor = 1;
+
qjpeg_start_compress (&cinfo, true);
// Compress each scanline