VirtualBox

source: vbox/trunk/src/libs/ffmpeg-20060710/libavformat/sgi.c@ 8998

最後變更 在這個檔案從8998是 5776,由 vboxsync 提交於 17 年 前

ffmpeg: exported to OSE

檔案大小: 10.7 KB
 
1/*
2 * SGI image format
3 * Todd Kirby <[email protected]>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "avformat.h"
21#include "avio.h"
22
23/* #define DEBUG */
24
25/* sgi image file signature */
26#define SGI_MAGIC 474
27
28#define SGI_HEADER_SIZE 512
29
30#define SGI_GRAYSCALE 1
31#define SGI_RGB 3
32#define SGI_RGBA 4
33
34#define SGI_SINGLE_CHAN 2
35#define SGI_MULTI_CHAN 3
36
37typedef struct SGIInfo{
38 short magic;
39 char rle;
40 char bytes_per_channel;
41 unsigned short dimension;
42 unsigned short xsize;
43 unsigned short ysize;
44 unsigned short zsize;
45} SGIInfo;
46
47
48static int sgi_probe(AVProbeData *pd)
49{
50 /* test for sgi magic */
51 if (pd->buf_size >= 2 && BE_16(&pd->buf[0]) == SGI_MAGIC) {
52 return AVPROBE_SCORE_MAX;
53 } else {
54 return 0;
55 }
56}
57
58/* read sgi header fields */
59static void read_sgi_header(ByteIOContext *f, SGIInfo *info)
60{
61 info->magic = (unsigned short) get_be16(f);
62 info->rle = get_byte(f);
63 info->bytes_per_channel = get_byte(f);
64 info->dimension = (unsigned short)get_be16(f);
65 info->xsize = (unsigned short) get_be16(f);
66 info->ysize = (unsigned short) get_be16(f);
67 info->zsize = (unsigned short) get_be16(f);
68
69 if(info->zsize > 4096)
70 info->zsize= 0;
71
72#ifdef DEBUG
73 printf("sgi header fields:\n");
74 printf(" magic: %d\n", info->magic);
75 printf(" rle: %d\n", info->rle);
76 printf(" bpc: %d\n", info->bytes_per_channel);
77 printf(" dim: %d\n", info->dimension);
78 printf(" xsize: %d\n", info->xsize);
79 printf(" ysize: %d\n", info->ysize);
80 printf(" zsize: %d\n", info->zsize);
81#endif
82
83 return;
84}
85
86
87/* read an uncompressed sgi image */
88static int read_uncompressed_sgi(const SGIInfo *si,
89 AVPicture *pict, ByteIOContext *f)
90{
91 int x, y, z, chan_offset, ret = 0;
92 uint8_t *dest_row;
93
94 /* skip header */
95 url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
96
97 pict->linesize[0] = si->xsize;
98
99 for (z = 0; z < si->zsize; z++) {
100
101#ifndef WORDS_BIGENDIAN
102 /* rgba -> bgra for rgba32 on little endian cpus */
103 if (si->zsize == 4 && z != 3)
104 chan_offset = 2 - z;
105 else
106#endif
107 chan_offset = z;
108
109 for (y = si->ysize - 1; y >= 0; y--) {
110 dest_row = pict->data[0] + (y * si->xsize * si->zsize);
111
112 for (x = 0; x < si->xsize; x++) {
113 dest_row[chan_offset] = get_byte(f);
114 dest_row += si->zsize;
115 }
116 }
117 }
118
119 return ret;
120}
121
122
123/* expand an rle row into a channel */
124static int expand_rle_row(ByteIOContext *f, unsigned char *optr,
125 int chan_offset, int pixelstride)
126{
127 unsigned char pixel, count;
128 int length = 0;
129
130#ifndef WORDS_BIGENDIAN
131 /* rgba -> bgra for rgba32 on little endian cpus */
132 if (pixelstride == 4 && chan_offset != 3) {
133 chan_offset = 2 - chan_offset;
134 }
135#endif
136
137 optr += chan_offset;
138
139 while (1) {
140 pixel = get_byte(f);
141
142 if (!(count = (pixel & 0x7f))) {
143 return length;
144 }
145 if (pixel & 0x80) {
146 while (count--) {
147 *optr = get_byte(f);
148 length++;
149 optr += pixelstride;
150 }
151 } else {
152 pixel = get_byte(f);
153
154 while (count--) {
155 *optr = pixel;
156 length++;
157 optr += pixelstride;
158 }
159 }
160 }
161}
162
163
164/* read a run length encoded sgi image */
165static int read_rle_sgi(const SGIInfo *sgi_info,
166 AVPicture *pict, ByteIOContext *f)
167{
168 uint8_t *dest_row;
169 unsigned long *start_table;
170 int y, z, xsize, ysize, zsize, tablen;
171 long start_offset;
172 int ret = 0;
173
174 xsize = sgi_info->xsize;
175 ysize = sgi_info->ysize;
176 zsize = sgi_info->zsize;
177
178 /* skip header */
179 url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
180
181 /* size of rle offset and length tables */
182 tablen = ysize * zsize * sizeof(long);
183
184 start_table = (unsigned long *)av_malloc(tablen);
185
186 if (!get_buffer(f, (uint8_t *)start_table, tablen)) {
187 ret = AVERROR_IO;
188 goto fail;
189 }
190
191 /* skip run length table */
192 url_fseek(f, tablen, SEEK_CUR);
193
194 for (z = 0; z < zsize; z++) {
195 for (y = 0; y < ysize; y++) {
196 dest_row = pict->data[0] + (ysize - 1 - y) * (xsize * zsize);
197
198 start_offset = BE_32(&start_table[y + z * ysize]);
199
200 /* don't seek if already at the next rle start offset */
201 if (url_ftell(f) != start_offset) {
202 url_fseek(f, start_offset, SEEK_SET);
203 }
204
205 if (expand_rle_row(f, dest_row, z, zsize) != xsize) {
206 ret = AVERROR_INVALIDDATA;
207 goto fail;
208 }
209 }
210 }
211
212fail:
213 av_free(start_table);
214
215 return ret;
216}
217
218
219static int sgi_read(ByteIOContext *f,
220 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
221{
222 SGIInfo sgi_info, *s = &sgi_info;
223 AVImageInfo info1, *info = &info1;
224 int ret;
225
226 read_sgi_header(f, s);
227
228 if (s->bytes_per_channel != 1) {
229 return AVERROR_INVALIDDATA;
230 }
231
232 /* check for supported image dimensions */
233 if (s->dimension != 2 && s->dimension != 3) {
234 return AVERROR_INVALIDDATA;
235 }
236
237 if (s->zsize == SGI_GRAYSCALE) {
238 info->pix_fmt = PIX_FMT_GRAY8;
239 } else if (s->zsize == SGI_RGB) {
240 info->pix_fmt = PIX_FMT_RGB24;
241 } else if (s->zsize == SGI_RGBA) {
242 info->pix_fmt = PIX_FMT_RGBA32;
243 } else {
244 return AVERROR_INVALIDDATA;
245 }
246
247 info->width = s->xsize;
248 info->height = s->ysize;
249
250 ret = alloc_cb(opaque, info);
251 if (ret)
252 return ret;
253
254 if (s->rle) {
255 return read_rle_sgi(s, &info->pict, f);
256 } else {
257 return read_uncompressed_sgi(s, &info->pict, f);
258 }
259
260 return 0; /* not reached */
261}
262
263#ifdef CONFIG_MUXERS
264static void write_sgi_header(ByteIOContext *f, const SGIInfo *info)
265{
266 int i;
267
268 put_be16(f, SGI_MAGIC);
269 put_byte(f, info->rle);
270 put_byte(f, info->bytes_per_channel);
271 put_be16(f, info->dimension);
272 put_be16(f, info->xsize);
273 put_be16(f, info->ysize);
274 put_be16(f, info->zsize);
275
276 /* The rest are constant in this implementation */
277 put_be32(f, 0L); /* pixmin */
278 put_be32(f, 255L); /* pixmax */
279 put_be32(f, 0L); /* dummy */
280
281 /* name */
282 for (i = 0; i < 80; i++) {
283 put_byte(f, 0);
284 }
285
286 put_be32(f, 0L); /* colormap */
287
288 /* The rest of the 512 byte header is unused. */
289 for (i = 0; i < 404; i++) {
290 put_byte(f, 0);
291 }
292}
293
294
295static int rle_row(ByteIOContext *f, char *row, int stride, int rowsize)
296{
297 int length, count, i, x;
298 char *start, repeat = 0;
299
300 for (x = rowsize, length = 0; x > 0;) {
301 start = row;
302 row += (2 * stride);
303 x -= 2;
304
305 while (x > 0 && (row[-2 * stride] != row[-1 * stride] ||
306 row[-1 * stride] != row[0])) {
307 row += stride;
308 x--;
309 };
310
311 row -= (2 * stride);
312 x += 2;
313
314 count = (row - start) / stride;
315 while (count > 0) {
316 i = count > 126 ? 126 : count;
317 count -= i;
318
319 put_byte(f, 0x80 | i);
320 length++;
321
322 while (i > 0) {
323 put_byte(f, *start);
324 start += stride;
325 i--;
326 length++;
327 };
328 };
329
330 if (x <= 0) {
331 break;
332 }
333
334 start = row;
335 repeat = row[0];
336
337 row += stride;
338 x--;
339
340 while (x > 0 && *row == repeat) {
341 row += stride;
342 x--;
343 };
344
345 count = (row - start) / stride;
346 while (count > 0) {
347 i = count > 126 ? 126 : count;
348 count -= i;
349
350 put_byte(f, i);
351 length++;
352
353 put_byte(f, repeat);
354 length++;
355 };
356 };
357
358 length++;
359
360 put_byte(f, 0);
361 return (length);
362}
363
364
365static int sgi_write(ByteIOContext *pb, AVImageInfo *info)
366{
367 SGIInfo sgi_info, *si = &sgi_info;
368 long *offsettab, *lengthtab;
369 int i, y, z;
370 int tablesize, chan_offset;
371 uint8_t *srcrow;
372
373 si->xsize = info->width;
374 si->ysize = info->height;
375 si->rle = 1;
376 si->bytes_per_channel = 1;
377
378 switch(info->pix_fmt) {
379 case PIX_FMT_GRAY8:
380 si->dimension = SGI_SINGLE_CHAN;
381 si->zsize = SGI_GRAYSCALE;
382 break;
383 case PIX_FMT_RGB24:
384 si->dimension = SGI_MULTI_CHAN;
385 si->zsize = SGI_RGB;
386 break;
387 case PIX_FMT_RGBA32:
388 si->dimension = SGI_MULTI_CHAN;
389 si->zsize = SGI_RGBA;
390 break;
391 default:
392 return AVERROR_INVALIDDATA;
393 }
394
395 write_sgi_header(pb, si);
396
397 tablesize = si->zsize * si->ysize * sizeof(long);
398
399 /* skip rle offset and length tables, write them at the end. */
400 url_fseek(pb, tablesize * 2, SEEK_CUR);
401 put_flush_packet(pb);
402
403 lengthtab = av_malloc(tablesize);
404 offsettab = av_malloc(tablesize);
405
406 for (z = 0; z < si->zsize; z++) {
407
408#ifndef WORDS_BIGENDIAN
409 /* rgba -> bgra for rgba32 on little endian cpus */
410 if (si->zsize == 4 && z != 3)
411 chan_offset = 2 - z;
412 else
413#endif
414 chan_offset = z;
415
416 srcrow = info->pict.data[0] + chan_offset;
417
418 for (y = si->ysize -1; y >= 0; y--) {
419 offsettab[(z * si->ysize) + y] = url_ftell(pb);
420 lengthtab[(z * si->ysize) + y] = rle_row(pb, srcrow,
421 si->zsize, si->xsize);
422 srcrow += info->pict.linesize[0];
423 }
424 }
425
426 url_fseek(pb, 512, SEEK_SET);
427
428 /* write offset table */
429 for (i = 0; i < (si->ysize * si->zsize); i++) {
430 put_be32(pb, offsettab[i]);
431 }
432
433 /* write length table */
434 for (i = 0; i < (si->ysize * si->zsize); i++) {
435 put_be32(pb, lengthtab[i]);
436 }
437
438 put_flush_packet(pb);
439
440 av_free(lengthtab);
441 av_free(offsettab);
442
443 return 0;
444}
445#endif // CONFIG_MUXERS
446
447AVImageFormat sgi_image_format = {
448 "sgi",
449 "sgi,rgb,rgba,bw",
450 sgi_probe,
451 sgi_read,
452 (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_RGBA32),
453#ifdef CONFIG_MUXERS
454 sgi_write,
455#else
456 NULL,
457#endif // CONFIG_MUXERS
458};
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette