// 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. // ----------------------------------------------------------------------------- // // Alpha-plane compression. // // Author: Skal (pascal.massimino@gmail.com)
// ----------------------------------------------------------------------------- // Encodes the given alpha data via specified compression method 'method'. // The pre-processing (quantization) is performed if 'quality' is less than 100. // For such cases, the encoding is lossy. The valid range is [0, 100] for // 'quality' and [0, 1] for 'method': // 'method = 0' - No compression; // 'method = 1' - Use lossless coder on the alpha plane only // 'filter' values [0, 4] correspond to prediction modes none, horizontal, // vertical & gradient filters. The prediction mode 4 will try all the // prediction modes 0 to 3 and pick the best one. // 'effort_level': specifies how much effort must be spent to try and reduce // the compressed output size. In range 0 (quick) to 6 (slow). // // 'output' corresponds to the buffer containing compressed alpha data. // This buffer is allocated by this method and caller should call // WebPSafeFree(*output) when done. // 'output_size' corresponds to size of this compressed alpha buffer. // // Returns 1 on successfully encoding the alpha and // 0 if either: // invalid quality or method, or // memory allocation for the compressed data fails.
#include"src/enc/vp8li_enc.h"
staticint EncodeLossless(const uint8_t* const data, int width, int height, int effort_level, // in [0..6] range int use_quality_100, VP8LBitWriter* const bw,
WebPAuxStats* const stats) { int ok = 0;
WebPConfig config;
WebPPicture picture;
if (!WebPPictureInit(&picture)) return 0;
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);
if (!WebPConfigInit(&config)) return 0;
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'. // If the alpha quality is set to 100 and the method to 6, allow for a high // lossless quality to trigger the cruncher.
config.quality =
(use_quality_100 && effort_level == 6) ? 100 : 8.f * effort_level;
assert(config.quality >= 0 && config.quality <= 100.f);
ok = VP8LEncodeStream(&config, &picture, bw);
WebPPictureFree(&picture);
ok = ok && !bw->error_; if (!ok) {
VP8LBitWriterWipeOut(bw); return 0;
} return 1;
}
// Small struct to hold the result of a filter mode compression attempt. typedefstruct {
size_t score;
VP8BitWriter bw;
WebPAuxStats stats;
} FilterTrial;
// This function always returns an initialized 'bw' object, even upon error. staticint EncodeAlphaInternal(const uint8_t* const data, int width, int height, int method, int filter, int reduce_levels, int effort_level, // in [0..6] range
uint8_t* const tmp_alpha,
FilterTrial* result) { int ok = 0; const uint8_t* alpha_src;
WebPFilterFunc filter_func;
uint8_t header; const size_t data_size = width * height; const uint8_t* output = NULL;
size_t output_size = 0;
VP8LBitWriter tmp_bw;
if (method != ALPHA_NO_COMPRESSION) {
ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3);
ok = ok && EncodeLossless(alpha_src, width, height, effort_level,
!reduce_levels, &tmp_bw, &result->stats); if (ok) {
output = VP8LBitWriterFinish(&tmp_bw); if (tmp_bw.error_) {
VP8LBitWriterWipeOut(&tmp_bw);
memset(&result->bw, 0, sizeof(result->bw)); return 0;
}
output_size = VP8LBitWriterNumBytes(&tmp_bw); if (output_size > data_size) { // compressed size is larger than source! Revert to uncompressed mode.
method = ALPHA_NO_COMPRESSION;
VP8LBitWriterWipeOut(&tmp_bw);
}
} else {
VP8LBitWriterWipeOut(&tmp_bw);
memset(&result->bw, 0, sizeof(result->bw)); return 0;
}
}
if (method == ALPHA_NO_COMPRESSION) {
output = alpha_src;
output_size = data_size;
ok = 1;
}
// Emit final result.
header = method | (filter << 2); if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
if (!VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size)) ok = 0;
ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN);
ok = ok && VP8BitWriterAppend(&result->bw, output, output_size);
if (method != ALPHA_NO_COMPRESSION) {
VP8LBitWriterWipeOut(&tmp_bw);
}
ok = ok && !result->bw.error_;
result->score = VP8BitWriterSize(&result->bw); return ok;
}
int VP8EncStartAlpha(VP8Encoder* const enc) { if (enc->has_alpha_) { if (enc->thread_level_ > 0) {
WebPWorker* const worker = &enc->alpha_worker_; // Makes sure worker is good to go. if (!WebPGetWorkerInterface()->Reset(worker)) { return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
WebPGetWorkerInterface()->Launch(worker); return 1;
} else { return CompressAlphaJob(enc, NULL); // just do the job right away
}
} return 1;
}
int VP8EncFinishAlpha(VP8Encoder* const enc) { if (enc->has_alpha_) { if (enc->thread_level_ > 0) {
WebPWorker* const worker = &enc->alpha_worker_; if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error
}
} return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
}
int VP8EncDeleteAlpha(VP8Encoder* const enc) { int ok = 1; if (enc->thread_level_ > 0) {
WebPWorker* const worker = &enc->alpha_worker_; // finish anything left in flight
ok = WebPGetWorkerInterface()->Sync(worker); // still need to end the worker, even if !ok
WebPGetWorkerInterface()->End(worker);
}
WebPSafeFree(enc->alpha_data_);
enc->alpha_data_ = NULL;
enc->alpha_data_size_ = 0;
enc->has_alpha_ = 0; 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.