source: geovis/trunk/TGAWriter.cpp @ 4626

Last change on this file since 4626 was 4028, checked in by ldelgass, 11 years ago

Add map layer commands

File size: 6.2 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2013  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
39GeoVis::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, data, dataLength);
76
77    Response *response = NULL;
78    if (strncmp(cmdName, "nv>legend", 9) == 0) {
79        response = new Response(Response::LEGEND);
80    } else {
81        response = new Response(Response::IMAGE);
82    }
83    response->setMessage(mesg, length, Response::DYNAMIC);
84    queue->enqueue(response);
85    TRACE("Leaving (%dx%d)\n", width, height);
86}
87#else
88
89/**
90 * \brief Writes image command + data to supplied file descriptor.
91 *
92 * The image data must be supplied in BGR(A) order with bottom to
93 * top scanline ordering.
94 *
95 * \param[in] fd File descriptor that will be written to
96 * \param[in] cmdName Command name to send (byte length will be appended)
97 * \param[in] data Image data
98 * \param[in] width Width of image in pixels
99 * \param[in] height Height of image in pixels
100 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
101 */
102void
103GeoVis::writeTGA(int fd, const char *cmdName,
104                 const unsigned char *data,
105                 int width, int height,
106                 int bytesPerPixel)
107{
108    TRACE("(%dx%d)\n", width, height);
109
110    size_t headerLength = 18;
111
112    char header[headerLength];
113    memset(header, 0, headerLength);
114    header[2] = (char)2;  // image type (2 = uncompressed true-color)
115    header[12] = (char)width;
116    header[13] = (char)(width >> 8);
117    header[14] = (char)height;
118    header[15] = (char)(height >> 8);
119    header[16] = (char)(bytesPerPixel*8); // bits per pixel
120
121    size_t dataLength = width * height * bytesPerPixel;
122
123    char command[200];
124    snprintf(command, sizeof(command), "%s %lu\n", cmdName,
125             (unsigned long)headerLength + dataLength);
126
127    size_t nRecs = 3;
128
129    struct iovec *iov;
130    iov = (struct iovec *)malloc(sizeof(struct iovec) * nRecs);
131
132    // Write the command, then the image header and data.
133    // Command
134    iov[0].iov_base = command;
135    iov[0].iov_len = strlen(command);
136    // Header of image data
137    iov[1].iov_base = header;
138    iov[1].iov_len = headerLength;
139    // Image data **must be BGR(A)!**
140    iov[2].iov_base = const_cast<unsigned char *>(data);
141    iov[2].iov_len = dataLength;
142
143    if (writev(fd, iov, nRecs) < 0) {
144        ERROR("write failed: %s\n", strerror(errno));
145    }
146    free(iov);
147
148    TRACE("Leaving (%dx%d)\n", width, height);
149}
150#endif  /*USE_THREADS*/
151
152/**
153 * \brief Writes image data to supplied file name
154 *
155 * The image data must be supplied with bottom to top
156 * scanline ordering.  Source data should have BGR(A)
157 * ordering, unless srcIsRGB is true, in which case
158 * the source data will be converted from RGB(A) to
159 * BGR(A).  Note that this is slow and it is better
160 * to pass in BGR(A) data.
161 *
162 * \param[in] filename Path to file that will be written
163 * \param[in] imgData Image data
164 * \param[in] width Width of image in pixels
165 * \param[in] height Height of image in pixels
166 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
167 * \param[in] srcIsRGB If true source data will be re-ordered
168 */
169void
170GeoVis::writeTGAFile(const char *filename,
171                     const unsigned char *imgData,
172                     int width, int height,
173                     int bytesPerPixel,
174                     bool srcIsRGB)
175{
176    TRACE("%s (%dx%d)\n", filename, width, height);
177
178    std::ofstream outfile(filename, std::ios::out | std::ios::binary | std::ios::trunc);
179    char header[18];
180    memset(header, 0, 18);
181    header[2] = (char)2;  // image type (2 = uncompressed true-color)
182    header[12] = (char)width;
183    header[13] = (char)(width >> 8);
184    header[14] = (char)height;
185    header[15] = (char)(height >> 8);
186    header[16] = (char)(bytesPerPixel*8); // bits per pixel
187
188    outfile.write(header, sizeof(header));
189
190    if (!srcIsRGB) {
191        outfile.write((const char *)imgData, width * height * bytesPerPixel);
192    } else {
193        // RGB(A) -> BGR(A)
194        for (int i = 0; i < width * height; i++) {
195            outfile << imgData[i*bytesPerPixel+2]
196                    << imgData[i*bytesPerPixel+1]
197                    << imgData[i*bytesPerPixel];
198            if (bytesPerPixel == 4) {
199                outfile << imgData[i*bytesPerPixel+3];
200            }
201        }
202    }
203
204    outfile.close();
205}
Note: See TracBrowser for help on using the repository browser.