int WebPEncode(const WebPConfig* config, WebPPicture* pic) { int ok = 0; if (pic == NULL) return 0; WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far if (config == NULL) // bad params return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); if (!WebPValidateConfig(config)) return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); if (pic->width <= 0 || pic->height <= 0) return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); if (!config->lossless) { VP8Encoder* enc = NULL; if (pic->y == NULL || pic->u == NULL || pic->v == NULL) { // Make sure we have YUVA samples. if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0; } enc = InitVP8Encoder(config, pic); if (enc == NULL) return 0; // pic->error is already set. // Note: each of the tasks below account for 20% in the progress report. ok = VP8EncAnalyze(enc); // Analysis is done, proceed to actual coding. ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel if (!enc->use_tokens_) { ok = VP8EncLoop(enc); } else { ok = VP8EncTokenLoop(enc); } ok = ok && VP8EncFinishAlpha(enc); #ifdef WEBP_EXPERIMENTAL_FEATURES ok = ok && VP8EncFinishLayer(enc); #endif ok = ok && VP8EncWrite(enc); StoreStats(enc); if (!ok) { VP8EncFreeBitWriters(enc); } ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok } else { // Make sure we have ARGB samples. if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { return 0; } ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. } return ok; }
int WebPEncode(const WebPConfig* config, WebPPicture* pic) { int ok = 0; if (pic == NULL) return 0; WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far if (config == NULL) // bad params return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); if (!WebPValidateConfig(config)) return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); if (pic->width <= 0 || pic->height <= 0) return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); if (!config->lossless) { VP8Encoder* enc = NULL; if (pic->y == NULL || pic->u == NULL || pic->v == NULL) { // Make sure we have YUVA samples. float dithering = 0.f; if (config->preprocessing & 2) { const float x = config->quality / 100.f; const float x2 = x * x; // slowly decreasing from max dithering at low quality (q->0) // to 0.5 dithering amplitude at high quality (q->100) dithering = 1.0f + (0.5f - 1.0f) * x2 * x2; } if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) { return 0; } } enc = InitVP8Encoder(config, pic); if (enc == NULL) return 0; // pic->error is already set. // Note: each of the tasks below account for 20% in the progress report. ok = VP8EncAnalyze(enc); // Analysis is done, proceed to actual coding. ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel if (!enc->use_tokens_) { ok = ok && VP8EncLoop(enc); } else { ok = ok && VP8EncTokenLoop(enc); } ok = ok && VP8EncFinishAlpha(enc); ok = ok && VP8EncWrite(enc); StoreStats(enc); if (!ok) { VP8EncFreeBitWriters(enc); } ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok } else { // Make sure we have ARGB samples. if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { return 0; } ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. } return ok; }