Add avifIsAlpha() to internal.h (#2057)
Also fix avifGetErrorForItemCategory() returned result for gain maps.
diff --git a/include/avif/internal.h b/include/avif/internal.h
index 3cf3aa0..ceb6110 100644
--- a/include/avif/internal.h
+++ b/include/avif/internal.h
@@ -156,6 +156,9 @@
// Ignores the gainMap field (which exists only if AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP is defined).
void avifImageCopySamples(avifImage * dstImage, const avifImage * srcImage, avifPlanesFlags planes);
+// ---------------------------------------------------------------------------
+// Alpha
+
typedef struct avifAlphaParams
{
uint32_t width;
@@ -321,6 +324,8 @@
AVIF_ITEM_CATEGORY_COUNT
} avifItemCategory;
+avifBool avifIsAlpha(avifItemCategory itemCategory);
+
// ---------------------------------------------------------------------------
#if defined(AVIF_ENABLE_EXPERIMENTAL_AVIR)
diff --git a/src/avif.c b/src/avif.c
index 264d004..aa7d8e6 100644
--- a/src/avif.c
+++ b/src/avif.c
@@ -868,6 +868,16 @@
// ---------------------------------------------------------------------------
+avifBool avifIsAlpha(avifItemCategory itemCategory)
+{
+ if (itemCategory == AVIF_ITEM_ALPHA) {
+ return AVIF_TRUE;
+ }
+ return AVIF_FALSE;
+}
+
+// ---------------------------------------------------------------------------
+
avifBool avifAreGridDimensionsValid(avifPixelFormat yuvFormat, uint32_t imageW, uint32_t imageH, uint32_t tileW, uint32_t tileH, avifDiagnostics * diag)
{
// ISO/IEC 23000-22:2019, Section 7.3.11.4.2:
diff --git a/src/read.c b/src/read.c
index 1a0d0b7..87005a7 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1523,7 +1523,7 @@
return AVIF_RESULT_INVALID_IMAGE_GRID;
}
- avifBool alpha = (tile->input->itemCategory == AVIF_ITEM_ALPHA);
+ const avifBool alpha = avifIsAlpha(tile->input->itemCategory);
if (alpha) {
// An alpha tile does not contain any YUV pixels.
AVIF_ASSERT_OR_RETURN(tile->image->yuvFormat == AVIF_PIXEL_FORMAT_NONE);
@@ -1618,8 +1618,7 @@
#endif
AVIF_ASSERT_OR_RETURN(avifImageSetViewRect(&dstView, dst, &dstViewRect) == AVIF_RESULT_OK &&
avifImageSetViewRect(&srcView, tile->image, &srcViewRect) == AVIF_RESULT_OK);
- avifImageCopySamples(&dstView, &srcView, (tile->input->itemCategory == AVIF_ITEM_ALPHA) ? AVIF_PLANES_A : AVIF_PLANES_YUV);
-
+ avifImageCopySamples(&dstView, &srcView, avifIsAlpha(tile->input->itemCategory) ? AVIF_PLANES_A : AVIF_PLANES_YUV);
return AVIF_RESULT_OK;
}
@@ -4970,7 +4969,7 @@
continue;
}
#endif
- if (c == AVIF_ITEM_ALPHA && !mainItems[c]->width && !mainItems[c]->height) {
+ if (avifIsAlpha(c) && !mainItems[c]->width && !mainItems[c]->height) {
// NON-STANDARD: Alpha subimage does not have an ispe property; adopt width/height from color item
AVIF_ASSERT_OR_RETURN(!(decoder->strictFlags & AVIF_STRICT_ALPHA_ISPE_REQUIRED));
mainItems[c]->width = mainItems[AVIF_ITEM_COLOR]->width;
@@ -4980,7 +4979,7 @@
AVIF_CHECKRES(avifDecoderGenerateImageTiles(decoder, &data->tileInfos[c], mainItems[c], c));
avifStrictFlags strictFlags = decoder->strictFlags;
- if (c == AVIF_ITEM_ALPHA && !isAlphaItemInInput) {
+ if (avifIsAlpha(c) && !isAlphaItemInInput) {
// In this case, the made up grid item will not have an associated pixi property. So validate everything else
// but the pixi property.
strictFlags &= ~AVIF_STRICT_PIXI_REQUIRED;
@@ -4991,7 +4990,7 @@
if (mainItems[AVIF_ITEM_COLOR]->progressive) {
decoder->progressiveState = AVIF_PROGRESSIVE_STATE_AVAILABLE;
- // data->color.firstTileIndex is not yet defined but will be set to 0 a few lines below.
+ // data->tileInfos[AVIF_ITEM_COLOR].firstTileIndex is not yet defined but will be set to 0 a few lines below.
const avifTile * colorTile = &data->tiles.tile[0];
if (colorTile->input->samples.count > 1) {
decoder->progressiveState = AVIF_PROGRESSIVE_STATE_ACTIVE;
@@ -5186,7 +5185,7 @@
return AVIF_RESULT_DECODE_GAIN_MAP_FAILED;
}
#endif
- return (itemCategory == AVIF_ITEM_ALPHA) ? AVIF_RESULT_DECODE_ALPHA_FAILED : AVIF_RESULT_DECODE_COLOR_FAILED;
+ return avifIsAlpha(itemCategory) ? AVIF_RESULT_DECODE_ALPHA_FAILED : AVIF_RESULT_DECODE_COLOR_FAILED;
}
static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextImageIndex, avifTileInfo * info)
@@ -5203,7 +5202,7 @@
}
avifBool isLimitedRangeAlpha = AVIF_FALSE;
- if (!tile->codec->getNextImage(tile->codec, decoder, sample, tile->input->itemCategory == AVIF_ITEM_ALPHA, &isLimitedRangeAlpha, tile->image)) {
+ if (!tile->codec->getNextImage(tile->codec, decoder, sample, avifIsAlpha(tile->input->itemCategory), &isLimitedRangeAlpha, tile->image)) {
avifDiagnosticsPrintf(&decoder->diag, "tile->codec->getNextImage() failed");
return avifGetErrorForItemCategory(tile->input->itemCategory);
}
@@ -5231,7 +5230,7 @@
// of the specification. However, it was allowed in version 1.0.0 of the
// specification. To allow such files, simply convert the alpha plane to
// full range.
- if ((tile->input->itemCategory == AVIF_ITEM_ALPHA) && isLimitedRangeAlpha) {
+ if (avifIsAlpha(tile->input->itemCategory) && isLimitedRangeAlpha) {
avifResult result = avifImageLimitedToFullAlpha(tile->image);
if (result != AVIF_RESULT_OK) {
avifDiagnosticsPrintf(&decoder->diag, "avifImageLimitedToFullAlpha failed");
@@ -5283,7 +5282,7 @@
default:
if ((decoder->image->width != src->width) || (decoder->image->height != src->height) ||
(decoder->image->depth != src->depth)) {
- if (tile->input->itemCategory == AVIF_ITEM_ALPHA) {
+ if (avifIsAlpha(tile->input->itemCategory)) {
avifDiagnosticsPrintf(&decoder->diag,
"The color image item does not match the alpha image item in width, height, or bit depth");
return AVIF_RESULT_DECODE_ALPHA_FAILED;
@@ -5297,7 +5296,7 @@
break;
}
- if (tile->input->itemCategory == AVIF_ITEM_ALPHA) {
+ if (avifIsAlpha(tile->input->itemCategory)) {
avifImageStealPlanes(decoder->image, src, AVIF_PLANES_A);
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
} else if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
diff --git a/src/write.c b/src/write.c
index 9cbe1f8..f7f510c 100644
--- a/src/write.c
+++ b/src/write.c
@@ -1115,7 +1115,7 @@
uint16_t * topLevelItemID)
{
const uint32_t cellCount = gridCols * gridRows;
- const char * infeName = (itemCategory == AVIF_ITEM_ALPHA) ? infeNameAlpha
+ const char * infeName = avifIsAlpha(itemCategory) ? infeNameAlpha
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
: (itemCategory == AVIF_ITEM_GAIN_MAP) ? infeNameGainMap
#endif
@@ -1192,7 +1192,12 @@
static avifResult avifGetErrorForItemCategory(avifItemCategory itemCategory)
{
- return (itemCategory == AVIF_ITEM_ALPHA) ? AVIF_RESULT_ENCODE_ALPHA_FAILED : AVIF_RESULT_ENCODE_COLOR_FAILED;
+#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
+ if (itemCategory == AVIF_ITEM_GAIN_MAP) {
+ return AVIF_RESULT_ENCODE_GAIN_MAP_FAILED;
+ }
+#endif
+ return avifIsAlpha(itemCategory) ? AVIF_RESULT_ENCODE_ALPHA_FAILED : AVIF_RESULT_ENCODE_COLOR_FAILED;
}
static avifResult avifValidateImageBasicProperties(const avifImage * avifImage)
@@ -1662,7 +1667,9 @@
}
cellImage = paddedCellImage;
}
- const int quantizer = (item->itemCategory == AVIF_ITEM_ALPHA) ? encoder->data->quantizerAlpha
+
+ const avifBool isAlpha = avifIsAlpha(item->itemCategory);
+ const int quantizer = isAlpha ? encoder->data->quantizerAlpha
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
: (item->itemCategory == AVIF_ITEM_GAIN_MAP) ? encoder->data->quantizerGainMap
#endif
@@ -1673,7 +1680,7 @@
avifResult encodeResult = item->codec->encodeImage(item->codec,
encoder,
cellImage,
- item->itemCategory == AVIF_ITEM_ALPHA,
+ isAlpha,
encoder->data->tileRowsLog2,
encoder->data->tileColsLog2,
quantizer,
@@ -1780,10 +1787,12 @@
// only process metadata (XMP/Exif) payloads when metadataPass is true
continue;
}
- avifBool isAlphaOrGainMap = item->itemCategory == AVIF_ITEM_ALPHA;
+ const avifBool isAlpha = avifIsAlpha(item->itemCategory);
+ const avifBool isAlphaOrGainMap = isAlpha
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
- isAlphaOrGainMap = isAlphaOrGainMap || item->itemCategory == AVIF_ITEM_GAIN_MAP;
+ || item->itemCategory == AVIF_ITEM_GAIN_MAP
#endif
+ ;
if (alphaAndGainMapPass != isAlphaOrGainMap) {
// only process alpha payloads when alphaPass is true
continue;
@@ -1794,8 +1803,7 @@
// We always interleave all AV1 items for layered images.
AVIF_ASSERT_OR_RETURN(item->encodeOutput->samples.count == item->mdatFixups.count);
- avifEncoderItemReference * ref = (item->itemCategory == AVIF_ITEM_ALPHA) ? avifArrayPush(layeredAlphaItems)
- : avifArrayPush(layeredColorItems);
+ avifEncoderItemReference * ref = avifArrayPush(isAlpha ? layeredAlphaItems : layeredColorItems);
AVIF_CHECKERR(ref != NULL, AVIF_RESULT_OUT_OF_MEMORY);
*ref = item;
continue;
@@ -1820,7 +1828,7 @@
avifEncodeSample * sample = &item->encodeOutput->samples.sample[sampleIndex];
AVIF_CHECKRES(avifRWStreamWrite(s, sample->data.data, sample->data.size));
- if (item->itemCategory == AVIF_ITEM_ALPHA) {
+ if (isAlpha) {
encoder->ioStats.alphaOBUSize += sample->data.size;
} else if (item->itemCategory == AVIF_ITEM_COLOR) {
encoder->ioStats.colorOBUSize += sample->data.size;
@@ -2254,7 +2262,7 @@
imageHeight = item->gridHeight;
}
- // Properties all image items need
+ // Properties all image items need (coded and derived)
// ispe = image spatial extent (width, height)
avifItemPropertyDedupStart(dedup);
avifBoxMarker ispe;
@@ -2272,15 +2280,16 @@
hasPixi = AVIF_FALSE;
}
#endif
+ const avifBool isAlpha = avifIsAlpha(item->itemCategory);
+ const uint8_t depth = (uint8_t)itemMetadata->depth;
if (hasPixi) {
avifItemPropertyDedupStart(dedup);
- uint8_t channelCount =
- (item->itemCategory == AVIF_ITEM_ALPHA || (itemMetadata->yuvFormat == AVIF_PIXEL_FORMAT_YUV400)) ? 1 : 3;
+ uint8_t channelCount = (isAlpha || (itemMetadata->yuvFormat == AVIF_PIXEL_FORMAT_YUV400)) ? 1 : 3;
avifBoxMarker pixi;
AVIF_CHECKRES(avifRWStreamWriteFullBox(&dedup->s, "pixi", AVIF_BOX_SIZE_TBD, 0, 0, &pixi));
AVIF_CHECKRES(avifRWStreamWriteU8(&dedup->s, channelCount)); // unsigned int (8) num_channels;
for (uint8_t chan = 0; chan < channelCount; ++chan) {
- AVIF_CHECKRES(avifRWStreamWriteU8(&dedup->s, (uint8_t)itemMetadata->depth)); // unsigned int (8) bits_per_channel;
+ AVIF_CHECKRES(avifRWStreamWriteU8(&dedup->s, depth)); // unsigned int (8) bits_per_channel;
}
avifRWStreamFinishBox(&dedup->s, pixi);
AVIF_CHECKRES(avifItemPropertyDedupFinish(dedup, s, &item->ipma, AVIF_FALSE));
@@ -2293,7 +2302,7 @@
AVIF_CHECKRES(avifItemPropertyDedupFinish(dedup, s, &item->ipma, AVIF_TRUE));
}
- if (item->itemCategory == AVIF_ITEM_ALPHA) {
+ if (isAlpha) {
// Alpha specific properties
avifItemPropertyDedupStart(dedup);