// Copyright 2011 Google Inc. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the COPYING file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // WebP encoder: main entry point // // Author: Skal (pascal.massimino@gmail.com)
staticvoid ResetBoundaryPredictions(VP8Encoder* const enc) { // init boundary values once for all // Note: actually, initializing the preds_[] is only needed for intra4. int i;
uint8_t* const top = enc->preds_ - enc->preds_w_;
uint8_t* const left = enc->preds_ - 1; for (i = -1; i < 4 * enc->mb_w_; ++i) {
top[i] = B_DC_PRED;
} for (i = 0; i < 4 * enc->mb_h_; ++i) {
left[i * enc->preds_w_] = B_DC_PRED;
}
enc->nz_[-1] = 0; // constant
}
// Mapping from config->method_ to coding tools used. //-------------------+---+---+---+---+---+---+---+ // Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | //-------------------+---+---+---+---+---+---+---+ // fast probe | x | | | x | | | | //-------------------+---+---+---+---+---+---+---+ // dynamic proba | ~ | x | x | x | x | x | x | //-------------------+---+---+---+---+---+---+---+ // fast mode analysis|[x]|[x]| | | x | x | x | //-------------------+---+---+---+---+---+---+---+ // basic rd-opt | | | | x | x | x | x | //-------------------+---+---+---+---+---+---+---+ // disto-refine i4/16| x | x | x | | | | | //-------------------+---+---+---+---+---+---+---+ // disto-refine uv | | x | x | | | | | //-------------------+---+---+---+---+---+---+---+ // rd-opt i4/16 | | | ~ | x | x | x | x | //-------------------+---+---+---+---+---+---+---+ // token buffer (opt)| | | | x | x | x | x | //-------------------+---+---+---+---+---+---+---+ // Trellis | | | | | | x |Ful| //-------------------+---+---+---+---+---+---+---+ // full-SNS | | | | | x | x | x | //-------------------+---+---+---+---+---+---+---+
// lower quality means smaller output -> we modulate a little the page // size based on quality. This is just a crude 1rst-order prediction.
{ constfloat scale = 1.f + config->quality * 5.f / 100.f; // in [1,6]
VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale));
} return enc;
}
staticint DeleteVP8Encoder(VP8Encoder* enc) { int ok = 1; if (enc != NULL) {
ok = VP8EncDeleteAlpha(enc);
VP8TBufferClear(&enc->tokens_);
WebPSafeFree(enc);
} return ok;
}
staticvoid StoreStats(VP8Encoder* const enc) { #if !defined(WEBP_DISABLE_STATS)
WebPAuxStats* const stats = enc->pic_->stats; if (stats != NULL) { int i, s; for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
stats->segment_level[i] = enc->dqm_[i].fstrength_;
stats->segment_quant[i] = enc->dqm_[i].quant_; for (s = 0; s <= 2; ++s) {
stats->residual_bytes[s][i] = enc->residual_bytes_[s][i];
}
}
FinalizePSNR(enc);
stats->coded_size = enc->coded_size_; for (i = 0; i < 3; ++i) {
stats->block_count[i] = enc->block_count_[i];
}
} #else// defined(WEBP_DISABLE_STATS)
WebPReportProgress(enc->pic_, 100, &enc->percent_); // done! #endif// !defined(WEBP_DISABLE_STATS)
}
int WebPEncodingSetError(const WebPPicture* const pic,
WebPEncodingError error) {
assert((int)error < VP8_ENC_ERROR_LAST);
assert((int)error >= VP8_ENC_OK); // The oldest error reported takes precedence over the new one. if (pic->error_code == VP8_ENC_OK) {
((WebPPicture*)pic)->error_code = error;
} return 0;
}
int WebPReportProgress(const WebPPicture* const pic, int percent, int* const percent_store) { if (percent_store != NULL && percent != *percent_store) {
*percent_store = percent; if (pic->progress_hook && !pic->progress_hook(percent, pic)) { // user abort requested return WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
}
} return 1; // ok
} //------------------------------------------------------------------------------
int WebPEncode(const WebPConfig* config, WebPPicture* pic) { int ok = 0; if (pic == NULL) return 0;
pic->error_code = 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 (!WebPValidatePicture(pic)) return 0; 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->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) { // Make sure we have YUVA samples. if (config->use_sharp_yuv || (config->preprocessing & 4)) { if (!WebPPictureSharpARGBToYUVA(pic)) { return 0;
}
} else { float dithering = 0.f; if (config->preprocessing & 2) { constfloat x = config->quality / 100.f; constfloat 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;
}
}
}
if (!config->exact) {
WebPCleanupTransparentArea(pic);
}
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;
}
if (!config->exact) {
WebPReplaceTransparentPixels(pic, 0x000000);
}
ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
}
return ok;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.