美文网首页
为啥微信添加个动态表情这么难?

为啥微信添加个动态表情这么难?

作者: adousj | 来源:发表于2016-09-12 01:23 被阅读35次

    每每看到好玩 gif 想要跟基友分享,结果发过去就成了死图。搜了半天才知道,要添加到微信表情才可以,照着添加了,结果又提示 “所选图片太大”!!!
    What the f**?我只是单纯的想分享一张 gif 动图,咋还生出这么多幺蛾子。

    拿 Graphics-Magic 练练手,程序中会多次尝试缩放直到结果 1M以下。

    #include <cassert>
    #include <cmath>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <fstream>
    #include <algorithm>
    
    #include <boost/format.hpp>
    #include <gflags/gflags.h>
    #include <Magick++.h> 
    
    DEFINE_int32(max_size, 1024, "output file size in Kb");
    DEFINE_string(in, "", "input image filename");
    DEFINE_string(out, "", "output image filename");
    DEFINE_int32(retry, 3, "max retry times");
    //DEFINE_int32(depth, 8, "output image depth");
    //DEFINE_int32(quality, 75, "output image quality");
    
    int read_image_vec(const std::string& filename, std::vector<Magick::Image>& image_vec) {
        assert(image_vec.empty());
        try {
            Magick::readImages(&image_vec, filename);
        } catch (Magick::Warning &warning) {
            std::cerr << warning.what() << std::endl;
        } catch (Magick::Error &error) {
            std::cerr << error.what() << std::endl;
        }
    
        return !image_vec.empty() && image_vec.front().isValid() ? 0 : 1;
    }
    
    Magick::Geometry image_vec_page(const std::vector<Magick::Image>& image_vec) {
        assert(!image_vec.empty());
        Magick::Geometry max_page(0, 0);
        for (const auto& image : image_vec) {
            auto page = image.page();
            if (page.width() > max_page.width()) {
                max_page.width(page.width());
            }
            if (page.height() > max_page.height()) {
                max_page.height(page.height());
            }
        }
        return max_page;
    }
    
    Magick::Geometry image_vec_size(const std::vector<Magick::Image>& image_vec) {
        assert(!image_vec.empty());
        Magick::Geometry max_size(0, 0);
        for (const auto& image : image_vec) {
            auto size = image.size();
            if (size.width() > max_size.width()) {
                max_size.width(size.width());
            }
            if (size.height() > max_size.height()) {
                max_size.height(size.height());
            }
        }
        return max_size;
    }
    
    double guess_resize_ratio(const off_t src_file_size,
                              const off_t max_file_size) {
        static double FILE_SIZE_RATIO = 1.0;
        FILE_SIZE_RATIO = std::max(0.5, FILE_SIZE_RATIO - 0.1);
        return sqrt(max_file_size * FILE_SIZE_RATIO / src_file_size);
    }
    
    void image_vec_resize(std::vector<Magick::Image>& image_vec, const double ratio) {
        assert(!image_vec.empty());
        assert(ratio > 0);
    
        for (auto& image : image_vec) {
            auto page = image.page();
    
            auto size = image.size();
            size.width(size.width() * ratio);
            size.height(size.height() * ratio);
            image.thumbnail(size);
    
            page.width(page.width() * ratio);
            page.height(page.height() * ratio);
            page.xOff(page.xOff() * ratio);
            page.yOff(page.yOff() * ratio);
            image.page(page);
        }
    }
    
    size_t image_vec_encode(std::vector<Magick::Image>& image_vec, Magick::Blob& blob) {
        assert(!image_vec.empty());
    
        /*
        for (auto& image : image_vec) {
            if (image.depth() > FLAGS_depth) {
                image.depth(FLAGS_depth);
            }
    
            if (image.quality() > FLAGS_quality) {
                image.quality(FLAGS_quality);
            }
    
            //image.type(Magick::OptimizeType);
        }
        */
    
        writeImages(image_vec.begin(), image_vec.end(), &blob);
        return blob.length();
    }
    
    int main(int argc, char** argv) {
        google::SetVersionString("1.0.0.0");
        google::ParseCommandLineFlags(&argc, &argv, true);
    
        Magick::InitializeMagick("./");
    
        std::vector<Magick::Image> image_vec;
        if (0 != read_image_vec(FLAGS_in, image_vec)) {
            std::cerr << "read input error" << std::endl;
            return -1;
        }
    
        std::cout << boost::format("frame: %1%") % image_vec.size() << std::endl;
    
        auto src_page = image_vec_page(image_vec);
        if (!src_page.isValid()) {
            std::cerr << boost::format("invalid page: %1%x%2%") % src_page.width() % src_page.height()
                      << std::endl;
            return -1;
        }
        std::cout << boost::format("page: %1%x%2%") % src_page.width() % src_page.height()
                  << std::endl;
    
        auto src_file_size = image_vec.front().fileSize();
        std::cout << boost::format("fileSize: %1%") % src_file_size << std::endl;
    
        off_t max_file_size = FLAGS_max_size * 1024;
        if (src_file_size <= max_file_size) {
            std::cout << "max_size no more than source file size, no need to resize" << std::endl;
            return 0;
        }
    
        // strip
        for_each(image_vec.begin(), image_vec.end(), Magick::stripImage());
    
        for (auto i = 0; i < FLAGS_retry; ++i) {
            std::cout << boost::format("try the %1% time") % (i + 1) << std::endl;
            std::cout << boost::format("    src page: %1%x%2%  fileSize: %3%")
                                       % src_page.width() % src_page.height()
                                       % src_file_size
                      << std::endl;
            auto ratio = guess_resize_ratio(src_file_size, max_file_size);
            image_vec_resize(image_vec, ratio);
            Magick::Blob blob;
            auto dst_file_size = image_vec_encode(image_vec, blob);
            auto dst_page = image_vec_page(image_vec);
            std::cout << boost::format("    dst page: %1%x%2%  fileSize: %3%")
                                       % dst_page.width() % dst_page.height()
                                       % dst_file_size
                      << std::endl;
            if (dst_file_size <= max_file_size) {
                std::ofstream ofs(FLAGS_out, std::ostream::out);
                ofs.write(static_cast<const char*>(blob.data()), blob.length());
                return 0;
            } else {
                src_file_size = dst_file_size;
                src_page = dst_page;
            }
        }
    
        std::cerr << "convert faild" << std::endl;
        return -1;
    }
    

    相关文章

      网友评论

          本文标题:为啥微信添加个动态表情这么难?

          本文链接:https://www.haomeiwen.com/subject/yucpettx.html