Mercurial > libavcodec.hg
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 } |