pcx.c
Go to the documentation of this file.
1 /*
2  * PC Paintbrush PCX (.pcx) image decoder
3  * Copyright (c) 2007, 2008 Ivo van Poorten
4  *
5  * This decoder does not support CGA palettes. I am unable to find samples
6  * and Netpbm cannot generate them.
7  *
8  * This file is part of Libav.
9  *
10  * Libav is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * Libav is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with Libav; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 #include "libavutil/imgutils.h"
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "get_bits.h"
29 #include "internal.h"
30 
31 typedef struct PCXContext {
33 } PCXContext;
34 
35 static av_cold int pcx_init(AVCodecContext *avctx) {
36  PCXContext *s = avctx->priv_data;
37 
39  avctx->coded_frame= &s->picture;
40 
41  return 0;
42 }
43 
47 static const uint8_t *pcx_rle_decode(const uint8_t *src,
48  const uint8_t *end,
49  uint8_t *dst,
50  unsigned int bytes_per_scanline,
51  int compressed) {
52  unsigned int i = 0;
53  unsigned char run, value;
54 
55  if (compressed) {
56  while (i < bytes_per_scanline && src < end) {
57  run = 1;
58  value = *src++;
59  if (value >= 0xc0 && src < end) {
60  run = value & 0x3f;
61  value = *src++;
62  }
63  while (i<bytes_per_scanline && run--)
64  dst[i++] = value;
65  }
66  } else {
67  memcpy(dst, src, bytes_per_scanline);
68  src += bytes_per_scanline;
69  }
70 
71  return src;
72 }
73 
74 static void pcx_palette(const uint8_t **src, uint32_t *dst, unsigned int pallen) {
75  unsigned int i;
76 
77  for (i=0; i<pallen; i++)
78  *dst++ = bytestream_get_be24(src);
79  if (pallen < 256)
80  memset(dst, 0, (256 - pallen) * sizeof(*dst));
81 }
82 
83 static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
84  AVPacket *avpkt) {
85  const uint8_t *buf = avpkt->data;
86  int buf_size = avpkt->size;
87  PCXContext * const s = avctx->priv_data;
88  AVFrame *picture = data;
89  AVFrame * const p = &s->picture;
90  int compressed, xmin, ymin, xmax, ymax;
91  unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x,
92  bytes_per_scanline;
93  uint8_t *ptr;
94  const uint8_t *buf_end = buf + buf_size;
95  uint8_t const *bufstart = buf;
96  uint8_t *scanline;
97  int ret = -1;
98 
99  if (buf[0] != 0x0a || buf[1] > 5) {
100  av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n");
101  return -1;
102  }
103 
104  compressed = buf[2];
105  xmin = AV_RL16(buf+ 4);
106  ymin = AV_RL16(buf+ 6);
107  xmax = AV_RL16(buf+ 8);
108  ymax = AV_RL16(buf+10);
109 
110  if (xmax < xmin || ymax < ymin) {
111  av_log(avctx, AV_LOG_ERROR, "invalid image dimensions\n");
112  return -1;
113  }
114 
115  w = xmax - xmin + 1;
116  h = ymax - ymin + 1;
117 
118  bits_per_pixel = buf[3];
119  bytes_per_line = AV_RL16(buf+66);
120  nplanes = buf[65];
121  bytes_per_scanline = nplanes * bytes_per_line;
122 
123  if (bytes_per_scanline < (w * bits_per_pixel * nplanes + 7) / 8 ||
124  (!compressed && bytes_per_scanline > buf_size / h)) {
125  av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n");
126  return -1;
127  }
128 
129  switch ((nplanes<<8) + bits_per_pixel) {
130  case 0x0308:
131  avctx->pix_fmt = AV_PIX_FMT_RGB24;
132  break;
133  case 0x0108:
134  case 0x0104:
135  case 0x0102:
136  case 0x0101:
137  case 0x0401:
138  case 0x0301:
139  case 0x0201:
140  avctx->pix_fmt = AV_PIX_FMT_PAL8;
141  break;
142  default:
143  av_log(avctx, AV_LOG_ERROR, "invalid PCX file\n");
144  return -1;
145  }
146 
147  buf += 128;
148 
149  if (p->data[0])
150  avctx->release_buffer(avctx, p);
151 
152  if (av_image_check_size(w, h, 0, avctx))
153  return -1;
154  if (w != avctx->width || h != avctx->height)
155  avcodec_set_dimensions(avctx, w, h);
156  if (ff_get_buffer(avctx, p) < 0) {
157  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
158  return -1;
159  }
160 
162 
163  ptr = p->data[0];
164  stride = p->linesize[0];
165 
166  scanline = av_malloc(bytes_per_scanline);
167  if (!scanline)
168  return AVERROR(ENOMEM);
169 
170  if (nplanes == 3 && bits_per_pixel == 8) {
171  for (y=0; y<h; y++) {
172  buf = pcx_rle_decode(buf, buf_end,
173  scanline, bytes_per_scanline, compressed);
174 
175  for (x=0; x<w; x++) {
176  ptr[3*x ] = scanline[x ];
177  ptr[3*x+1] = scanline[x+ bytes_per_line ];
178  ptr[3*x+2] = scanline[x+(bytes_per_line<<1)];
179  }
180 
181  ptr += stride;
182  }
183 
184  } else if (nplanes == 1 && bits_per_pixel == 8) {
185  const uint8_t *palstart = bufstart + buf_size - 769;
186 
187  if (buf_size < 769) {
188  av_log(avctx, AV_LOG_ERROR, "File is too short\n");
189  ret = buf_size;
190  goto end;
191  }
192 
193  for (y = 0; y < h; y++, ptr += stride) {
194  buf = pcx_rle_decode(buf, buf_end,
195  scanline, bytes_per_scanline, compressed);
196  memcpy(ptr, scanline, w);
197  }
198 
199  if (buf != palstart) {
200  av_log(avctx, AV_LOG_WARNING, "image data possibly corrupted\n");
201  buf = palstart;
202  }
203  if (*buf++ != 12) {
204  av_log(avctx, AV_LOG_ERROR, "expected palette after image data\n");
205  ret = buf_size;
206  goto end;
207  }
208 
209  } else if (nplanes == 1) { /* all packed formats, max. 16 colors */
210  GetBitContext s;
211 
212  for (y=0; y<h; y++) {
213  init_get_bits(&s, scanline, bytes_per_scanline<<3);
214 
215  buf = pcx_rle_decode(buf, buf_end,
216  scanline, bytes_per_scanline, compressed);
217 
218  for (x=0; x<w; x++)
219  ptr[x] = get_bits(&s, bits_per_pixel);
220  ptr += stride;
221  }
222 
223  } else { /* planar, 4, 8 or 16 colors */
224  int i;
225 
226  for (y=0; y<h; y++) {
227  buf = pcx_rle_decode(buf, buf_end,
228  scanline, bytes_per_scanline, compressed);
229 
230  for (x=0; x<w; x++) {
231  int m = 0x80 >> (x&7), v = 0;
232  for (i=nplanes - 1; i>=0; i--) {
233  v <<= 1;
234  v += !!(scanline[i*bytes_per_line + (x>>3)] & m);
235  }
236  ptr[x] = v;
237  }
238  ptr += stride;
239  }
240  }
241 
242  if (nplanes == 1 && bits_per_pixel == 8) {
243  pcx_palette(&buf, (uint32_t *) p->data[1], 256);
244  } else if (bits_per_pixel < 8) {
245  const uint8_t *palette = bufstart+16;
246  pcx_palette(&palette, (uint32_t *) p->data[1], 16);
247  }
248 
249  *picture = s->picture;
250  *got_frame = 1;
251 
252  ret = buf - bufstart;
253 end:
254  av_free(scanline);
255  return ret;
256 }
257 
258 static av_cold int pcx_end(AVCodecContext *avctx) {
259  PCXContext *s = avctx->priv_data;
260 
261  if(s->picture.data[0])
262  avctx->release_buffer(avctx, &s->picture);
263 
264  return 0;
265 }
266 
268  .name = "pcx",
269  .type = AVMEDIA_TYPE_VIDEO,
270  .id = AV_CODEC_ID_PCX,
271  .priv_data_size = sizeof(PCXContext),
272  .init = pcx_init,
273  .close = pcx_end,
275  .capabilities = CODEC_CAP_DR1,
276  .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"),
277 };
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:61
This structure describes decoded (raw) audio or video data.
Definition: avcodec.h:989
void(* release_buffer)(struct AVCodecContext *c, AVFrame *pic)
Called to release buffers which were allocated with get_buffer.
Definition: avcodec.h:2259
misc image utilities
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:237
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:67
AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:2725
static av_cold int pcx_init(AVCodecContext *avctx)
Definition: pcx.c:35
void avcodec_set_dimensions(AVCodecContext *s, int width, int height)
Definition: utils.c:149
int size
Definition: avcodec.h:916
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1533
#define AV_RL16
Definition: intreadwrite.h:42
AVCodec ff_pcx_decoder
Definition: pcx.c:267
uint8_t run
Definition: svq3.c:132
static av_cold int pcx_end(AVCodecContext *avctx)
Definition: pcx.c:258
int stride
Definition: mace.c:144
AVCodec.
Definition: avcodec.h:2960
static int decode(MimicContext *ctx, int quality, int num_coeffs, int is_iframe)
Definition: mimic.c:228
uint8_t
Definition: pcx.c:31
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:76
const char data[16]
Definition: mxf.c:66
uint8_t * data
Definition: avcodec.h:915
bitstream reader API header.
static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: pcx.c:83
static int init(AVCodecParserContext *s)
Definition: h264_parser.c:335
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:139
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:88
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:146
const char * name
Name of the codec implementation.
Definition: avcodec.h:2967
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:220
static AVFrame * picture
enum AVPictureType pict_type
Picture type of the frame, see ?_TYPE below.
Definition: avcodec.h:1065
int width
picture width / height.
Definition: avcodec.h:1508
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame)
Get a buffer for a frame.
Definition: utils.c:464
struct PCXContext PCXContext
external API header
int linesize[AV_NUM_DATA_POINTERS]
Size, in bytes, of the data for each picture/channel plane.
Definition: avcodec.h:1008
main external API structure.
Definition: avcodec.h:1339
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:326
void avcodec_get_frame_defaults(AVFrame *frame)
Set the fields of the given AVFrame to default values.
Definition: utils.c:604
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:372
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: avcodec.h:997
static const uint8_t * pcx_rle_decode(const uint8_t *src, const uint8_t *end, uint8_t *dst, unsigned int bytes_per_scanline, int compressed)
Definition: pcx.c:47
common internal api header.
static void pcx_palette(const uint8_t **src, uint32_t *dst, unsigned int pallen)
Definition: pcx.c:74
void * priv_data
Definition: avcodec.h:1382
This structure stores compressed data.
Definition: avcodec.h:898
AVFrame picture
Definition: pcx.c:32