"Fossies" - the Fresh Open Source Software Archive

Member "libav-12.3/libavcodec/pictordec.c" (12 Feb 2018, 8254 Bytes) of package /linux/misc/libav-12.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pictordec.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 12.2_vs_12.3.

    1 /*
    2  * Pictor/PC Paint decoder
    3  * Copyright (c) 2010 Peter Ross <pross@xvid.org>
    4  *
    5  * This file is part of Libav.
    6  *
    7  * Libav is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation; either
   10  * version 2.1 of the License, or (at your option) any later version.
   11  *
   12  * Libav is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with Libav; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   20  */
   21 
   22 /**
   23  * @file
   24  * Pictor/PC Paint decoder
   25  */
   26 
   27 #include "libavutil/imgutils.h"
   28 #include "avcodec.h"
   29 #include "bytestream.h"
   30 #include "cga_data.h"
   31 #include "internal.h"
   32 
   33 typedef struct PicContext {
   34     int width, height;
   35     int nb_planes;
   36     GetByteContext g;
   37 } PicContext;
   38 
   39 static void picmemset_8bpp(PicContext *s, AVFrame *frame, int value, int run,
   40                            int *x, int *y)
   41 {
   42     while (run > 0) {
   43         uint8_t *d = frame->data[0] + *y * frame->linesize[0];
   44         if (*x + run >= s->width) {
   45             int n = s->width - *x;
   46             memset(d + *x, value, n);
   47             run -= n;
   48             *x = 0;
   49             *y -= 1;
   50             if (*y < 0)
   51                 break;
   52         } else {
   53             memset(d + *x, value, run);
   54             *x += run;
   55             break;
   56         }
   57     }
   58 }
   59 
   60 static void picmemset(PicContext *s, AVFrame *frame, int value, int run,
   61                       int *x, int *y, int *plane, int bits_per_plane)
   62 {
   63     uint8_t *d;
   64     int shift = *plane * bits_per_plane;
   65     int mask  = ((1 << bits_per_plane) - 1) << shift;
   66     value   <<= shift;
   67 
   68     while (run > 0) {
   69         int j;
   70         for (j = 8-bits_per_plane; j >= 0; j -= bits_per_plane) {
   71             d = frame->data[0] + *y * frame->linesize[0];
   72             d[*x] |= (value >> j) & mask;
   73             *x += 1;
   74             if (*x == s->width) {
   75                 *y -= 1;
   76                 *x = 0;
   77                 if (*y < 0) {
   78                    *y = s->height - 1;
   79                    *plane += 1;
   80                    value <<= bits_per_plane;
   81                    mask  <<= bits_per_plane;
   82                    if (*plane >= s->nb_planes)
   83                        break;
   84                 }
   85             }
   86         }
   87         run--;
   88     }
   89 }
   90 
   91 static const uint8_t cga_mode45_index[6][4] = {
   92     [0] = { 0, 3,  5,   7 }, // mode4, palette#1, low intensity
   93     [1] = { 0, 2,  4,   6 }, // mode4, palette#2, low intensity
   94     [2] = { 0, 3,  4,   7 }, // mode5, low intensity
   95     [3] = { 0, 11, 13, 15 }, // mode4, palette#1, high intensity
   96     [4] = { 0, 10, 12, 14 }, // mode4, palette#2, high intensity
   97     [5] = { 0, 11, 12, 15 }, // mode5, high intensity
   98 };
   99 
  100 static int decode_frame(AVCodecContext *avctx,
  101                         void *data, int *got_frame,
  102                         AVPacket *avpkt)
  103 {
  104     PicContext *s = avctx->priv_data;
  105     AVFrame *frame = data;
  106     uint32_t *palette;
  107     int bits_per_plane, bpp, etype, esize, npal, pos_after_pal;
  108     int i, x, y, plane, tmp, ret;
  109 
  110     bytestream2_init(&s->g, avpkt->data, avpkt->size);
  111 
  112     if (bytestream2_get_bytes_left(&s->g) < 11)
  113         return AVERROR_INVALIDDATA;
  114 
  115     if (bytestream2_get_le16u(&s->g) != 0x1234)
  116         return AVERROR_INVALIDDATA;
  117 
  118     s->width       = bytestream2_get_le16u(&s->g);
  119     s->height      = bytestream2_get_le16u(&s->g);
  120     bytestream2_skip(&s->g, 4);
  121     tmp            = bytestream2_get_byteu(&s->g);
  122     bits_per_plane = tmp & 0xF;
  123     s->nb_planes   = (tmp >> 4) + 1;
  124     bpp            = bits_per_plane * s->nb_planes;
  125     if (bits_per_plane > 8 || bpp < 1 || bpp > 32) {
  126         avpriv_request_sample(avctx, "Unsupported bit depth");
  127         return AVERROR_PATCHWELCOME;
  128     }
  129 
  130     if (bytestream2_peek_byte(&s->g) == 0xFF) {
  131         bytestream2_skip(&s->g, 2);
  132         etype = bytestream2_get_le16(&s->g);
  133         esize = bytestream2_get_le16(&s->g);
  134         if (bytestream2_get_bytes_left(&s->g) < esize)
  135             return AVERROR_INVALIDDATA;
  136     } else {
  137         etype = -1;
  138         esize = 0;
  139     }
  140 
  141     avctx->pix_fmt = AV_PIX_FMT_PAL8;
  142 
  143     if (s->width != avctx->width || s->height != avctx->height) {
  144         ret = ff_set_dimensions(avctx, s->width, s->height);
  145         if (ret < 0)
  146             return ret;
  147     }
  148 
  149     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
  150         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
  151         return ret;
  152     }
  153     memset(frame->data[0], 0, s->height * frame->linesize[0]);
  154     frame->pict_type           = AV_PICTURE_TYPE_I;
  155     frame->palette_has_changed = 1;
  156 
  157     pos_after_pal = bytestream2_tell(&s->g) + esize;
  158     palette = (uint32_t*)frame->data[1];
  159     if (etype == 1 && esize > 1 && bytestream2_peek_byte(&s->g) < 6) {
  160         int idx = bytestream2_get_byte(&s->g);
  161         npal = 4;
  162         for (i = 0; i < npal; i++)
  163             palette[i] = ff_cga_palette[ cga_mode45_index[idx][i] ];
  164     } else if (etype == 2) {
  165         npal = FFMIN(esize, 16);
  166         for (i = 0; i < npal; i++) {
  167             int pal_idx = bytestream2_get_byte(&s->g);
  168             palette[i]  = ff_cga_palette[FFMIN(pal_idx, 16)];
  169         }
  170     } else if (etype == 3) {
  171         npal = FFMIN(esize, 16);
  172         for (i = 0; i < npal; i++) {
  173             int pal_idx = bytestream2_get_byte(&s->g);
  174             palette[i]  = ff_ega_palette[FFMIN(pal_idx, 63)];
  175         }
  176     } else if (etype == 4 || etype == 5) {
  177         npal = FFMIN(esize / 3, 256);
  178         for (i = 0; i < npal; i++)
  179             palette[i] = bytestream2_get_be24(&s->g) << 2;
  180     } else {
  181         if (bpp == 1) {
  182             npal = 2;
  183             palette[0] = 0x000000;
  184             palette[1] = 0xFFFFFF;
  185         } else if (bpp == 2) {
  186             npal = 4;
  187             for (i = 0; i < npal; i++)
  188                 palette[i] = ff_cga_palette[ cga_mode45_index[0][i] ];
  189         } else {
  190             npal = 16;
  191             memcpy(palette, ff_cga_palette, npal * 4);
  192         }
  193     }
  194     // fill remaining palette entries
  195     memset(palette + npal, 0, AVPALETTE_SIZE - npal * 4);
  196     // skip remaining palette bytes
  197     bytestream2_seek(&s->g, pos_after_pal, SEEK_SET);
  198 
  199     x = 0;
  200     y = s->height - 1;
  201     plane = 0;
  202     if (bytestream2_get_le16(&s->g)) {
  203         while (bytestream2_get_bytes_left(&s->g) >= 6) {
  204             int stop_size, marker, t1, t2;
  205 
  206             t1        = bytestream2_get_bytes_left(&s->g);
  207             t2        = bytestream2_get_le16(&s->g);
  208             stop_size = t1 - FFMIN(t1, t2);
  209             // ignore uncompressed block size
  210             bytestream2_skip(&s->g, 2);
  211             marker    = bytestream2_get_byte(&s->g);
  212 
  213             while (plane < s->nb_planes &&
  214                    bytestream2_get_bytes_left(&s->g) > stop_size) {
  215                 int run = 1;
  216                 int val = bytestream2_get_byte(&s->g);
  217                 if (val == marker) {
  218                     run = bytestream2_get_byte(&s->g);
  219                     if (run == 0)
  220                         run = bytestream2_get_le16(&s->g);
  221                     val = bytestream2_get_byte(&s->g);
  222                 }
  223                 if (!bytestream2_get_bytes_left(&s->g))
  224                     break;
  225 
  226                 if (bits_per_plane == 8) {
  227                     picmemset_8bpp(s, frame, val, run, &x, &y);
  228                     if (y < 0)
  229                         goto finish;
  230                 } else {
  231                     picmemset(s, frame, val, run, &x, &y, &plane, bits_per_plane);
  232                 }
  233             }
  234         }
  235     } else {
  236         avpriv_request_sample(avctx, "Uncompressed image");
  237         return avpkt->size;
  238     }
  239 finish:
  240 
  241     *got_frame      = 1;
  242     return avpkt->size;
  243 }
  244 
  245 AVCodec ff_pictor_decoder = {
  246     .name           = "pictor",
  247     .long_name      = NULL_IF_CONFIG_SMALL("Pictor/PC Paint"),
  248     .type           = AVMEDIA_TYPE_VIDEO,
  249     .id             = AV_CODEC_ID_PICTOR,
  250     .priv_data_size = sizeof(PicContext),
  251     .decode         = decode_frame,
  252     .capabilities   = AV_CODEC_CAP_DR1,
  253 };