From abd8ee5a5234055ddcdfa6c6651f9c037a4d1ee6 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 5 Jan 2026 12:30:07 -0800
Subject: [PATCH] Added APNG support to the Xcode build
---
Xcode/SDL_image.xcodeproj/project.pbxproj | 28 +++++++++++
Xcode/config.xcconfig | 10 ++--
.../showanim.xcodeproj/project.pbxproj | 46 +++++++++++++++++++
src/IMG_libpng.c | 8 ++++
4 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/Xcode/SDL_image.xcodeproj/project.pbxproj b/Xcode/SDL_image.xcodeproj/project.pbxproj
index d50b51f00..97dccad86 100644
--- a/Xcode/SDL_image.xcodeproj/project.pbxproj
+++ b/Xcode/SDL_image.xcodeproj/project.pbxproj
@@ -96,6 +96,13 @@
remoteGlobalIDString = F307EEDC28288CCF003915D7;
remoteInfo = jxl;
};
+ F31BA83E2F0C56BA00646176 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = F31BA7F62F0C417B00646176 /* png.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F3D87D21281EA9C3005DA540;
+ remoteInfo = png;
+ };
F35475DB2829BA80007E9EDA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F35475D42829BA80007E9EDA /* avif.xcodeproj */;
@@ -193,6 +200,7 @@
BE1FA72E07AF4C45004B6283 /* SDL3_image.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL3_image.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F307EFA82828C8FA003915D7 /* jxl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = jxl.xcodeproj; path = jxl/jxl.xcodeproj; sourceTree = "<group>"; };
F31094C2282AE42D008EF641 /* IMG_stb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG_stb.c; path = ../src/IMG_stb.c; sourceTree = "<group>"; };
+ F31BA7F62F0C417B00646176 /* png.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = png.xcodeproj; path = png/png.xcodeproj; sourceTree = "<group>"; };
F34123BF2D41A75D00D6C2B7 /* INSTALL.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = INSTALL.md; sourceTree = "<group>"; };
F34123C32D41A79D00D6C2B7 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = LICENSE.txt; path = ../../../LICENSE.txt; sourceTree = "<group>"; };
F34123C52D41A7D800D6C2B7 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../../../README.md; sourceTree = "<group>"; };
@@ -268,6 +276,7 @@
F3547625282AE1C6007E9EDA /* config.xcconfig */,
F35475D42829BA80007E9EDA /* avif.xcodeproj */,
F307EFA82828C8FA003915D7 /* jxl.xcodeproj */,
+ F31BA7F62F0C417B00646176 /* png.xcodeproj */,
F3D87D15281EA88F005DA540 /* webp.xcodeproj */,
F59C70FC00D5CB5801000001 /* pkg-support */,
0153844A006D81B07F000001 /* Public Headers */,
@@ -346,6 +355,14 @@
name = Products;
sourceTree = "<group>";
};
+ F31BA8322F0C56BA00646176 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F31BA83F2F0C56BA00646176 /* png.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
F34123BE2D41A71500D6C2B7 /* framework */ = {
isa = PBXGroup;
children = (
@@ -480,6 +497,10 @@
ProductGroup = F307EFA92828C8FA003915D7 /* Products */;
ProjectRef = F307EFA82828C8FA003915D7 /* jxl.xcodeproj */;
},
+ {
+ ProductGroup = F31BA8322F0C56BA00646176 /* Products */;
+ ProjectRef = F31BA7F62F0C417B00646176 /* png.xcodeproj */;
+ },
{
ProductGroup = F3D87D16281EA88F005DA540 /* Products */;
ProjectRef = F3D87D15281EA88F005DA540 /* webp.xcodeproj */;
@@ -502,6 +523,13 @@
remoteRef = F307EFAC2828C8FA003915D7 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
+ F31BA83F2F0C56BA00646176 /* png.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = png.framework;
+ remoteRef = F31BA83E2F0C56BA00646176 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
F35475DC2829BA80007E9EDA /* avif.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
diff --git a/Xcode/config.xcconfig b/Xcode/config.xcconfig
index 67e24606b..73d8718cc 100644
--- a/Xcode/config.xcconfig
+++ b/Xcode/config.xcconfig
@@ -18,11 +18,15 @@
//JXL_PREPROCESSOR_DEFINITIONS = LOAD_JXL
//JXL_FRAMEWORK_LDFLAGS = -weak_framework jxl
+// Uncomment these lines to enable libpng support
+// If you do this, you should run external/download.sh to download the decode libraries and add png.framework to your application bundle.
+//PNG_PREPROCESSOR_DEFINITIONS = SDL_IMAGE_LIBPNG INCLUDE_PNG_FRAMEWORK
+//PNG_FRAMEWORK_LDFLAGS = -weak_framework png
+
// Uncomment these lines to enable WebP support
// If you do this, you should run external/download.sh to download the decode libraries and add webp.framework to your application bundle.
//WEBP_PREPROCESSOR_DEFINITIONS = LOAD_WEBP
//WEBP_FRAMEWORK_LDFLAGS = -weak_framework webp
-CONFIG_PREPROCESSOR_DEFINITIONS = $(inherited) $(AVIF_PREPROCESSOR_DEFINITIONS) $(JXL_PREPROCESSOR_DEFINITIONS) $(WEBP_PREPROCESSOR_DEFINITIONS)
-CONFIG_FRAMEWORK_LDFLAGS = $(inherited) $(AVIF_FRAMEWORK_LDFLAGS) $(JXL_FRAMEWORK_LDFLAGS) $(WEBP_FRAMEWORK_LDFLAGS)
-
+CONFIG_PREPROCESSOR_DEFINITIONS = $(inherited) $(AVIF_PREPROCESSOR_DEFINITIONS) $(JXL_PREPROCESSOR_DEFINITIONS) $(PNG_PREPROCESSOR_DEFINITIONS) $(WEBP_PREPROCESSOR_DEFINITIONS)
+CONFIG_FRAMEWORK_LDFLAGS = $(inherited) $(AVIF_FRAMEWORK_LDFLAGS) $(JXL_FRAMEWORK_LDFLAGS) $(PNG_FRAMEWORK_LDFLAGS) $(WEBP_FRAMEWORK_LDFLAGS)
diff --git a/Xcode/showanim/showanim.xcodeproj/project.pbxproj b/Xcode/showanim/showanim.xcodeproj/project.pbxproj
index d01dfa9c1..488d7ab1c 100644
--- a/Xcode/showanim/showanim.xcodeproj/project.pbxproj
+++ b/Xcode/showanim/showanim.xcodeproj/project.pbxproj
@@ -7,6 +7,12 @@
objects = {
/* Begin PBXBuildFile section */
+ F31BA8222F0C524300646176 /* png.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F31BA8212F0C524300646176 /* png.framework */; };
+ F31BA8232F0C524300646176 /* png.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = F31BA8212F0C524300646176 /* png.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ F31BA8252F0C524E00646176 /* png.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F31BA8242F0C524E00646176 /* png.framework */; };
+ F31BA8262F0C524E00646176 /* png.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = F31BA8242F0C524E00646176 /* png.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ F31BA8282F0C525C00646176 /* png.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F31BA8272F0C525C00646176 /* png.framework */; };
+ F31BA8292F0C525C00646176 /* png.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = F31BA8272F0C525C00646176 /* png.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F341283C2D4B496D00D6C2B7 /* SDL3.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = F34123152D4077A600D6C2B7 /* SDL3.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F341283D2D4B498100D6C2B7 /* SDL3.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = F34123152D4077A600D6C2B7 /* SDL3.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F341283E2D4B498700D6C2B7 /* SDL3.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = F34123152D4077A600D6C2B7 /* SDL3.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -34,6 +40,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ F31BA84B2F0C56BA00646176 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = F31BA81E2F0C521E00646176 /* png.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = F3D87D21281EA9C3005DA540;
+ remoteInfo = png;
+ };
F34123142D4077A600D6C2B7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F344001D2D401E16003F26D7 /* SDL.xcodeproj */;
@@ -110,6 +123,7 @@
F39CD44B281DC6C8006CF638 /* SDL3_image.framework in Copy Frameworks */,
F35475F92829BAC7007E9EDA /* avif.framework in Copy Frameworks */,
F35474562828CDE0007E9EDA /* jxl.framework in Copy Frameworks */,
+ F31BA8292F0C525C00646176 /* png.framework in Copy Frameworks */,
F3E949DB281EAC3500B8F4EA /* webp.framework in Copy Frameworks */,
);
name = "Copy Frameworks";
@@ -125,6 +139,7 @@
F39CD452281DC9CE006CF638 /* SDL3_image.framework in Copy Frameworks */,
F35475FA2829BACC007E9EDA /* avif.framework in Copy Frameworks */,
F35474552828CDDB007E9EDA /* jxl.framework in Copy Frameworks */,
+ F31BA8262F0C524E00646176 /* png.framework in Copy Frameworks */,
F3E949DC281EAC9600B8F4EA /* webp.framework in Copy Frameworks */,
);
name = "Copy Frameworks";
@@ -140,6 +155,7 @@
F3ED80FF281DA63000C33C5B /* SDL3_image.framework in Copy Frameworks */,
F35475FB2829BAD0007E9EDA /* avif.framework in Copy Frameworks */,
F35474502828CAF5007E9EDA /* jxl.framework in Copy Frameworks */,
+ F31BA8232F0C524300646176 /* png.framework in Copy Frameworks */,
F3E949DD281EAC9C00B8F4EA /* webp.framework in Copy Frameworks */,
);
name = "Copy Frameworks";
@@ -148,6 +164,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ F31BA81E2F0C521E00646176 /* png.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = png.xcodeproj; path = ../png/png.xcodeproj; sourceTree = SOURCE_ROOT; };
+ F31BA8212F0C524300646176 /* png.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = png.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F31BA8242F0C524E00646176 /* png.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = png.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ F31BA8272F0C525C00646176 /* png.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = png.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F344001D2D401E16003F26D7 /* SDL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL.xcodeproj; path = ../../../SDL/Xcode/SDL/SDL.xcodeproj; sourceTree = SOURCE_ROOT; };
F35474462828CADB007E9EDA /* jxl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = jxl.xcodeproj; path = ../jxl/jxl.xcodeproj; sourceTree = "<group>"; };
F35475E52829BAB1007E9EDA /* avif.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = avif.xcodeproj; path = ../avif/avif.xcodeproj; sourceTree = "<group>"; };
@@ -170,6 +190,7 @@
buildActionMask = 2147483647;
files = (
F34128402D4B4A5600D6C2B7 /* SDL3.framework in Frameworks */,
+ F31BA8222F0C524300646176 /* png.framework in Frameworks */,
F3ED80F5281DA3F600C33C5B /* SDL3_image.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -179,6 +200,7 @@
buildActionMask = 2147483647;
files = (
F341283F2D4B4A4F00D6C2B7 /* SDL3.framework in Frameworks */,
+ F31BA8252F0C524E00646176 /* png.framework in Frameworks */,
F3ED80E3281DA16500C33C5B /* SDL3_image.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -188,6 +210,7 @@
buildActionMask = 2147483647;
files = (
F34128412D4B4A5C00D6C2B7 /* SDL3.framework in Frameworks */,
+ F31BA8282F0C525C00646176 /* png.framework in Frameworks */,
F3ED8113281DC13D00C33C5B /* SDL3_image.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -195,6 +218,14 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ F31BA8342F0C56BA00646176 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F31BA84C2F0C56BA00646176 /* png.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
F341230F2D4077A600D6C2B7 /* Products */ = {
isa = PBXGroup;
children = (
@@ -239,6 +270,7 @@
F3ED80CD281D9ED600C33C5B /* SDL_image.xcodeproj */,
F35475E52829BAB1007E9EDA /* avif.xcodeproj */,
F35474462828CADB007E9EDA /* jxl.xcodeproj */,
+ F31BA81E2F0C521E00646176 /* png.xcodeproj */,
F3E949D5281EAC1B00B8F4EA /* webp.xcodeproj */,
F3ED80AB281D9E8800C33C5B /* Shared */,
F3ED80BA281D9E8900C33C5B /* macOS */,
@@ -284,6 +316,9 @@
F3ED80E2281DA16500C33C5B /* Frameworks */ = {
isa = PBXGroup;
children = (
+ F31BA8272F0C525C00646176 /* png.framework */,
+ F31BA8242F0C524E00646176 /* png.framework */,
+ F31BA8212F0C524300646176 /* png.framework */,
F3ED8104281DADB900C33C5B /* macOS */,
F3ED8105281DADC900C33C5B /* iOS */,
F3ED810D281DC07200C33C5B /* tvOS */,
@@ -410,6 +445,10 @@
ProductGroup = F35474472828CADB007E9EDA /* Products */;
ProjectRef = F35474462828CADB007E9EDA /* jxl.xcodeproj */;
},
+ {
+ ProductGroup = F31BA8342F0C56BA00646176 /* Products */;
+ ProjectRef = F31BA81E2F0C521E00646176 /* png.xcodeproj */;
+ },
{
ProductGroup = F341230F2D4077A600D6C2B7 /* Products */;
ProjectRef = F344001D2D401E16003F26D7 /* SDL.xcodeproj */;
@@ -433,6 +472,13 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
+ F31BA84C2F0C56BA00646176 /* png.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = png.framework;
+ remoteRef = F31BA84B2F0C56BA00646176 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
F34123152D4077A600D6C2B7 /* SDL3.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
diff --git a/src/IMG_libpng.c b/src/IMG_libpng.c
index 1f9fc385a..07f3f87ab 100644
--- a/src/IMG_libpng.c
+++ b/src/IMG_libpng.c
@@ -34,7 +34,11 @@
#include "IMG_anim_decoder.h"
#ifdef SDL_IMAGE_LIBPNG
+#ifdef INCLUDE_PNG_FRAMEWORK
+#include <png/png.h>
+#else
#include <png.h>
+#endif
#if defined(LOAD_LIBPNG_DYNAMIC) && defined(SDL_ELF_NOTE_DLOPEN)
SDL_ELF_NOTE_DLOPEN(
@@ -198,6 +202,10 @@ static struct
}
#endif
+#ifdef __APPLE__
+/* Need to turn off optimizations so weak framework load check works */
+__attribute__((optnone))
+#endif
static bool IMG_InitPNG(void)
{
if (lib.loaded == 0) {