Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #ifdef HAVE_WEBP
     44 
     45 #include "precomp.hpp"
     46 
     47 #include <webp/decode.h>
     48 #include <webp/encode.h>
     49 
     50 #include <stdio.h>
     51 #include <limits.h>
     52 
     53 #include "grfmt_webp.hpp"
     54 
     55 #include "opencv2/imgproc.hpp"
     56 
     57 const size_t WEBP_HEADER_SIZE = 32;
     58 
     59 namespace cv
     60 {
     61 
     62 WebPDecoder::WebPDecoder()
     63 {
     64     m_buf_supported = true;
     65 }
     66 
     67 WebPDecoder::~WebPDecoder() {}
     68 
     69 size_t WebPDecoder::signatureLength() const
     70 {
     71     return WEBP_HEADER_SIZE;
     72 }
     73 
     74 bool WebPDecoder::checkSignature(const String & signature) const
     75 {
     76     bool ret = false;
     77 
     78     if(signature.size() >= WEBP_HEADER_SIZE)
     79     {
     80         WebPBitstreamFeatures features;
     81         if(VP8_STATUS_OK == WebPGetFeatures((uint8_t *)signature.c_str(),
     82                                             WEBP_HEADER_SIZE, &features))
     83         {
     84             ret = true;
     85         }
     86     }
     87 
     88     return ret;
     89 }
     90 
     91 ImageDecoder WebPDecoder::newDecoder() const
     92 {
     93     return makePtr<WebPDecoder>();
     94 }
     95 
     96 bool WebPDecoder::readHeader()
     97 {
     98     if (m_buf.empty())
     99     {
    100         FILE * wfile = NULL;
    101 
    102         wfile = fopen(m_filename.c_str(), "rb");
    103 
    104         if(wfile == NULL)
    105         {
    106             return false;
    107         }
    108 
    109         fseek(wfile, 0, SEEK_END);
    110         long int wfile_size = ftell(wfile);
    111         fseek(wfile, 0, SEEK_SET);
    112 
    113         if(wfile_size > static_cast<long int>(INT_MAX))
    114         {
    115             fclose(wfile);
    116             return false;
    117         }
    118 
    119         data.create(1, wfile_size, CV_8U);
    120 
    121         size_t data_size = fread(data.ptr(), 1, wfile_size, wfile);
    122 
    123         if(wfile)
    124         {
    125             fclose(wfile);
    126         }
    127 
    128         if(static_cast<long int>(data_size) != wfile_size)
    129         {
    130             return false;
    131         }
    132     }
    133     else
    134     {
    135         data = m_buf;
    136     }
    137 
    138     WebPBitstreamFeatures features;
    139     if(VP8_STATUS_OK == WebPGetFeatures(data.ptr(), WEBP_HEADER_SIZE, &features))
    140     {
    141         m_width  = features.width;
    142         m_height = features.height;
    143 
    144         if (features.has_alpha)
    145         {
    146             m_type = CV_8UC4;
    147             channels = 4;
    148         }
    149         else
    150         {
    151             m_type = CV_8UC3;
    152             channels = 3;
    153         }
    154 
    155         return true;
    156     }
    157 
    158     return false;
    159 }
    160 
    161 bool WebPDecoder::readData(Mat &img)
    162 {
    163     if( m_width > 0 && m_height > 0 )
    164     {
    165         if (img.cols != m_width || img.rows != m_height || img.type() != m_type)
    166         {
    167             img.create(m_height, m_width, m_type);
    168         }
    169 
    170         uchar* out_data = img.ptr();
    171         size_t out_data_size = img.cols * img.rows * img.elemSize();
    172 
    173         uchar *res_ptr = 0;
    174         if (channels == 3)
    175         {
    176             res_ptr = WebPDecodeBGRInto(data.ptr(), data.total(), out_data,
    177                                         (int)out_data_size, (int)img.step);
    178         }
    179         else if (channels == 4)
    180         {
    181             res_ptr = WebPDecodeBGRAInto(data.ptr(), data.total(), out_data,
    182                                          (int)out_data_size, (int)img.step);
    183         }
    184 
    185         if(res_ptr == out_data)
    186         {
    187             return true;
    188         }
    189     }
    190 
    191     return false;
    192 }
    193 
    194 WebPEncoder::WebPEncoder()
    195 {
    196     m_description = "WebP files (*.webp)";
    197     m_buf_supported = true;
    198 }
    199 
    200 WebPEncoder::~WebPEncoder() { }
    201 
    202 ImageEncoder WebPEncoder::newEncoder() const
    203 {
    204     return makePtr<WebPEncoder>();
    205 }
    206 
    207 bool WebPEncoder::write(const Mat& img, const std::vector<int>& params)
    208 {
    209     int channels = img.channels(), depth = img.depth();
    210     int width = img.cols, height = img.rows;
    211 
    212     const Mat *image = &img;
    213     Mat temp;
    214     size_t size = 0;
    215 
    216     bool comp_lossless = true;
    217     float quality = 100.0f;
    218 
    219     if (params.size() > 1)
    220     {
    221         if (params[0] == CV_IMWRITE_WEBP_QUALITY)
    222         {
    223             comp_lossless = false;
    224             quality = static_cast<float>(params[1]);
    225             if (quality < 1.0f)
    226             {
    227                 quality = 1.0f;
    228             }
    229             if (quality > 100.0f)
    230             {
    231                 comp_lossless = true;
    232             }
    233         }
    234     }
    235 
    236     uint8_t *out = NULL;
    237 
    238     if(depth != CV_8U)
    239     {
    240         return false;
    241     }
    242 
    243     if(channels == 1)
    244     {
    245         cvtColor(*image, temp, CV_GRAY2BGR);
    246         image = &temp;
    247         channels = 3;
    248     }
    249     else if (channels == 2)
    250     {
    251         return false;
    252     }
    253 
    254     if (comp_lossless)
    255     {
    256         if(channels == 3)
    257         {
    258             size = WebPEncodeLosslessBGR(image->ptr(), width, height, (int)image->step, &out);
    259         }
    260         else if(channels == 4)
    261         {
    262             size = WebPEncodeLosslessBGRA(image->ptr(), width, height, (int)image->step, &out);
    263         }
    264     }
    265     else
    266     {
    267         if(channels == 3)
    268         {
    269             size = WebPEncodeBGR(image->ptr(), width, height, (int)image->step, quality, &out);
    270         }
    271         else if(channels == 4)
    272         {
    273             size = WebPEncodeBGRA(image->ptr(), width, height, (int)image->step, quality, &out);
    274         }
    275     }
    276 
    277     if(size > 0)
    278     {
    279         if(m_buf)
    280         {
    281             m_buf->resize(size);
    282             memcpy(&(*m_buf)[0], out, size);
    283         }
    284         else
    285         {
    286             FILE *fd = fopen(m_filename.c_str(), "wb");
    287             if(fd != NULL)
    288             {
    289                 fwrite(out, size, sizeof(uint8_t), fd);
    290                 fclose(fd); fd = NULL;
    291             }
    292         }
    293     }
    294 
    295     if (out != NULL)
    296     {
    297         free(out);
    298         out = NULL;
    299     }
    300 
    301     return size > 0;
    302 }
    303 
    304 }
    305 
    306 #endif
    307