1
/******************************************************************************/
4
/* Copyright 2000 by Schroff Development Corporation, Shawnee-Mission, */
5
/* Kansas, United States of America. All rights reserved. */
7
/******************************************************************************/
9
/* This Display Driver is distributed as "freeware". There are no */
10
/* restrictions on its' usage. */
12
/******************************************************************************/
14
/* DISCLAIMER OF ALL WARRANTIES AND LIABILITY */
16
/* Schroff Development Corporation makes no warranties, either expressed */
17
/* or implied, with respect to the programs contained within this file, or */
18
/* with respect to software used in conjunction with these programs. The */
19
/* programs are distributed 'as is'. The entire risk as to its quality and */
20
/* performance is assumed by the purchaser. Schroff Development Corporation */
21
/* does not guarantee, warrant or make any representation regarding the */
22
/* use of, or the results of the use of the programs in terms of correctness, */
23
/* accuracy, reliability, or performance. Schroff Development Corporation */
24
/* assumes no liability for any direct, indirect, or consquential, special */
25
/* or exemplary damages, regardless of its having been advised of the */
26
/* possibility of such damage. */
28
/******************************************************************************/
32
// This is a Display Driver that was written to comply with the PhotoRealistic
33
// RenderMan Display Driver Implementation Guide (on the web at:
34
// www.pixar.com/products/rendermandocs/toolkit/Toolkit/dspy.html).
36
// This driver places image data into a Windows .BMP file. It writes this data
37
// one scanline at a time and tries to minimize memory consumption.
45
#include <aqsis/ri/ndspy.h> // NOTE: Use Pixar's ndspy.h if you've got it.
48
typedef struct tagBITMAPFILEHEADER { // bmfh
56
/* instead of sizeof(BITMAPFILEHEADER) since this must be 14 */
57
#define BITMAPFILEHEADER_SIZEOF 14
59
typedef struct tagRGBQUAD { // rgbq
60
unsigned char rgbBlue;
61
unsigned char rgbGreen;
63
unsigned char rgbReserved;
66
typedef struct tagBITMAPINFOHEADER{ // bmih
80
typedef struct tagBITMAPINFO {
81
BITMAPINFOHEADER bmiHeader;
87
// -----------------------------------------------------------------------------
89
// -----------------------------------------------------------------------------
108
// -----------------------------------------------------------------------------
110
// -----------------------------------------------------------------------------
112
static const int DEFAULT_IMAGEWIDTH = 512; // Tiff display driver defaults are good enough for me.
113
static const int DEFAULT_IMAGEHEIGHT = 384;
114
static const float DEFAULT_PIXELASPECTRATIO = 1.0f;
118
// Set SHOW_CALLSTACK to 1 to see trace messages from the
119
// driver (which will be written to stderr).
122
#define SHOW_CALLSTACK 0
124
// -----------------------------------------------------------------------------
125
// Function Prototypes
126
// -----------------------------------------------------------------------------
128
static int DWORDALIGN(int bits);
129
static bool bitmapfileheader(BITMAPFILEHEADER *bfh, FILE *fp);
130
static unsigned short swap2( unsigned short s );
131
static unsigned long swap4( unsigned long l );
132
static bool lowendian();
134
// -----------------------------------------------------------------------------
136
// -----------------------------------------------------------------------------
139
//******************************************************************************
142
// Initializes the display driver, allocates necessary resources, checks image
143
// size, specifies format in which incoming data will arrive.
144
//******************************************************************************
146
extern "C" PtDspyError DspyImageOpen(PtDspyImageHandle *image,
147
const char *drivername,
148
const char *filename,
152
const UserParameter *parameters,
154
PtDspyDevFormat *format,
155
PtFlagStuff *flagstuff)
157
PtDspyError rval = PkDspyErrorNone;
159
static AppData g_Data;
164
fprintf(stderr, "sdcBMP_DspyImageOpen called.\n");
167
pData = (AppData *) calloc(1, sizeof(g_Data));
170
// Initialize our global resources
172
memset(&g_Data, sizeof(AppData), 0);
174
flagstuff->flags = PkDspyFlagsWantsScanLineOrder;
177
width = DEFAULT_IMAGEWIDTH;
180
height = DEFAULT_IMAGEHEIGHT;
183
g_Data.FileName = strdup(filename);
184
g_Data.Channels = formatCount;
186
g_Data.PixelBytes = 3; // One byte for red, one for green, and one for blue.
188
g_Data.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
189
g_Data.bmi.bmiHeader.biWidth = width;
190
g_Data.bmi.bmiHeader.biHeight = height;
191
g_Data.bmi.bmiHeader.biPlanes = 1;
192
g_Data.bmi.bmiHeader.biBitCount = 24;
193
g_Data.bmi.bmiHeader.biCompression = BI_RGB;
195
g_Data.RowSize = DWORDALIGN(width * g_Data.bmi.bmiHeader.biBitCount);
196
g_Data.bmi.bmiHeader.biSizeImage = g_Data.RowSize * height;
198
g_Data.TotalPixels = width * height;
201
// Prepare the file header
203
g_Data.bfh.bfType = 0x4D42; // ASCII "BM"
204
g_Data.bfh.bfSize = BITMAPFILEHEADER_SIZEOF +
205
sizeof(BITMAPINFOHEADER) +
206
g_Data.bmi.bmiHeader.biSizeImage;
207
g_Data.bfh.bfOffBits = BITMAPFILEHEADER_SIZEOF + sizeof(BITMAPINFOHEADER);
210
// Create a buffer for the image data (calloc clears all pixels to black)
212
g_Data.ImageData = (char *)calloc(1, g_Data.RowSize);
214
if ( ! g_Data.ImageData )
216
fprintf(stderr, "sdcBMP_DspyImageOpen_sdcBMP: Insufficient Memory\n");
217
rval = PkDspyErrorNoResource;
221
// Open the file and get ready to write.
223
g_Data.fp = fopen(g_Data.FileName, "wb");
227
fprintf(stderr, "sdcBMP_DspyImageOpen: Unable to open [%s]\n", g_Data.FileName);
228
rval = PkDspyErrorNoResource;
232
// Write out the BITMAPFILEHEADER
235
g_Data.bfh.bfType = swap2(g_Data.bfh.bfType);
236
g_Data.bfh.bfSize = swap4(g_Data.bfh.bfSize);
237
g_Data.bfh.bfOffBits = swap4(g_Data.bfh.bfOffBits);
239
if ( ! bitmapfileheader(&g_Data.bfh, g_Data.fp) )
242
fprintf(stderr, "sdcBMP_SaveBitmap: Error writing to [%s]\n", g_Data.FileName);
248
g_Data.bfh.bfType = swap2(g_Data.bfh.bfType);
249
g_Data.bfh.bfSize = swap4(g_Data.bfh.bfSize);
250
g_Data.bfh.bfOffBits = swap4(g_Data.bfh.bfOffBits);
255
g_Data.bmi.bmiHeader.biSize = swap4(g_Data.bmi.bmiHeader.biSize);
256
g_Data.bmi.bmiHeader.biWidth= swap4(g_Data.bmi.bmiHeader.biWidth);
257
g_Data.bmi.bmiHeader.biHeight= swap4(g_Data.bmi.bmiHeader.biHeight);
258
g_Data.bmi.bmiHeader.biPlanes = swap2(g_Data.bmi.bmiHeader.biPlanes);
259
g_Data.bmi.bmiHeader.biBitCount = swap2(g_Data.bmi.bmiHeader.biBitCount);
260
g_Data.bmi.bmiHeader.biCompression= swap4(g_Data.bmi.bmiHeader.biCompression);
261
g_Data.bmi.bmiHeader.biSizeImage= swap4(g_Data.bmi.bmiHeader.biSizeImage);
262
g_Data.bmi.bmiHeader.biXPelsPerMeter= swap4(g_Data.bmi.bmiHeader.biXPelsPerMeter);
263
g_Data.bmi.bmiHeader.biYPelsPerMeter= swap4(g_Data.bmi.bmiHeader.biYPelsPerMeter);
264
g_Data.bmi.bmiHeader.biClrUsed= swap4(g_Data.bmi.bmiHeader.biClrUsed);
265
g_Data.bmi.bmiHeader.biClrImportant= swap4(g_Data.bmi.bmiHeader.biClrImportant);
267
// Write out the BITMAPINFOHEADER
269
if ( ! fwrite(&g_Data.bmi.bmiHeader,
270
sizeof(BITMAPINFOHEADER),
274
fprintf(stderr, "sdcBMP_SaveBitmap: Error writing to [%s]\n", g_Data.FileName);
275
rval = PkDspyErrorNoResource;
281
g_Data.bmi.bmiHeader.biSize = swap4(g_Data.bmi.bmiHeader.biSize);
282
g_Data.bmi.bmiHeader.biWidth= swap4(g_Data.bmi.bmiHeader.biWidth);
283
g_Data.bmi.bmiHeader.biHeight= swap4(g_Data.bmi.bmiHeader.biHeight);
284
g_Data.bmi.bmiHeader.biPlanes = swap2(g_Data.bmi.bmiHeader.biPlanes);
285
g_Data.bmi.bmiHeader.biBitCount = swap2(g_Data.bmi.bmiHeader.biBitCount);
286
g_Data.bmi.bmiHeader.biCompression= swap4(g_Data.bmi.bmiHeader.biCompression);
287
g_Data.bmi.bmiHeader.biSizeImage= swap4(g_Data.bmi.bmiHeader.biSizeImage);
288
g_Data.bmi.bmiHeader.biXPelsPerMeter= swap4(g_Data.bmi.bmiHeader.biXPelsPerMeter);
289
g_Data.bmi.bmiHeader.biYPelsPerMeter= swap4(g_Data.bmi.bmiHeader.biYPelsPerMeter);
290
g_Data.bmi.bmiHeader.biClrUsed= swap4(g_Data.bmi.bmiHeader.biClrUsed);
291
g_Data.bmi.bmiHeader.biClrImportant= swap4(g_Data.bmi.bmiHeader.biClrImportant);
295
memcpy((void*) pData, (void *) &g_Data, sizeof(AppData));
299
if ( rval != PkDspyErrorNone )
311
//******************************************************************************
314
// Query the display driver for image size (if not specified in the open call)
316
//******************************************************************************
318
extern "C" PtDspyError DspyImageQuery(PtDspyImageHandle image,
319
PtDspyQueryType type,
324
fprintf(stderr, "sdcBMP_DspyImageQuery called, type: %d.\n", type);
327
AppData *pData = (AppData *)image;
328
PtDspyError ret = PkDspyErrorNone;
329
PtDspyOverwriteInfo owi;
332
if ( size > 0 && data )
336
case PkOverwriteQuery:
338
if ( size > sizeof(owi) )
344
memcpy(data, &owi, size);
349
if ( size > sizeof(si) )
354
si.width = pData->bmi.bmiHeader.biWidth;
355
si.height = pData->bmi.bmiHeader.biHeight;
356
si.aspectRatio = DEFAULT_PIXELASPECTRATIO;
360
si.width = DEFAULT_IMAGEWIDTH;
361
si.height = DEFAULT_IMAGEHEIGHT;
362
si.aspectRatio = DEFAULT_PIXELASPECTRATIO;
365
memcpy(data, &si, size);
369
ret = PkDspyErrorUnsupported;
374
ret = PkDspyErrorBadParams;
382
//******************************************************************************
385
// Send data to the display driver.
386
//******************************************************************************
387
extern "C" PtDspyError DspyImageData(PtDspyImageHandle image,
393
const unsigned char *data)
401
AppData *pData = (AppData *)image;
406
fprintf(stderr, "sdcBMP_DspyImageData called.\n");
409
if ( (ymin+1) != ymax_plusone )
411
fprintf(stderr, "sdcBMP_DspyImageData: Image data not in scanline format\n");
412
return PkDspyErrorBadParams;
415
spot = pData->bfh.bfOffBits +
416
(pData->RowSize * (pData->bmi.bmiHeader.biHeight - ymin - 1));
417
spot += pData->PixelBytes * xmin;
419
if ( fseek(pData->fp, spot, SEEK_SET) != 0 )
421
fprintf(stderr, "sdcBMP_DspyImageData: Seek failure\n");
422
return PkDspyErrorUndefined;
426
to = pData->ImageData;
428
for (x = xmin; x < xmax_plusone; x++)
430
// Extract the r, g, and b values from data
435
if ( pData->Channels == 1 )
438
if ( pData->Channels >= 3 )
440
r = data[pData->Channels - 1];
441
g = data[pData->Channels - 2];
442
b = data[pData->Channels - 3];
449
// Place the r, g, and b values into our bitmap
456
if ( ! fwrite(pData->ImageData, int(to - pData->ImageData), 1, pData->fp) )
458
fprintf(stderr, "sdcBMP_DspyImageData: Error writing file\n");
459
return PkDspyErrorUndefined;
462
return PkDspyErrorNone;
467
//******************************************************************************
469
//******************************************************************************
471
extern "C" PtDspyError DspyImageClose(PtDspyImageHandle image)
474
fprintf(stderr, "sdcBMP_DspyImageClose called.\n");
477
AppData *pData = (AppData *)image;
483
if ( pData->FileName )
484
free(pData->FileName);
485
pData->FileName = NULL;
487
if ( pData->ImageData )
488
free(pData->ImageData);
489
pData->ImageData = NULL;
493
return PkDspyErrorNone;
498
//******************************************************************************
500
//******************************************************************************
502
static int DWORDALIGN(int bits)
504
return int(((bits + 31) >> 5) << 2);
507
//******************************************************************************
509
//******************************************************************************
511
static bool ExitApplication()
514
fprintf(stderr, "sdcBMP_ExitApplication called.\n");
521
//******************************************************************************
522
// Save an header for bitmap; must be save field by field since the sizeof is 14
523
//******************************************************************************
525
static bool bitmapfileheader(BITMAPFILEHEADER *bfh, FILE *fp)
530
retval = retval && (fwrite(&bfh->bfType, 1, 2, fp) == 2);
531
retval = retval && (fwrite(&bfh->bfSize, 1, 4, fp) == 4);
532
retval = retval && (fwrite(&bfh->bfReserved1, 1, 2, fp)== 2);
533
retval = retval && (fwrite(&bfh->bfReserved2, 1, 2, fp)== 2);
534
retval = retval && (fwrite(&bfh->bfOffBits, 1, 4, fp)== 4);
541
//******************************************************************************
542
// Swap a short if you are not on NT/Pentium you must swap
543
//******************************************************************************
544
static unsigned short swap2( unsigned short s )
547
unsigned char *in, *out;
549
out = ( unsigned char* ) & n;
550
in = ( unsigned char* ) & s;
558
//******************************************************************************
559
// Swap a long if you are not on NT/Pentium you must swap
560
//******************************************************************************
561
static unsigned long swap4(unsigned long l)
564
unsigned char *c, *d;
566
c = (unsigned char*) &n;
567
d = (unsigned char*) &l;
578
//******************************************************************************
579
// Determine if we are low endian or big endian
580
//******************************************************************************
582
static bool lowendian()
584
unsigned short low = 0xFFFE;
585
unsigned char * pt = (unsigned char *) &low;
587
return (*pt == 0xFF);