Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/plugins/savejpg.c
3203 views
1
// savejpg.c
2
//
3
// Module for compressing and saving ElmerPost-pictures in jpg format
4
//
5
// Compile e.g. as follows:
6
//
7
// Linux: gcc -I/usr/include/tcl8.4 -L/usr/lib/tcl8.4 -Wall -shared -O -o savejpg.so savejpg.c -lGL -ltcl8.4 -ljpeg
8
// MinGW: gcc -Wall -shared -O -o savejpg.dll savejpg.c -lopengl32 -ltcl84 -ljpeg
9
//
10
// Copy the shared library into $ELMER_POST_HOME/modules and ruin ElmerPost
11
//
12
// Usage:
13
//
14
// Elmer-Post: savejpg file quality
15
//
16
// Defaults:
17
//
18
// file = elmerpost.jpg
19
// quality = 85 (1=bad, 100=good)
20
//
21
// Modified from screensave.c
22
//
23
// Written by: ML, 29. Sept. 2007
24
25
#if defined(WIN32) || defined(win32)
26
#include <windows.h>
27
// This is to avoid redefinition of INT32 in jmoreconfig.h:
28
#define XMD_H
29
#endif
30
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34
#include <GL/gl.h>
35
#include <tcl.h>
36
37
#include <jpeglib.h>
38
39
#if !(defined(WIN32) || defined(win32))
40
#include <errno.h>
41
extern int errno;
42
#endif
43
44
static int SaveJPG( ClientData cl,Tcl_Interp *interp,int argc,char **argv ) {
45
unsigned char *buffer;
46
char fname[256];
47
int nx, ny, ox, oy, viewp[4];
48
struct jpeg_compress_struct cinfo;
49
struct jpeg_error_mgr jerr;
50
FILE *outfile;
51
JSAMPROW row_pointer[1];
52
int row_stride, quality = 85;
53
54
// Determine file name & quality:
55
//--------------------------------
56
if( argc < 2 ) {
57
strcpy( fname, "elmerpost.jpg" );
58
} else {
59
strncpy( fname,argv[1], 256 );
60
if( argc == 3 ) {
61
quality = atoi( argv[2] );
62
}
63
}
64
65
// Open output file:
66
//-------------------
67
if( (outfile = fopen(fname, "wb")) == NULL ) {
68
#if defined(WIN32) || defined(win32)
69
sprintf( interp->result, "savejpg: can't open [%s] for writing!\n",fname );
70
#else
71
sprintf( interp->result, "savejpg: can't open [%s] for writing:\n%s\n",
72
fname, strerror(errno) );
73
#endif
74
return TCL_ERROR;
75
}
76
77
// Determine picture size:
78
//------------------------
79
glGetIntegerv( GL_VIEWPORT, viewp );
80
ox = viewp[0];
81
oy = viewp[1];
82
nx = viewp[2]+1;
83
ny = viewp[3]+1;
84
85
// Allocate buffer:
86
//------------------
87
if ( !(buffer=(unsigned char *)malloc(nx*ny*3)) ) {
88
#if defined(WIN32) || defined(win32)
89
sprintf( interp->result, "savejpg: can't allocate enough memory!\n" );
90
#else
91
sprintf( interp->result, "savejpg: can't allocate enough memory:\n%s\n",
92
strerror(errno) );
93
#endif
94
fclose( outfile );
95
return TCL_ERROR;
96
}
97
fprintf( stdout, "Saving %s (quality: %d)... ", fname, quality );
98
fflush( stdout );
99
100
// Copy RGB-data into buffer:
101
//----------------------------
102
glReadBuffer( GL_FRONT );
103
glReadPixels( ox, oy, nx, ny, GL_RGB, GL_UNSIGNED_BYTE, buffer );
104
105
// Compress into JPG(YUV) & save:
106
//-------------------------------
107
cinfo.err = jpeg_std_error( &jerr );
108
jpeg_create_compress( &cinfo );
109
jpeg_stdio_dest( &cinfo, outfile );
110
111
cinfo.image_width = nx;
112
cinfo.image_height = ny;
113
cinfo.input_components = 3;
114
cinfo.in_color_space = JCS_RGB;
115
116
jpeg_set_defaults( &cinfo );
117
jpeg_set_quality( &cinfo, quality, TRUE );
118
jpeg_start_compress( &cinfo, TRUE );
119
120
row_stride = 3*nx;
121
while( cinfo.next_scanline < cinfo.image_height ) {
122
row_pointer[0] = &buffer[ (ny-1-cinfo.next_scanline) * row_stride ];
123
(void)jpeg_write_scanlines( &cinfo, row_pointer, 1 );
124
}
125
126
jpeg_finish_compress( &cinfo );
127
fclose( outfile );
128
129
jpeg_destroy_compress( &cinfo );
130
fprintf( stdout, "done [ok]\n" );
131
fflush( stdout );
132
133
free( buffer );
134
return TCL_OK;
135
}
136
137
#if defined(WIN32) || defined(win32)
138
__declspec(dllexport)
139
#endif
140
141
int Savejpg_Init( Tcl_Interp *interp ) {
142
Tcl_CreateCommand( interp, "savejpg", (Tcl_CmdProc *)SaveJPG,
143
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL );
144
return TCL_OK;
145
}
146
147