| 1275 | } |
| 1276 | |
| 1277 | static avifBool avifEncodeImages(avifSettings * settings, |
| 1278 | avifInput * input, |
| 1279 | const avifInputFile * firstFile, |
| 1280 | const avifImage * firstImage, |
| 1281 | const avifImage * const * gridCells, |
| 1282 | avifRWData * encoded, |
| 1283 | avifEncodedByteSizes * byteSizes) |
| 1284 | { |
| 1285 | if (settings->targetSize == -1) { |
| 1286 | return avifEncodeImagesFixedQuality(settings, input, firstFile, firstImage, gridCells, encoded, byteSizes); |
| 1287 | } |
| 1288 | |
| 1289 | avifBool hasGainMap = AVIF_FALSE; |
| 1290 | avifBool allQualitiesConstrained = settings->qualityIsConstrained && settings->qualityAlphaIsConstrained; |
| 1291 | #if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) |
| 1292 | hasGainMap = (firstImage->gainMap && firstImage->gainMap->image); |
| 1293 | if (hasGainMap) { |
| 1294 | allQualitiesConstrained = allQualitiesConstrained && settings->qualityGainMapIsConstrained; |
| 1295 | } |
| 1296 | #endif |
| 1297 | |
| 1298 | if (allQualitiesConstrained) { |
| 1299 | fprintf(stderr, "ERROR: --target-size is used with constrained --qcolor and --qalpha %s\n", (hasGainMap ? "and --qgain-map" : "")); |
| 1300 | return AVIF_FALSE; |
| 1301 | } |
| 1302 | |
| 1303 | printf("Starting a binary search to find the %s%s generating the encoded image size closest to %d bytes, please wait...\n", |
| 1304 | settings->qualityAlphaIsConstrained ? "color quality" |
| 1305 | : (settings->qualityIsConstrained ? "alpha quality" : "color and alpha qualities"), |
| 1306 | (hasGainMap && !settings->qualityGainMapIsConstrained) ? " and gain map quality" : "", |
| 1307 | settings->targetSize); |
| 1308 | const size_t targetSize = (size_t)settings->targetSize; |
| 1309 | |
| 1310 | // TODO(yguyon): Use quantizer instead of quality because quantizer range is smaller (faster binary search). |
| 1311 | int closestQuality = INVALID_QUALITY; |
| 1312 | avifRWData closestEncoded = { NULL, 0 }; |
| 1313 | size_t closestSizeDiff = 0; |
| 1314 | avifEncodedByteSizes closestByteSizes = { 0, 0, 0 }; |
| 1315 | |
| 1316 | int minQuality = settings->progressive ? PROGRESSIVE_WORST_QUALITY : AVIF_QUALITY_WORST; // inclusive |
| 1317 | int maxQuality = AVIF_QUALITY_BEST; // inclusive |
| 1318 | while (minQuality <= maxQuality) { |
| 1319 | const int quality = (minQuality + maxQuality) / 2; |
| 1320 | if (!settings->qualityIsConstrained) { |
| 1321 | settings->overrideQuality = quality; |
| 1322 | } |
| 1323 | if (!settings->qualityAlphaIsConstrained) { |
| 1324 | settings->overrideQualityAlpha = quality; |
| 1325 | } |
| 1326 | if (!settings->qualityGainMapIsConstrained) { |
| 1327 | settings->qualityGainMap = quality; |
| 1328 | } |
| 1329 | |
| 1330 | if (!avifEncodeImagesFixedQuality(settings, input, firstFile, firstImage, gridCells, encoded, byteSizes)) { |
| 1331 | avifRWDataFree(&closestEncoded); |
| 1332 | return AVIF_FALSE; |
| 1333 | } |
| 1334 | printf("Encoded image of size %" AVIF_FMT_ZU " bytes.\n", encoded->size); |
no test coverage detected