⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgi.c

📁 FFmpeg is an audio/video conversion tool. It includes libavcodec, the leading open source codec libr
💻 C
字号:
/* * SGI image format * Todd Kirby <doubleshot@pacbell.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "avformat.h"#include "avio.h"/* #define DEBUG *//* sgi image file signature */#define SGI_MAGIC 474#define SGI_HEADER_SIZE 512#define SGI_GRAYSCALE 1#define SGI_RGB 3#define SGI_RGBA 4#define SGI_SINGLE_CHAN 2#define SGI_MULTI_CHAN 3typedef struct SGIInfo{    short magic;    char rle;    char bytes_per_channel;    unsigned short dimension;    unsigned short xsize;    unsigned short ysize;    unsigned short zsize;} SGIInfo;static int sgi_probe(AVProbeData *pd){    /* test for sgi magic */    if (pd->buf_size >= 2 && BE_16(&pd->buf[0]) == SGI_MAGIC) {        return AVPROBE_SCORE_MAX;    } else {        return 0;    }}/* read sgi header fields */static void read_sgi_header(ByteIOContext *f, SGIInfo *info){    info->magic = (unsigned short) get_be16(f);    info->rle = get_byte(f);    info->bytes_per_channel = get_byte(f);    info->dimension = (unsigned short)get_be16(f);    info->xsize = (unsigned short) get_be16(f);    info->ysize = (unsigned short) get_be16(f);    info->zsize = (unsigned short) get_be16(f);#ifdef DEBUG    printf("sgi header fields:\n");    printf("  magic: %d\n", info->magic);    printf("    rle: %d\n", info->rle);    printf("    bpc: %d\n", info->bytes_per_channel);    printf("    dim: %d\n", info->dimension);    printf("  xsize: %d\n", info->xsize);    printf("  ysize: %d\n", info->ysize);    printf("  zsize: %d\n", info->zsize);#endif    return;}/* read an uncompressed sgi image */static int read_uncompressed_sgi(const SGIInfo *si,         AVPicture *pict, ByteIOContext *f){    int x, y, z, chan_offset, ret = 0;    uint8_t *dest_row;    /* skip header */     url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);    pict->linesize[0] = si->xsize;    for (z = 0; z < si->zsize; z++) {#ifndef WORDS_BIGENDIAN        /* rgba -> bgra for rgba32 on little endian cpus */        if (si->zsize == 4 && z != 3)             chan_offset = 2 - z;        else#endif            chan_offset = z;                    for (y = si->ysize - 1; y >= 0; y--) {            dest_row = pict->data[0] + (y * si->xsize * si->zsize);            for (x = 0; x < si->xsize; x++) {                dest_row[chan_offset] = get_byte(f);                 dest_row += si->zsize;            }        }    }    return ret;}/* expand an rle row into a channel */static int expand_rle_row(ByteIOContext *f, unsigned char *optr,        int chan_offset, int pixelstride){    unsigned char pixel, count;    int length = 0; #ifndef WORDS_BIGENDIAN    /* rgba -> bgra for rgba32 on little endian cpus */    if (pixelstride == 4 && chan_offset != 3) {       chan_offset = 2 - chan_offset;    }#endif            optr += chan_offset;    while (1) {        pixel = get_byte(f);        if (!(count = (pixel & 0x7f))) {            return length;        }        if (pixel & 0x80) {            while (count--) {                *optr = get_byte(f);                length++;                optr += pixelstride;            }        } else {            pixel = get_byte(f);            while (count--) {                *optr = pixel;                length++;                optr += pixelstride;            }        }    }}/* read a run length encoded sgi image */static int read_rle_sgi(const SGIInfo *sgi_info,         AVPicture *pict, ByteIOContext *f){    uint8_t *dest_row;    unsigned long *start_table;    int y, z, xsize, ysize, zsize, tablen;     long start_offset;    int ret = 0;    xsize = sgi_info->xsize;    ysize = sgi_info->ysize;    zsize = sgi_info->zsize;    /* skip header */     url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);    /* size of rle offset and length tables */    tablen = ysize * zsize * sizeof(long);    start_table = (unsigned long *)av_malloc(tablen);    if (!get_buffer(f, (uint8_t *)start_table, tablen)) {        ret = AVERROR_IO;        goto fail;    }    /* skip run length table */     url_fseek(f, tablen, SEEK_CUR);    for (z = 0; z < zsize; z++) {        for (y = 0; y < ysize; y++) {            dest_row = pict->data[0] + (ysize - 1 - y) * (xsize * zsize);            start_offset = BE_32(&start_table[y + z * ysize]);            /* don't seek if already at the next rle start offset */            if (url_ftell(f) != start_offset) {                url_fseek(f, start_offset, SEEK_SET);            }            if (expand_rle_row(f, dest_row, z, zsize) != xsize) {              ret =  AVERROR_INVALIDDATA;              goto fail;            }        }    }fail:    av_free(start_table);    return ret;}static int sgi_read(ByteIOContext *f,         int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque){    SGIInfo sgi_info, *s = &sgi_info;    AVImageInfo info1, *info = &info1;    int ret;    read_sgi_header(f, s);    if (s->bytes_per_channel != 1) {        return AVERROR_INVALIDDATA;    }    /* check for supported image dimensions */    if (s->dimension != 2 && s->dimension != 3) {        return AVERROR_INVALIDDATA;    }    if (s->zsize == SGI_GRAYSCALE) {        info->pix_fmt = PIX_FMT_GRAY8;    } else if (s->zsize == SGI_RGB) {        info->pix_fmt = PIX_FMT_RGB24;    } else if (s->zsize == SGI_RGBA) {        info->pix_fmt = PIX_FMT_RGBA32;    } else {        return AVERROR_INVALIDDATA;    }    info->width = s->xsize;    info->height = s->ysize;    ret = alloc_cb(opaque, info);    if (ret)        return ret;    if (s->rle) {        return read_rle_sgi(s, &info->pict, f);    } else {        return read_uncompressed_sgi(s, &info->pict, f);    }    return 0; /* not reached */}#ifdef CONFIG_ENCODERSstatic void write_sgi_header(ByteIOContext *f, const SGIInfo *info){    int i;    put_be16(f, SGI_MAGIC);    put_byte(f, info->rle);    put_byte(f, info->bytes_per_channel);     put_be16(f, info->dimension);    put_be16(f, info->xsize);    put_be16(f, info->ysize);    put_be16(f, info->zsize);    /* The rest are constant in this implementation */    put_be32(f, 0L); /* pixmin */     put_be32(f, 255L); /* pixmax */     put_be32(f, 0L); /* dummy */     /* name */    for (i = 0; i < 80; i++) {        put_byte(f, 0);    }    put_be32(f, 0L); /* colormap */     /* The rest of the 512 byte header is unused. */    for (i = 0; i < 404; i++) {        put_byte(f, 0);    }}static int rle_row(ByteIOContext *f, char *row, int stride, int rowsize){    int length, count, i, x;    char *start, repeat = 0;    for (x = rowsize, length = 0; x > 0;) {        start = row;        row += (2 * stride);        x -= 2;        while (x > 0 && (row[-2 * stride] != row[-1 * stride] ||                     row[-1 * stride] != row[0])) {            row += stride;            x--;        };        row -= (2 * stride);        x += 2;        count = (row - start) / stride;        while (count > 0) {            i = count > 126 ? 126 : count;            count -= i;            put_byte(f, 0x80 | i);             length++;            while (i > 0) {                put_byte(f, *start);                start += stride;                i--;                length++;            };        };        if (x <= 0) {            break;        }        start = row;        repeat = row[0];        row += stride;        x--;        while (x > 0 && *row == repeat) {            row += stride;            x--;        };        count = (row - start) / stride;        while (count > 0) {            i = count > 126 ? 126 : count;            count -= i;            put_byte(f, i);            length++;            put_byte(f, repeat);             length++;        };    };    length++;    put_byte(f, 0);     return (length);}static int sgi_write(ByteIOContext *pb, AVImageInfo *info){    SGIInfo sgi_info, *si = &sgi_info;    long *offsettab, *lengthtab;    int i, y, z;    int tablesize, chan_offset;    uint8_t *srcrow;    si->xsize = info->width;    si->ysize = info->height;    si->rle = 1;    si->bytes_per_channel = 1;        switch(info->pix_fmt) {        case PIX_FMT_GRAY8:            si->dimension = SGI_SINGLE_CHAN;            si->zsize = SGI_GRAYSCALE;            break;        case PIX_FMT_RGB24:            si->dimension = SGI_MULTI_CHAN;            si->zsize = SGI_RGB;            break;         case PIX_FMT_RGBA32:            si->dimension = SGI_MULTI_CHAN;            si->zsize = SGI_RGBA;            break;        default:            return AVERROR_INVALIDDATA;    }    write_sgi_header(pb, si);     tablesize = si->zsize * si->ysize * sizeof(long);        /* skip rle offset and length tables, write them at the end. */    url_fseek(pb, tablesize * 2, SEEK_CUR);    put_flush_packet(pb);        lengthtab = av_malloc(tablesize);    offsettab = av_malloc(tablesize);    for (z = 0; z < si->zsize; z++) {#ifndef WORDS_BIGENDIAN        /* rgba -> bgra for rgba32 on little endian cpus */        if (si->zsize == 4 && z != 3)             chan_offset = 2 - z;        else#endif            chan_offset = z;                srcrow = info->pict.data[0] + chan_offset;                for (y = si->ysize -1; y >= 0; y--) {            offsettab[(z * si->ysize) + y] = url_ftell(pb);            lengthtab[(z * si->ysize) + y] = rle_row(pb, srcrow,                    si->zsize, si->xsize);            srcrow += info->pict.linesize[0];         }    }    url_fseek(pb, 512, SEEK_SET);        /* write offset table */    for (i = 0; i < (si->ysize * si->zsize); i++) {        put_be32(pb, offsettab[i]);    }     /* write length table */    for (i = 0; i < (si->ysize * si->zsize); i++) {        put_be32(pb, lengthtab[i]);    }    put_flush_packet(pb);        av_free(lengthtab);    av_free(offsettab);    return 0;}#endif // CONFIG_ENCODERSAVImageFormat sgi_image_format = {    "sgi",    "sgi,rgb,rgba,bw",    sgi_probe,    sgi_read,    (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_RGBA32), #ifdef CONFIG_ENCODERS    sgi_write,#else    NULL,#endif // CONFIG_ENCODERS};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -