wiretap 0.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +2 -1
- data/ext/Makefile +27 -24
- data/ext/audio_format.cpp +10 -8
- data/ext/charstream.h +41 -0
- data/ext/extconf.rb +8 -10
- data/ext/frame_io.cpp +120 -0
- data/ext/frame_io.h +45 -0
- data/ext/image_format.cpp +49 -169
- data/ext/image_io.cpp +466 -0
- data/ext/image_io.h +73 -0
- data/ext/node.cpp +71 -48
- data/ext/nodeframes.cpp +36 -34
- data/ext/nodemetadata.cpp +21 -3
- data/ext/server.cpp +2 -2
- data/ext/serverlist.cpp +20 -8
- data/ext/wiretap.cpp +11 -8
- data/ext/wiretap.h +17 -13
- data/lib/wiretap.rb +65 -5
- data/test_new/common.rb +8 -0
- data/{test/wiretap-images → test_new/fixtures/img/ppm-8bit}/01.ppm +0 -0
- data/test_new/fixtures/raw/cube_2k_12bitP_1f/0.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_2k_8bit_1f/0.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_10bit_5f/0.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_10bit_5f/1.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_10bit_5f/2.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_10bit_5f/3.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_10bit_5f/4.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitP_5f/0.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitP_5f/1.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitP_5f/2.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitP_5f/3.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitP_5f/4.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitU_5f/0.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitU_5f/1.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitU_5f/2.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitU_5f/3.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_12bitU_5f/4.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/0.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/1.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/2.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/3.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/4.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/5.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/6.stoneimage +0 -0
- data/test_new/fixtures/raw/cube_SD_8bit_8f/7.stoneimage +0 -0
- data/{test/wiretap-images/b1.stonesound → test_new/fixtures/raw-snd/simple.stonesound} +0 -0
- data/{test/wiretap-images/output.wav → test_new/fixtures/snd/simple-wave.wav} +0 -0
- data/test_new/test_audio_conversions.rb +28 -0
- data/test_new/test_image_conversions.rb +132 -0
- data/test_new/test_parts/connect_to_test_host.rb +27 -0
- data/test_new/test_parts/constants.rb +7 -0
- data/test_new/test_parts/create_test_project.rb +37 -0
- data/test_new/test_parts/raw_formats_and_uploads.rb +170 -0
- data/test_new/test_parts/server_list.rb +20 -0
- data/test_new/test_parts/simple_node_lookup_and_browsing.rb +76 -0
- data/test_new/test_suite.rb +70 -0
- data/{test/convert.rb → test_new/test_thread_worker.rb} +2 -3
- metadata +71 -61
- data/ext/bmp.cpp +0 -65
- data/ext/image.h +0 -27
- data/ext/ppm.cpp +0 -132
- data/ext/sgi.cpp +0 -69
- data/test/audio.rb +0 -27
- data/test/image.rb +0 -101
- data/test/read_frames.rb +0 -142
- data/test/wiretap-images/32bit.stoneimage +0 -621
- data/test/wiretap-images/36bit.stoneimage +0 -1036
- data/test/wiretap-images/48bit.stoneimage +1 -800
- data/test/wiretap-images/a.stoneimage +0 -0
- data/test/wiretap-images/a0.stoneimage +0 -0
- data/test/wiretap-images/a1.stoneimage +0 -0
- data/test/wiretap-images/a2.stoneimage +0 -0
- data/test/wiretap-images/a3.stoneimage +0 -0
- data/test/wiretap-images/a4.stoneimage +0 -0
- data/test/wiretap-images/importable-seq/00000001.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000002.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000003.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000004.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000005.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000006.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000007.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000008.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000009.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000010.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000011.ppm +0 -0
- data/test/wiretap-images/importable-seq/00000012.ppm +0 -0
- data/test/wiretap-images/monsters_001.tif +0 -0
- data/test/wiretap-images/monsters_002.tif +0 -0
- data/test/wiretap-images/monsters_003.tif +0 -0
- data/test/wiretap-images/output.mov +0 -0
- data/test/write_frames.rb +0 -82
data/ext/image_io.cpp
ADDED
@@ -0,0 +1,466 @@
|
|
1
|
+
#include "wiretap.h"
|
2
|
+
#include <sys/types.h>
|
3
|
+
#include <sys/stat.h>
|
4
|
+
|
5
|
+
/************ Memstream writers *****************/
|
6
|
+
charstream::charstream() {}
|
7
|
+
void charstream::write_char(unsigned char channel) {}
|
8
|
+
charstream::~charstream() {}
|
9
|
+
|
10
|
+
|
11
|
+
void charstream::write_int32_le(int value) {
|
12
|
+
write_char(value >> 0 & 0xFF);
|
13
|
+
write_char(value >> 8 & 0xFF);
|
14
|
+
write_char(value >> 16& 0xFF);
|
15
|
+
write_char(value >> 24& 0xFF);
|
16
|
+
}
|
17
|
+
|
18
|
+
void charstream::write_int32_be(int value) {
|
19
|
+
write_char(value >> 24& 0xFF);
|
20
|
+
write_char(value >> 16& 0xFF);
|
21
|
+
write_char(value >> 8 & 0xFF);
|
22
|
+
write_char(value >> 0 & 0xFF);
|
23
|
+
}
|
24
|
+
|
25
|
+
void charstream::write_int16_le(short value) {
|
26
|
+
write_char(value >> 0 & 0xFF);
|
27
|
+
write_char(value >> 8 & 0xFF);
|
28
|
+
}
|
29
|
+
|
30
|
+
void charstream::write_int16_be(short value) {
|
31
|
+
write_char(value >> 8 & 0xFF);
|
32
|
+
write_char(value >> 0 & 0xFF);
|
33
|
+
}
|
34
|
+
|
35
|
+
void charstream::write_string(char* value) {
|
36
|
+
while(value && *value) {
|
37
|
+
write_char(*value);
|
38
|
+
value++;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
memstream::memstream(unsigned char* _ptr) { ptr = _ptr; }
|
44
|
+
void memstream::write_char(unsigned char channel) {
|
45
|
+
*ptr++ = channel;
|
46
|
+
}
|
47
|
+
|
48
|
+
filestream::filestream(FILE* _f) { f = _f; }
|
49
|
+
void filestream::write_char(unsigned char channel) {
|
50
|
+
fwrite(&channel, sizeof(channel), 1, f);
|
51
|
+
}
|
52
|
+
|
53
|
+
filestream_bgr::filestream_bgr(FILE* _f){ f = _f; count = 0; memset(buffer, 0, sizeof(buffer)); }
|
54
|
+
void filestream_bgr::write_char(unsigned char channel) {
|
55
|
+
buffer[2 - count] = channel;
|
56
|
+
count++;
|
57
|
+
if(count == 3) {
|
58
|
+
fwrite(buffer, sizeof(buffer), 1, f);
|
59
|
+
count = 0;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
/************ ImageIO *************/
|
65
|
+
|
66
|
+
ImageIO* ImageIO::open(const char* filename, WireTapClipFormat& format, bool read_only) {
|
67
|
+
FILE* infile = fopen(filename, read_only ? "r" : "w+");
|
68
|
+
if(!infile) {
|
69
|
+
THROW("Couldn't open file %s for %s", filename, read_only ? "reading" : "writing");
|
70
|
+
}
|
71
|
+
char *extension = 0;
|
72
|
+
for(extension = const_cast<char *>(filename) + strlen(filename); extension > filename; extension--) {
|
73
|
+
if(*extension == '.') {
|
74
|
+
extension++;
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
if(!strcmp(extension, "ppm")) return new ImageIO_PPM(filename, infile, format);
|
79
|
+
if(!strcmp(extension, "sgi")) return new ImageIO_SGI(filename, infile, format);
|
80
|
+
if(!strcmp(extension, "bmp")) return new ImageIO_BMP(filename, infile, format);
|
81
|
+
if(!strcmp(extension, "stoneimage")) return new ImageIO_RAW(filename, infile, format);
|
82
|
+
return NULL;
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
int ImageIO::extract_int() {
|
87
|
+
char buffer[256];
|
88
|
+
int pos = 0;
|
89
|
+
char c;
|
90
|
+
while(!feof(this->f)) {
|
91
|
+
c = fgetc(this->f);
|
92
|
+
if(!isalnum(c)) {
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
buffer[pos++] = c;
|
96
|
+
if(pos == sizeof(buffer)) break;
|
97
|
+
}
|
98
|
+
buffer[pos] = '\0';
|
99
|
+
return atoi(buffer);
|
100
|
+
}
|
101
|
+
|
102
|
+
int ImageIO::read_int32_be() {
|
103
|
+
unsigned char bytes[4];
|
104
|
+
fread(bytes, sizeof(bytes), 1, f);
|
105
|
+
return (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + (bytes[3]);
|
106
|
+
}
|
107
|
+
|
108
|
+
short ImageIO::read_int16_be() {
|
109
|
+
unsigned char bytes[2];
|
110
|
+
fread(bytes, sizeof(bytes), 1, f);
|
111
|
+
return (bytes[0] << 8) + (bytes[1]);
|
112
|
+
}
|
113
|
+
|
114
|
+
unsigned char ImageIO::read_int8() {
|
115
|
+
unsigned char byte;
|
116
|
+
fread(&byte, 1, 1, f);
|
117
|
+
return byte;
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
ImageIO::ImageIO(const char* _filename, FILE* _f, WireTapClipFormat& _format) : format(_format) {
|
123
|
+
filename = _filename;
|
124
|
+
f = _f;
|
125
|
+
}
|
126
|
+
|
127
|
+
|
128
|
+
ImageIO::~ImageIO() {
|
129
|
+
if(f) {
|
130
|
+
fclose(f);
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
|
135
|
+
void ImageIO::decode_image_data(unsigned char* frame, charstream& writer) {
|
136
|
+
std::auto_ptr<FrameIO> frame_io(FrameIO::decoder(frame, format.width(), format.height(), format.bitsPerPixel()));
|
137
|
+
if(!frame_io.get()) {
|
138
|
+
THROW("Unsupported color depth for dumping image: %d", format.bitsPerPixel());
|
139
|
+
}
|
140
|
+
frame_io->decode(writer);
|
141
|
+
}
|
142
|
+
|
143
|
+
/************** PPM format *****************/
|
144
|
+
|
145
|
+
ImageIO_PPM::ImageIO_PPM(const char* _filename, FILE* _f, WireTapClipFormat& _format) : ImageIO(_filename, _f, _format) {
|
146
|
+
}
|
147
|
+
|
148
|
+
void ImageIO_PPM::read_format() {
|
149
|
+
extract_int();
|
150
|
+
|
151
|
+
format.setWidth(extract_int());
|
152
|
+
format.setHeight(extract_int());
|
153
|
+
|
154
|
+
int maxval = extract_int();
|
155
|
+
if(maxval > 255) {
|
156
|
+
//FIXME: possible memory leak in using function.
|
157
|
+
THROW("Decoding 16bit PPM files is not supported");
|
158
|
+
}
|
159
|
+
|
160
|
+
format.setBitsPerPixel(24);
|
161
|
+
format.setNumChannels(3);
|
162
|
+
format.setFrameBufferSize((format.bitsPerPixel()/8)*format.width()*format.height());
|
163
|
+
format.setFrameRate(25);
|
164
|
+
format.setScanFormat(format.strToScanFormat("progressive"));
|
165
|
+
format.setFormatTag("rgb");
|
166
|
+
format.setMetaDataTag("IFFFS_XML");
|
167
|
+
format.setMetaData("<IFFFS_XML Version=\"1.0\"><ClipData></ClipData></IFFFS_XML>");
|
168
|
+
}
|
169
|
+
|
170
|
+
|
171
|
+
unsigned char* ImageIO_PPM::read_data() {
|
172
|
+
unsigned char* frame = new unsigned char[format.frameBufferSize()];
|
173
|
+
|
174
|
+
size_t row_size = format.width()*3;
|
175
|
+
|
176
|
+
for(int i = 0; i < format.height(); i++) {
|
177
|
+
size_t read_bytes = fread(frame + (format.height() - 1 - i)*row_size, 1, row_size, f);
|
178
|
+
if(read_bytes != row_size) {
|
179
|
+
rb_warn("Read %d bytes, expected %d. Step: %d", read_bytes, row_size, i);
|
180
|
+
return 0;
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
return frame;
|
185
|
+
}
|
186
|
+
|
187
|
+
void ImageIO_PPM::write_data(unsigned char* frame) {
|
188
|
+
|
189
|
+
}
|
190
|
+
|
191
|
+
|
192
|
+
/************** SGI format *****************/
|
193
|
+
|
194
|
+
|
195
|
+
ImageIO_SGI::ImageIO_SGI(const char* _filename, FILE* _f, WireTapClipFormat& _format) : ImageIO(_filename, _f, _format) {
|
196
|
+
compressed = false;
|
197
|
+
bit16 = false;
|
198
|
+
}
|
199
|
+
|
200
|
+
void ImageIO_SGI::read_format() {
|
201
|
+
const int header_padding = 404;
|
202
|
+
const int magic = 474;
|
203
|
+
|
204
|
+
short _magic = read_int16_be();
|
205
|
+
if(_magic != magic) {
|
206
|
+
rb_warn("Warning: %s has a broken file format: %d", filename, _magic);
|
207
|
+
}
|
208
|
+
|
209
|
+
compressed = read_int8() ? true : false;
|
210
|
+
switch(read_int8()) { // 1 for 1 byte per channel. 24 bit picture
|
211
|
+
case 1: format.setBitsPerPixel(24);
|
212
|
+
break;
|
213
|
+
case 2: format.setBitsPerPixel(48);
|
214
|
+
bit16 = true;
|
215
|
+
break;
|
216
|
+
}
|
217
|
+
|
218
|
+
format.setFrameBufferSize((format.bitsPerPixel()/8)*format.width()*format.height());
|
219
|
+
format.setFrameRate(25);
|
220
|
+
format.setScanFormat(format.strToScanFormat("progressive"));
|
221
|
+
format.setFormatTag("rgb");
|
222
|
+
format.setMetaDataTag("IFFFS_XML");
|
223
|
+
format.setMetaData("<IFFFS_XML Version=\"1.0\"><ClipData></ClipData></IFFFS_XML>");
|
224
|
+
|
225
|
+
short d;
|
226
|
+
if((d = read_int16_be()) != 3) {
|
227
|
+
rb_warn("Unknown number of dimensions: %d. Cannot read", d);
|
228
|
+
}
|
229
|
+
format.setWidth(read_int16_be());
|
230
|
+
format.setHeight(read_int16_be());
|
231
|
+
format.setNumChannels(read_int16_be());
|
232
|
+
/*int pix_min = */read_int32_be();
|
233
|
+
/*int pix_max = */read_int32_be();
|
234
|
+
read_int32_be(); // dummy
|
235
|
+
|
236
|
+
char image_name[80];
|
237
|
+
fread(image_name, sizeof(image_name), 1, f);
|
238
|
+
|
239
|
+
int cl;
|
240
|
+
if((cl = read_int32_be()) != 0) {
|
241
|
+
rb_warn("Unkwnown colormap: %d", cl);
|
242
|
+
}
|
243
|
+
char padding[header_padding];
|
244
|
+
fread(padding, sizeof(padding), 1, f);
|
245
|
+
if(compressed) {
|
246
|
+
int tablen = format.height()*3; //Only for colour pictures
|
247
|
+
|
248
|
+
start_table = std::auto_ptr<unsigned long>(new unsigned long[tablen]);
|
249
|
+
for(int i = 0; i < tablen; i++) {
|
250
|
+
start_table.get()[i] = read_int32_be();
|
251
|
+
}
|
252
|
+
|
253
|
+
length_table = std::auto_ptr<unsigned long>(new unsigned long[tablen]);
|
254
|
+
for(int i = 0; i < tablen; i++) {
|
255
|
+
length_table.get()[i] = read_int32_be();
|
256
|
+
}
|
257
|
+
}
|
258
|
+
}
|
259
|
+
|
260
|
+
unsigned char* ImageIO_SGI::read_channel(int channel) {
|
261
|
+
return compressed ? read_compressed(channel) : read_uncompressed(channel);
|
262
|
+
}
|
263
|
+
|
264
|
+
/*
|
265
|
+
* Decoding as here: http://www.martinreddy.net/gfx/2d/RGB.txt
|
266
|
+
*/
|
267
|
+
unsigned char* ImageIO_SGI::read_compressed(int channel) {
|
268
|
+
int row_size = format.width()*format.bitsPerPixel()/24;
|
269
|
+
int line_size = row_size*format.height();
|
270
|
+
unsigned char* line = new unsigned char[line_size];
|
271
|
+
for(int rowno = 0; rowno < format.height(); rowno++) {
|
272
|
+
int compressed_row_length = length_table.get()[rowno + channel*format.height()];
|
273
|
+
std::auto_ptr<unsigned char> row_in(new unsigned char[compressed_row_length]);
|
274
|
+
fseek(f, start_table.get()[rowno + channel*format.height()], SEEK_SET);
|
275
|
+
fread(row_in.get(), compressed_row_length, 1, f);
|
276
|
+
expand_row(line + row_size*rowno, row_in.get());
|
277
|
+
}
|
278
|
+
return line;
|
279
|
+
}
|
280
|
+
|
281
|
+
void ImageIO_SGI::expand_row(unsigned char* optr, unsigned char* iptr) {
|
282
|
+
unsigned char pixel, count, pixel_high = 0;
|
283
|
+
while(1) {
|
284
|
+
pixel = *iptr++;
|
285
|
+
if(bit16) pixel = *iptr++;
|
286
|
+
if ( !(count = (pixel & 0x7f)) ) {
|
287
|
+
return;
|
288
|
+
}
|
289
|
+
if(pixel & 0x80) {
|
290
|
+
while(count--) {
|
291
|
+
*optr = *iptr++;
|
292
|
+
optr++;
|
293
|
+
if(bit16) {
|
294
|
+
*optr = *iptr++;
|
295
|
+
optr++;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
} else {
|
299
|
+
pixel = *iptr++;
|
300
|
+
if(bit16) {
|
301
|
+
pixel_high = pixel;
|
302
|
+
pixel = *iptr++;
|
303
|
+
}
|
304
|
+
while(count--) {
|
305
|
+
if(bit16) {
|
306
|
+
*optr = pixel_high;
|
307
|
+
optr++;
|
308
|
+
}
|
309
|
+
*optr = pixel;
|
310
|
+
optr++;
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
|
317
|
+
unsigned char* ImageIO_SGI::read_uncompressed(int channel) {
|
318
|
+
int line_size = format.width()*format.height()*format.bitsPerPixel()/24;
|
319
|
+
unsigned char* line = new unsigned char[line_size];
|
320
|
+
fread(line, line_size, 1, f);
|
321
|
+
return line;
|
322
|
+
}
|
323
|
+
|
324
|
+
unsigned char* ImageIO_SGI::read_data() {
|
325
|
+
int pixel_count = format.width()*format.height()*format.bitsPerPixel()/8;
|
326
|
+
unsigned char* frame = new unsigned char[pixel_count];
|
327
|
+
std::auto_ptr<unsigned char> line_r(read_channel(0));
|
328
|
+
std::auto_ptr<unsigned char> line_g(read_channel(1));
|
329
|
+
std::auto_ptr<unsigned char> line_b(read_channel(2));
|
330
|
+
|
331
|
+
int frame_ptr = 0;
|
332
|
+
int line_ptr = 0;
|
333
|
+
for(int i = 0; i < format.height(); i++) {
|
334
|
+
for(int j = 0; j < format.width(); j++) {
|
335
|
+
frame[frame_ptr++] = line_r.get()[line_ptr];
|
336
|
+
if(bit16) frame[frame_ptr++] = line_r.get()[line_ptr+1];
|
337
|
+
frame[frame_ptr++] = line_g.get()[line_ptr];
|
338
|
+
if(bit16) frame[frame_ptr++] = line_g.get()[line_ptr+1];
|
339
|
+
frame[frame_ptr++] = line_b.get()[line_ptr];
|
340
|
+
if(bit16) frame[frame_ptr++] = line_b.get()[line_ptr+1];
|
341
|
+
line_ptr++;
|
342
|
+
if(bit16) line_ptr++;
|
343
|
+
}
|
344
|
+
}
|
345
|
+
return frame;
|
346
|
+
}
|
347
|
+
|
348
|
+
|
349
|
+
|
350
|
+
static void write_channel(int width, int height, int number, unsigned char* frame, FILE* f) {
|
351
|
+
std::auto_ptr<unsigned char> buffer(new unsigned char[width*height]);
|
352
|
+
for(int i = 0; i < width*height; i++) {
|
353
|
+
buffer.get()[i] = frame[3*i + number];
|
354
|
+
}
|
355
|
+
fwrite(buffer.get(), width*height, 1, f);
|
356
|
+
}
|
357
|
+
|
358
|
+
|
359
|
+
static int wiretap_write_sgi_header(int width, int height, charstream& writer) {
|
360
|
+
//const int header_size = 512;
|
361
|
+
const int header_padding = 404;
|
362
|
+
const int magic = 474;
|
363
|
+
|
364
|
+
writer.write_int16_be(magic); // Magic 474
|
365
|
+
writer.write_char(0); // 0 for uncompressed
|
366
|
+
writer.write_char(1); // 1 for 1 byte per channel. 24 bit picture
|
367
|
+
writer.write_int16_be(3); // 3 dimensions - one plain image with multiple channels
|
368
|
+
writer.write_int16_be(width);
|
369
|
+
writer.write_int16_be(height);
|
370
|
+
writer.write_int16_be(3); // 3 for RGB mode: 3 channels
|
371
|
+
writer.write_int32_be(0); // minimum pixel value
|
372
|
+
writer.write_int32_be(0xFF); // maximum pixel value
|
373
|
+
writer.write_int32_be(0); // dummy
|
374
|
+
|
375
|
+
char image_name[80] = "Ruby wiretap encoded";
|
376
|
+
for(size_t i = 0; i < sizeof(image_name); i++) {
|
377
|
+
writer.write_char(image_name[i]);
|
378
|
+
}
|
379
|
+
|
380
|
+
writer.write_int32_be(0); // colormap is in normal mode (0)
|
381
|
+
for(int i = 0; i < header_padding; i++) {
|
382
|
+
writer.write_char(0);
|
383
|
+
}
|
384
|
+
return 0;
|
385
|
+
}
|
386
|
+
|
387
|
+
|
388
|
+
|
389
|
+
void ImageIO_SGI::write_data(unsigned char* frame) {
|
390
|
+
std::auto_ptr<unsigned char> buffer(new unsigned char[format.width()*format.height()*3]);
|
391
|
+
filestream stream(f);
|
392
|
+
memstream mem(buffer.get());
|
393
|
+
|
394
|
+
wiretap_write_sgi_header(format.width(), format.height(), stream);
|
395
|
+
decode_image_data(frame, mem);
|
396
|
+
|
397
|
+
write_channel(format.width(), format.height(), 0, buffer.get(), f);
|
398
|
+
write_channel(format.width(), format.height(), 1, buffer.get(), f);
|
399
|
+
write_channel(format.width(), format.height(), 2, buffer.get(), f);
|
400
|
+
}
|
401
|
+
|
402
|
+
|
403
|
+
|
404
|
+
/************** BMP format *****************/
|
405
|
+
|
406
|
+
ImageIO_BMP::ImageIO_BMP(const char* _filename, FILE* _f, WireTapClipFormat& _format) : ImageIO(_filename, _f, _format) {
|
407
|
+
}
|
408
|
+
|
409
|
+
void ImageIO_BMP::read_format() {
|
410
|
+
}
|
411
|
+
unsigned char* ImageIO_BMP::read_data() {
|
412
|
+
return NULL;
|
413
|
+
}
|
414
|
+
|
415
|
+
void ImageIO_BMP::write_header() {
|
416
|
+
filestream writer(f);
|
417
|
+
const int header_size = 54;
|
418
|
+
int size = header_size + format.width() * format.height() * 3;
|
419
|
+
writer.write_string("BM"); // 0,1
|
420
|
+
writer.write_int32_le(size); // 2,3,4,5
|
421
|
+
writer.write_int32_le(0); // 6,7,8,9: reserved data
|
422
|
+
writer.write_int32_le(header_size); // 10,11,12,13: Image header ends.
|
423
|
+
writer.write_int32_le(40); // 14,15,16,17: Image information size
|
424
|
+
writer.write_int32_le(format.width()); // 18,19,20,21: Width
|
425
|
+
writer.write_int32_le(format.height()); // 22,23,24,25: Height
|
426
|
+
writer.write_int16_le(1); // 26,27: Number of color planes
|
427
|
+
writer.write_int16_le(24); // 28,29: Bits per pixel. We write only 24 bit images
|
428
|
+
writer.write_int32_le(0); // 30,31,32,33: Compression schema. None
|
429
|
+
writer.write_int32_le(format.width()*format.height()*3); // 34,35,36,37: raw data size. 3 bytes per pixel.
|
430
|
+
writer.write_int32_le(2834); // 38,39,40,41: horisontal resolution. Perhaprs 72 dpi. I don't know
|
431
|
+
writer.write_int32_le(2834); // 42,43,44,45: vertical resolution
|
432
|
+
writer.write_int32_le(0); // 46,47,48,49: number of colors
|
433
|
+
writer.write_int32_le(0); // 50,51,52,53: number of important colors
|
434
|
+
}
|
435
|
+
|
436
|
+
|
437
|
+
void ImageIO_BMP::write_data(unsigned char* frame) {
|
438
|
+
filestream_bgr stream_bgr(f);
|
439
|
+
|
440
|
+
write_header();
|
441
|
+
decode_image_data(frame, stream_bgr);
|
442
|
+
}
|
443
|
+
|
444
|
+
|
445
|
+
/************** RAW format *****************/
|
446
|
+
ImageIO_RAW::ImageIO_RAW(const char* _filename, FILE* _f, WireTapClipFormat& _format) : ImageIO(_filename, _f, _format) {
|
447
|
+
}
|
448
|
+
|
449
|
+
void ImageIO_RAW::read_format() {}
|
450
|
+
unsigned char* ImageIO_RAW::read_data() {
|
451
|
+
struct stat sb;
|
452
|
+
if(!stat(filename, &sb)) {
|
453
|
+
return NULL;
|
454
|
+
}
|
455
|
+
unsigned char* frame = new unsigned char[sb.st_size];
|
456
|
+
if(!fread(frame, sb.st_size, 1, f)) {
|
457
|
+
delete frame;
|
458
|
+
return NULL;
|
459
|
+
}
|
460
|
+
return frame;
|
461
|
+
}
|
462
|
+
|
463
|
+
void ImageIO_RAW::write_data(unsigned char* frame) {
|
464
|
+
fwrite(frame, format.frameBufferSize(), 1, f);
|
465
|
+
}
|
466
|
+
|
data/ext/image_io.h
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#ifndef _IMAGE_IO_H_
|
2
|
+
#define _IMAGE_IO_H_
|
3
|
+
#include <string.h>
|
4
|
+
#include "charstream.h"
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
class ImageIO {
|
10
|
+
public:
|
11
|
+
virtual void read_format() = 0;
|
12
|
+
virtual unsigned char* read_data() = 0;
|
13
|
+
virtual void write_data(unsigned char* frame) = 0;
|
14
|
+
|
15
|
+
static ImageIO* open(const char* filename, WireTapClipFormat& format, bool read_only = true);
|
16
|
+
ImageIO(const char* _filename, FILE* _f, WireTapClipFormat& _format);
|
17
|
+
virtual ~ImageIO();
|
18
|
+
protected:
|
19
|
+
FILE* f;
|
20
|
+
const char* filename;
|
21
|
+
WireTapClipFormat& format;
|
22
|
+
int extract_int();
|
23
|
+
int read_int32_be();
|
24
|
+
short read_int16_be();
|
25
|
+
unsigned char read_int8();
|
26
|
+
void decode_image_data(unsigned char* frame, charstream& writer);
|
27
|
+
};
|
28
|
+
|
29
|
+
class ImageIO_SGI : public ImageIO {
|
30
|
+
public:
|
31
|
+
ImageIO_SGI(const char* filename, FILE* f, WireTapClipFormat& _format);
|
32
|
+
virtual void read_format();
|
33
|
+
virtual unsigned char* read_data();
|
34
|
+
virtual void write_data(unsigned char* frame);
|
35
|
+
protected:
|
36
|
+
bool compressed;
|
37
|
+
bool bit16;
|
38
|
+
std::auto_ptr<unsigned long> length_table;
|
39
|
+
std::auto_ptr<unsigned long> start_table;
|
40
|
+
unsigned char* read_channel(int channel);
|
41
|
+
unsigned char* read_uncompressed(int channel);
|
42
|
+
unsigned char* read_compressed(int channel);
|
43
|
+
void expand_row(unsigned char* optr, unsigned char* iptr);
|
44
|
+
};
|
45
|
+
|
46
|
+
class ImageIO_PPM : public ImageIO {
|
47
|
+
public:
|
48
|
+
ImageIO_PPM(const char* filename, FILE* f, WireTapClipFormat& _format);
|
49
|
+
virtual void read_format();
|
50
|
+
virtual unsigned char* read_data();
|
51
|
+
virtual void write_data(unsigned char* frame);
|
52
|
+
};
|
53
|
+
|
54
|
+
class ImageIO_BMP : public ImageIO {
|
55
|
+
public:
|
56
|
+
ImageIO_BMP(const char* filename, FILE* f, WireTapClipFormat& _format);
|
57
|
+
virtual void read_format();
|
58
|
+
virtual unsigned char* read_data();
|
59
|
+
virtual void write_data(unsigned char* frame);
|
60
|
+
protected:
|
61
|
+
void write_header();
|
62
|
+
};
|
63
|
+
|
64
|
+
class ImageIO_RAW : public ImageIO {
|
65
|
+
public:
|
66
|
+
ImageIO_RAW(const char* filename, FILE* f, WireTapClipFormat& _format);
|
67
|
+
virtual void read_format();
|
68
|
+
virtual unsigned char* read_data();
|
69
|
+
virtual void write_data(unsigned char* frame);
|
70
|
+
};
|
71
|
+
|
72
|
+
#endif /* _IMAGE_IO_H_ */
|
73
|
+
|