Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/plugins/savepng.c
3203 views
1
// savepng.c
2
//
3
// Module for compressing and saving ElmerPost-pictures in PNG-format
4
//
5
// Compile e.g. as follows:
6
//
7
// MinGW: gcc -Wall -shared -O -o savepng.dll savepng.c -lopengl32 -ltcl84 -lpng
8
//
9
// Copy the shared library into $ELMER_POST_HOME/modules and ruin ElmerPost
10
//
11
// Usage:
12
//
13
// Elmer-Post: savepng file
14
//
15
// Defaults:
16
//
17
// file = elmerpost.png
18
//
19
// Modified from screensave.c
20
//
21
// Written by: ML, 08. Jan. 2008
22
23
#if defined(WIN32) || defined(win32)
24
#include <windows.h>
25
#endif
26
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include <GL/gl.h>
31
#include <tcl.h>
32
33
#define PNG_DEBUG 3
34
#include <png.h>
35
36
#if !(defined(WIN32) || defined(win32))
37
#include <errno.h>
38
extern int errno;
39
#endif
40
41
static int SavePNG( ClientData cl,Tcl_Interp *interp,int argc,char **argv ) {
42
unsigned char *buffer;
43
char fname[256];
44
int nx, ny, ox, oy, viewp[4];
45
int y, stride;
46
47
png_byte color_type = PNG_COLOR_TYPE_RGB;
48
png_byte bit_depth = 8;
49
png_structp png_ptr;
50
png_infop info_ptr;
51
png_bytep *row_pointers;
52
53
// Determine file name:
54
//---------------------
55
if( argc < 2 ) {
56
strcpy( fname, "elmerpost.png" );
57
} else {
58
strncpy( fname, argv[1], 256 );
59
}
60
61
// Open file:
62
//-----------
63
FILE *image = fopen( fname, "wb" );
64
if( image==NULL ) {
65
#if defined(WIN32) || defined(win32)
66
sprintf( interp->result, "savepng: can't open [%s] for writing!\n",fname );
67
#else
68
sprintf( interp->result, "savepng: can't open [%s] for writing:\n%s\n",
69
fname, strerror(errno) );
70
#endif
71
return TCL_ERROR;
72
}
73
74
// Determine picture size:
75
//------------------------
76
glGetIntegerv( GL_VIEWPORT, viewp );
77
ox = viewp[0];
78
oy = viewp[1];
79
nx = viewp[2]+1;
80
ny = viewp[3]+1;
81
82
// Allocate buffer:
83
//------------------
84
buffer = (unsigned char *) malloc( nx*ny*3 );
85
if ( buffer==NULL ) {
86
#if defined(WIN32) || defined(win32)
87
sprintf( interp->result, "savepng: can't allocate memory!\n" );
88
#else
89
sprintf( interp->result, "savepng: can't allocate memory:\n%s\n",
90
strerror(errno) );
91
#endif
92
return TCL_ERROR;
93
}
94
95
fprintf( stdout, "Saving %s ... ", fname );
96
fflush( stdout );
97
98
// Copy RGB-data into buffer:
99
//----------------------------
100
glReadBuffer( GL_FRONT );
101
glReadPixels( ox, oy, nx, ny, GL_RGB, GL_UNSIGNED_BYTE, buffer );
102
103
// Flip the picture:
104
//------------------
105
stride = 3*nx;
106
for( y=0; y<ny/2; y++ ) {
107
unsigned char *r1 = buffer + stride*y;
108
unsigned char *r2 = buffer + stride*(ny-1-y);
109
memcpy( buffer, r1, stride );
110
memcpy( r1, r2, stride );
111
memcpy( r2, buffer, stride );
112
}
113
114
// Set up row pointers:
115
//----------------------
116
row_pointers = (png_bytep *) malloc( sizeof(png_bytep) * ny );
117
for( y=0; y<ny; y++ )
118
row_pointers[y] = buffer + stride*y;
119
120
// Initialize PNG write struct:
121
//------------------------------
122
png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
123
if( !png_ptr ) {
124
#if defined(WIN32) || defined(win32)
125
sprintf( interp->result, "savepng: can't create write struct!\n" );
126
#else
127
sprintf( interp->result, "savepng: can't create write struct:\n%s\n",
128
strerror(errno) );
129
#endif
130
return TCL_ERROR;
131
}
132
133
// Create info struct:
134
//---------------------
135
info_ptr = png_create_info_struct( png_ptr );
136
if( !info_ptr ) {
137
#if defined(WIN32) || defined(win32)
138
sprintf( interp->result, "savepng: can't create info struct!\n" );
139
#else
140
sprintf( interp->result, "savepng: can't create info struct:\n%s\n",
141
strerror(errno) );
142
#endif
143
return TCL_ERROR;
144
}
145
146
// Init io:
147
//----------
148
if( setjmp(png_jmpbuf(png_ptr)) ) {
149
#if defined(WIN32) || defined(win32)
150
sprintf( interp->result, "savepng: error in init_io!\n" );
151
#else
152
sprintf( interp->result, "savepng: error in init_io:\n%s\n",
153
strerror(errno) );
154
#endif
155
return TCL_ERROR;
156
}
157
158
png_init_io( png_ptr, image );
159
160
// Write header:
161
//---------------
162
if( setjmp(png_jmpbuf(png_ptr)) ) {
163
#if defined(WIN32) || defined(win32)
164
sprintf( interp->result, "savepng: can't write headers!\n" );
165
#else
166
sprintf( interp->result, "savepng: can't write headers:\n%s\n",
167
strerror(errno) );
168
#endif
169
return TCL_ERROR;
170
}
171
172
png_set_IHDR( png_ptr, info_ptr, nx, ny,
173
bit_depth, color_type, PNG_INTERLACE_NONE,
174
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
175
176
png_write_info( png_ptr, info_ptr );
177
178
// Write bytes:
179
//--------------
180
if( setjmp(png_jmpbuf(png_ptr)) ) {
181
#if defined(WIN32) || defined(win32)
182
sprintf( interp->result, "savepng: can't write bytes!\n" );
183
#else
184
sprintf( interp->result, "savepng: can't write bytes:\n%s\n",
185
strerror(errno) );
186
#endif
187
return TCL_ERROR;
188
}
189
190
png_write_image( png_ptr, row_pointers );
191
192
// End write:
193
//-----------
194
if( setjmp(png_jmpbuf(png_ptr)) ) {
195
#if defined(WIN32) || defined(win32)
196
sprintf( interp->result, "savepng: can't finalize!\n" );
197
#else
198
sprintf( interp->result, "savepng: can't finalize:\n%s\n",
199
strerror(errno) );
200
#endif
201
return TCL_ERROR;
202
}
203
204
png_write_end( png_ptr, NULL );
205
206
// Cleanup:
207
//----------
208
free(row_pointers);
209
fclose( image );
210
free( buffer );
211
fprintf( stdout, "done\n");
212
fflush( stdout );
213
214
return TCL_OK;
215
}
216
217
#if defined(WIN32) || defined(win32)
218
__declspec(dllexport)
219
#endif
220
221
int Savepng_Init( Tcl_Interp *interp ) {
222
Tcl_CreateCommand( interp, "savepng", (Tcl_CmdProc *)SavePNG,
223
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL );
224
return TCL_OK;
225
}
226
227