Commit faf167c5 authored by Joe Drago's avatar Joe Drago
Browse files

Refactor imir implementation to match HEIF Draft Amendment 2, which replaces...

Refactor imir implementation to match HEIF Draft Amendment 2, which replaces 'axis' with 'mode' and inverts the behavior
No related merge requests found
Showing with 28 additions and 20 deletions
+28 -20
......@@ -103,7 +103,7 @@ static void syntax(void)
printf(" --crop CROPX,CROPY,CROPW,CROPH : Add clap property (clean aperture), but calculated from a crop rectangle\n");
printf(" --clap WN,WD,HN,HD,HON,HOD,VON,VOD: Add clap property (clean aperture). Width, Height, HOffset, VOffset (in num/denom pairs)\n");
printf(" --irot ANGLE : Add irot property (rotation). [0-3], makes (90 * ANGLE) degree rotation anti-clockwise\n");
printf(" --imir AXIS : Add imir property (mirroring). 0=vertical axis (\"left-to-right\"), 1=horizontal axis (\"top-to-bottom\")\n");
printf(" --imir MODE : Add imir property (mirroring). 0=top-to-bottom, 1=left-to-right\n");
printf("\n");
if (avifCodecName(AVIF_CODEC_CHOICE_AOM, 0)) {
printf("aom-specific advanced options:\n");
......@@ -439,7 +439,7 @@ int main(int argc, char * argv[])
uint32_t clapValues[8];
avifBool cropConversionRequired = AVIF_FALSE;
uint8_t irotAngle = 0xff; // sentinel value indicating "unused"
uint8_t imirAxis = 0xff; // sentinel value indicating "unused"
uint8_t imirMode = 0xff; // sentinel value indicating "unused"
avifCodecChoice codecChoice = AVIF_CODEC_CHOICE_AUTO;
avifRange requestedRange = AVIF_RANGE_FULL;
avifBool lossless = AVIF_FALSE;
......@@ -729,9 +729,9 @@ int main(int argc, char * argv[])
}
} else if (!strcmp(arg, "--imir")) {
NEXTARG();
imirAxis = (uint8_t)atoi(arg);
if (imirAxis > 1) {
fprintf(stderr, "ERROR: Invalid imir axis: %s\n", arg);
imirMode = (uint8_t)atoi(arg);
if (imirMode > 1) {
fprintf(stderr, "ERROR: Invalid imir mode: %s\n", arg);
returnCode = 1;
goto cleanup;
}
......@@ -909,9 +909,9 @@ int main(int argc, char * argv[])
image->transformFlags |= AVIF_TRANSFORM_IROT;
image->irot.angle = irotAngle;
}
if (imirAxis != 0xff) {
if (imirMode != 0xff) {
image->transformFlags |= AVIF_TRANSFORM_IMIR;
image->imir.axis = imirAxis;
image->imir.mode = imirMode;
}
avifBool usingAOM = AVIF_FALSE;
......
......@@ -99,9 +99,7 @@ static void avifImageDumpInternal(avifImage * avif, uint32_t gridCols, uint32_t
printf(" * irot (Rotation) : %u\n", avif->irot.angle);
}
if (avif->transformFlags & AVIF_TRANSFORM_IMIR) {
printf(" * imir (Mirror) : %u (%s)\n",
avif->imir.axis,
(avif->imir.axis == 0) ? "Vertical axis, \"left-to-right\"" : "Horizontal axis, \"top-to-bottom\"");
printf(" * imir (Mirror) : Mode %u (%s)\n", avif->imir.mode, (avif->imir.mode == 0) ? "top-to-bottom" : "left-to-right");
}
}
}
......
......@@ -360,14 +360,24 @@ typedef struct avifImageRotation
typedef struct avifImageMirror
{
// 'imir' from ISO/IEC 23008-12:2017 6.5.12:
// "axis specifies a vertical (axis = 0) or horizontal (axis = 1) axis for the mirroring operation."
// 'imir' from ISO/IEC 23008-12:2017 6.5.12 (Draft Amendment 2):
//
// 'mode' specifies how the mirroring is performed:
//
// 0 indicates that the top and bottom parts of the image are exchanged;
// 1 specifies that the left and right parts are exchanged.
//
// NOTE In Exif, orientation tag can be used to signal mirroring operations. Exif
// orientation tag 4 corresponds to mode = 0 of ImageMirror, and Exif orientation tag 2
// corresponds to mode = 1 accordingly.
//
// Legal values: [0, 1]
//
// 0: Mirror about a vertical axis ("left-to-right")
// 1: Mirror about a horizontal axis ("top-to-bottom")
uint8_t axis;
// NOTE: As of HEIF Draft Amendment 2, the name of this variable has changed from 'axis' to 'mode' as
// the logic behind it has been *inverted*. Please use the wording above describing the legal
// values for 'mode' and update any code that previously may have used `axis` to use
// the *opposite* value (0 now means top-to-bottom, where it used to mean left-to-right).
uint8_t mode;
} avifImageMirror;
// ---------------------------------------------------------------------------
......
......@@ -1553,10 +1553,10 @@ static avifBool avifParseImageMirrorProperty(avifProperty * prop, const uint8_t
BEGIN_STREAM(s, raw, rawLen, diag, "Box[imir]");
avifImageMirror * imir = &prop->u.imir;
CHECK(avifROStreamRead(&s, &imir->axis, 1)); // unsigned int (7) reserved = 0; unsigned int (1) axis;
if ((imir->axis & 0xfe) != 0) {
CHECK(avifROStreamRead(&s, &imir->mode, 1)); // unsigned int (7) reserved = 0; unsigned int (1) mode;
if ((imir->mode & 0xfe) != 0) {
// reserved bits must be 0
avifDiagnosticsPrintf(diag, "Box[imir] contains nonzero reserved bits [%u]", imir->axis);
avifDiagnosticsPrintf(diag, "Box[imir] contains nonzero reserved bits [%u]", imir->mode);
return AVIF_FALSE;
}
return AVIF_TRUE;
......
......@@ -275,8 +275,8 @@ static void avifEncoderWriteColorProperties(avifRWStream * s, const avifImage *
}
if (imageMetadata->transformFlags & AVIF_TRANSFORM_IMIR) {
avifBoxMarker imir = avifRWStreamWriteBox(s, "imir", AVIF_BOX_SIZE_TBD);
uint8_t axis = imageMetadata->imir.axis & 0x1;
avifRWStreamWrite(s, &axis, 1); // unsigned int (7) reserved = 0; unsigned int (1) axis;
uint8_t mode = imageMetadata->imir.mode & 0x1;
avifRWStreamWrite(s, &mode, 1); // unsigned int (7) reserved = 0; unsigned int (1) mode;
avifRWStreamFinishBox(s, imir);
if (ipma && itemPropertyIndex) {
ipmaPush(ipma, ++(*itemPropertyIndex), AVIF_TRUE);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment