1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// jpeg.c : define member function for saving windows in JPEG files
// 'void window::save_jpeg(char* fina, int q)' // q = quality
// it is not defined in window.c !!
// wolfk 5/2000
/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
#include "window.h"
#include <X11/Xutil.h>
struct ppm { // struct for 3byte ppm rgb pixels rgb=888 needed for jpeg
unsigned char r,g,b;
inline void boost(unsigned short c565) { // blow up rgb565 -> rgb888
r = (c565 >> 11) << 3;
g = (c565 >> 5) << 2;
b = c565 << 3;
}
inline unsigned short c565() { // return standard 565 color
unsigned short val = b >> 3;
val |= (g >> 2) << 5;
val |= (r >> 3) << 11;
return val;
}
};
extern "C" {
#include "jpeglib.h"
}
// to be called after initialization of the cinfo struct
// write one frame compressed to file stream associated with cinfo
// may be called succesively for more frames
void JPEG_compress(struct jpeg_compress_struct *cinfo, int image_width, unsigned short *image_buffer) {
jpeg_start_compress(cinfo, TRUE);
struct ppm ppm_buffer[image_width]; // buffer for one scanline
/* pointer to JSAMPLE row[s] */
JSAMPROW pptr = (unsigned char*) ppm_buffer;
while (cinfo->next_scanline < cinfo->image_height) {
unsigned short *im_line = image_buffer + image_width*cinfo->next_scanline;
for (int i=0; i < image_width; i++) ppm_buffer[i].boost(im_line[i]);
jpeg_write_scanlines(cinfo, &pptr, 1);
}
jpeg_finish_compress(cinfo);
}
void compress_jpeg(FILE *fsave, int quality, int ww, int hh, unsigned short* image_buf) {
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, fsave);
cinfo.image_width = ww; /* image width and height, in pixels */
cinfo.image_height = hh;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
JPEG_compress(&cinfo,ww,image_buf);
jpeg_destroy_compress(&cinfo);
}
void compress_jpeg(FILE *fsave, int quality, XImage *xi) {
int ww = xi->bytes_per_line/2; // = (width/2)*2 :
compress_jpeg(fsave, quality, ww, xi->height, (unsigned short*) xi->data);
}
// to be called after initialization of the cinfo struct
// read one frame from file stream associated with cinfo and decompress
// may be called succesively for more frames of a video
void JPEG_decompress(struct jpeg_decompress_struct *cinfo, unsigned short *image_buffer) {
int ww = cinfo->output_width;
int row_stride = ww * cinfo->output_components;
/* Make a one-row-high sample array that will go away when done with image */
JSAMPARRAY buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1);
while (cinfo->output_scanline < cinfo->output_height) {
jpeg_read_scanlines(cinfo, buffer, 1);
unsigned short *capline= image_buffer + ww*cinfo->output_scanline;
ppm* ppline = (ppm*) buffer[0];
for (int i=0; i < ww; i++) capline[i] = ppline[i].c565();
}
}
// the following functions are only for demonstrations
void load_jpeg_file(FILE *fload) {
if (fload == NULL) return;
static struct jpeg_decompress_struct cinfo; // static for retry
static struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, fload);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
/*
if ((int) cinfo.output_width != biWidth ||
(int) cinfo.output_height != biHeight) {
printf("adapting size to %dx%d\n",cinfo.output_width,cinfo.output_height);
adjust_size(cinfo.output_width,cinfo.output_height);
}
*/
// JPEG_decompress(&cinfo, cap_buf);
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
// map_and_redraw();
}
void load_jpeg(char* fina) {
if (! True_Color_Visual) error("jpegs only supported for TrueColor Mode");
FILE *fload = fopen(fina,"r");
if (fload == NULL) return;
load_jpeg_file(fload);
printf("loaded jpeg image from '%s'\n",fina);
fclose(fload);
}
// interface function
void window::save_jpeg(char* fina, int q) { // q = quality
if (! True_Color_Visual) error("jpegs only supported for TrueColor Mode");
FILE *fsave = fopen(fina,"w");
if (fsave == NULL) return;
XImage *xi = GetImage();
compress_jpeg(fsave,q,xi);
int fsize = ftell(fsave);
printf("saved jpeg q = %d to '%s' (%d x %d) %d byte compfct = %.1f\n",
q,fina,width,height,fsize,2.0*width*height/fsize);
fclose(fsave);
XDestroyImage(xi);
}
void save_jpeg(window *w, char* fina, int q = 50) { // q = quality
int ww = w->width, hh = w->height;
if (! True_Color_Visual) error("jpegs only supported for TrueColor Mode");
FILE *fsave = fopen(fina,"w");
if (fsave == NULL) return;
XImage *xi = XGetImage(display,w->Win,0,0,ww,hh,AllPlanes,ZPixmap);
compress_jpeg(fsave,q,ww,hh, (unsigned short*) xi->data);
int fsize = ftell(fsave);
printf("saved jpeg q = %d to '%s' (%d x %d) %d byte compfct = %.1f\n",
q,fina,ww,hh,fsize,2.0*ww*hh/fsize);
fclose(fsave);
XDestroyImage(xi);
}
|