/*
* $Id: sgidump.c,v 1.1.2.1 2001/10/30 13:38:59 jedwards Exp $
*/
/*
* File: sgidump.c
*
* Author: Don Middleton
* National Center for Atmospheric Research
* PO 3000, Boulder, Colorado
*
* Date: Mon Jul 14 20:15:52 MDT 1997
*
* Description: Provides *working* windowdump code
* for SGI OS6.X and later.
*/
/*
Vis5D system for visualizing five dimensional gridded data sets
Copyright (C) 1990 - 1996 Bill Hibbard, Brian Paul, Dave Santek,
and Andre Battaiola.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "sgidump.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/Xmd.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int SGIWrite(
FILE *fp,
int nx,
int ny,
unsigned char *buf);
static char *program_name = "xdump";
/*
* Standard fatal error routine - call like printf but maximum of 7 arguments.
* Does not require dpy or screen defined.
*/
/* VARARGS1 */
static void Fatal_Error( char *msg )
{
fflush(stdout);
fflush(stderr);
fprintf(stderr, "%s: error: %s\n", program_name, msg);
exit(1);
}
void
SGI_Dump(
Display *display,
int scr,
Window window,
FILE *out,
GLenum oglbuf
)
{
Display *dpy;
int screen;
unsigned long swaptest = 1;
XColor *colors;
unsigned buffer_size;
int win_name_size;
int header_size;
int ncolors, i;
char *win_name;
Bool got_win_name;
XWindowAttributes win_info;
XImage *image;
int absx, absy, x, y;
unsigned width, height;
int dwidth, dheight;
int bw;
Window dummywin;
static unsigned char *buf;
static int last_nx = -1;
static int last_ny = -1;
int length, status;
dpy = display;
screen = scr;
glReadBuffer(oglbuf);
glFinish();
/*
* Get the parameters of the window being dumped.
*/
if(!XGetWindowAttributes(dpy, window, &win_info))
Fatal_Error("Can't get target window attributes.");
/* handle any frame window */
if (!XTranslateCoordinates (dpy, window, RootWindow (dpy, screen), 0, 0,
&absx, &absy, &dummywin)) {
fprintf (stderr,
"%s: unable to translate window coordinates (%d,%d)\n",
program_name, absx, absy);
exit (1);
}
win_info.x = absx;
win_info.y = absy;
width = win_info.width;
height = win_info.height;
bw = 0;
/* Allocate or adjust buffer for imagery. */
if (buf == (unsigned char *) NULL) {
buf = (unsigned char *) calloc(1, width*height*3);
if (buf == (unsigned char *) NULL) {
perror("SGI_Dump()");
return;
}
}
else {
if (last_nx != width || last_ny != height) {
(void) free(buf);
buf = (unsigned char *) calloc(1, width*height*3);
if (buf == (unsigned char *) NULL) {
perror("SGI_Dump()");
return;
}
}
}
last_nx = width ; last_ny = height;
(void) glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
status = SGIWrite(out, win_info.width, win_info.height, buf);
if (status != 0) {
(void) fprintf(stderr,
"SGI_Dump(): Error encoding/writing SGI rasterfile\n");
}
return;
}
#define SGI_MAGIC 0732
typedef enum {
SGI_CM_NORMAL, /* file contains rows of values which
* are either RGB values (zsize == 3)
* or greyramp values (zsize == 1) */
SGI_CM_DITHERED,
SGI_CM_SCREEN, /* File contains data which is a screen
* image; getrow() returns buffer which
* can be displayed writepixels(). */
SGI_CM_COLORMAP /* File has colormap. */
} SgiColormapType;
#define SGI_TYPEMASK 0xff00
#define SGI_BPPMASK 0x00ff
#define SGI_TYPE_VERBATIM 0x0000
#define SGI_TYPE_RLE 0x0100
#define SGI_ISRLE(type) (((type) & SGI_TYPEMASK) == SGI_TYPE_RLE)
#define SGI_ISVERBATIM(type) (((type) & SGI_TYPEMASK) == SGI_TYPE_VERBATIM)
#define SGI_BPP(type) ((type) & SGI_BPPMASK)
#define RLE(bpp) (SGI_TYPE_RLE | (bpp))
#define VERBATIM(bpp) (SGI_TYPE_VERBATIM | (bpp))
/*
SGI reserves 512 bytes for the header, but the structure itself
is not (yet) that large.
*/
#ifdef ArchAlpha
typedef unsigned int UInt32_T;
typedef unsigned short UInt16_T;
typedef int Int32_T;
typedef short Int16_T;
#else
typedef unsigned long UInt32_T;
typedef unsigned short UInt16_T;
typedef long Int32_T;
typedef short Int16_T;
#endif
#define RAS_SGI_RESERVED 512
#ifdef ArchCray
#define B32 :32
#define B16 :16
#else
#define B32
#define B16
#endif /* ArchCray */
/*
** Format of SGI file header. Note field types indicate field sizes.
**
*/
typedef struct {
UInt16_T imagic B16;
UInt16_T type B16;
UInt16_T dim B16;
UInt16_T xsize B16;
UInt16_T ysize B16;
UInt16_T zsize B16;
UInt32_T min B32;
UInt32_T max B32;
UInt32_T wastebytes B32;
char name[80];
SgiColormapType colormap B32;
} SGIFileHeader_T;
int SGIWrite(
FILE *fp,
int nx,
int ny,
unsigned char *buf
) {
SGIFileHeader_T header;
int x, y, i, nb;
unsigned long swaptest = 1;
static unsigned char *tmpbuf;
static int tmpbuf_size = 0;
unsigned char *iptr, *optr;
if (tmpbuf == (unsigned char *) NULL) {
if (nx > RAS_SGI_RESERVED) {
tmpbuf_size = nx;
}
else {
tmpbuf_size = RAS_SGI_RESERVED;
}
tmpbuf = (unsigned char *) calloc(1, tmpbuf_size);
if (! tmpbuf) {
(void) fprintf(stderr,
"sgidump: Memory allocation error\n");
return(-1);
}
}
header.type = SGI_TYPE_VERBATIM | 1;
header.imagic = SGI_MAGIC;
header.dim = 3;
header.xsize = nx;
header.ysize = ny;
header.zsize = 3; /* RGB image. */
header.min = 0;
header.max = 255;
header.wastebytes = 0;
header.colormap = SGI_CM_NORMAL;
sprintf(header.name,"Created by Vis5d+ version %s",VERSION);
/* strcpy(header.name,"no name"); */
/* Write the header. */
nb = fwrite(&header, sizeof(header),1, fp);
if (nb != 1) {
(void) fprintf(stderr,
"sgidump: Error writing header\n");
return(-1);
}
/* Write bytes remaining before actual image data. */
memset(tmpbuf, 0,RAS_SGI_RESERVED-sizeof(header));
nb = fwrite(tmpbuf, 1, (RAS_SGI_RESERVED-sizeof(header)), fp);
if (nb != (RAS_SGI_RESERVED-sizeof(header))) {
(void) fprintf(stderr,
"sgidump: Error writing header\n");
return(-1);
}
/*
** SGI_VERBATIM rasterfiles are scan-plane interleaved,
** so we write out the red plane, the green plane, and then
** the blue plane. There is no compression done here.
*/
for(i=0; i<3; i++) {
for(y=ny-1; y>=0; y--) {
iptr = &buf[((ny-y-1)*nx*3)+i];
optr = tmpbuf;
for(x=0; x<nx; x++) {
*optr = *iptr;
optr += 1;
iptr += 3;
}
nb = fwrite(tmpbuf, 1, nx, fp);
if (nb != nx) {
(void) fprintf(stderr,
"sgidump: Error writing header\n");
return(-1);
}
}
}
return(0);
}
syntax highlighted by Code2HTML, v. 0.9.1