mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-25 13:18:22 +01:00
Implement progress report (and user abort)
New cwebp flag is -progress Change-Id: Ied872cca13f512036860783bbee1bdbccad72768
This commit is contained in:
parent
eda520a92e
commit
30971c9e95
7
README
7
README
@ -127,6 +127,7 @@ options:
|
||||
-h / -help ............ short help
|
||||
-H / -longhelp ........ long help
|
||||
-q <float> ............. quality factor (0:small..100:big)
|
||||
-alpha_q <int> ......... Transparency-compression quality (0..100)
|
||||
-preset <string> ....... Preset setting, one of:
|
||||
default, photo, picture,
|
||||
drawing, icon, text
|
||||
@ -141,20 +142,22 @@ options:
|
||||
-strong ................ use strong filter instead of simple.
|
||||
-partition_limit <int> . limit quality to fit the 512k limit on
|
||||
the first partition (0=no degradation ... 100=full)
|
||||
-alpha_comp <int> ...... set the transparency-compression
|
||||
-noalpha ............... discard any transparency information.
|
||||
-pass <int> ............ analysis pass number (1..10)
|
||||
-partitions <int> ...... number of partitions to use (0..3)
|
||||
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
|
||||
-resize <w> <h> ........ resize picture (after any cropping)
|
||||
-map <int> ............. print map of extra info.
|
||||
-d <file.pgm> .......... dump the compressed output (PGM file).
|
||||
-alpha_method <int> .... Transparency-compression method (0..1)
|
||||
-noalpha ............... discard any transparency information.
|
||||
|
||||
-short ................. condense printed message
|
||||
-quiet ................. don't print anything.
|
||||
-version ............... print version number and exit.
|
||||
-noasm ................. disable all assembly optimizations.
|
||||
-v ..................... verbose, e.g. print encoding/decoding times
|
||||
-progress .............. report encoding progress
|
||||
|
||||
|
||||
Experimental Options:
|
||||
-size <int> ............ Target size (in bytes)
|
||||
|
@ -641,6 +641,15 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static int ProgressReport(int percent, const WebPPicture* const picture) {
|
||||
printf("[%s]: %3d %% \r",
|
||||
(char*)picture->stats->user_data, percent);
|
||||
fflush(stdout);
|
||||
return 1; // all ok
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static void HelpShort(void) {
|
||||
printf("Usage:\n\n");
|
||||
printf(" cwebp [options] -q quality input.png -o output.webp\n\n");
|
||||
@ -702,6 +711,7 @@ static void HelpLong(void) {
|
||||
#endif
|
||||
printf(" -v ..................... verbose, e.g. print encoding/decoding "
|
||||
"times\n");
|
||||
printf(" -progress .............. report encoding progress\n");
|
||||
printf("\n");
|
||||
printf("Experimental Options:\n");
|
||||
printf(" -af .................... auto-adjust filter strength.\n");
|
||||
@ -727,7 +737,8 @@ static const char* const kErrorMessages[] = {
|
||||
"in the manual (`man cwebp`)",
|
||||
"PARTITION_OVERFLOW: Partition is too big to fit 16M",
|
||||
"BAD_WRITE: Picture writer returned an I/O error",
|
||||
"FILE_TOO_BIG: File would be too big to fit in 4G"
|
||||
"FILE_TOO_BIG: File would be too big to fit in 4G",
|
||||
"USER_ABORT: encoding abort requested by user"
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -741,6 +752,7 @@ int main(int argc, const char *argv[]) {
|
||||
int keep_alpha = 1;
|
||||
int crop = 0, crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0;
|
||||
int resize_w = 0, resize_h = 0;
|
||||
int show_progress = 0;
|
||||
WebPPicture picture;
|
||||
WebPConfig config;
|
||||
WebPAuxStats stats;
|
||||
@ -833,6 +845,8 @@ int main(int argc, const char *argv[]) {
|
||||
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) {
|
||||
@ -882,6 +896,8 @@ int main(int argc, const char *argv[]) {
|
||||
fprintf(stderr, "Error! Cannot read input picture\n");
|
||||
goto Error;
|
||||
}
|
||||
picture.progress_hook = (show_progress && !quiet) ? ProgressReport : NULL;
|
||||
|
||||
if (verbose) {
|
||||
const double time = StopwatchReadAndReset(&stop_watch);
|
||||
fprintf(stderr, "Time to read input: %.3fs\n", time);
|
||||
@ -908,6 +924,7 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
}
|
||||
picture.stats = &stats;
|
||||
stats.user_data = (void*)in_file;
|
||||
|
||||
// Compress
|
||||
if (verbose) {
|
||||
|
@ -156,6 +156,9 @@ Disable all assembly optimizations.
|
||||
.B \-v
|
||||
Print extra information (encoding time in particular).
|
||||
.TP
|
||||
.B \-progress
|
||||
Report encoding progress in percent.
|
||||
.TP
|
||||
.B \-quiet
|
||||
Do not print anything.
|
||||
.TP
|
||||
|
@ -46,7 +46,7 @@ int VP8EncFinishAlpha(VP8Encoder* enc) {
|
||||
enc->alpha_data_size_ = (uint32_t)tmp_size;
|
||||
enc->alpha_data_ = tmp_data;
|
||||
}
|
||||
return 1;
|
||||
return WebPReportProgress(enc, enc->percent_ + 20);
|
||||
}
|
||||
|
||||
void VP8EncDeleteAlpha(VP8Encoder* enc) {
|
||||
|
@ -339,6 +339,7 @@ static void MBAnalyze(VP8EncIterator* const it,
|
||||
// this stage.
|
||||
|
||||
int VP8EncAnalyze(VP8Encoder* const enc) {
|
||||
int ok = 1;
|
||||
int alphas[256] = { 0 };
|
||||
VP8EncIterator it;
|
||||
|
||||
@ -347,12 +348,13 @@ int VP8EncAnalyze(VP8Encoder* const enc) {
|
||||
do {
|
||||
VP8IteratorImport(&it);
|
||||
MBAnalyze(&it, alphas, &enc->uv_alpha_);
|
||||
ok = VP8IteratorProgress(&it, 20);
|
||||
// Let's pretend we have perfect lossless reconstruction.
|
||||
} while (VP8IteratorNext(&it, it.yuv_in_));
|
||||
} while (ok && VP8IteratorNext(&it, it.yuv_in_));
|
||||
enc->uv_alpha_ /= enc->mb_w_ * enc->mb_h_;
|
||||
AssignSegments(enc, alphas);
|
||||
if (ok) AssignSegments(enc, alphas);
|
||||
|
||||
return 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
|
@ -560,6 +560,7 @@ static void ResetAfterSkip(VP8EncIterator* const it) {
|
||||
|
||||
int VP8EncLoop(VP8Encoder* const enc) {
|
||||
int i, s, p;
|
||||
int ok = 1;
|
||||
VP8EncIterator it;
|
||||
VP8ModeScore info;
|
||||
const int dont_use_skip = !enc->proba_.use_skip_proba_;
|
||||
@ -595,12 +596,17 @@ int VP8EncLoop(VP8Encoder* const enc) {
|
||||
StoreSideInfo(&it);
|
||||
VP8StoreFilterStats(&it);
|
||||
VP8IteratorExport(&it);
|
||||
} while (VP8IteratorNext(&it, it.yuv_out_));
|
||||
VP8AdjustFilterStrength(&it);
|
||||
ok = VP8IteratorProgress(&it, 20);
|
||||
} while (ok && VP8IteratorNext(&it, it.yuv_out_));
|
||||
|
||||
if (ok) {
|
||||
VP8AdjustFilterStrength(&it);
|
||||
}
|
||||
|
||||
// Finalize the partitions
|
||||
for (p = 0; p < enc->num_parts_; ++p) {
|
||||
VP8BitWriterFinish(enc->parts_ + p);
|
||||
ok &= !enc->parts_[p].error_;
|
||||
}
|
||||
// and byte counters
|
||||
if (enc->pic_->stats) {
|
||||
@ -610,7 +616,10 @@ int VP8EncLoop(VP8Encoder* const enc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
if (!ok) { // need to do some memory cleanup
|
||||
VP8EncFreeBitWriters(enc);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -622,7 +631,7 @@ int VP8EncLoop(VP8Encoder* const enc) {
|
||||
#define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better
|
||||
|
||||
static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
|
||||
float* const PSNR) {
|
||||
float* const PSNR, int percent_delta) {
|
||||
VP8EncIterator it;
|
||||
uint64_t size = 0;
|
||||
uint64_t distortion = 0;
|
||||
@ -651,6 +660,8 @@ static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
|
||||
RecordResiduals(&it, &info);
|
||||
size += info.R;
|
||||
distortion += info.D;
|
||||
if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
|
||||
return 0;
|
||||
} while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0);
|
||||
size += FinalizeSkipProba(enc);
|
||||
size += FinalizeTokenProbas(enc);
|
||||
@ -671,6 +682,10 @@ int VP8StatLoop(VP8Encoder* const enc) {
|
||||
(enc->config_->target_size > 0 || enc->config_->target_PSNR > 0);
|
||||
const int fast_probe = (enc->method_ < 2 && !do_search);
|
||||
float q = enc->config_->quality;
|
||||
const int max_passes = enc->config_->pass;
|
||||
const int task_percent = 20;
|
||||
const int percent_per_pass = (task_percent + max_passes / 2) / max_passes;
|
||||
const int final_percent = enc->percent_ + task_percent;
|
||||
int pass;
|
||||
int nb_mbs;
|
||||
|
||||
@ -680,36 +695,38 @@ int VP8StatLoop(VP8Encoder* const enc) {
|
||||
|
||||
// No target size: just do several pass without changing 'q'
|
||||
if (!do_search) {
|
||||
for (pass = 0; pass < enc->config_->pass; ++pass) {
|
||||
for (pass = 0; pass < max_passes; ++pass) {
|
||||
const int rd_opt = (enc->method_ > 2);
|
||||
OneStatPass(enc, q, rd_opt, nb_mbs, NULL);
|
||||
if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// binary search for a size close to target
|
||||
for (pass = 0; pass < enc->config_->pass && (dqs[pass] > 0); ++pass) {
|
||||
const int rd_opt = 1;
|
||||
float PSNR;
|
||||
int criterion;
|
||||
const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR);
|
||||
} else {
|
||||
// binary search for a size close to target
|
||||
for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) {
|
||||
const int rd_opt = 1;
|
||||
float PSNR;
|
||||
int criterion;
|
||||
const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR,
|
||||
percent_per_pass);
|
||||
#if DEBUG_SEARCH
|
||||
printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q);
|
||||
printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q);
|
||||
#endif
|
||||
|
||||
if (enc->config_->target_PSNR > 0) {
|
||||
criterion = (PSNR < enc->config_->target_PSNR);
|
||||
} else {
|
||||
criterion = (size < enc->config_->target_size);
|
||||
}
|
||||
// dichotomize
|
||||
if (criterion) {
|
||||
q += dqs[pass];
|
||||
} else {
|
||||
q -= dqs[pass];
|
||||
if (!size) return 0;
|
||||
if (enc->config_->target_PSNR > 0) {
|
||||
criterion = (PSNR < enc->config_->target_PSNR);
|
||||
} else {
|
||||
criterion = (size < enc->config_->target_size);
|
||||
}
|
||||
// dichotomize
|
||||
if (criterion) {
|
||||
q += dqs[pass];
|
||||
} else {
|
||||
q -= dqs[pass];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return WebPReportProgress(enc, final_percent);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -66,9 +66,18 @@ void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
|
||||
it->yuv_out2_ = enc->yuv_out2_;
|
||||
it->yuv_p_ = enc->yuv_p_;
|
||||
it->lf_stats_ = enc->lf_stats_;
|
||||
it->percent0_ = enc->percent_;
|
||||
VP8IteratorReset(it);
|
||||
}
|
||||
|
||||
int VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
|
||||
if (delta && it->enc_->pic_->progress_hook) {
|
||||
const int percent = it->percent0_ + delta * it->y_ / (it->enc_->mb_h_ - 1);
|
||||
return WebPReportProgress(it->enc_, percent);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Import the source samples into the cache. Takes care of replicating
|
||||
// boundary pixels if necessary.
|
||||
|
@ -18,10 +18,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
|
||||
#endif /* WEBP_EXPERIMENTAL_FEATURES */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void VP8EncInitLayer(VP8Encoder* const enc) {
|
||||
@ -35,8 +31,6 @@ void VP8EncInitLayer(VP8Encoder* const enc) {
|
||||
|
||||
void VP8EncCodeLayerBlock(VP8EncIterator* it) {
|
||||
(void)it; // remove a warning
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
#endif /* WEBP_EXPERIMENTAL_FEATURES */
|
||||
}
|
||||
|
||||
int VP8EncFinishLayer(VP8Encoder* const enc) {
|
||||
|
@ -356,9 +356,20 @@ static size_t GeneratePartition0(VP8Encoder* const enc) {
|
||||
return !bw->error_;
|
||||
}
|
||||
|
||||
void VP8EncFreeBitWriters(VP8Encoder* const enc) {
|
||||
int p;
|
||||
VP8BitWriterWipeOut(&enc->bw_);
|
||||
for (p = 0; p < enc->num_parts_; ++p) {
|
||||
VP8BitWriterWipeOut(enc->parts_ + p);
|
||||
}
|
||||
}
|
||||
|
||||
int VP8EncWrite(VP8Encoder* const enc) {
|
||||
WebPPicture* const pic = enc->pic_;
|
||||
VP8BitWriter* const bw = &enc->bw_;
|
||||
const int task_percent = 19;
|
||||
const int percent_per_part = task_percent / enc->num_parts_;
|
||||
const int final_percent = enc->percent_ + task_percent;
|
||||
int ok = 0;
|
||||
size_t vp8_size, pad, riff_size;
|
||||
int p;
|
||||
@ -399,7 +410,7 @@ int VP8EncWrite(VP8Encoder* const enc) {
|
||||
ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size)
|
||||
&& pic->writer(part0, size0, pic)
|
||||
&& EmitPartitionsSize(enc, pic);
|
||||
free((void*)part0);
|
||||
VP8BitWriterWipeOut(bw); // will free the internal buffer.
|
||||
}
|
||||
|
||||
// Token partitions
|
||||
@ -408,7 +419,8 @@ int VP8EncWrite(VP8Encoder* const enc) {
|
||||
const size_t size = VP8BitWriterSize(enc->parts_ + p);
|
||||
if (size)
|
||||
ok = ok && pic->writer(buf, size, pic);
|
||||
free((void*)buf);
|
||||
VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer.
|
||||
ok = ok && WebPReportProgress(enc, enc->percent_ + percent_per_part);
|
||||
}
|
||||
|
||||
// Padding byte
|
||||
@ -417,6 +429,7 @@ int VP8EncWrite(VP8Encoder* const enc) {
|
||||
}
|
||||
|
||||
enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size);
|
||||
ok = ok && WebPReportProgress(enc, final_percent);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -272,6 +272,7 @@ typedef struct {
|
||||
LFStats* lf_stats_; // filter stats (borrowed from enc_)
|
||||
int do_trellis_; // if true, perform extra level optimisation
|
||||
int done_; // true when scan is finished
|
||||
int percent0_; // saved initial progress percent
|
||||
} VP8EncIterator;
|
||||
|
||||
// in iterator.c
|
||||
@ -288,6 +289,9 @@ void VP8IteratorExport(const VP8EncIterator* const it);
|
||||
// it->yuv_out_ or it->yuv_in_.
|
||||
int VP8IteratorNext(VP8EncIterator* const it,
|
||||
const uint8_t* const block_to_save);
|
||||
// Report progression based on macroblock rows. Return 0 for user-abort request.
|
||||
int VP8IteratorProgress(const VP8EncIterator* const it,
|
||||
int final_delta_percent);
|
||||
// Intra4x4 iterations
|
||||
void VP8IteratorStartI4(VP8EncIterator* const it);
|
||||
// returns true if not done.
|
||||
@ -330,6 +334,8 @@ struct VP8Encoder {
|
||||
VP8BitWriter bw_; // part0
|
||||
VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions
|
||||
|
||||
int percent_; // for progress
|
||||
|
||||
// transparency blob
|
||||
int has_alpha_;
|
||||
uint8_t* alpha_data_; // non-NULL if transparency is present
|
||||
@ -401,6 +407,8 @@ void VP8CodeIntraModes(VP8Encoder* const enc);
|
||||
// and appending an assembly of all the pre-coded token partitions.
|
||||
// Return true if everything is ok.
|
||||
int VP8EncWrite(VP8Encoder* const enc);
|
||||
// Release memory allocated for bit-writing in VP8EncLoop & seq.
|
||||
void VP8EncFreeBitWriters(VP8Encoder* const enc);
|
||||
|
||||
// in frame.c
|
||||
extern const uint8_t VP8EncBands[16 + 1];
|
||||
@ -422,6 +430,7 @@ int VP8StatLoop(VP8Encoder* const enc);
|
||||
// in webpenc.c
|
||||
// Assign an error code to a picture. Return false for convenience.
|
||||
int WebPEncodingSetError(WebPPicture* const pic, WebPEncodingError error);
|
||||
int WebPReportProgress(VP8Encoder* const enc, int percent);
|
||||
|
||||
// in analysis.c
|
||||
// Main analysis loop. Decides the segmentations and complexity.
|
||||
|
@ -242,6 +242,7 @@ static VP8Encoder* InitEncoder(const WebPConfig* const config,
|
||||
enc->config_ = config;
|
||||
enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
|
||||
enc->pic_ = picture;
|
||||
enc->percent_ = 0;
|
||||
|
||||
MapConfigToTools(enc);
|
||||
VP8EncDspInit();
|
||||
@ -301,15 +302,28 @@ static void StoreStats(VP8Encoder* const enc) {
|
||||
stats->block_count[i] = enc->block_count_[i];
|
||||
}
|
||||
}
|
||||
WebPReportProgress(enc, 100); // done!
|
||||
}
|
||||
|
||||
int WebPEncodingSetError(WebPPicture* const pic, WebPEncodingError error) {
|
||||
assert((int)error <= VP8_ENC_ERROR_BAD_WRITE);
|
||||
assert((int)error < VP8_ENC_ERROR_LAST);
|
||||
assert((int)error >= VP8_ENC_OK);
|
||||
pic->error_code = error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebPReportProgress(VP8Encoder* const enc, int percent) {
|
||||
if (percent != enc->percent_) {
|
||||
WebPPicture* const pic = enc->pic_;
|
||||
enc->percent_ = percent;
|
||||
if (pic->progress_hook && !pic->progress_hook(percent, pic)) {
|
||||
// user abort requested
|
||||
WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1; // ok
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
|
||||
@ -332,6 +346,7 @@ int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
|
||||
|
||||
enc = InitEncoder(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)
|
||||
&& VP8StatLoop(enc)
|
||||
&& VP8EncLoop(enc)
|
||||
@ -341,6 +356,9 @@ int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
|
||||
#endif
|
||||
&& VP8EncWrite(enc);
|
||||
StoreStats(enc);
|
||||
if (!ok) {
|
||||
VP8EncFreeBitWriters(enc);
|
||||
}
|
||||
DeleteEncoder(enc);
|
||||
|
||||
return ok;
|
||||
|
@ -179,6 +179,13 @@ int VP8BitWriterAppend(VP8BitWriter* const bw,
|
||||
return 1;
|
||||
}
|
||||
|
||||
void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
|
||||
if (bw) {
|
||||
free(bw->buf_);
|
||||
memset(bw, 0, sizeof(*bw));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
|
@ -27,18 +27,26 @@ struct VP8BitWriter {
|
||||
int32_t value_;
|
||||
int run_; // number of outstanding bits
|
||||
int nb_bits_; // number of pending bits
|
||||
uint8_t* buf_;
|
||||
uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned.
|
||||
size_t pos_;
|
||||
size_t max_pos_;
|
||||
int error_; // true in case of error
|
||||
};
|
||||
|
||||
// Initialize the object. Allocates some initial memory based on expected_size.
|
||||
int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size);
|
||||
// Finalize the bitstream coding. Returns a pointer to the internal buffer.
|
||||
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw);
|
||||
// Release any pending memory and zeroes the object. Not a mandatory call.
|
||||
// Only useful in case of error, when the internal buffer hasn't been grabbed!
|
||||
void VP8BitWriterWipeOut(VP8BitWriter* const bw);
|
||||
|
||||
int VP8PutBit(VP8BitWriter* const bw, int bit, int prob);
|
||||
int VP8PutBitUniform(VP8BitWriter* const bw, int bit);
|
||||
void VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits);
|
||||
void VP8PutSignedValue(VP8BitWriter* const bw, int value, int nb_bits);
|
||||
|
||||
// Appends some bytes to the internal buffer. Data is copied.
|
||||
int VP8BitWriterAppend(VP8BitWriter* const bw,
|
||||
const uint8_t* data, size_t size);
|
||||
|
||||
@ -47,9 +55,11 @@ static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
|
||||
return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_;
|
||||
}
|
||||
|
||||
// Returns a pointer to the internal buffer.
|
||||
static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) {
|
||||
return bw->buf_;
|
||||
}
|
||||
// Returns the size of the internal buffer.
|
||||
static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
|
||||
return bw->pos_;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WEBP_ENCODER_ABI_VERSION 0x0002
|
||||
#define WEBP_ENCODER_ABI_VERSION 0x0003
|
||||
|
||||
// Return the encoder's version number, packed in hexadecimal using 8bits for
|
||||
// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
|
||||
@ -72,7 +72,7 @@ typedef struct {
|
||||
int partition_limit; // quality degradation allowed to fit the 512k limit on
|
||||
// prediction modes coding (0=no degradation, 100=full)
|
||||
int alpha_compression; // Algorithm for encoding the alpha plane (0 = none,
|
||||
// 1 = Backward reference counts encoded with
|
||||
// 1 = backward reference counts encoded with
|
||||
// arithmetic encoder). Default is 1.
|
||||
int alpha_quality; // Between 0 (smallest size) and 100 (lossless).
|
||||
// Default is 100.
|
||||
@ -134,6 +134,9 @@ typedef struct {
|
||||
|
||||
int alpha_data_size; // size of the transparency data
|
||||
int layer_data_size; // size of the enhancement layer data
|
||||
|
||||
void* user_data; // this field is free to be set to any value and
|
||||
// used during callbacks (like progress-report e.g.).
|
||||
} WebPAuxStats;
|
||||
|
||||
// Signature for output function. Should return 1 if writing was successful.
|
||||
@ -142,6 +145,10 @@ typedef struct {
|
||||
typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size,
|
||||
const WebPPicture* const picture);
|
||||
|
||||
// Progress hook, called from time to time to report progress. It can return 0
|
||||
// to request an abort of the encoding process, or 1 otherwise if all is OK.
|
||||
typedef int (*WebPProgressHook)(int percent, const WebPPicture* const picture);
|
||||
|
||||
typedef enum {
|
||||
// chroma sampling
|
||||
WEBP_YUV420 = 0, // 4:2:0
|
||||
@ -169,6 +176,8 @@ typedef enum {
|
||||
VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M
|
||||
VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes
|
||||
VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G
|
||||
VP8_ENC_ERROR_USER_ABORT, // abort request by user
|
||||
VP8_ENC_ERROR_LAST // list terminator. always last.
|
||||
} WebPEncodingError;
|
||||
|
||||
// maximum width/height allowed (inclusive), in pixels
|
||||
@ -205,6 +214,8 @@ struct WebPPicture {
|
||||
int uv0_stride;
|
||||
|
||||
WebPEncodingError error_code; // error code in case of problem.
|
||||
|
||||
WebPProgressHook progress_hook; // if not NULL, called while encoding.
|
||||
};
|
||||
|
||||
// Internal, version-checked, entry point
|
||||
|
Loading…
Reference in New Issue
Block a user