source: branches/Rappture 1.2/packages/vizservers/vtkvis/TGAWriter.cpp @ 3208

Last change on this file since 3208 was 3177, checked in by mmc, 12 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

  • Property svn:eol-style set to native
File size: 6.3 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2012  HUBzero Foundation, LLC
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.