~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to filebuffer/filebuffer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Aqsis
 
2
// Copyright ļæ½ 1997 - 2001, Paul C. Gregory
 
3
//
 
4
// Contact: pgregory@aqsis.com
 
5
//
 
6
// This library is free software; you can redistribute it and/or
 
7
// modify it under the terms of the GNU General Public
 
8
// License as published by the Free Software Foundation; either
 
9
// version 2 of the License, or (at your option) any later version.
 
10
//
 
11
// This library is distributed in the hope that it will be useful,
 
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
// General Public License for more details.
 
15
//
 
16
// You should have received a copy of the GNU General Public
 
17
// License along with this library; if not, write to the Free Software
 
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 
 
20
 
 
21
/** \file
 
22
                \brief Implements a TIFF based display driver.
 
23
                \author Paul C. Gregory (pgregory@aqsis.com)
 
24
*/
 
25
 
 
26
#include        <iostream>
 
27
#include        <stdlib.h>
 
28
#include        <memory>
 
29
 
 
30
#include        "aqsis.h"
 
31
#include        "logging.h"
 
32
#include        "logging_streambufs.h"
 
33
 
 
34
#if defined(AQSIS_SYSTEM_WIN32) || defined(AQSIS_SYSTEM_MACOSX)
 
35
#include        <version.h>
 
36
#endif
 
37
 
 
38
#ifdef AQSIS_SYSTEM_WIN32
 
39
 
 
40
#include        <process.h>
 
41
 
 
42
#else // AQSIS_SYSTEM_WIN32
 
43
 
 
44
typedef int SOCKET;
 
45
 
 
46
#endif // !AQSIS_SYSTEM_WIN32
 
47
 
 
48
#include        "displaydriver.h"
 
49
#include        "dd.h"
 
50
#include        "tiffio.h"
 
51
#include        "sstring.h"
 
52
 
 
53
using namespace Aqsis;
 
54
 
 
55
/// Static response message for a format query.
 
56
SqDDMessageFormatResponse frmt( 2 );
 
57
/// Static response message close message.
 
58
SqDDMessageCloseAcknowledge closeack;
 
59
 
 
60
/** Handle a query message from the manager.
 
61
 */
 
62
TqInt Query( SOCKET s, SqDDMessageBase* pMsg );
 
63
/** Handle an open message from the handler.
 
64
 */
 
65
TqInt Open( SOCKET s, SqDDMessageBase* pMsg );
 
66
/** Handle a data message from the manager.
 
67
 */
 
68
TqInt Data( SOCKET s, SqDDMessageBase* pMsg );
 
69
/** Handle a close message from the manager.
 
70
 */
 
71
TqInt Close( SOCKET s, SqDDMessageBase* pMsg );
 
72
/** Handle an abandon message from the manager.
 
73
 */
 
74
TqInt Abandon( SOCKET s, SqDDMessageBase* pMsg );
 
75
 
 
76
 
 
77
/// Main loop,, just cycle handling any recieved messages.
 
78
int main( int argc, char* argv[] )
 
79
{
 
80
    std::auto_ptr<std::streambuf> reset_level( new Aqsis::reset_level_buf(std::cerr) );
 
81
    std::auto_ptr<std::streambuf> show_timestamps( new Aqsis::timestamp_buf(std::cerr) );
 
82
    std::auto_ptr<std::streambuf> fold_duplicates( new Aqsis::fold_duplicates_buf(std::cerr) );
 
83
    std::auto_ptr<std::streambuf> show_level( new Aqsis::show_level_buf(std::cerr) );
 
84
    std::auto_ptr<std::streambuf> filter_level( new Aqsis::filter_by_level_buf(Aqsis::WARNING, std::cerr) );
 
85
 
 
86
    int port = -1;
 
87
    char *portStr = getenv( "AQSIS_DD_PORT" );
 
88
 
 
89
    if ( portStr != NULL )
 
90
    {
 
91
        port = atoi( portStr );
 
92
    }
 
93
 
 
94
    if ( DDInitialise( NULL, port ) == 0 )
 
95
    {
 
96
        DDProcessMessages();
 
97
    }
 
98
    else
 
99
    {
 
100
        std::cerr << error << "Could not open communications channel to Aqsis" << std::endl;
 
101
        return 1;
 
102
    }
 
103
 
 
104
    return 0;
 
105
}
 
106
 
 
107
 
 
108
TqInt   XRes, YRes;
 
109
TqInt   g_Channels;
 
110
TqInt   g_Format;
 
111
// BitsPerSample;
 
112
unsigned char* pByteData;
 
113
float*  pFloatData;
 
114
TIFF*   pOut;
 
115
TqInt   g_CWXmin, g_CWYmin;
 
116
TqInt   g_CWXmax, g_CWYmax;
 
117
uint16  compression = COMPRESSION_NONE, quality = 0;
 
118
TqFloat quantize_zeroval = 0.0f;
 
119
TqFloat quantize_oneval  = 0.0f;
 
120
TqFloat quantize_minval  = 0.0f;
 
121
TqFloat quantize_maxval  = 0.0f;
 
122
TqFloat dither_val       = 0.0f;
 
123
 
 
124
/// Storage for the output file name.
 
125
std::string     strFilename( "output.tif" );
 
126
 
 
127
TqInt Query( SOCKET s, SqDDMessageBase* pMsgB )
 
128
{
 
129
    switch ( pMsgB->m_MessageID )
 
130
    {
 
131
    case MessageID_FormatQuery:
 
132
        {
 
133
            SqDDMessageFormatQuery* pMsg = static_cast<SqDDMessageFormatQuery*>(pMsgB);
 
134
            g_Format = pMsg->m_Formats[0];
 
135
            frmt.m_DataFormat = g_Format;
 
136
            if ( DDSendMsg( s, &frmt ) <= 0 )
 
137
                return ( -1 );
 
138
            // Create a buffer big enough to hold a row of buckets.
 
139
            pByteData = NULL;
 
140
            pFloatData = NULL;
 
141
            if ( g_Format == DataFormat_Unsigned8 )
 
142
                pByteData = new unsigned char[ XRes * YRes * g_Channels ];
 
143
            else
 
144
                pFloatData = new float[ XRes * YRes * g_Channels ];
 
145
        }
 
146
        break;
 
147
    }
 
148
    return ( 0 );
 
149
}
 
150
 
 
151
TqInt Open( SOCKET s, SqDDMessageBase* pMsgB )
 
152
{
 
153
    SqDDMessageOpen * pMsg = static_cast<SqDDMessageOpen*>( pMsgB );
 
154
 
 
155
    XRes = ( pMsg->m_CropWindowXMax - pMsg->m_CropWindowXMin );
 
156
    YRes = ( pMsg->m_CropWindowYMax - pMsg->m_CropWindowYMin );
 
157
    g_Channels = pMsg->m_Channels;
 
158
    //  BitsPerSample = pMsg->m_BitsPerSample;
 
159
 
 
160
    g_CWXmin = pMsg->m_CropWindowXMin;
 
161
    g_CWYmin = pMsg->m_CropWindowYMin;
 
162
    g_CWXmax = pMsg->m_CropWindowXMax;
 
163
    g_CWYmax = pMsg->m_CropWindowYMax;
 
164
 
 
165
    return ( 0 );
 
166
}
 
167
 
 
168
 
 
169
TqInt Data( SOCKET s, SqDDMessageBase* pMsgB )
 
170
{
 
171
    SqDDMessageData * pMsg = static_cast<SqDDMessageData*>( pMsgB );
 
172
 
 
173
    TqInt       linelen = XRes * g_Channels;
 
174
    char* pBucket = reinterpret_cast<char*>( &pMsg->m_Data );
 
175
 
 
176
    SqDDMessageData * const message = static_cast<SqDDMessageData*>( pMsgB );
 
177
 
 
178
    // CHeck if the beck is not at all within the crop window.
 
179
    if ( message->m_XMin > g_CWXmax || message->m_XMaxPlus1 < g_CWXmin ||
 
180
            message->m_YMin > g_CWYmax || message->m_YMaxPlus1 < g_CWYmin )
 
181
        return ( 0 );
 
182
 
 
183
    TqInt y;
 
184
    for ( y = pMsg->m_YMin - g_CWYmin; y < pMsg->m_YMaxPlus1 - g_CWYmin; y++ )
 
185
    {
 
186
        TqInt x;
 
187
        for ( x = pMsg->m_XMin - g_CWXmin; x < pMsg->m_XMaxPlus1 - g_CWXmin; x++ )
 
188
        {
 
189
            if ( x >= 0 && y >= 0 && x < XRes && y < YRes )
 
190
            {
 
191
                TqInt so = ( y * linelen ) + ( x * g_Channels );
 
192
 
 
193
                TqInt i = 0;
 
194
                while ( i < g_Channels )
 
195
                {
 
196
                    TqFloat value = reinterpret_cast<TqFloat*>( pBucket ) [ i ];
 
197
 
 
198
                    if( !( quantize_zeroval == 0.0f &&
 
199
                            quantize_oneval  == 0.0f &&
 
200
                            quantize_minval  == 0.0f &&
 
201
                            quantize_maxval  == 0.0f ) )
 
202
                    {
 
203
                        value = ROUND(quantize_zeroval + value * (quantize_oneval - quantize_zeroval) + dither_val );
 
204
                        value = CLAMP(value, quantize_minval, quantize_maxval) ;
 
205
                    }
 
206
 
 
207
                                        if ( g_Format == DataFormat_Unsigned8 )
 
208
                                        {
 
209
                                                if( NULL != pByteData )
 
210
                                                        pByteData[ so ] = static_cast<char>( value );
 
211
                                        }
 
212
                                        else
 
213
                                        {
 
214
                                                if( NULL != pFloatData )
 
215
                                                        pFloatData[ so ] = value;
 
216
                                        }
 
217
                    so++;
 
218
                    i++;
 
219
                }
 
220
            }
 
221
            pBucket += pMsg->m_ElementSize;
 
222
        }
 
223
    }
 
224
    return ( 0 );
 
225
}
 
226
 
 
227
 
 
228
TqInt Close( SOCKET s, SqDDMessageBase* pMsgB )
 
229
{
 
230
    uint16 photometric = PHOTOMETRIC_RGB;
 
231
    uint16 config = PLANARCONFIG_CONTIG;
 
232
    SqDDMessageClose *pClose = ( SqDDMessageClose * ) pMsgB;
 
233
 
 
234
    pOut = TIFFOpen( strFilename.c_str(), "w" );
 
235
 
 
236
    if ( pOut )
 
237
    {
 
238
        // Write the image to a tiff file.
 
239
        char version[ 80 ];
 
240
 
 
241
        int ExtraSamplesTypes[ 1 ] = {EXTRASAMPLE_ASSOCALPHA};
 
242
 
 
243
#if defined(AQSIS_SYSTEM_WIN32) || defined(AQSIS_SYSTEM_MACOSX)
 
244
        sprintf( version, "%s %s", STRNAME, VERSION_STR );
 
245
#else
 
246
        sprintf( version, "%s %s", STRNAME, VERSION );
 
247
#endif
 
248
 
 
249
        bool use_logluv = false;
 
250
 
 
251
        // Set common tags
 
252
        TIFFSetField( pOut, TIFFTAG_SOFTWARE, ( uint32 ) version );
 
253
        TIFFSetField( pOut, TIFFTAG_IMAGEWIDTH, ( uint32 ) XRes );
 
254
        TIFFSetField( pOut, TIFFTAG_IMAGELENGTH, ( uint32 ) YRes );
 
255
        TIFFSetField( pOut, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
 
256
        TIFFSetField( pOut, TIFFTAG_SAMPLESPERPIXEL, g_Channels );
 
257
 
 
258
        // Write out an 8 bits per pixel integer image.
 
259
        if ( g_Format == DataFormat_Unsigned8 )
 
260
        {
 
261
            TIFFSetField( pOut, TIFFTAG_BITSPERSAMPLE, 8 );
 
262
            TIFFSetField( pOut, TIFFTAG_PLANARCONFIG, config );
 
263
            TIFFSetField( pOut, TIFFTAG_COMPRESSION, compression );
 
264
            if ( compression == COMPRESSION_JPEG )
 
265
                TIFFSetField( pOut, TIFFTAG_JPEGQUALITY, quality );
 
266
            //if (description != "")
 
267
            //TIFFSetField(TIFFTAG_IMAGEDESCRIPTION, description);
 
268
            TIFFSetField( pOut, TIFFTAG_PHOTOMETRIC, photometric );
 
269
            TIFFSetField( pOut, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize( pOut, 0 ) );
 
270
 
 
271
            if ( g_Channels == 4 )
 
272
                TIFFSetField( pOut, TIFFTAG_EXTRASAMPLES, 1, ExtraSamplesTypes );
 
273
 
 
274
            // Set the position tages in case we aer dealing with a cropped image.
 
275
            TIFFSetField( pOut, TIFFTAG_XPOSITION, ( float ) g_CWXmin );
 
276
            TIFFSetField( pOut, TIFFTAG_YPOSITION, ( float ) g_CWYmin );
 
277
 
 
278
            TqInt       linelen = XRes * g_Channels;
 
279
            TqInt row;
 
280
            for ( row = 0; row < YRes; row++ )
 
281
            {
 
282
                if ( TIFFWriteScanline( pOut, pByteData + ( row * linelen ), row, 0 ) < 0 )
 
283
                    break;
 
284
            }
 
285
            TIFFClose( pOut );
 
286
        }
 
287
        else
 
288
        {
 
289
            // Write out a floating point image.
 
290
            TIFFSetField( pOut, TIFFTAG_STONITS, ( double ) 1.0 );
 
291
 
 
292
            //                  if(/* user wants logluv compression*/)
 
293
            //                  {
 
294
            //                          if(/* user wants to save the alpha channel */)
 
295
            //                          {
 
296
            //                                  warn("SGI LogLuv encoding does not allow an alpha channel"
 
297
            //                                                  " - using uncompressed IEEEFP instead");
 
298
            //                          }
 
299
            //                          else
 
300
            //                          {
 
301
            //                                  use_logluv = true;
 
302
            //                          }
 
303
            //
 
304
            //                          if(/* user wants LZW compression*/)
 
305
            //                          {
 
306
            //                                  warn("LZW compression is not available with SGI LogLuv encoding\n");
 
307
            //                          }
 
308
            //                  }
 
309
 
 
310
            if ( use_logluv )
 
311
            {
 
312
                /* use SGI LogLuv compression */
 
313
                TIFFSetField( pOut, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT );
 
314
                TIFFSetField( pOut, TIFFTAG_BITSPERSAMPLE, 16 );
 
315
                TIFFSetField( pOut, TIFFTAG_COMPRESSION, COMPRESSION_SGILOG );
 
316
                TIFFSetField( pOut, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_LOGLUV );
 
317
                TIFFSetField( pOut, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT );
 
318
            }
 
319
            else
 
320
            {
 
321
                /* use uncompressed IEEEFP pixels */
 
322
                TIFFSetField( pOut, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP );
 
323
                TIFFSetField( pOut, TIFFTAG_BITSPERSAMPLE, 32 );
 
324
                TIFFSetField( pOut, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
 
325
                TIFFSetField( pOut, TIFFTAG_COMPRESSION, compression );
 
326
            }
 
327
 
 
328
            TIFFSetField( pOut, TIFFTAG_SAMPLESPERPIXEL, g_Channels );
 
329
 
 
330
            if ( g_Channels == 4 )
 
331
                TIFFSetField( pOut, TIFFTAG_EXTRASAMPLES, 1, ExtraSamplesTypes );
 
332
            // Set the position tages in case we aer dealing with a cropped image.
 
333
            TIFFSetField( pOut, TIFFTAG_XPOSITION, ( float ) g_CWXmin );
 
334
            TIFFSetField( pOut, TIFFTAG_YPOSITION, ( float ) g_CWYmin );
 
335
            TIFFSetField( pOut, TIFFTAG_PLANARCONFIG, config );
 
336
 
 
337
            TqInt       linelen = XRes * g_Channels;
 
338
            TqInt row = 0;
 
339
            for ( row = 0; row < YRes; row++ )
 
340
            {
 
341
                if ( TIFFWriteScanline( pOut, pFloatData + ( row * linelen ), row, 0 ) < 0 )
 
342
                    break;
 
343
            }
 
344
            TIFFClose( pOut );
 
345
        }
 
346
    }
 
347
 
 
348
    delete[] ( pByteData );
 
349
    delete[] ( pFloatData );
 
350
 
 
351
    if ( DDSendMsg( s, &closeack ) <= 0 )
 
352
        return ( -1 );
 
353
    else
 
354
        return ( 1 );
 
355
}
 
356
 
 
357
 
 
358
TqInt Abandon( SOCKET s, SqDDMessageBase* pMsgB )
 
359
{
 
360
    return ( 1 );
 
361
}
 
362
 
 
363
 
 
364
/** Handle a general message from the manager.
 
365
 */
 
366
TqInt HandleMessage( SOCKET s, SqDDMessageBase* pMsgB )
 
367
{
 
368
    switch ( pMsgB->m_MessageID )
 
369
    {
 
370
    case MessageID_Filename:
 
371
        {
 
372
            SqDDMessageFilename * pMsg = static_cast<SqDDMessageFilename*>( pMsgB );
 
373
            strFilename = pMsg->m_String;
 
374
        }
 
375
        break;
 
376
 
 
377
    case MessageID_UserParam:
 
378
        {
 
379
            SqDDMessageUserParam * pMsg = static_cast<SqDDMessageUserParam*>( pMsgB );
 
380
            // Check if we understand the parameter.
 
381
            if( strncmp( pMsg->m_NameAndData, "compression", pMsg->m_NameLength ) == 0 )
 
382
            {
 
383
                const char* pvalue = reinterpret_cast<const char*>( &pMsg->m_NameAndData[ pMsg->m_NameLength + 1 ] );
 
384
                if ( strstr( pvalue, "none" ) != 0 )
 
385
                    compression = COMPRESSION_NONE;
 
386
                else if ( strstr( pvalue, "lzw" ) != 0 )
 
387
                    compression = COMPRESSION_LZW;
 
388
                else if ( strstr( pvalue, "deflate" ) != 0 )
 
389
                    compression = COMPRESSION_DEFLATE;
 
390
                else if ( strstr( pvalue, "jpeg" ) != 0 )
 
391
                    compression = COMPRESSION_JPEG;
 
392
                else if ( strstr( pvalue, "packbits" ) != 0 )
 
393
                    compression = COMPRESSION_PACKBITS;
 
394
            }
 
395
            else if( strncmp( pMsg->m_NameAndData, "quality", pMsg->m_NameLength ) == 0 )
 
396
            {
 
397
                quality = *reinterpret_cast<TqInt*>( &pMsg->m_NameAndData[ pMsg->m_NameLength + 1 ] );
 
398
                if ( quality > 100 )    quality = 100;
 
399
            }
 
400
            else if( strncmp( pMsg->m_NameAndData, "quantize", pMsg->m_NameLength ) == 0 )
 
401
            {
 
402
                TqFloat* quantize = reinterpret_cast<TqFloat*>( &pMsg->m_NameAndData[ pMsg->m_NameLength + 1 ] );
 
403
                quantize_zeroval = quantize[0];
 
404
                quantize_oneval  = quantize[1];
 
405
                quantize_minval  = quantize[2];
 
406
                quantize_maxval  = quantize[3];
 
407
            }
 
408
        }
 
409
        break;
 
410
    }
 
411
    return ( 0 );
 
412
}