Libav 0.7.1
|
00001 /* 00002 * Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image decoder 00003 * Copyright (c) 2007, 2008 Ivo van Poorten 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavutil/intreadwrite.h" 00023 #include "libavutil/imgutils.h" 00024 #include "avcodec.h" 00025 00026 #define RT_OLD 0 00027 #define RT_STANDARD 1 00028 #define RT_BYTE_ENCODED 2 00029 #define RT_FORMAT_RGB 3 00030 #define RT_FORMAT_TIFF 4 00031 #define RT_FORMAT_IFF 5 00032 00033 typedef struct SUNRASTContext { 00034 AVFrame picture; 00035 } SUNRASTContext; 00036 00037 static av_cold int sunrast_init(AVCodecContext *avctx) { 00038 SUNRASTContext *s = avctx->priv_data; 00039 00040 avcodec_get_frame_defaults(&s->picture); 00041 avctx->coded_frame= &s->picture; 00042 00043 return 0; 00044 } 00045 00046 static int sunrast_decode_frame(AVCodecContext *avctx, void *data, 00047 int *data_size, AVPacket *avpkt) { 00048 const uint8_t *buf = avpkt->data; 00049 SUNRASTContext * const s = avctx->priv_data; 00050 AVFrame *picture = data; 00051 AVFrame * const p = &s->picture; 00052 unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen; 00053 uint8_t *ptr; 00054 const uint8_t *bufstart = buf; 00055 00056 if (AV_RB32(buf) != 0x59a66a95) { 00057 av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n"); 00058 return -1; 00059 } 00060 00061 w = AV_RB32(buf+4); 00062 h = AV_RB32(buf+8); 00063 depth = AV_RB32(buf+12); 00064 type = AV_RB32(buf+20); 00065 maptype = AV_RB32(buf+24); 00066 maplength = AV_RB32(buf+28); 00067 00068 if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) { 00069 av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n"); 00070 return -1; 00071 } 00072 if (type > RT_FORMAT_IFF) { 00073 av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n"); 00074 return -1; 00075 } 00076 if (maptype & ~1) { 00077 av_log(avctx, AV_LOG_ERROR, "invalid colormap type\n"); 00078 return -1; 00079 } 00080 00081 buf += 32; 00082 00083 switch (depth) { 00084 case 1: 00085 avctx->pix_fmt = PIX_FMT_MONOWHITE; 00086 break; 00087 case 8: 00088 avctx->pix_fmt = PIX_FMT_PAL8; 00089 break; 00090 case 24: 00091 avctx->pix_fmt = (type == RT_FORMAT_RGB) ? PIX_FMT_RGB24 : PIX_FMT_BGR24; 00092 break; 00093 default: 00094 av_log(avctx, AV_LOG_ERROR, "invalid depth\n"); 00095 return -1; 00096 } 00097 00098 if (p->data[0]) 00099 avctx->release_buffer(avctx, p); 00100 00101 if (av_image_check_size(w, h, 0, avctx)) 00102 return -1; 00103 if (w != avctx->width || h != avctx->height) 00104 avcodec_set_dimensions(avctx, w, h); 00105 if (avctx->get_buffer(avctx, p) < 0) { 00106 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00107 return -1; 00108 } 00109 00110 p->pict_type = AV_PICTURE_TYPE_I; 00111 00112 if (depth != 8 && maplength) { 00113 av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n"); 00114 00115 } else if (depth == 8) { 00116 unsigned int len = maplength / 3; 00117 00118 if (!maplength) { 00119 av_log(avctx, AV_LOG_ERROR, "colormap expected\n"); 00120 return -1; 00121 } 00122 if (maplength % 3 || maplength > 768) { 00123 av_log(avctx, AV_LOG_WARNING, "invalid colormap length\n"); 00124 return -1; 00125 } 00126 00127 ptr = p->data[1]; 00128 for (x=0; x<len; x++, ptr+=4) 00129 *(uint32_t *)ptr = (buf[x]<<16) + (buf[len+x]<<8) + buf[len+len+x]; 00130 } 00131 00132 buf += maplength; 00133 00134 ptr = p->data[0]; 00135 stride = p->linesize[0]; 00136 00137 /* scanlines are aligned on 16 bit boundaries */ 00138 len = (depth * w + 7) >> 3; 00139 alen = len + (len&1); 00140 00141 if (type == RT_BYTE_ENCODED) { 00142 int value, run; 00143 uint8_t *end = ptr + h*stride; 00144 00145 x = 0; 00146 while (ptr != end) { 00147 run = 1; 00148 if ((value = *buf++) == 0x80) { 00149 run = *buf++ + 1; 00150 if (run != 1) 00151 value = *buf++; 00152 } 00153 while (run--) { 00154 if (x < len) 00155 ptr[x] = value; 00156 if (++x >= alen) { 00157 x = 0; 00158 ptr += stride; 00159 if (ptr == end) 00160 break; 00161 } 00162 } 00163 } 00164 } else { 00165 for (y=0; y<h; y++) { 00166 memcpy(ptr, buf, len); 00167 ptr += stride; 00168 buf += alen; 00169 } 00170 } 00171 00172 *picture = s->picture; 00173 *data_size = sizeof(AVFrame); 00174 00175 return buf - bufstart; 00176 } 00177 00178 static av_cold int sunrast_end(AVCodecContext *avctx) { 00179 SUNRASTContext *s = avctx->priv_data; 00180 00181 if(s->picture.data[0]) 00182 avctx->release_buffer(avctx, &s->picture); 00183 00184 return 0; 00185 } 00186 00187 AVCodec ff_sunrast_decoder = { 00188 "sunrast", 00189 AVMEDIA_TYPE_VIDEO, 00190 CODEC_ID_SUNRAST, 00191 sizeof(SUNRASTContext), 00192 sunrast_init, 00193 NULL, 00194 sunrast_end, 00195 sunrast_decode_frame, 00196 CODEC_CAP_DR1, 00197 NULL, 00198 .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), 00199 };