static bool encodePixels(IntSize imageSize, const unsigned char* pixels, bool premultiplied, int quality, Vector<unsigned char>* output) { if (imageSize.width() <= 0 || imageSize.width() > WEBP_MAX_DIMENSION) return false; if (imageSize.height() <= 0 || imageSize.height() > WEBP_MAX_DIMENSION) return false; WebPConfig config; if (!WebPConfigInit(&config)) return false; WebPPicture picture; if (!WebPPictureInit(&picture)) return false; picture.width = imageSize.width(); picture.height = imageSize.height(); if (premultiplied && !platformPremultipliedImportPicture(pixels, &picture)) return false; if (!premultiplied && !importPictureRGBX<false>(pixels, &picture)) return false; picture.custom_ptr = output; picture.writer = &writeOutput; config.quality = quality; config.method = 3; bool success = WebPEncode(&config, &picture); WebPPictureFree(&picture); return success; }
bool WebpOutput::open (const std::string &name, const ImageSpec &spec, OpenMode mode) { if (mode != Create) { error ("%s does not support subimages or MIP levels", format_name()); return false; } // saving 'name' and 'spec' for later use m_filename = name; stash_spec(spec); m_file = fopen (m_filename.c_str (), "wb"); if (!m_file) { error ("Unable to open file \"%s\"", m_filename.c_str ()); return false; } if (!WebPPictureInit(&m_webp_picture)) { error("Couldn't initialize WebPPicture\n"); close(); return false; } m_webp_picture.width = m_spec.width; m_webp_picture.height = m_spec.height; m_webp_picture.writer = WebpImageWriter; m_webp_picture.custom_ptr = (void*)m_file; if (!WebPConfigInit(&m_webp_config)) { error("Couldn't initialize WebPPicture\n"); close(); return false; } m_webp_config.method = 6; int compression_quality = 100; const ImageIOParameter *qual = m_spec.find_attribute ("CompressionQuality", TypeDesc::INT); if (qual) { compression_quality = *static_cast<const int*>(qual->data()); } m_webp_config.quality = compression_quality; // forcing UINT8 format m_spec.set_format (TypeDesc::UINT8); m_scanline_size = m_spec.width * m_spec.nchannels; const int image_buffer = m_spec.height * m_scanline_size; m_uncompressed_image.resize(image_buffer, 0); return true; }
static gboolean export_webp (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result, GOutputStream *stream) { GeglProperties *o = GEGL_PROPERTIES (operation); WebPConfig config; WebPPicture picture; const Babl *format; gint status; g_return_val_if_fail (stream != NULL, FALSE); if (!WebPConfigInit (&config) || !WebPPictureInit (&picture)) { g_warning ("could not initialize WebP encoder"); return FALSE; } if (!WebPConfigPreset (&config, WEBP_PRESET_DEFAULT, o->quality)) { g_warning("could not load WebP default preset"); return FALSE; } picture.width = result->width; picture.height = result->height; format = babl_format ("R'G'B'A u8"); if (!WebPValidateConfig (&config)) { g_warning ("WebP encoder configuration is invalid"); return FALSE; } picture.writer = write_to_stream; picture.custom_ptr = stream; if (save_RGBA (&picture, input, result, format)) { g_warning ("could not pass pixels data to WebP encoder"); return FALSE; } status = WebPEncode (&config, &picture); WebPPictureFree (&picture); return status ? TRUE : FALSE; }
static int EncodeLossless(const uint8_t* const data, int width, int height, int effort_level, // in [0..6] range VP8BitWriter* const bw, WebPAuxStats* const stats) { int ok = 0; WebPConfig config; WebPPicture picture; VP8LBitWriter tmp_bw; WebPPictureInit(&picture); picture.width = width; picture.height = height; picture.use_argb = 1; picture.stats = stats; if (!WebPPictureAlloc(&picture)) return 0; // Transfer the alpha values to the green channel. { int i, j; uint32_t* dst = picture.argb; const uint8_t* src = data; for (j = 0; j < picture.height; ++j) { for (i = 0; i < picture.width; ++i) { dst[i] = (src[i] << 8) | 0xff000000u; } src += width; dst += picture.argb_stride; } } WebPConfigInit(&config); config.lossless = 1; config.method = effort_level; // impact is very small // Set moderate default quality setting for alpha. Higher qualities (80 and // above) could be very slow. config.quality = 10.f + 15.f * effort_level; if (config.quality > 100.f) config.quality = 100.f; ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3); ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK); WebPPictureFree(&picture); if (ok) { const uint8_t* const data = VP8LBitWriterFinish(&tmp_bw); const size_t data_size = VP8LBitWriterNumBytes(&tmp_bw); VP8BitWriterAppend(bw, data, data_size); } VP8LBitWriterDestroy(&tmp_bw); return ok && !bw->error_; }
static int EncodeLossless(const uint8_t* const data, int width, int height, int effort_level, // in [0..6] range VP8LBitWriter* const bw, WebPAuxStats* const stats) { int ok = 0; WebPConfig config; WebPPicture picture; WebPPictureInit(&picture); picture.width = width; picture.height = height; picture.use_argb = 1; picture.stats = stats; if (!WebPPictureAlloc(&picture)) return 0; // Transfer the alpha values to the green channel. { int i, j; uint32_t* dst = picture.argb; const uint8_t* src = data; for (j = 0; j < picture.height; ++j) { for (i = 0; i < picture.width; ++i) { dst[i] = src[i] << 8; // we leave A/R/B channels zero'd. } src += width; dst += picture.argb_stride; } } WebPConfigInit(&config); config.lossless = 1; config.method = effort_level; // impact is very small // Set a low default quality for encoding alpha. Ensure that Alpha quality at // lower methods (3 and below) is less than the threshold for triggering // costly 'BackwardReferencesTraceBackwards'. config.quality = 8.f * effort_level; assert(config.quality >= 0 && config.quality <= 100.f); ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK); WebPPictureFree(&picture); ok = ok && !bw->error_; if (!ok) { VP8LBitWriterDestroy(bw); return 0; } return 1; }
static int EncodeLossless(const uint8_t* const data, int width, int height, int effort_level, // in [0..6] range VP8LBitWriter* const bw, WebPAuxStats* const stats) { int ok = 0; WebPConfig config; WebPPicture picture; WebPPictureInit(&picture); picture.width = width; picture.height = height; picture.use_argb = 1; picture.stats = stats; if (!WebPPictureAlloc(&picture)) return 0; // Transfer the alpha values to the green channel. WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, picture.argb, picture.argb_stride); WebPConfigInit(&config); config.lossless = 1; // Enable exact, or it would alter RGB values of transparent alpha, which is // normally OK but not here since we are not encoding the input image but an // internal encoding-related image containing necessary exact information in // RGB channels. config.exact = 1; config.method = effort_level; // impact is very small // Set a low default quality for encoding alpha. Ensure that Alpha quality at // lower methods (3 and below) is less than the threshold for triggering // costly 'BackwardReferencesTraceBackwards'. config.quality = 8.f * effort_level; assert(config.quality >= 0 && config.quality <= 100.f); // TODO(urvang): Temporary fix to avoid generating images that trigger // a decoder bug related to alpha with color cache. // See: https://code.google.com/p/webp/issues/detail?id=239 // Need to re-enable this later. ok = (VP8LEncodeStream(&config, &picture, bw, 0 /*use_cache*/) == VP8_ENC_OK); WebPPictureFree(&picture); ok = ok && !bw->error_; if (!ok) { VP8LBitWriterWipeOut(bw); return 0; } return 1; }
void process_rgba8_webp(T const& image, std::string const& t, std::ostream & stream) { #if defined(HAVE_WEBP) WebPConfig config; // Default values set here will be lossless=0 and quality=75 (as least as of webp v0.3.1) if (!WebPConfigInit(&config)) { throw std::runtime_error("version mismatch"); } // see for more details: https://github.com/mapnik/mapnik/wiki/Image-IO#webp-output-options bool alpha = true; handle_webp_options(t,config,alpha); save_as_webp(stream,image,config,alpha); #else throw image_writer_exception("webp output is not enabled in your build of Mapnik"); #endif }
int main(int argc, const char *argv[]) { int verbose = 0; int gif_error = GIF_ERROR; WebPMuxError err = WEBP_MUX_OK; int ok = 0; const char *in_file = NULL, *out_file = NULL; FILE* out = NULL; GifFileType* gif = NULL; WebPPicture picture; WebPPicture view; WebPMemoryWriter memory; WebPMuxFrameInfo frame; WebPMuxAnimParams anim = { WHITE_COLOR, 0 }; int is_first_frame = 1; int done; int c; int quiet = 0; WebPConfig config; WebPMux* mux = NULL; WebPData webp_data = { NULL, 0 }; int stored_icc = 0; // Whether we have already stored an ICC profile. int stored_xmp = 0; memset(&frame, 0, sizeof(frame)); frame.id = WEBP_CHUNK_ANMF; frame.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND; if (!WebPConfigInit(&config) || !WebPPictureInit(&picture)) { fprintf(stderr, "Error! Version mismatch!\n"); return -1; } config.lossless = 1; // Use lossless compression by default. if (argc == 1) { Help(); return 0; } for (c = 1; c < argc; ++c) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { Help(); return 0; } else if (!strcmp(argv[c], "-o") && c < argc - 1) { out_file = argv[++c]; } else if (!strcmp(argv[c], "-lossy")) { config.lossless = 0; } else if (!strcmp(argv[c], "-q") && c < argc - 1) { config.quality = (float)strtod(argv[++c], NULL); } else if (!strcmp(argv[c], "-m") && c < argc - 1) { config.method = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-f") && c < argc - 1) { config.filter_strength = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-version")) { const int enc_version = WebPGetEncoderVersion(); const int mux_version = WebPGetMuxVersion(); printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n", (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, enc_version & 0xff, (mux_version >> 16) & 0xff, (mux_version >> 8) & 0xff, mux_version & 0xff); return 0; } else if (!strcmp(argv[c], "-quiet")) { quiet = 1; } else if (!strcmp(argv[c], "-v")) { verbose = 1; } else if (argv[c][0] == '-') { fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); Help(); return -1; } else { in_file = argv[c]; } }
/** Encode a FIBITMAP to a WebP image @param hmem Memory output stream, containing on return the encoded image @param dib The FIBITMAP to encode @param flags FreeImage save flags @return Returns TRUE if successfull, returns FALSE otherwise */ static BOOL EncodeImage(FIMEMORY *hmem, FIBITMAP *dib, int flags) { WebPPicture picture; // Input buffer WebPConfig config; // Coding parameters BOOL bIsFlipped = FALSE; try { const unsigned width = FreeImage_GetWidth(dib); const unsigned height = FreeImage_GetHeight(dib); const unsigned bpp = FreeImage_GetBPP(dib); const unsigned pitch = FreeImage_GetPitch(dib); // check image type FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); if( !((image_type == FIT_BITMAP) && ((bpp == 24) || (bpp == 32))) ) { throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } // check format limits if(MAX(width, height) > WEBP_MAX_DIMENSION) { FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height); return FALSE; } // Initialize output I/O if(WebPPictureInit(&picture) == 1) { picture.writer = WebP_MemoryWriter; picture.custom_ptr = hmem; picture.width = (int)width; picture.height = (int)height; } else { throw "Couldn't initialize WebPPicture"; } // --- Set encoding parameters --- // Initialize encoding parameters to default values WebPConfigInit(&config); // quality/speed trade-off (0=fast, 6=slower-better) config.method = 6; if((flags & WEBP_LOSSLESS) == WEBP_LOSSLESS) { // lossless encoding config.lossless = 1; picture.use_argb = 1; } else if((flags & 0x7F) > 0) { // lossy encoding config.lossless = 0; // quality is between 1 (smallest file) and 100 (biggest) - default to 75 config.quality = (float)(flags & 0x7F); if(config.quality > 100) { config.quality = 100; } } // validate encoding parameters if(WebPValidateConfig(&config) == 0) { throw "Failed to initialize encoder"; } // --- Perform encoding --- // Invert dib scanlines bIsFlipped = FreeImage_FlipVertical(dib); // convert dib buffer to output stream const BYTE *bits = FreeImage_GetBits(dib); #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR switch(bpp) { case 24: WebPPictureImportBGR(&picture, bits, pitch); break; case 32: WebPPictureImportBGRA(&picture, bits, pitch); break; } #else switch(bpp) { case 24: WebPPictureImportRGB(&picture, bits, pitch); break; case 32: WebPPictureImportRGBA(&picture, bits, pitch); break; } #endif // FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR if(!WebPEncode(&config, &picture)) { throw "Failed to encode image"; } WebPPictureFree(&picture); if(bIsFlipped) { // invert dib scanlines FreeImage_FlipVertical(dib); } return TRUE; } catch (const char* text) { WebPPictureFree(&picture); if(bIsFlipped) { // invert dib scanlines FreeImage_FlipVertical(dib); } if(NULL != text) { FreeImage_OutputMessageProc(s_format_id, text); } } return FALSE; }
int webp_encode(const char *in_file, const char *out_file, const FfiWebpEncodeConfig *encode_config) { int return_value = -1; FILE *out = NULL; int keep_alpha = 1; WebPPicture picture; WebPConfig config; // OPTIONS BEGIN if (encode_config->lossless == 0 || encode_config->lossless == 1){ config.lossless = encode_config->lossless; } if (encode_config->quality >= 0 && encode_config->quality <= 100){ config.quality = encode_config->quality; } if (encode_config->method >= 0 && encode_config->method <= 6){ config.method = encode_config->method; } if (encode_config->target_size > 0){ config.target_size = encode_config->target_size; } if (encode_config->target_PSNR > 0){ config.target_PSNR = encode_config->target_PSNR; } if (encode_config->segments >= 0 && encode_config->segments <= 4){ config.segments = encode_config->segments; } if (encode_config->sns_strength >= 0 && encode_config->sns_strength <= 100){ config.sns_strength = encode_config->sns_strength; } if (encode_config->filter_strength >= 0 && encode_config->filter_strength <= 100){ config.filter_strength = encode_config->filter_strength; } if (encode_config->filter_sharpness >= 0 && encode_config->filter_sharpness <= 7){ config.filter_sharpness = encode_config->filter_sharpness; } if (encode_config->filter_type == 0 || encode_config->filter_type == 1){ config.filter_type = encode_config->filter_type; } if (encode_config->autofilter == 0 || encode_config->autofilter == 1){ config.autofilter = encode_config->autofilter; } if (encode_config->alpha_compression == 0 || encode_config->alpha_compression == 1){ config.alpha_compression = encode_config->alpha_compression; } if (encode_config->alpha_filtering >= 0 && encode_config->alpha_filtering <= 2){ config.alpha_filtering = encode_config->alpha_filtering; } if (encode_config->alpha_quality >= 0 && encode_config->alpha_quality <= 100){ config.alpha_quality = encode_config->alpha_quality; } if (encode_config->pass >= 0 && encode_config->pass <= 10){ config.pass = encode_config->pass; } if (encode_config->show_compressed >= 0){ config.show_compressed = encode_config->show_compressed; } if (encode_config->preprocessing == 0 || encode_config->preprocessing == 1){ config.preprocessing = encode_config->preprocessing; } if (encode_config->partitions >= 0 && encode_config->partitions <= 3){ config.partitions = encode_config->partitions; } if (encode_config->partition_limit >= 0 && encode_config->partition_limit <= 100){ config.partition_limit = encode_config->partition_limit; } if ((encode_config->width | encode_config->height) > 0){ picture.width = encode_config->width; picture.height = encode_config->height; } // OPTIONS END if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) { //fprintf(stderr, "Error! Version mismatch!\n"); return 1; } if (!WebPValidateConfig(&config)) { //fprintf(stderr, "Error! Invalid configuration.\n"); return_value = 2; goto Error; } if (!UtilReadPicture(in_file, &picture, keep_alpha)) { //fprintf(stderr, "Error! Cannot read input picture file '%s'\n", in_file); return_value = 3; goto Error; } out = fopen(out_file, "wb"); if (out == NULL) { //fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file); return_value = 4; goto Error; } picture.writer = EncodeWriter; picture.custom_ptr = (void*)out; if ((encode_config->crop_w | encode_config->crop_h) > 0){ if (!WebPPictureView(&picture, encode_config->crop_x, encode_config->crop_y, encode_config->crop_w, encode_config->crop_h, &picture)) { //fprintf(stderr, "Error! Cannot crop picture\n"); return_value = 5; goto Error; } } if ((encode_config->resize_w | encode_config->resize_h) > 0) { if (!WebPPictureRescale(&picture, encode_config->resize_w, encode_config->resize_h)) { //fprintf(stderr, "Error! Cannot resize picture\n"); return_value = 6; goto Error; } } if (picture.extra_info_type > 0) { AllocExtraInfo(&picture); } if (!WebPEncode(&config, &picture)) { //fprintf(stderr, "Error! Cannot encode picture as WebP\n"); return_value = 7; goto Error; } return_value = 0; Error: free(picture.extra_info); WebPPictureFree(&picture); if (out != NULL) { fclose(out); } return return_value; }
PyObject* _anim_encoder_add(PyObject* self, PyObject* args) { uint8_t* rgb; Py_ssize_t size; int timestamp; int width; int height; char* mode; int lossless; float quality_factor; int method; WebPConfig config; WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self; WebPAnimEncoder* enc = encp->enc; WebPPicture* frame = &(encp->frame); if (!PyArg_ParseTuple(args, "z#iiisifi", (char**)&rgb, &size, ×tamp, &width, &height, &mode, &lossless, &quality_factor, &method)) { return NULL; } // Check for NULL frame, which sets duration of final frame if (!rgb) { WebPAnimEncoderAdd(enc, NULL, timestamp, NULL); Py_RETURN_NONE; } // Setup config for this frame if (!WebPConfigInit(&config)) { PyErr_SetString(PyExc_RuntimeError, "failed to initialize config!"); return NULL; } config.lossless = lossless; config.quality = quality_factor; config.method = method; // Validate the config if (!WebPValidateConfig(&config)) { PyErr_SetString(PyExc_ValueError, "invalid configuration"); return NULL; } // Populate the frame with raw bytes passed to us frame->width = width; frame->height = height; frame->use_argb = 1; // Don't convert RGB pixels to YUV if (strcmp(mode, "RGBA")==0) { WebPPictureImportRGBA(frame, rgb, 4 * width); } else if (strcmp(mode, "RGBX")==0) { WebPPictureImportRGBX(frame, rgb, 4 * width); } // Add the frame to the encoder if (!WebPAnimEncoderAdd(enc, frame, timestamp, &config)) { PyErr_SetString(PyExc_RuntimeError, WebPAnimEncoderGetError(enc)); return NULL; } Py_RETURN_NONE; }
bool QWebpHandler::write(const QImage &image) { if (image.isNull()) { qWarning() << "source image is null."; return false; } QImage srcImage = image; #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN if (srcImage.format() != QImage::Format_ARGB32) srcImage = srcImage.convertToFormat(QImage::Format_ARGB32); #else /* Q_BIG_ENDIAN */ if (srcImage.format() != QImage::Format_RGBA8888) srcImage = srcImage.convertToFormat(QImage::Format_RGBA8888); #endif WebPPicture picture; WebPConfig config; if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) { qWarning() << "failed to init webp picture and config"; return false; } picture.width = srcImage.width(); picture.height = srcImage.height(); picture.use_argb = 1; #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN if (!WebPPictureImportBGRA(&picture, srcImage.bits(), srcImage.bytesPerLine())) { #else /* Q_BIG_ENDIAN */ if (!WebPPictureImportRGBA(&picture, srcImage.bits(), srcImage.bytesPerLine())) { #endif qWarning() << "failed to import image data to webp picture."; WebPPictureFree(&picture); return false; } config.lossless = m_lossless; config.quality = m_quality; picture.writer = pictureWriter; picture.custom_ptr = device(); if (!WebPEncode(&config, &picture)) { qWarning() << "failed to encode webp picture, error code: " << picture.error_code; WebPPictureFree(&picture); return false; } WebPPictureFree(&picture); return true; } QVariant QWebpHandler::option(ImageOption option) const { if (!supportsOption(option) || !ensureScanned()) return QVariant(); switch (option) { case Quality: return m_quality; case Size: return QSize(m_width, m_height); case Animation: return (m_flags & ANIMATION_FLAG) == ANIMATION_FLAG; default: return QVariant(); } } void QWebpHandler::setOption(ImageOption option, const QVariant &value) { switch (option) { case Quality: m_quality = qBound(0, value.toInt(), 100); m_lossless = (m_quality >= 100); return; default: break; } return QImageIOHandler::setOption(option, value); } bool QWebpHandler::supportsOption(ImageOption option) const { return option == Quality || option == Size || option == Animation; } QByteArray QWebpHandler::name() const { return QByteArrayLiteral("webp"); } int QWebpHandler::imageCount() const { if (!ensureScanned()) return 0; if ((m_flags & ANIMATION_FLAG) == 0) return 1; return m_frameCount; } int QWebpHandler::currentImageNumber() const { if (!ensureScanned()) return 0; return m_iter.frame_num; } QRect QWebpHandler::currentImageRect() const { if (!ensureScanned()) return QRect(); return QRect(m_iter.x_offset, m_iter.y_offset, m_iter.width, m_iter.height); } bool QWebpHandler::jumpToImage(int imageNumber) { if (!ensureScanned()) return false; WebPDemuxReleaseIterator(&m_iter); return WebPDemuxGetFrame(m_demuxer, imageNumber, &m_iter); } bool QWebpHandler::jumpToNextImage() { if (!ensureScanned()) return false; return WebPDemuxNextFrame(&m_iter); } int QWebpHandler::loopCount() const { if (!ensureScanned() || (m_flags & ANIMATION_FLAG) == 0) return 0; return m_loop; } int QWebpHandler::nextImageDelay() const { if (!ensureScanned()) return 0; return m_iter.duration; }
static gboolean real_save_webp (GdkPixbuf *pixbuf, gchar **keys, gchar **values, GError **error, gboolean to_callback, FILE *f, save_context *context) { WebPPicture picture; WebPConfig config; gint w, h, rowstride, has_alpha, rc; guchar *pixels; if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) { g_set_error(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "WebP encoder version mismatch."); return FALSE; } if (keys && *keys) { gchar **kiter = keys; gchar **viter = values; while (*kiter) { if (strncmp (*kiter, "quality", 7) == 0) { float quality = (float) g_ascii_strtod (*viter, NULL); if (quality < 0 || quality > 100) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "WebP quality must be a value between 0 and 100."); return FALSE; } config.quality = quality; } else if (strncmp (*kiter, "preset", 6) == 0) { WebPPreset preset; if (strncmp (*viter, "default", 7) == 0) { preset = WEBP_PRESET_DEFAULT; } else if (strncmp (*viter, "photo", 5) == 0) { preset = WEBP_PRESET_PHOTO; } else if (strncmp (*viter, "picture", 7) == 0) { preset = WEBP_PRESET_PICTURE; } else if (strncmp (*viter, "drawing", 7) == 0) { preset = WEBP_PRESET_DRAWING; } else if (strncmp (*viter, "icon", 4) == 0) { preset = WEBP_PRESET_ICON; } else if (strncmp (*viter, "text", 4) == 0) { preset = WEBP_PRESET_TEXT; } else { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "WebP encoder invalid preset."); return FALSE; } if (WebPConfigPreset (&config, preset, config.quality) == 0) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "Could not initialize decoder with preset."); return FALSE; } } ++kiter; ++viter; } } if (WebPValidateConfig (&config) != 1) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_BAD_OPTION, "Invalid encoding configuration"); return FALSE; } w = gdk_pixbuf_get_width (pixbuf); h = gdk_pixbuf_get_height (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); picture.width = w; picture.height = h; if (has_alpha) { rc = WebPPictureImportRGBA (&picture, pixels, rowstride); } else { rc = WebPPictureImportRGB (&picture, pixels, rowstride); } if (rc == 0) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, "Failed to allocate picture"); return FALSE; } if (to_callback) { picture.writer = save_callback; picture.custom_ptr = (void*) context; } else { picture.writer = write_file; picture.custom_ptr = (void*) f; } if (WebPEncode(&config, &picture) == 0) { fprintf(stderr, "Error! Cannot encode picture as WebP\n"); } return TRUE; }
status_t WebPTranslator::_TranslateFromBits(BPositionIO* stream, BMessage* ioExtension, uint32 outType, BPositionIO* target) { if (!outType) outType = WEBP_IMAGE_FORMAT; if (outType != WEBP_IMAGE_FORMAT) return B_NO_TRANSLATOR; TranslatorBitmap bitsHeader; status_t status; status = identify_bits_header(stream, NULL, &bitsHeader); if (status != B_OK) return status; if (bitsHeader.colors == B_CMAP8) { // TODO: support whatever colospace by intermediate colorspace conversion printf("Error! Colorspace not supported\n"); return B_NO_TRANSLATOR; } int32 bitsBytesPerPixel = 0; switch (bitsHeader.colors) { case B_RGB32: case B_RGB32_BIG: case B_RGBA32: case B_RGBA32_BIG: case B_CMY32: case B_CMYA32: case B_CMYK32: bitsBytesPerPixel = 4; break; case B_RGB24: case B_RGB24_BIG: case B_CMY24: bitsBytesPerPixel = 3; break; case B_RGB16: case B_RGB16_BIG: case B_RGBA15: case B_RGBA15_BIG: case B_RGB15: case B_RGB15_BIG: bitsBytesPerPixel = 2; break; case B_CMAP8: case B_GRAY8: bitsBytesPerPixel = 1; break; default: return B_ERROR; } if (bitsBytesPerPixel < 3) { // TODO support return B_NO_TRANSLATOR; } WebPPicture picture; WebPConfig config; if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) { printf("Error! Version mismatch!\n"); return B_ERROR; } WebPPreset preset = (WebPPreset)fSettings->SetGetInt32(WEBP_SETTING_PRESET); config.quality = (float)fSettings->SetGetInt32(WEBP_SETTING_QUALITY); if (!WebPConfigPreset(&config, (WebPPreset)preset, config.quality)) { printf("Error! Could initialize configuration with preset."); return B_ERROR; } config.method = fSettings->SetGetInt32(WEBP_SETTING_METHOD); config.preprocessing = fSettings->SetGetBool(WEBP_SETTING_PREPROCESSING); if (!WebPValidateConfig(&config)) { printf("Error! Invalid configuration.\n"); return B_ERROR; } picture.width = bitsHeader.bounds.IntegerWidth() + 1; picture.height = bitsHeader.bounds.IntegerHeight() + 1; int stride = bitsHeader.rowBytes; int bitsSize = picture.height * stride; uint8* bits = (uint8*)malloc(bitsSize); if (bits == NULL) return B_NO_MEMORY; if (stream->Read(bits, bitsSize) != bitsSize) { free(bits); return B_IO_ERROR; } if (!WebPPictureImportBGRA(&picture, bits, stride)) { printf("Error! WebPEncode() failed!\n"); free(bits); return B_ERROR; } free(bits); picture.writer = _EncodedWriter; picture.custom_ptr = target; picture.stats = NULL; if (!WebPEncode(&config, &picture)) { printf("Error! WebPEncode() failed!\n"); status = B_NO_TRANSLATOR; } else status = B_OK; WebPPictureFree(&picture); return status; }
static gboolean _cairo_surface_write_as_webp (cairo_surface_t *image, char **buffer, gsize *buffer_size, char **keys, char **values, GError **error) { gboolean lossless; int quality; int method; WebPConfig config; CairoWebpData *cairo_webp_data; WebPPicture pic; lossless = TRUE; quality = 75; method = 4; if (keys && *keys) { char **kiter = keys; char **viter = values; while (*kiter) { if (strcmp (*kiter, "lossless") == 0) { if (*viter == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Must specify a value for the 'lossless' option"); return FALSE; } lossless = atoi (*viter); if (lossless < 0 || lossless > 1) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Invalid value set for the 'lossless' option of the WebP saver"); return FALSE; } } else if (strcmp (*kiter, "quality") == 0) { if (*viter == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Must specify a quality value to the WebP saver"); return FALSE; } quality = atoi (*viter); if (quality < 0 || quality > 100) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unsupported quality value passed to the WebP saver"); return FALSE; } } else if (strcmp (*kiter, "method") == 0) { if (*viter == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Must specify a method value to the WebP saver"); return FALSE; } method = atoi (*viter); if (method < 0 || method > 6) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unsupported method value passed to the WebP saver"); return FALSE; } } else { g_warning ("Bad option name '%s' passed to the WebP saver", *kiter); return FALSE; } ++kiter; ++viter; } } if (! WebPConfigInit (&config)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Version error"); return FALSE; } config.lossless = lossless; config.quality = quality; config.method = method; if (! WebPValidateConfig (&config)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Config error"); return FALSE; } cairo_webp_data = g_new0 (CairoWebpData, 1); cairo_webp_data->error = error; cairo_webp_data->buffer_data = gth_buffer_data_new (); cairo_webp_data->success = FALSE; WebPPictureInit (&pic); pic.width = cairo_image_surface_get_width (image); pic.height = cairo_image_surface_get_height (image); pic.writer = cairo_webp_writer_func; pic.custom_ptr = cairo_webp_data; pic.use_argb = TRUE; if (_WebPPictureImportCairoSurface (&pic, image)) { int ok = WebPEncode (&config, &pic); WebPPictureFree (&pic); if (cairo_webp_data->success && ! ok) { g_set_error (cairo_webp_data->error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Encoding error: %d", pic.error_code); cairo_webp_data->success = FALSE; } } else { g_set_error (cairo_webp_data->error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Memory error"); cairo_webp_data->success = FALSE; } if (cairo_webp_data->success) gth_buffer_data_get (cairo_webp_data->buffer_data, buffer, buffer_size); _cairo_webp_data_destroy (cairo_webp_data); return TRUE; }
int main(int argc, const char *argv[]) { int verbose = 0; int gif_error = GIF_ERROR; WebPMuxError err = WEBP_MUX_OK; int ok = 0; const char *in_file = NULL, *out_file = NULL; FILE* out = NULL; GifFileType* gif = NULL; int frame_duration = 0; int frame_timestamp = 0; GIFDisposeMethod orig_dispose = GIF_DISPOSE_NONE; WebPPicture frame; // Frame rectangle only (not disposed). WebPPicture curr_canvas; // Not disposed. WebPPicture prev_canvas; // Disposed. WebPPicture prev_to_prev_canvas; // Disposed. WebPAnimEncoder* enc = NULL; WebPAnimEncoderOptions enc_options; WebPConfig config; int is_first_frame = 1; // Whether we are processing the first frame. int done; int c; int quiet = 0; WebPData webp_data; int keep_metadata = METADATA_XMP; // ICC not output by default. WebPData icc_data; int stored_icc = 0; // Whether we have already stored an ICC profile. WebPData xmp_data; int stored_xmp = 0; // Whether we have already stored an XMP profile. int loop_count = 0; int stored_loop_count = 0; // Whether we have found an explicit loop count. WebPMux* mux = NULL; int default_kmin = 1; // Whether to use default kmin value. int default_kmax = 1; if (!WebPConfigInit(&config) || !WebPAnimEncoderOptionsInit(&enc_options) || !WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) || !WebPPictureInit(&prev_canvas) || !WebPPictureInit(&prev_to_prev_canvas)) { fprintf(stderr, "Error! Version mismatch!\n"); return -1; } config.lossless = 1; // Use lossless compression by default. WebPDataInit(&webp_data); WebPDataInit(&icc_data); WebPDataInit(&xmp_data); if (argc == 1) { Help(); return 0; } for (c = 1; c < argc; ++c) { int parse_error = 0; if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { Help(); return 0; } else if (!strcmp(argv[c], "-o") && c < argc - 1) { out_file = argv[++c]; } else if (!strcmp(argv[c], "-lossy")) { config.lossless = 0; } else if (!strcmp(argv[c], "-mixed")) { enc_options.allow_mixed = 1; config.lossless = 0; } else if (!strcmp(argv[c], "-q") && c < argc - 1) { config.quality = ExUtilGetFloat(argv[++c], &parse_error); } else if (!strcmp(argv[c], "-m") && c < argc - 1) { config.method = ExUtilGetInt(argv[++c], 0, &parse_error); } else if (!strcmp(argv[c], "-min_size")) { enc_options.minimize_size = 1; } else if (!strcmp(argv[c], "-kmax") && c < argc - 1) { enc_options.kmax = ExUtilGetInt(argv[++c], 0, &parse_error); default_kmax = 0; } else if (!strcmp(argv[c], "-kmin") && c < argc - 1) { enc_options.kmin = ExUtilGetInt(argv[++c], 0, &parse_error); default_kmin = 0; } else if (!strcmp(argv[c], "-f") && c < argc - 1) { config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error); } else if (!strcmp(argv[c], "-metadata") && c < argc - 1) { static const struct { const char* option; int flag; } kTokens[] = { { "all", METADATA_ALL }, { "none", 0 }, { "icc", METADATA_ICC }, { "xmp", METADATA_XMP }, }; const size_t kNumTokens = sizeof(kTokens) / sizeof(*kTokens); const char* start = argv[++c]; const char* const end = start + strlen(start); keep_metadata = 0; while (start < end) { size_t i; const char* token = strchr(start, ','); if (token == NULL) token = end; for (i = 0; i < kNumTokens; ++i) { if ((size_t)(token - start) == strlen(kTokens[i].option) && !strncmp(start, kTokens[i].option, strlen(kTokens[i].option))) { if (kTokens[i].flag != 0) { keep_metadata |= kTokens[i].flag; } else { keep_metadata = 0; } break; } } if (i == kNumTokens) { fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", (int)(token - start), start); Help(); return -1; } start = token + 1; } } else if (!strcmp(argv[c], "-mt")) { ++config.thread_level; } else if (!strcmp(argv[c], "-version")) { const int enc_version = WebPGetEncoderVersion(); const int mux_version = WebPGetMuxVersion(); printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n", (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, enc_version & 0xff, (mux_version >> 16) & 0xff, (mux_version >> 8) & 0xff, mux_version & 0xff); return 0; } else if (!strcmp(argv[c], "-quiet")) { quiet = 1; } else if (!strcmp(argv[c], "-v")) { verbose = 1; enc_options.verbose = 1; } else if (!strcmp(argv[c], "--")) { if (c < argc - 1) in_file = argv[++c]; break; } else if (argv[c][0] == '-') { fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); Help(); return -1; } else { in_file = argv[c]; } if (parse_error) { Help(); return -1; } }
static MagickBooleanType WriteWEBPImage(const ImageInfo *image_info, Image *image) { int webp_status; MagickBooleanType status; register const PixelPacket *__restrict__ p; register ssize_t x; register unsigned char *__restrict__ q; ssize_t y; unsigned char *pixels; WebPConfig configure; WebPPicture picture; WebPAuxStats statistics; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); if (WebPPictureInit(&picture) == 0) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); picture.writer=WebPWriter; picture.custom_ptr=(void *) image; picture.stats=(&statistics); picture.width=(int) image->columns; picture.height=(int) image->rows; if (image->quality != UndefinedCompressionQuality) configure.quality=(float) image->quality; if (WebPConfigInit(&configure) == 0) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); /* Future: set custom configuration parameters here. */ if (WebPValidateConfig(&configure) == 0) ThrowWriterException(ResourceLimitError,"UnableToEncodeImageFile"); /* Allocate memory for pixels. */ pixels=(unsigned char *) AcquireQuantumMemory(image->columns, (image->matte != MagickFalse ? 4 : 3)*image->rows*sizeof(*pixels)); if (pixels == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); /* Convert image to WebP raster pixels. */ q=pixels; for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { *q++=ScaleQuantumToChar(GetRedPixelComponent(p)); *q++=ScaleQuantumToChar(GetGreenPixelComponent(p)); *q++=ScaleQuantumToChar(GetBluePixelComponent(p)); if (image->matte != MagickFalse) *q++=ScaleQuantumToChar((Quantum) (QuantumRange- (image->matte != MagickFalse ? GetOpacityPixelComponent(p) : OpaqueOpacity))); p++; } status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } if (image->matte == MagickFalse) webp_status=WebPPictureImportRGB(&picture,pixels,3*picture.width); else webp_status=WebPPictureImportRGBA(&picture,pixels,4*picture.width); pixels=(unsigned char *) RelinquishMagickMemory(pixels); webp_status=WebPEncode(&configure,&picture); (void) CloseBlob(image); return(webp_status == 0 ? MagickFalse : MagickTrue); }
int main(int argc, const char *argv[]) { const char *in_file = NULL, *out_file = NULL, *dump_file = NULL; FILE *out = NULL; int c; int short_output = 0; int quiet = 0; int keep_alpha = 0; int crop = 0, crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0; int resize_w = 0, resize_h = 0; WebPPicture picture; WebPConfig config; WebPAuxStats stats; Stopwatch stop_watch; #ifdef WEBP_EXPERIMENTAL_FEATURES keep_alpha = 1; #endif if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) { fprintf(stderr, "Error! Version mismatch!\n"); goto Error; } if (argc == 1) { HelpShort(); return 0; } for (c = 1; c < argc; ++c) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { HelpShort(); return 0; } else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) { HelpLong(); return 0; } else if (!strcmp(argv[c], "-o") && c < argc - 1) { out_file = argv[++c]; } else if (!strcmp(argv[c], "-d") && c < argc - 1) { dump_file = argv[++c]; config.show_compressed = 1; } else if (!strcmp(argv[c], "-short")) { short_output++; } else if (!strcmp(argv[c], "-s") && c < argc - 2) { picture.width = strtol(argv[++c], NULL, 0); picture.height = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-m") && c < argc - 1) { config.method = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-q") && c < argc - 1) { config.quality = (float)strtod(argv[++c], NULL); } else if (!strcmp(argv[c], "-size") && c < argc - 1) { config.target_size = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-psnr") && c < argc - 1) { config.target_PSNR = (float)strtod(argv[++c], NULL); } else if (!strcmp(argv[c], "-sns") && c < argc - 1) { config.sns_strength = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-f") && c < argc - 1) { config.filter_strength = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-af")) { config.autofilter = 1; } else if (!strcmp(argv[c], "-strong")) { config.filter_type = 1; } else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) { config.filter_sharpness = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-pass") && c < argc - 1) { config.pass = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-pre") && c < argc - 1) { config.preprocessing = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-segments") && c < argc - 1) { config.segments = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) { config.partition_limit = strtol(argv[++c], NULL, 0); #ifdef WEBP_EXPERIMENTAL_FEATURES } else if (!strcmp(argv[c], "-alpha_comp") && c < argc - 1) { config.alpha_compression = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-noalpha")) { keep_alpha = 0; #endif } else if (!strcmp(argv[c], "-map") && c < argc - 1) { picture.extra_info_type = strtol(argv[++c], NULL, 0); #ifdef WEBP_EXPERIMENTAL_FEATURES } else if (!strcmp(argv[c], "-444")) { picture.colorspace = WEBP_YUV444; } else if (!strcmp(argv[c], "-422")) { picture.colorspace = WEBP_YUV422; } else if (!strcmp(argv[c], "-gray")) { picture.colorspace = WEBP_YUV400; #endif } else if (!strcmp(argv[c], "-crop") && c < argc - 4) { crop = 1; crop_x = strtol(argv[++c], NULL, 0); crop_y = strtol(argv[++c], NULL, 0); crop_w = strtol(argv[++c], NULL, 0); crop_h = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-resize") && c < argc - 2) { resize_w = strtol(argv[++c], NULL, 0); resize_h = strtol(argv[++c], NULL, 0); #ifndef WEBP_DLL } else if (!strcmp(argv[c], "-noasm")) { VP8GetCPUInfo = NULL; #endif } else if (!strcmp(argv[c], "-version")) { const int version = WebPGetEncoderVersion(); printf("%d.%d.%d\n", (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); return 0; } else if (!strcmp(argv[c], "-quiet")) { quiet = 1; } else if (!strcmp(argv[c], "-preset") && c < argc - 1) { WebPPreset preset; ++c; if (!strcmp(argv[c], "default")) { preset = WEBP_PRESET_DEFAULT; } else if (!strcmp(argv[c], "photo")) { preset = WEBP_PRESET_PHOTO; } else if (!strcmp(argv[c], "picture")) { preset = WEBP_PRESET_PICTURE; } else if (!strcmp(argv[c], "drawing")) { preset = WEBP_PRESET_DRAWING; } else if (!strcmp(argv[c], "icon")) { preset = WEBP_PRESET_ICON; } else if (!strcmp(argv[c], "text")) { preset = WEBP_PRESET_TEXT; } else { fprintf(stderr, "Error! Unrecognized preset: %s\n", argv[c]); goto Error; } if (!WebPConfigPreset(&config, preset, config.quality)) { fprintf(stderr, "Error! Could initialize configuration with preset.\n"); goto Error; } } else if (!strcmp(argv[c], "-v")) { verbose = 1; } else if (argv[c][0] == '-') { fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); HelpLong(); return -1; } else { in_file = argv[c]; } }
int main(int argc, const char *argv[]) { int return_value = -1; const char *in_file = NULL, *out_file = NULL, *dump_file = NULL; FILE *out = NULL; int c; int short_output = 0; int quiet = 0; int keep_alpha = 1; int blend_alpha = 0; uint32_t background_color = 0xffffffu; int crop = 0, crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0; int resize_w = 0, resize_h = 0; int lossless_preset = 6; int use_lossless_preset = -1; // -1=unset, 0=don't use, 1=use it int show_progress = 0; int keep_metadata = 0; int metadata_written = 0; WebPPicture picture; int print_distortion = -1; // -1=off, 0=PSNR, 1=SSIM, 2=LSIM WebPPicture original_picture; // when PSNR or SSIM is requested WebPConfig config; WebPAuxStats stats; WebPMemoryWriter memory_writer; Metadata metadata; Stopwatch stop_watch; MetadataInit(&metadata); WebPMemoryWriterInit(&memory_writer); if (!WebPPictureInit(&picture) || !WebPPictureInit(&original_picture) || !WebPConfigInit(&config)) { fprintf(stderr, "Error! Version mismatch!\n"); return -1; } if (argc == 1) { HelpShort(); return 0; } for (c = 1; c < argc; ++c) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { HelpShort(); return 0; } else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) { HelpLong(); return 0; } else if (!strcmp(argv[c], "-o") && c < argc - 1) { out_file = argv[++c]; } else if (!strcmp(argv[c], "-d") && c < argc - 1) { dump_file = argv[++c]; config.show_compressed = 1; } else if (!strcmp(argv[c], "-print_psnr")) { config.show_compressed = 1; print_distortion = 0; } else if (!strcmp(argv[c], "-print_ssim")) { config.show_compressed = 1; print_distortion = 1; } else if (!strcmp(argv[c], "-print_lsim")) { config.show_compressed = 1; print_distortion = 2; } else if (!strcmp(argv[c], "-short")) { ++short_output; } else if (!strcmp(argv[c], "-s") && c < argc - 2) { picture.width = strtol(argv[++c], NULL, 0); picture.height = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-m") && c < argc - 1) { config.method = strtol(argv[++c], NULL, 0); use_lossless_preset = 0; // disable -z option } else if (!strcmp(argv[c], "-q") && c < argc - 1) { config.quality = (float)strtod(argv[++c], NULL); use_lossless_preset = 0; // disable -z option } else if (!strcmp(argv[c], "-z") && c < argc - 1) { lossless_preset = strtol(argv[++c], NULL, 0); if (use_lossless_preset != 0) use_lossless_preset = 1; } else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) { config.alpha_quality = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) { config.alpha_compression = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-alpha_cleanup")) { keep_alpha = keep_alpha ? 2 : 0; } else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 1) { blend_alpha = 1; background_color = strtol(argv[++c], NULL, 16); // <- parses '0x' prefix background_color = background_color & 0x00ffffffu; } else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) { ++c; if (!strcmp(argv[c], "none")) { config.alpha_filtering = 0; } else if (!strcmp(argv[c], "fast")) { config.alpha_filtering = 1; } else if (!strcmp(argv[c], "best")) { config.alpha_filtering = 2; } else { fprintf(stderr, "Error! Unrecognized alpha filter: %s\n", argv[c]); goto Error; } } else if (!strcmp(argv[c], "-noalpha")) { keep_alpha = 0; } else if (!strcmp(argv[c], "-lossless")) { config.lossless = 1; } else if (!strcmp(argv[c], "-hint") && c < argc - 1) { ++c; if (!strcmp(argv[c], "photo")) { config.image_hint = WEBP_HINT_PHOTO; } else if (!strcmp(argv[c], "picture")) { config.image_hint = WEBP_HINT_PICTURE; } else if (!strcmp(argv[c], "graph")) { config.image_hint = WEBP_HINT_GRAPH; } else { fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]); goto Error; } } else if (!strcmp(argv[c], "-size") && c < argc - 1) { config.target_size = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-psnr") && c < argc - 1) { config.target_PSNR = (float)strtod(argv[++c], NULL); } else if (!strcmp(argv[c], "-sns") && c < argc - 1) { config.sns_strength = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-f") && c < argc - 1) { config.filter_strength = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-af")) { config.autofilter = 1; } else if (!strcmp(argv[c], "-jpeg_like")) { config.emulate_jpeg_size = 1; } else if (!strcmp(argv[c], "-mt")) { ++config.thread_level; // increase thread level } else if (!strcmp(argv[c], "-low_memory")) { config.low_memory = 1; } else if (!strcmp(argv[c], "-strong")) { config.filter_type = 1; } else if (!strcmp(argv[c], "-nostrong")) { config.filter_type = 0; } else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) { config.filter_sharpness = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-pass") && c < argc - 1) { config.pass = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-pre") && c < argc - 1) { config.preprocessing = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-segments") && c < argc - 1) { config.segments = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) { config.partition_limit = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-map") && c < argc - 1) { picture.extra_info_type = strtol(argv[++c], NULL, 0); #ifdef WEBP_EXPERIMENTAL_FEATURES } else if (!strcmp(argv[c], "-444")) { picture.colorspace = WEBP_YUV444; } else if (!strcmp(argv[c], "-422")) { picture.colorspace = WEBP_YUV422; } else if (!strcmp(argv[c], "-gray")) { picture.colorspace = WEBP_YUV400; #endif } else if (!strcmp(argv[c], "-crop") && c < argc - 4) { crop = 1; crop_x = strtol(argv[++c], NULL, 0); crop_y = strtol(argv[++c], NULL, 0); crop_w = strtol(argv[++c], NULL, 0); crop_h = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-resize") && c < argc - 2) { resize_w = strtol(argv[++c], NULL, 0); resize_h = strtol(argv[++c], NULL, 0); #ifndef WEBP_DLL } else if (!strcmp(argv[c], "-noasm")) { VP8GetCPUInfo = NULL; #endif } else if (!strcmp(argv[c], "-version")) { const int version = WebPGetEncoderVersion(); printf("%d.%d.%d\n", (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); return 0; } else if (!strcmp(argv[c], "-progress")) { show_progress = 1; } else if (!strcmp(argv[c], "-quiet")) { quiet = 1; } else if (!strcmp(argv[c], "-preset") && c < argc - 1) { WebPPreset preset; ++c; if (!strcmp(argv[c], "default")) { preset = WEBP_PRESET_DEFAULT; } else if (!strcmp(argv[c], "photo")) { preset = WEBP_PRESET_PHOTO; } else if (!strcmp(argv[c], "picture")) { preset = WEBP_PRESET_PICTURE; } else if (!strcmp(argv[c], "drawing")) { preset = WEBP_PRESET_DRAWING; } else if (!strcmp(argv[c], "icon")) { preset = WEBP_PRESET_ICON; } else if (!strcmp(argv[c], "text")) { preset = WEBP_PRESET_TEXT; } else { fprintf(stderr, "Error! Unrecognized preset: %s\n", argv[c]); goto Error; } if (!WebPConfigPreset(&config, preset, config.quality)) { fprintf(stderr, "Error! Could initialize configuration with preset.\n"); goto Error; } } else if (!strcmp(argv[c], "-metadata") && c < argc - 1) { static const struct { const char* option; int flag; } kTokens[] = { { "all", METADATA_ALL }, { "none", 0 }, { "exif", METADATA_EXIF }, { "icc", METADATA_ICC }, { "xmp", METADATA_XMP }, }; const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]); const char* start = argv[++c]; const char* const end = start + strlen(start); while (start < end) { size_t i; const char* token = strchr(start, ','); if (token == NULL) token = end; for (i = 0; i < kNumTokens; ++i) { if ((size_t)(token - start) == strlen(kTokens[i].option) && !strncmp(start, kTokens[i].option, strlen(kTokens[i].option))) { if (kTokens[i].flag != 0) { keep_metadata |= kTokens[i].flag; } else { keep_metadata = 0; } break; } } if (i == kNumTokens) { fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", (int)(token - start), start); HelpLong(); return -1; } start = token + 1; } #ifdef HAVE_WINCODEC_H if (keep_metadata != 0 && keep_metadata != METADATA_ICC) { // TODO(jzern): remove when -metadata is supported on all platforms. fprintf(stderr, "Warning: only ICC profile extraction is currently" " supported on this platform!\n"); } #endif } else if (!strcmp(argv[c], "-v")) { verbose = 1; } else if (!strcmp(argv[c], "--")) { if (c < argc - 1) in_file = argv[++c]; break; } else if (argv[c][0] == '-') { fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); HelpLong(); return -1; } else { in_file = argv[c]; } }
int main(int argc, const char *argv[]) { int verbose = 0; int gif_error = GIF_ERROR; WebPMuxError err = WEBP_MUX_OK; int ok = 0; const char *in_file = NULL, *out_file = NULL; FILE* out = NULL; GifFileType* gif = NULL; WebPConfig config; WebPPicture frame; WebPMuxFrameInfo info; WebPMuxAnimParams anim = { WHITE_COLOR, 0 }; WebPFrameCache* cache = NULL; int is_first_frame = 1; // Whether we are processing the first frame. int done; int c; int quiet = 0; WebPMux* mux = NULL; WebPData webp_data = { NULL, 0 }; int keep_metadata = METADATA_XMP; // ICC not output by default. int stored_icc = 0; // Whether we have already stored an ICC profile. int stored_xmp = 0; int default_kmin = 1; // Whether to use default kmin value. int default_kmax = 1; size_t kmin = 0; size_t kmax = 0; int allow_mixed = 0; // If true, each frame can be lossy or lossless. ResetFrameInfo(&info); if (!WebPConfigInit(&config) || !WebPPictureInit(&frame)) { fprintf(stderr, "Error! Version mismatch!\n"); return -1; } config.lossless = 1; // Use lossless compression by default. config.image_hint = WEBP_HINT_GRAPH; // always low-color if (argc == 1) { Help(); return 0; } for (c = 1; c < argc; ++c) { int parse_error = 0; if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { Help(); return 0; } else if (!strcmp(argv[c], "-o") && c < argc - 1) { out_file = argv[++c]; } else if (!strcmp(argv[c], "-lossy")) { config.lossless = 0; } else if (!strcmp(argv[c], "-mixed")) { allow_mixed = 1; config.lossless = 0; } else if (!strcmp(argv[c], "-q") && c < argc - 1) { config.quality = ExUtilGetFloat(argv[++c], &parse_error); } else if (!strcmp(argv[c], "-m") && c < argc - 1) { config.method = ExUtilGetInt(argv[++c], 0, &parse_error); } else if (!strcmp(argv[c], "-kmax") && c < argc - 1) { kmax = ExUtilGetUInt(argv[++c], 0, &parse_error); default_kmax = 0; } else if (!strcmp(argv[c], "-kmin") && c < argc - 1) { kmin = ExUtilGetUInt(argv[++c], 0, &parse_error); default_kmin = 0; } else if (!strcmp(argv[c], "-f") && c < argc - 1) { config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error); } else if (!strcmp(argv[c], "-metadata") && c < argc - 1) { static const struct { const char* option; int flag; } kTokens[] = { { "all", METADATA_ALL }, { "none", 0 }, { "icc", METADATA_ICC }, { "xmp", METADATA_XMP }, }; const size_t kNumTokens = sizeof(kTokens) / sizeof(*kTokens); const char* start = argv[++c]; const char* const end = start + strlen(start); keep_metadata = 0; while (start < end) { size_t i; const char* token = strchr(start, ','); if (token == NULL) token = end; for (i = 0; i < kNumTokens; ++i) { if ((size_t)(token - start) == strlen(kTokens[i].option) && !strncmp(start, kTokens[i].option, strlen(kTokens[i].option))) { if (kTokens[i].flag != 0) { keep_metadata |= kTokens[i].flag; } else { keep_metadata = 0; } break; } } if (i == kNumTokens) { fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", (int)(token - start), start); Help(); return -1; } start = token + 1; } } else if (!strcmp(argv[c], "-mt")) { ++config.thread_level; } else if (!strcmp(argv[c], "-version")) { const int enc_version = WebPGetEncoderVersion(); const int mux_version = WebPGetMuxVersion(); printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n", (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, enc_version & 0xff, (mux_version >> 16) & 0xff, (mux_version >> 8) & 0xff, mux_version & 0xff); return 0; } else if (!strcmp(argv[c], "-quiet")) { quiet = 1; } else if (!strcmp(argv[c], "-v")) { verbose = 1; } else if (!strcmp(argv[c], "--")) { if (c < argc - 1) in_file = argv[++c]; break; } else if (argv[c][0] == '-') { fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); Help(); return -1; } else { in_file = argv[c]; } if (parse_error) { Help(); return -1; } }