static gboolean take_screenshot (void *user_data, char *fname) { Viewer *self = (Viewer*) user_data; int w = GTK_WIDGET (self->gl_area)->allocation.width; int h = GTK_WIDGET (self->gl_area)->allocation.height; uint8_t *bgra = (uint8_t*)malloc (w*h*4); uint8_t *rgb = (uint8_t*)malloc (w*h*3); glReadPixels (0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, bgra); FILE *fp = fopen (fname, "wb"); if (! fp) { perror ("fopen"); err ("couldn't take screenshot\n"); return FALSE; } else { pixel_convert_8u_bgra_to_8u_rgb (rgb, w*3, w, h, bgra, w*4); ppm_write_bottom_up (fp, rgb, w, h, w*3); fclose (fp); dbg ("screenshot saved to %s\n", fname); viewer_set_status_bar_message (self, "screenshot saved to %s", fname); } free (bgra); free (rgb); return TRUE; }
int jpeg_compress_8u_bgra (const uint8_t * src, int width, int height, int stride, uint8_t * dest, int * destsize, int quality) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; struct jpeg_destination_mgr jdest; int out_size = *destsize; cinfo.err = jpeg_std_error (&jerr); jpeg_create_compress (&cinfo); jdest.next_output_byte = dest; jdest.free_in_buffer = out_size; jdest.init_destination = init_destination; jdest.empty_output_buffer = empty_output_buffer; jdest.term_destination = term_destination; cinfo.dest = &jdest; cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults (&cinfo); jpeg_set_quality (&cinfo, quality, TRUE); jpeg_start_compress (&cinfo, TRUE); while (cinfo.next_scanline < height) { uint8_t buf[width*3]; pixel_convert_8u_bgra_to_8u_rgb (buf, 0, width, 1, src + cinfo.next_scanline * stride, 0); JSAMPROW row = (JSAMPROW) buf; jpeg_write_scanlines (&cinfo, &row, 1); } jpeg_finish_compress (&cinfo); *destsize = out_size - jdest.free_in_buffer; jpeg_destroy_compress (&cinfo); return 0; }