source: branches/blt4/packages/vizservers/vtkvis/TGAWriter.cpp @ 2542

Last change on this file since 2542 was 2542, checked in by gah, 13 years ago

update from trunk

File size: 6.3 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2011, Purdue Research Foundation
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#include <cstdio>
9#include <cstdlib>
10#include <cstring>
11#include <cerrno>
12#include <sys/uio.h>
13
14#include <iostream>
15#include <fstream>
16
17#include "TGAWriter.h"
18#include "Trace.h"
19#ifdef USE_THREADS
20#include "ResponseQueue.h"
21#endif
22
23#ifdef USE_THREADS
24
25/**
26 * \brief Writes image command + data to supplied file descriptor.
27 *
28 * The image data must be supplied in BGR(A) order with bottom to
29 * top scanline ordering.
30 *
31 * \param[in] queue Pointer to ResponseQueue to write to
32 * \param[in] cmdName Command name to send (byte length will be appended)
33 * \param[in] data Image data
34 * \param[in] width Width of image in pixels
35 * \param[in] height Height of image in pixels
36 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
37 */
38void
39Rappture::VtkVis::queueTGA(ResponseQueue *queue, const char *cmdName,
40                           const unsigned char *data,
41                           int width, int height,
42                           int bytesPerPixel)
43{
44    TRACE("(%dx%d)\n", width, height);
45
46    size_t headerLength = 18;
47
48    char header[headerLength];
49    memset(header, 0, headerLength);
50    header[2] = (char)2;  // image type (2 = uncompressed true-color)
51    header[12] = (char)width;
52    header[13] = (char)(width >> 8);
53    header[14] = (char)height;
54    header[15] = (char)(height >> 8);
55    header[16] = (char)(bytesPerPixel*8); // bits per pixel
56
57    size_t dataLength = width * height * bytesPerPixel;
58    size_t cmdLength;
59
60    char command[200];
61    cmdLength = snprintf(command, sizeof(command), "%s %lu\n", cmdName,
62                         (unsigned long)headerLength + dataLength);
63
64    size_t length;
65    unsigned char *mesg = NULL;
66
67    length = headerLength + dataLength + cmdLength;
68    mesg = (unsigned char *)malloc(length);
69    if (mesg == NULL) {
70        ERROR("can't allocate %ld bytes for the image message", length);
71        return;
72    }
73    memcpy(mesg, command, cmdLength);
74    memcpy(mesg + cmdLength, header, headerLength);
75    memcpy(mesg + cmdLength + headerLength,
76           const_cast<unsigned char *>(data), dataLength);
77
78    Response *response = NULL;
79    if (strncmp(cmdName, "nv>legend", 9) == 0) {
80        response = new Response(Response::LEGEND);
81    } else {
82        response = new Response(Response::IMAGE);
83    }
84    response->setMessage(mesg, length, Response::DYNAMIC);
85    queue->enqueue(response);
86    TRACE("Leaving (%dx%d)\n", width, height);
87}
88#else
89
90/**
91 * \brief Writes image command + data to supplied file descriptor.
92 *
93 * The image data must be supplied in BGR(A) order with bottom to
94 * top scanline ordering.
95 *
96 * \param[in] fd File descriptor that will be written to
97 * \param[in] cmdName Command name to send (byte length will be appended)
98 * \param[in] data Image data
99 * \param[in] width Width of image in pixels
100 * \param[in] height Height of image in pixels
101 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
102 */
103void
104Rappture::VtkVis::writeTGA(int fd, const char *cmdName,
105                           const unsigned char *data,
106                           int width, int height,
107                           int bytesPerPixel)
108{
109    TRACE("(%dx%d)\n", width, height);
110
111    size_t headerLength = 18;
112
113    char header[headerLength];
114    memset(header, 0, headerLength);
115    header[2] = (char)2;  // image type (2 = uncompressed true-color)
116    header[12] = (char)width;
117    header[13] = (char)(width >> 8);
118    header[14] = (char)height;
119    header[15] = (char)(height >> 8);
120    header[16] = (char)(bytesPerPixel*8); // bits per pixel
121
122    size_t dataLength = width * height * bytesPerPixel;
123
124    char command[200];
125    snprintf(command, sizeof(command), "%s %lu\n", cmdName,
126             (unsigned long)headerLength + dataLength);
127
128    size_t nRecs = 3;
129
130    struct iovec *iov;
131    iov = (struct iovec *)malloc(sizeof(struct iovec) * nRecs);
132
133    // Write the command, then the image header and data.
134    // Command
135    iov[0].iov_base = command;
136    iov[0].iov_len = strlen(command);
137    // Header of image data
138    iov[1].iov_base = header;
139    iov[1].iov_len = headerLength;
140    // Image data **must be BGR(A)!**
141    iov[2].iov_base = const_cast<unsigned char *>(data);
142    iov[2].iov_len = dataLength;
143
144    if (writev(fd, iov, nRecs) < 0) {
145        ERROR("write failed: %s\n", strerror(errno));
146    }
147    free(iov);
148
149    TRACE("Leaving (%dx%d)\n", width, height);
150}
151#endif  /*USE_THREADS*/
152
153/**
154 * \brief Writes image data to supplied file name
155 *
156 * The image data must be supplied with bottom to top
157 * scanline ordering.  Source data should have BGR(A)
158 * ordering, unless srcIsRGB is true, in which case
159 * the source data will be converted from RGB(A) to
160 * BGR(A).  Note that this is slow and it is better
161 * to pass in BGR(A) data.
162 *
163 * \param[in] filename Path to file that will be written
164 * \param[in] imgData Image data
165 * \param[in] width Width of image in pixels
166 * \param[in] height Height of image in pixels
167 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
168 * \param[in] srcIsRGB If true source data will be re-ordered
169 */
170void
171Rappture::VtkVis::writeTGAFile(const char *filename,
172                               const unsigned char *imgData,
173                               int width, int height,
174                               int bytesPerPixel,
175                               bool srcIsRGB)
176{
177    TRACE("%s (%dx%d)\n", filename, width, height);
178
179    std::ofstream outfile(filename, std::ios::out | std::ios::binary | std::ios::trunc);
180    char header[18];
181    memset(header, 0, 18);
182    header[2] = (char)2;  // image type (2 = uncompressed true-color)
183    header[12] = (char)width;
184    header[13] = (char)(width >> 8);
185    header[14] = (char)height;
186    header[15] = (char)(height >> 8);
187    header[16] = (char)(bytesPerPixel*8); // bits per pixel
188
189    outfile.write(header, sizeof(header));
190
191    if (!srcIsRGB) {
192        outfile.write((const char *)imgData, width * height * bytesPerPixel);
193    } else {
194        // RGB(A) -> BGR(A)
195        for (int i = 0; i < width * height; i++) {
196            outfile << imgData[i*bytesPerPixel+2]
197                    << imgData[i*bytesPerPixel+1]
198                    << imgData[i*bytesPerPixel];
199            if (bytesPerPixel == 4) {
200                outfile << imgData[i*bytesPerPixel+3];
201            }
202        }
203    }
204
205    outfile.close();
206}
Note: See TracBrowser for help on using the repository browser.