Skip to content

Commit

Permalink
Update MinimizedItemBox experimental prototype (#2114)
Browse files Browse the repository at this point in the history
Split is_centered into is_horizontally_centered and
is_vertically_centered.
Read alpha_item_codec_config_size after alpha_item_data_size.
Skip writing compatible_brands to save 4 bytes.
  • Loading branch information
y-guyon authored Apr 15, 2024
1 parent 6c2ad21 commit 7cb941b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 52 deletions.
52 changes: 29 additions & 23 deletions src/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -3583,7 +3583,7 @@ static avifResult avifParseMinimizedImageBox(avifMeta * meta, uint64_t rawOffset
// TODO(yguyon): Implement or return an appropriate error in cases where AVIF_RESULT_NOT_IMPLEMENTED is returned.

uint32_t version;
AVIF_CHECKERR(avifROStreamReadBits(&s, &version, 2), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(2) version;
AVIF_CHECKERR(avifROStreamReadBits(&s, &version, 2), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(2) version;
AVIF_CHECKERR(version == 0, AVIF_RESULT_NOT_IMPLEMENTED);

uint32_t width, height;
Expand All @@ -3595,30 +3595,34 @@ static avifResult avifParseMinimizedImageBox(avifMeta * meta, uint64_t rawOffset
++height;

uint32_t isFloat;
AVIF_CHECKERR(avifROStreamReadBits(&s, &isFloat, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) is_float;
AVIF_CHECKERR(avifROStreamReadBits(&s, &isFloat, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) is_float;
if (isFloat) {
// unsigned int(2) float_precision;
// bit(2) float_precision;
return AVIF_RESULT_NOT_IMPLEMENTED;
}
uint32_t bitDepth;
AVIF_CHECKERR(avifROStreamReadBits(&s, &bitDepth, 4), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) bit_depth_minus_one;
AVIF_CHECKERR(avifROStreamReadBits(&s, &bitDepth, 4), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) bit_depth_minus_one;
++bitDepth;
AVIF_CHECKERR((bitDepth == 8) || (bitDepth == 10) || (bitDepth == 12), AVIF_RESULT_UNSUPPORTED_DEPTH);
uint32_t subsampling;
AVIF_CHECKERR(avifROStreamReadBits(&s, &subsampling, 2), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(2) subsampling;
AVIF_CHECKERR(avifROStreamReadBits(&s, &subsampling, 2), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(2) subsampling;
const avifPixelFormat yuvFormat = subsampling == 0 ? AVIF_PIXEL_FORMAT_YUV400 : (avifPixelFormat)subsampling;
const avifBool isMonochrome = yuvFormat == AVIF_PIXEL_FORMAT_YUV400;
const avifBool isSubsampled = yuvFormat == AVIF_PIXEL_FORMAT_YUV422 || yuvFormat == AVIF_PIXEL_FORMAT_YUV420;
avifChromaSamplePosition yuvChromaSamplePosition = AVIF_CHROMA_SAMPLE_POSITION_UNKNOWN;
if (isSubsampled) {
uint32_t isCentered;
AVIF_CHECKERR(avifROStreamReadBits(&s, &isCentered, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) is_centered;
yuvChromaSamplePosition = isCentered ? AVIF_CHROMA_SAMPLE_POSITION_VERTICAL : AVIF_CHROMA_SAMPLE_POSITION_COLOCATED;
if (yuvFormat == AVIF_PIXEL_FORMAT_YUV422 || yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
uint32_t isHorizontallyCentered;
AVIF_CHECKERR(avifROStreamReadBits(&s, &isHorizontallyCentered, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) is_horizontally_centered;
AVIF_CHECKERR(!isHorizontallyCentered, AVIF_RESULT_NOT_IMPLEMENTED);
}
if (yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
uint32_t isVerticallyCentered;
AVIF_CHECKERR(avifROStreamReadBits(&s, &isVerticallyCentered, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) is_vertically_centered;
yuvChromaSamplePosition = isVerticallyCentered ? AVIF_CHROMA_SAMPLE_POSITION_VERTICAL : AVIF_CHROMA_SAMPLE_POSITION_COLOCATED;
}
uint32_t fullRange;
AVIF_CHECKERR(avifROStreamReadBits(&s, &fullRange, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) full_range;
AVIF_CHECKERR(avifROStreamReadBits(&s, &fullRange, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) full_range;
uint32_t colorType;
AVIF_CHECKERR(avifROStreamReadBits(&s, &colorType, 2), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(2) color_type;
AVIF_CHECKERR(avifROStreamReadBits(&s, &colorType, 2), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(2) color_type;
uint32_t colorPrimaries;
uint32_t transferCharacteristics;
uint32_t matrixCoefficients;
Expand All @@ -3629,7 +3633,7 @@ static avifResult avifParseMinimizedImageBox(avifMeta * meta, uint64_t rawOffset
if (isMonochrome) {
matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED;
} else {
AVIF_CHECKERR(avifROStreamReadBits(&s, &matrixCoefficients, 8), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(8) matrix_coefficients;
AVIF_CHECKERR(avifROStreamReadBits(&s, &matrixCoefficients, 8), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(8) matrix_coefficients;
}
AVIF_CHECKERR(avifROStreamReadVarInt(&s, &iccDataSize), AVIF_RESULT_BMFF_PARSE_FAILED); // varint icc_data_size_minus_one;
AVIF_CHECKERR(iccDataSize != UINT32_MAX, AVIF_RESULT_BMFF_PARSE_FAILED);
Expand All @@ -3643,20 +3647,20 @@ static avifResult avifParseMinimizedImageBox(avifMeta * meta, uint64_t rawOffset
} else {
const uint32_t numBitsPerComponent = (colorType == AVIF_MINI_COLOR_TYPE_NCLX_5BIT) ? 5 : 8;
AVIF_CHECKERR(avifROStreamReadBits(&s, &colorPrimaries, numBitsPerComponent),
AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(5/8) color_primaries;
AVIF_RESULT_BMFF_PARSE_FAILED); // bit(5/8) color_primaries;
AVIF_CHECKERR(avifROStreamReadBits(&s, &transferCharacteristics, numBitsPerComponent),
AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(5/8) transfer_characteristics;
AVIF_RESULT_BMFF_PARSE_FAILED); // bit(5/8) transfer_characteristics;
if (isMonochrome) {
matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED;
} else {
AVIF_CHECKERR(avifROStreamReadBits(&s, &matrixCoefficients, numBitsPerComponent),
AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(5/8) matrix_coefficients;
AVIF_RESULT_BMFF_PARSE_FAILED); // bit(5/8) matrix_coefficients;
}
iccDataSize = 0;
}

uint32_t hasExplicitCodecTypes;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExplicitCodecTypes, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) has_explicit_codec_types;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExplicitCodecTypes, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) has_explicit_codec_types;
if (hasExplicitCodecTypes) {
// unsigned int(32) infe_type;
// unsigned int(32) codec_config_type;
Expand All @@ -3672,30 +3676,32 @@ static avifResult avifParseMinimizedImageBox(avifMeta * meta, uint64_t rawOffset
uint32_t hasAlpha;
uint32_t alphaIsPremultiplied = AVIF_FALSE;
uint32_t alphaItemDataSize = 0;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasAlpha, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) has_alpha;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasAlpha, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) has_alpha;
if (hasAlpha) {
AVIF_CHECKERR(avifROStreamReadBits(&s, &alphaIsPremultiplied, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) alpha_is_premultiplied;
AVIF_CHECKERR(avifROStreamReadBits(&s, &alphaIsPremultiplied, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) alpha_is_premultiplied;
AVIF_CHECKERR(avifROStreamReadVarInt(&s, &alphaItemDataSize), AVIF_RESULT_BMFF_PARSE_FAILED); // varint alpha_item_data_size;
const avifBool hasSeparateAlphaItem = alphaItemDataSize != 0;
AVIF_CHECKERR(hasSeparateAlphaItem, AVIF_RESULT_NOT_IMPLEMENTED); // AV1 does not support a built-in alpha channel in the main item.
uint32_t alphaItemCodecConfigSize;
AVIF_CHECKERR(avifROStreamReadVarInt(&s, &alphaItemCodecConfigSize), AVIF_RESULT_BMFF_PARSE_FAILED); // varint alpha_item_codec_config_size;
AVIF_CHECKERR(alphaItemCodecConfigSize == 4, AVIF_RESULT_NOT_IMPLEMENTED);
AVIF_CHECKERR(avifROStreamReadVarInt(&s, &alphaItemDataSize), AVIF_RESULT_BMFF_PARSE_FAILED); // varint alpha_item_data_size;
}

uint32_t hasExtendedMeta, hasExif, hasXMP;
uint32_t extendedMetaSize = 0, exifSize = 0, xmpSize = 0;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExtendedMeta, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) has_extended_meta;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExtendedMeta, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) has_extended_meta;
if (hasExtendedMeta) {
AVIF_CHECKERR(avifROStreamReadVarInt(&s, &extendedMetaSize), AVIF_RESULT_BMFF_PARSE_FAILED); // varint extended_meta_size_minus_one;
AVIF_CHECKERR(extendedMetaSize != UINT32_MAX, AVIF_RESULT_BMFF_PARSE_FAILED);
++extendedMetaSize;
}
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExif, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) has_exif;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasExif, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) has_exif;
if (hasExif) {
AVIF_CHECKERR(avifROStreamReadVarInt(&s, &exifSize), AVIF_RESULT_BMFF_PARSE_FAILED); // varint exif_data_size_minus_one;
AVIF_CHECKERR(exifSize != UINT32_MAX, AVIF_RESULT_BMFF_PARSE_FAILED);
++exifSize;
}
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasXMP, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(1) has_xmp;
AVIF_CHECKERR(avifROStreamReadBits(&s, &hasXMP, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) has_xmp;
if (hasXMP) {
AVIF_CHECKERR(avifROStreamReadVarInt(&s, &xmpSize), AVIF_RESULT_BMFF_PARSE_FAILED); // varint xmp_data_size_minus_one;
AVIF_CHECKERR(xmpSize != UINT32_MAX, AVIF_RESULT_BMFF_PARSE_FAILED);
Expand Down
62 changes: 33 additions & 29 deletions src/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -2376,7 +2376,7 @@ static avifResult avifEncoderWriteFileTypeBoxAndMinimizedImageBox(avifEncoder *
AVIF_CHECKRES(avifRWStreamWriteBox(&s, "ftyp", AVIF_BOX_SIZE_TBD, &ftyp));
AVIF_CHECKRES(avifRWStreamWriteChars(&s, "mif3", 4)); // unsigned int(32) major_brand;
AVIF_CHECKRES(avifRWStreamWriteU32(&s, 0)); // unsigned int(32) minor_version;
AVIF_CHECKRES(avifRWStreamWriteChars(&s, "mif3", 4)); // unsigned int(32) compatible_brands[];
// unsigned int(32) compatible_brands[];
avifRWStreamFinishBox(&s, ftyp);

avifRWData extendedMeta = AVIF_DATA_EMPTY;
Expand Down Expand Up @@ -2411,71 +2411,75 @@ static avifResult avifEncoderWriteMinimizedImageBox(avifEncoder * encoder, avifR
const avifImage * const image = encoder->data->imageMetadata;

const avifBool isMonochrome = image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400;
const avifBool isSubsampled = image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422 || image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420;
const avifBool fullRange = image->yuvRange == AVIF_RANGE_FULL;

avifBoxMarker mini;
AVIF_CHECKRES(avifRWStreamWriteBox(s, "mini", AVIF_BOX_SIZE_TBD, &mini));
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 2)); // unsigned int(2) version;
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 2)); // bit(2) version;

AVIF_CHECKRES(avifRWStreamWriteVarInt(s, image->width - 1)); // varint width_minus_one;
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, image->height - 1)); // varint height_minus_one;

AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 1)); // unsigned int(1) is_float;
// unsigned int(2) float_precision;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->depth - 1, 4)); // unsigned int(4) bit_depth_minus_one;
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 1)); // bit(1) is_float;
// bit(2) float_precision;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->depth - 1, 4)); // bit(4) bit_depth_minus_one;
if (isMonochrome) {
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 2)); // unsigned int(2) subsampling;
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 2)); // bit(2) subsampling;
} else {
AVIF_CHECKRES(avifRWStreamWriteBits(s, (uint32_t)image->yuvFormat, 2)); // unsigned int(2) subsampling;
}
if (isSubsampled) {
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->yuvChromaSamplePosition == AVIF_CHROMA_SAMPLE_POSITION_VERTICAL ? 1 : 0, 1)); // unsigned int(1) is_centered;
AVIF_CHECKRES(avifRWStreamWriteBits(s, (uint32_t)image->yuvFormat, 2)); // bit(2) subsampling;
if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422 || image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 1)); // bit(1) is_horizontally_centered;
}
if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
const uint32_t isVerticallyCentered = image->yuvChromaSamplePosition == AVIF_CHROMA_SAMPLE_POSITION_VERTICAL ? 1 : 0;
AVIF_CHECKRES(avifRWStreamWriteBits(s, isVerticallyCentered, 1)); // bit(1) is_vertically_centered;
}
}
AVIF_CHECKRES(avifRWStreamWriteBits(s, fullRange, 1)); // unsigned int(1) full_range;
AVIF_CHECKRES(avifRWStreamWriteBits(s, fullRange, 1)); // bit(1) full_range;
if (image->icc.size) {
AVIF_CHECKRES(avifRWStreamWriteBits(s, AVIF_MINI_COLOR_TYPE_ICC, 2)); // unsigned int(2) color_type;
AVIF_CHECKRES(avifRWStreamWriteBits(s, AVIF_MINI_COLOR_TYPE_ICC, 2)); // bit(2) color_type;
AVIF_CHECKERR(image->colorPrimaries == AVIF_COLOR_PRIMARIES_UNSPECIFIED, AVIF_RESULT_INVALID_ARGUMENT);
AVIF_CHECKERR(image->transferCharacteristics == AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED, AVIF_RESULT_INVALID_ARGUMENT);
if (isMonochrome) {
AVIF_CHECKERR(image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED, AVIF_RESULT_INVALID_ARGUMENT);
} else {
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->matrixCoefficients, 8)); // unsigned int(8) matrix_coefficients;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->matrixCoefficients, 8)); // bit(8) matrix_coefficients;
}
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, (uint32_t)image->icc.size - 1)); // varint icc_data_size_minus_one;
} else {
if (image->colorPrimaries == AVIF_COLOR_PRIMARIES_SRGB && image->transferCharacteristics == AVIF_TRANSFER_CHARACTERISTICS_SRGB &&
(image->matrixCoefficients == (isMonochrome ? AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED : AVIF_MATRIX_COEFFICIENTS_BT601))) {
AVIF_CHECKRES(avifRWStreamWriteBits(s, AVIF_MINI_COLOR_TYPE_SRGB, 2)); // unsigned int(2) color_type;
AVIF_CHECKRES(avifRWStreamWriteBits(s, AVIF_MINI_COLOR_TYPE_SRGB, 2)); // bit(2) color_type;
} else {
const avifMiniColorType colorType = ((image->colorPrimaries >> 5 == 0) && (image->transferCharacteristics >> 5 == 0) &&
(image->matrixCoefficients >> 5 == 0))
? AVIF_MINI_COLOR_TYPE_NCLX_5BIT
: AVIF_MINI_COLOR_TYPE_NCLX_8BIT;
const uint32_t numBitsPerComponent = (colorType == AVIF_MINI_COLOR_TYPE_NCLX_5BIT) ? 5 : 8;
AVIF_CHECKRES(avifRWStreamWriteBits(s, colorType, 2)); // unsigned int(2) color_type;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->colorPrimaries, numBitsPerComponent)); // unsigned int(5/8) color_primaries;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->transferCharacteristics, numBitsPerComponent)); // unsigned int(5/8) transfer_characteristics;
AVIF_CHECKRES(avifRWStreamWriteBits(s, colorType, 2)); // bit(2) color_type;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->colorPrimaries, numBitsPerComponent)); // bit(5/8) color_primaries;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->transferCharacteristics, numBitsPerComponent)); // bit(5/8) transfer_characteristics;
if (isMonochrome) {
AVIF_CHECKERR(image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED, AVIF_RESULT_INVALID_ARGUMENT);
} else {
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->matrixCoefficients, numBitsPerComponent)); // unsigned int(5/8) matrix_coefficients;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->matrixCoefficients, numBitsPerComponent)); // bit(5/8) matrix_coefficients;
}
}
}

AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 1)); // unsigned int(1) has_explicit_codec_types;
// unsigned int(32) infe_type;
// unsigned int(32) codec_config_type;
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 1)); // bit(1) has_explicit_codec_types;
// bit(32) infe_type;
// bit(32) codec_config_type;
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, 4)); // varint main_item_codec_config_size;
AVIF_ASSERT_OR_RETURN(colorData->size >= 1);
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, (uint32_t)colorData->size - 1)); // varint main_item_data_size_minus_one;

AVIF_CHECKRES(avifRWStreamWriteBits(s, alphaItem ? 1 : 0, 1)); // unsigned int(1) has_alpha;
AVIF_CHECKRES(avifRWStreamWriteBits(s, alphaItem ? 1 : 0, 1)); // bit(1) has_alpha;
if (alphaItem) {
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->alphaPremultiplied, 1)); // unsigned int(1) alpha_is_premultiplied;
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, 4)); // varint alpha_item_codec_config_size;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->alphaPremultiplied, 1)); // bit(1) alpha_is_premultiplied;
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, (uint32_t)alphaData->size)); // varint alpha_item_data_size;
AVIF_ASSERT_OR_RETURN(alphaData->size != 0);
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, 4)); // varint alpha_item_codec_config_size;
}

if (image->clli.maxCLL || image->clli.maxPALL || (image->transformFlags != AVIF_TRANSFORM_NONE)) {
Expand All @@ -2484,22 +2488,22 @@ static avifResult avifEncoderWriteMinimizedImageBox(avifEncoder * encoder, avifR
AVIF_CHECKRES(avifImageWriteExtendedMeta(image, &extendedMetaStream));
avifRWStreamFinishWrite(&extendedMetaStream);
}
AVIF_CHECKRES(avifRWStreamWriteBits(s, extendedMeta->size ? 1 : 0, 1)); // unsigned int(1) has_extended_meta;
AVIF_CHECKRES(avifRWStreamWriteBits(s, extendedMeta->size ? 1 : 0, 1)); // bit(1) has_extended_meta;
if (extendedMeta->size) {
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, (uint32_t)extendedMeta->size - 1)); // varint extended_meta_size_minus_one;
}

AVIF_CHECKRES(avifRWStreamWriteBits(s, image->exif.size ? 1 : 0, 1)); // unsigned int(1) has_exif;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->exif.size ? 1 : 0, 1)); // bit(1) has_exif;
if (image->exif.size) {
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, (uint32_t)image->exif.size - 1)); // varint exif_data_size_minus_one;
}
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->xmp.size ? 1 : 0, 1)); // unsigned int(1) has_xmp;
AVIF_CHECKRES(avifRWStreamWriteBits(s, image->xmp.size ? 1 : 0, 1)); // bit(1) has_xmp;
if (image->xmp.size) {
AVIF_CHECKRES(avifRWStreamWriteVarInt(s, (uint32_t)image->xmp.size - 1)); // varint xmp_data_size_minus_one;
}

// Padding to align with whole bytes if necessary.
if (s->numUsedBitsInPartialByte) {
if (s->numUsedBitsInPartialByte != 0) {
AVIF_CHECKRES(avifRWStreamWriteBits(s, 0, 8 - s->numUsedBitsInPartialByte));
}

Expand Down

0 comments on commit 7cb941b

Please sign in to comment.