• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/tiffenc.c

Go to the documentation of this file.
00001 /*
00002  * TIFF image encoder
00003  * Copyright (c) 2007 Bartlomiej Wolowiec
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #include "avcodec.h"
00028 #if CONFIG_ZLIB
00029 #include <zlib.h>
00030 #endif
00031 #include "bytestream.h"
00032 #include "tiff.h"
00033 #include "rle.h"
00034 #include "lzw.h"
00035 #include "put_bits.h"
00036 
00037 #define TIFF_MAX_ENTRY 32
00038 
00040 static const uint8_t type_sizes2[6] = {
00041     0, 1, 1, 2, 4, 8
00042 };
00043 
00044 typedef struct TiffEncoderContext {
00045     AVClass *avclass;
00046     AVCodecContext *avctx;
00047     AVFrame picture;
00048 
00049     int width;                          
00050     int height;                         
00051     unsigned int bpp;                   
00052     int compr;                          
00053     int bpp_tab_size;                   
00054     int photometric_interpretation;     
00055     int strips;                         
00056     int rps;                            
00057     uint8_t entries[TIFF_MAX_ENTRY*12]; 
00058     int num_entries;                    
00059     uint8_t **buf;                      
00060     uint8_t *buf_start;                 
00061     int buf_size;                       
00062     uint16_t subsampling[2];            
00063     struct LZWEncodeState *lzws;        
00064 } TiffEncoderContext;
00065 
00066 
00073 inline static int check_size(TiffEncoderContext * s, uint64_t need)
00074 {
00075     if (s->buf_size < *s->buf - s->buf_start + need) {
00076         *s->buf = s->buf_start + s->buf_size + 1;
00077         av_log(s->avctx, AV_LOG_ERROR, "Buffer is too small\n");
00078         return 1;
00079     }
00080     return 0;
00081 }
00082 
00092 static void tnput(uint8_t ** p, int n, const uint8_t * val, enum TiffTypes type,
00093                   int flip)
00094 {
00095     int i;
00096 #if HAVE_BIGENDIAN
00097     flip ^= ((int[]) {0, 0, 0, 1, 3, 3})[type];
00098 #endif
00099     for (i = 0; i < n * type_sizes2[type]; i++)
00100         *(*p)++ = val[i ^ flip];
00101 }
00102 
00111 static void add_entry(TiffEncoderContext * s,
00112                       enum TiffTags tag, enum TiffTypes type, int count,
00113                       const void *ptr_val)
00114 {
00115     uint8_t *entries_ptr = s->entries + 12 * s->num_entries;
00116 
00117     assert(s->num_entries < TIFF_MAX_ENTRY);
00118 
00119     bytestream_put_le16(&entries_ptr, tag);
00120     bytestream_put_le16(&entries_ptr, type);
00121     bytestream_put_le32(&entries_ptr, count);
00122 
00123     if (type_sizes[type] * count <= 4) {
00124         tnput(&entries_ptr, count, ptr_val, type, 0);
00125     } else {
00126         bytestream_put_le32(&entries_ptr, *s->buf - s->buf_start);
00127         check_size(s, count * type_sizes2[type]);
00128         tnput(s->buf, count, ptr_val, type, 0);
00129     }
00130 
00131     s->num_entries++;
00132 }
00133 
00134 static void add_entry1(TiffEncoderContext * s,
00135                        enum TiffTags tag, enum TiffTypes type, int val){
00136     uint16_t w = val;
00137     uint32_t dw= val;
00138     add_entry(s, tag, type, 1, type == TIFF_SHORT ? (void *)&w : (void *)&dw);
00139 }
00140 
00151 static int encode_strip(TiffEncoderContext * s, const int8_t * src,
00152                         uint8_t * dst, int n, int compr)
00153 {
00154 
00155     switch (compr) {
00156 #if CONFIG_ZLIB
00157     case TIFF_DEFLATE:
00158     case TIFF_ADOBE_DEFLATE:
00159         {
00160             unsigned long zlen = s->buf_size - (*s->buf - s->buf_start);
00161             if (compress(dst, &zlen, src, n) != Z_OK) {
00162                 av_log(s->avctx, AV_LOG_ERROR, "Compressing failed\n");
00163                 return -1;
00164             }
00165             return zlen;
00166         }
00167 #endif
00168     case TIFF_RAW:
00169         if (check_size(s, n))
00170             return -1;
00171         memcpy(dst, src, n);
00172         return n;
00173     case TIFF_PACKBITS:
00174         return ff_rle_encode(dst, s->buf_size - (*s->buf - s->buf_start), src, 1, n, 2, 0xff, -1, 0);
00175     case TIFF_LZW:
00176         return ff_lzw_encode(s->lzws, src, n);
00177     default:
00178         return -1;
00179     }
00180 }
00181 
00182 static void pack_yuv(TiffEncoderContext * s, uint8_t * dst, int lnum)
00183 {
00184     AVFrame *p = &s->picture;
00185     int i, j, k;
00186     int w = (s->width - 1) / s->subsampling[0] + 1;
00187     uint8_t *pu = &p->data[1][lnum / s->subsampling[1] * p->linesize[1]];
00188     uint8_t *pv = &p->data[2][lnum / s->subsampling[1] * p->linesize[2]];
00189     for (i = 0; i < w; i++){
00190         for (j = 0; j < s->subsampling[1]; j++)
00191             for (k = 0; k < s->subsampling[0]; k++)
00192                 *dst++ = p->data[0][(lnum + j) * p->linesize[0] +
00193                                     i * s->subsampling[0] + k];
00194         *dst++ = *pu++;
00195         *dst++ = *pv++;
00196     }
00197 }
00198 
00199 static int encode_frame(AVCodecContext * avctx, unsigned char *buf,
00200                         int buf_size, void *data)
00201 {
00202     TiffEncoderContext *s = avctx->priv_data;
00203     AVFrame *pict = data;
00204     AVFrame *const p = (AVFrame *) & s->picture;
00205     int i;
00206     int n;
00207     uint8_t *ptr = buf;
00208     uint8_t *offset;
00209     uint32_t strips;
00210     uint32_t *strip_sizes = NULL;
00211     uint32_t *strip_offsets = NULL;
00212     int bytes_per_row;
00213     uint32_t res[2] = { 72, 1 };        // image resolution (72/1)
00214     uint16_t bpp_tab[] = { 8, 8, 8, 8 };
00215     int ret = -1;
00216     int is_yuv = 0;
00217     uint8_t *yuv_line = NULL;
00218     int shift_h, shift_v;
00219 
00220     s->avctx = avctx;
00221     s->buf_start = buf;
00222     s->buf = &ptr;
00223     s->buf_size = buf_size;
00224 
00225     *p = *pict;
00226     p->pict_type = AV_PICTURE_TYPE_I;
00227     p->key_frame = 1;
00228     avctx->coded_frame= &s->picture;
00229 
00230     s->compr = TIFF_PACKBITS;
00231     if (avctx->compression_level == 0) {
00232         s->compr = TIFF_RAW;
00233     } else if(avctx->compression_level == 2) {
00234         s->compr = TIFF_LZW;
00235 #if CONFIG_ZLIB
00236     } else if ((avctx->compression_level >= 3)) {
00237         s->compr = TIFF_DEFLATE;
00238 #endif
00239     }
00240 
00241     s->width = avctx->width;
00242     s->height = avctx->height;
00243     s->subsampling[0] = 1;
00244     s->subsampling[1] = 1;
00245 
00246     switch (avctx->pix_fmt) {
00247     case PIX_FMT_RGB24:
00248         s->bpp = 24;
00249         s->photometric_interpretation = 2;
00250         break;
00251     case PIX_FMT_GRAY8:
00252         s->bpp = 8;
00253         s->photometric_interpretation = 1;
00254         break;
00255     case PIX_FMT_PAL8:
00256         s->bpp = 8;
00257         s->photometric_interpretation = 3;
00258         break;
00259     case PIX_FMT_MONOBLACK:
00260     case PIX_FMT_MONOWHITE:
00261         s->bpp = 1;
00262         s->photometric_interpretation = avctx->pix_fmt == PIX_FMT_MONOBLACK;
00263         bpp_tab[0] = 1;
00264         break;
00265     case PIX_FMT_YUV420P:
00266     case PIX_FMT_YUV422P:
00267     case PIX_FMT_YUV444P:
00268     case PIX_FMT_YUV410P:
00269     case PIX_FMT_YUV411P:
00270         s->photometric_interpretation = 6;
00271         avcodec_get_chroma_sub_sample(avctx->pix_fmt,
00272                 &shift_h, &shift_v);
00273         s->bpp = 8 + (16 >> (shift_h + shift_v));
00274         s->subsampling[0] = 1 << shift_h;
00275         s->subsampling[1] = 1 << shift_v;
00276         s->bpp_tab_size = 3;
00277         is_yuv = 1;
00278         break;
00279     default:
00280         av_log(s->avctx, AV_LOG_ERROR,
00281                "This colors format is not supported\n");
00282         return -1;
00283     }
00284     if (!is_yuv)
00285         s->bpp_tab_size = ((s->bpp + 7) >> 3);
00286 
00287     if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE || s->compr == TIFF_LZW)
00288         //best choose for DEFLATE
00289         s->rps = s->height;
00290     else
00291         s->rps = FFMAX(8192 / (((s->width * s->bpp) >> 3) + 1), 1);     // suggest size of strip
00292     s->rps = ((s->rps - 1) / s->subsampling[1] + 1) * s->subsampling[1]; // round rps up
00293 
00294     strips = (s->height - 1) / s->rps + 1;
00295 
00296     if (check_size(s, 8))
00297         goto fail;
00298 
00299     // write header
00300     bytestream_put_le16(&ptr, 0x4949);
00301     bytestream_put_le16(&ptr, 42);
00302 
00303     offset = ptr;
00304     bytestream_put_le32(&ptr, 0);
00305 
00306     strip_sizes = av_mallocz(sizeof(*strip_sizes) * strips);
00307     strip_offsets = av_mallocz(sizeof(*strip_offsets) * strips);
00308     if (!strip_sizes || !strip_offsets) {
00309         ret = AVERROR(ENOMEM);
00310         goto fail;
00311     }
00312 
00313     bytes_per_row = (((s->width - 1)/s->subsampling[0] + 1) * s->bpp
00314                     * s->subsampling[0] * s->subsampling[1] + 7) >> 3;
00315     if (is_yuv){
00316         yuv_line = av_malloc(bytes_per_row);
00317         if (yuv_line == NULL){
00318             av_log(s->avctx, AV_LOG_ERROR, "Not enough memory\n");
00319             ret = AVERROR(ENOMEM);
00320             goto fail;
00321         }
00322     }
00323 
00324 #if CONFIG_ZLIB
00325     if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) {
00326         uint8_t *zbuf;
00327         int zlen, zn;
00328         int j;
00329 
00330         zlen = bytes_per_row * s->rps;
00331         zbuf = av_malloc(zlen);
00332         if (!zbuf) {
00333             ret = AVERROR(ENOMEM);
00334             goto fail;
00335         }
00336         strip_offsets[0] = ptr - buf;
00337         zn = 0;
00338         for (j = 0; j < s->rps; j++) {
00339             if (is_yuv){
00340                 pack_yuv(s, yuv_line, j);
00341                 memcpy(zbuf + zn, yuv_line, bytes_per_row);
00342                 j += s->subsampling[1] - 1;
00343             }
00344             else
00345                 memcpy(zbuf + j * bytes_per_row,
00346                        p->data[0] + j * p->linesize[0], bytes_per_row);
00347             zn += bytes_per_row;
00348         }
00349         n = encode_strip(s, zbuf, ptr, zn, s->compr);
00350         av_free(zbuf);
00351         if (n<0) {
00352             av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n");
00353             goto fail;
00354         }
00355         ptr += n;
00356         strip_sizes[0] = ptr - buf - strip_offsets[0];
00357     } else
00358 #endif
00359     {
00360         if (s->compr == TIFF_LZW) {
00361             s->lzws = av_malloc(ff_lzw_encode_state_size);
00362             if (!s->lzws) {
00363                 ret = AVERROR(ENOMEM);
00364                 goto fail;
00365             }
00366         }
00367         for (i = 0; i < s->height; i++) {
00368             if (strip_sizes[i / s->rps] == 0) {
00369                 if(s->compr == TIFF_LZW){
00370                     ff_lzw_encode_init(s->lzws, ptr, s->buf_size - (*s->buf - s->buf_start),
00371                                        12, FF_LZW_TIFF, put_bits);
00372                 }
00373                 strip_offsets[i / s->rps] = ptr - buf;
00374             }
00375             if (is_yuv){
00376                  pack_yuv(s, yuv_line, i);
00377                  n = encode_strip(s, yuv_line, ptr, bytes_per_row, s->compr);
00378                  i += s->subsampling[1] - 1;
00379             }
00380             else
00381                 n = encode_strip(s, p->data[0] + i * p->linesize[0],
00382                         ptr, bytes_per_row, s->compr);
00383             if (n < 0) {
00384                 av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n");
00385                 goto fail;
00386             }
00387             strip_sizes[i / s->rps] += n;
00388             ptr += n;
00389             if(s->compr == TIFF_LZW && (i==s->height-1 || i%s->rps == s->rps-1)){
00390                 int ret;
00391                 ret = ff_lzw_encode_flush(s->lzws, flush_put_bits);
00392                 strip_sizes[(i / s->rps )] += ret ;
00393                 ptr += ret;
00394             }
00395         }
00396         if(s->compr == TIFF_LZW)
00397             av_free(s->lzws);
00398     }
00399 
00400     s->num_entries = 0;
00401 
00402     add_entry1(s,TIFF_SUBFILE,           TIFF_LONG,             0);
00403     add_entry1(s,TIFF_WIDTH,             TIFF_LONG,             s->width);
00404     add_entry1(s,TIFF_HEIGHT,            TIFF_LONG,             s->height);
00405 
00406     if (s->bpp_tab_size)
00407     add_entry(s, TIFF_BPP,               TIFF_SHORT,    s->bpp_tab_size, bpp_tab);
00408 
00409     add_entry1(s,TIFF_COMPR,             TIFF_SHORT,            s->compr);
00410     add_entry1(s,TIFF_INVERT,            TIFF_SHORT,            s->photometric_interpretation);
00411     add_entry(s, TIFF_STRIP_OFFS,        TIFF_LONG,     strips, strip_offsets);
00412 
00413     if (s->bpp_tab_size)
00414     add_entry1(s,TIFF_SAMPLES_PER_PIXEL, TIFF_SHORT,            s->bpp_tab_size);
00415 
00416     add_entry1(s,TIFF_ROWSPERSTRIP,      TIFF_LONG,             s->rps);
00417     add_entry(s, TIFF_STRIP_SIZE,        TIFF_LONG,     strips, strip_sizes);
00418     add_entry(s, TIFF_XRES,              TIFF_RATIONAL, 1,      res);
00419     add_entry(s, TIFF_YRES,              TIFF_RATIONAL, 1,      res);
00420     add_entry1(s,TIFF_RES_UNIT,          TIFF_SHORT,            2);
00421 
00422     if(!(avctx->flags & CODEC_FLAG_BITEXACT))
00423     add_entry(s, TIFF_SOFTWARE_NAME,     TIFF_STRING,
00424               strlen(LIBAVCODEC_IDENT) + 1, LIBAVCODEC_IDENT);
00425 
00426     if (avctx->pix_fmt == PIX_FMT_PAL8) {
00427         uint16_t pal[256 * 3];
00428         for (i = 0; i < 256; i++) {
00429             uint32_t rgb = *(uint32_t *) (p->data[1] + i * 4);
00430             pal[i]       = ((rgb >> 16) & 0xff) * 257;
00431             pal[i + 256] = ((rgb >> 8 ) & 0xff) * 257;
00432             pal[i + 512] = ( rgb        & 0xff) * 257;
00433         }
00434         add_entry(s, TIFF_PAL, TIFF_SHORT, 256 * 3, pal);
00435     }
00436     if (is_yuv){
00438         uint32_t refbw[12] = {15, 1, 235, 1, 128, 1, 240, 1, 128, 1, 240, 1};
00439         add_entry(s, TIFF_YCBCR_SUBSAMPLING, TIFF_SHORT,    2, s->subsampling);
00440         add_entry(s, TIFF_REFERENCE_BW,      TIFF_RATIONAL, 6, refbw);
00441     }
00442     bytestream_put_le32(&offset, ptr - buf);    // write offset to dir
00443 
00444     if (check_size(s, 6 + s->num_entries * 12))
00445         goto fail;
00446     bytestream_put_le16(&ptr, s->num_entries);  // write tag count
00447     bytestream_put_buffer(&ptr, s->entries, s->num_entries * 12);
00448     bytestream_put_le32(&ptr, 0);
00449 
00450     ret = ptr - buf;
00451 
00452 fail:
00453     av_free(strip_sizes);
00454     av_free(strip_offsets);
00455     av_free(yuv_line);
00456     return ret;
00457 }
00458 
00459 AVCodec ff_tiff_encoder = {
00460     "tiff",
00461     AVMEDIA_TYPE_VIDEO,
00462     CODEC_ID_TIFF,
00463     sizeof(TiffEncoderContext),
00464     NULL,
00465     encode_frame,
00466     NULL,
00467     NULL,
00468     0,
00469     NULL,
00470     .pix_fmts =
00471         (const enum PixelFormat[]) {PIX_FMT_RGB24, PIX_FMT_PAL8, PIX_FMT_GRAY8,
00472                               PIX_FMT_MONOBLACK, PIX_FMT_MONOWHITE,
00473                               PIX_FMT_YUV420P, PIX_FMT_YUV422P,
00474                               PIX_FMT_YUV444P, PIX_FMT_YUV410P,
00475                               PIX_FMT_YUV411P,
00476                               PIX_FMT_NONE},
00477     .long_name = NULL_IF_CONFIG_SMALL("TIFF image"),
00478 };

Generated on Fri Feb 22 2013 07:24:29 for FFmpeg by  doxygen 1.7.1