source: trunk/src/testing/app/FileViewer/ImageViewer/imageviewer.cpp @ 4

Revision 4, 9.6 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1/*****************************************************************************************
2 * imageviewer: loads an image and sends it to SAGE for display
3 *
4 * Copyright (C) 2007 Electronic Visualization Laboratory,
5 * University of Illinois at Chicago
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above
15 *    copyright notice, this list of conditions and the following disclaimer
16 *    in the documentation and/or other materials provided with the distribution.
17 *  * Neither the name of the University of Illinois at Chicago nor
18 *    the names of its contributors may be used to endorse or promote
19 *    products derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Direct questions, comments etc to www.evl.uic.edu/cavern/forum
34 *
35 * Author: Ratko Jagodic, Luc Renambot
36 *
37 *****************************************************************************************/
38
39
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <string>
44#include <time.h>
45#include <unistd.h>
46#include <wand/magick-wand.h>
47
48// headers for SAGE
49#include "sail.h"
50#include "misc.h"
51
52
53//#if MagickLibVersion >= 0x645
54//#define MagickGetImagePixels MagickGetAuthenticPixels
55//#endif
56
57
58#ifdef USE_DXT
59
60// for dxt compression
61#include "libdxt.h"
62// if true, it will show the original image and not the dxt compressed one
63bool loadDXT = true;
64
65#else
66
67bool loadDXT = false;
68typedef unsigned char byte;
69#define memalign(x,y) malloc((y))
70
71#endif
72
73
74using namespace std;
75
76
77#define ThrowWandException(wand)                \
78  {                                             \
79    char                                        \
80      *description;                             \
81                                                \
82    ExceptionType                               \
83      severity;                                 \
84                                                    \
85    description=MagickGetException(wand,&severity);                     \
86    (void) fprintf(stderr,"%s %s %ld %s\n",GetMagickModule(),description); \
87    description=(char *) MagickRelinquishMemory(description);           \
88    exit(-1);                                                           \
89  }
90
91
92// -----------------------------------------------------------------------------
93
94#ifdef USE_DXT
95void readDXT(string fileName, byte **buffer, unsigned int &width,
96             unsigned int &height)
97{
98    unsigned long r;
99    unsigned int numBytes;
100    FILE *f = fopen(fileName.data(), "rb");
101
102    // read the size of the image from the first 8 bytes
103    r = fread(&width, sizeof(unsigned int), 1, f);
104    r = fread(&height, sizeof(unsigned int), 1, f);
105    r = fread(&numBytes, sizeof(unsigned int), 1, f);
106
107    // allocate buffer size and read the rest of the file into it
108    *buffer = (byte*) malloc(width*height*4/8);
109    memset(*buffer, 0, width*height*4/8);
110    r = fread(*buffer, 1, width*height*4/8, f);
111    fclose(f);
112}
113
114
115void writeDXT(string fileName, byte *buffer, unsigned int width,
116              unsigned int height, unsigned int numBytes)
117{
118    fprintf(stderr, "\n**** Writing DXT to file... %u bytes", numBytes);
119
120    unsigned long r;
121    FILE *f = fopen(fileName.data(), "wb");
122
123    if (f != NULL)
124    {
125        // write the size of the image in the first 8 bytes
126        r = fwrite(&width, sizeof(unsigned int), 1, f);
127        r = fwrite(&height, sizeof(unsigned int), 1, f);
128        r = fwrite(&numBytes, sizeof(unsigned int), 1, f);
129
130        // write the buffer out to the file
131        r = fwrite(buffer, 1, numBytes, f);
132        fclose(f);
133    }
134    else
135        fprintf(stderr, "\n**** Imageviewer ERROR: Unable to write DXT file. Check dir permissions.\n");
136}
137#endif
138
139
140void getRGBA(string fileName, byte **rgba, unsigned int &width,
141              unsigned int &height)
142{
143    // use ImageMagick to read all other formats
144    MagickBooleanType status;
145    MagickWand *wand;
146
147    // read file
148    wand=NewMagickWand();
149    status=MagickReadImage(wand, fileName.data());
150    if (status == MagickFalse)
151        ThrowWandException(wand);
152
153    // get the image size
154    width = MagickGetImageWidth(wand);
155    height = MagickGetImageHeight(wand);
156
157    // crop the image if necessary to make sure it's a multiple of 4
158    if (loadDXT)
159    {
160        if (width%4 != 0 || height%4 != 0)
161        {
162            fprintf(stderr, "\n**** Image cropped a few pixels to be a multiple of 4 for dxt");
163            width -= width%4;
164            height -= height%4;
165        }
166
167        // flip the image to have the correct orientation for dxt
168        MagickFlipImage(wand);
169    }
170
171    // get the pixels
172    *rgba = (byte*) memalign(16, width*height*4);
173    memset(*rgba, 0, width*height*4);
174    MagickGetImagePixels(wand, 0, 0, width, height, "RGBA", CharPixel, *rgba);
175    DestroyMagickWand(wand);
176}
177
178#ifdef USE_DXT
179void rgbaToDXT(string fileName, byte **rgba, byte **dxt, unsigned int width,
180               unsigned int height)
181{
182    unsigned int numBytes;
183
184    // compress into DXT
185    *dxt = (byte*) memalign(16, width*height*4/8);
186    memset(*dxt, 0, width*height*4/8);
187    numBytes = CompressDXT(*rgba, *dxt, width, height, FORMAT_DXT1, 1);
188
189    // write this DXT out to a file (change extension to .dxt)
190    string dxtFileName = string(fileName);
191    dxtFileName.resize(fileName.rfind("."));
192    dxtFileName += ".dxt";
193    writeDXT(dxtFileName, *dxt, width, height, numBytes);
194}
195
196
197bool dxtFileExists(string fileName)
198{
199    // replace the extension with .dxt
200    string dxtFileName = string(fileName);
201    dxtFileName.resize(fileName.rfind("."));
202    dxtFileName += ".dxt";
203
204    // check whether the file exists by trying to open it
205    FILE *dxtFile = fopen(dxtFileName.data(), "r");
206    if ( dxtFile == NULL)
207    {
208        fprintf(stderr, "\nDXT file for %s doesn't exist yet.", fileName.data());
209        return false;
210    }
211    else
212    {
213        fclose(dxtFile);
214        return true;
215    }
216}
217#endif
218
219// -----------------------------------------------------------------------------
220
221
222
223int main(int argc,char **argv)
224{
225    byte *sageBuffer = NULL;  // buffers for sage and dxt data
226    byte *dxt = NULL;
227    byte *rgba = NULL;
228    unsigned int width, height;  // image size
229    unsigned int window_width=0, window_height=0;  // sage window size
230
231
232    // parse command line arguments
233    if (argc < 2){
234        fprintf(stderr, "\n\nUSAGE: imageviewer filename [width] [height] [-show_original]");
235        return 0;
236    }
237    for (int argNum=2; argNum<argc; argNum++)
238    {
239        if (strcmp(argv[argNum], "-show_original") == 0) {
240            loadDXT = false;
241        }
242        else if(atoi(argv[argNum]) != 0 && atoi(argv[argNum+1]) != 0) {
243            window_width = atoi( argv[argNum] );
244            window_height = atoi( argv[argNum+1] );
245            argNum++;  // increment because we read two args here
246        }
247    }
248
249
250    // check file extension
251    string fileName, fileExt;
252    fileName = string(argv[1]);
253    fileExt = fileName.substr(fileName.rfind("."));
254
255    // if image is in DXT load it directly, otherwise compress and load
256    if(fileExt.compare(".dxt") == 0)   // DXT
257#ifndef USE_DXT
258    {
259        fprintf(stderr, "\n\nImageviewer was not compiled with DXT option\n");
260        exit(0);
261    }
262#else
263        readDXT(fileName, &dxt, width, height);
264
265    else if(loadDXT && dxtFileExists(fileName))
266    {
267        // replace the extension with .dxt and read the file
268        string dxtFileName = string(fileName);
269        dxtFileName.resize(fileName.rfind("."));
270        dxtFileName += ".dxt";
271        readDXT(dxtFileName, &dxt, width, height);
272    }
273#endif
274    else                               // all other image formats
275    {
276        getRGBA(fileName, &rgba, width, height);
277        #ifdef USE_DXT
278        if (loadDXT)
279        {
280            rgbaToDXT(fileName, &rgba, &dxt, width, height);
281            free(rgba);
282            rgba = NULL;
283        }
284        #endif
285    }
286
287    // if the user didn't specify the window size, use the image size
288    if (window_height == 0 && window_width == 0)
289    {
290        window_width = width;
291        window_height = height;
292    }
293
294    // initialize SAIL
295    sail sageInf; // sail object
296    sailConfig scfg;
297    scfg.init("imageviewer.conf");
298    scfg.setAppName("imageviewer");
299
300    scfg.resX = width;
301    scfg.resY = height;
302
303    if (scfg.winWidth == -1 || scfg.winHeight == -1)
304    {
305        scfg.winWidth = window_width;
306        scfg.winHeight = window_height;
307    }
308
309    if (loadDXT)
310    {
311        scfg.pixFmt = PIXFMT_DXT;
312        scfg.rowOrd = BOTTOM_TO_TOP;
313    }
314    else
315    {
316        scfg.pixFmt = PIXFMT_8888;
317        scfg.rowOrd = TOP_TO_BOTTOM;
318    }
319    sageInf.init(scfg);
320
321
322    // get buffer from SAGE and fill it with dxt data
323    sageBuffer = (byte*)sageInf.getBuffer();
324    if (loadDXT)
325        memcpy(sageBuffer, dxt, width*height*4/8);
326    else
327        memcpy(sageBuffer, rgba, width*height*4);
328    sageInf.swapBuffer();
329
330    // a second time for the backbuffer
331    /* doesn't need with END_FRAME fix
332    sageBuffer = (byte*)sageInf.getBuffer();
333    if (loadDXT)
334        memcpy(sageBuffer, dxt, width*height*4/8);
335    else
336        memcpy(sageBuffer, rgba, width*height*4);
337    sageInf.swapBuffer();
338    */
339
340    // release the memory
341    free(dxt);
342    free(rgba);
343
344
345    // Wait the end
346    while (1)
347    {
348        usleep(500000);  // so that we don't keep spinning too frequently (0.5s)
349        sageMessage msg;
350        if (sageInf.checkMsg(msg, false) > 0) {
351            switch (msg.getCode()) {
352            case APP_QUIT:
353                sageInf.shutdown();
354                exit(1);
355                break;
356            }
357        }
358    }
359
360    return 0;
361}
Note: See TracBrowser for help on using the repository browser.