comparison sgidec.c @ 10194:5b05416fcb6b libavcodec

Support uncompressed 16 bit sgi image format, as e.g. used by the files at http://media.xiph.org/svt/2160p50_CgrLevels_Master_SVTdec05_/1_CrowdRun_2160p50_CgrLevels_MASTER_SVTdec05_/
author reimar
date Sat, 19 Sep 2009 11:42:41 +0000
parents 54bc8a2727b0
children 8a4984c5cacc
comparison
equal deleted inserted replaced
10193:ee31a41c5062 10194:5b05416fcb6b
26 typedef struct SgiState { 26 typedef struct SgiState {
27 AVFrame picture; 27 AVFrame picture;
28 unsigned int width; 28 unsigned int width;
29 unsigned int height; 29 unsigned int height;
30 unsigned int depth; 30 unsigned int depth;
31 unsigned int bytes_per_channel;
31 int linesize; 32 int linesize;
32 } SgiState; 33 } SgiState;
33 34
34 /** 35 /**
35 * Expand an RLE row into a channel. 36 * Expand an RLE row into a channel.
123 static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end, 124 static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end,
124 const uint8_t *in_buf, const uint8_t *in_end, SgiState* s) 125 const uint8_t *in_buf, const uint8_t *in_end, SgiState* s)
125 { 126 {
126 int x, y, z; 127 int x, y, z;
127 const uint8_t *ptr; 128 const uint8_t *ptr;
128 unsigned int offset = s->height * s->width; 129 unsigned int offset = s->height * s->width * s->bytes_per_channel;
129 130
130 /* Test buffer size. */ 131 /* Test buffer size. */
131 if (offset * s->depth > in_end - in_buf) { 132 if (offset * s->depth > in_end - in_buf) {
132 return -1; 133 return -1;
133 } 134 }
134 135
135 for (y = s->height - 1; y >= 0; y--) { 136 for (y = s->height - 1; y >= 0; y--) {
136 out_end = out_buf + (y * s->linesize); 137 out_end = out_buf + (y * s->linesize);
137 for (x = s->width; x > 0; x--) { 138 for (x = s->width; x > 0; x--) {
138 ptr = in_buf++; 139 ptr = in_buf += s->bytes_per_channel;
139 for(z = 0; z < s->depth; z ++) { 140 for(z = 0; z < s->depth; z ++) {
140 bytestream_put_byte(&out_end, *ptr); 141 memcpy(out_end, ptr, s->bytes_per_channel);
142 out_end += s->bytes_per_channel;
141 ptr += offset; 143 ptr += offset;
142 } 144 }
143 } 145 }
144 } 146 }
145 return 0; 147 return 0;
153 int buf_size = avpkt->size; 155 int buf_size = avpkt->size;
154 SgiState *s = avctx->priv_data; 156 SgiState *s = avctx->priv_data;
155 AVFrame *picture = data; 157 AVFrame *picture = data;
156 AVFrame *p = &s->picture; 158 AVFrame *p = &s->picture;
157 const uint8_t *in_end = in_buf + buf_size; 159 const uint8_t *in_end = in_buf + buf_size;
158 unsigned int dimension, bytes_per_channel, rle; 160 unsigned int dimension, rle;
159 int ret = 0; 161 int ret = 0;
160 uint8_t *out_buf, *out_end; 162 uint8_t *out_buf, *out_end;
161 163
162 if (buf_size < SGI_HEADER_SIZE){ 164 if (buf_size < SGI_HEADER_SIZE){
163 av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", buf_size); 165 av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", buf_size);
169 av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); 171 av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
170 return -1; 172 return -1;
171 } 173 }
172 174
173 rle = bytestream_get_byte(&in_buf); 175 rle = bytestream_get_byte(&in_buf);
174 bytes_per_channel = bytestream_get_byte(&in_buf); 176 s->bytes_per_channel = bytestream_get_byte(&in_buf);
175 dimension = bytestream_get_be16(&in_buf); 177 dimension = bytestream_get_be16(&in_buf);
176 s->width = bytestream_get_be16(&in_buf); 178 s->width = bytestream_get_be16(&in_buf);
177 s->height = bytestream_get_be16(&in_buf); 179 s->height = bytestream_get_be16(&in_buf);
178 s->depth = bytestream_get_be16(&in_buf); 180 s->depth = bytestream_get_be16(&in_buf);
179 181
180 if (bytes_per_channel != 1) { 182 if (s->bytes_per_channel != 1 && (s->bytes_per_channel != 2 || rle)) {
181 av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); 183 av_log(avctx, AV_LOG_ERROR, "wrong channel number\n");
182 return -1; 184 return -1;
183 } 185 }
184 186
185 /* Check for supported image dimensions. */ 187 /* Check for supported image dimensions. */
187 av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n"); 189 av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n");
188 return -1; 190 return -1;
189 } 191 }
190 192
191 if (s->depth == SGI_GRAYSCALE) { 193 if (s->depth == SGI_GRAYSCALE) {
192 avctx->pix_fmt = PIX_FMT_GRAY8; 194 avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_GRAY16BE : PIX_FMT_GRAY8;
193 } else if (s->depth == SGI_RGB) { 195 } else if (s->depth == SGI_RGB) {
194 avctx->pix_fmt = PIX_FMT_RGB24; 196 avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_RGB48BE : PIX_FMT_RGB24;
195 } else if (s->depth == SGI_RGBA) { 197 } else if (s->depth == SGI_RGBA && s->bytes_per_channel == 1) {
196 avctx->pix_fmt = PIX_FMT_RGBA; 198 avctx->pix_fmt = PIX_FMT_RGBA;
197 } else { 199 } else {
198 av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); 200 av_log(avctx, AV_LOG_ERROR, "wrong picture format\n");
199 return -1; 201 return -1;
200 } 202 }