Move some Exif functions to apps/shared/avifexif
So that the avif_apps target does not depend on avif_internal.
Fix avifSetExifOrientation() comment.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5fbea3f..2a8b8cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -504,10 +504,10 @@
find_package(JPEG REQUIRED)
add_library(
- avif_apps STATIC apps/shared/avifjpeg.c apps/shared/iccjpeg.c apps/shared/avifpng.c apps/shared/avifutil.c
- apps/shared/y4m.c
+ avif_apps STATIC apps/shared/avifexif.c apps/shared/avifjpeg.c apps/shared/iccjpeg.c apps/shared/avifpng.c
+ apps/shared/avifutil.c apps/shared/y4m.c
)
- target_link_libraries(avif_apps avif_internal ${AVIF_PLATFORM_LIBRARIES} ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${JPEG_LIBRARY})
+ target_link_libraries(avif_apps avif ${AVIF_PLATFORM_LIBRARIES} ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${JPEG_LIBRARY})
# In GitHub CI's macos-latest os image, /usr/local/include has not only the headers of libpng
# libjpeg but also the headers of an older version of libavif. Put the avif include directory
# before ${PNG_PNG_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} to prevent picking up old libavif headers
diff --git a/README.md b/README.md
index 77b5dc2..b1a9c81 100644
--- a/README.md
+++ b/README.md
@@ -76,9 +76,9 @@
```sh
clang-format -style=file -i \
- apps/*.c apps/shared/avifjpeg.* apps/shared/avifpng.* \
- apps/shared/avifutil.* apps/shared/y4m.* examples/*.c \
- include/avif/*.h src/*.c tests/*.c \
+ apps/*.c apps/shared/avifexif.* apps/shared/avifjpeg.* \
+ apps/shared/avifpng.* apps/shared/avifutil.* apps/shared/y4m.* \
+ examples/*.c include/avif/*.h src/*.c tests/*.c \
tests/gtest/*.h tests/gtest/*.cc tests/oss-fuzz/*.cc
```
diff --git a/apps/shared/avifexif.c b/apps/shared/avifexif.c
new file mode 100644
index 0000000..626a244
--- /dev/null
+++ b/apps/shared/avifexif.c
@@ -0,0 +1,63 @@
+// Copyright 2022 Google LLC
+// SPDX-License-Identifier: BSD-2-Clause
+
+#include "avifexif.h"
+#include "avif/avif.h"
+
+uint8_t avifImageGetExifOrientationFromIrotImir(const avifImage * image)
+{
+ if ((image->transformFlags & AVIF_TRANSFORM_IROT) && (image->irot.angle == 1)) {
+ if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
+ if (image->imir.mode) {
+ return 7; // 90 degrees anti-clockwise then swap left and right.
+ }
+ return 5; // 90 degrees anti-clockwise then swap top and bottom.
+ }
+ return 6; // 90 degrees anti-clockwise.
+ }
+ if ((image->transformFlags & AVIF_TRANSFORM_IROT) && (image->irot.angle == 2)) {
+ if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
+ if (image->imir.mode) {
+ return 4; // 180 degrees anti-clockwise then swap left and right.
+ }
+ return 2; // 180 degrees anti-clockwise then swap top and bottom.
+ }
+ return 3; // 180 degrees anti-clockwise.
+ }
+ if ((image->transformFlags & AVIF_TRANSFORM_IROT) && (image->irot.angle == 3)) {
+ if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
+ if (image->imir.mode) {
+ return 5; // 270 degrees anti-clockwise then swap left and right.
+ }
+ return 7; // 270 degrees anti-clockwise then swap top and bottom.
+ }
+ return 8; // 270 degrees anti-clockwise.
+ }
+ if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
+ if (image->imir.mode) {
+ return 2; // Swap left and right.
+ }
+ return 4; // Swap top and bottom.
+ }
+ return 1; // Default orientation ("top-left", no-op).
+}
+
+avifResult avifSetExifOrientation(avifRWData * exif, uint8_t orientation)
+{
+ size_t offset;
+ const avifResult result = avifGetExifOrientationOffset(exif->data, exif->size, &offset);
+ if (result != AVIF_RESULT_OK) {
+ return result;
+ }
+ if (offset < exif->size) {
+ exif->data[offset] = orientation;
+ return AVIF_RESULT_OK;
+ }
+ // No Exif orientation was found.
+ if (orientation == 1) {
+ // The default orientation is 1, so if the given orientation is 1 too, do nothing.
+ return AVIF_RESULT_OK;
+ }
+ // Adding an orientation tag to an Exif payload is involved.
+ return AVIF_RESULT_NOT_IMPLEMENTED;
+}
diff --git a/apps/shared/avifexif.h b/apps/shared/avifexif.h
new file mode 100644
index 0000000..0c99a61
--- /dev/null
+++ b/apps/shared/avifexif.h
@@ -0,0 +1,23 @@
+// Copyright 2022 Google LLC
+// SPDX-License-Identifier: BSD-2-Clause
+
+#ifndef LIBAVIF_APPS_SHARED_AVIFEXIF_H
+#define LIBAVIF_APPS_SHARED_AVIFEXIF_H
+
+#include "avif/avif.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Converts image->transformFlags, image->irot and image->imir to the equivalent Exif orientation value in [1:8].
+uint8_t avifImageGetExifOrientationFromIrotImir(const avifImage * image);
+
+// Attempts to parse the Exif payload until the orientation is found, then sets it to the given value.
+avifResult avifSetExifOrientation(avifRWData * exif, uint8_t orientation);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ifndef LIBAVIF_APPS_SHARED_AVIFEXIF_H
diff --git a/apps/shared/avifjpeg.c b/apps/shared/avifjpeg.c
index 707ef40..6d7deb8 100644
--- a/apps/shared/avifjpeg.c
+++ b/apps/shared/avifjpeg.c
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-2-Clause
#include "avifjpeg.h"
-#include "avif/internal.h"
+#include "avifexif.h"
#include "avifutil.h"
#include <assert.h>
diff --git a/apps/shared/avifpng.c b/apps/shared/avifpng.c
index 684970a..775ce73 100644
--- a/apps/shared/avifpng.c
+++ b/apps/shared/avifpng.c
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: BSD-2-Clause
#include "avifpng.h"
-#include "avif/internal.h"
+#include "avifexif.h"
#include "avifutil.h"
#include "png.h"
diff --git a/include/avif/avif.h b/include/avif/avif.h
index dd7dc31..fab51a5 100644
--- a/include/avif/avif.h
+++ b/include/avif/avif.h
@@ -187,6 +187,15 @@
AVIF_API void avifRWDataFree(avifRWData * raw);
// ---------------------------------------------------------------------------
+// Metadata
+
+// Validates the first bytes of the Exif payload and finds the TIFF header offset (up to UINT32_MAX).
+AVIF_API avifResult avifGetExifTiffHeaderOffset(const uint8_t * exif, size_t exifSize, size_t * offset);
+// Returns the offset to the Exif 8-bit orientation value and AVIF_RESULT_OK, or an error.
+// If the offset is set to exifSize, there was no parsing error but no orientation tag was found.
+AVIF_API avifResult avifGetExifOrientationOffset(const uint8_t * exif, size_t exifSize, size_t * offset);
+
+// ---------------------------------------------------------------------------
// avifPixelFormat
//
// Note to libavif maintainers: The lookup tables in avifImageYUVToRGBLibYUV
diff --git a/include/avif/internal.h b/include/avif/internal.h
index 04d2619..1fd7f3e 100644
--- a/include/avif/internal.h
+++ b/include/avif/internal.h
@@ -207,15 +207,9 @@
// ---------------------------------------------------------------------------
// Metadata
-// Validates the first bytes of the Exif payload and finds the TIFF header offset (up to UINT32_MAX).
-avifResult avifGetExifTiffHeaderOffset(const uint8_t * exif, size_t exifSize, size_t * offset);
// Attempts to parse the image->exif payload for Exif orientation and sets image->transformFlags, image->irot and
// image->imir on success. Returns AVIF_RESULT_INVALID_EXIF_PAYLOAD on failure.
avifResult avifImageExtractExifOrientationToIrotImir(avifImage * image);
-// Converts image->transformFlags, image->irot and image->imir to the equivalent Exif orientation value in [1:8].
-uint8_t avifImageGetExifOrientationFromIrotImir(const avifImage * image);
-// Attempts to parse the image->exif payload until the Exif orientation is found, then sets it to the given value.
-avifResult avifSetExifOrientation(avifRWData * exif, uint8_t orientation);
// ---------------------------------------------------------------------------
// avifCodecDecodeInput
diff --git a/src/exif.c b/src/exif.c
index 58489b3..82bf6f3 100644
--- a/src/exif.c
+++ b/src/exif.c
@@ -22,7 +22,7 @@
// Returns the offset to the Exif 8-bit orientation value and AVIF_RESULT_OK, or an error.
// If the offset is set to exifSize, there was no parsing error but no orientation tag was found.
-static avifResult avifGetExifOrientationOffset(const uint8_t * exif, size_t exifSize, size_t * offset)
+avifResult avifGetExifOrientationOffset(const uint8_t * exif, size_t exifSize, size_t * offset)
{
const avifResult result = avifGetExifTiffHeaderOffset(exif, exifSize, offset);
if (result != AVIF_RESULT_OK) {
@@ -142,64 +142,6 @@
return AVIF_RESULT_OK;
}
-uint8_t avifImageGetExifOrientationFromIrotImir(const avifImage * image)
-{
- if ((image->transformFlags & AVIF_TRANSFORM_IROT) && (image->irot.angle == 1)) {
- if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
- if (image->imir.mode) {
- return 7; // 90 degrees anti-clockwise then swap left and right.
- }
- return 5; // 90 degrees anti-clockwise then swap top and bottom.
- }
- return 6; // 90 degrees anti-clockwise.
- }
- if ((image->transformFlags & AVIF_TRANSFORM_IROT) && (image->irot.angle == 2)) {
- if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
- if (image->imir.mode) {
- return 4; // 180 degrees anti-clockwise then swap left and right.
- }
- return 2; // 180 degrees anti-clockwise then swap top and bottom.
- }
- return 3; // 180 degrees anti-clockwise.
- }
- if ((image->transformFlags & AVIF_TRANSFORM_IROT) && (image->irot.angle == 3)) {
- if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
- if (image->imir.mode) {
- return 5; // 270 degrees anti-clockwise then swap left and right.
- }
- return 7; // 270 degrees anti-clockwise then swap top and bottom.
- }
- return 8; // 270 degrees anti-clockwise.
- }
- if (image->transformFlags & AVIF_TRANSFORM_IMIR) {
- if (image->imir.mode) {
- return 2; // Swap left and right.
- }
- return 4; // Swap top and bottom.
- }
- return 1; // Default orientation ("top-left", no-op).
-}
-
-avifResult avifSetExifOrientation(avifRWData * exif, uint8_t orientation)
-{
- size_t offset;
- const avifResult result = avifGetExifOrientationOffset(exif->data, exif->size, &offset);
- if (result != AVIF_RESULT_OK) {
- return result;
- }
- if (offset < exif->size) {
- exif->data[offset] = orientation;
- return AVIF_RESULT_OK;
- }
- // No Exif orientation was found.
- if (orientation == 1) {
- // The default orientation is 1, so if the given orientation is 1 too, do nothing.
- return AVIF_RESULT_OK;
- }
- // Adding an orientation tag to an Exif payload is involved.
- return AVIF_RESULT_NOT_IMPLEMENTED;
-}
-
void avifImageSetMetadataExif(avifImage * image, const uint8_t * exif, size_t exifSize)
{
avifRWDataSet(&image->exif, exif, exifSize);