Home | History | Annotate | Download | only in enc
      1 // Copyright 2011 Google Inc.
      2 //
      3 // This code is licensed under the same terms as WebM:
      4 //  Software License Agreement:  http://www.webmproject.org/license/software/
      5 //  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
      6 // -----------------------------------------------------------------------------
      7 //
      8 // Alpha-plane compression.
      9 //
     10 // Author: Skal (pascal.massimino (at) gmail.com)
     11 
     12 #include <assert.h>
     13 #include <stdlib.h>
     14 #include "vp8enci.h"
     15 
     16 #ifdef WEBP_EXPERIMENTAL_FEATURES
     17 #include "zlib.h"
     18 #endif
     19 
     20 #if defined(__cplusplus) || defined(c_plusplus)
     21 extern "C" {
     22 #endif
     23 
     24 #ifdef WEBP_EXPERIMENTAL_FEATURES
     25 
     26 #define CHUNK_SIZE 8192
     27 
     28 //-----------------------------------------------------------------------------
     29 
     30 static int CompressAlpha(const uint8_t* data, size_t data_size,
     31                          uint8_t** output, size_t* output_size,
     32                          int algo) {
     33   int ret = Z_OK;
     34   z_stream strm;
     35   unsigned char chunk[CHUNK_SIZE];
     36 
     37   *output = NULL;
     38   *output_size = 0;
     39   memset(&strm, 0, sizeof(strm));
     40   if (deflateInit(&strm, algo ? Z_BEST_SPEED : Z_BEST_COMPRESSION) != Z_OK) {
     41     return 0;
     42   }
     43   strm.next_in = (unsigned char*)data;
     44   strm.avail_in = data_size;
     45   do {
     46     size_t size_out;
     47 
     48     strm.next_out = chunk;
     49     strm.avail_out = CHUNK_SIZE;
     50     ret = deflate(&strm, Z_FINISH);
     51     if (ret == Z_STREAM_ERROR) {
     52       break;
     53     }
     54     size_out = CHUNK_SIZE - strm.avail_out;
     55     if (size_out) {
     56       size_t new_size = *output_size + size_out;
     57       uint8_t* new_output = realloc(*output, new_size);
     58       if (new_output == NULL) {
     59         ret = Z_MEM_ERROR;
     60         break;
     61       }
     62       memcpy(new_output + *output_size, chunk, size_out);
     63       *output_size = new_size;
     64       *output = new_output;
     65     }
     66   } while (ret != Z_STREAM_END || strm.avail_out == 0);
     67 
     68   deflateEnd(&strm);
     69   if (ret != Z_STREAM_END) {
     70     free(*output);
     71     output_size = 0;
     72     return 0;
     73   }
     74   return 1;
     75 }
     76 
     77 #endif    /* WEBP_EXPERIMENTAL_FEATURES */
     78 
     79 void VP8EncInitAlpha(VP8Encoder* enc) {
     80   enc->has_alpha_ = (enc->pic_->a != NULL);
     81   enc->alpha_data_ = NULL;
     82   enc->alpha_data_size_ = 0;
     83 }
     84 
     85 void VP8EncCodeAlphaBlock(VP8EncIterator* it) {
     86   (void)it;
     87   // Nothing for now. We just ZLIB-compress in the end.
     88 }
     89 
     90 int VP8EncFinishAlpha(VP8Encoder* enc) {
     91   if (enc->has_alpha_) {
     92 #ifdef WEBP_EXPERIMENTAL_FEATURES
     93     const WebPPicture* pic = enc->pic_;
     94     assert(pic->a);
     95     if (!CompressAlpha(pic->a, pic->width * pic->height,
     96                        &enc->alpha_data_, &enc->alpha_data_size_,
     97                        enc->config_->alpha_compression)) {
     98       return 0;
     99     }
    100 #endif
    101   }
    102   return 1;
    103 }
    104 
    105 void VP8EncDeleteAlpha(VP8Encoder* enc) {
    106   free(enc->alpha_data_);
    107   enc->alpha_data_ = NULL;
    108   enc->alpha_data_size_ = 0;
    109   enc->has_alpha_ = 0;
    110 }
    111 
    112 #if defined(__cplusplus) || defined(c_plusplus)
    113 }    // extern "C"
    114 #endif
    115