added zlib and libpng
This commit is contained in:
parent
2ff50efb58
commit
1054c18ba9
|
@ -1,2 +1,4 @@
|
||||||
/build/
|
/build/
|
||||||
*~
|
*~
|
||||||
|
/.cache/
|
||||||
|
/compile_commands.json
|
||||||
|
|
|
@ -3,11 +3,27 @@
|
||||||
#
|
#
|
||||||
cmake_minimum_required (VERSION 3.8)
|
cmake_minimum_required (VERSION 3.8)
|
||||||
|
|
||||||
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
|
||||||
|
|
||||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
||||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||||
add_subdirectory(lib/glfw-3.3.8)
|
add_subdirectory(lib/glfw-3.3.8)
|
||||||
|
|
||||||
|
|
||||||
|
set(PNG_BUILD_ZLIB ON)
|
||||||
|
set(PNG_SHARED OFF)
|
||||||
|
set(PNG_STATIC ON)
|
||||||
|
set(PNG_EXECUTABLES OFF)
|
||||||
|
set(PNG_TESTS OFF)
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
set(SKIP_INSTALL_ALL ON)
|
||||||
|
set(ZLIB_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/lib/zlib-1.2.13" "${CMAKE_BINARY_DIR}/lib/zlib-1.2.13")
|
||||||
|
add_subdirectory(lib/zlib-1.2.13)
|
||||||
|
set(ZLIB_LIBRARY zlib)
|
||||||
|
add_subdirectory(lib/lpng1639)
|
||||||
|
|
||||||
project ("glew")
|
project ("glew")
|
||||||
|
|
||||||
add_library(glew STATIC "lib/glew-2.1.0/src/glew.c" "lib/glew-2.1.0/include/GL/glew.h")
|
add_library(glew STATIC "lib/glew-2.1.0/src/glew.c" "lib/glew-2.1.0/include/GL/glew.h")
|
||||||
|
@ -18,10 +34,27 @@ set_target_properties(glew PROPERTIES COMPILE_FLAGS "-Wno-everything")
|
||||||
target_compile_definitions(glew PUBLIC GLEW_STATIC)
|
target_compile_definitions(glew PUBLIC GLEW_STATIC)
|
||||||
|
|
||||||
project ("skunkworks")
|
project ("skunkworks")
|
||||||
|
set(SOURCE
|
||||||
|
src/gl.h
|
||||||
|
src/skunkworks.c
|
||||||
|
src/skunkworks.h
|
||||||
|
src/test.c
|
||||||
|
src/vec2i.c
|
||||||
|
src/window.c
|
||||||
|
|
||||||
add_executable (skunkworks "src/skunkworks.c" "src/skunkworks.h" "src/test.c")
|
include/vec2i.h
|
||||||
target_link_libraries(skunkworks glfw glew)
|
include/window.h
|
||||||
target_include_directories(skunkworks PRIVATE lib/glfw-3.8.8/include lib/glew-2.1.0/include)
|
)
|
||||||
|
|
||||||
|
add_executable (skunkworks ${SOURCE})
|
||||||
|
target_link_libraries(skunkworks glfw glew png_static zlibstatic)
|
||||||
|
target_include_directories(skunkworks PRIVATE
|
||||||
|
lib/glfw-3.8.8/include
|
||||||
|
lib/glew-2.1.0/include
|
||||||
|
lib/lpng1639
|
||||||
|
build/lib/lpng1639
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
set_target_properties(skunkworks PROPERTIES C_STANDARD 90 C_STANDARD_REQUIRED YES C_EXTENSIONS NO)
|
set_target_properties(skunkworks PROPERTIES C_STANDARD 90 C_STANDARD_REQUIRED YES C_EXTENSIONS NO)
|
||||||
set_target_properties(skunkworks PROPERTIES COMPILE_FLAGS "-Wall -Werror -pedantic")
|
set_target_properties(skunkworks PROPERTIES COMPILE_FLAGS "-Wall -Werror -pedantic")
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
# skunkworks-c
|
# skunkworks-c
|
||||||
|
|
||||||
|
## code standard
|
||||||
|
|
||||||
|
snake_case for variables, function names, and struct names.
|
||||||
|
always explicit struct, no typedefs.
|
||||||
|
prefix struct members with _ (yes, its allowed, but _within_ structs only) if "private".
|
|
@ -1,2 +1,2 @@
|
||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && ninja && skunkworks.exe
|
cd build && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -GNinja .. && ninja && copy compile_commands.json .. && skunkworks.exe
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef GUARD_B329567D1B1FDC855E0489217F4BCBE2
|
||||||
|
#define GUARD_B329567D1B1FDC855E0489217F4BCBE2
|
||||||
|
|
||||||
|
struct vec2i {
|
||||||
|
int x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vec2i sw_vec2i(int x, int y);
|
||||||
|
|
||||||
|
#endif /* GUARD_B329567D1B1FDC855E0489217F4BCBE2 */
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef GUARD_F247452E0BF1EC9CD9131C2A6FD281CA
|
||||||
|
#define GUARD_F247452E0BF1EC9CD9131C2A6FD281CA
|
||||||
|
|
||||||
|
#include "vec2i.h"
|
||||||
|
|
||||||
|
typedef struct GLFWwindow GLFWwindow;
|
||||||
|
|
||||||
|
struct window {
|
||||||
|
struct vec2i size;
|
||||||
|
|
||||||
|
GLFWwindow *_window;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window *sw_window_create(struct vec2i size, char *title);
|
||||||
|
|
||||||
|
#endif /* GUARD_F247452E0BF1EC9CD9131C2A6FD281CA */
|
|
@ -0,0 +1,69 @@
|
||||||
|
version: 1.6.x-{build}
|
||||||
|
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- /libpng[0-1][0-7]/
|
||||||
|
|
||||||
|
image:
|
||||||
|
- Visual Studio 2022
|
||||||
|
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- TOOLCHAIN: vstudio
|
||||||
|
AUTOMATION: cmake
|
||||||
|
ARCH: x86
|
||||||
|
- TOOLCHAIN: vstudio
|
||||||
|
AUTOMATION: cmake
|
||||||
|
ARCH: x64
|
||||||
|
- TOOLCHAIN: vstudio
|
||||||
|
AUTOMATION: cmake
|
||||||
|
ARCH: arm64
|
||||||
|
CI_NO_TEST: 1
|
||||||
|
- TOOLCHAIN: msys2
|
||||||
|
AUTOMATION: cmake
|
||||||
|
ARCH: i686
|
||||||
|
- TOOLCHAIN: msys2
|
||||||
|
AUTOMATION: cmake
|
||||||
|
ARCH: x86_64
|
||||||
|
- TOOLCHAIN: msys2
|
||||||
|
AUTOMATION: autotools
|
||||||
|
ARCH: i686
|
||||||
|
- TOOLCHAIN: msys2
|
||||||
|
AUTOMATION: autotools
|
||||||
|
ARCH: x86_64
|
||||||
|
- TOOLCHAIN: msys2
|
||||||
|
AUTOMATION: legacy
|
||||||
|
ARCH: i686
|
||||||
|
- TOOLCHAIN: msys2
|
||||||
|
AUTOMATION: legacy
|
||||||
|
ARCH: x86_64
|
||||||
|
|
||||||
|
install:
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" C:\tools\vcpkg\vcpkg.exe install zlib:%ARCH%-windows'
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" C:\tools\vcpkg\vcpkg.exe integrate install'
|
||||||
|
|
||||||
|
before_build:
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" set CI_CMAKE_VARS=-DCMAKE_TOOLCHAIN_FILE=C:\tools\vcpkg\scripts\buildsystems\vcpkg.cmake'
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" set CI_CMAKE_GENERATOR=Visual Studio 17 2022'
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" if "%ARCH%"=="x86" set CI_CMAKE_GENERATOR_PLATFORM=Win32'
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" if "%ARCH%"=="x64" set CI_CMAKE_GENERATOR_PLATFORM=x64'
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" if "%ARCH%"=="arm64" set CI_CMAKE_GENERATOR_PLATFORM=ARM64'
|
||||||
|
- 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="cmake" set CI_CMAKE_GENERATOR=Unix Makefiles'
|
||||||
|
- 'if "%TOOLCHAIN%"=="msys2" if "%ARCH%"=="i686" set PATH=C:\msys64\mingw32\bin;%PATH%'
|
||||||
|
- 'if "%TOOLCHAIN%"=="msys2" if "%ARCH%"=="x86_64" set PATH=C:\msys64\mingw64\bin;%PATH%'
|
||||||
|
- 'if "%TOOLCHAIN%"=="msys2" set CI_CC=%ARCH%-w64-mingw32-gcc'
|
||||||
|
- 'set CI_CMAKE_BUILD_FLAGS=--parallel 2'
|
||||||
|
- 'set CI_CTEST_FLAGS=--parallel 2'
|
||||||
|
- 'set CI_MAKE_FLAGS=-j2'
|
||||||
|
- 'set CI_LEGACY_MAKEFILES=scripts/makefile.gcc scripts/makefile.msys scripts/makefile.std'
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- 'if "%TOOLCHAIN%"=="vstudio" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_cmake.sh"'
|
||||||
|
- 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="cmake" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_cmake.sh"'
|
||||||
|
- 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="autotools" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_autotools.sh"'
|
||||||
|
- 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="legacy" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_legacy.sh"'
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- C:\tools\vcpkg\installed
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Precompiled headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Linker output files
|
||||||
|
*.exp
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
|
||||||
|
# Compiled dynamic libraries
|
||||||
|
*.dll
|
||||||
|
*.dylib
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
|
||||||
|
# Compiled static libraries
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lai
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Compiled executables
|
||||||
|
*.app/
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
*.su
|
||||||
|
|
||||||
|
# Libpng configuration and build artifacts
|
||||||
|
.deps/
|
||||||
|
.dirstamp
|
||||||
|
Makefile
|
||||||
|
autom4te.cache/
|
||||||
|
config.h
|
||||||
|
config.h.in~
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
configure~
|
||||||
|
libpng-config
|
||||||
|
libpng.pc
|
||||||
|
libpng.vers
|
||||||
|
libpng16-config
|
||||||
|
libpng16.pc
|
||||||
|
libtool
|
||||||
|
pnglibconf.[ch]
|
||||||
|
pnglibconf.dfn
|
||||||
|
pnglibconf.out
|
||||||
|
pnglibconf.pre
|
||||||
|
pngprefix.h
|
||||||
|
stamp-h1
|
||||||
|
vers.out
|
||||||
|
|
||||||
|
# Libpng test artifacts
|
||||||
|
png-fix-itxt
|
||||||
|
pngcp
|
||||||
|
pngfix
|
||||||
|
pngimage
|
||||||
|
pngstest
|
||||||
|
pngtest
|
||||||
|
pngunknown
|
||||||
|
pngvalid
|
||||||
|
timepng
|
||||||
|
pngout.png
|
||||||
|
|
||||||
|
# Libpng CI artifacts
|
||||||
|
out/
|
|
@ -0,0 +1,45 @@
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- /libpng[0-1][0-7]/
|
||||||
|
|
||||||
|
language: c
|
||||||
|
|
||||||
|
os:
|
||||||
|
- freebsd
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
compiler:
|
||||||
|
- clang
|
||||||
|
- gcc
|
||||||
|
|
||||||
|
env:
|
||||||
|
- AUTOMATION=cmake CI_NO_TEST=1
|
||||||
|
- AUTOMATION=cmake CI_CMAKE_VARS="-DPNG_HARDWARE_OPTIMIZATIONS=ON" CI_SANITIZERS="address,undefined"
|
||||||
|
- AUTOMATION=cmake CI_CMAKE_VARS="-DPNG_HARDWARE_OPTIMIZATIONS=OFF" CI_SANITIZERS="address,undefined"
|
||||||
|
- AUTOMATION=autotools CI_NO_TEST=1
|
||||||
|
- AUTOMATION=autotools CI_CONFIGURE_FLAGS="--enable-hardware-optimizations"
|
||||||
|
- AUTOMATION=autotools CI_CONFIGURE_FLAGS="--disable-hardware-optimizations"
|
||||||
|
- AUTOMATION=legacy CI_NO_TEST=1
|
||||||
|
- AUTOMATION=legacy CI_SANITIZERS="address,undefined"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: osx
|
||||||
|
compiler: cc
|
||||||
|
env: AUTOMATION=cmake CI_CMAKE_GENERATOR=Xcode
|
||||||
|
exclude:
|
||||||
|
- os: freebsd
|
||||||
|
compiler: gcc
|
||||||
|
- os: osx
|
||||||
|
compiler: gcc
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- 'export CI_CMAKE_BUILD_FLAGS="--parallel 2"'
|
||||||
|
- 'export CI_CTEST_FLAGS="--parallel 2"'
|
||||||
|
- 'export CI_MAKE_FLAGS=-j2'
|
||||||
|
- 'export CI_CC=$TRAVIS_COMPILER'
|
||||||
|
- 'export CI_LEGACY_MAKEFILES="scripts/makefile.$TRAVIS_COMPILER scripts/makefile.std"'
|
||||||
|
|
||||||
|
script:
|
||||||
|
- './ci/ci_$AUTOMATION.sh'
|
|
@ -0,0 +1,46 @@
|
||||||
|
libpng 1.6.39 - November 20, 2022
|
||||||
|
=================================
|
||||||
|
|
||||||
|
This is a public release of libpng, intended for use in production code.
|
||||||
|
|
||||||
|
|
||||||
|
Files available for download
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Source files with LF line endings (for Unix/Linux):
|
||||||
|
|
||||||
|
* libpng-1.6.39.tar.xz (LZMA-compressed, recommended)
|
||||||
|
* libpng-1.6.39.tar.gz
|
||||||
|
|
||||||
|
Source files with CRLF line endings (for Windows):
|
||||||
|
|
||||||
|
* lpng1639.7z (LZMA-compressed, recommended)
|
||||||
|
* lpng1639.zip
|
||||||
|
|
||||||
|
Other information:
|
||||||
|
|
||||||
|
* README.md
|
||||||
|
* LICENSE.md
|
||||||
|
* AUTHORS.md
|
||||||
|
* TRADEMARK.md
|
||||||
|
|
||||||
|
|
||||||
|
Changes from version 1.6.38 to version 1.6.39
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
* Changed the error handler of oversized chunks (i.e. larger than
|
||||||
|
PNG_USER_CHUNK_MALLOC_MAX) from png_chunk_error to png_benign_error.
|
||||||
|
* Fixed a buffer overflow error in contrib/tools/pngfix.
|
||||||
|
* Fixed a memory leak (CVE-2019-6129) in contrib/tools/pngcp.
|
||||||
|
* Disabled the ARM Neon optimizations by default in the CMake file,
|
||||||
|
following the default behavior of the configure script.
|
||||||
|
* Allowed configure.ac to work with the trunk version of autoconf.
|
||||||
|
* Removed the support for "install" targets from the legacy makefiles;
|
||||||
|
removed the obsolete makefile.cegcc.
|
||||||
|
* Cleaned up the code and updated the internal documentation.
|
||||||
|
|
||||||
|
|
||||||
|
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
|
||||||
|
Subscription is required; visit
|
||||||
|
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
|
||||||
|
to subscribe.
|
|
@ -0,0 +1,50 @@
|
||||||
|
PNG REFERENCE LIBRARY AUTHORS
|
||||||
|
=============================
|
||||||
|
|
||||||
|
This is the list of PNG Reference Library ("libpng") Contributing
|
||||||
|
Authors, for copyright and licensing purposes.
|
||||||
|
|
||||||
|
* Andreas Dilger
|
||||||
|
* Cosmin Truta
|
||||||
|
* Dave Martindale
|
||||||
|
* Eric S. Raymond
|
||||||
|
* Gilles Vollant
|
||||||
|
* Glenn Randers-Pehrson
|
||||||
|
* Greg Roelofs
|
||||||
|
* Guy Eric Schalnat
|
||||||
|
* James Yu
|
||||||
|
* John Bowler
|
||||||
|
* Kevin Bracey
|
||||||
|
* Magnus Holmgren
|
||||||
|
* Mandar Sahastrabuddhe
|
||||||
|
* Mans Rullgard
|
||||||
|
* Matt Sarett
|
||||||
|
* Mike Klein
|
||||||
|
* Pascal Massimino
|
||||||
|
* Paul Schmidt
|
||||||
|
* Qiang Zhou
|
||||||
|
* Sam Bushell
|
||||||
|
* Samuel Williams
|
||||||
|
* Simon-Pierre Cadieux
|
||||||
|
* Tim Wegner
|
||||||
|
* Tom Lane
|
||||||
|
* Tom Tanner
|
||||||
|
* Vadim Barkov
|
||||||
|
* Willem van Schaik
|
||||||
|
* Zhijie Liang
|
||||||
|
* Arm Holdings
|
||||||
|
- Richard Townsend
|
||||||
|
* Google Inc.
|
||||||
|
- Dan Field
|
||||||
|
- Leon Scroggins III
|
||||||
|
- Matt Sarett
|
||||||
|
- Mike Klein
|
||||||
|
- Sami Boukortt
|
||||||
|
|
||||||
|
The build projects, the build scripts, the test scripts, and other
|
||||||
|
files in the "ci", "projects", "scripts" and "tests" directories, have
|
||||||
|
other copyright owners, but are released under the libpng license.
|
||||||
|
|
||||||
|
Some files in the "contrib" directory, and some tools-generated files
|
||||||
|
that are distributed with libpng, have other copyright owners, and are
|
||||||
|
released under other open source licenses.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,464 @@
|
||||||
|
|
||||||
|
Installing libpng
|
||||||
|
|
||||||
|
Contents
|
||||||
|
|
||||||
|
I. Simple installation
|
||||||
|
II. Rebuilding the configure scripts
|
||||||
|
III. Using scripts/makefile*
|
||||||
|
IV. Using cmake
|
||||||
|
V. Directory structure
|
||||||
|
VI. Building with project files
|
||||||
|
VII. Building with makefiles
|
||||||
|
VIII. Configuring libpng for 16-bit platforms
|
||||||
|
IX. Configuring for DOS
|
||||||
|
X. Configuring for Medium Model
|
||||||
|
XI. Prepending a prefix to exported symbols
|
||||||
|
XII. Configuring for compiler xxx:
|
||||||
|
XIII. Removing unwanted object code
|
||||||
|
XIV. Enabling or disabling hardware optimizations
|
||||||
|
XV. Changes to the build and configuration of libpng in libpng-1.5.x
|
||||||
|
XVI. Setjmp/longjmp issues
|
||||||
|
XVII. Common linking failures
|
||||||
|
XVIII. Other sources of information about libpng
|
||||||
|
|
||||||
|
I. Simple installation
|
||||||
|
|
||||||
|
On Unix/Linux and similar systems, you can simply type
|
||||||
|
|
||||||
|
./configure [--prefix=/path]
|
||||||
|
make check
|
||||||
|
make install
|
||||||
|
|
||||||
|
and ignore the rest of this document. "/path" is the path to the directory
|
||||||
|
where you want to install the libpng "lib", "include", and "bin"
|
||||||
|
subdirectories.
|
||||||
|
|
||||||
|
If you downloaded a GIT clone, you will need to run ./autogen.sh before
|
||||||
|
running ./configure, to create "configure" and "Makefile.in" which are
|
||||||
|
not included in the GIT repository.
|
||||||
|
|
||||||
|
Note that "configure" is only included in the "*.tar" distributions and not
|
||||||
|
in the "*.zip" or "*.7z" distributions. If you downloaded one of those
|
||||||
|
distributions, see "Building with project files" or "Building with makefiles",
|
||||||
|
below.
|
||||||
|
|
||||||
|
II. Rebuilding the configure scripts
|
||||||
|
|
||||||
|
If configure does not work on your system, or if you have a need to
|
||||||
|
change configure.ac or Makefile.am, and you have a reasonably
|
||||||
|
up-to-date set of tools, running ./autogen.sh in a git clone before
|
||||||
|
running ./configure may fix the problem. To be really sure that you
|
||||||
|
aren't using any of the included pre-built scripts, especially if you
|
||||||
|
are building from a tar distribution instead of a git distribution,
|
||||||
|
do this:
|
||||||
|
|
||||||
|
./configure --enable-maintainer-mode
|
||||||
|
make maintainer-clean
|
||||||
|
./autogen.sh --maintainer --clean
|
||||||
|
./autogen.sh --maintainer
|
||||||
|
./configure [--prefix=/path] [other options]
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
make check
|
||||||
|
|
||||||
|
III. Using scripts/makefile*
|
||||||
|
|
||||||
|
Instead, you can use one of the custom-built makefiles in the
|
||||||
|
"scripts" directory
|
||||||
|
|
||||||
|
cp scripts/pnglibconf.h.prebuilt pnglibconf.h
|
||||||
|
cp scripts/makefile.system makefile
|
||||||
|
make test
|
||||||
|
make install
|
||||||
|
|
||||||
|
The files that are presently available in the scripts directory
|
||||||
|
are listed and described in scripts/README.txt.
|
||||||
|
|
||||||
|
Or you can use one of the "projects" in the "projects" directory.
|
||||||
|
|
||||||
|
Before installing libpng, you must first install zlib, if it
|
||||||
|
is not already on your system. zlib can usually be found
|
||||||
|
wherever you got libpng; otherwise go to https://zlib.net/. You can
|
||||||
|
place zlib in the same directory as libpng or in another directory.
|
||||||
|
|
||||||
|
If your system already has a preinstalled zlib you will still need
|
||||||
|
to have access to the zlib.h and zconf.h include files that
|
||||||
|
correspond to the version of zlib that's installed.
|
||||||
|
|
||||||
|
If you wish to test with a particular zlib that is not first in the
|
||||||
|
standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS,
|
||||||
|
and LD_LIBRARY_PATH in your environment before running "make test"
|
||||||
|
or "make distcheck":
|
||||||
|
|
||||||
|
ZLIBLIB=/path/to/lib export ZLIBLIB
|
||||||
|
ZLIBINC=/path/to/include export ZLIBINC
|
||||||
|
CPPFLAGS="-I$ZLIBINC" export CPPFLAGS
|
||||||
|
LDFLAGS="-L$ZLIBLIB" export LDFLAGS
|
||||||
|
LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC
|
||||||
|
in your environment and type
|
||||||
|
|
||||||
|
make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test
|
||||||
|
|
||||||
|
IV. Using cmake
|
||||||
|
|
||||||
|
If you want to use "cmake" (see www.cmake.org), type
|
||||||
|
|
||||||
|
cmake . -DCMAKE_INSTALL_PREFIX=/path
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
|
||||||
|
As when using the simple configure method described above, "/path" points to
|
||||||
|
the installation directory where you want to put the libpng "lib", "include",
|
||||||
|
and "bin" subdirectories.
|
||||||
|
|
||||||
|
V. Directory structure
|
||||||
|
|
||||||
|
You can rename the directories that you downloaded (they
|
||||||
|
might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.8"
|
||||||
|
or "zlib128") so that you have directories called "zlib" and "libpng".
|
||||||
|
|
||||||
|
Your directory structure should look like this:
|
||||||
|
|
||||||
|
.. (the parent directory)
|
||||||
|
libpng (this directory)
|
||||||
|
INSTALL (this file)
|
||||||
|
README
|
||||||
|
*.h, *.c => libpng source files
|
||||||
|
CMakeLists.txt => "cmake" script
|
||||||
|
ci
|
||||||
|
ci_*.sh
|
||||||
|
configuration files:
|
||||||
|
configure.ac, configure, Makefile.am, Makefile.in,
|
||||||
|
autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in,
|
||||||
|
libpng-config.in, aclocal.m4, config.h.in, config.sub,
|
||||||
|
depcomp, install-sh, mkinstalldirs, test-pngtest.sh, etc.
|
||||||
|
contrib
|
||||||
|
arm-neon, conftest, examples, gregbook, libtests, pngminim,
|
||||||
|
pngminus, pngsuite, tools, visupng
|
||||||
|
projects
|
||||||
|
owatcom, visualc71, vstudio
|
||||||
|
scripts
|
||||||
|
makefile.*
|
||||||
|
*.def (module definition files)
|
||||||
|
etc.
|
||||||
|
pngtest.png
|
||||||
|
etc.
|
||||||
|
zlib
|
||||||
|
README, *.h, *.c, contrib, etc.
|
||||||
|
|
||||||
|
If the line endings in the files look funny, you may wish to get the other
|
||||||
|
distribution of libpng. It is available in both tar.gz (UNIX style line
|
||||||
|
endings) and zip (DOS style line endings) formats.
|
||||||
|
|
||||||
|
VI. Building with project files
|
||||||
|
|
||||||
|
If you are building libpng with Microsoft Visual Studio, you can enter
|
||||||
|
the directory projects\visualc71 or projects\vstudio and follow the
|
||||||
|
instructions in README.txt.
|
||||||
|
|
||||||
|
Otherwise, enter the zlib directory and follow the instructions in
|
||||||
|
zlib/README, then come back here and run "configure" or choose the
|
||||||
|
appropriate makefile in the scripts directory.
|
||||||
|
|
||||||
|
VII. Building with makefiles
|
||||||
|
|
||||||
|
Copy the file (or files) that you need from the
|
||||||
|
scripts directory into this directory, for example
|
||||||
|
|
||||||
|
UNIX example:
|
||||||
|
|
||||||
|
cp scripts/makefile.std Makefile
|
||||||
|
make
|
||||||
|
|
||||||
|
Windows example:
|
||||||
|
|
||||||
|
nmake -f scripts\makefile.vcwin32
|
||||||
|
|
||||||
|
Read the makefile to see if you need to change any source or
|
||||||
|
target directories to match your preferences.
|
||||||
|
|
||||||
|
Then read pnglibconf.dfa to see if you want to make any configuration
|
||||||
|
changes.
|
||||||
|
|
||||||
|
Then just run "make" which will create the libpng library in
|
||||||
|
this directory and "make test" which will run a quick test that reads
|
||||||
|
the "pngtest.png" file and writes a "pngout.png" file that should be
|
||||||
|
identical to it. Look for "9782 zero samples" in the output of the
|
||||||
|
test. For more confidence, you can run another test by typing
|
||||||
|
"pngtest pngnow.png" and looking for "289 zero samples" in the output.
|
||||||
|
Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare
|
||||||
|
your output with the result shown in contrib/pngsuite/README.
|
||||||
|
|
||||||
|
Most of the makefiles used to allow you to run "make install" to put
|
||||||
|
the library in its final resting place, but that feature is no longer
|
||||||
|
supported. The only tested and supported manners to install libpng are
|
||||||
|
the conventional build and install procedures driven by the configure
|
||||||
|
script or by the CMake file.
|
||||||
|
|
||||||
|
VIII. Configuring for DOS and other 16-bit platforms
|
||||||
|
|
||||||
|
Officially, the support for 16-bit platforms has been removed.
|
||||||
|
|
||||||
|
For DOS users who only have access to the lower 640K, you will
|
||||||
|
have to limit zlib's memory usage via a png_set_compression_mem_level()
|
||||||
|
call. See zlib.h or zconf.h in the zlib library for more information.
|
||||||
|
|
||||||
|
You may be or may not be in luck if you target the "large" memory model,
|
||||||
|
but all the smaller models ("small", "compact" and "medium") are known
|
||||||
|
to be unworkable. For DOS users who have access beyond the lower 640K,
|
||||||
|
a "flat" 32-bit DOS model (such as DJGPP) is strongly recommended.
|
||||||
|
|
||||||
|
For DOS users who only have access to the lower 640K, you will have to
|
||||||
|
limit zlib's memory usage via a png_set_compression_mem_level() call.
|
||||||
|
You will also have to look into zconf.h to tell zlib (and thus libpng)
|
||||||
|
that it cannot allocate more than 64K at a time. Even if you can, the
|
||||||
|
memory won't be accessible. Therefore, you should limit zlib and libpng
|
||||||
|
to 64K by defining MAXSEG_64K.
|
||||||
|
|
||||||
|
IX. Prepending a prefix to exported symbols
|
||||||
|
|
||||||
|
Starting with libpng-1.6.0, you can configure libpng (when using the
|
||||||
|
"configure" script) to prefix all exported symbols by means of the
|
||||||
|
configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any
|
||||||
|
string beginning with a letter and containing only uppercase
|
||||||
|
and lowercase letters, digits, and the underscore (i.e., a C language
|
||||||
|
identifier). This creates a set of macros in pnglibconf.h, so this is
|
||||||
|
transparent to applications; their function calls get transformed by
|
||||||
|
the macros to use the modified names.
|
||||||
|
|
||||||
|
X. Configuring for compiler xxx:
|
||||||
|
|
||||||
|
All includes for libpng are in pngconf.h. If you need to add, change
|
||||||
|
or delete an include, this is the place to do it.
|
||||||
|
The includes that are not needed outside libpng are placed in pngpriv.h,
|
||||||
|
which is only used by the routines inside libpng itself.
|
||||||
|
The files in libpng proper only include pngpriv.h and png.h, which
|
||||||
|
in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h.
|
||||||
|
As of libpng-1.5.0, pngpriv.h also includes three other private header
|
||||||
|
files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material
|
||||||
|
that previously appeared in the public headers.
|
||||||
|
|
||||||
|
XI. Removing unwanted object code
|
||||||
|
|
||||||
|
There are a bunch of #define's in pngconf.h that control what parts of
|
||||||
|
libpng are compiled. All the defines end in _SUPPORTED. If you are
|
||||||
|
never going to use a capability, you can change the #define to #undef
|
||||||
|
before recompiling libpng and save yourself code and data space, or
|
||||||
|
you can turn off individual capabilities with defines that begin with
|
||||||
|
"PNG_NO_".
|
||||||
|
|
||||||
|
In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead.
|
||||||
|
|
||||||
|
You can also turn all of the transforms and ancillary chunk capabilities
|
||||||
|
off en masse with compiler directives that define
|
||||||
|
PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
|
||||||
|
or all four, along with directives to turn on any of the capabilities that
|
||||||
|
you do want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the
|
||||||
|
extra transformations but still leave the library fully capable of reading
|
||||||
|
and writing PNG files with all known public chunks. Use of the
|
||||||
|
PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library
|
||||||
|
that is incapable of reading or writing ancillary chunks. If you are
|
||||||
|
not using the progressive reading capability, you can turn that off
|
||||||
|
with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING
|
||||||
|
capability, which you'll still have).
|
||||||
|
|
||||||
|
All the reading and writing specific code are in separate files, so the
|
||||||
|
linker should only grab the files it needs. However, if you want to
|
||||||
|
make sure, or if you are building a stand alone library, all the
|
||||||
|
reading files start with "pngr" and all the writing files start with "pngw".
|
||||||
|
The files that don't match either (like png.c, pngtrans.c, etc.)
|
||||||
|
are used for both reading and writing, and always need to be included.
|
||||||
|
The progressive reader is in pngpread.c
|
||||||
|
|
||||||
|
If you are creating or distributing a dynamically linked library (a .so
|
||||||
|
or DLL file), you should not remove or disable any parts of the library,
|
||||||
|
as this will cause applications linked with different versions of the
|
||||||
|
library to fail if they call functions not available in your library.
|
||||||
|
The size of the library itself should not be an issue, because only
|
||||||
|
those sections that are actually used will be loaded into memory.
|
||||||
|
|
||||||
|
XII. Enabling or disabling hardware optimizations
|
||||||
|
|
||||||
|
Certain hardware capabilities, such as the Intel SSE instructions,
|
||||||
|
are normally detected at run time. Enable them with configure options
|
||||||
|
such as one of
|
||||||
|
|
||||||
|
--enable-arm-neon=yes
|
||||||
|
--enable-mips-msa=yes
|
||||||
|
--enable-intel-sse=yes
|
||||||
|
--enable-powerpc-vsx=yes
|
||||||
|
|
||||||
|
or enable them all at once with
|
||||||
|
|
||||||
|
--enable-hardware-optimizations=yes
|
||||||
|
|
||||||
|
or, if you are not using "configure", you can use one
|
||||||
|
or more of
|
||||||
|
|
||||||
|
CPPFLAGS += "-DPNG_ARM_NEON"
|
||||||
|
CPPFLAGS += "-DPNG_MIPS_MSA"
|
||||||
|
CPPFLAGS += "-DPNG_INTEL_SSE"
|
||||||
|
CPPFLAGS += "-DPNG_POWERPC_VSX"
|
||||||
|
|
||||||
|
See for example scripts/makefile.linux-opt
|
||||||
|
|
||||||
|
If you wish to avoid using them,
|
||||||
|
you can disable them via the configure option
|
||||||
|
|
||||||
|
--disable-hardware-optimizations
|
||||||
|
|
||||||
|
to disable them all, or
|
||||||
|
|
||||||
|
--enable-intel-sse=no
|
||||||
|
|
||||||
|
to disable a particular one,
|
||||||
|
or via compiler-command options such as
|
||||||
|
|
||||||
|
CPPFLAGS += "-DPNG_ARM_NEON_OPT=0, -DPNG_MIPS_MSA_OPT=0,
|
||||||
|
-DPNG_INTEL_SSE_OPT=0, -DPNG_POWERPC_VSX_OPT=0"
|
||||||
|
|
||||||
|
If you are using cmake, hardware optimizations are "on"
|
||||||
|
by default. To disable them, use
|
||||||
|
|
||||||
|
cmake . -DPNG_ARM_NEON=no -DPNG_INTEL_SSE=no \
|
||||||
|
-DPNG_MIPS_MSA=no -DPNG_POWERPC_VSX=no
|
||||||
|
|
||||||
|
or disable them all at once with
|
||||||
|
|
||||||
|
cmake . -DPNG_HARDWARE_OPTIMIZATIONS=no
|
||||||
|
|
||||||
|
XIII. Changes to the build and configuration of libpng in libpng-1.5.x
|
||||||
|
|
||||||
|
Details of internal changes to the library code can be found in the CHANGES
|
||||||
|
file and in the GIT repository logs. These will be of no concern to the vast
|
||||||
|
majority of library users or builders; however, the few who configure libpng
|
||||||
|
to a non-default feature set may need to change how this is done.
|
||||||
|
|
||||||
|
There should be no need for library builders to alter build scripts if
|
||||||
|
these use the distributed build support - configure or the makefiles -
|
||||||
|
however, users of the makefiles may care to update their build scripts
|
||||||
|
to build pnglibconf.h where the corresponding makefile does not do so.
|
||||||
|
|
||||||
|
Building libpng with a non-default configuration has changed completely.
|
||||||
|
The old method using pngusr.h should still work correctly even though the
|
||||||
|
way pngusr.h is used in the build has been changed; however, library
|
||||||
|
builders will probably want to examine the changes to take advantage of
|
||||||
|
new capabilities and to simplify their build system.
|
||||||
|
|
||||||
|
A. Specific changes to library configuration capabilities
|
||||||
|
|
||||||
|
The exact mechanism used to control attributes of API functions has
|
||||||
|
changed. A single set of operating system independent macro definitions
|
||||||
|
is used and operating system specific directives are defined in
|
||||||
|
pnglibconf.h
|
||||||
|
|
||||||
|
As part of this the mechanism used to choose procedure call standards on
|
||||||
|
those systems that allow a choice has been changed. At present this only
|
||||||
|
affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems
|
||||||
|
running on Intel processors. As before, PNGAPI is defined where required
|
||||||
|
to control the exported API functions; however, two new macros, PNGCBAPI
|
||||||
|
and PNGCAPI, are used instead for callback functions (PNGCBAPI) and
|
||||||
|
(PNGCAPI) for functions that must match a C library prototype (currently
|
||||||
|
only png_longjmp_ptr, which must match the C longjmp function.) The new
|
||||||
|
approach is documented in pngconf.h
|
||||||
|
|
||||||
|
Despite these changes, libpng 1.5.0 only supports the native C function
|
||||||
|
calling standard on those platforms tested so far ("__cdecl" on Microsoft
|
||||||
|
Windows). This is because the support requirements for alternative
|
||||||
|
calling conventions seem to no longer exist. Developers who find it
|
||||||
|
necessary to set PNG_API_RULE to 1 should advise the mailing list
|
||||||
|
(png-mng-implement) of this and library builders who use Openwatcom and
|
||||||
|
therefore set PNG_API_RULE to 2 should also contact the mailing list.
|
||||||
|
|
||||||
|
B. Changes to the configuration mechanism
|
||||||
|
|
||||||
|
Prior to libpng-1.5.0 library builders who needed to configure libpng
|
||||||
|
had either to modify the exported pngconf.h header file to add system
|
||||||
|
specific configuration or had to write feature selection macros into
|
||||||
|
pngusr.h and cause this to be included into pngconf.h by defining
|
||||||
|
PNG_USER_CONFIG. The latter mechanism had the disadvantage that an
|
||||||
|
application built without PNG_USER_CONFIG defined would see the
|
||||||
|
unmodified, default, libpng API and thus would probably fail to link.
|
||||||
|
|
||||||
|
These mechanisms still work in the configure build and in any makefile
|
||||||
|
build that builds pnglibconf.h, although the feature selection macros
|
||||||
|
have changed somewhat as described above. In 1.5.0, however, pngusr.h is
|
||||||
|
processed only once, at the time the exported header file pnglibconf.h is
|
||||||
|
built. pngconf.h no longer includes pngusr.h; therefore, pngusr.h is ignored
|
||||||
|
after the build of pnglibconf.h and it is never included in an application
|
||||||
|
build.
|
||||||
|
|
||||||
|
The formerly used alternative of adding a list of feature macros to the
|
||||||
|
CPPFLAGS setting in the build also still works; however, the macros will be
|
||||||
|
copied to pnglibconf.h and this may produce macro redefinition warnings
|
||||||
|
when the individual C files are compiled.
|
||||||
|
|
||||||
|
All configuration now only works if pnglibconf.h is built from
|
||||||
|
scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan
|
||||||
|
(the original author of awk) maintains C source code of that awk and this
|
||||||
|
and all known later implementations (often called by subtly different
|
||||||
|
names - nawk and gawk for example) are adequate to build pnglibconf.h.
|
||||||
|
The Sun Microsystems (now Oracle) program 'awk' is an earlier version
|
||||||
|
and does not work; this may also apply to other systems that have a
|
||||||
|
functioning awk called 'nawk'.
|
||||||
|
|
||||||
|
Configuration options are now documented in scripts/pnglibconf.dfa. This
|
||||||
|
file also includes dependency information that ensures a configuration is
|
||||||
|
consistent; that is, if a feature is switched off, dependent features are
|
||||||
|
also switched off. As a recommended alternative to using feature macros in
|
||||||
|
pngusr.h a system builder may also define equivalent options in pngusr.dfa
|
||||||
|
(or, indeed, any file) and add that to the configuration by setting
|
||||||
|
DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate
|
||||||
|
how to do this, and also illustrate a case where pngusr.h is still required.
|
||||||
|
|
||||||
|
After you have built libpng, the definitions that were recorded in
|
||||||
|
pnglibconf.h are available to your application (pnglibconf.h is included
|
||||||
|
in png.h and gets installed alongside png.h and pngconf.h in your
|
||||||
|
$PREFIX/include directory). Do not edit pnglibconf.h after you have built
|
||||||
|
libpng, because than the settings would not accurately reflect the settings
|
||||||
|
that were used to build libpng.
|
||||||
|
|
||||||
|
XIV. Setjmp/longjmp issues
|
||||||
|
|
||||||
|
Libpng uses setjmp()/longjmp() for error handling. Unfortunately setjmp()
|
||||||
|
is known to be not thread-safe on some platforms and we don't know of
|
||||||
|
any platform where it is guaranteed to be thread-safe. Therefore, if
|
||||||
|
your application is going to be using multiple threads, you should
|
||||||
|
configure libpng with PNG_NO_SETJMP in your pngusr.dfa file, with
|
||||||
|
-DPNG_NO_SETJMP on your compile line, or with
|
||||||
|
|
||||||
|
#undef PNG_SETJMP_SUPPORTED
|
||||||
|
|
||||||
|
in your pnglibconf.h or pngusr.h.
|
||||||
|
|
||||||
|
Starting with libpng-1.6.0, the library included a "simplified API".
|
||||||
|
This requires setjmp/longjmp, so you must either build the library
|
||||||
|
with PNG_SETJMP_SUPPORTED defined, or with PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
and PNG_SIMPLIFIED_WRITE_SUPPORTED undefined.
|
||||||
|
|
||||||
|
XV. Common linking failures
|
||||||
|
|
||||||
|
If your application fails to find libpng or zlib entries while linking:
|
||||||
|
|
||||||
|
Be sure "-lz" appears after "-lpng" on your linking command.
|
||||||
|
|
||||||
|
Be sure you have built libpng, zlib, and your application for the
|
||||||
|
same platform (e.g., 32-bit or 64-bit).
|
||||||
|
|
||||||
|
If you are using the vstudio project, observe the WARNING in
|
||||||
|
project/vstudio/README.txt.
|
||||||
|
|
||||||
|
XVI. Other sources of information about libpng:
|
||||||
|
|
||||||
|
Further information can be found in the README and libpng-manual.txt
|
||||||
|
files, in the individual makefiles, in png.h, and the manual pages
|
||||||
|
libpng.3 and png.5.
|
||||||
|
|
||||||
|
Copyright (c) 2022 Cosmin Truta
|
||||||
|
Copyright (c) 1998-2002,2006-2016 Glenn Randers-Pehrson
|
||||||
|
This document is released under the libpng license.
|
||||||
|
For conditions of distribution and use, see the disclaimer
|
||||||
|
and license in png.h.
|
|
@ -0,0 +1,134 @@
|
||||||
|
COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
PNG Reference Library License version 2
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
* Copyright (c) 1995-2022 The PNG Reference Library Authors.
|
||||||
|
* Copyright (c) 2018-2022 Cosmin Truta.
|
||||||
|
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
|
||||||
|
* Copyright (c) 1996-1997 Andreas Dilger.
|
||||||
|
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||||
|
|
||||||
|
The software is supplied "as is", without warranty of any kind,
|
||||||
|
express or implied, including, without limitation, the warranties
|
||||||
|
of merchantability, fitness for a particular purpose, title, and
|
||||||
|
non-infringement. In no event shall the Copyright owners, or
|
||||||
|
anyone distributing the software, be liable for any damages or
|
||||||
|
other liability, whether in contract, tort or otherwise, arising
|
||||||
|
from, out of, or in connection with the software, or the use or
|
||||||
|
other dealings in the software, even if advised of the possibility
|
||||||
|
of such damage.
|
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute
|
||||||
|
this software, or portions hereof, for any purpose, without fee,
|
||||||
|
subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you
|
||||||
|
must not claim that you wrote the original software. If you
|
||||||
|
use this software in a product, an acknowledgment in the product
|
||||||
|
documentation would be appreciated, but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must
|
||||||
|
not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This Copyright notice may not be removed or altered from any
|
||||||
|
source or altered source distribution.
|
||||||
|
|
||||||
|
|
||||||
|
PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
|
||||||
|
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
|
||||||
|
derived from libpng-1.0.6, and are distributed according to the same
|
||||||
|
disclaimer and license as libpng-1.0.6 with the following individuals
|
||||||
|
added to the list of Contributing Authors:
|
||||||
|
|
||||||
|
Simon-Pierre Cadieux
|
||||||
|
Eric S. Raymond
|
||||||
|
Mans Rullgard
|
||||||
|
Cosmin Truta
|
||||||
|
Gilles Vollant
|
||||||
|
James Yu
|
||||||
|
Mandar Sahastrabuddhe
|
||||||
|
Google Inc.
|
||||||
|
Vadim Barkov
|
||||||
|
|
||||||
|
and with the following additions to the disclaimer:
|
||||||
|
|
||||||
|
There is no warranty against interference with your enjoyment of
|
||||||
|
the library or against infringement. There is no warranty that our
|
||||||
|
efforts or the library will fulfill any of your particular purposes
|
||||||
|
or needs. This library is provided with all faults, and the entire
|
||||||
|
risk of satisfactory quality, performance, accuracy, and effort is
|
||||||
|
with the user.
|
||||||
|
|
||||||
|
Some files in the "contrib" directory and some configure-generated
|
||||||
|
files that are distributed with libpng have other copyright owners, and
|
||||||
|
are released under other open source licenses.
|
||||||
|
|
||||||
|
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
|
||||||
|
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
|
||||||
|
libpng-0.96, and are distributed according to the same disclaimer and
|
||||||
|
license as libpng-0.96, with the following individuals added to the
|
||||||
|
list of Contributing Authors:
|
||||||
|
|
||||||
|
Tom Lane
|
||||||
|
Glenn Randers-Pehrson
|
||||||
|
Willem van Schaik
|
||||||
|
|
||||||
|
libpng versions 0.89, June 1996, through 0.96, May 1997, are
|
||||||
|
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
|
||||||
|
and are distributed according to the same disclaimer and license as
|
||||||
|
libpng-0.88, with the following individuals added to the list of
|
||||||
|
Contributing Authors:
|
||||||
|
|
||||||
|
John Bowler
|
||||||
|
Kevin Bracey
|
||||||
|
Sam Bushell
|
||||||
|
Magnus Holmgren
|
||||||
|
Greg Roelofs
|
||||||
|
Tom Tanner
|
||||||
|
|
||||||
|
Some files in the "scripts" directory have other copyright owners,
|
||||||
|
but are released under this license.
|
||||||
|
|
||||||
|
libpng versions 0.5, May 1995, through 0.88, January 1996, are
|
||||||
|
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||||
|
|
||||||
|
For the purposes of this copyright and license, "Contributing Authors"
|
||||||
|
is defined as the following set of individuals:
|
||||||
|
|
||||||
|
Andreas Dilger
|
||||||
|
Dave Martindale
|
||||||
|
Guy Eric Schalnat
|
||||||
|
Paul Schmidt
|
||||||
|
Tim Wegner
|
||||||
|
|
||||||
|
The PNG Reference Library is supplied "AS IS". The Contributing
|
||||||
|
Authors and Group 42, Inc. disclaim all warranties, expressed or
|
||||||
|
implied, including, without limitation, the warranties of
|
||||||
|
merchantability and of fitness for any purpose. The Contributing
|
||||||
|
Authors and Group 42, Inc. assume no liability for direct, indirect,
|
||||||
|
incidental, special, exemplary, or consequential damages, which may
|
||||||
|
result from the use of the PNG Reference Library, even if advised of
|
||||||
|
the possibility of such damage.
|
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute this
|
||||||
|
source code, or portions hereof, for any purpose, without fee, subject
|
||||||
|
to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this source code must not be misrepresented.
|
||||||
|
|
||||||
|
2. Altered versions must be plainly marked as such and must not
|
||||||
|
be misrepresented as being the original source.
|
||||||
|
|
||||||
|
3. This Copyright notice may not be removed or altered from any
|
||||||
|
source or altered source distribution.
|
||||||
|
|
||||||
|
The Contributing Authors and Group 42, Inc. specifically permit,
|
||||||
|
without fee, and encourage the use of this source code as a component
|
||||||
|
to supporting the PNG file format in commercial products. If you use
|
||||||
|
this source code in a product, acknowledgment is not required but would
|
||||||
|
be appreciated.
|
|
@ -0,0 +1,392 @@
|
||||||
|
# Makefile.am, the source file for Makefile.in (and hence Makefile), is
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Cosmin Truta
|
||||||
|
# Copyright (c) 2004-2016 Glenn Randers-Pehrson
|
||||||
|
#
|
||||||
|
# This code is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h
|
||||||
|
|
||||||
|
PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I scripts
|
||||||
|
|
||||||
|
# test programs - run on make check, make distcheck
|
||||||
|
check_PROGRAMS= pngtest pngunknown pngstest pngvalid pngimage pngcp
|
||||||
|
if HAVE_CLOCK_GETTIME
|
||||||
|
check_PROGRAMS += timepng
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Utilities - installed
|
||||||
|
bin_PROGRAMS= pngfix png-fix-itxt
|
||||||
|
|
||||||
|
# This ensures that pnglibconf.h gets built at the start of 'make all' or
|
||||||
|
# 'make check', but it does not add dependencies to the individual programs,
|
||||||
|
# this is done below.
|
||||||
|
#
|
||||||
|
# IMPORTANT: always add the object modules of new programs to the list below
|
||||||
|
# because otherwise the sequence 'configure; make new-program' will *sometimes*
|
||||||
|
# result in the installed (system) pnglibconf.h being used and the result is
|
||||||
|
# always wrong and always very confusing.
|
||||||
|
BUILT_SOURCES = pnglibconf.h
|
||||||
|
|
||||||
|
pngtest_SOURCES = pngtest.c
|
||||||
|
pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
pngvalid_SOURCES = contrib/libtests/pngvalid.c
|
||||||
|
pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
pngstest_SOURCES = contrib/libtests/pngstest.c
|
||||||
|
pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
pngunknown_SOURCES = contrib/libtests/pngunknown.c
|
||||||
|
pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
pngimage_SOURCES = contrib/libtests/pngimage.c
|
||||||
|
pngimage_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
timepng_SOURCES = contrib/libtests/timepng.c
|
||||||
|
timepng_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
pngfix_SOURCES = contrib/tools/pngfix.c
|
||||||
|
pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
png_fix_itxt_SOURCES = contrib/tools/png-fix-itxt.c
|
||||||
|
|
||||||
|
pngcp_SOURCES = contrib/tools/pngcp.c
|
||||||
|
pngcp_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
|
||||||
|
# Generally these are single line shell scripts to run a test with a particular
|
||||||
|
# set of parameters:
|
||||||
|
TESTS =\
|
||||||
|
tests/pngtest-all\
|
||||||
|
tests/pngvalid-gamma-16-to-8 tests/pngvalid-gamma-alpha-mode\
|
||||||
|
tests/pngvalid-gamma-background tests/pngvalid-gamma-expand16-alpha-mode\
|
||||||
|
tests/pngvalid-gamma-expand16-background\
|
||||||
|
tests/pngvalid-gamma-expand16-transform tests/pngvalid-gamma-sbit\
|
||||||
|
tests/pngvalid-gamma-threshold tests/pngvalid-gamma-transform\
|
||||||
|
tests/pngvalid-progressive-size\
|
||||||
|
tests/pngvalid-progressive-interlace-standard\
|
||||||
|
tests/pngvalid-transform\
|
||||||
|
tests/pngvalid-progressive-standard tests/pngvalid-standard\
|
||||||
|
tests/pngstest-1.8 tests/pngstest-1.8-alpha tests/pngstest-linear\
|
||||||
|
tests/pngstest-linear-alpha tests/pngstest-none tests/pngstest-none-alpha\
|
||||||
|
tests/pngstest-sRGB tests/pngstest-sRGB-alpha tests/pngunknown-IDAT\
|
||||||
|
tests/pngunknown-discard tests/pngunknown-if-safe tests/pngunknown-sAPI\
|
||||||
|
tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg\
|
||||||
|
tests/pngimage-quick tests/pngimage-full
|
||||||
|
|
||||||
|
# man pages
|
||||||
|
dist_man_MANS= libpng.3 libpngpf.3 png.5
|
||||||
|
|
||||||
|
# generate the -config scripts if required
|
||||||
|
binconfigs= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config
|
||||||
|
EXTRA_SCRIPTS= libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config
|
||||||
|
bin_SCRIPTS= @binconfigs@
|
||||||
|
|
||||||
|
# rules to build libpng, only build the old library on request
|
||||||
|
lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||||
|
# EXTRA_LTLIBRARIES= libpng.la
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\
|
||||||
|
pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\
|
||||||
|
pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\
|
||||||
|
png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa
|
||||||
|
|
||||||
|
if PNG_ARM_NEON
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\
|
||||||
|
arm/filter_neon.S arm/filter_neon_intrinsics.c \
|
||||||
|
arm/palette_neon_intrinsics.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if PNG_MIPS_MSA
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += mips/mips_init.c\
|
||||||
|
mips/filter_msa_intrinsics.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if PNG_INTEL_SSE
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += intel/intel_init.c\
|
||||||
|
intel/filter_sse2_intrinsics.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if PNG_POWERPC_VSX
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += powerpc/powerpc_init.c\
|
||||||
|
powerpc/filter_vsx_intrinsics.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h
|
||||||
|
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \
|
||||||
|
-version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0
|
||||||
|
|
||||||
|
if HAVE_LD_VERSION_SCRIPT
|
||||||
|
# Versioned symbols and restricted exports
|
||||||
|
if HAVE_SOLARIS_LD
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,-M -Wl,libpng.vers
|
||||||
|
else
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,--version-script=libpng.vers
|
||||||
|
endif
|
||||||
|
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers
|
||||||
|
else
|
||||||
|
# Only restricted exports when possible
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -export-symbols libpng.sym
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym
|
||||||
|
endif
|
||||||
|
|
||||||
|
#distribute headers in /usr/include/libpng/*
|
||||||
|
pkgincludedir= $(includedir)/$(PNGLIB_BASENAME)
|
||||||
|
pkginclude_HEADERS= png.h pngconf.h
|
||||||
|
nodist_pkginclude_HEADERS= pnglibconf.h
|
||||||
|
|
||||||
|
# pkg-config stuff, note that libpng.pc is always required in order
|
||||||
|
# to get the correct library
|
||||||
|
pkgconfigdir = @pkgconfigdir@
|
||||||
|
pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc
|
||||||
|
|
||||||
|
# Extra source distribution files, '${srcdir}' is used below to stop build files
|
||||||
|
# from those directories being included. This only works if the configure is
|
||||||
|
# not done in the source directory!
|
||||||
|
EXTRA_DIST= \
|
||||||
|
ANNOUNCE AUTHORS CHANGES INSTALL LICENSE README TODO TRADEMARK \
|
||||||
|
pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \
|
||||||
|
${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \
|
||||||
|
$(TESTS) $(XFAIL_TESTS) tests/pngstest \
|
||||||
|
CMakeLists.txt example.c libpng-manual.txt
|
||||||
|
|
||||||
|
SCRIPT_CLEANFILES=scripts/*.out scripts/*.chk
|
||||||
|
|
||||||
|
CLEANFILES= *.tf? pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \
|
||||||
|
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \
|
||||||
|
check.new pnglibconf.h pngprefix.h symbols.new pngtest-log.txt \
|
||||||
|
pnglibconf.out pnglibconf.c pnglibconf.pre pnglibconf.dfn \
|
||||||
|
$(SCRIPT_CLEANFILES)
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \
|
||||||
|
config.sub configure depcomp install-sh ltmain.sh missing
|
||||||
|
|
||||||
|
# PNG_COPTS give extra options for the C compiler to be used on all compilation
|
||||||
|
# steps (unless targe_CFLAGS is specified; that will take precedence over
|
||||||
|
# AM_CFLAGS)
|
||||||
|
PNG_COPTS = @PNG_COPTS@
|
||||||
|
AM_CFLAGS = ${PNG_COPTS}
|
||||||
|
|
||||||
|
# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe
|
||||||
|
# other operating systems (NeXT?) the C preprocessor selected by configure
|
||||||
|
# checks input tokens for validity - effectively it performs part of the ANSI-C
|
||||||
|
# parsing - and therefore fails with the .df files. configure.ac has special
|
||||||
|
# checks for this and sets DFNCPP appropriately.
|
||||||
|
DFNCPP = @DFNCPP@
|
||||||
|
|
||||||
|
SUFFIXES = .chk .out
|
||||||
|
|
||||||
|
$(PNGLIB_BASENAME).pc: libpng.pc
|
||||||
|
cp libpng.pc $@
|
||||||
|
|
||||||
|
$(PNGLIB_BASENAME)-config: libpng-config
|
||||||
|
cp libpng-config $@
|
||||||
|
|
||||||
|
scripts/sym.out scripts/vers.out: png.h pngconf.h pnglibconf.h
|
||||||
|
scripts/prefix.out: png.h pngconf.h pnglibconf.out
|
||||||
|
scripts/symbols.out: png.h pngconf.h $(srcdir)/scripts/pnglibconf.h.prebuilt
|
||||||
|
scripts/intprefix.out: pnglibconf.h
|
||||||
|
|
||||||
|
libpng.sym: scripts/sym.out
|
||||||
|
rm -f $@
|
||||||
|
cp $? $@
|
||||||
|
libpng.vers: scripts/vers.out
|
||||||
|
rm -f $@
|
||||||
|
cp $? $@
|
||||||
|
|
||||||
|
if DO_PNG_PREFIX
|
||||||
|
# Rename functions in scripts/prefix.out with a PNG_PREFIX prefix.
|
||||||
|
# Rename macros in scripts/macro.lst from PNG_PREFIXpng_ to PNG_ (the actual
|
||||||
|
# implementation of the macro).
|
||||||
|
pnglibconf.h: pnglibconf.out scripts/prefix.out scripts/macro.lst
|
||||||
|
rm -f $@
|
||||||
|
$(AWK) 's==0 && NR>1{print prev}\
|
||||||
|
s==0{prev=$$0}\
|
||||||
|
s==1{print "#define", $$1, "@PNG_PREFIX@" $$1}\
|
||||||
|
s==2{print "#define @PNG_PREFIX@png_" $$1, "PNG_" $$1}\
|
||||||
|
END{print prev}' s=0 pnglibconf.out s=1 scripts/prefix.out\
|
||||||
|
s=2 ${srcdir}/scripts/macro.lst >pnglibconf.tf8
|
||||||
|
mv pnglibconf.tf8 $@
|
||||||
|
|
||||||
|
pngprefix.h: scripts/intprefix.out
|
||||||
|
rm -f pngprefix.tf1
|
||||||
|
$(AWK) '{print "#define", $$1, "@PNG_PREFIX@" $$1}' $? >pngprefix.tf1
|
||||||
|
mv pngprefix.tf1 $@
|
||||||
|
else
|
||||||
|
pnglibconf.h: pnglibconf.out
|
||||||
|
rm -f $@
|
||||||
|
cp $? $@
|
||||||
|
|
||||||
|
pngprefix.h: # is empty
|
||||||
|
:>$@
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(srcdir)/scripts/pnglibconf.h.prebuilt:
|
||||||
|
@echo "Attempting to build $@" >&2
|
||||||
|
@echo "This is a machine generated file, but if you want to make" >&2
|
||||||
|
@echo "a new one simply make 'scripts/pnglibconf.out', copy that" >&2
|
||||||
|
@echo "AND set PNG_ZLIB_VERNUM to 0 (you MUST do this)" >&2
|
||||||
|
@exit 1
|
||||||
|
|
||||||
|
# The following is necessary to ensure that the local pnglibconf.h is used, not
|
||||||
|
# an installed one (this can happen immediately after on a clean system if
|
||||||
|
# 'make test' is the first thing the user does.) Only files which include
|
||||||
|
# one of the png source files (typically png.h or pngpriv.h) need to be listed
|
||||||
|
# here:
|
||||||
|
pngtest.o: pnglibconf.h
|
||||||
|
|
||||||
|
contrib/libtests/makepng.o: pnglibconf.h
|
||||||
|
contrib/libtests/pngstest.o: pnglibconf.h
|
||||||
|
contrib/libtests/pngunknown.o: pnglibconf.h
|
||||||
|
contrib/libtests/pngimage.o: pnglibconf.h
|
||||||
|
contrib/libtests/pngvalid.o: pnglibconf.h
|
||||||
|
contrib/libtests/readpng.o: pnglibconf.h
|
||||||
|
contrib/libtests/tarith.o: pnglibconf.h
|
||||||
|
contrib/libtests/timepng.o: pnglibconf.h
|
||||||
|
|
||||||
|
contrib/tools/makesRGB.o: pnglibconf.h
|
||||||
|
contrib/tools/pngfix.o: pnglibconf.h
|
||||||
|
contrib/tools/pngcp.o: pnglibconf.h
|
||||||
|
|
||||||
|
# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually
|
||||||
|
# be built with PNG_USE_READ_MACROS; this prevents the read macros from
|
||||||
|
# interfering with the symbol file format.
|
||||||
|
SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0'\
|
||||||
|
-DPNGLIB_VERSION='@PNGLIB_VERSION@'\
|
||||||
|
-DSYMBOL_PREFIX='$(SYMBOL_PREFIX)'\
|
||||||
|
-DPNG_NO_USE_READ_MACROS -DPNG_BUILDING_SYMBOL_TABLE
|
||||||
|
|
||||||
|
if DO_PNG_PREFIX
|
||||||
|
SYMBOL_CFLAGS += -DPNG_PREFIX='@PNG_PREFIX@'
|
||||||
|
endif
|
||||||
|
|
||||||
|
.c.out:
|
||||||
|
rm -f $@ $*.tf[12]
|
||||||
|
test -d scripts || mkdir scripts || test -d scripts
|
||||||
|
$(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\
|
||||||
|
$(CPPFLAGS) $(SYMBOL_CFLAGS) $< > $*.tf1
|
||||||
|
$(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2
|
||||||
|
rm -f $*.tf1
|
||||||
|
mv $*.tf2 $@
|
||||||
|
|
||||||
|
# The .c file for pnglibconf.h is machine generated
|
||||||
|
pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA)
|
||||||
|
rm -f $@ $*.tf[45]
|
||||||
|
$(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf4 version=search\
|
||||||
|
${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\
|
||||||
|
${srcdir}/pngusr.dfa $(DFA_XTRA) 1>&2
|
||||||
|
$(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf5 $*.tf4 1>&2
|
||||||
|
rm $*.tf4
|
||||||
|
mv $*.tf5 $@
|
||||||
|
|
||||||
|
# Symbol checks (.def and .out files should match)
|
||||||
|
scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.out
|
||||||
|
|
||||||
|
.out.chk:
|
||||||
|
rm -f $@ $*.new
|
||||||
|
$(AWK) -f ${srcdir}/scripts/checksym.awk ${srcdir}/scripts/${*F}.def\
|
||||||
|
of="$*.new" $< >&2
|
||||||
|
mv $*.new $@
|
||||||
|
|
||||||
|
# used on demand to regenerate the standard header, CPPFLAGS should
|
||||||
|
# be empty - no non-standard defines
|
||||||
|
scripts/pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h
|
||||||
|
rm -f $@ pnglibconf.tf[67]
|
||||||
|
test -z "$(CPPFLAGS)"
|
||||||
|
echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\
|
||||||
|
$(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf6\
|
||||||
|
logunsupported=1 version=search ${srcdir}/pngconf.h -\
|
||||||
|
${srcdir}/scripts/pnglibconf.dfa 1>&2
|
||||||
|
$(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf7\
|
||||||
|
pnglibconf.tf6 1>&2
|
||||||
|
rm pnglibconf.tf6
|
||||||
|
mv pnglibconf.tf7 $@
|
||||||
|
|
||||||
|
$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h \
|
||||||
|
pnglibconf.h pngpriv.h pngdebug.h pnginfo.h pngstruct.h pngprefix.h
|
||||||
|
|
||||||
|
test: check-am
|
||||||
|
|
||||||
|
# Extra checks
|
||||||
|
check: scripts/symbols.chk
|
||||||
|
|
||||||
|
# Don't distribute the generated script files
|
||||||
|
dist-hook:
|
||||||
|
cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES)
|
||||||
|
|
||||||
|
# Make links between installed files with release-specific names and the generic
|
||||||
|
# file names. If this install rule is run the generic names will be deleted and
|
||||||
|
# recreated - this has obvious issues for systems with multiple installations.
|
||||||
|
|
||||||
|
install-header-links:
|
||||||
|
@set -ex; cd '$(DESTDIR)$(includedir)'; for f in $(HEADERS); do \
|
||||||
|
rm -f "$$f"; $(LN_S) "$(PNGLIB_BASENAME)/$$f" "$$f"; done
|
||||||
|
|
||||||
|
uninstall-header-links:
|
||||||
|
cd '$(DESTDIR)$(includedir)'; rm -f $(HEADERS)
|
||||||
|
|
||||||
|
install-libpng-pc:
|
||||||
|
@set -ex; cd '$(DESTDIR)$(pkgconfigdir)'; rm -f libpng.pc; \
|
||||||
|
$(LN_S) '$(PNGLIB_BASENAME).pc' libpng.pc
|
||||||
|
|
||||||
|
uninstall-libpng-pc:
|
||||||
|
rm -f '$(DESTDIR)$(pkgconfigdir)/libpng.pc'
|
||||||
|
|
||||||
|
# EXT_LIST is a list of the possibly library directory extensions, this exists
|
||||||
|
# because we can't find a good way of discovering the file extensions that are
|
||||||
|
# actually installed on a given system, so instead we check for every extension
|
||||||
|
# we have seen.
|
||||||
|
|
||||||
|
EXT_LIST = a dll.a so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ la sl dylib
|
||||||
|
|
||||||
|
install-library-links:
|
||||||
|
@set -x; cd '$(DESTDIR)$(libdir)';\
|
||||||
|
for ext in $(EXT_LIST); do\
|
||||||
|
rm -f "libpng.$$ext";\
|
||||||
|
if test -f "$(PNGLIB_BASENAME).$$ext"; then\
|
||||||
|
$(LN_S) "$(PNGLIB_BASENAME).$$ext" "libpng.$$ext" || exit 1;\
|
||||||
|
fi;\
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-library-links:
|
||||||
|
@set -x; cd '$(DESTDIR)$(libdir)'; for ext in $(EXT_LIST); do\
|
||||||
|
rm -f "libpng.$$ext"; done
|
||||||
|
|
||||||
|
install-libpng-config:
|
||||||
|
@set -ex; cd '$(DESTDIR)$(bindir)'; rm -f libpng-config; \
|
||||||
|
$(LN_S) '$(PNGLIB_BASENAME)-config' libpng-config
|
||||||
|
|
||||||
|
uninstall-libpng-config:
|
||||||
|
rm -f '$(DESTDIR)$(bindir)/libpng-config'
|
||||||
|
|
||||||
|
if DO_INSTALL_LINKS
|
||||||
|
# If --enable-unversioned-links is specified the header and lib file links
|
||||||
|
# will be automatically made on a 'make install':
|
||||||
|
|
||||||
|
install-data-hook: install-header-links
|
||||||
|
uninstall-hook: uninstall-header-links
|
||||||
|
install-exec-hook: install-library-links
|
||||||
|
uninstall-hook: uninstall-library-links
|
||||||
|
endif
|
||||||
|
|
||||||
|
if DO_INSTALL_LIBPNG_PC
|
||||||
|
# Likewise, --install-pc causes libpng.pc to be constructed:
|
||||||
|
|
||||||
|
install-data-hook: install-libpng-pc
|
||||||
|
uninstall-hook: uninstall-libpng-pc
|
||||||
|
endif
|
||||||
|
|
||||||
|
if DO_INSTALL_LIBPNG_CONFIG
|
||||||
|
# And --install-config:
|
||||||
|
|
||||||
|
install-exec-hook: install-libpng-config
|
||||||
|
uninstall-hook: uninstall-libpng-config
|
||||||
|
endif
|
||||||
|
|
||||||
|
# The following addition ensures that 'make all' always builds the test programs
|
||||||
|
# too. It used to, but some change either in libpng or configure stopped this
|
||||||
|
# working.
|
||||||
|
all-am: $(check_PROGRAMS)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,184 @@
|
||||||
|
README for libpng version 1.6.39
|
||||||
|
================================
|
||||||
|
|
||||||
|
See the note about version numbers near the top of png.h.
|
||||||
|
See INSTALL for instructions on how to install libpng.
|
||||||
|
|
||||||
|
Libpng comes in several distribution formats. Get libpng-*.tar.gz or
|
||||||
|
libpng-*.tar.xz if you want UNIX-style line endings in the text files,
|
||||||
|
or lpng*.7z or lpng*.zip if you want DOS-style line endings.
|
||||||
|
|
||||||
|
Version 0.89 was the first official release of libpng. Don't let the
|
||||||
|
fact that it's the first release fool you. The libpng library has been
|
||||||
|
in extensive use and testing since mid-1995. By late 1997 it had
|
||||||
|
finally gotten to the stage where there hadn't been significant
|
||||||
|
changes to the API in some time, and people have a bad feeling about
|
||||||
|
libraries with versions < 1.0. Version 1.0.0 was released in
|
||||||
|
March 1998.
|
||||||
|
|
||||||
|
****
|
||||||
|
Note that some of the changes to the png_info structure render this
|
||||||
|
version of the library binary incompatible with libpng-0.89 or
|
||||||
|
earlier versions if you are using a shared library. The type of the
|
||||||
|
"filler" parameter for png_set_filler() has changed from png_byte to
|
||||||
|
png_uint_32, which will affect shared-library applications that use
|
||||||
|
this function.
|
||||||
|
|
||||||
|
To avoid problems with changes to the internals of the png info_struct,
|
||||||
|
new APIs have been made available in 0.95 to avoid direct application
|
||||||
|
access to info_ptr. These functions are the png_set_<chunk> and
|
||||||
|
png_get_<chunk> functions. These functions should be used when
|
||||||
|
accessing/storing the info_struct data, rather than manipulating it
|
||||||
|
directly, to avoid such problems in the future.
|
||||||
|
|
||||||
|
It is important to note that the APIs did not make current programs
|
||||||
|
that access the info struct directly incompatible with the new
|
||||||
|
library, through libpng-1.2.x. In libpng-1.4.x, which was meant to
|
||||||
|
be a transitional release, members of the png_struct and the
|
||||||
|
info_struct can still be accessed, but the compiler will issue a
|
||||||
|
warning about deprecated usage. Since libpng-1.5.0, direct access
|
||||||
|
to these structs is not allowed, and the definitions of the structs
|
||||||
|
reside in private pngstruct.h and pnginfo.h header files that are not
|
||||||
|
accessible to applications. It is strongly suggested that new
|
||||||
|
programs use the new APIs (as shown in example.c and pngtest.c), and
|
||||||
|
older programs be converted to the new format, to facilitate upgrades
|
||||||
|
in the future.
|
||||||
|
****
|
||||||
|
|
||||||
|
Additions since 0.90 include the ability to compile libpng as a
|
||||||
|
Windows DLL, and new APIs for accessing data in the info struct.
|
||||||
|
Experimental functions include the ability to set weighting and cost
|
||||||
|
factors for row filter selection, direct reads of integers from buffers
|
||||||
|
on big-endian processors that support misaligned data access, faster
|
||||||
|
methods of doing alpha composition, and more accurate 16->8 bit color
|
||||||
|
conversion.
|
||||||
|
|
||||||
|
The additions since 0.89 include the ability to read from a PNG stream
|
||||||
|
which has had some (or all) of the signature bytes read by the calling
|
||||||
|
application. This also allows the reading of embedded PNG streams that
|
||||||
|
do not have the PNG file signature. As well, it is now possible to set
|
||||||
|
the library action on the detection of chunk CRC errors. It is possible
|
||||||
|
to set different actions based on whether the CRC error occurred in a
|
||||||
|
critical or an ancillary chunk.
|
||||||
|
|
||||||
|
For a detailed description on using libpng, read libpng-manual.txt.
|
||||||
|
For examples of libpng in a program, see example.c and pngtest.c. For
|
||||||
|
usage information and restrictions (what little they are) on libpng,
|
||||||
|
see png.h. For a description on using zlib (the compression library
|
||||||
|
used by libpng) and zlib's restrictions, see zlib.h
|
||||||
|
|
||||||
|
I have included a general makefile, as well as several machine and
|
||||||
|
compiler specific ones, but you may have to modify one for your own
|
||||||
|
needs.
|
||||||
|
|
||||||
|
You should use zlib 1.0.4 or later to run this, but it MAY work with
|
||||||
|
versions as old as zlib 0.95. Even so, there are bugs in older zlib
|
||||||
|
versions which can cause the output of invalid compression streams for
|
||||||
|
some images.
|
||||||
|
|
||||||
|
You should also note that zlib is a compression library that is useful
|
||||||
|
for more things than just PNG files. You can use zlib as a drop-in
|
||||||
|
replacement for fread() and fwrite(), if you are so inclined.
|
||||||
|
|
||||||
|
zlib should be available at the same place that libpng is, or at
|
||||||
|
https://zlib.net.
|
||||||
|
|
||||||
|
You may also want a copy of the PNG specification. It is available
|
||||||
|
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
|
||||||
|
these at http://www.libpng.org/pub/png/pngdocs.html .
|
||||||
|
|
||||||
|
This code is currently being archived at libpng.sourceforge.io in the
|
||||||
|
[DOWNLOAD] area, and at http://libpng.download/src .
|
||||||
|
|
||||||
|
This release, based in a large way on Glenn's, Guy's and Andreas'
|
||||||
|
earlier work, was created and will be supported by myself and the PNG
|
||||||
|
development group.
|
||||||
|
|
||||||
|
Send comments/corrections/commendations to png-mng-implement at
|
||||||
|
lists.sourceforge.net (subscription required; visit
|
||||||
|
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
|
||||||
|
to subscribe).
|
||||||
|
|
||||||
|
Send general questions about the PNG specification to png-mng-misc
|
||||||
|
at lists.sourceforge.net (subscription required; visit
|
||||||
|
https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
|
||||||
|
subscribe).
|
||||||
|
|
||||||
|
Files in this distribution:
|
||||||
|
|
||||||
|
ANNOUNCE => Announcement of this version, with recent changes
|
||||||
|
AUTHORS => List of contributing authors
|
||||||
|
CHANGES => Description of changes between libpng versions
|
||||||
|
INSTALL => Instructions to install libpng
|
||||||
|
LICENSE => License to use and redistribute libpng
|
||||||
|
README => This file
|
||||||
|
TODO => Things not implemented in the current library
|
||||||
|
TRADEMARK => Trademark information
|
||||||
|
example.c => Example code for using libpng functions
|
||||||
|
libpng.3 => Manual page for libpng (includes libpng-manual.txt)
|
||||||
|
libpng-manual.txt => Description of libpng and its functions
|
||||||
|
libpngpf.3 => Manual page for libpng's private functions (deprecated)
|
||||||
|
png.5 => Manual page for the PNG format
|
||||||
|
png.c => Basic interface functions common to library
|
||||||
|
png.h => Library function and interface declarations (public)
|
||||||
|
pngpriv.h => Library function and interface declarations (private)
|
||||||
|
pngconf.h => System specific library configuration (public)
|
||||||
|
pngstruct.h => png_struct declaration (private)
|
||||||
|
pnginfo.h => png_info struct declaration (private)
|
||||||
|
pngdebug.h => debugging macros (private)
|
||||||
|
pngerror.c => Error/warning message I/O functions
|
||||||
|
pngget.c => Functions for retrieving info from struct
|
||||||
|
pngmem.c => Memory handling functions
|
||||||
|
pngbar.png => PNG logo, 88x31
|
||||||
|
pngnow.png => PNG logo, 98x31
|
||||||
|
pngpread.c => Progressive reading functions
|
||||||
|
pngread.c => Read data/helper high-level functions
|
||||||
|
pngrio.c => Lowest-level data read I/O functions
|
||||||
|
pngrtran.c => Read data transformation functions
|
||||||
|
pngrutil.c => Read data utility functions
|
||||||
|
pngset.c => Functions for storing data into the info_struct
|
||||||
|
pngtest.c => Library test program
|
||||||
|
pngtest.png => Library test sample image
|
||||||
|
pngtrans.c => Common data transformation functions
|
||||||
|
pngwio.c => Lowest-level write I/O functions
|
||||||
|
pngwrite.c => High-level write functions
|
||||||
|
pngwtran.c => Write data transformations
|
||||||
|
pngwutil.c => Write utility functions
|
||||||
|
arm/ => Optimized code for the ARM platform
|
||||||
|
intel/ => Optimized code for the INTEL-SSE2 platform
|
||||||
|
mips/ => Optimized code for the MIPS platform
|
||||||
|
powerpc/ => Optimized code for the PowerPC platform
|
||||||
|
ci/ => Scripts for continuous integration
|
||||||
|
contrib/ => External contributions
|
||||||
|
arm-neon/ => Optimized code for the ARM-NEON platform
|
||||||
|
mips-msa/ => Optimized code for the MIPS-MSA platform
|
||||||
|
powerpc-vsx/ => Optimized code for the POWERPC-VSX platform
|
||||||
|
examples/ => Example programs
|
||||||
|
gregbook/ => Source code for PNG reading and writing, from
|
||||||
|
"PNG: The Definitive Guide" by Greg Roelofs,
|
||||||
|
O'Reilly, 1999
|
||||||
|
libtests/ => Test programs
|
||||||
|
oss-fuzz/ => Files used by the OSS-Fuzz project for fuzz-testing
|
||||||
|
libpng
|
||||||
|
pngminim/ => Minimal decoder, encoder, and progressive decoder
|
||||||
|
programs demonstrating the use of pngusr.dfa
|
||||||
|
pngminus/ => Simple pnm2png and png2pnm programs
|
||||||
|
pngsuite/ => Test images
|
||||||
|
testpngs/ => Test images
|
||||||
|
tools/ => Various tools
|
||||||
|
visupng/ => VisualPng, a Windows viewer for PNG images
|
||||||
|
projects/ => Project files and workspaces for various IDEs
|
||||||
|
owatcom/ => OpenWatcom project
|
||||||
|
visualc71/ => Microsoft Visual C++ 7.1 workspace
|
||||||
|
vstudio/ => Microsoft Visual Studio workspace
|
||||||
|
scripts/ => Scripts and makefiles for building libpng
|
||||||
|
(see scripts/README.txt for the complete list)
|
||||||
|
tests/ => Test scripts
|
||||||
|
|
||||||
|
Good luck, and happy coding!
|
||||||
|
|
||||||
|
* Cosmin Truta (current maintainer, since 2018)
|
||||||
|
* Glenn Randers-Pehrson (former maintainer, 1998-2018)
|
||||||
|
* Andreas Eric Dilger (former maintainer, 1996-1997)
|
||||||
|
* Guy Eric Schalnat (original author and former maintainer, 1995-1996)
|
||||||
|
(formerly of Group 42, Inc.)
|
|
@ -0,0 +1,23 @@
|
||||||
|
TODO - list of things to do for libpng:
|
||||||
|
|
||||||
|
* Fix all defects (duh!)
|
||||||
|
* Better C++ wrapper / full C++ implementation (?)
|
||||||
|
* Fix the problems with C++ and 'extern "C"'.
|
||||||
|
* cHRM transformation.
|
||||||
|
* Palette creation.
|
||||||
|
* "grayscale->palette" transformation and "palette->grayscale" detection.
|
||||||
|
* Improved dithering.
|
||||||
|
* Multi-lingual error and warning message support.
|
||||||
|
* Complete sRGB transformation. (Currently it simply uses gamma=0.45455.)
|
||||||
|
* Man pages for function calls.
|
||||||
|
* Better documentation.
|
||||||
|
* Better filter selection
|
||||||
|
(e.g., counting huffman bits/precompression; filter inertia; filter costs).
|
||||||
|
* Histogram creation.
|
||||||
|
* Text conversion between different code pages (e.g., Latin-1 -> Mac).
|
||||||
|
* Avoid building gamma tables whenever possible.
|
||||||
|
* Greater precision in changing to linear gamma for compositing against
|
||||||
|
background, and in doing rgb-to-gray transformations.
|
||||||
|
* Investigate pre-incremented loop counters and other loop constructions.
|
||||||
|
* Interpolated method of handling interlacing.
|
||||||
|
* More validations for libpng transformations.
|
|
@ -0,0 +1,8 @@
|
||||||
|
TRADEMARK
|
||||||
|
=========
|
||||||
|
|
||||||
|
The name "libpng" has not been registered by the Copyright owners
|
||||||
|
as a trademark in any jurisdiction. However, because libpng has
|
||||||
|
been distributed and maintained world-wide, continually since 1995,
|
||||||
|
the Copyright owners claim "common-law trademark protection" in any
|
||||||
|
jurisdiction where common-law trademark is recognized.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,139 @@
|
||||||
|
|
||||||
|
/* arm_init.c - NEON optimised filter functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018-2022 Cosmin Truta
|
||||||
|
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
|
||||||
|
* Written by Mans Rullgard, 2011.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This module requires POSIX 1003.1 functions. */
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
|
||||||
|
#include "../pngpriv.h"
|
||||||
|
|
||||||
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
|
#if PNG_ARM_NEON_OPT > 0
|
||||||
|
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
|
||||||
|
/* WARNING: it is strongly recommended that you do not build libpng with
|
||||||
|
* run-time checks for CPU features if at all possible. In the case of the ARM
|
||||||
|
* NEON instructions there is no processor-specific way of detecting the
|
||||||
|
* presence of the required support, therefore run-time detection is extremely
|
||||||
|
* OS specific.
|
||||||
|
*
|
||||||
|
* You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
|
||||||
|
* a fragment of C source code which defines the png_have_neon function. There
|
||||||
|
* are a number of implementations in contrib/arm-neon, but the only one that
|
||||||
|
* has partial support is contrib/arm-neon/linux.c - a generic Linux
|
||||||
|
* implementation which reads /proc/cpufino.
|
||||||
|
*/
|
||||||
|
#include <signal.h> /* for sig_atomic_t */
|
||||||
|
|
||||||
|
#ifndef PNG_ARM_NEON_FILE
|
||||||
|
# if defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
/* ARM Neon is expected to be unconditionally available on ARM64. */
|
||||||
|
# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on ARM64"
|
||||||
|
# elif defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||||
|
/* ARM Neon is expected to be available on the target CPU architecture. */
|
||||||
|
# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this CPU arch"
|
||||||
|
# elif defined(__linux__)
|
||||||
|
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
|
||||||
|
# else
|
||||||
|
# error "No support for run-time ARM Neon checking; use compile-time options"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int png_have_neon(png_structp png_ptr);
|
||||||
|
#ifdef PNG_ARM_NEON_FILE
|
||||||
|
# include PNG_ARM_NEON_FILE
|
||||||
|
#endif
|
||||||
|
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||||
|
|
||||||
|
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
|
||||||
|
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
|
||||||
|
{
|
||||||
|
/* The switch statement is compiled in for ARM_NEON_API, the call to
|
||||||
|
* png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
|
||||||
|
* the check is only performed if the API has not set the NEON option on
|
||||||
|
* or off explicitly. In this case the check controls what happens.
|
||||||
|
*
|
||||||
|
* If the CHECK is not compiled in and the option is UNSET the behavior prior
|
||||||
|
* to 1.6.7 was to use the NEON code - this was a bug caused by having the
|
||||||
|
* wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
|
||||||
|
* as documented in png.h
|
||||||
|
*/
|
||||||
|
png_debug(1, "in png_init_filter_functions_neon");
|
||||||
|
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||||
|
switch ((pp->options >> PNG_ARM_NEON) & 3)
|
||||||
|
{
|
||||||
|
case PNG_OPTION_UNSET:
|
||||||
|
/* Allow the run-time check to execute if it has been enabled -
|
||||||
|
* thus both API and CHECK can be turned on. If it isn't supported
|
||||||
|
* this case will fall through to the 'default' below, which just
|
||||||
|
* returns.
|
||||||
|
*/
|
||||||
|
#endif /* PNG_ARM_NEON_API_SUPPORTED */
|
||||||
|
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
|
||||||
|
{
|
||||||
|
static volatile sig_atomic_t no_neon = -1; /* not checked */
|
||||||
|
|
||||||
|
if (no_neon < 0)
|
||||||
|
no_neon = !png_have_neon(pp);
|
||||||
|
|
||||||
|
if (no_neon)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||||
|
default: /* OFF or INVALID */
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PNG_OPTION_ON:
|
||||||
|
/* Option turned on */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* IMPORTANT: any new external functions used here must be declared using
|
||||||
|
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
|
||||||
|
* 'prefix' option to configure works:
|
||||||
|
*
|
||||||
|
* ./configure --with-libpng-prefix=foobar_
|
||||||
|
*
|
||||||
|
* Verify you have got this right by running the above command, doing a build
|
||||||
|
* and examining pngprefix.h; it must contain a #define for every external
|
||||||
|
* function you add. (Notice that this happens automatically for the
|
||||||
|
* initialization function.)
|
||||||
|
*/
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
|
||||||
|
|
||||||
|
if (bpp == 3)
|
||||||
|
{
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||||
|
png_read_filter_row_paeth3_neon;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (bpp == 4)
|
||||||
|
{
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
|
||||||
|
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||||
|
png_read_filter_row_paeth4_neon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||||
|
#endif /* READ */
|
|
@ -0,0 +1,253 @@
|
||||||
|
|
||||||
|
/* filter_neon.S - NEON optimised filter functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Cosmin Truta
|
||||||
|
* Copyright (c) 2014,2017 Glenn Randers-Pehrson
|
||||||
|
* Written by Mans Rullgard, 2011.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is required to get the symbol renames, which are #defines, and the
|
||||||
|
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
|
||||||
|
*/
|
||||||
|
#define PNG_VERSION_INFO_ONLY
|
||||||
|
#include "../pngpriv.h"
|
||||||
|
|
||||||
|
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
|
/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
|
||||||
|
* ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
|
||||||
|
* only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
|
||||||
|
* for the logic which sets PNG_USE_ARM_NEON_ASM:
|
||||||
|
*/
|
||||||
|
#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
|
||||||
|
|
||||||
|
#if PNG_ARM_NEON_OPT > 0
|
||||||
|
|
||||||
|
#ifdef __ELF__
|
||||||
|
# define ELF
|
||||||
|
#else
|
||||||
|
# define ELF @
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.arch armv7-a
|
||||||
|
.fpu neon
|
||||||
|
|
||||||
|
.macro func name, export=0
|
||||||
|
.macro endfunc
|
||||||
|
ELF .size \name, . - \name
|
||||||
|
.endfunc
|
||||||
|
.purgem endfunc
|
||||||
|
.endm
|
||||||
|
.text
|
||||||
|
|
||||||
|
/* Explicitly specifying alignment here because some versions of
|
||||||
|
* GAS don't align code correctly. This is harmless in correctly
|
||||||
|
* written versions of GAS.
|
||||||
|
*/
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
.if \export
|
||||||
|
.global \name
|
||||||
|
.endif
|
||||||
|
ELF .type \name, STT_FUNC
|
||||||
|
.func \name
|
||||||
|
\name:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
func png_read_filter_row_sub4_neon, export=1
|
||||||
|
ldr r3, [r0, #4] @ rowbytes
|
||||||
|
vmov.i8 d3, #0
|
||||||
|
1:
|
||||||
|
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||||
|
vadd.u8 d0, d3, d4
|
||||||
|
vadd.u8 d1, d0, d5
|
||||||
|
vadd.u8 d2, d1, d6
|
||||||
|
vadd.u8 d3, d2, d7
|
||||||
|
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||||
|
subs r3, r3, #16
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func png_read_filter_row_sub3_neon, export=1
|
||||||
|
ldr r3, [r0, #4] @ rowbytes
|
||||||
|
vmov.i8 d3, #0
|
||||||
|
mov r0, r1
|
||||||
|
mov r2, #3
|
||||||
|
mov r12, #12
|
||||||
|
vld1.8 {q11}, [r0], r12
|
||||||
|
1:
|
||||||
|
vext.8 d5, d22, d23, #3
|
||||||
|
vadd.u8 d0, d3, d22
|
||||||
|
vext.8 d6, d22, d23, #6
|
||||||
|
vadd.u8 d1, d0, d5
|
||||||
|
vext.8 d7, d23, d23, #1
|
||||||
|
vld1.8 {q11}, [r0], r12
|
||||||
|
vst1.32 {d0[0]}, [r1,:32], r2
|
||||||
|
vadd.u8 d2, d1, d6
|
||||||
|
vst1.32 {d1[0]}, [r1], r2
|
||||||
|
vadd.u8 d3, d2, d7
|
||||||
|
vst1.32 {d2[0]}, [r1], r2
|
||||||
|
vst1.32 {d3[0]}, [r1], r2
|
||||||
|
subs r3, r3, #12
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func png_read_filter_row_up_neon, export=1
|
||||||
|
ldr r3, [r0, #4] @ rowbytes
|
||||||
|
1:
|
||||||
|
vld1.8 {q0}, [r1,:128]
|
||||||
|
vld1.8 {q1}, [r2,:128]!
|
||||||
|
vadd.u8 q0, q0, q1
|
||||||
|
vst1.8 {q0}, [r1,:128]!
|
||||||
|
subs r3, r3, #16
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func png_read_filter_row_avg4_neon, export=1
|
||||||
|
ldr r12, [r0, #4] @ rowbytes
|
||||||
|
vmov.i8 d3, #0
|
||||||
|
1:
|
||||||
|
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||||
|
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||||
|
vhadd.u8 d0, d3, d16
|
||||||
|
vadd.u8 d0, d0, d4
|
||||||
|
vhadd.u8 d1, d0, d17
|
||||||
|
vadd.u8 d1, d1, d5
|
||||||
|
vhadd.u8 d2, d1, d18
|
||||||
|
vadd.u8 d2, d2, d6
|
||||||
|
vhadd.u8 d3, d2, d19
|
||||||
|
vadd.u8 d3, d3, d7
|
||||||
|
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||||
|
subs r12, r12, #16
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func png_read_filter_row_avg3_neon, export=1
|
||||||
|
push {r4,lr}
|
||||||
|
ldr r12, [r0, #4] @ rowbytes
|
||||||
|
vmov.i8 d3, #0
|
||||||
|
mov r0, r1
|
||||||
|
mov r4, #3
|
||||||
|
mov lr, #12
|
||||||
|
vld1.8 {q11}, [r0], lr
|
||||||
|
1:
|
||||||
|
vld1.8 {q10}, [r2], lr
|
||||||
|
vext.8 d5, d22, d23, #3
|
||||||
|
vhadd.u8 d0, d3, d20
|
||||||
|
vext.8 d17, d20, d21, #3
|
||||||
|
vadd.u8 d0, d0, d22
|
||||||
|
vext.8 d6, d22, d23, #6
|
||||||
|
vhadd.u8 d1, d0, d17
|
||||||
|
vext.8 d18, d20, d21, #6
|
||||||
|
vadd.u8 d1, d1, d5
|
||||||
|
vext.8 d7, d23, d23, #1
|
||||||
|
vld1.8 {q11}, [r0], lr
|
||||||
|
vst1.32 {d0[0]}, [r1,:32], r4
|
||||||
|
vhadd.u8 d2, d1, d18
|
||||||
|
vst1.32 {d1[0]}, [r1], r4
|
||||||
|
vext.8 d19, d21, d21, #1
|
||||||
|
vadd.u8 d2, d2, d6
|
||||||
|
vhadd.u8 d3, d2, d19
|
||||||
|
vst1.32 {d2[0]}, [r1], r4
|
||||||
|
vadd.u8 d3, d3, d7
|
||||||
|
vst1.32 {d3[0]}, [r1], r4
|
||||||
|
subs r12, r12, #12
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
pop {r4,pc}
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
.macro paeth rx, ra, rb, rc
|
||||||
|
vaddl.u8 q12, \ra, \rb @ a + b
|
||||||
|
vaddl.u8 q15, \rc, \rc @ 2*c
|
||||||
|
vabdl.u8 q13, \rb, \rc @ pa
|
||||||
|
vabdl.u8 q14, \ra, \rc @ pb
|
||||||
|
vabd.u16 q15, q12, q15 @ pc
|
||||||
|
vcle.u16 q12, q13, q14 @ pa <= pb
|
||||||
|
vcle.u16 q13, q13, q15 @ pa <= pc
|
||||||
|
vcle.u16 q14, q14, q15 @ pb <= pc
|
||||||
|
vand q12, q12, q13 @ pa <= pb && pa <= pc
|
||||||
|
vmovn.u16 d28, q14
|
||||||
|
vmovn.u16 \rx, q12
|
||||||
|
vbsl d28, \rb, \rc
|
||||||
|
vbsl \rx, \ra, d28
|
||||||
|
.endm
|
||||||
|
|
||||||
|
func png_read_filter_row_paeth4_neon, export=1
|
||||||
|
ldr r12, [r0, #4] @ rowbytes
|
||||||
|
vmov.i8 d3, #0
|
||||||
|
vmov.i8 d20, #0
|
||||||
|
1:
|
||||||
|
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||||
|
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||||
|
paeth d0, d3, d16, d20
|
||||||
|
vadd.u8 d0, d0, d4
|
||||||
|
paeth d1, d0, d17, d16
|
||||||
|
vadd.u8 d1, d1, d5
|
||||||
|
paeth d2, d1, d18, d17
|
||||||
|
vadd.u8 d2, d2, d6
|
||||||
|
paeth d3, d2, d19, d18
|
||||||
|
vmov d20, d19
|
||||||
|
vadd.u8 d3, d3, d7
|
||||||
|
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||||
|
subs r12, r12, #16
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func png_read_filter_row_paeth3_neon, export=1
|
||||||
|
push {r4,lr}
|
||||||
|
ldr r12, [r0, #4] @ rowbytes
|
||||||
|
vmov.i8 d3, #0
|
||||||
|
vmov.i8 d4, #0
|
||||||
|
mov r0, r1
|
||||||
|
mov r4, #3
|
||||||
|
mov lr, #12
|
||||||
|
vld1.8 {q11}, [r0], lr
|
||||||
|
1:
|
||||||
|
vld1.8 {q10}, [r2], lr
|
||||||
|
paeth d0, d3, d20, d4
|
||||||
|
vext.8 d5, d22, d23, #3
|
||||||
|
vadd.u8 d0, d0, d22
|
||||||
|
vext.8 d17, d20, d21, #3
|
||||||
|
paeth d1, d0, d17, d20
|
||||||
|
vst1.32 {d0[0]}, [r1,:32], r4
|
||||||
|
vext.8 d6, d22, d23, #6
|
||||||
|
vadd.u8 d1, d1, d5
|
||||||
|
vext.8 d18, d20, d21, #6
|
||||||
|
paeth d2, d1, d18, d17
|
||||||
|
vext.8 d7, d23, d23, #1
|
||||||
|
vld1.8 {q11}, [r0], lr
|
||||||
|
vst1.32 {d1[0]}, [r1], r4
|
||||||
|
vadd.u8 d2, d2, d6
|
||||||
|
vext.8 d19, d21, d21, #1
|
||||||
|
paeth d3, d2, d19, d18
|
||||||
|
vst1.32 {d2[0]}, [r1], r4
|
||||||
|
vmov d4, d19
|
||||||
|
vadd.u8 d3, d3, d7
|
||||||
|
vst1.32 {d3[0]}, [r1], r4
|
||||||
|
subs r12, r12, #12
|
||||||
|
bgt 1b
|
||||||
|
|
||||||
|
pop {r4,pc}
|
||||||
|
endfunc
|
||||||
|
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||||
|
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
|
||||||
|
#endif /* READ */
|
|
@ -0,0 +1,402 @@
|
||||||
|
|
||||||
|
/* filter_neon_intrinsics.c - NEON optimised filter functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Cosmin Truta
|
||||||
|
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
|
||||||
|
* Written by James Yu <james.yu at linaro.org>, October 2013.
|
||||||
|
* Based on filter_neon.S, written by Mans Rullgard, 2011.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../pngpriv.h"
|
||||||
|
|
||||||
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
|
/* This code requires -mfpu=neon on the command line: */
|
||||||
|
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
|
||||||
|
# include <arm64_neon.h>
|
||||||
|
#else
|
||||||
|
# include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* libpng row pointers are not necessarily aligned to any particular boundary,
|
||||||
|
* however this code will only work with appropriate alignment. arm/arm_init.c
|
||||||
|
* checks for this (and will not compile unless it is done). This code uses
|
||||||
|
* variants of png_aligncast to avoid compiler warnings.
|
||||||
|
*/
|
||||||
|
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
|
||||||
|
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
|
||||||
|
|
||||||
|
/* The following relies on a variable 'temp_pointer' being declared with type
|
||||||
|
* 'type'. This is written this way just to hide the GCC strict aliasing
|
||||||
|
* warning; note that the code is safe because there never is an alias between
|
||||||
|
* the input and output pointers.
|
||||||
|
*
|
||||||
|
* When compiling with MSVC ARM64, the png_ldr macro can't be passed directly
|
||||||
|
* to vst4_lane_u32, because of an internal compiler error inside MSVC.
|
||||||
|
* To avoid this compiler bug, we use a temporary variable (vdest_val) to store
|
||||||
|
* the result of png_ldr.
|
||||||
|
*/
|
||||||
|
#define png_ldr(type,pointer)\
|
||||||
|
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
|
||||||
|
|
||||||
|
#if PNG_ARM_NEON_OPT > 0
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
png_bytep rp = row;
|
||||||
|
png_bytep rp_stop = row + row_info->rowbytes;
|
||||||
|
png_const_bytep pp = prev_row;
|
||||||
|
|
||||||
|
png_debug(1, "in png_read_filter_row_up_neon");
|
||||||
|
|
||||||
|
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||||
|
{
|
||||||
|
uint8x16_t qrp, qpp;
|
||||||
|
|
||||||
|
qrp = vld1q_u8(rp);
|
||||||
|
qpp = vld1q_u8(pp);
|
||||||
|
qrp = vaddq_u8(qrp, qpp);
|
||||||
|
vst1q_u8(rp, qrp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
png_bytep rp = row;
|
||||||
|
png_bytep rp_stop = row + row_info->rowbytes;
|
||||||
|
|
||||||
|
uint8x16_t vtmp = vld1q_u8(rp);
|
||||||
|
uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||||
|
uint8x8x2_t vrp = *vrpt;
|
||||||
|
|
||||||
|
uint8x8x4_t vdest;
|
||||||
|
vdest.val[3] = vdup_n_u8(0);
|
||||||
|
|
||||||
|
png_debug(1, "in png_read_filter_row_sub3_neon");
|
||||||
|
|
||||||
|
for (; rp < rp_stop;)
|
||||||
|
{
|
||||||
|
uint8x8_t vtmp1, vtmp2;
|
||||||
|
uint32x2_t *temp_pointer;
|
||||||
|
|
||||||
|
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||||
|
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||||
|
vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||||
|
vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
|
||||||
|
|
||||||
|
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||||
|
vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
|
||||||
|
vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
|
||||||
|
|
||||||
|
vtmp = vld1q_u8(rp + 12);
|
||||||
|
vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||||
|
vrp = *vrpt;
|
||||||
|
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||||
|
rp += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
png_bytep rp = row;
|
||||||
|
png_bytep rp_stop = row + row_info->rowbytes;
|
||||||
|
|
||||||
|
uint8x8x4_t vdest;
|
||||||
|
vdest.val[3] = vdup_n_u8(0);
|
||||||
|
|
||||||
|
png_debug(1, "in png_read_filter_row_sub4_neon");
|
||||||
|
|
||||||
|
for (; rp < rp_stop; rp += 16)
|
||||||
|
{
|
||||||
|
uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||||
|
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||||
|
uint8x8x4_t vrp = *vrpt;
|
||||||
|
uint32x2x4_t *temp_pointer;
|
||||||
|
uint32x2x4_t vdest_val;
|
||||||
|
|
||||||
|
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||||
|
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
|
||||||
|
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
|
||||||
|
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
|
||||||
|
|
||||||
|
vdest_val = png_ldr(uint32x2x4_t, &vdest);
|
||||||
|
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PNG_UNUSED(prev_row)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
png_bytep rp = row;
|
||||||
|
png_const_bytep pp = prev_row;
|
||||||
|
png_bytep rp_stop = row + row_info->rowbytes;
|
||||||
|
|
||||||
|
uint8x16_t vtmp;
|
||||||
|
uint8x8x2_t *vrpt;
|
||||||
|
uint8x8x2_t vrp;
|
||||||
|
uint8x8x4_t vdest;
|
||||||
|
vdest.val[3] = vdup_n_u8(0);
|
||||||
|
|
||||||
|
vtmp = vld1q_u8(rp);
|
||||||
|
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||||
|
vrp = *vrpt;
|
||||||
|
|
||||||
|
png_debug(1, "in png_read_filter_row_avg3_neon");
|
||||||
|
|
||||||
|
for (; rp < rp_stop; pp += 12)
|
||||||
|
{
|
||||||
|
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||||
|
|
||||||
|
uint8x8x2_t *vppt;
|
||||||
|
uint8x8x2_t vpp;
|
||||||
|
|
||||||
|
uint32x2_t *temp_pointer;
|
||||||
|
|
||||||
|
vtmp = vld1q_u8(pp);
|
||||||
|
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||||
|
vpp = *vppt;
|
||||||
|
|
||||||
|
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||||
|
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||||
|
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||||
|
|
||||||
|
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||||
|
vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||||
|
vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
|
||||||
|
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||||
|
|
||||||
|
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||||
|
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||||
|
|
||||||
|
vtmp = vld1q_u8(rp + 12);
|
||||||
|
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||||
|
vrp = *vrpt;
|
||||||
|
|
||||||
|
vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
|
||||||
|
vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
|
||||||
|
|
||||||
|
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||||
|
|
||||||
|
vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
|
||||||
|
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||||
|
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||||
|
rp += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
png_bytep rp = row;
|
||||||
|
png_bytep rp_stop = row + row_info->rowbytes;
|
||||||
|
png_const_bytep pp = prev_row;
|
||||||
|
|
||||||
|
uint8x8x4_t vdest;
|
||||||
|
vdest.val[3] = vdup_n_u8(0);
|
||||||
|
|
||||||
|
png_debug(1, "in png_read_filter_row_avg4_neon");
|
||||||
|
|
||||||
|
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||||
|
{
|
||||||
|
uint32x2x4_t vtmp;
|
||||||
|
uint8x8x4_t *vrpt, *vppt;
|
||||||
|
uint8x8x4_t vrp, vpp;
|
||||||
|
uint32x2x4_t *temp_pointer;
|
||||||
|
uint32x2x4_t vdest_val;
|
||||||
|
|
||||||
|
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||||
|
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||||
|
vrp = *vrpt;
|
||||||
|
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||||
|
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||||
|
vpp = *vppt;
|
||||||
|
|
||||||
|
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||||
|
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||||
|
vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
|
||||||
|
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||||
|
vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
|
||||||
|
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||||
|
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
|
||||||
|
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||||
|
|
||||||
|
vdest_val = png_ldr(uint32x2x4_t, &vdest);
|
||||||
|
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8x8_t
|
||||||
|
paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
|
||||||
|
{
|
||||||
|
uint8x8_t d, e;
|
||||||
|
uint16x8_t p1, pa, pb, pc;
|
||||||
|
|
||||||
|
p1 = vaddl_u8(a, b); /* a + b */
|
||||||
|
pc = vaddl_u8(c, c); /* c * 2 */
|
||||||
|
pa = vabdl_u8(b, c); /* pa */
|
||||||
|
pb = vabdl_u8(a, c); /* pb */
|
||||||
|
pc = vabdq_u16(p1, pc); /* pc */
|
||||||
|
|
||||||
|
p1 = vcleq_u16(pa, pb); /* pa <= pb */
|
||||||
|
pa = vcleq_u16(pa, pc); /* pa <= pc */
|
||||||
|
pb = vcleq_u16(pb, pc); /* pb <= pc */
|
||||||
|
|
||||||
|
p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
|
||||||
|
|
||||||
|
d = vmovn_u16(pb);
|
||||||
|
e = vmovn_u16(p1);
|
||||||
|
|
||||||
|
d = vbsl_u8(d, b, c);
|
||||||
|
e = vbsl_u8(e, a, d);
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
png_bytep rp = row;
|
||||||
|
png_const_bytep pp = prev_row;
|
||||||
|
png_bytep rp_stop = row + row_info->rowbytes;
|
||||||
|
|
||||||
|
uint8x16_t vtmp;
|
||||||
|
uint8x8x2_t *vrpt;
|
||||||
|
uint8x8x2_t vrp;
|
||||||
|
uint8x8_t vlast = vdup_n_u8(0);
|
||||||
|
uint8x8x4_t vdest;
|
||||||
|
vdest.val[3] = vdup_n_u8(0);
|
||||||
|
|
||||||
|
vtmp = vld1q_u8(rp);
|
||||||
|
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||||
|
vrp = *vrpt;
|
||||||
|
|
||||||
|
png_debug(1, "in png_read_filter_row_paeth3_neon");
|
||||||
|
|
||||||
|
for (; rp < rp_stop; pp += 12)
|
||||||
|
{
|
||||||
|
uint8x8x2_t *vppt;
|
||||||
|
uint8x8x2_t vpp;
|
||||||
|
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||||
|
uint32x2_t *temp_pointer;
|
||||||
|
|
||||||
|
vtmp = vld1q_u8(pp);
|
||||||
|
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||||
|
vpp = *vppt;
|
||||||
|
|
||||||
|
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||||
|
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||||
|
|
||||||
|
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||||
|
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||||
|
vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
|
||||||
|
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||||
|
|
||||||
|
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||||
|
vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||||
|
vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
|
||||||
|
vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
|
||||||
|
|
||||||
|
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||||
|
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||||
|
|
||||||
|
vtmp = vld1q_u8(rp + 12);
|
||||||
|
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||||
|
vrp = *vrpt;
|
||||||
|
|
||||||
|
vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
|
||||||
|
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||||
|
|
||||||
|
vlast = vtmp2;
|
||||||
|
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||||
|
rp += 3;
|
||||||
|
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||||
|
rp += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
|
||||||
|
png_const_bytep prev_row)
|
||||||
|
{
|
||||||
|
png_bytep rp = row;
|
||||||
|
png_bytep rp_stop = row + row_info->rowbytes;
|
||||||
|
png_const_bytep pp = prev_row;
|
||||||
|
|
||||||
|
uint8x8_t vlast = vdup_n_u8(0);
|
||||||
|
uint8x8x4_t vdest;
|
||||||
|
vdest.val[3] = vdup_n_u8(0);
|
||||||
|
|
||||||
|
png_debug(1, "in png_read_filter_row_paeth4_neon");
|
||||||
|
|
||||||
|
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||||
|
{
|
||||||
|
uint32x2x4_t vtmp;
|
||||||
|
uint8x8x4_t *vrpt, *vppt;
|
||||||
|
uint8x8x4_t vrp, vpp;
|
||||||
|
uint32x2x4_t *temp_pointer;
|
||||||
|
uint32x2x4_t vdest_val;
|
||||||
|
|
||||||
|
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||||
|
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||||
|
vrp = *vrpt;
|
||||||
|
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||||
|
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||||
|
vpp = *vppt;
|
||||||
|
|
||||||
|
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||||
|
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||||
|
vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
|
||||||
|
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||||
|
vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
|
||||||
|
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||||
|
vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
|
||||||
|
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||||
|
|
||||||
|
vlast = vpp.val[3];
|
||||||
|
|
||||||
|
vdest_val = png_ldr(uint32x2x4_t, &vdest);
|
||||||
|
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||||
|
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
|
||||||
|
#endif /* READ */
|
|
@ -0,0 +1,151 @@
|
||||||
|
|
||||||
|
/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018-2019 Cosmin Truta
|
||||||
|
* Copyright (c) 2017-2018 Arm Holdings. All rights reserved.
|
||||||
|
* Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../pngpriv.h"
|
||||||
|
|
||||||
|
#if PNG_ARM_NEON_IMPLEMENTATION == 1
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
|
||||||
|
# include <arm64_neon.h>
|
||||||
|
#else
|
||||||
|
# include <arm_neon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Build an RGBA8 palette from the separate RGB and alpha palettes. */
|
||||||
|
void
|
||||||
|
png_riffle_palette_neon(png_structrp png_ptr)
|
||||||
|
{
|
||||||
|
png_const_colorp palette = png_ptr->palette;
|
||||||
|
png_bytep riffled_palette = png_ptr->riffled_palette;
|
||||||
|
png_const_bytep trans_alpha = png_ptr->trans_alpha;
|
||||||
|
int num_trans = png_ptr->num_trans;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Initially black, opaque. */
|
||||||
|
uint8x16x4_t w = {{
|
||||||
|
vdupq_n_u8(0x00),
|
||||||
|
vdupq_n_u8(0x00),
|
||||||
|
vdupq_n_u8(0x00),
|
||||||
|
vdupq_n_u8(0xff),
|
||||||
|
}};
|
||||||
|
|
||||||
|
png_debug(1, "in png_riffle_palette_neon");
|
||||||
|
|
||||||
|
/* First, riffle the RGB colours into an RGBA8 palette.
|
||||||
|
* The alpha component is set to opaque for now.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 256; i += 16)
|
||||||
|
{
|
||||||
|
uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i));
|
||||||
|
w.val[0] = v.val[0];
|
||||||
|
w.val[1] = v.val[1];
|
||||||
|
w.val[2] = v.val[2];
|
||||||
|
vst4q_u8(riffled_palette + (i << 2), w);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix up the missing transparency values. */
|
||||||
|
for (i = 0; i < num_trans; i++)
|
||||||
|
riffled_palette[(i << 2) + 3] = trans_alpha[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expands a palettized row into RGBA8. */
|
||||||
|
int
|
||||||
|
png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
|
||||||
|
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
|
||||||
|
{
|
||||||
|
png_uint_32 row_width = row_info->width;
|
||||||
|
const png_uint_32 *riffled_palette =
|
||||||
|
(const png_uint_32 *)png_ptr->riffled_palette;
|
||||||
|
const png_uint_32 pixels_per_chunk = 4;
|
||||||
|
png_uint_32 i;
|
||||||
|
|
||||||
|
png_debug(1, "in png_do_expand_palette_rgba8_neon");
|
||||||
|
|
||||||
|
PNG_UNUSED(row)
|
||||||
|
if (row_width < pixels_per_chunk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* This function originally gets the last byte of the output row.
|
||||||
|
* The NEON part writes forward from a given position, so we have
|
||||||
|
* to seek this back by 4 pixels x 4 bytes.
|
||||||
|
*/
|
||||||
|
*ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1);
|
||||||
|
|
||||||
|
for (i = 0; i < row_width; i += pixels_per_chunk)
|
||||||
|
{
|
||||||
|
uint32x4_t cur;
|
||||||
|
png_bytep sp = *ssp - i, dp = *ddp - (i << 2);
|
||||||
|
cur = vld1q_dup_u32 (riffled_palette + *(sp - 3));
|
||||||
|
cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1);
|
||||||
|
cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2);
|
||||||
|
cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3);
|
||||||
|
vst1q_u32((void *)dp, cur);
|
||||||
|
}
|
||||||
|
if (i != row_width)
|
||||||
|
{
|
||||||
|
/* Remove the amount that wasn't processed. */
|
||||||
|
i -= pixels_per_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrement output pointers. */
|
||||||
|
*ssp = *ssp - i;
|
||||||
|
*ddp = *ddp - (i << 2);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expands a palettized row into RGB8. */
|
||||||
|
int
|
||||||
|
png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info,
|
||||||
|
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
|
||||||
|
{
|
||||||
|
png_uint_32 row_width = row_info->width;
|
||||||
|
png_const_bytep palette = (png_const_bytep)png_ptr->palette;
|
||||||
|
const png_uint_32 pixels_per_chunk = 8;
|
||||||
|
png_uint_32 i;
|
||||||
|
|
||||||
|
png_debug(1, "in png_do_expand_palette_rgb8_neon");
|
||||||
|
|
||||||
|
PNG_UNUSED(row)
|
||||||
|
if (row_width <= pixels_per_chunk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Seeking this back by 8 pixels x 3 bytes. */
|
||||||
|
*ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1);
|
||||||
|
|
||||||
|
for (i = 0; i < row_width; i += pixels_per_chunk)
|
||||||
|
{
|
||||||
|
uint8x8x3_t cur;
|
||||||
|
png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i);
|
||||||
|
cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7)));
|
||||||
|
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1);
|
||||||
|
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2);
|
||||||
|
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3);
|
||||||
|
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4);
|
||||||
|
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5);
|
||||||
|
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6);
|
||||||
|
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7);
|
||||||
|
vst3_u8((void *)dp, cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != row_width)
|
||||||
|
{
|
||||||
|
/* Remove the amount that wasn't processed. */
|
||||||
|
i -= pixels_per_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrement output pointers. */
|
||||||
|
*ssp = *ssp - i;
|
||||||
|
*ddp = *ddp - ((i << 1) + i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PNG_ARM_NEON_IMPLEMENTATION */
|
|
@ -0,0 +1,225 @@
|
||||||
|
#! /bin/sh
|
||||||
|
#
|
||||||
|
# Run 'autoreconf' to build 'configure', 'Makefile.in' and other configure
|
||||||
|
# control files.
|
||||||
|
#
|
||||||
|
# The first time this is run on a GIT checkout the only files that exist are
|
||||||
|
# configure.ac and Makefile.am; all of the autotools support scripts are
|
||||||
|
# missing. They are instantiated with autoreconf --force --install.
|
||||||
|
#
|
||||||
|
# For regular ("tarball") distributions all the files should exist. We do not
|
||||||
|
# want them to be updated *under any circumstances*. It should never be
|
||||||
|
# necessary to run autogen.sh because ./configure --enable-maintainer-mode says
|
||||||
|
# what to do if Makefile.am or configure.ac are changed.
|
||||||
|
#
|
||||||
|
# It is *probably* OK to update the files on a GIT checkout, because they have
|
||||||
|
# come from the local tools, but leave that to the user who is assumed to know
|
||||||
|
# whether it is ok or required.
|
||||||
|
#
|
||||||
|
# This script is intended to work without arguments, there are, however, hidden
|
||||||
|
# arguments (a) for use while testing the script and (b) to fix up systems that
|
||||||
|
# have been broken. If (b) is required the script prompts for the correct
|
||||||
|
# options. For this reason the options are *NOT* documented in the help; this
|
||||||
|
# is deliberate; UTSL.
|
||||||
|
#
|
||||||
|
clean=
|
||||||
|
maintainer=
|
||||||
|
while test $# -gt 0
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
--maintainer)
|
||||||
|
maintainer=1;;
|
||||||
|
|
||||||
|
--clean)
|
||||||
|
clean=1;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
exec >&2
|
||||||
|
echo "$0: usage: ./autogen.sh"
|
||||||
|
if test -d .git
|
||||||
|
then
|
||||||
|
echo " ./autogen.sh generates the configure script and"
|
||||||
|
echo " Makefile.in, or refreshes them after changes to Makefile.am"
|
||||||
|
echo " or configure.ac. You may prefer to just run autoreconf."
|
||||||
|
elif test -z "$maintainer"
|
||||||
|
then
|
||||||
|
echo " DO NOT RUN THIS SCRIPT."
|
||||||
|
echo " If you need to change Makefile.am or configure.ac then you"
|
||||||
|
echo " also need to run ./configure --enable-maintainer-mode and"
|
||||||
|
echo " use the appropriate autotools, *NOT* this script, to update"
|
||||||
|
echo " everything, please check the documentation of autoreconf."
|
||||||
|
echo " WARNING: libpng is intentionally generated with a known,"
|
||||||
|
echo " fixed, set of autotools. It is known *NOT* to work with"
|
||||||
|
echo " the collection of autotools distributed on highly reputable"
|
||||||
|
echo " operating systems."
|
||||||
|
echo " Remember: autotools is GNU software, you are expected to"
|
||||||
|
echo " pay for support."
|
||||||
|
else
|
||||||
|
echo " You have run autogen.sh with --maintainer enabled and you"
|
||||||
|
echo " are not using a GIT distribution, then you have given an"
|
||||||
|
echo " unrecognized argument. This is not good. --maintainer"
|
||||||
|
echo " switches off any assumptions that you might not know what"
|
||||||
|
echo " you are doing."
|
||||||
|
fi
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
#
|
||||||
|
# First check for a set of the autotools files; if absent then this is assumed
|
||||||
|
# to be a GIT version and the local autotools must be used. If present this
|
||||||
|
# is a tarball distribution and the script should not be used. If partially
|
||||||
|
# present bad things are happening.
|
||||||
|
#
|
||||||
|
# The autotools generated files:
|
||||||
|
libpng_autotools_files="Makefile.in aclocal.m4 config.guess config.h.in
|
||||||
|
config.sub configure depcomp install-sh ltmain.sh missing\
|
||||||
|
test-driver"
|
||||||
|
#
|
||||||
|
# Files generated by versions of configue >2.68 or automake >1.13 (i.e. later
|
||||||
|
# versions than those required by configure.ac):
|
||||||
|
libpng_autotools_extra="compile config.h.in~"
|
||||||
|
#
|
||||||
|
# These are separate because 'maintainer-clean' does not remove them.
|
||||||
|
libpng_libtool_files="scripts/libtool.m4 scripts/ltoptions.m4\
|
||||||
|
scripts/ltsugar.m4 scripts/ltversion.m4 scripts/lt~obsolete.m4"
|
||||||
|
|
||||||
|
libpng_autotools_dirs="autom4te.cache" # not required
|
||||||
|
#
|
||||||
|
# The configure generated files:
|
||||||
|
libpng_configure_files="Makefile config.h config.log config.status\
|
||||||
|
libpng-config libpng.pc libtool stamp-h1"
|
||||||
|
|
||||||
|
libpng_configure_dirs=".deps"
|
||||||
|
#
|
||||||
|
# We must remove the configure generated files as well as the autotools
|
||||||
|
# generated files if autotools are regenerated because otherwise if configure
|
||||||
|
# has been run without "--enable-maintainer-mode" make can do a partial update
|
||||||
|
# of Makefile. These functions do the two bits of cleaning.
|
||||||
|
clean_autotools(){
|
||||||
|
rm -rf $libpng_autotools_files $libpng_libtool_files $libpng_autotools_dirs
|
||||||
|
rm -rf $libpng_autotools_extra
|
||||||
|
}
|
||||||
|
|
||||||
|
clean_configure(){
|
||||||
|
rm -rf $libpng_configure_files $libpng_configure_dirs
|
||||||
|
}
|
||||||
|
#
|
||||||
|
# Clean: remove everything (this is to help with testing)
|
||||||
|
if test -n "$clean"
|
||||||
|
then
|
||||||
|
clean_configure
|
||||||
|
if test -n "$maintainer"
|
||||||
|
then
|
||||||
|
clean_autotools
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
# Validate the distribution.
|
||||||
|
libpng_autotools_file_found=
|
||||||
|
libpng_autotools_file_missing=
|
||||||
|
for file in $libpng_autotools_files
|
||||||
|
do
|
||||||
|
if test -f "$file"
|
||||||
|
then
|
||||||
|
libpng_autotools_file_found=1
|
||||||
|
else
|
||||||
|
libpng_autotools_file_missing=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
#
|
||||||
|
# Presence of one of these does not *invalidate* missing, but absence
|
||||||
|
# invalidates found.
|
||||||
|
for file in $libpng_libtool_files
|
||||||
|
do
|
||||||
|
if test ! -f "$file"
|
||||||
|
then
|
||||||
|
libpng_autotools_file_missing=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
#
|
||||||
|
# The cache directory doesn't matter - it will be regenerated and does not exist
|
||||||
|
# anyway in a tarball.
|
||||||
|
#
|
||||||
|
# Either everything is missing or everything is there, the --maintainer option
|
||||||
|
# just changes this so that the mode is set to generate all the files.
|
||||||
|
mode=
|
||||||
|
if test -z "$libpng_autotools_file_found" -o -n "$maintainer"
|
||||||
|
then
|
||||||
|
mode="autoreconf"
|
||||||
|
else
|
||||||
|
if test -n "$libpng_autotools_file_missing"
|
||||||
|
then
|
||||||
|
mode="broken"
|
||||||
|
else
|
||||||
|
mode="configure"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
# So:
|
||||||
|
case "$mode" in
|
||||||
|
autoreconf)
|
||||||
|
# Clean in case configure files exist
|
||||||
|
clean_configure
|
||||||
|
clean_autotools
|
||||||
|
# Everything must be initialized, so use --force
|
||||||
|
if autoreconf --warnings=all --force --install
|
||||||
|
then
|
||||||
|
missing=
|
||||||
|
for file in $libpng_autotools_files
|
||||||
|
do
|
||||||
|
test -f "$file" || missing=1
|
||||||
|
done
|
||||||
|
# ignore the cache directory
|
||||||
|
test -z "$missing" || {
|
||||||
|
exec >&2
|
||||||
|
echo "autoreconf was run, but did not produce all the expected"
|
||||||
|
echo "files. It is likely that your autotools installation is"
|
||||||
|
echo "not compatible with that expected by libpng."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
exec >&2
|
||||||
|
echo "autoreconf failed: your version of autotools is incompatible"
|
||||||
|
echo "with this libpng version. Please use a distributed archive"
|
||||||
|
echo "(which includes the autotools generated files) and run configure"
|
||||||
|
echo "instead."
|
||||||
|
exit 1
|
||||||
|
fi;;
|
||||||
|
|
||||||
|
configure)
|
||||||
|
if test -d .git
|
||||||
|
then
|
||||||
|
exec >&2
|
||||||
|
echo "ERROR: running autoreconf on an initialized system"
|
||||||
|
echo " This is not necessary; it is only necessary to remake the"
|
||||||
|
echo " autotools generated files if Makefile.am or configure.ac"
|
||||||
|
echo " change and make does the right thing with:"
|
||||||
|
echo
|
||||||
|
echo " ./configure --enable-maintainer-mode."
|
||||||
|
echo
|
||||||
|
echo " You can run autoreconf yourself if you don't like maintainer"
|
||||||
|
echo " mode and you can also just run autoreconf -f -i to initialize"
|
||||||
|
echo " everything in the first place; this script is only for"
|
||||||
|
echo " compatibility with prior releases."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
exec >&2
|
||||||
|
echo "autogen.sh is intended only to generate 'configure' on systems"
|
||||||
|
echo "that do not have it. You have a complete 'configure', if you"
|
||||||
|
echo "need to change Makefile.am or configure.ac you also need to"
|
||||||
|
echo "run configure with the --enable-maintainer-mode option."
|
||||||
|
exit 1
|
||||||
|
fi;;
|
||||||
|
|
||||||
|
broken)
|
||||||
|
exec >&2
|
||||||
|
echo "Your system has a partial set of autotools generated files."
|
||||||
|
echo "autogen.sh is unable to proceed. The full set of files is"
|
||||||
|
echo "contained in the libpng 'tar' distribution archive and you do"
|
||||||
|
echo "not need to run autogen.sh if you use it."
|
||||||
|
exit 1;;
|
||||||
|
esac
|
|
@ -0,0 +1,117 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ci_autotools.sh
|
||||||
|
# Continuously integrate libpng using the GNU Autotools.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2019-2022 Cosmin Truta.
|
||||||
|
#
|
||||||
|
# This software is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h.
|
||||||
|
|
||||||
|
CI_SCRIPTNAME="$(basename "$0")"
|
||||||
|
CI_SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
CI_SRCDIR="$(dirname "$CI_SCRIPTDIR")"
|
||||||
|
CI_BUILDDIR="$CI_SRCDIR/out/autotools.build"
|
||||||
|
CI_INSTALLDIR="$CI_SRCDIR/out/autotools.install"
|
||||||
|
|
||||||
|
function ci_info {
|
||||||
|
printf >&2 "%s: %s\\n" "$CI_SCRIPTNAME" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_err {
|
||||||
|
printf >&2 "%s: error: %s\\n" "$CI_SCRIPTNAME" "$*"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_spawn {
|
||||||
|
printf >&2 "%s: executing:" "$CI_SCRIPTNAME"
|
||||||
|
printf >&2 " %q" "$@"
|
||||||
|
printf >&2 "\\n"
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_init_autotools {
|
||||||
|
CI_SYSTEM_NAME="$(uname -s)"
|
||||||
|
CI_MACHINE_NAME="$(uname -m)"
|
||||||
|
CI_MAKE="${CI_MAKE:-make}"
|
||||||
|
# Set CI_CC to cc by default, if the cc command is available.
|
||||||
|
# The configure script defaults CC to gcc, which is not always a good idea.
|
||||||
|
[[ -x $(command -v cc) ]] && CI_CC="${CI_CC:-cc}"
|
||||||
|
# Ensure that the CI_ variables that cannot be customized reliably are not initialized.
|
||||||
|
[[ ! $CI_CONFIGURE_VARS ]] || ci_err "unexpected: \$CI_CONFIGURE_VARS='$CI_CONFIGURE_VARS'"
|
||||||
|
[[ ! $CI_MAKE_VARS ]] || ci_err "unexpected: \$CI_MAKE_VARS='$CI_MAKE_VARS'"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_trace_autotools {
|
||||||
|
ci_info "## START OF CONFIGURATION ##"
|
||||||
|
ci_info "system name: $CI_SYSTEM_NAME"
|
||||||
|
ci_info "machine hardware name: $CI_MACHINE_NAME"
|
||||||
|
ci_info "source directory: $CI_SRCDIR"
|
||||||
|
ci_info "build directory: $CI_BUILDDIR"
|
||||||
|
ci_info "install directory: $CI_INSTALLDIR"
|
||||||
|
ci_info "environment option: \$CI_CONFIGURE_FLAGS: '$CI_CONFIGURE_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_MAKE: '$CI_MAKE'"
|
||||||
|
ci_info "environment option: \$CI_MAKE_FLAGS: '$CI_MAKE_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_CC: '$CI_CC'"
|
||||||
|
ci_info "environment option: \$CI_CC_FLAGS: '$CI_CC_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_CPP: '$CI_CPP'"
|
||||||
|
ci_info "environment option: \$CI_CPP_FLAGS: '$CI_CPP_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_AR: '$CI_AR'"
|
||||||
|
ci_info "environment option: \$CI_RANLIB: '$CI_RANLIB'"
|
||||||
|
ci_info "environment option: \$CI_LD: '$CI_LD'"
|
||||||
|
ci_info "environment option: \$CI_LD_FLAGS: '$CI_LD_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_SANITIZERS: '$CI_SANITIZERS'"
|
||||||
|
ci_info "environment option: \$CI_NO_TEST: '$CI_NO_TEST'"
|
||||||
|
ci_info "environment option: \$CI_NO_INSTALL: '$CI_NO_INSTALL'"
|
||||||
|
ci_info "environment option: \$CI_NO_CLEAN: '$CI_NO_CLEAN'"
|
||||||
|
ci_info "executable: \$CI_MAKE: $(command -V "$CI_MAKE")"
|
||||||
|
[[ $CI_CC ]] &&
|
||||||
|
ci_info "executable: \$CI_CC: $(command -V "$CI_CC")"
|
||||||
|
[[ $CI_CPP ]] &&
|
||||||
|
ci_info "executable: \$CI_CPP: $(command -V "$CI_CPP")"
|
||||||
|
[[ $CI_AR ]] &&
|
||||||
|
ci_info "executable: \$CI_AR: $(command -V "$CI_AR")"
|
||||||
|
[[ $CI_RANLIB ]] &&
|
||||||
|
ci_info "executable: \$CI_RANLIB: $(command -V "$CI_RANLIB")"
|
||||||
|
[[ $CI_LD ]] &&
|
||||||
|
ci_info "executable: \$CI_LD: $(command -V "$CI_LD")"
|
||||||
|
ci_info "## END OF CONFIGURATION ##"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_build_autotools {
|
||||||
|
ci_info "## START OF BUILD ##"
|
||||||
|
# Export the configure build environment.
|
||||||
|
[[ $CI_CC ]] && ci_spawn export CC="$CI_CC"
|
||||||
|
[[ $CI_CC_FLAGS ]] && ci_spawn export CFLAGS="$CI_CC_FLAGS"
|
||||||
|
[[ $CI_CPP ]] && ci_spawn export CPP="$CI_CPP"
|
||||||
|
[[ $CI_CPP_FLAGS ]] && ci_spawn export CPPFLAGS="$CI_CPP_FLAGS"
|
||||||
|
[[ $CI_AR ]] && ci_spawn export AR="$CI_AR"
|
||||||
|
[[ $CI_RANLIB ]] && ci_spawn export RANLIB="$CI_RANLIB"
|
||||||
|
[[ $CI_LD ]] && ci_spawn export CPP="$CI_LD"
|
||||||
|
[[ $CI_LD_FLAGS ]] && ci_spawn export LDFLAGS="$CI_LD_FLAGS"
|
||||||
|
[[ $CI_SANITIZERS ]] && {
|
||||||
|
ci_spawn export CFLAGS="-fsanitize=$CI_SANITIZERS ${CFLAGS:-"-O2"}"
|
||||||
|
ci_spawn export LDFLAGS="-fsanitize=$CI_SANITIZERS $LDFLAGS"
|
||||||
|
}
|
||||||
|
# Build and install.
|
||||||
|
ci_spawn rm -fr "$CI_BUILDDIR" "$CI_INSTALLDIR"
|
||||||
|
ci_spawn mkdir -p "$CI_BUILDDIR"
|
||||||
|
ci_spawn cd "$CI_BUILDDIR"
|
||||||
|
ci_spawn "$CI_SRCDIR/configure" --prefix="$CI_INSTALLDIR" $CI_CONFIGURE_FLAGS
|
||||||
|
ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS
|
||||||
|
[[ $CI_NO_TEST ]] || ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS test
|
||||||
|
[[ $CI_NO_INSTALL ]] || ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS install
|
||||||
|
[[ $CI_NO_CLEAN ]] || ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS clean
|
||||||
|
[[ $CI_NO_CLEAN ]] || ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS distclean
|
||||||
|
ci_info "## END OF BUILD ##"
|
||||||
|
}
|
||||||
|
|
||||||
|
ci_init_autotools
|
||||||
|
ci_trace_autotools
|
||||||
|
[[ $# -eq 0 ]] || {
|
||||||
|
ci_info "note: this program accepts environment options only"
|
||||||
|
ci_err "unexpected command arguments: '$*'"
|
||||||
|
}
|
||||||
|
ci_build_autotools
|
|
@ -0,0 +1,169 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ci_cmake.sh
|
||||||
|
# Continuously integrate libpng using CMake.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2019-2022 Cosmin Truta.
|
||||||
|
#
|
||||||
|
# This software is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h.
|
||||||
|
|
||||||
|
CI_SCRIPTNAME="$(basename "$0")"
|
||||||
|
CI_SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
CI_SRCDIR="$(dirname "$CI_SCRIPTDIR")"
|
||||||
|
CI_BUILDDIR="$CI_SRCDIR/out/cmake.build"
|
||||||
|
CI_INSTALLDIR="$CI_SRCDIR/out/cmake.install"
|
||||||
|
|
||||||
|
function ci_info {
|
||||||
|
printf >&2 "%s: %s\\n" "$CI_SCRIPTNAME" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_err {
|
||||||
|
printf >&2 "%s: error: %s\\n" "$CI_SCRIPTNAME" "$*"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_spawn {
|
||||||
|
printf >&2 "%s: executing:" "$CI_SCRIPTNAME"
|
||||||
|
printf >&2 " %q" "$@"
|
||||||
|
printf >&2 "\\n"
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_init_cmake {
|
||||||
|
CI_SYSTEM_NAME="$(uname -s)"
|
||||||
|
CI_MACHINE_NAME="$(uname -m)"
|
||||||
|
CI_CMAKE="${CI_CMAKE:-cmake}"
|
||||||
|
CI_CTEST="${CI_CTEST:-ctest}"
|
||||||
|
CI_CMAKE_BUILD_TYPE="${CI_CMAKE_BUILD_TYPE:-Release}"
|
||||||
|
[[ -x $(command -v ninja) ]] && CI_CMAKE_GENERATOR="${CI_CMAKE_GENERATOR:-Ninja}"
|
||||||
|
if [[ $CI_CMAKE_GENERATOR == "Visual Studio"* ]]
|
||||||
|
then
|
||||||
|
# Initialize the CI_...DIR_NATIVE variables, for the benefit of
|
||||||
|
# the native Windows build tools. The regular CI_...DIR variables
|
||||||
|
# can only be used inside Bash-on-Windows.
|
||||||
|
mkdir -p "$CI_BUILDDIR"
|
||||||
|
mkdir -p "$CI_INSTALLDIR"
|
||||||
|
if [[ -x $CYGPATH ]]
|
||||||
|
then
|
||||||
|
CI_SRCDIR_NATIVE="$("$CYGPATH" -w "$CI_SRCDIR")"
|
||||||
|
CI_BUILDDIR_NATIVE="$("$CYGPATH" -w "$CI_BUILDDIR")"
|
||||||
|
CI_INSTALLDIR_NATIVE="$("$CYGPATH" -w "$CI_INSTALLDIR")"
|
||||||
|
else
|
||||||
|
CI_SRCDIR_NATIVE="$(cd "$CI_SRCDIR" ; pwd -W || pwd -P)"
|
||||||
|
CI_BUILDDIR_NATIVE="$(cd "$CI_BUILDDIR" ; pwd -W || pwd -P)"
|
||||||
|
CI_INSTALLDIR_NATIVE="$(cd "$CI_INSTALLDIR" ; pwd -W || pwd -P)"
|
||||||
|
fi
|
||||||
|
# Clean up incidental mixtures of Windows and Bash-on-Windows
|
||||||
|
# environment variables, to avoid confusing MSBuild.
|
||||||
|
[[ $TEMP && ( $Temp || $temp ) ]] && unset TEMP
|
||||||
|
[[ $TMP && ( $Tmp || $tmp ) ]] && unset TMP
|
||||||
|
# Ensure that CI_CMAKE_GENERATOR_PLATFORM is initialized for this generator.
|
||||||
|
[[ $CI_CMAKE_GENERATOR_PLATFORM ]] || ci_err "missing: \$CI_CMAKE_GENERATOR_PLATFORM"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_trace_cmake {
|
||||||
|
ci_info "## START OF CONFIGURATION ##"
|
||||||
|
ci_info "system name: $CI_SYSTEM_NAME"
|
||||||
|
ci_info "machine hardware name: $CI_MACHINE_NAME"
|
||||||
|
ci_info "source directory: $CI_SRCDIR"
|
||||||
|
[[ $CI_SRCDIR_NATIVE ]] &&
|
||||||
|
ci_info "source directory (native): $CI_SRCDIR_NATIVE"
|
||||||
|
ci_info "build directory: $CI_BUILDDIR"
|
||||||
|
[[ $CI_BUILDDIR_NATIVE ]] &&
|
||||||
|
ci_info "build directory (native): $CI_BUILDDIR_NATIVE"
|
||||||
|
ci_info "install directory: $CI_INSTALLDIR"
|
||||||
|
[[ $CI_INSTALLDIR_NATIVE ]] &&
|
||||||
|
ci_info "install directory (native): $CI_INSTALLDIR_NATIVE"
|
||||||
|
ci_info "environment option: \$CI_CMAKE: '$CI_CMAKE'"
|
||||||
|
ci_info "environment option: \$CI_CMAKE_GENERATOR: '$CI_CMAKE_GENERATOR'"
|
||||||
|
ci_info "environment option: \$CI_CMAKE_GENERATOR_PLATFORM: '$CI_CMAKE_GENERATOR_PLATFORM'"
|
||||||
|
ci_info "environment option: \$CI_CMAKE_BUILD_TYPE: '$CI_CMAKE_BUILD_TYPE'"
|
||||||
|
ci_info "environment option: \$CI_CMAKE_BUILD_FLAGS: '$CI_CMAKE_BUILD_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_CMAKE_VARS: '$CI_CMAKE_VARS'"
|
||||||
|
ci_info "environment option: \$CI_CTEST: '$CI_CTEST'"
|
||||||
|
ci_info "environment option: \$CI_CTEST_FLAGS: '$CI_CTEST_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_CC: '$CI_CC'"
|
||||||
|
ci_info "environment option: \$CI_CC_FLAGS: '$CI_CC_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_AR: '$CI_AR'"
|
||||||
|
ci_info "environment option: \$CI_RANLIB: '$CI_RANLIB'"
|
||||||
|
ci_info "environment option: \$CI_SANITIZERS: '$CI_SANITIZERS'"
|
||||||
|
ci_info "environment option: \$CI_NO_TEST: '$CI_NO_TEST'"
|
||||||
|
ci_info "environment option: \$CI_NO_INSTALL: '$CI_NO_INSTALL'"
|
||||||
|
ci_info "environment option: \$CI_NO_CLEAN: '$CI_NO_CLEAN'"
|
||||||
|
ci_info "executable: \$CI_CMAKE: $(command -V "$CI_CMAKE")"
|
||||||
|
ci_info "executable: \$CI_CTEST: $(command -V "$CI_CTEST")"
|
||||||
|
[[ $CI_CMAKE_GENERATOR == *"Ninja"* ]] &&
|
||||||
|
ci_info "executable: $(command -V ninja)"
|
||||||
|
[[ $CI_CC ]] &&
|
||||||
|
ci_info "executable: \$CI_CC: $(command -V "$CI_CC")"
|
||||||
|
[[ $CI_AR ]] &&
|
||||||
|
ci_info "executable: \$CI_AR: $(command -V "$CI_AR")"
|
||||||
|
[[ $CI_RANLIB ]] &&
|
||||||
|
ci_info "executable: \$CI_RANLIB: $(command -V "$CI_RANLIB")"
|
||||||
|
ci_info "## END OF CONFIGURATION ##"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_build_cmake {
|
||||||
|
ci_info "## START OF BUILD ##"
|
||||||
|
ci_spawn "$(command -v "$CI_CMAKE")" --version
|
||||||
|
ci_spawn "$(command -v "$CI_CTEST")" --version
|
||||||
|
# Initialize ALL_CC_FLAGS as a string.
|
||||||
|
local ALL_CC_FLAGS="$CI_CC_FLAGS"
|
||||||
|
[[ $CI_SANITIZERS ]] && ALL_CC_FLAGS="-fsanitize=$CI_SANITIZERS $ALL_CC_FLAGS"
|
||||||
|
# Initialize ALL_CMAKE_VARS, ALL_CMAKE_BUILD_FLAGS and ALL_CTEST_FLAGS as arrays.
|
||||||
|
local -a ALL_CMAKE_VARS=()
|
||||||
|
[[ $CI_CC ]] && ALL_CMAKE_VARS+=(-DCMAKE_C_COMPILER="$CI_CC")
|
||||||
|
[[ $ALL_CC_FLAGS ]] && ALL_CMAKE_VARS+=(-DCMAKE_C_FLAGS="$ALL_CC_FLAGS")
|
||||||
|
[[ $CI_AR ]] && ALL_CMAKE_VARS+=(-DCMAKE_AR="$CI_AR")
|
||||||
|
[[ $CI_RANLIB ]] && ALL_CMAKE_VARS+=(-DCMAKE_RANLIB="$CI_RANLIB")
|
||||||
|
ALL_CMAKE_VARS+=(-DCMAKE_BUILD_TYPE="$CI_CMAKE_BUILD_TYPE")
|
||||||
|
ALL_CMAKE_VARS+=(-DCMAKE_VERBOSE_MAKEFILE=ON)
|
||||||
|
[[ $CI_NO_TEST ]] && ALL_CMAKE_VARS+=(-DPNG_TESTS=OFF)
|
||||||
|
ALL_CMAKE_VARS+=($CI_CMAKE_VARS)
|
||||||
|
local -a ALL_CMAKE_BUILD_FLAGS=($CI_CMAKE_BUILD_FLAGS)
|
||||||
|
local -a ALL_CTEST_FLAGS=($CI_CTEST_FLAGS)
|
||||||
|
# Initialize SRCDIR_NATIVE and INSTALLDIR_NATIVE.
|
||||||
|
local SRCDIR_NATIVE="${CI_SRCDIR_NATIVE:-"$CI_SRCDIR"}"
|
||||||
|
local INSTALLDIR_NATIVE="${CI_INSTALLDIR_NATIVE:-"$CI_INSTALLDIR"}"
|
||||||
|
# Export the CMake environment variables.
|
||||||
|
[[ $CI_CMAKE_GENERATOR ]] &&
|
||||||
|
ci_spawn export CMAKE_GENERATOR="$CI_CMAKE_GENERATOR"
|
||||||
|
[[ $CI_CMAKE_GENERATOR_PLATFORM ]] &&
|
||||||
|
ci_spawn export CMAKE_GENERATOR_PLATFORM="$CI_CMAKE_GENERATOR_PLATFORM"
|
||||||
|
# Build and install.
|
||||||
|
ci_spawn rm -fr "$CI_BUILDDIR" "$CI_INSTALLDIR"
|
||||||
|
ci_spawn mkdir -p "$CI_BUILDDIR"
|
||||||
|
ci_spawn cd "$CI_BUILDDIR"
|
||||||
|
ci_spawn "$CI_CMAKE" "${ALL_CMAKE_VARS[@]}" \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="$INSTALLDIR_NATIVE" \
|
||||||
|
"$SRCDIR_NATIVE"
|
||||||
|
ci_spawn "$CI_CMAKE" --build . \
|
||||||
|
--config "$CI_CMAKE_BUILD_TYPE" \
|
||||||
|
"${ALL_CMAKE_BUILD_FLAGS[@]}"
|
||||||
|
[[ $CI_NO_TEST ]] ||
|
||||||
|
ci_spawn "$CI_CTEST" --build-config "$CI_CMAKE_BUILD_TYPE" \
|
||||||
|
"${ALL_CTEST_FLAGS[@]}"
|
||||||
|
[[ $CI_NO_INSTALL ]] ||
|
||||||
|
ci_spawn "$CI_CMAKE" --build . \
|
||||||
|
--config "$CI_CMAKE_BUILD_TYPE" \
|
||||||
|
--target install \
|
||||||
|
"${ALL_CMAKE_BUILD_FLAGS[@]}"
|
||||||
|
[[ $CI_NO_CLEAN ]] ||
|
||||||
|
ci_spawn "$CI_CMAKE" --build . \
|
||||||
|
--config "$CI_CMAKE_BUILD_TYPE" \
|
||||||
|
--target clean \
|
||||||
|
"${ALL_CMAKE_BUILD_FLAGS[@]}"
|
||||||
|
ci_info "## END OF BUILD ##"
|
||||||
|
}
|
||||||
|
|
||||||
|
ci_init_cmake
|
||||||
|
ci_trace_cmake
|
||||||
|
[[ $# -eq 0 ]] || {
|
||||||
|
ci_info "note: this program accepts environment options only"
|
||||||
|
ci_err "unexpected command arguments: '$*'"
|
||||||
|
}
|
||||||
|
ci_build_cmake
|
|
@ -0,0 +1,147 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ci_legacy.sh
|
||||||
|
# Continuously integrate libpng using the legacy makefiles.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2019-2022 Cosmin Truta.
|
||||||
|
#
|
||||||
|
# This software is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h.
|
||||||
|
|
||||||
|
CI_SCRIPTNAME="$(basename "$0")"
|
||||||
|
CI_SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
CI_SRCDIR="$(dirname "$CI_SCRIPTDIR")"
|
||||||
|
CI_BUILDDIR="$CI_SRCDIR"
|
||||||
|
|
||||||
|
function ci_info {
|
||||||
|
printf >&2 "%s: %s\\n" "$CI_SCRIPTNAME" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_err {
|
||||||
|
printf >&2 "%s: error: %s\\n" "$CI_SCRIPTNAME" "$*"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_spawn {
|
||||||
|
printf >&2 "%s: executing:" "$CI_SCRIPTNAME"
|
||||||
|
printf >&2 " %q" "$@"
|
||||||
|
printf >&2 "\\n"
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_init_legacy {
|
||||||
|
CI_SYSTEM_NAME="$(uname -s)"
|
||||||
|
CI_MACHINE_NAME="$(uname -m)"
|
||||||
|
CI_MAKE="${CI_MAKE:-make}"
|
||||||
|
case "$CI_SYSTEM_NAME" in
|
||||||
|
( Darwin | *BSD | DragonFly )
|
||||||
|
[[ -x $(command -v clang) ]] && CI_CC="${CI_CC:-clang}" ;;
|
||||||
|
( * )
|
||||||
|
[[ -x $(command -v gcc) ]] && CI_CC="${CI_CC:-gcc}" ;;
|
||||||
|
esac
|
||||||
|
CI_CC="${CI_CC:-cc}"
|
||||||
|
case "$CI_CC" in
|
||||||
|
( *clang* )
|
||||||
|
CI_LEGACY_MAKEFILES="${CI_LEGACY_MAKEFILES:-"scripts/makefile.clang"}" ;;
|
||||||
|
( *gcc* )
|
||||||
|
CI_LEGACY_MAKEFILES="${CI_LEGACY_MAKEFILES:-"scripts/makefile.gcc"}" ;;
|
||||||
|
( cc | c89 | c99 )
|
||||||
|
CI_LEGACY_MAKEFILES="${CI_LEGACY_MAKEFILES:-"scripts/makefile.std"}" ;;
|
||||||
|
esac
|
||||||
|
CI_LD="${CI_LD:-"$CI_CC"}"
|
||||||
|
CI_LIBS="${CI_LIBS:-"-lz -lm"}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_trace_legacy {
|
||||||
|
ci_info "## START OF CONFIGURATION ##"
|
||||||
|
ci_info "system name: $CI_SYSTEM_NAME"
|
||||||
|
ci_info "machine hardware name: $CI_MACHINE_NAME"
|
||||||
|
ci_info "source directory: $CI_SRCDIR"
|
||||||
|
ci_info "build directory: $CI_BUILDDIR"
|
||||||
|
ci_info "environment option: \$CI_LEGACY_MAKEFILES: '$CI_LEGACY_MAKEFILES'"
|
||||||
|
ci_info "environment option: \$CI_MAKE: '$CI_MAKE'"
|
||||||
|
ci_info "environment option: \$CI_MAKE_FLAGS: '$CI_MAKE_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_MAKE_VARS: '$CI_MAKE_VARS'"
|
||||||
|
ci_info "environment option: \$CI_CC: '$CI_CC'"
|
||||||
|
ci_info "environment option: \$CI_CC_FLAGS: '$CI_CC_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_CPP: '$CI_CPP'"
|
||||||
|
ci_info "environment option: \$CI_CPP_FLAGS: '$CI_CPP_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_AR: '$CI_AR'"
|
||||||
|
ci_info "environment option: \$CI_RANLIB: '$CI_RANLIB'"
|
||||||
|
ci_info "environment option: \$CI_LD: '$CI_LD'"
|
||||||
|
ci_info "environment option: \$CI_LD_FLAGS: '$CI_LD_FLAGS'"
|
||||||
|
ci_info "environment option: \$CI_LIBS: '$CI_LIBS'"
|
||||||
|
ci_info "environment option: \$CI_SANITIZERS: '$CI_SANITIZERS'"
|
||||||
|
ci_info "environment option: \$CI_NO_TEST: '$CI_NO_TEST'"
|
||||||
|
ci_info "environment option: \$CI_NO_CLEAN: '$CI_NO_CLEAN'"
|
||||||
|
ci_info "executable: \$CI_MAKE: $(command -V "$CI_MAKE")"
|
||||||
|
[[ $CI_CC ]] &&
|
||||||
|
ci_info "executable: \$CI_CC: $(command -V "$CI_CC")"
|
||||||
|
[[ $CI_CPP ]] &&
|
||||||
|
ci_info "executable: \$CI_CPP: $(command -V "$CI_CPP")"
|
||||||
|
[[ $CI_AR ]] &&
|
||||||
|
ci_info "executable: \$CI_AR: $(command -V "$CI_AR")"
|
||||||
|
[[ $CI_RANLIB ]] &&
|
||||||
|
ci_info "executable: \$CI_RANLIB: $(command -V "$CI_RANLIB")"
|
||||||
|
[[ $CI_LD ]] &&
|
||||||
|
ci_info "executable: \$CI_LD: $(command -V "$CI_LD")"
|
||||||
|
ci_info "## END OF CONFIGURATION ##"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ci_build_legacy {
|
||||||
|
ci_info "## START OF BUILD ##"
|
||||||
|
# Initialize ALL_CC_FLAGS and ALL_LD_FLAGS as strings.
|
||||||
|
local ALL_CC_FLAGS="$CI_CC_FLAGS"
|
||||||
|
local ALL_LD_FLAGS="$CI_LD_FLAGS"
|
||||||
|
[[ $CI_SANITIZERS ]] && {
|
||||||
|
ALL_CC_FLAGS="-fsanitize=$CI_SANITIZERS ${ALL_CC_FLAGS:-"-O2"}"
|
||||||
|
ALL_LD_FLAGS="-fsanitize=$CI_SANITIZERS $ALL_LD_FLAGS"
|
||||||
|
}
|
||||||
|
# Initialize ALL_MAKE_FLAGS and ALL_MAKE_VARS as arrays.
|
||||||
|
local -a ALL_MAKE_FLAGS=($CI_MAKE_FLAGS)
|
||||||
|
local -a ALL_MAKE_VARS=()
|
||||||
|
[[ $CI_CC ]] && ALL_MAKE_VARS+=(CC="$CI_CC")
|
||||||
|
[[ $ALL_CC_FLAGS ]] && ALL_MAKE_VARS+=(CFLAGS="$ALL_CC_FLAGS")
|
||||||
|
[[ $CI_CPP ]] && ALL_MAKE_VARS+=(CPP="$CI_CPP")
|
||||||
|
[[ $CI_CPP_FLAGS ]] && ALL_MAKE_VARS+=(CPPFLAGS="$CI_CPP_FLAGS")
|
||||||
|
[[ $CI_AR ]] && ALL_MAKE_VARS+=(
|
||||||
|
AR="${CI_AR:-ar}"
|
||||||
|
AR_RC="${CI_AR:-ar} rc"
|
||||||
|
)
|
||||||
|
[[ $CI_RANLIB ]] && ALL_MAKE_VARS+=(RANLIB="$CI_RANLIB")
|
||||||
|
[[ $CI_LD ]] && ALL_MAKE_VARS+=(LD="$CI_LD")
|
||||||
|
[[ $ALL_LD_FLAGS ]] && ALL_MAKE_VARS+=(LDFLAGS="$ALL_LD_FLAGS")
|
||||||
|
ALL_MAKE_VARS+=(LIBS="$CI_LIBS")
|
||||||
|
ALL_MAKE_VARS+=($CI_MAKE_VARS)
|
||||||
|
# Build!
|
||||||
|
ci_spawn cd "$CI_SRCDIR"
|
||||||
|
local MY_MAKEFILE
|
||||||
|
for MY_MAKEFILE in $CI_LEGACY_MAKEFILES
|
||||||
|
do
|
||||||
|
ci_info "using makefile: $MY_MAKEFILE"
|
||||||
|
ci_spawn "$CI_MAKE" -f "$MY_MAKEFILE" \
|
||||||
|
"${ALL_MAKE_FLAGS[@]}" \
|
||||||
|
"${ALL_MAKE_VARS[@]}"
|
||||||
|
[[ $CI_NO_TEST ]] ||
|
||||||
|
ci_spawn "$CI_MAKE" -f "$MY_MAKEFILE" \
|
||||||
|
"${ALL_MAKE_FLAGS[@]}" \
|
||||||
|
"${ALL_MAKE_VARS[@]}" \
|
||||||
|
test
|
||||||
|
[[ $CI_NO_CLEAN ]] ||
|
||||||
|
ci_spawn "$CI_MAKE" -f "$MY_MAKEFILE" \
|
||||||
|
"${ALL_MAKE_FLAGS[@]}" \
|
||||||
|
"${ALL_MAKE_VARS[@]}" \
|
||||||
|
clean
|
||||||
|
done
|
||||||
|
ci_info "## END OF BUILD ##"
|
||||||
|
}
|
||||||
|
|
||||||
|
ci_init_legacy
|
||||||
|
ci_trace_legacy
|
||||||
|
[[ $# -eq 0 ]] || {
|
||||||
|
ci_info "note: this program accepts environment options only"
|
||||||
|
ci_err "unexpected command arguments: '$*'"
|
||||||
|
}
|
||||||
|
ci_build_legacy
|
|
@ -0,0 +1,348 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
|
||||||
|
scriptversion=2018-03-07.03; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||||
|
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# As a special exception to the GNU General Public License, if you
|
||||||
|
# distribute this file as part of a program that contains a
|
||||||
|
# configuration script generated by Autoconf, you may include it under
|
||||||
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# This file is maintained in Automake, please report
|
||||||
|
# bugs to <bug-automake@gnu.org> or send patches to
|
||||||
|
# <automake-patches@gnu.org>.
|
||||||
|
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
|
||||||
|
# We need space, tab and new line, in precisely that order. Quoting is
|
||||||
|
# there to prevent tools from complaining about whitespace usage.
|
||||||
|
IFS=" "" $nl"
|
||||||
|
|
||||||
|
file_conv=
|
||||||
|
|
||||||
|
# func_file_conv build_file lazy
|
||||||
|
# Convert a $build file to $host form and store it in $file
|
||||||
|
# Currently only supports Windows hosts. If the determined conversion
|
||||||
|
# type is listed in (the comma separated) LAZY, no conversion will
|
||||||
|
# take place.
|
||||||
|
func_file_conv ()
|
||||||
|
{
|
||||||
|
file=$1
|
||||||
|
case $file in
|
||||||
|
/ | /[!/]*) # absolute file, and not a UNC file
|
||||||
|
if test -z "$file_conv"; then
|
||||||
|
# lazily determine how to convert abs files
|
||||||
|
case `uname -s` in
|
||||||
|
MINGW*)
|
||||||
|
file_conv=mingw
|
||||||
|
;;
|
||||||
|
CYGWIN* | MSYS*)
|
||||||
|
file_conv=cygwin
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
file_conv=wine
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
case $file_conv/,$2, in
|
||||||
|
*,$file_conv,*)
|
||||||
|
;;
|
||||||
|
mingw/*)
|
||||||
|
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||||
|
;;
|
||||||
|
cygwin/* | msys/*)
|
||||||
|
file=`cygpath -m "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
wine/*)
|
||||||
|
file=`winepath -w "$file" || echo "$file"`
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashL linkdir
|
||||||
|
# Make cl look for libraries in LINKDIR
|
||||||
|
func_cl_dashL ()
|
||||||
|
{
|
||||||
|
func_file_conv "$1"
|
||||||
|
if test -z "$lib_path"; then
|
||||||
|
lib_path=$file
|
||||||
|
else
|
||||||
|
lib_path="$lib_path;$file"
|
||||||
|
fi
|
||||||
|
linker_opts="$linker_opts -LIBPATH:$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_dashl library
|
||||||
|
# Do a library search-path lookup for cl
|
||||||
|
func_cl_dashl ()
|
||||||
|
{
|
||||||
|
lib=$1
|
||||||
|
found=no
|
||||||
|
save_IFS=$IFS
|
||||||
|
IFS=';'
|
||||||
|
for dir in $lib_path $LIB
|
||||||
|
do
|
||||||
|
IFS=$save_IFS
|
||||||
|
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.dll.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/$lib.lib"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/$lib.lib
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if test -f "$dir/lib$lib.a"; then
|
||||||
|
found=yes
|
||||||
|
lib=$dir/lib$lib.a
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$save_IFS
|
||||||
|
|
||||||
|
if test "$found" != yes; then
|
||||||
|
lib=$lib.lib
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# func_cl_wrapper cl arg...
|
||||||
|
# Adjust compile command to suit cl
|
||||||
|
func_cl_wrapper ()
|
||||||
|
{
|
||||||
|
# Assume a capable shell
|
||||||
|
lib_path=
|
||||||
|
shared=:
|
||||||
|
linker_opts=
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.[oO][bB][jJ])
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fo"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
func_file_conv "$2"
|
||||||
|
set x "$@" -Fe"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-I)
|
||||||
|
eat=1
|
||||||
|
func_file_conv "$2" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-I*)
|
||||||
|
func_file_conv "${1#-I}" mingw
|
||||||
|
set x "$@" -I"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashl "$2"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-l*)
|
||||||
|
func_cl_dashl "${1#-l}"
|
||||||
|
set x "$@" "$lib"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-L)
|
||||||
|
eat=1
|
||||||
|
func_cl_dashL "$2"
|
||||||
|
;;
|
||||||
|
-L*)
|
||||||
|
func_cl_dashL "${1#-L}"
|
||||||
|
;;
|
||||||
|
-static)
|
||||||
|
shared=false
|
||||||
|
;;
|
||||||
|
-Wl,*)
|
||||||
|
arg=${1#-Wl,}
|
||||||
|
save_ifs="$IFS"; IFS=','
|
||||||
|
for flag in $arg; do
|
||||||
|
IFS="$save_ifs"
|
||||||
|
linker_opts="$linker_opts $flag"
|
||||||
|
done
|
||||||
|
IFS="$save_ifs"
|
||||||
|
;;
|
||||||
|
-Xlinker)
|
||||||
|
eat=1
|
||||||
|
linker_opts="$linker_opts $2"
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||||
|
func_file_conv "$1"
|
||||||
|
set x "$@" -Tp"$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||||
|
func_file_conv "$1" mingw
|
||||||
|
set x "$@" "$file"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
if test -n "$linker_opts"; then
|
||||||
|
linker_opts="-link$linker_opts"
|
||||||
|
fi
|
||||||
|
exec "$@" $linker_opts
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
eat=
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
'')
|
||||||
|
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
-h | --h*)
|
||||||
|
cat <<\EOF
|
||||||
|
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Wrapper for compilers which do not understand '-c -o'.
|
||||||
|
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||||
|
arguments, and rename the output as expected.
|
||||||
|
|
||||||
|
If you are trying to build a whole package this is not the
|
||||||
|
right script to run: please start by reading the file 'INSTALL'.
|
||||||
|
|
||||||
|
Report bugs to <bug-automake@gnu.org>.
|
||||||
|
EOF
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
-v | --v*)
|
||||||
|
echo "compile $scriptversion"
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||||
|
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||||
|
func_cl_wrapper "$@" # Doesn't return...
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ofile=
|
||||||
|
cfile=
|
||||||
|
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$eat"; then
|
||||||
|
eat=
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
-o)
|
||||||
|
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||||
|
# So we strip '-o arg' only if arg is an object.
|
||||||
|
eat=1
|
||||||
|
case $2 in
|
||||||
|
*.o | *.obj)
|
||||||
|
ofile=$2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" -o "$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*.c)
|
||||||
|
cfile=$1
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set x "$@" "$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -z "$ofile" || test -z "$cfile"; then
|
||||||
|
# If no '-o' option was seen then we might have been invoked from a
|
||||||
|
# pattern rule where we don't need one. That is ok -- this is a
|
||||||
|
# normal compilation that the losing compiler can handle. If no
|
||||||
|
# '.c' file was seen then we are probably linking. That is also
|
||||||
|
# ok.
|
||||||
|
exec "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Name of file we expect compiler to create.
|
||||||
|
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||||
|
|
||||||
|
# Create the lock directory.
|
||||||
|
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||||
|
# that we are using for the .o file. Also, base the name on the expected
|
||||||
|
# object file name, since that is what matters with a parallel build.
|
||||||
|
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||||
|
while true; do
|
||||||
|
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
# FIXME: race condition here if user kills between mkdir and trap.
|
||||||
|
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||||
|
|
||||||
|
# Run the compile.
|
||||||
|
"$@"
|
||||||
|
ret=$?
|
||||||
|
|
||||||
|
if test -f "$cofile"; then
|
||||||
|
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||||
|
elif test -f "${cofile}bj"; then
|
||||||
|
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rmdir "$lockdir"
|
||||||
|
exit $ret
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC0"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,123 @@
|
||||||
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#undef HAVE_DLFCN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `feenableexcept' function. */
|
||||||
|
#undef HAVE_FEENABLEEXCEPT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `m' library (-lm). */
|
||||||
|
#undef HAVE_LIBM
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `z' library (-lz). */
|
||||||
|
#undef HAVE_LIBZ
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pow' function. */
|
||||||
|
#undef HAVE_POW
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdio.h> header file. */
|
||||||
|
#undef HAVE_STDIO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||||
|
#undef LT_OBJDIR
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#undef PACKAGE_URL
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Turn on ARM Neon optimizations at run-time */
|
||||||
|
#undef PNG_ARM_NEON_API_SUPPORTED
|
||||||
|
|
||||||
|
/* Check for ARM Neon support at run-time */
|
||||||
|
#undef PNG_ARM_NEON_CHECK_SUPPORTED
|
||||||
|
|
||||||
|
/* Enable ARM Neon optimizations */
|
||||||
|
#undef PNG_ARM_NEON_OPT
|
||||||
|
|
||||||
|
/* Enable Intel SSE optimizations */
|
||||||
|
#undef PNG_INTEL_SSE_OPT
|
||||||
|
|
||||||
|
/* Turn on MIPS MSA optimizations at run-time */
|
||||||
|
#undef PNG_MIPS_MSA_API_SUPPORTED
|
||||||
|
|
||||||
|
/* Check for MIPS MSA support at run-time */
|
||||||
|
#undef PNG_MIPS_MSA_CHECK_SUPPORTED
|
||||||
|
|
||||||
|
/* Enable MIPS MSA optimizations */
|
||||||
|
#undef PNG_MIPS_MSA_OPT
|
||||||
|
|
||||||
|
/* Turn on POWERPC VSX optimizations at run-time */
|
||||||
|
#undef PNG_POWERPC_VSX_API_SUPPORTED
|
||||||
|
|
||||||
|
/* Check for POWERPC VSX support at run-time */
|
||||||
|
#undef PNG_POWERPC_VSX_CHECK_SUPPORTED
|
||||||
|
|
||||||
|
/* Enable POWERPC VSX optimizations */
|
||||||
|
#undef PNG_POWERPC_VSX_OPT
|
||||||
|
|
||||||
|
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||||
|
required in a freestanding environment). This macro is provided for
|
||||||
|
backward compatibility; new code need not use it. */
|
||||||
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||||
|
#undef TM_IN_SYS_TIME
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* Define to the equivalent of the C99 'restrict' keyword, or to
|
||||||
|
nothing if this is not supported. Do not define if restrict is
|
||||||
|
supported only directly. */
|
||||||
|
#undef restrict
|
||||||
|
/* Work around a bug in older versions of Sun C++, which did not
|
||||||
|
#define __restrict__ or support _Restrict or __restrict__
|
||||||
|
even though the corresponding Sun C compiler ended up with
|
||||||
|
"#define restrict _Restrict" or "#define restrict __restrict__"
|
||||||
|
in the previous line. This workaround can be removed once
|
||||||
|
we assume Oracle Developer Studio 12.5 (2016) or later. */
|
||||||
|
#if defined __SUNPRO_CC && !defined __RESTRICT && !defined __restrict__
|
||||||
|
# define _Restrict
|
||||||
|
# define __restrict__
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,527 @@
|
||||||
|
# configure.ac
|
||||||
|
|
||||||
|
# Copyright (c) 2018-2022 Cosmin Truta
|
||||||
|
# Copyright (c) 2004-2016 Glenn Randers-Pehrson
|
||||||
|
|
||||||
|
# This code is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h
|
||||||
|
|
||||||
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
dnl
|
||||||
|
dnl Minor upgrades (compatible ABI): increment the package version
|
||||||
|
dnl (third field in two places below) and set the PNGLIB_RELEASE
|
||||||
|
dnl variable.
|
||||||
|
dnl
|
||||||
|
dnl Major upgrades (incompatible ABI): increment the package major
|
||||||
|
dnl version (second field, or first if desired), set the minor
|
||||||
|
dnl to 0, set PNGLIB_MAJOR below *and* follow the instructions in
|
||||||
|
dnl Makefile.am to upgrade the package name.
|
||||||
|
|
||||||
|
dnl This is here to prevent earlier autoconf from being used, it
|
||||||
|
dnl should not be necessary to regenerate configure if the time
|
||||||
|
dnl stamps are correct
|
||||||
|
AC_PREREQ([2.68])
|
||||||
|
|
||||||
|
dnl Version number stuff here:
|
||||||
|
|
||||||
|
AC_INIT([libpng],[1.6.39],[png-mng-implement@lists.sourceforge.net])
|
||||||
|
AC_CONFIG_MACRO_DIR([scripts])
|
||||||
|
|
||||||
|
# libpng does not follow GNU file name conventions (hence 'foreign')
|
||||||
|
# color-tests requires automake 1.11 or later
|
||||||
|
# silent-rules requires automake 1.11 or later
|
||||||
|
# dist-xz requires automake 1.11 or later
|
||||||
|
# 1.12.2 fixes a security issue in 1.11.2 and 1.12.1
|
||||||
|
# 1.13 is required for parallel tests
|
||||||
|
AM_INIT_AUTOMAKE([1.13 foreign dist-xz color-tests silent-rules subdir-objects])
|
||||||
|
# The following line causes --disable-maintainer-mode to be the default to
|
||||||
|
# configure. This is necessary because libpng distributions cannot rely on the
|
||||||
|
# time stamps of the autotools generated files being correct
|
||||||
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
|
dnl configure.ac and Makefile.am expect automake 1.11.2 or a compatible later
|
||||||
|
dnl version; aclocal.m4 will generate a failure if you use a prior version of
|
||||||
|
dnl automake, so the following is not necessary (and is not defined anyway):
|
||||||
|
dnl AM_PREREQ([1.11.2])
|
||||||
|
dnl stop configure from automagically running automake
|
||||||
|
|
||||||
|
PNGLIB_VERSION=1.6.39
|
||||||
|
PNGLIB_MAJOR=1
|
||||||
|
PNGLIB_MINOR=6
|
||||||
|
PNGLIB_RELEASE=39
|
||||||
|
|
||||||
|
dnl End of version number stuff
|
||||||
|
|
||||||
|
AC_CONFIG_SRCDIR([pngget.c])
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
|
# Checks for programs.
|
||||||
|
AC_LANG([C])
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_AS
|
||||||
|
LT_PATH_LD
|
||||||
|
AC_PROG_CPP
|
||||||
|
AC_PROG_AWK
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
|
||||||
|
dnl libtool/libtoolize; version 2.4.2 is the tested version. This or any
|
||||||
|
dnl compatible later version may be used
|
||||||
|
LT_INIT([win32-dll])
|
||||||
|
LT_PREREQ([2.4.2])
|
||||||
|
|
||||||
|
# Some awks crash when confronted with pnglibconf.dfa, do a test run now
|
||||||
|
# to make sure this doesn't happen
|
||||||
|
AC_MSG_CHECKING([that AWK works])
|
||||||
|
if ${AWK} -f ${srcdir}/scripts/options.awk out="/dev/null" version=search\
|
||||||
|
${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\
|
||||||
|
${srcdir}/pngusr.dfa 1>&2
|
||||||
|
then
|
||||||
|
AC_MSG_RESULT([ok])
|
||||||
|
else
|
||||||
|
AC_MSG_FAILURE([failed], 1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is a remnant of the old cc -E validation, where it may have been
|
||||||
|
# necessary to use a different preprocessor for .dfn files
|
||||||
|
DFNCPP="$CPP"
|
||||||
|
AC_SUBST(DFNCPP)
|
||||||
|
|
||||||
|
# -Werror cannot be passed to GCC in CFLAGS because configure will fail
|
||||||
|
# (it checks the compiler with a program that generates a warning).
|
||||||
|
# Add the following option to deal with this:
|
||||||
|
AC_ARG_VAR(PNG_COPTS,
|
||||||
|
[additional flags for the C compiler, use this for options that would]
|
||||||
|
[cause configure itself to fail])
|
||||||
|
AC_ARG_ENABLE(werror,
|
||||||
|
AS_HELP_STRING([[[--enable-werror[=OPT]]]],
|
||||||
|
[Pass -Werror or the given argument to the compiler if it is supported]),
|
||||||
|
[test "$enable_werror" = "yes" && enable_werror="-Werror"
|
||||||
|
if test "$enable_werror" != "no"; then
|
||||||
|
sav_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$enable_werror $CFLAGS"
|
||||||
|
AC_MSG_CHECKING([if the compiler allows $enable_werror])
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_SOURCE([
|
||||||
|
[int main(int argc, char **argv){]
|
||||||
|
[return argv[argc-1][0];]
|
||||||
|
[}]])],
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
PNG_COPTS="$PNG_COPTS $enable_werror",
|
||||||
|
AC_MSG_RESULT(no))
|
||||||
|
CFLAGS="$sav_CFLAGS"
|
||||||
|
fi],)
|
||||||
|
|
||||||
|
# For GCC 5 the default mode for C is -std=gnu11 instead of -std=gnu89.
|
||||||
|
# In pngpriv.h we request just the POSIX 1003.1 and C89 APIs by defining
|
||||||
|
# _POSIX_SOURCE to 1. This is incompatible with the new default mode, so
|
||||||
|
# we test for that and force the "-std=c89" compiler option:
|
||||||
|
AC_MSG_CHECKING([if we need to force back C standard to C89])
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([
|
||||||
|
[#define _POSIX_SOURCE 1]
|
||||||
|
[#include <stdio.h>]
|
||||||
|
])],
|
||||||
|
AC_MSG_RESULT(no),[
|
||||||
|
if test "x$GCC" != "xyes"; then
|
||||||
|
AC_MSG_ERROR(
|
||||||
|
[Forcing back to C89 is required but the flags are only known for GCC])
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
CFLAGS="$CFLAGS -std=c89"
|
||||||
|
])
|
||||||
|
|
||||||
|
# Checks for structures and compiler characteristics.
|
||||||
|
AC_STRUCT_TM
|
||||||
|
AC_C_RESTRICT
|
||||||
|
|
||||||
|
# Checks for library functions.
|
||||||
|
AC_CHECK_FUNCS([pow], ,
|
||||||
|
[AC_CHECK_LIB([m], [pow], , [AC_MSG_ERROR([cannot find pow])])])
|
||||||
|
|
||||||
|
# Some later POSIX 1003.1 functions are required for test programs, failure
|
||||||
|
# here is soft (the corresponding test program is not built).
|
||||||
|
AC_CHECK_FUNC([clock_gettime], , [AC_MSG_WARN([not building timepng])])
|
||||||
|
AM_CONDITIONAL([HAVE_CLOCK_GETTIME], [test "$ac_cv_func_clock_gettime" = "yes"])
|
||||||
|
|
||||||
|
AC_ARG_WITH(zlib-prefix,
|
||||||
|
AS_HELP_STRING([[[--with-zlib-prefix]]],
|
||||||
|
[prefix that may have been used in installed zlib]),
|
||||||
|
[ZPREFIX=${withval}],
|
||||||
|
[ZPREFIX='z_'])
|
||||||
|
AC_CHECK_LIB([z], [zlibVersion], ,
|
||||||
|
[AC_CHECK_LIB([z], [${ZPREFIX}zlibVersion], ,
|
||||||
|
[AC_MSG_ERROR([zlib not installed])])])
|
||||||
|
|
||||||
|
# The following is for pngvalid, to ensure it catches FP errors even on
|
||||||
|
# platforms that don't enable FP exceptions, the function appears in the math
|
||||||
|
# library (typically), it's not an error if it is not found.
|
||||||
|
AC_CHECK_LIB([m], [feenableexcept])
|
||||||
|
AC_CHECK_FUNCS([feenableexcept])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([if using Solaris linker])
|
||||||
|
SLD=`$LD --version 2>&1 | grep Solaris`
|
||||||
|
if test "$SLD"; then
|
||||||
|
have_solaris_ld=yes
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
have_solaris_ld=no
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_SOLARIS_LD, test "$have_solaris_ld" = "yes")
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([if libraries can be versioned])
|
||||||
|
# Special case for PE/COFF platforms: ld reports
|
||||||
|
# support for version-script, but doesn't actually
|
||||||
|
# DO anything with it.
|
||||||
|
case $host in
|
||||||
|
*cygwin* | *mingw32* | *interix* )
|
||||||
|
have_ld_version_script=no
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
|
||||||
|
if test "$have_solaris_ld" = "yes"; then
|
||||||
|
GLD=`$LD --help < /dev/null 2>&1 | grep 'M mapfile'`
|
||||||
|
else
|
||||||
|
GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$GLD"; then
|
||||||
|
have_ld_version_script=yes
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
have_ld_version_script=no
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_WARN(*** You have not enabled versioned symbols.)
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
|
||||||
|
|
||||||
|
if test "$have_ld_version_script" = "yes"; then
|
||||||
|
AC_MSG_CHECKING([for symbol prefix])
|
||||||
|
SYMBOL_PREFIX=`echo "PREFIX=__USER_LABEL_PREFIX__" \
|
||||||
|
| ${CPP-${CC-gcc} -E} - 2>&1 \
|
||||||
|
| ${EGREP-grep} "^PREFIX=" \
|
||||||
|
| ${SED-sed} -e "s:^PREFIX=::" -e "s:__USER_LABEL_PREFIX__::"`
|
||||||
|
AC_SUBST(SYMBOL_PREFIX)
|
||||||
|
AC_MSG_RESULT($SYMBOL_PREFIX)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Substitutions for .in files
|
||||||
|
AC_SUBST(PNGLIB_VERSION)
|
||||||
|
AC_SUBST(PNGLIB_MAJOR)
|
||||||
|
AC_SUBST(PNGLIB_MINOR)
|
||||||
|
AC_SUBST(PNGLIB_RELEASE)
|
||||||
|
|
||||||
|
# Additional arguments (and substitutions)
|
||||||
|
# Allow the pkg-config directory to be set
|
||||||
|
AC_ARG_WITH(pkgconfigdir,
|
||||||
|
AS_HELP_STRING([[[--with-pkgconfigdir]]],
|
||||||
|
[Use the specified pkgconfig dir (default is libdir/pkgconfig)]),
|
||||||
|
[pkgconfigdir=${withval}],
|
||||||
|
[pkgconfigdir='${libdir}/pkgconfig'])
|
||||||
|
|
||||||
|
AC_SUBST([pkgconfigdir])
|
||||||
|
AC_MSG_NOTICE([[pkgconfig directory is ${pkgconfigdir}]])
|
||||||
|
|
||||||
|
# Make the *-config binary config scripts optional
|
||||||
|
AC_ARG_WITH(binconfigs,
|
||||||
|
AS_HELP_STRING([[[--with-binconfigs]]],
|
||||||
|
[Generate shell libpng-config scripts as well as pkg-config data]
|
||||||
|
[@<:@default=yes@:>@]),
|
||||||
|
[if test "${withval}" = no; then
|
||||||
|
binconfigs=
|
||||||
|
AC_MSG_NOTICE([[libpng-config scripts will not be built]])
|
||||||
|
else
|
||||||
|
binconfigs='${binconfigs}'
|
||||||
|
fi],
|
||||||
|
[binconfigs='${binconfigs}'])
|
||||||
|
AC_SUBST([binconfigs])
|
||||||
|
|
||||||
|
# Support for prefixes to the API function names; this will generate defines
|
||||||
|
# at the start of the build to rename exported library functions
|
||||||
|
AC_ARG_WITH(libpng-prefix,
|
||||||
|
AS_HELP_STRING([[[--with-libpng-prefix]]],
|
||||||
|
[prefix libpng exported function (API) names with the given value]),
|
||||||
|
[if test "${withval:-no}" != "no"; then
|
||||||
|
AC_SUBST([PNG_PREFIX], [${withval}])
|
||||||
|
fi])
|
||||||
|
AM_CONDITIONAL([DO_PNG_PREFIX], [test "${with_libpng_prefix:-no}" != "no"])
|
||||||
|
|
||||||
|
# Control over what links are made for installed files. Versioned files are
|
||||||
|
# always installed, when the following options are turned on corresponding
|
||||||
|
# unversioned links are also created (normally as symbolic links):
|
||||||
|
AC_ARG_ENABLE([unversioned-links],
|
||||||
|
AS_HELP_STRING([[[--enable-unversioned-links]]],
|
||||||
|
[Installed libpng header files are placed in a versioned subdirectory]
|
||||||
|
[and installed libpng library (including DLL) files are versioned.]
|
||||||
|
[If this option is enabled unversioned links will be created pointing to]
|
||||||
|
[the corresponding installed files. If you use libpng.pc or]
|
||||||
|
[libpng-config for all builds you do not need these links, but if you]
|
||||||
|
[compile programs directly they will typically #include <png.h> and]
|
||||||
|
[link with -lpng; in that case you need the links.]
|
||||||
|
[The links can be installed manually using 'make install-header-links']
|
||||||
|
[and 'make install-library-links' and can be removed using the]
|
||||||
|
[corresponding uninstall- targets. If you do enable this option every]
|
||||||
|
[libpng 'make install' will recreate the links to point to the just]
|
||||||
|
[installed version of libpng. The default is to create the links;]
|
||||||
|
[use --disable-unversioned-links to change this]))
|
||||||
|
|
||||||
|
# The AM_CONDITIONAL test is written so that the default is enabled;
|
||||||
|
# --disable-unversioned-links must be given to turn the option off.
|
||||||
|
AM_CONDITIONAL([DO_INSTALL_LINKS],[test "$enable_unversioned_links" != "no"])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([unversioned-libpng-pc],
|
||||||
|
AS_HELP_STRING([[[--enable-unversioned-libpng-pc]]],
|
||||||
|
[Install the configuration file 'libpng.pc' as a link to the versioned]
|
||||||
|
[version. This is done by default - use --disable-unversioned-libpng-pc]
|
||||||
|
[to change this.]))
|
||||||
|
AM_CONDITIONAL([DO_INSTALL_LIBPNG_PC],
|
||||||
|
[test "$enable_unversioned_libpng_pc" != "no"])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([unversioned-libpng-config],
|
||||||
|
AS_HELP_STRING([[[--enable-unversioned-libpng-config]]],
|
||||||
|
[Install the configuration file 'libpng-config' as a link to the]
|
||||||
|
[versioned version. This is done by default - use]
|
||||||
|
[--disable-unversioned-libpng-config to change this.]))
|
||||||
|
AM_CONDITIONAL([DO_INSTALL_LIBPNG_CONFIG],
|
||||||
|
[test "$enable_unversioned_libpng_config" != "no"])
|
||||||
|
|
||||||
|
# HOST-SPECIFIC OPTIONS
|
||||||
|
# =====================
|
||||||
|
#
|
||||||
|
# DEFAULT
|
||||||
|
# =======
|
||||||
|
#
|
||||||
|
AC_ARG_ENABLE([hardware-optimizations],
|
||||||
|
AS_HELP_STRING([[[--enable-hardware-optimizations]]],
|
||||||
|
[Enable hardware optimizations: =no/off, yes/on:]),
|
||||||
|
[case "$enableval" in
|
||||||
|
no|off)
|
||||||
|
# disable hardware optimization on all systems:
|
||||||
|
enable_arm_neon=no
|
||||||
|
AC_DEFINE([PNG_ARM_NEON_OPT], [0],
|
||||||
|
[Disable ARM_NEON optimizations])
|
||||||
|
enable_mips_msa=no
|
||||||
|
AC_DEFINE([PNG_MIPS_MSA_OPT], [0],
|
||||||
|
[Disable MIPS_MSA optimizations])
|
||||||
|
enable_powerpc_vsx=no
|
||||||
|
AC_DEFINE([PNG_POWERPC_VSX_OPT], [0],
|
||||||
|
[Disable POWERPC VSX optimizations])
|
||||||
|
enable_intel_sse=no
|
||||||
|
AC_DEFINE([PNG_INTEL_SSE_OPT], [0],
|
||||||
|
[Disable INTEL_SSE optimizations])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# allow enabling hardware optimization on any system:
|
||||||
|
case "$host_cpu" in
|
||||||
|
arm*|aarch64*)
|
||||||
|
enable_arm_neon=yes
|
||||||
|
AC_DEFINE([PNG_ARM_NEON_OPT], [2],
|
||||||
|
[Enable ARM_NEON optimizations])
|
||||||
|
;;
|
||||||
|
mipsel*|mips64el*)
|
||||||
|
enable_mips_msa=yes
|
||||||
|
AC_DEFINE([PNG_MIPS_MSA_OPT], [2],
|
||||||
|
[Enable MIPS_MSA optimizations])
|
||||||
|
;;
|
||||||
|
i?86|x86_64)
|
||||||
|
enable_intel_sse=yes
|
||||||
|
AC_DEFINE([PNG_INTEL_SSE_OPT], [1],
|
||||||
|
[Enable Intel SSE optimizations])
|
||||||
|
;;
|
||||||
|
powerpc*|ppc64*)
|
||||||
|
enable_powerpc_vsx=yes
|
||||||
|
AC_DEFINE([PNG_POWERPC_VSX_OPT], [2],
|
||||||
|
[Enable POWERPC VSX optimizations])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# ARM
|
||||||
|
# ===
|
||||||
|
#
|
||||||
|
# ARM NEON (SIMD) support.
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([arm-neon],
|
||||||
|
AS_HELP_STRING([[[--enable-arm-neon]]],
|
||||||
|
[Enable ARM NEON optimizations: =no/off, check, api, yes/on:]
|
||||||
|
[no/off: disable the optimizations; check: use internal checking code]
|
||||||
|
[(deprecated and poorly supported); api: disable by default, enable by]
|
||||||
|
[a call to png_set_option; yes/on: turn on unconditionally.]
|
||||||
|
[If not specified: determined by the compiler.]),
|
||||||
|
[case "$enableval" in
|
||||||
|
no|off)
|
||||||
|
# disable the default enabling on __ARM_NEON__ systems:
|
||||||
|
AC_DEFINE([PNG_ARM_NEON_OPT], [0],
|
||||||
|
[Disable ARM Neon optimizations])
|
||||||
|
# Prevent inclusion of the assembler files below:
|
||||||
|
enable_arm_neon=no ;;
|
||||||
|
check)
|
||||||
|
AC_DEFINE([PNG_ARM_NEON_CHECK_SUPPORTED], [],
|
||||||
|
[Check for ARM Neon support at run-time]);;
|
||||||
|
api)
|
||||||
|
AC_DEFINE([PNG_ARM_NEON_API_SUPPORTED], [],
|
||||||
|
[Turn on ARM Neon optimizations at run-time]);;
|
||||||
|
yes|on)
|
||||||
|
AC_DEFINE([PNG_ARM_NEON_OPT], [2],
|
||||||
|
[Enable ARM Neon optimizations])
|
||||||
|
AC_MSG_WARN([--enable-arm-neon: please specify 'check' or 'api', if]
|
||||||
|
[you want the optimizations unconditionally pass -mfpu=neon]
|
||||||
|
[to the compiler.]);;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([--enable-arm-neon=${enable_arm_neon}: invalid value])
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# Add ARM-specific files to all builds where $host_cpu is arm ('arm*') or
|
||||||
|
# where ARM optimizations were explicitly requested (this allows a fallback
|
||||||
|
# if a future host CPU does not match 'arm*')
|
||||||
|
|
||||||
|
AM_CONDITIONAL([PNG_ARM_NEON],
|
||||||
|
[test "$enable_arm_neon" != 'no' &&
|
||||||
|
case "$host_cpu" in
|
||||||
|
arm*|aarch64*) : ;;
|
||||||
|
*) test "$enable_arm_neon" != '' ;;
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# MIPS
|
||||||
|
# ====
|
||||||
|
#
|
||||||
|
# MIPS MSA (SIMD) support.
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([mips-msa],
|
||||||
|
AS_HELP_STRING([[[--enable-mips-msa]]],
|
||||||
|
[Enable MIPS MSA optimizations: =no/off, check, api, yes/on:]
|
||||||
|
[no/off: disable the optimizations; check: use internal checking code]
|
||||||
|
[(deprecated and poorly supported); api: disable by default, enable by]
|
||||||
|
[a call to png_set_option; yes/on: turn on unconditionally.]
|
||||||
|
[If not specified: determined by the compiler.]),
|
||||||
|
[case "$enableval" in
|
||||||
|
no|off)
|
||||||
|
# disable the default enabling on __mips_msa systems:
|
||||||
|
AC_DEFINE([PNG_MIPS_MSA_OPT], [0],
|
||||||
|
[Disable MIPS MSA optimizations])
|
||||||
|
# Prevent inclusion of the assembler files below:
|
||||||
|
enable_mips_msa=no ;;
|
||||||
|
check)
|
||||||
|
AC_DEFINE([PNG_MIPS_MSA_CHECK_SUPPORTED], [],
|
||||||
|
[Check for MIPS MSA support at run-time]);;
|
||||||
|
api)
|
||||||
|
AC_DEFINE([PNG_MIPS_MSA_API_SUPPORTED], [],
|
||||||
|
[Turn on MIPS MSA optimizations at run-time]);;
|
||||||
|
yes|on)
|
||||||
|
AC_DEFINE([PNG_MIPS_MSA_OPT], [2],
|
||||||
|
[Enable MIPS MSA optimizations])
|
||||||
|
AC_MSG_WARN([--enable-mips-msa: please specify 'check' or 'api', if]
|
||||||
|
[you want the optimizations unconditionally pass '-mmsa -mfp64']
|
||||||
|
[to the compiler.]);;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([--enable-mips-msa=${enable_mips_msa}: invalid value])
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# Add MIPS-specific files to all builds where $host_cpu is mips ('mips*') or
|
||||||
|
# where MIPS optimizations were explicitly requested (this allows a fallback
|
||||||
|
# if a future host CPU does not match 'mips*')
|
||||||
|
|
||||||
|
AM_CONDITIONAL([PNG_MIPS_MSA],
|
||||||
|
[test "$enable_mips_msa" != 'no' &&
|
||||||
|
case "$host_cpu" in
|
||||||
|
mipsel*|mips64el*) : ;;
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# INTEL
|
||||||
|
# =====
|
||||||
|
#
|
||||||
|
# INTEL SSE (SIMD) support.
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([intel-sse],
|
||||||
|
AS_HELP_STRING([[[--enable-intel-sse]]],
|
||||||
|
[Enable Intel SSE optimizations: =no/off, yes/on:]
|
||||||
|
[no/off: disable the optimizations;]
|
||||||
|
[yes/on: enable the optimizations.]
|
||||||
|
[If not specified: determined by the compiler.]),
|
||||||
|
[case "$enableval" in
|
||||||
|
no|off)
|
||||||
|
# disable the default enabling:
|
||||||
|
AC_DEFINE([PNG_INTEL_SSE_OPT], [0],
|
||||||
|
[Disable Intel SSE optimizations])
|
||||||
|
# Prevent inclusion of the assembler files below:
|
||||||
|
enable_intel_sse=no ;;
|
||||||
|
yes|on)
|
||||||
|
AC_DEFINE([PNG_INTEL_SSE_OPT], [1],
|
||||||
|
[Enable Intel SSE optimizations]);;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([--enable-intel-sse=${enable_intel_sse}: invalid value])
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# Add Intel-specific files to all builds where $host_cpu is Intel ('x86*') or
|
||||||
|
# where Intel optimizations were explicitly requested (this allows a fallback
|
||||||
|
# if a future host CPU does not match 'x86*')
|
||||||
|
AM_CONDITIONAL([PNG_INTEL_SSE],
|
||||||
|
[test "$enable_intel_sse" != 'no' &&
|
||||||
|
case "$host_cpu" in
|
||||||
|
i?86|x86_64) : ;;
|
||||||
|
*) test "$enable_intel_sse" != '' ;;
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# PowerPC
|
||||||
|
# =======
|
||||||
|
#
|
||||||
|
# PowerPC VSX (SIMD) support.
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([powerpc-vsx],
|
||||||
|
AS_HELP_STRING([[[--enable-powerpc-vsx]]],
|
||||||
|
[Enable POWERPC VSX optimizations: =no/off, check, api, yes/on:]
|
||||||
|
[no/off: disable the optimizations; check: use internal checking code]
|
||||||
|
[api: disable by default, enable by a call to png_set_option]
|
||||||
|
[yes/on: turn on unconditionally.]
|
||||||
|
[If not specified: determined by the compiler.]),
|
||||||
|
[case "$enableval" in
|
||||||
|
no|off)
|
||||||
|
# disable the default enabling on __ppc64__ systems:
|
||||||
|
AC_DEFINE([PNG_POWERPC_VSX_OPT], [0],
|
||||||
|
[Disable POWERPC VSX optimizations])
|
||||||
|
# Prevent inclusion of the platform-specific files below:
|
||||||
|
enable_powerpc_vsx=no ;;
|
||||||
|
check)
|
||||||
|
AC_DEFINE([PNG_POWERPC_VSX_CHECK_SUPPORTED], [],
|
||||||
|
[Check for POWERPC VSX support at run-time])
|
||||||
|
AC_MSG_WARN([--enable-powerpc-vsx Please check contrib/powerpc/README file]
|
||||||
|
[for the list of supported OSes.]);;
|
||||||
|
api)
|
||||||
|
AC_DEFINE([PNG_POWERPC_VSX_API_SUPPORTED], [],
|
||||||
|
[Turn on POWERPC VSX optimizations at run-time]);;
|
||||||
|
yes|on)
|
||||||
|
AC_DEFINE([PNG_POWERPC_VSX_OPT], [2],
|
||||||
|
[Enable POWERPC VSX optimizations])
|
||||||
|
AC_MSG_WARN([--enable-powerpc-vsx: please specify 'check' or 'api', if]
|
||||||
|
[you want the optimizations unconditionally pass '-maltivec -mvsx']
|
||||||
|
[or '-mcpu=power8' to the compiler.]);;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([--enable-powerpc-vsx=${enable_powerpc_vsx}: invalid value])
|
||||||
|
esac])
|
||||||
|
|
||||||
|
# Add PowerPC-specific files to all builds where $host_cpu is powerpc('powerpc*')
|
||||||
|
# or where PowerPC optimizations were explicitly requested (this allows a fallback
|
||||||
|
# if a future host CPU does not match 'powerpc*')
|
||||||
|
|
||||||
|
AM_CONDITIONAL([PNG_POWERPC_VSX],
|
||||||
|
[test "$enable_powerpc_vsx" != 'no' &&
|
||||||
|
case "$host_cpu" in
|
||||||
|
powerpc*|ppc64*) : ;;
|
||||||
|
esac])
|
||||||
|
|
||||||
|
AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]])
|
||||||
|
|
||||||
|
# Config files, substituting as above
|
||||||
|
AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in])
|
||||||
|
AC_CONFIG_FILES([libpng-config:libpng-config.in],
|
||||||
|
[chmod +x libpng-config])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
This "contrib" directory contains contributions which are not necessarily under
|
||||||
|
the libpng license, although all are open source. They are not part of
|
||||||
|
libpng proper and are not used for building the library, although some are used
|
||||||
|
for testing the library via "make check".
|
|
@ -0,0 +1,83 @@
|
||||||
|
OPERATING SYSTEM SPECIFIC ARM NEON DETECTION
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Detection of the ability to execute ARM NEON on an ARM processor requires
|
||||||
|
operating system support. (The information is not available in user mode.)
|
||||||
|
|
||||||
|
HOW TO USE THIS
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This directory contains C code fragments that can be included in arm/arm_init.c
|
||||||
|
by setting the macro PNG_ARM_NEON_FILE to the file name in "" or <> at build
|
||||||
|
time. This setting is not recorded in pnglibconf.h and can be changed simply by
|
||||||
|
rebuilding arm/arm_init.o with the required macro definition.
|
||||||
|
|
||||||
|
For any of this code to be used the ARM NEON code must be enabled and run time
|
||||||
|
checks must be supported. I.e.:
|
||||||
|
|
||||||
|
#if PNG_ARM_NEON_OPT > 0
|
||||||
|
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
|
||||||
|
|
||||||
|
This is done in a 'configure' build by passing configure the argument:
|
||||||
|
|
||||||
|
--enable-arm-neon=check
|
||||||
|
|
||||||
|
Apart from the basic Linux implementation in contrib/arm-neon/linux.c this code
|
||||||
|
is unsupported. That means that it is not even compiled on a regular basis and
|
||||||
|
may be broken in any given minor release.
|
||||||
|
|
||||||
|
FILE FORMAT
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Each file documents its testing status as of the last time it was tested (which
|
||||||
|
may have been a long time ago):
|
||||||
|
|
||||||
|
STATUS: one of:
|
||||||
|
SUPPORTED: This indicates that the file is included in the regularly
|
||||||
|
performed test builds and bugs are fixed when discovered.
|
||||||
|
COMPILED: This indicates that the code did compile at least once. See the
|
||||||
|
more detailed description for the extent to which the result was
|
||||||
|
successful.
|
||||||
|
TESTED: This means the code was fully compiled into the libpng test programs
|
||||||
|
and these were run at least once.
|
||||||
|
|
||||||
|
BUG REPORTS: an email address to which to send reports of problems
|
||||||
|
|
||||||
|
The file is a fragment of C code. It should not define any 'extern' symbols;
|
||||||
|
everything should be static. It must define the function:
|
||||||
|
|
||||||
|
static int png_have_neon(png_structp png_ptr);
|
||||||
|
|
||||||
|
That function must return 1 if ARM NEON instructions are supported, 0 if not.
|
||||||
|
It must not execute png_error unless it detects a bug. A png_error will prevent
|
||||||
|
the reading of the PNG and in the future, writing too.
|
||||||
|
|
||||||
|
BUG REPORTS
|
||||||
|
-----------
|
||||||
|
|
||||||
|
If you mail a bug report for any file that is not SUPPORTED there may only be
|
||||||
|
limited response. Consider fixing it and sending a patch to fix the problem -
|
||||||
|
this is more likely to result in action.
|
||||||
|
|
||||||
|
CONTRIBUTIONS
|
||||||
|
-------------
|
||||||
|
|
||||||
|
You may send contributions of new implementations to
|
||||||
|
png-mng-implement@sourceforge.net. Please write code in strict C90 C where
|
||||||
|
possible. Obviously OS dependencies are to be expected. If you submit code you
|
||||||
|
must have the authors permission and it must have a license that is acceptable
|
||||||
|
to the current maintainer; in particular that license must permit modification
|
||||||
|
and redistribution.
|
||||||
|
|
||||||
|
Please try to make the contribution a single file and give the file a clear and
|
||||||
|
unambiguous name that identifies the target OS. If multiple files really are
|
||||||
|
required put them all in a sub-directory.
|
||||||
|
|
||||||
|
You must also be prepared to handle bug reports from users of the code, either
|
||||||
|
by joining the png-mng-implement mailing list or by providing an email for the
|
||||||
|
"BUG REPORTS" entry or both. Please make sure that the header of the file
|
||||||
|
contains the STATUS and BUG REPORTS fields as above.
|
||||||
|
|
||||||
|
Please list the OS requirements as precisely as possible. Ideally you should
|
||||||
|
also list the environment in which the code has been tested and certainly list
|
||||||
|
any environments where you suspect it might not work.
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* contrib/arm-neon/android-ndk.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Glenn Randers-Pehrson
|
||||||
|
* Written by John Bowler, 2014.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* SEE contrib/arm-neon/README before reporting bugs
|
||||||
|
*
|
||||||
|
* STATUS: COMPILED, UNTESTED
|
||||||
|
* BUG REPORTS: png-mng-implement@sourceforge.net
|
||||||
|
*
|
||||||
|
* png_have_neon implemented for the Android NDK, see:
|
||||||
|
*
|
||||||
|
* Documentation:
|
||||||
|
* http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html
|
||||||
|
* https://code.google.com/p/android/issues/detail?id=49065
|
||||||
|
*
|
||||||
|
* NOTE: this requires that libpng is built against the Android NDK and linked
|
||||||
|
* with an implementation of the Android ARM 'cpu-features' library. The code
|
||||||
|
* has been compiled only, not linked: no version of the library has been found,
|
||||||
|
* only the header files exist in the NDK.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cpu-features.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
png_have_neon(png_structp png_ptr)
|
||||||
|
{
|
||||||
|
/* This is a whole lot easier than the linux code, however it is probably
|
||||||
|
* implemented as below, therefore it is better to cache the result (these
|
||||||
|
* function calls may be slow!)
|
||||||
|
*/
|
||||||
|
PNG_UNUSED(png_ptr)
|
||||||
|
return android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
|
||||||
|
(android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/* contrib/arm-neon/linux-auxv.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Glenn Randers-Pehrson
|
||||||
|
* Written by Mans Rullgard, 2011.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* SEE contrib/arm-neon/README before reporting bugs
|
||||||
|
*
|
||||||
|
* STATUS: COMPILED, TESTED
|
||||||
|
* BUG REPORTS: png-mng-implement@sourceforge.net
|
||||||
|
*
|
||||||
|
* png_have_neon implemented for Linux versions which allow access to
|
||||||
|
* /proc/self/auxv. This is probably faster, cleaner and safer than the code to
|
||||||
|
* read /proc/cpuinfo in contrib/arm-neon/linux, however it is yet another piece
|
||||||
|
* of potentially untested code and has more complex dependencies than the code
|
||||||
|
* to read cpuinfo.
|
||||||
|
*
|
||||||
|
* This generic __linux__ implementation requires reading /proc/self/auxv and
|
||||||
|
* looking at each element for one that records NEON capabilities.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h> /* for POSIX 1003.1 */
|
||||||
|
#include <errno.h> /* for EINTR */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <elf.h>
|
||||||
|
#include <asm/hwcap.h>
|
||||||
|
|
||||||
|
/* A read call may be interrupted, in which case it returns -1 and sets errno to
|
||||||
|
* EINTR if nothing was done, otherwise (if something was done) a partial read
|
||||||
|
* may result.
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
safe_read(png_structp png_ptr, int fd, void *buffer_in, size_t nbytes)
|
||||||
|
{
|
||||||
|
size_t ntotal = 0;
|
||||||
|
char *buffer = png_voidcast(char*, buffer_in);
|
||||||
|
|
||||||
|
while (nbytes > 0)
|
||||||
|
{
|
||||||
|
unsigned int nread;
|
||||||
|
int iread;
|
||||||
|
|
||||||
|
/* Passing nread > INT_MAX to read is implementation defined in POSIX
|
||||||
|
* 1003.1, therefore despite the unsigned argument portable code must
|
||||||
|
* limit the value to INT_MAX!
|
||||||
|
*/
|
||||||
|
if (nbytes > INT_MAX)
|
||||||
|
nread = INT_MAX;
|
||||||
|
|
||||||
|
else
|
||||||
|
nread = (unsigned int)/*SAFE*/nbytes;
|
||||||
|
|
||||||
|
iread = read(fd, buffer, nread);
|
||||||
|
|
||||||
|
if (iread == -1)
|
||||||
|
{
|
||||||
|
/* This is the devil in the details, a read can terminate early with 0
|
||||||
|
* bytes read because of EINTR, yet it still returns -1 otherwise end
|
||||||
|
* of file cannot be distinguished.
|
||||||
|
*/
|
||||||
|
if (errno != EINTR)
|
||||||
|
{
|
||||||
|
png_warning(png_ptr, "/proc read failed");
|
||||||
|
return 0; /* I.e., a permanent failure */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (iread < 0)
|
||||||
|
{
|
||||||
|
/* Not a valid 'read' result: */
|
||||||
|
png_warning(png_ptr, "OS /proc read bug");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (iread > 0)
|
||||||
|
{
|
||||||
|
/* Continue reading until a permanent failure, or EOF */
|
||||||
|
buffer += iread;
|
||||||
|
nbytes -= (unsigned int)/*SAFE*/iread;
|
||||||
|
ntotal += (unsigned int)/*SAFE*/iread;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return ntotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ntotal; /* nbytes == 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
png_have_neon(png_structp png_ptr)
|
||||||
|
{
|
||||||
|
int fd = open("/proc/self/auxv", O_RDONLY);
|
||||||
|
Elf32_auxv_t aux;
|
||||||
|
|
||||||
|
/* Failsafe: failure to open means no NEON */
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
png_warning(png_ptr, "/proc/self/auxv open failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (safe_read(png_ptr, fd, &aux, sizeof aux) == sizeof aux)
|
||||||
|
{
|
||||||
|
if (aux.a_type == AT_HWCAP && (aux.a_un.a_val & HWCAP_NEON) != 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/* contrib/arm-neon/linux.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014, 2017 Glenn Randers-Pehrson
|
||||||
|
* Written by John Bowler, 2014, 2017.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* SEE contrib/arm-neon/README before reporting bugs
|
||||||
|
*
|
||||||
|
* STATUS: SUPPORTED
|
||||||
|
* BUG REPORTS: png-mng-implement@sourceforge.net
|
||||||
|
*
|
||||||
|
* png_have_neon implemented for Linux by reading the widely available
|
||||||
|
* pseudo-file /proc/cpuinfo.
|
||||||
|
*
|
||||||
|
* This code is strict ANSI-C and is probably moderately portable; it does
|
||||||
|
* however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
png_have_neon(png_structp png_ptr)
|
||||||
|
{
|
||||||
|
FILE *f = fopen("/proc/cpuinfo", "rb");
|
||||||
|
|
||||||
|
if (f != NULL)
|
||||||
|
{
|
||||||
|
/* This is a simple state machine which reads the input byte-by-byte until
|
||||||
|
* it gets a match on the 'neon' feature or reaches the end of the stream.
|
||||||
|
*/
|
||||||
|
static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 };
|
||||||
|
static const char ch_neon[] = { 78, 69, 79, 78 };
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine
|
||||||
|
} state;
|
||||||
|
int counter;
|
||||||
|
|
||||||
|
for (state=StartLine, counter=0;;)
|
||||||
|
{
|
||||||
|
int ch = fgetc(f);
|
||||||
|
|
||||||
|
if (ch == EOF)
|
||||||
|
{
|
||||||
|
/* EOF means error or end-of-file, return false; neon at EOF is
|
||||||
|
* assumed to be a mistake.
|
||||||
|
*/
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case StartLine:
|
||||||
|
/* Match spaces at the start of line */
|
||||||
|
if (ch <= 32) /* skip control characters and space */
|
||||||
|
break;
|
||||||
|
|
||||||
|
counter=0;
|
||||||
|
state = Feature;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case Feature:
|
||||||
|
/* Match 'FEATURE', ASCII case insensitive. */
|
||||||
|
if ((ch & ~0x20) == ch_feature[counter])
|
||||||
|
{
|
||||||
|
if (++counter == (sizeof ch_feature))
|
||||||
|
state = Colon;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* did not match 'feature' */
|
||||||
|
state = SkipLine;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case SkipLine:
|
||||||
|
skipLine:
|
||||||
|
/* Skip everything until we see linefeed or carriage return */
|
||||||
|
if (ch != 10 && ch != 13)
|
||||||
|
break;
|
||||||
|
|
||||||
|
state = StartLine;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Colon:
|
||||||
|
/* Match any number of space or tab followed by ':' */
|
||||||
|
if (ch == 32 || ch == 9)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ch == 58) /* i.e. ':' */
|
||||||
|
{
|
||||||
|
state = StartTag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Either a bad line format or a 'feature' prefix followed by
|
||||||
|
* other characters.
|
||||||
|
*/
|
||||||
|
state = SkipLine;
|
||||||
|
goto skipLine;
|
||||||
|
|
||||||
|
case StartTag:
|
||||||
|
/* Skip space characters before a tag */
|
||||||
|
if (ch == 32 || ch == 9)
|
||||||
|
break;
|
||||||
|
|
||||||
|
state = Neon;
|
||||||
|
counter = 0;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case Neon:
|
||||||
|
/* Look for 'neon' tag */
|
||||||
|
if ((ch & ~0x20) == ch_neon[counter])
|
||||||
|
{
|
||||||
|
if (++counter == (sizeof ch_neon))
|
||||||
|
state = HaveNeon;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = SkipTag;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case SkipTag:
|
||||||
|
/* Skip non-space characters */
|
||||||
|
if (ch == 10 || ch == 13)
|
||||||
|
state = StartLine;
|
||||||
|
|
||||||
|
else if (ch == 32 || ch == 9)
|
||||||
|
state = StartTag;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HaveNeon:
|
||||||
|
/* Have seen a 'neon' prefix, but there must be a space or new
|
||||||
|
* line character to terminate it.
|
||||||
|
*/
|
||||||
|
if (ch == 10 || ch == 13 || ch == 32 || ch == 9)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = SkipTag;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
png_error(png_ptr, "png_have_neon: internal error (bug)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PNG_WARNINGS_SUPPORTED
|
||||||
|
else
|
||||||
|
png_warning(png_ptr, "/proc/cpuinfo open failed");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
This directory contains test configuration files, currently always '.dfa' files
|
||||||
|
intended to be used in the build by setting the make macro DFA_XTRA to the name
|
||||||
|
of the file.
|
||||||
|
|
||||||
|
These files are used in release validation of the 'configure' builds of libpng
|
||||||
|
by building 'make check', or 'make all-am' for cross-builds, with each .dfa
|
||||||
|
file.
|
||||||
|
|
||||||
|
The files in this directory may change between minor releases, however
|
||||||
|
contributions describing specific builds of libpng are welcomed. There is no
|
||||||
|
guarantee that libpng will continue to build with such configurations; support
|
||||||
|
for given configurations can be, and has been, dropped between successive minor
|
||||||
|
releases. However if a .dfa file describing a configuration is not in this
|
||||||
|
directory it is very unlikely that it will be tested before a minor release!
|
||||||
|
|
||||||
|
You can use these .dfa files as the basis of new configurations. Files in this
|
||||||
|
directory should not have any use restrictions or restrictive licenses.
|
||||||
|
|
||||||
|
This directory is not included in the .zip and .7z distributions, which do
|
||||||
|
not contain 'configure' scripts.
|
||||||
|
|
||||||
|
DOCUMENTATION
|
||||||
|
=============
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
${srcdir}/pngusr.dfa
|
||||||
|
${srcdir}/contrib/pngminim/*/pngusr.dfa
|
||||||
|
|
||||||
|
Documentation of the options:
|
||||||
|
${srcdir}/scripts/pnglibconf.dfa
|
||||||
|
|
||||||
|
Documentation of the file format:
|
||||||
|
${srcdir}/scripts/options.awk
|
||||||
|
|
||||||
|
FILE NAMING
|
||||||
|
===========
|
||||||
|
|
||||||
|
File names in this directory may NOT contain any of the five characters:
|
||||||
|
|
||||||
|
- , + * ?
|
||||||
|
|
||||||
|
Neither may they contain any space character.
|
||||||
|
|
||||||
|
While other characters may be used it is strongly suggested that file names be
|
||||||
|
limited to lower case Latiin alphabetic characters (a-z), digits (0-9) and, if
|
||||||
|
necessary the underscore (_) character. File names should be about 8 characters
|
||||||
|
long (excluding the .dfa extension). Submitted .dfa files should have names
|
||||||
|
between 7 and 16 characters long, shorter names (6 characters or less) are
|
||||||
|
reserved for standard tests.
|
|
@ -0,0 +1,57 @@
|
||||||
|
# pngcp.dfa
|
||||||
|
# Build time configuration of libpng
|
||||||
|
#
|
||||||
|
# Author: John Bowler
|
||||||
|
# Copyright: (c) John Bowler, 2016
|
||||||
|
# Usage rights:
|
||||||
|
# To the extent possible under law, the author has waived all copyright and
|
||||||
|
# related or neighboring rights to this work. This work is published from:
|
||||||
|
# United States.
|
||||||
|
#
|
||||||
|
# Build libpng with support for pngcp. This means just png_read_png,
|
||||||
|
# png_write_png and small number of configuration settings.
|
||||||
|
#
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
# This option is specific to this configuration; it adds a #define to the
|
||||||
|
# generated pnglibconf.h which turns on the (not portable) timing option for
|
||||||
|
# pngcp. Note that any option is automatically preceded by PNG_; there is no
|
||||||
|
# way round this and this is deliberate.
|
||||||
|
option PNGCP_TIMING
|
||||||
|
|
||||||
|
# Because of the everything off above the option must also be turned on. This
|
||||||
|
# may not be done in one step because it is safer and avoids mis-spelled options
|
||||||
|
# in user .dfa files to error out if an unrecognized option is turned on.
|
||||||
|
option PNGCP_TIMING on
|
||||||
|
|
||||||
|
# Options to turn on png_read_png and png_write_png:
|
||||||
|
option INFO_IMAGE on
|
||||||
|
option SEQUENTIAL_READ on
|
||||||
|
option EASY_ACCESS on
|
||||||
|
option WRITE on
|
||||||
|
option WRITE_16BIT on
|
||||||
|
option WRITE_FILTER on
|
||||||
|
|
||||||
|
# pngcp needs this to preserve unknown chunks, switching all these on means that
|
||||||
|
# pngcp can work without explicit known chunk reading support
|
||||||
|
option UNKNOWN_CHUNKS on
|
||||||
|
option SET_UNKNOWN_CHUNKS on
|
||||||
|
option HANDLE_AS_UNKNOWN on
|
||||||
|
option SAVE_UNKNOWN_CHUNKS on
|
||||||
|
option WRITE_UNKNOWN_CHUNKS on
|
||||||
|
|
||||||
|
# pngcp needs this to handle palette files with invalid indices:
|
||||||
|
option CHECK_FOR_INVALID_INDEX on
|
||||||
|
option GET_PALETTE_MAX on
|
||||||
|
|
||||||
|
# Pre-libpng 1.7 pngcp has to stash text chunks manually, post 1.7 without this
|
||||||
|
# text chunks should be handled as unknown ok.
|
||||||
|
option TEXT on
|
||||||
|
|
||||||
|
# this is used to turn off limits:
|
||||||
|
option USER_LIMITS on
|
||||||
|
option SET_USER_LIMITS on
|
||||||
|
|
||||||
|
# these are just required for specific customizations
|
||||||
|
option WRITE_CUSTOMIZE_ZTXT_COMPRESSION on
|
||||||
|
option WRITE_CUSTOMIZE_COMPRESSION on
|
|
@ -0,0 +1,58 @@
|
||||||
|
# read.dfa
|
||||||
|
# Build time configuration of libpng
|
||||||
|
#
|
||||||
|
# Author: John Bowler
|
||||||
|
# Copyright: (c) John Bowler, 2013
|
||||||
|
# Usage rights:
|
||||||
|
# To the extent possible under law, the author has waived all copyright and
|
||||||
|
# related or neighboring rights to this work. This work is published from:
|
||||||
|
# United States.
|
||||||
|
#
|
||||||
|
# Build libpng with basic read support. This enables the lowest level libpng
|
||||||
|
# read API - the one where the calling code has to use a loop to read each row.
|
||||||
|
# At present this is the API used by most programs.
|
||||||
|
#
|
||||||
|
# Support is enabled only for those chunks and transformations that are
|
||||||
|
# typically required - others can be added easily.
|
||||||
|
#
|
||||||
|
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
# The sequential read code is enabled here; the progressive code can be used
|
||||||
|
# instead but there is no point enabling both.
|
||||||
|
|
||||||
|
option SEQUENTIAL_READ on
|
||||||
|
|
||||||
|
# Likewise it is pointless enabling both fixed and floating point APIs. Choose
|
||||||
|
# one or the other for both the API and the internal math.
|
||||||
|
|
||||||
|
#Fixed point:
|
||||||
|
#option FIXED_POINT on
|
||||||
|
#option FLOATING_ARITHMETIC off
|
||||||
|
|
||||||
|
#Floating point:
|
||||||
|
option FLOATING_POINT on
|
||||||
|
option FLOATING_ARITHMETIC on
|
||||||
|
|
||||||
|
# Basic error handling, IO and user memory support. The latter allows the
|
||||||
|
# application program to provide its own implementations of 'malloc' and 'free'.
|
||||||
|
option SETJMP on
|
||||||
|
option STDIO on
|
||||||
|
option USER_MEM on
|
||||||
|
|
||||||
|
# To read the full set of PNG images correctly interlace, transparency and
|
||||||
|
# 16-bit support is required. The application can implement interlace itself,
|
||||||
|
# but very few do and it's no longer possible to disable it when READ is
|
||||||
|
# enabled.
|
||||||
|
option READ_tRNS on
|
||||||
|
option READ_16BIT on
|
||||||
|
|
||||||
|
# Everything else is application dependent. This file assumes the app handles
|
||||||
|
# all the native PNG bit layouts, so it doesn't need any of layout change
|
||||||
|
# transforms, but needs libpng to perform gamma correction. It doesn't do any
|
||||||
|
# colorspace stuff and ignores the 'significant bit' information.
|
||||||
|
#
|
||||||
|
# If your app always expands the image to a limited set of bit layouts you
|
||||||
|
# probably want to consider using the simplified API instead of the low level
|
||||||
|
# one - see png.h and s_read.dfa.
|
||||||
|
option READ_GAMMA on
|
|
@ -0,0 +1,35 @@
|
||||||
|
# s_read.dfa
|
||||||
|
# Build time configuration of libpng
|
||||||
|
#
|
||||||
|
# Author: John Bowler
|
||||||
|
# Copyright: (c) John Bowler, 2013
|
||||||
|
# Usage rights:
|
||||||
|
# To the extent possible under law, the author has waived all copyright and
|
||||||
|
# related or neighboring rights to this work. This work is published from:
|
||||||
|
# United States.
|
||||||
|
#
|
||||||
|
# Build libpng with simplified read support (only). This builds a minimal
|
||||||
|
# libpng able to read all PNG formats and convert them into a small number of
|
||||||
|
# well understood memory formats.
|
||||||
|
#
|
||||||
|
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
option SIMPLIFIED_READ on
|
||||||
|
|
||||||
|
# It isn't necessary to chose fixed or floating point for the APIs because the
|
||||||
|
# simplified API doesn't need fixed or floating point numbers. It is necessary
|
||||||
|
# to chose an internal math implementation. The default (because of 'everything
|
||||||
|
# = off') is fixed point - turn the floating point implementation on if you have
|
||||||
|
# hardware floating point or prefer your software floating point implementation.
|
||||||
|
option FLOATING_ARITHMETIC on
|
||||||
|
|
||||||
|
# This is not strictly necessary, but without it the message strings in the API
|
||||||
|
# will not be filled in
|
||||||
|
option ERROR_TEXT on
|
||||||
|
|
||||||
|
# Switching these options on enables the 'AFIRST' and 'BGR' formats - you don't
|
||||||
|
# need this if you don't use them, they just allow the in-memory layout to be
|
||||||
|
# changed to match common hardware formats.
|
||||||
|
option SIMPLIFIED_READ_AFIRST on
|
||||||
|
option SIMPLIFIED_READ_BGR on
|
|
@ -0,0 +1,33 @@
|
||||||
|
# s_write.dfa
|
||||||
|
# Build time configuration of libpng
|
||||||
|
#
|
||||||
|
# Author: John Bowler
|
||||||
|
# Copyright: (c) John Bowler, 2013
|
||||||
|
# Usage rights:
|
||||||
|
# To the extent possible under law, the author has waived all copyright and
|
||||||
|
# related or neighboring rights to this work. This work is published from:
|
||||||
|
# United States.
|
||||||
|
#
|
||||||
|
# Build libpng with (just) simplified write support
|
||||||
|
#
|
||||||
|
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
option SIMPLIFIED_WRITE on
|
||||||
|
|
||||||
|
# It isn't necessary to chose fixed or floating point for the APIs because the
|
||||||
|
# simplified API doesn't need fixed or floating point numbers. It is necessary
|
||||||
|
# to chose an internal math implementation. The default (because of 'everything
|
||||||
|
# = off') is fixed point - turn the floating point implementation on if you have
|
||||||
|
# hardware floating point or prefer your software floating point implementation.
|
||||||
|
option FLOATING_ARITHMETIC on
|
||||||
|
|
||||||
|
# This is not strictly necessary, but without it the message strings in the API
|
||||||
|
# will not be filled in
|
||||||
|
option ERROR_TEXT on
|
||||||
|
|
||||||
|
# Switching these options on enables the 'AFIRST' and 'BGR' formats - you don't
|
||||||
|
# need this if you don't use them, they just allow the in-memory layout to be
|
||||||
|
# changed to match common hardware formats.
|
||||||
|
option SIMPLIFIED_WRITE_AFIRST on
|
||||||
|
option SIMPLIFIED_WRITE_BGR on
|
|
@ -0,0 +1,36 @@
|
||||||
|
# simple.dfa
|
||||||
|
# Build time configuration of libpng
|
||||||
|
#
|
||||||
|
# Author: John Bowler
|
||||||
|
# Copyright: (c) John Bowler, 2013
|
||||||
|
# Usage rights:
|
||||||
|
# To the extent possible under law, the author has waived all copyright and
|
||||||
|
# related or neighboring rights to this work. This work is published from:
|
||||||
|
# United States.
|
||||||
|
#
|
||||||
|
# Build libpng with just the simplified APIs (read and write).
|
||||||
|
#
|
||||||
|
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
option SIMPLIFIED_WRITE on
|
||||||
|
option SIMPLIFIED_READ on
|
||||||
|
|
||||||
|
# It isn't necessary to chose fixed or floating point for the APIs because the
|
||||||
|
# simplified API doesn't need fixed or floating point numbers. It is necessary
|
||||||
|
# to chose an internal math implementation. The default (because of 'everything
|
||||||
|
# = off') is fixed point - turn the floating point implementation on if you have
|
||||||
|
# hardware floating point or prefer your software floating point implementation.
|
||||||
|
option FLOATING_ARITHMETIC on
|
||||||
|
|
||||||
|
# This is not strictly necessary, but without it the message strings in the API
|
||||||
|
# will not be filled in
|
||||||
|
option ERROR_TEXT on
|
||||||
|
|
||||||
|
# Switching these options on enables the 'AFIRST' and 'BGR' formats - you don't
|
||||||
|
# need this if you don't use them, they just allow the in-memory layout to be
|
||||||
|
# changed to match common hardware formats.
|
||||||
|
option SIMPLIFIED_READ_AFIRST on
|
||||||
|
option SIMPLIFIED_READ_BGR on
|
||||||
|
option SIMPLIFIED_WRITE_AFIRST on
|
||||||
|
option SIMPLIFIED_WRITE_BGR on
|
|
@ -0,0 +1,45 @@
|
||||||
|
# write.dfa
|
||||||
|
# Build time configuration of libpng
|
||||||
|
#
|
||||||
|
# Author: John Bowler
|
||||||
|
# Copyright: (c) John Bowler, 2013
|
||||||
|
# Usage rights:
|
||||||
|
# To the extent possible under law, the author has waived all copyright and
|
||||||
|
# related or neighboring rights to this work. This work is published from:
|
||||||
|
# United States.
|
||||||
|
#
|
||||||
|
# Build libpng with no read support and minimal write support.
|
||||||
|
#
|
||||||
|
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
# Switch on the write code - this makes a minimalist encoder
|
||||||
|
|
||||||
|
option WRITE on
|
||||||
|
|
||||||
|
# Choose fixed or floating point APIs and arithmetic. The choices are
|
||||||
|
# independent but normally they will match. It is typically better to use the
|
||||||
|
# floating point if you have floating point hardware. If you don't know, or
|
||||||
|
# (perhaps) to make libpng smaller used fixed point throughout.
|
||||||
|
|
||||||
|
#Fixed point:
|
||||||
|
#option FIXED_POINT on
|
||||||
|
#option FLOATING_ARITHMETIC off
|
||||||
|
|
||||||
|
#Floating point:
|
||||||
|
option FLOATING_POINT on
|
||||||
|
option FLOATING_ARITHMETIC on
|
||||||
|
|
||||||
|
# Basic error handling, IO and user memory support. The latter allows the
|
||||||
|
# application program to provide its own implementations of 'malloc' and 'free'.
|
||||||
|
option SETJMP on
|
||||||
|
option STDIO on
|
||||||
|
option USER_MEM on
|
||||||
|
|
||||||
|
# Everything else is optional. Unlike the read code in libpng the write code
|
||||||
|
# does not need to deal with arbitrary formats, so only add support for things
|
||||||
|
# you really do write! For example you might only write sRGB images, sometimes
|
||||||
|
# with transparency and never write 16 bit images, so:
|
||||||
|
option WRITE_sRGB on
|
||||||
|
option WRITE_tRNS on
|
||||||
|
#option WRITE_16BIT off (this is the default with 'everything = off')
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
This directory (contrib/examples) contains examples of libpng usage.
|
||||||
|
|
||||||
|
NO COPYRIGHT RIGHTS ARE CLAIMED TO ANY OF THE FILES IN THIS DIRECTORY.
|
||||||
|
|
||||||
|
To the extent possible under law, the authors have waived all copyright and
|
||||||
|
related or neighboring rights to this work. This work is published from:
|
||||||
|
United States.
|
||||||
|
|
||||||
|
The files may be used freely in any way. The intention is that appropriate
|
||||||
|
parts of the files be used in other libpng-using programs without any need for
|
||||||
|
the authors of the using code to seek copyright or license from the original
|
||||||
|
authors.
|
||||||
|
|
||||||
|
The source code and comments in this directory are the original work of the
|
||||||
|
people named below. No other person or organization has made contributions to
|
||||||
|
the work in this directory.
|
||||||
|
|
||||||
|
ORIGINAL AUTHORS
|
||||||
|
The following people have contributed to the code in this directory. None
|
||||||
|
of the people below claim any rights with regard to the contents of this
|
||||||
|
directory.
|
||||||
|
|
||||||
|
John Bowler <jbowler at acm.org>
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*- iccfrompng
|
||||||
|
*
|
||||||
|
* COPYRIGHT: Written by John Cunningham Bowler, 2011.
|
||||||
|
* To the extent possible under law, the author has waived all copyright and
|
||||||
|
* related or neighboring rights to this work. This work is published from:
|
||||||
|
* United States.
|
||||||
|
*
|
||||||
|
* Extract any icc profiles found in the given PNG files. This is a simple
|
||||||
|
* example of a program that extracts information from the header of a PNG file
|
||||||
|
* without processing the image. Notice that some header information may occur
|
||||||
|
* after the image data. Textual data and comments are an example; the approach
|
||||||
|
* in this file won't work reliably for such data because it only looks for the
|
||||||
|
* information in the section of the file that precedes the image data.
|
||||||
|
*
|
||||||
|
* Compile and link against libpng and zlib, plus anything else required on the
|
||||||
|
* system you use.
|
||||||
|
*
|
||||||
|
* To use supply a list of PNG files containing iCCP chunks, the chunks will be
|
||||||
|
* extracted to a similarly named file with the extension replaced by 'icc',
|
||||||
|
* which will be overwritten without warning.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <png.h>
|
||||||
|
|
||||||
|
#if defined(PNG_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) && \
|
||||||
|
defined (PNG_iCCP_SUPPORTED)
|
||||||
|
|
||||||
|
|
||||||
|
static int verbose = 1;
|
||||||
|
static png_byte no_profile[] = "no profile";
|
||||||
|
|
||||||
|
static png_bytep
|
||||||
|
extract(FILE *fp, png_uint_32 *proflen)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
||||||
|
png_infop info_ptr = NULL;
|
||||||
|
png_bytep result = NULL;
|
||||||
|
|
||||||
|
/* Initialize for error or no profile: */
|
||||||
|
*proflen = 0;
|
||||||
|
|
||||||
|
if (png_ptr == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "iccfrompng: version library mismatch?\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (info_ptr == NULL)
|
||||||
|
png_error(png_ptr, "OOM allocating info structure");
|
||||||
|
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
png_charp name;
|
||||||
|
int compression_type;
|
||||||
|
png_bytep profile;
|
||||||
|
|
||||||
|
if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile,
|
||||||
|
proflen) & PNG_INFO_iCCP)
|
||||||
|
{
|
||||||
|
result = malloc(*proflen);
|
||||||
|
if (result != NULL)
|
||||||
|
memcpy(result, profile, *proflen);
|
||||||
|
|
||||||
|
else
|
||||||
|
png_error(png_ptr, "OOM allocating profile buffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
result = no_profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
extract_one_file(const char *filename)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
FILE *fp = fopen(filename, "rb");
|
||||||
|
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
png_uint_32 proflen = 0;
|
||||||
|
png_bytep profile = extract(fp, &proflen);
|
||||||
|
|
||||||
|
if (profile != NULL && profile != no_profile)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char *output;
|
||||||
|
|
||||||
|
{
|
||||||
|
const char *ep = strrchr(filename, '.');
|
||||||
|
|
||||||
|
if (ep != NULL)
|
||||||
|
len = ep-filename;
|
||||||
|
|
||||||
|
else
|
||||||
|
len = strlen(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
output = malloc(len + 5);
|
||||||
|
if (output != NULL)
|
||||||
|
{
|
||||||
|
FILE *of;
|
||||||
|
|
||||||
|
memcpy(output, filename, len);
|
||||||
|
strcpy(output+len, ".icc");
|
||||||
|
|
||||||
|
of = fopen(output, "wb");
|
||||||
|
if (of != NULL)
|
||||||
|
{
|
||||||
|
if (fwrite(profile, proflen, 1, of) == 1 &&
|
||||||
|
fflush(of) == 0 &&
|
||||||
|
fclose(of) == 0)
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
printf("%s -> %s\n", filename, output);
|
||||||
|
/* Success return */
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: error writing profile\n", output);
|
||||||
|
if (remove(output))
|
||||||
|
fprintf(stderr, "%s: could not remove file\n", output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s: failed to open output file\n", output);
|
||||||
|
|
||||||
|
free(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s: OOM allocating string!\n", filename);
|
||||||
|
|
||||||
|
free(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (verbose && profile == no_profile)
|
||||||
|
printf("%s has no profile\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s: could not open file\n", filename);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int extracted = 0;
|
||||||
|
|
||||||
|
for (i=1; i<argc; ++i)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[i], "-q") == 0)
|
||||||
|
verbose = 0;
|
||||||
|
|
||||||
|
else if (extract_one_file(argv[i]))
|
||||||
|
extracted = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exit code is true if any extract succeeds */
|
||||||
|
return extracted == 0;
|
||||||
|
}
|
||||||
|
#endif /* READ && STDIO && iCCP */
|
|
@ -0,0 +1,371 @@
|
||||||
|
/*- pngpixel
|
||||||
|
*
|
||||||
|
* COPYRIGHT: Written by John Cunningham Bowler, 2011.
|
||||||
|
* To the extent possible under law, the author has waived all copyright and
|
||||||
|
* related or neighboring rights to this work. This work is published from:
|
||||||
|
* United States.
|
||||||
|
*
|
||||||
|
* Read a single pixel value from a PNG file.
|
||||||
|
*
|
||||||
|
* This code illustrates basic 'by-row' reading of a PNG file using libpng.
|
||||||
|
* Rows are read until a particular pixel is found; the value of this pixel is
|
||||||
|
* then printed on stdout.
|
||||||
|
*
|
||||||
|
* The code illustrates how to do this on interlaced as well as non-interlaced
|
||||||
|
* images. Normally you would call png_set_interlace_handling() to have libpng
|
||||||
|
* deal with the interlace for you, but that obliges you to buffer half of the
|
||||||
|
* image to assemble the interlaced rows. In this code
|
||||||
|
* png_set_interlace_handling() is not called and, instead, the code handles the
|
||||||
|
* interlace passes directly looking for the required pixel.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <setjmp.h> /* required for error handling */
|
||||||
|
|
||||||
|
/* Normally use <png.h> here to get the installed libpng, but this is done to
|
||||||
|
* ensure the code picks up the local libpng implementation:
|
||||||
|
*/
|
||||||
|
#include "../../png.h"
|
||||||
|
|
||||||
|
#if defined(PNG_READ_SUPPORTED) && defined(PNG_SEQUENTIAL_READ_SUPPORTED)
|
||||||
|
|
||||||
|
/* Return component 'c' of pixel 'x' from the given row. */
|
||||||
|
static unsigned int
|
||||||
|
component(png_const_bytep row, png_uint_32 x, unsigned int c,
|
||||||
|
unsigned int bit_depth, unsigned int channels)
|
||||||
|
{
|
||||||
|
/* PNG images can be up to 2^31 pixels wide, but this means they can be up to
|
||||||
|
* 2^37 bits wide (for a 64-bit pixel - the largest possible) and hence 2^34
|
||||||
|
* bytes wide. Since the row fitted into memory, however, the following must
|
||||||
|
* work:
|
||||||
|
*/
|
||||||
|
png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels);
|
||||||
|
png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c);
|
||||||
|
|
||||||
|
row = (png_const_bytep)(((const png_byte (*)[8])row) + bit_offset_hi);
|
||||||
|
row += bit_offset_lo >> 3;
|
||||||
|
bit_offset_lo &= 0x07;
|
||||||
|
|
||||||
|
/* PNG pixels are packed into bytes to put the first pixel in the highest
|
||||||
|
* bits of the byte and into two bytes for 16-bit values with the high 8 bits
|
||||||
|
* first, so:
|
||||||
|
*/
|
||||||
|
switch (bit_depth)
|
||||||
|
{
|
||||||
|
case 1: return (row[0] >> (7-bit_offset_lo)) & 0x01;
|
||||||
|
case 2: return (row[0] >> (6-bit_offset_lo)) & 0x03;
|
||||||
|
case 4: return (row[0] >> (4-bit_offset_lo)) & 0x0f;
|
||||||
|
case 8: return row[0];
|
||||||
|
case 16: return (row[0] << 8) + row[1];
|
||||||
|
default:
|
||||||
|
/* This should never happen; it indicates a bug in this program or in
|
||||||
|
* libpng itself:
|
||||||
|
*/
|
||||||
|
fprintf(stderr, "pngpixel: invalid bit depth %u\n", bit_depth);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print a pixel from a row returned by libpng; determine the row format, find
|
||||||
|
* the pixel, and print the relevant information to stdout.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
|
||||||
|
png_uint_32 x)
|
||||||
|
{
|
||||||
|
unsigned int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
switch (png_get_color_type(png_ptr, info_ptr))
|
||||||
|
{
|
||||||
|
case PNG_COLOR_TYPE_GRAY:
|
||||||
|
printf("GRAY %u\n", component(row, x, 0, bit_depth, 1));
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* The palette case is slightly more difficult - the palette and, if
|
||||||
|
* present, the tRNS ('transparency', though the values are really
|
||||||
|
* opacity) data must be read to give the full picture:
|
||||||
|
*/
|
||||||
|
case PNG_COLOR_TYPE_PALETTE:
|
||||||
|
{
|
||||||
|
int index = component(row, x, 0, bit_depth, 1);
|
||||||
|
png_colorp palette = NULL;
|
||||||
|
int num_palette = 0;
|
||||||
|
|
||||||
|
if ((png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) &
|
||||||
|
PNG_INFO_PLTE) && num_palette > 0 && palette != NULL)
|
||||||
|
{
|
||||||
|
png_bytep trans_alpha = NULL;
|
||||||
|
int num_trans = 0;
|
||||||
|
if ((png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans,
|
||||||
|
NULL) & PNG_INFO_tRNS) && num_trans > 0 &&
|
||||||
|
trans_alpha != NULL)
|
||||||
|
printf("INDEXED %u = %d %d %d %d\n", index,
|
||||||
|
palette[index].red, palette[index].green,
|
||||||
|
palette[index].blue,
|
||||||
|
index < num_trans ? trans_alpha[index] : 255);
|
||||||
|
|
||||||
|
else /* no transparency */
|
||||||
|
printf("INDEXED %u = %d %d %d\n", index,
|
||||||
|
palette[index].red, palette[index].green,
|
||||||
|
palette[index].blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
printf("INDEXED %u = invalid index\n", index);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PNG_COLOR_TYPE_RGB:
|
||||||
|
printf("RGB %u %u %u\n", component(row, x, 0, bit_depth, 3),
|
||||||
|
component(row, x, 1, bit_depth, 3),
|
||||||
|
component(row, x, 2, bit_depth, 3));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||||
|
printf("GRAY+ALPHA %u %u\n", component(row, x, 0, bit_depth, 2),
|
||||||
|
component(row, x, 1, bit_depth, 2));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||||
|
printf("RGBA %u %u %u %u\n", component(row, x, 0, bit_depth, 4),
|
||||||
|
component(row, x, 1, bit_depth, 4),
|
||||||
|
component(row, x, 2, bit_depth, 4),
|
||||||
|
component(row, x, 3, bit_depth, 4));
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
png_error(png_ptr, "pngpixel: invalid color type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
/* This program uses the default, <setjmp.h> based, libpng error handling
|
||||||
|
* mechanism, therefore any local variable that exists before the call to
|
||||||
|
* setjmp and is changed after the call to setjmp returns successfully must
|
||||||
|
* be declared with 'volatile' to ensure that their values don't get
|
||||||
|
* destroyed by longjmp:
|
||||||
|
*/
|
||||||
|
volatile int result = 1/*fail*/;
|
||||||
|
|
||||||
|
if (argc == 4)
|
||||||
|
{
|
||||||
|
long x = atol(argv[1]);
|
||||||
|
long y = atol(argv[2]);
|
||||||
|
FILE *f = fopen(argv[3], "rb");
|
||||||
|
volatile png_bytep row = NULL;
|
||||||
|
|
||||||
|
if (f != NULL)
|
||||||
|
{
|
||||||
|
/* libpng requires a callback function for handling errors; this
|
||||||
|
* callback must not return. The default callback function uses a
|
||||||
|
* stored <setjmp.h> style jmp_buf which is held in a png_struct and
|
||||||
|
* writes error messages to stderr. Creating the png_struct is a
|
||||||
|
* little tricky; just copy the following code.
|
||||||
|
*/
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (png_ptr != NULL)
|
||||||
|
{
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
|
||||||
|
if (info_ptr != NULL)
|
||||||
|
{
|
||||||
|
/* Declare stack variables to hold pointers to locally allocated
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Initialize the error control buffer: */
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)) == 0)
|
||||||
|
{
|
||||||
|
png_uint_32 width, height;
|
||||||
|
int bit_depth, color_type, interlace_method,
|
||||||
|
compression_method, filter_method;
|
||||||
|
png_bytep row_tmp;
|
||||||
|
|
||||||
|
/* Now associate the recently opened (FILE*) with the default
|
||||||
|
* libpng initialization functions. Sometimes libpng is
|
||||||
|
* compiled without stdio support (it can be difficult to do
|
||||||
|
* in some environments); in that case you will have to write
|
||||||
|
* your own read callback to read data from the (FILE*).
|
||||||
|
*/
|
||||||
|
png_init_io(png_ptr, f);
|
||||||
|
|
||||||
|
/* And read the first part of the PNG file - the header and
|
||||||
|
* all the information up to the first pixel.
|
||||||
|
*/
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
/* This fills in enough information to tell us the width of
|
||||||
|
* each row in bytes, allocate the appropriate amount of
|
||||||
|
* space. In this case png_malloc is used - it will not
|
||||||
|
* return if memory isn't available.
|
||||||
|
*/
|
||||||
|
row = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
|
||||||
|
info_ptr));
|
||||||
|
|
||||||
|
/* To avoid the overhead of using a volatile auto copy row_tmp
|
||||||
|
* to a local here - just use row for the png_free below.
|
||||||
|
*/
|
||||||
|
row_tmp = row;
|
||||||
|
|
||||||
|
/* All the information we need is in the header is returned by
|
||||||
|
* png_get_IHDR, if this fails we can now use 'png_error' to
|
||||||
|
* signal the error and return control to the setjmp above.
|
||||||
|
*/
|
||||||
|
if (png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||||
|
&bit_depth, &color_type, &interlace_method,
|
||||||
|
&compression_method, &filter_method))
|
||||||
|
{
|
||||||
|
int passes, pass;
|
||||||
|
|
||||||
|
/* png_set_interlace_handling returns the number of
|
||||||
|
* passes required as well as turning on libpng's
|
||||||
|
* handling, but since we do it ourselves this is
|
||||||
|
* necessary:
|
||||||
|
*/
|
||||||
|
switch (interlace_method)
|
||||||
|
{
|
||||||
|
case PNG_INTERLACE_NONE:
|
||||||
|
passes = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PNG_INTERLACE_ADAM7:
|
||||||
|
passes = PNG_INTERLACE_ADAM7_PASSES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
png_error(png_ptr, "pngpixel: unknown interlace");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now read the pixels, pass-by-pass, row-by-row: */
|
||||||
|
png_start_read_image(png_ptr);
|
||||||
|
|
||||||
|
for (pass=0; pass<passes; ++pass)
|
||||||
|
{
|
||||||
|
png_uint_32 ystart, xstart, ystep, xstep;
|
||||||
|
png_uint_32 py;
|
||||||
|
|
||||||
|
if (interlace_method == PNG_INTERLACE_ADAM7)
|
||||||
|
{
|
||||||
|
/* Sometimes the whole pass is empty because the
|
||||||
|
* image is too narrow or too short. libpng
|
||||||
|
* expects to be called for each row that is
|
||||||
|
* present in the pass, so it may be necessary to
|
||||||
|
* skip the loop below (over py) if the image is
|
||||||
|
* too narrow.
|
||||||
|
*/
|
||||||
|
if (PNG_PASS_COLS(width, pass) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* We need the starting pixel and the offset
|
||||||
|
* between each pixel in this pass; use the macros
|
||||||
|
* in png.h:
|
||||||
|
*/
|
||||||
|
xstart = PNG_PASS_START_COL(pass);
|
||||||
|
ystart = PNG_PASS_START_ROW(pass);
|
||||||
|
xstep = PNG_PASS_COL_OFFSET(pass);
|
||||||
|
ystep = PNG_PASS_ROW_OFFSET(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ystart = xstart = 0;
|
||||||
|
ystep = xstep = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To find the pixel, loop over 'py' for each pass
|
||||||
|
* reading a row and then checking to see if it
|
||||||
|
* contains the pixel.
|
||||||
|
*/
|
||||||
|
for (py = ystart; py < height; py += ystep)
|
||||||
|
{
|
||||||
|
png_uint_32 px, ppx;
|
||||||
|
|
||||||
|
/* png_read_row takes two pointers. When libpng
|
||||||
|
* handles the interlace the first is filled in
|
||||||
|
* pixel-by-pixel, and the second receives the same
|
||||||
|
* pixels but they are replicated across the
|
||||||
|
* unwritten pixels so far for each pass. When we
|
||||||
|
* do the interlace, however, they just contain
|
||||||
|
* the pixels from the interlace pass - giving
|
||||||
|
* both is wasteful and pointless, so we pass a
|
||||||
|
* NULL pointer.
|
||||||
|
*/
|
||||||
|
png_read_row(png_ptr, row_tmp, NULL);
|
||||||
|
|
||||||
|
/* Now find the pixel if it is in this row; there
|
||||||
|
* are, of course, much better ways of doing this
|
||||||
|
* than using a for loop:
|
||||||
|
*/
|
||||||
|
if (y == py) for (px = xstart, ppx = 0;
|
||||||
|
px < width; px += xstep, ++ppx) if (x == px)
|
||||||
|
{
|
||||||
|
/* 'ppx' is the index of the pixel in the row
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
print_pixel(png_ptr, info_ptr, row_tmp, ppx);
|
||||||
|
|
||||||
|
/* Now terminate the loops early - we have
|
||||||
|
* found and handled the required data.
|
||||||
|
*/
|
||||||
|
goto pass_loop_end;
|
||||||
|
} /* x loop */
|
||||||
|
} /* y loop */
|
||||||
|
} /* pass loop */
|
||||||
|
|
||||||
|
/* Finally free the temporary buffer: */
|
||||||
|
pass_loop_end:
|
||||||
|
row = NULL;
|
||||||
|
png_free(png_ptr, row_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
png_error(png_ptr, "pngpixel: png_get_IHDR failed");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Else libpng has raised an error. An error message has
|
||||||
|
* already been output, so it is only necessary to clean up
|
||||||
|
* locally allocated data:
|
||||||
|
*/
|
||||||
|
if (row != NULL)
|
||||||
|
{
|
||||||
|
/* The default implementation of png_free never errors out
|
||||||
|
* (it just crashes if something goes wrong), but the safe
|
||||||
|
* way of using it is still to clear 'row' before calling
|
||||||
|
* png_free:
|
||||||
|
*/
|
||||||
|
png_bytep row_tmp = row;
|
||||||
|
row = NULL;
|
||||||
|
png_free(png_ptr, row_tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
png_destroy_info_struct(png_ptr, &info_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "pngpixel: out of memory allocating png_info\n");
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "pngpixel: out of memory allocating png_struct\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "pngpixel: %s: could not open file\n", argv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
/* Wrong number of arguments */
|
||||||
|
fprintf(stderr, "pngpixel: usage: pngpixel x y png-file\n");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif /* READ && SEQUENTIAL_READ */
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*- pngtopng
|
||||||
|
*
|
||||||
|
* COPYRIGHT: Written by John Cunningham Bowler, 2011, 2017.
|
||||||
|
* To the extent possible under law, the author has waived all copyright and
|
||||||
|
* related or neighboring rights to this work. This work is published from:
|
||||||
|
* United States.
|
||||||
|
*
|
||||||
|
* Read a PNG and write it out in a fixed format, using the 'simplified API'
|
||||||
|
* that was introduced in libpng-1.6.0.
|
||||||
|
*
|
||||||
|
* This sample code is just the code from the top of 'example.c' with some error
|
||||||
|
* handling added. See example.c for more comments.
|
||||||
|
*/
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Normally use <png.h> here to get the installed libpng, but this is done to
|
||||||
|
* ensure the code picks up the local libpng implementation:
|
||||||
|
*/
|
||||||
|
#include "../../png.h"
|
||||||
|
#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && \
|
||||||
|
defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
int result = 1;
|
||||||
|
|
||||||
|
if (argc == 3)
|
||||||
|
{
|
||||||
|
png_image image;
|
||||||
|
|
||||||
|
/* Only the image structure version number needs to be set. */
|
||||||
|
memset(&image, 0, sizeof image);
|
||||||
|
image.version = PNG_IMAGE_VERSION;
|
||||||
|
|
||||||
|
if (png_image_begin_read_from_file(&image, argv[1]))
|
||||||
|
{
|
||||||
|
png_bytep buffer;
|
||||||
|
|
||||||
|
/* Change this to try different formats! If you set a colormap format
|
||||||
|
* then you must also supply a colormap below.
|
||||||
|
*/
|
||||||
|
image.format = PNG_FORMAT_RGBA;
|
||||||
|
|
||||||
|
buffer = malloc(PNG_IMAGE_SIZE(image));
|
||||||
|
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
if (png_image_finish_read(&image, NULL/*background*/, buffer,
|
||||||
|
0/*row_stride*/, NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP */))
|
||||||
|
{
|
||||||
|
if (png_image_write_to_file(&image, argv[2],
|
||||||
|
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
||||||
|
NULL/*colormap*/))
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "pngtopng: write %s: %s\n", argv[2],
|
||||||
|
image.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "pngtopng: read %s: %s\n", argv[1],
|
||||||
|
image.message);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "pngtopng: out of memory: %lu bytes\n",
|
||||||
|
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||||
|
|
||||||
|
/* This is the only place where a 'free' is required; libpng does
|
||||||
|
* the cleanup on error and success, but in this case we couldn't
|
||||||
|
* complete the read because of running out of memory and so libpng
|
||||||
|
* has not got to the point where it can do cleanup.
|
||||||
|
*/
|
||||||
|
png_image_free(&image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
/* Failed to read the first argument: */
|
||||||
|
fprintf(stderr, "pngtopng: %s: %s\n", argv[1], image.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
/* Wrong number of arguments */
|
||||||
|
fprintf(stderr, "pngtopng: usage: pngtopng input-file output-file\n");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif /* READ && WRITE */
|
|
@ -0,0 +1,648 @@
|
||||||
|
/*- simpleover
|
||||||
|
*
|
||||||
|
* COPYRIGHT: Written by John Cunningham Bowler, 2015.
|
||||||
|
* To the extent possible under law, the author has waived all copyright and
|
||||||
|
* related or neighboring rights to this work. This work is published from:
|
||||||
|
* United States.
|
||||||
|
*
|
||||||
|
* Read several PNG files, which should have an alpha channel or transparency
|
||||||
|
* information, and composite them together to produce one or more 16-bit linear
|
||||||
|
* RGBA intermediates. This involves doing the correct 'over' composition to
|
||||||
|
* combine the alpha channels and corresponding data.
|
||||||
|
*
|
||||||
|
* Finally read an output (background) PNG using the 24-bit RGB format (the
|
||||||
|
* PNG will be composited on green (#00ff00) by default if it has an alpha
|
||||||
|
* channel), and apply the intermediate image generated above to specified
|
||||||
|
* locations in the image.
|
||||||
|
*
|
||||||
|
* The command line has the general format:
|
||||||
|
*
|
||||||
|
* simpleover <background.png> [output.png]
|
||||||
|
* {--sprite=width,height,name {[--at=x,y] {sprite.png}}}
|
||||||
|
* {--add=name {x,y}}
|
||||||
|
*
|
||||||
|
* The --sprite and --add options may occur multiple times. They are executed
|
||||||
|
* in order. --add may refer to any sprite already read.
|
||||||
|
*
|
||||||
|
* This code is intended to show how to composite multiple images together
|
||||||
|
* correctly. Apart from the libpng Simplified API the only work done in here
|
||||||
|
* is to combine multiple input PNG images into a single sprite; this involves
|
||||||
|
* a Porter-Duff 'over' operation and the input PNG images may, as a result,
|
||||||
|
* be regarded as being layered one on top of the other with the first (leftmost
|
||||||
|
* on the command line) being at the bottom and the last on the top.
|
||||||
|
*/
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* Normally use <png.h> here to get the installed libpng, but this is done to
|
||||||
|
* ensure the code picks up the local libpng implementation, so long as this
|
||||||
|
* file is linked against a sufficiently recent libpng (1.6+) it is ok to
|
||||||
|
* change this to <png.h>:
|
||||||
|
*/
|
||||||
|
#include "../../png.h"
|
||||||
|
|
||||||
|
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
|
||||||
|
#define sprite_name_chars 15
|
||||||
|
struct sprite {
|
||||||
|
FILE *file;
|
||||||
|
png_uint_16p buffer;
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
char name[sprite_name_chars+1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0 /* div by 65535 test program */
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
double err = 0;
|
||||||
|
unsigned int xerr = 0;
|
||||||
|
unsigned int r = 32769;
|
||||||
|
{
|
||||||
|
unsigned int x = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
unsigned int t = x + (x >> 16) /*+ (x >> 31)*/ + r;
|
||||||
|
double v = x, errtest;
|
||||||
|
|
||||||
|
if (t < x) {
|
||||||
|
fprintf(stderr, "overflow: %u+%u -> %u\n", x, r, t);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
v /= 65535;
|
||||||
|
errtest = v;
|
||||||
|
t >>= 16;
|
||||||
|
errtest -= t;
|
||||||
|
|
||||||
|
if (errtest > err) {
|
||||||
|
err = errtest;
|
||||||
|
xerr = x;
|
||||||
|
|
||||||
|
if (errtest >= .5) {
|
||||||
|
fprintf(stderr, "error: %u/65535 = %f, not %u, error %f\n",
|
||||||
|
x, v, t, errtest);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (++x <= 65535U*65535U);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("error %f @ %u\n", err, xerr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* div by 65535 test program */
|
||||||
|
|
||||||
|
static void
|
||||||
|
sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
||||||
|
png_imagep image, const png_uint_16 *buffer)
|
||||||
|
{
|
||||||
|
/* This is where the Porter-Duff 'Over' operator is evaluated; change this
|
||||||
|
* code to change the operator (this could be parameterized). Any other
|
||||||
|
* image processing operation could be used here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Check for an x or y offset that pushes any part of the image beyond the
|
||||||
|
* right or bottom of the sprite:
|
||||||
|
*/
|
||||||
|
if ((y_offset < 0 || (unsigned)/*SAFE*/y_offset < sprite->height) &&
|
||||||
|
(x_offset < 0 || (unsigned)/*SAFE*/x_offset < sprite->width))
|
||||||
|
{
|
||||||
|
unsigned int y = 0;
|
||||||
|
|
||||||
|
if (y_offset < 0)
|
||||||
|
y = -y_offset; /* Skip to first visible row */
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
unsigned int x = 0;
|
||||||
|
|
||||||
|
if (x_offset < 0)
|
||||||
|
x = -x_offset;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* In and out are RGBA values, so: */
|
||||||
|
const png_uint_16 *in_pixel = buffer + (y * image->width + x)*4;
|
||||||
|
png_uint_32 in_alpha = in_pixel[3];
|
||||||
|
|
||||||
|
/* This is the optimized Porter-Duff 'Over' operation, when the
|
||||||
|
* input alpha is 0 the output is not changed.
|
||||||
|
*/
|
||||||
|
if (in_alpha > 0)
|
||||||
|
{
|
||||||
|
png_uint_16 *out_pixel = sprite->buffer +
|
||||||
|
((y+y_offset) * sprite->width + (x+x_offset))*4;
|
||||||
|
|
||||||
|
/* This is the weight to apply to the output: */
|
||||||
|
in_alpha = 65535-in_alpha;
|
||||||
|
|
||||||
|
if (in_alpha > 0)
|
||||||
|
{
|
||||||
|
/* The input must be composed onto the output. This means
|
||||||
|
* multiplying the current output pixel value by the inverse
|
||||||
|
* of the input alpha (1-alpha). A division is required but
|
||||||
|
* it is by the constant 65535. Approximate this as:
|
||||||
|
*
|
||||||
|
* (x + (x >> 16) + 32769) >> 16;
|
||||||
|
*
|
||||||
|
* This is exact (and does not overflow) for all values of
|
||||||
|
* x in the range 0..65535*65535. (Note that the calculation
|
||||||
|
* produces the closest integer; the maximum error is <0.5).
|
||||||
|
*/
|
||||||
|
png_uint_32 tmp;
|
||||||
|
|
||||||
|
# define compose(c)\
|
||||||
|
tmp = out_pixel[c] * in_alpha;\
|
||||||
|
tmp = (tmp + (tmp >> 16) + 32769) >> 16;\
|
||||||
|
out_pixel[c] = tmp + in_pixel[c]
|
||||||
|
|
||||||
|
/* The following is very vectorizable... */
|
||||||
|
compose(0);
|
||||||
|
compose(1);
|
||||||
|
compose(2);
|
||||||
|
compose(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
out_pixel[0] = in_pixel[0],
|
||||||
|
out_pixel[1] = in_pixel[1],
|
||||||
|
out_pixel[2] = in_pixel[2],
|
||||||
|
out_pixel[3] = in_pixel[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (++x < image->width);
|
||||||
|
}
|
||||||
|
while (++y < image->height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
create_sprite(struct sprite *sprite, int *argc, const char ***argv)
|
||||||
|
{
|
||||||
|
/* Read the arguments and create this sprite. The sprite buffer has already
|
||||||
|
* been allocated. This reads the input PNGs one by one in linear format,
|
||||||
|
* composes them onto the sprite buffer (the code in the function above)
|
||||||
|
* then saves the result, converting it on the fly to PNG RGBA 8-bit format.
|
||||||
|
*/
|
||||||
|
while (*argc > 0)
|
||||||
|
{
|
||||||
|
char tombstone;
|
||||||
|
int x = 0, y = 0;
|
||||||
|
|
||||||
|
if ((*argv)[0][0] == '-' && (*argv)[0][1] == '-')
|
||||||
|
{
|
||||||
|
/* The only supported option is --at. */
|
||||||
|
if (sscanf((*argv)[0], "--at=%d,%d%c", &x, &y, &tombstone) != 2)
|
||||||
|
break; /* success; caller will parse this option */
|
||||||
|
|
||||||
|
++*argv, --*argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The argument has to be a file name */
|
||||||
|
png_image image;
|
||||||
|
|
||||||
|
image.version = PNG_IMAGE_VERSION;
|
||||||
|
image.opaque = NULL;
|
||||||
|
|
||||||
|
if (png_image_begin_read_from_file(&image, (*argv)[0]))
|
||||||
|
{
|
||||||
|
png_uint_16p buffer;
|
||||||
|
|
||||||
|
image.format = PNG_FORMAT_LINEAR_RGB_ALPHA;
|
||||||
|
|
||||||
|
buffer = malloc(PNG_IMAGE_SIZE(image));
|
||||||
|
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
if (png_image_finish_read(&image, NULL/*background*/, buffer,
|
||||||
|
0/*row_stride*/,
|
||||||
|
NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/))
|
||||||
|
{
|
||||||
|
/* This is the place where the Porter-Duff 'Over' operator
|
||||||
|
* needs to be done by this code. In fact, any image
|
||||||
|
* processing required can be done here; the data is in
|
||||||
|
* the correct format (linear, 16-bit) and source and
|
||||||
|
* destination are in memory.
|
||||||
|
*/
|
||||||
|
sprite_op(sprite, x, y, &image, buffer);
|
||||||
|
free(buffer);
|
||||||
|
++*argv, --*argc;
|
||||||
|
/* And continue to the next argument */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
fprintf(stderr, "simpleover: read %s: %s\n", (*argv)[0],
|
||||||
|
image.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: out of memory: %lu bytes\n",
|
||||||
|
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||||
|
|
||||||
|
/* png_image_free must be called if we abort the Simplified API
|
||||||
|
* read because of a problem detected in this code. If problems
|
||||||
|
* are detected in the Simplified API it cleans up itself.
|
||||||
|
*/
|
||||||
|
png_image_free(&image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Failed to read the first argument: */
|
||||||
|
fprintf(stderr, "simpleover: %s: %s\n", (*argv)[0], image.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* failure */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All the sprite operations have completed successfully. Save the RGBA
|
||||||
|
* buffer as a PNG using the simplified write API.
|
||||||
|
*/
|
||||||
|
sprite->file = tmpfile();
|
||||||
|
|
||||||
|
if (sprite->file != NULL)
|
||||||
|
{
|
||||||
|
png_image save;
|
||||||
|
|
||||||
|
memset(&save, 0, sizeof save);
|
||||||
|
save.version = PNG_IMAGE_VERSION;
|
||||||
|
save.opaque = NULL;
|
||||||
|
save.width = sprite->width;
|
||||||
|
save.height = sprite->height;
|
||||||
|
save.format = PNG_FORMAT_LINEAR_RGB_ALPHA;
|
||||||
|
save.flags = PNG_IMAGE_FLAG_FAST;
|
||||||
|
save.colormap_entries = 0;
|
||||||
|
|
||||||
|
if (png_image_write_to_stdio(&save, sprite->file, 1/*convert_to_8_bit*/,
|
||||||
|
sprite->buffer, 0/*row_stride*/, NULL/*colormap*/))
|
||||||
|
{
|
||||||
|
/* Success; the buffer is no longer needed: */
|
||||||
|
free(sprite->buffer);
|
||||||
|
sprite->buffer = NULL;
|
||||||
|
return 1; /* ok */
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "simpleover: write sprite %s: %s\n", sprite->name,
|
||||||
|
save.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "simpleover: sprite %s: could not allocate tmpfile: %s\n",
|
||||||
|
sprite->name, strerror(errno));
|
||||||
|
|
||||||
|
return 0; /* fail */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
||||||
|
int *argc, const char ***argv)
|
||||||
|
{
|
||||||
|
/* Given a --add argument naming this sprite, perform the operations listed
|
||||||
|
* in the following arguments. The arguments are expected to have the form
|
||||||
|
* (x,y), which is just an offset at which to add the sprite to the
|
||||||
|
* output.
|
||||||
|
*/
|
||||||
|
while (*argc > 0)
|
||||||
|
{
|
||||||
|
char tombstone;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
if ((*argv)[0][0] == '-' && (*argv)[0][1] == '-')
|
||||||
|
return 1; /* success */
|
||||||
|
|
||||||
|
if (sscanf((*argv)[0], "%d,%d%c", &x, &y, &tombstone) == 2)
|
||||||
|
{
|
||||||
|
/* Now add the new image into the sprite data, but only if it
|
||||||
|
* will fit.
|
||||||
|
*/
|
||||||
|
if (x < 0 || y < 0 ||
|
||||||
|
(unsigned)/*SAFE*/x >= output->width ||
|
||||||
|
(unsigned)/*SAFE*/y >= output->height ||
|
||||||
|
sprite->width > output->width-x ||
|
||||||
|
sprite->height > output->height-y)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: sprite %s @ (%d,%d) outside image\n",
|
||||||
|
sprite->name, x, y);
|
||||||
|
/* Could just skip this, but for the moment it is an error */
|
||||||
|
return 0; /* error */
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Since we know the sprite fits we can just read it into the
|
||||||
|
* output using the simplified API.
|
||||||
|
*/
|
||||||
|
png_image in;
|
||||||
|
|
||||||
|
in.version = PNG_IMAGE_VERSION;
|
||||||
|
rewind(sprite->file);
|
||||||
|
|
||||||
|
if (png_image_begin_read_from_stdio(&in, sprite->file))
|
||||||
|
{
|
||||||
|
in.format = PNG_FORMAT_RGB; /* force compose */
|
||||||
|
|
||||||
|
if (png_image_finish_read(&in, NULL/*background*/,
|
||||||
|
out_buf + (y*output->width + x)*3/*RGB*/,
|
||||||
|
output->width*3/*row_stride*/,
|
||||||
|
NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/))
|
||||||
|
{
|
||||||
|
++*argv, --*argc;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The read failed: */
|
||||||
|
fprintf(stderr, "simpleover: add sprite %s: %s\n", sprite->name,
|
||||||
|
in.message);
|
||||||
|
return 0; /* error */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: --add='%s': invalid position %s\n",
|
||||||
|
sprite->name, (*argv)[0]);
|
||||||
|
return 0; /* error */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* ok */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||||
|
const char **argv)
|
||||||
|
{
|
||||||
|
int result = 1; /* success */
|
||||||
|
# define csprites 10/*limit*/
|
||||||
|
# define str(a) #a
|
||||||
|
int nsprites = 0;
|
||||||
|
struct sprite sprites[csprites];
|
||||||
|
|
||||||
|
while (argc > 0)
|
||||||
|
{
|
||||||
|
result = 0; /* fail */
|
||||||
|
|
||||||
|
if (strncmp(argv[0], "--sprite=", 9) == 0)
|
||||||
|
{
|
||||||
|
char tombstone;
|
||||||
|
|
||||||
|
if (nsprites < csprites)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
sprites[nsprites].width = sprites[nsprites].height = 0;
|
||||||
|
sprites[nsprites].name[0] = 0;
|
||||||
|
|
||||||
|
n = sscanf(argv[0], "--sprite=%u,%u,%" str(sprite_name_chars) "s%c",
|
||||||
|
&sprites[nsprites].width, &sprites[nsprites].height,
|
||||||
|
sprites[nsprites].name, &tombstone);
|
||||||
|
|
||||||
|
if ((n == 2 || n == 3) &&
|
||||||
|
sprites[nsprites].width > 0 && sprites[nsprites].height > 0)
|
||||||
|
{
|
||||||
|
size_t buf_size, tmp;
|
||||||
|
|
||||||
|
/* Default a name if not given. */
|
||||||
|
if (sprites[nsprites].name[0] == 0)
|
||||||
|
sprintf(sprites[nsprites].name, "sprite-%d", nsprites+1);
|
||||||
|
|
||||||
|
/* Allocate a buffer for the sprite and calculate the buffer
|
||||||
|
* size:
|
||||||
|
*/
|
||||||
|
buf_size = sizeof (png_uint_16 [4]);
|
||||||
|
buf_size *= sprites[nsprites].width;
|
||||||
|
buf_size *= sprites[nsprites].height;
|
||||||
|
|
||||||
|
/* This can overflow a (size_t); check for this: */
|
||||||
|
tmp = buf_size;
|
||||||
|
tmp /= sprites[nsprites].width;
|
||||||
|
tmp /= sprites[nsprites].height;
|
||||||
|
|
||||||
|
if (tmp == sizeof (png_uint_16 [4]))
|
||||||
|
{
|
||||||
|
sprites[nsprites].buffer = malloc(buf_size);
|
||||||
|
/* This buffer must be initialized to transparent: */
|
||||||
|
memset(sprites[nsprites].buffer, 0, buf_size);
|
||||||
|
|
||||||
|
if (sprites[nsprites].buffer != NULL)
|
||||||
|
{
|
||||||
|
sprites[nsprites].file = NULL;
|
||||||
|
++argv, --argc;
|
||||||
|
|
||||||
|
if (create_sprite(sprites+nsprites++, &argc, &argv))
|
||||||
|
{
|
||||||
|
result = 1; /* still ok */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break; /* error */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overflow, or OOM */
|
||||||
|
fprintf(stderr, "simpleover: %s: sprite too large\n", argv[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: %s: invalid sprite (%u,%u)\n",
|
||||||
|
argv[0], sprites[nsprites].width, sprites[nsprites].height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: %s: too many sprites\n", argv[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strncmp(argv[0], "--add=", 6) == 0)
|
||||||
|
{
|
||||||
|
const char *name = argv[0]+6;
|
||||||
|
int isprite = nsprites;
|
||||||
|
|
||||||
|
++argv, --argc;
|
||||||
|
|
||||||
|
while (--isprite >= 0)
|
||||||
|
{
|
||||||
|
if (strcmp(sprites[isprite].name, name) == 0)
|
||||||
|
{
|
||||||
|
if (!add_sprite(output, out_buf, sprites+isprite, &argc, &argv))
|
||||||
|
goto out; /* error in add_sprite */
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isprite < 0) /* sprite not found */
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: --add='%s': sprite not found\n", name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: %s: unrecognized operation\n", argv[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 1; /* ok */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up the cache of sprites: */
|
||||||
|
out:
|
||||||
|
while (--nsprites >= 0)
|
||||||
|
{
|
||||||
|
if (sprites[nsprites].buffer != NULL)
|
||||||
|
free(sprites[nsprites].buffer);
|
||||||
|
|
||||||
|
if (sprites[nsprites].file != NULL)
|
||||||
|
(void)fclose(sprites[nsprites].file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
int result = 1; /* default to fail */
|
||||||
|
|
||||||
|
if (argc >= 2)
|
||||||
|
{
|
||||||
|
int argi = 2;
|
||||||
|
const char *output = NULL;
|
||||||
|
png_image image;
|
||||||
|
|
||||||
|
if (argc > 2 && argv[2][0] != '-'/*an operation*/)
|
||||||
|
{
|
||||||
|
output = argv[2];
|
||||||
|
argi = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
image.version = PNG_IMAGE_VERSION;
|
||||||
|
image.opaque = NULL;
|
||||||
|
|
||||||
|
if (png_image_begin_read_from_file(&image, argv[1]))
|
||||||
|
{
|
||||||
|
png_bytep buffer;
|
||||||
|
|
||||||
|
image.format = PNG_FORMAT_RGB; /* 24-bit RGB */
|
||||||
|
|
||||||
|
buffer = malloc(PNG_IMAGE_SIZE(image));
|
||||||
|
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
png_color background = {0, 0xff, 0}; /* fully saturated green */
|
||||||
|
|
||||||
|
if (png_image_finish_read(&image, &background, buffer,
|
||||||
|
0/*row_stride*/, NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP */))
|
||||||
|
{
|
||||||
|
/* At this point png_image_finish_read has cleaned up the
|
||||||
|
* allocated data in png_image, and only the buffer needs to be
|
||||||
|
* freed.
|
||||||
|
*
|
||||||
|
* Perform the remaining operations:
|
||||||
|
*/
|
||||||
|
if (simpleover_process(&image, buffer, argc-argi, argv+argi))
|
||||||
|
{
|
||||||
|
/* Write the output: */
|
||||||
|
if ((output != NULL &&
|
||||||
|
png_image_write_to_file(&image, output,
|
||||||
|
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
||||||
|
NULL/*colormap*/)) ||
|
||||||
|
(output == NULL &&
|
||||||
|
png_image_write_to_stdio(&image, stdout,
|
||||||
|
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
||||||
|
NULL/*colormap*/)))
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "simpleover: write %s: %s\n",
|
||||||
|
output == NULL ? "stdout" : output, image.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* else simpleover_process writes an error message */
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "simpleover: read %s: %s\n", argv[1],
|
||||||
|
image.message);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "simpleover: out of memory: %lu bytes\n",
|
||||||
|
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||||
|
|
||||||
|
/* This is the only place where a 'free' is required; libpng does
|
||||||
|
* the cleanup on error and success, but in this case we couldn't
|
||||||
|
* complete the read because of running out of memory.
|
||||||
|
*/
|
||||||
|
png_image_free(&image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Failed to read the first argument: */
|
||||||
|
fprintf(stderr, "simpleover: %s: %s\n", argv[1], image.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Usage message */
|
||||||
|
fprintf(stderr,
|
||||||
|
"simpleover: usage: simpleover background.png [output.png]\n"
|
||||||
|
" Output 'background.png' as a 24-bit RGB PNG file in 'output.png'\n"
|
||||||
|
" or, if not given, stdout. 'background.png' will be composited\n"
|
||||||
|
" on fully saturated green.\n"
|
||||||
|
"\n"
|
||||||
|
" Optionally, before output, process additional PNG files:\n"
|
||||||
|
"\n"
|
||||||
|
" --sprite=width,height,name {[--at=x,y] {sprite.png}}\n"
|
||||||
|
" Produce a transparent sprite of size (width,height) and with\n"
|
||||||
|
" name 'name'.\n"
|
||||||
|
" For each sprite.png composite it using a Porter-Duff 'Over'\n"
|
||||||
|
" operation at offset (x,y) in the sprite (defaulting to (0,0)).\n"
|
||||||
|
" Input PNGs will be truncated to the area of the sprite.\n"
|
||||||
|
"\n"
|
||||||
|
" --add='name' {x,y}\n"
|
||||||
|
" Optionally, before output, composite a sprite, 'name', which\n"
|
||||||
|
" must have been previously produced using --sprite, at each\n"
|
||||||
|
" offset (x,y) in the output image. Each sprite must fit\n"
|
||||||
|
" completely within the output image.\n"
|
||||||
|
"\n"
|
||||||
|
" PNG files are processed in the order they occur on the command\n"
|
||||||
|
" line and thus the first PNG processed appears as the bottommost\n"
|
||||||
|
" in the output image.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif /* SIMPLIFIED_READ */
|
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
|
@ -0,0 +1,50 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
|
@ -0,0 +1,131 @@
|
||||||
|
# Sample makefile for rpng-win / rpng2-win / wpng using mingw32-gcc and make.
|
||||||
|
# Greg Roelofs
|
||||||
|
# Last modified: 2 June 2007
|
||||||
|
#
|
||||||
|
# The programs built by this makefile are described in the book,
|
||||||
|
# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
|
||||||
|
# Associates, 1999). Go buy a copy, eh? Well, OK, it's not
|
||||||
|
# generally for sale anymore, but it's the thought that counts,
|
||||||
|
# right? (Hint: http://www.libpng.org/pub/png/book/ )
|
||||||
|
#
|
||||||
|
# Invoke this makefile from a DOS-prompt window via:
|
||||||
|
#
|
||||||
|
# make -f Makefile.mingw32
|
||||||
|
#
|
||||||
|
# This makefile assumes libpng and zlib have already been built or downloaded
|
||||||
|
# and are in subdirectories at the same level as the current subdirectory
|
||||||
|
# (as indicated by the PNGDIR and ZDIR macros below). It makes no assumptions
|
||||||
|
# at all about the mingw32 installation tree (W32DIR). Edit as appropriate.
|
||||||
|
#
|
||||||
|
# Note that the names of the dynamic and static libpng and zlib libraries
|
||||||
|
# used below may change in later releases of the libraries. This makefile
|
||||||
|
# builds both statically and dynamically linked executables by default.
|
||||||
|
# (You need only one set, but for testing it can be handy to have both.)
|
||||||
|
|
||||||
|
|
||||||
|
# macros --------------------------------------------------------------------
|
||||||
|
|
||||||
|
#PNGDIR = ../..# for libpng-x.y.z/contrib/gregbook builds
|
||||||
|
PNGDIR = ../libpng-win32
|
||||||
|
PNGINC = -I$(PNGDIR)
|
||||||
|
PNGLIBd = $(PNGDIR)/libpng.dll.a # dynamically linked
|
||||||
|
PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng
|
||||||
|
|
||||||
|
#ZDIR = ../../../zlib-win32# for libpng-x.y.z/contrib/gregbook builds
|
||||||
|
ZDIR = ../zlib-win32
|
||||||
|
ZINC = -I$(ZDIR)
|
||||||
|
ZLIBd = $(ZDIR)/libzdll.a
|
||||||
|
ZLIBs = $(ZDIR)/libz.a
|
||||||
|
|
||||||
|
# change this to be the path where mingw32 installs its stuff:
|
||||||
|
W32DIR =
|
||||||
|
#W32DIR = /usr/local/cross-tools/i386-mingw32msvc
|
||||||
|
W32INC = -I$(W32DIR)/include
|
||||||
|
W32LIB = $(W32DIR)/lib/libuser32.a $(W32DIR)/lib/libgdi32.a
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
#CC = i386-mingw32msvc-gcc # e.g., Linux -> Win32 cross-compilation
|
||||||
|
LD = $(CC)
|
||||||
|
RM = rm -f
|
||||||
|
CPPFLAGS = $(INCS)
|
||||||
|
CFLAGS = -O -Wall $(MINGW_CCFLAGS)
|
||||||
|
# [note that -Wall is a gcc-specific compilation flag ("most warnings on")]
|
||||||
|
# [-ansi, -pedantic and -W can also be used]
|
||||||
|
LDFLAGS = $(MINGW_LDFLAGS)
|
||||||
|
O = .o
|
||||||
|
E = .exe
|
||||||
|
|
||||||
|
INCS = $(PNGINC) $(ZINC) $(W32INC)
|
||||||
|
RLIBSd = $(PNGLIBd) $(ZLIBd) $(W32LIB) -lm
|
||||||
|
RLIBSs = $(PNGLIBs) $(ZLIBs) $(W32LIB) -lm
|
||||||
|
WLIBSd = $(PNGLIBd) $(ZLIBd)
|
||||||
|
WLIBSs = $(PNGLIBs) $(ZLIBs)
|
||||||
|
|
||||||
|
RPNG = rpng-win
|
||||||
|
RPNG2 = rpng2-win
|
||||||
|
WPNG = wpng
|
||||||
|
|
||||||
|
ROBJSd = $(RPNG)$(O) readpng.pic$(O)
|
||||||
|
ROBJS2d = $(RPNG2)$(O) readpng2.pic$(O)
|
||||||
|
WOBJSd = $(WPNG)$(O) writepng.pic$(O)
|
||||||
|
|
||||||
|
RPNGs = $(RPNG)-static
|
||||||
|
RPNG2s = $(RPNG2)-static
|
||||||
|
WPNGs = $(WPNG)-static
|
||||||
|
|
||||||
|
ROBJSs = $(RPNG)$(O) readpng$(O)
|
||||||
|
ROBJS2s = $(RPNG2)$(O) readpng2$(O)
|
||||||
|
WOBJSs = $(WPNG)$(O) writepng$(O)
|
||||||
|
|
||||||
|
STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E)
|
||||||
|
DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
|
||||||
|
|
||||||
|
EXES = $(STATIC_EXES) $(DYNAMIC_EXES)
|
||||||
|
|
||||||
|
|
||||||
|
# implicit make rules -------------------------------------------------------
|
||||||
|
|
||||||
|
.c$(O):
|
||||||
|
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
|
||||||
|
|
||||||
|
%.pic$(O): %.c
|
||||||
|
$(CC) -c $(CPPFLAGS) $(CFLAGS) -DPNG_BUILD_DLL -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
# dependencies --------------------------------------------------------------
|
||||||
|
|
||||||
|
all: $(EXES)
|
||||||
|
|
||||||
|
$(RPNGs)$(E): $(ROBJSs)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJSs) $(RLIBSs)
|
||||||
|
|
||||||
|
$(RPNG)$(E): $(ROBJSd)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJSd) $(RLIBSd)
|
||||||
|
|
||||||
|
$(RPNG2s)$(E): $(ROBJS2s)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS2s) $(RLIBSs)
|
||||||
|
|
||||||
|
$(RPNG2)$(E): $(ROBJS2d)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS2d) $(RLIBSd)
|
||||||
|
|
||||||
|
$(WPNGs)$(E): $(WOBJSs)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(WOBJSs) $(WLIBSs)
|
||||||
|
|
||||||
|
$(WPNG)$(E): $(WOBJSd)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(WOBJSd) $(WLIBSd)
|
||||||
|
|
||||||
|
$(RPNG)$(O): $(RPNG).c readpng.h
|
||||||
|
$(RPNG2)$(O): $(RPNG2).c readpng2.h
|
||||||
|
$(WPNG)$(O): $(WPNG).c writepng.h
|
||||||
|
|
||||||
|
readpng$(O) readpng.pic$(O): readpng.c readpng.h
|
||||||
|
readpng2$(O) readpng2.pic$(O): readpng2.c readpng2.h
|
||||||
|
writepng$(O) writepng.pic$(O): writepng.c writepng.h
|
||||||
|
|
||||||
|
|
||||||
|
# maintenance ---------------------------------------------------------------
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(EXES)
|
||||||
|
$(RM) $(ROBJSs) $(ROBJS2s) $(WOBJSs)
|
||||||
|
$(RM) $(ROBJSd) $(ROBJS2d) $(WOBJSd)
|
|
@ -0,0 +1,105 @@
|
||||||
|
# Sample makefile for rpng-x / rpng2-x / wpng for SGI using cc and make.
|
||||||
|
# Greg Roelofs
|
||||||
|
# Last modified: 7 March 2002
|
||||||
|
#
|
||||||
|
# The programs built by this makefile are described in the book,
|
||||||
|
# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
|
||||||
|
# Associates, 1999). Go buy a copy, eh? Buy some for friends
|
||||||
|
# and family, too. (Not that this is a blatant plug or anything.)
|
||||||
|
#
|
||||||
|
# Invoke this makefile from a shell prompt in the usual way; for example:
|
||||||
|
#
|
||||||
|
# make -f Makefile.sgi
|
||||||
|
#
|
||||||
|
# This makefile assumes libpng and zlib have already been built or downloaded
|
||||||
|
# and are both installed in /usr/local/{include,lib} (as indicated by the
|
||||||
|
# PNG* and Z* macros below). Edit as appropriate--choose only ONE each of
|
||||||
|
# the PNGINC, PNGLIB, ZINC and ZLIB lines.
|
||||||
|
#
|
||||||
|
# This makefile builds dynamically linked executables (against libpng and zlib,
|
||||||
|
# that is), but that can be changed by uncommenting the appropriate PNGLIB and
|
||||||
|
# ZLIB lines.
|
||||||
|
|
||||||
|
|
||||||
|
# macros --------------------------------------------------------------------
|
||||||
|
|
||||||
|
PNGINC = -I/usr/local/include/libpng16
|
||||||
|
PNGLIB = -L/usr/local/lib -lpng16 # dynamically linked against libpng
|
||||||
|
#PNGLIB = /usr/local/lib/libpng16.a # statically linked against libpng
|
||||||
|
# or:
|
||||||
|
#PNGINC = -I../..
|
||||||
|
#PNGLIB = -L../.. -lpng
|
||||||
|
#PNGLIB = ../../libpng.a
|
||||||
|
|
||||||
|
ZINC = -I/usr/local/include
|
||||||
|
ZLIB = -L/usr/local/lib -lz # dynamically linked against zlib
|
||||||
|
#ZLIB = /usr/local/lib/libz.a # statically linked against zlib
|
||||||
|
#ZINC = -I../zlib
|
||||||
|
#ZLIB = -L../zlib -lz
|
||||||
|
#ZLIB = ../../../zlib/libz.a
|
||||||
|
|
||||||
|
XINC = -I/usr/include/X11 # old-style, stock X distributions
|
||||||
|
XLIB = -L/usr/lib/X11 -lX11
|
||||||
|
#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows)
|
||||||
|
#XLIB = -L/usr/openwin/lib -lX11
|
||||||
|
#XINC = -I/usr/X11R6/include # new X distributions (XFree86, etc.)
|
||||||
|
#XLIB = -L/usr/X11R6/lib -lX11
|
||||||
|
|
||||||
|
INCS = $(PNGINC) $(ZINC) $(XINC)
|
||||||
|
RLIBS = $(PNGLIB) $(ZLIB) $(XLIB) -lm
|
||||||
|
WLIBS = $(PNGLIB) $(ZLIB)
|
||||||
|
|
||||||
|
CC = cc
|
||||||
|
LD = cc
|
||||||
|
RM = rm -f
|
||||||
|
# ABI must be the same as that used to build libpng.
|
||||||
|
ABI =
|
||||||
|
CPPFLAGS =
|
||||||
|
CFLAGS = $(ABI) -O -fullwarn $(INCS)
|
||||||
|
LDFLAGS = $(ABI)
|
||||||
|
O = .o
|
||||||
|
E =
|
||||||
|
|
||||||
|
RPNG = rpng-x
|
||||||
|
RPNG2 = rpng2-x
|
||||||
|
WPNG = wpng
|
||||||
|
|
||||||
|
ROBJS = $(RPNG)$(O) readpng$(O)
|
||||||
|
ROBJS2 = $(RPNG2)$(O) readpng2$(O)
|
||||||
|
WOBJS = $(WPNG)$(O) writepng$(O)
|
||||||
|
|
||||||
|
EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
|
||||||
|
|
||||||
|
|
||||||
|
# implicit make rules -------------------------------------------------------
|
||||||
|
|
||||||
|
.c$(O):
|
||||||
|
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
|
# dependencies --------------------------------------------------------------
|
||||||
|
|
||||||
|
all: $(EXES)
|
||||||
|
|
||||||
|
$(RPNG)$(E): $(ROBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBS)
|
||||||
|
|
||||||
|
$(RPNG2)$(E): $(ROBJS2)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBS)
|
||||||
|
|
||||||
|
$(WPNG)$(E): $(WOBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBS)
|
||||||
|
|
||||||
|
$(RPNG)$(O): $(RPNG).c readpng.h
|
||||||
|
$(RPNG2)$(O): $(RPNG2).c readpng2.h
|
||||||
|
$(WPNG)$(O): $(WPNG).c writepng.h
|
||||||
|
|
||||||
|
readpng$(O): readpng.c readpng.h
|
||||||
|
readpng2$(O): readpng2.c readpng2.h
|
||||||
|
writepng$(O): writepng.c writepng.h
|
||||||
|
|
||||||
|
|
||||||
|
# maintenance ---------------------------------------------------------------
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)
|
|
@ -0,0 +1,134 @@
|
||||||
|
# Sample makefile for rpng-x / rpng2-x / wpng using gcc and make.
|
||||||
|
# Greg Roelofs
|
||||||
|
# Last modified: 2 June 2007
|
||||||
|
#
|
||||||
|
# The programs built by this makefile are described in the book,
|
||||||
|
# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
|
||||||
|
# Associates, 1999). Go buy a copy, eh? Well, OK, it's not
|
||||||
|
# generally for sale anymore, but it's the thought that counts,
|
||||||
|
# right? (Hint: http://www.libpng.org/pub/png/book/ )
|
||||||
|
#
|
||||||
|
# Invoke this makefile from a shell prompt in the usual way; for example:
|
||||||
|
#
|
||||||
|
# make -f Makefile.unx
|
||||||
|
#
|
||||||
|
# This makefile assumes libpng and zlib have already been built or downloaded
|
||||||
|
# and are installed in /usr/local/{include,lib} or as otherwise indicated by
|
||||||
|
# the PNG* and Z* macros below. Edit as appropriate--choose only ONE each of
|
||||||
|
# the PNGINC, PNGLIBd, PNGLIBs, ZINC, ZLIBd and ZLIBs lines.
|
||||||
|
#
|
||||||
|
# This makefile builds both dynamically and statically linked executables
|
||||||
|
# (against libpng and zlib, that is), but that can be changed by modifying
|
||||||
|
# the "EXES =" line. (You need only one set, but for testing it can be handy
|
||||||
|
# to have both.)
|
||||||
|
|
||||||
|
|
||||||
|
# macros --------------------------------------------------------------------
|
||||||
|
|
||||||
|
#PNGDIR = /usr/local/lib
|
||||||
|
#PNGINC = -I/usr/local/include/libpng16
|
||||||
|
#PNGLIBd = -L$(PNGDIR) -lpng16 # dynamically linked, installed libpng
|
||||||
|
#PNGLIBs = $(PNGDIR)/libpng16.a # statically linked, installed libpng
|
||||||
|
# or:
|
||||||
|
PNGDIR = ../..# this one is for libpng-x.y.z/contrib/gregbook builds
|
||||||
|
#PNGDIR = ../libpng
|
||||||
|
PNGINC = -I$(PNGDIR)
|
||||||
|
PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng16 # dynamically linked
|
||||||
|
PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng
|
||||||
|
|
||||||
|
ZDIR = /usr/local/lib
|
||||||
|
#ZDIR = /usr/lib64
|
||||||
|
ZINC = -I/usr/local/include
|
||||||
|
ZLIBd = -L$(ZDIR) -lz # dynamically linked against zlib
|
||||||
|
ZLIBs = $(ZDIR)/libz.a # statically linked against zlib
|
||||||
|
# or:
|
||||||
|
#ZDIR = ../zlib
|
||||||
|
#ZINC = -I$(ZDIR)
|
||||||
|
#ZLIBd = -Wl,-rpath,$(ZDIR) -L$(ZDIR) -lz # -rpath allows in-place testing
|
||||||
|
#ZLIBs = $(ZDIR)/libz.a
|
||||||
|
|
||||||
|
#XINC = -I/usr/include # old-style, stock X distributions
|
||||||
|
#XLIB = -L/usr/lib/X11 -lX11 # (including SGI IRIX)
|
||||||
|
#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows)
|
||||||
|
#XLIB = -L/usr/openwin/lib -lX11
|
||||||
|
XINC = -I/usr/X11R6/include # new X distributions (X.org, etc.)
|
||||||
|
XLIB = -L/usr/X11R6/lib -lX11
|
||||||
|
#XLIB = -L/usr/X11R6/lib64 -lX11 # e.g., Red Hat on AMD64
|
||||||
|
|
||||||
|
INCS = $(PNGINC) $(ZINC) $(XINC)
|
||||||
|
RLIBSd = $(PNGLIBd) $(ZLIBd) $(XLIB) -lm
|
||||||
|
RLIBSs = $(PNGLIBs) $(ZLIBs) $(XLIB) -lm
|
||||||
|
WLIBSd = $(PNGLIBd) $(ZLIBd) -lm
|
||||||
|
WLIBSs = $(PNGLIBs) $(ZLIBs) -lm
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
LD = gcc
|
||||||
|
RM = rm -f
|
||||||
|
CPPFLAGS = $(INCS) -DFEATURE_LOOP
|
||||||
|
CFLAGS = -O -Wall
|
||||||
|
#CFLAGS = -O -W -Wall -Wextra -pedantic -ansi
|
||||||
|
# [note that -Wall is a gcc-specific compilation flag ("most warnings on")]
|
||||||
|
# [-ansi, -pedantic, -Wextra, and -W can also be used]
|
||||||
|
LDFLAGS =
|
||||||
|
O = .o
|
||||||
|
E =
|
||||||
|
|
||||||
|
RPNG = rpng-x
|
||||||
|
RPNG2 = rpng2-x
|
||||||
|
WPNG = wpng
|
||||||
|
|
||||||
|
RPNGs = $(RPNG)-static
|
||||||
|
RPNG2s = $(RPNG2)-static
|
||||||
|
WPNGs = $(WPNG)-static
|
||||||
|
|
||||||
|
ROBJS = $(RPNG)$(O) readpng$(O)
|
||||||
|
ROBJS2 = $(RPNG2)$(O) readpng2$(O)
|
||||||
|
WOBJS = $(WPNG)$(O) writepng$(O)
|
||||||
|
|
||||||
|
STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E)
|
||||||
|
DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
|
||||||
|
|
||||||
|
EXES = $(STATIC_EXES) $(DYNAMIC_EXES)
|
||||||
|
|
||||||
|
|
||||||
|
# implicit make rules -------------------------------------------------------
|
||||||
|
|
||||||
|
.c$(O):
|
||||||
|
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
|
# dependencies --------------------------------------------------------------
|
||||||
|
|
||||||
|
all: $(EXES)
|
||||||
|
|
||||||
|
$(RPNGs)$(E): $(ROBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSs)
|
||||||
|
|
||||||
|
$(RPNG)$(E): $(ROBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSd)
|
||||||
|
|
||||||
|
$(RPNG2s)$(E): $(ROBJS2)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSs)
|
||||||
|
|
||||||
|
$(RPNG2)$(E): $(ROBJS2)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSd)
|
||||||
|
|
||||||
|
$(WPNGs)$(E): $(WOBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSs)
|
||||||
|
|
||||||
|
$(WPNG)$(E): $(WOBJS)
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSd)
|
||||||
|
|
||||||
|
$(RPNG)$(O): $(RPNG).c readpng.h
|
||||||
|
$(RPNG2)$(O): $(RPNG2).c readpng2.h
|
||||||
|
$(WPNG)$(O): $(WPNG).c writepng.h
|
||||||
|
|
||||||
|
readpng$(O): readpng.c readpng.h
|
||||||
|
readpng2$(O): readpng2.c readpng2.h
|
||||||
|
writepng$(O): writepng.c writepng.h
|
||||||
|
|
||||||
|
|
||||||
|
# maintenance ---------------------------------------------------------------
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)
|
|
@ -0,0 +1,114 @@
|
||||||
|
# Sample makefile for rpng-win / rpng2-win / wpng using MSVC and NMAKE.
|
||||||
|
# Greg Roelofs
|
||||||
|
# Last modified: 2 June 2007
|
||||||
|
#
|
||||||
|
# The programs built by this makefile are described in the book,
|
||||||
|
# "PNG: The Definitive Guide," by Greg Roelofs (O'Reilly and
|
||||||
|
# Associates, 1999). Go buy a copy, eh? Well, OK, it's not
|
||||||
|
# generally for sale anymore, but it's the thought that counts,
|
||||||
|
# right? (Hint: http://www.libpng.org/pub/png/book/ )
|
||||||
|
#
|
||||||
|
# Invoke this makefile from a DOS prompt window via:
|
||||||
|
#
|
||||||
|
# %devstudio%\vc\bin\vcvars32.bat
|
||||||
|
# nmake -nologo -f Makefile.w32
|
||||||
|
#
|
||||||
|
# where %devstudio% is the installation directory for MSVC / DevStudio. If
|
||||||
|
# you get "environment out of space" errors, create a desktop shortcut with
|
||||||
|
# "c:\windows\command.com /e:4096" as the program command line and set the
|
||||||
|
# working directory to this directory. Then double-click to open the new
|
||||||
|
# DOS-prompt window with a bigger environment and retry the commands above.
|
||||||
|
#
|
||||||
|
# This makefile assumes libpng and zlib have already been built or downloaded
|
||||||
|
# and are in subdirectories at the same level as the current subdirectory
|
||||||
|
# (as indicated by the PNGPATH and ZPATH macros below). Edit as appropriate.
|
||||||
|
#
|
||||||
|
# Note that the names of the dynamic and static libpng and zlib libraries
|
||||||
|
# used below may change in later releases of the libraries. This makefile
|
||||||
|
# builds statically linked executables, but that can be changed by uncom-
|
||||||
|
# menting the appropriate PNGLIB and ZLIB lines.
|
||||||
|
|
||||||
|
!include <ntwin32.mak>
|
||||||
|
|
||||||
|
|
||||||
|
# macros --------------------------------------------------------------------
|
||||||
|
|
||||||
|
PNGPATH = ../libpng
|
||||||
|
PNGINC = -I$(PNGPATH)
|
||||||
|
#PNGLIB = $(PNGPATH)/pngdll.lib
|
||||||
|
PNGLIB = $(PNGPATH)/libpng.lib
|
||||||
|
|
||||||
|
ZPATH = ../zlib
|
||||||
|
ZINC = -I$(ZPATH)
|
||||||
|
#ZLIB = $(ZPATH)/zlibdll.lib
|
||||||
|
ZLIB = $(ZPATH)/zlibstat.lib
|
||||||
|
|
||||||
|
WINLIBS = -defaultlib:user32.lib gdi32.lib
|
||||||
|
# ["real" apps may also need comctl32.lib, comdlg32.lib, winmm.lib, etc.]
|
||||||
|
|
||||||
|
INCS = $(PNGINC) $(ZINC)
|
||||||
|
RLIBS = $(PNGLIB) $(ZLIB) $(WINLIBS)
|
||||||
|
WLIBS = $(PNGLIB) $(ZLIB)
|
||||||
|
|
||||||
|
CC = cl
|
||||||
|
LD = link
|
||||||
|
RM = del
|
||||||
|
CPPFLAGS = $(INCS)
|
||||||
|
CFLAGS = -nologo -O -W3 $(cvars)
|
||||||
|
# [note that -W3 is an MSVC-specific compilation flag ("all warnings on")]
|
||||||
|
# [see %devstudio%\vc\include\win32.mak for cvars macro definition]
|
||||||
|
O = .obj
|
||||||
|
E = .exe
|
||||||
|
|
||||||
|
RLDFLAGS = -nologo -subsystem:windows
|
||||||
|
WLDFLAGS = -nologo
|
||||||
|
|
||||||
|
RPNG = rpng-win
|
||||||
|
RPNG2 = rpng2-win
|
||||||
|
WPNG = wpng
|
||||||
|
|
||||||
|
ROBJS = $(RPNG)$(O) readpng$(O)
|
||||||
|
ROBJS2 = $(RPNG2)$(O) readpng2$(O)
|
||||||
|
WOBJS = $(WPNG)$(O) writepng$(O)
|
||||||
|
|
||||||
|
EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
|
||||||
|
|
||||||
|
|
||||||
|
# implicit make rules -------------------------------------------------------
|
||||||
|
|
||||||
|
.c$(O):
|
||||||
|
$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
|
# dependencies --------------------------------------------------------------
|
||||||
|
|
||||||
|
all: $(EXES)
|
||||||
|
|
||||||
|
$(RPNG)$(E): $(ROBJS)
|
||||||
|
$(LD) $(RLDFLAGS) -out:$@ $(ROBJS) $(RLIBS)
|
||||||
|
|
||||||
|
$(RPNG2)$(E): $(ROBJS2)
|
||||||
|
$(LD) $(RLDFLAGS) -out:$@ $(ROBJS2) $(RLIBS)
|
||||||
|
|
||||||
|
$(WPNG)$(E): $(WOBJS)
|
||||||
|
$(LD) $(WLDFLAGS) -out:$@ $(WOBJS) $(WLIBS)
|
||||||
|
|
||||||
|
$(RPNG)$(O): $(RPNG).c readpng.h
|
||||||
|
$(RPNG2)$(O): $(RPNG2).c readpng2.h
|
||||||
|
$(WPNG)$(O): $(WPNG).c writepng.h
|
||||||
|
|
||||||
|
readpng$(O): readpng.c readpng.h
|
||||||
|
readpng2$(O): readpng2.c readpng2.h
|
||||||
|
writepng$(O): writepng.c writepng.h
|
||||||
|
|
||||||
|
|
||||||
|
# maintenance ---------------------------------------------------------------
|
||||||
|
|
||||||
|
clean:
|
||||||
|
# ideally we could just do this:
|
||||||
|
# $(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)
|
||||||
|
# ...but the Windows "DEL" command is none too bright, so:
|
||||||
|
$(RM) r*$(E)
|
||||||
|
$(RM) w*$(E)
|
||||||
|
$(RM) r*$(O)
|
||||||
|
$(RM) w*$(O)
|
|
@ -0,0 +1,186 @@
|
||||||
|
===========================
|
||||||
|
PNG: The Definitive Guide
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Source Code
|
||||||
|
|
||||||
|
Chapters 13, 14 and 15 of "PNG: The Definitive Guide" discuss three free,
|
||||||
|
cross-platform demo programs that show how to use the libpng reference
|
||||||
|
library: rpng, rpng2 and wpng. rpng and rpng2 are viewers; the first is
|
||||||
|
a very simple example that that shows how a standard file-viewer might use
|
||||||
|
libpng, while the second is designed to process streaming data and shows
|
||||||
|
how a web browser might be written. wpng is a simple command-line program
|
||||||
|
that reads binary PGM and PPM files (the ``raw'' grayscale and RGB subsets
|
||||||
|
of PBMPLUS/NetPBM) and converts them to PNG.
|
||||||
|
|
||||||
|
The source code for all three demo programs currently compiles under
|
||||||
|
Unix, OpenVMS, and 32-bit Windows. (Special thanks to Martin Zinser,
|
||||||
|
zinser at decus.de, for making the necessary changes for OpenVMS and for
|
||||||
|
providing an appropriate build script.) Build instructions can be found
|
||||||
|
below.
|
||||||
|
|
||||||
|
Files:
|
||||||
|
|
||||||
|
README this file
|
||||||
|
LICENSE terms of distribution and reuse (BSD-like or GNU GPL)
|
||||||
|
COPYING GNU General Public License (GPL)
|
||||||
|
|
||||||
|
Makefile.unx Unix makefile
|
||||||
|
Makefile.w32 Windows (MSVC) makefile
|
||||||
|
makevms.com OpenVMS build script
|
||||||
|
|
||||||
|
rpng-win.c Windows front end for the basic viewer
|
||||||
|
rpng-x.c X Window System (Unix, OpenVMS) front end
|
||||||
|
readpng.c generic back end for the basic viewer
|
||||||
|
readpng.h header file for the basic viewer
|
||||||
|
|
||||||
|
rpng2-win.c Windows front end for the progressive viewer
|
||||||
|
rpng2-x.c X front end for the progressive viewer
|
||||||
|
readpng2.c generic back end for the progressive viewer
|
||||||
|
readpng2.h header file for the progressive viewer
|
||||||
|
|
||||||
|
wpng.c generic (text) front end for the converter
|
||||||
|
writepng.c generic back end for the converter
|
||||||
|
writepng.h header file for the converter
|
||||||
|
|
||||||
|
toucan.png transparent PNG for testing (by Stefan Schneider)
|
||||||
|
|
||||||
|
Note that, although the programs are designed to be functional, their
|
||||||
|
primary purpose is to illustrate how to use libpng to add PNG support to
|
||||||
|
other programs. As such, their user interfaces are crude and definitely
|
||||||
|
are not intended for everyday use.
|
||||||
|
|
||||||
|
Please see http://www.libpng.org/pub/png/pngbook.html for further infor-
|
||||||
|
mation and links to the latest version of the source code, and Chapters
|
||||||
|
13-15 of the book for detailed discussion of the three programs.
|
||||||
|
|
||||||
|
Greg Roelofs
|
||||||
|
https://pobox.com/~newt/greg_contact.html
|
||||||
|
16 March 2008
|
||||||
|
|
||||||
|
|
||||||
|
BUILD INSTRUCTIONS
|
||||||
|
|
||||||
|
- Prerequisites (in order of compilation):
|
||||||
|
|
||||||
|
- zlib https://zlib.net/
|
||||||
|
- libpng http://www.libpng.org/pub/png/libpng.html
|
||||||
|
- pngbook http://www.libpng.org/pub/png/book/sources.html
|
||||||
|
|
||||||
|
The pngbook demo programs are explicitly designed to demonstrate proper
|
||||||
|
coding techniques for using the libpng reference library. As a result,
|
||||||
|
you need to download and build both zlib (on which libpng depends) and
|
||||||
|
libpng. A common build setup is to place the zlib, libpng and pngbook
|
||||||
|
subdirectory trees ("folders") in the same parent directory. Then the
|
||||||
|
libpng build can refer to files in ../zlib (or ..\zlib or [-.zlib]),
|
||||||
|
and similarly for the pngbook build.
|
||||||
|
|
||||||
|
Note that all three packages are designed to be built from a command
|
||||||
|
line by default; those who wish to use a graphical or other integrated
|
||||||
|
development environments are on their own.
|
||||||
|
|
||||||
|
|
||||||
|
- Unix:
|
||||||
|
|
||||||
|
Unpack the latest pngbook sources (which should correspond to this
|
||||||
|
README file) into a directory and change into that directory.
|
||||||
|
|
||||||
|
Copy Makefile.unx to Makefile and edit the PNG* and Z* variables
|
||||||
|
appropriately (possibly also the X* variables if necessary).
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
There is no "install" target, so copy the three executables somewhere
|
||||||
|
in your path or run them from the current directory. All three will
|
||||||
|
print a basic usage screen when run without any command-line arguments;
|
||||||
|
see the book for more details.
|
||||||
|
|
||||||
|
|
||||||
|
- Windows:
|
||||||
|
|
||||||
|
Unpack the latest pngbook sources (which should correspond to this
|
||||||
|
README file) into a folder, open a "DOS shell" or "command prompt"
|
||||||
|
or equivalent command-line window, and cd into the folder where you
|
||||||
|
unpacked the source code.
|
||||||
|
|
||||||
|
For MSVC, set up the necessary environment variables by invoking
|
||||||
|
|
||||||
|
%devstudio%\vc\bin\vcvars32.bat
|
||||||
|
|
||||||
|
where where %devstudio% is the installation directory for MSVC /
|
||||||
|
DevStudio. If you get "environment out of space" errors under 95/98,
|
||||||
|
create a desktop shortcut with "c:\windows\command.com /e:4096" as
|
||||||
|
the program command line and set the working directory to the pngbook
|
||||||
|
directory. Then double-click to open the new DOS-prompt window with
|
||||||
|
a bigger environment and retry the commands above.
|
||||||
|
|
||||||
|
Copy Makefile.w32 to Makefile and edit the PNGPATH and ZPATH variables
|
||||||
|
appropriately (possibly also the "INC" and "LIB" variables if needed).
|
||||||
|
Note that the names of the dynamic and static libpng and zlib libraries
|
||||||
|
used in the makefile may change in later releases of the libraries.
|
||||||
|
Also note that, as of libpng version 1.0.5, MSVC DLL builds do not work.
|
||||||
|
This makefile therefore builds statically linked executables, but if
|
||||||
|
the DLL problems ever get fixed, uncommenting the appropriate PNGLIB
|
||||||
|
and ZLIB lines will build dynamically linked executables instead.
|
||||||
|
|
||||||
|
Do the build by typing
|
||||||
|
|
||||||
|
nmake
|
||||||
|
|
||||||
|
The result should be three executables: rpng-win.exe, rpng2-win.exe,
|
||||||
|
and wpng.exe. Copy them somewhere in your PATH or run them from the
|
||||||
|
current folder. Like the Unix versions, the two windowed programs
|
||||||
|
(rpng and rpng2) now display a usage screen in a console window when
|
||||||
|
invoked without command-line arguments; this is new behavior as of
|
||||||
|
the June 2001 release. Note that the programs use the Unix-style "-"
|
||||||
|
character to specify options, instead of the more common DOS/Windows
|
||||||
|
"/" character. (For example: "rpng2-win -bgpat 4 foo.png", not
|
||||||
|
"rpng2-win /bgpat 4 foo.png")
|
||||||
|
|
||||||
|
|
||||||
|
- OpenVMS:
|
||||||
|
|
||||||
|
Unpack the pngbook sources into a subdirectory and change into that
|
||||||
|
subdirectory.
|
||||||
|
|
||||||
|
Edit makevms.com appropriately, specifically the zpath and pngpath
|
||||||
|
variables.
|
||||||
|
|
||||||
|
@makevms
|
||||||
|
|
||||||
|
To run the programs, they probably first need to be set up as "foreign
|
||||||
|
symbols," with "disk" and "dir" set appropriately:
|
||||||
|
|
||||||
|
$ rpng == "$disk:[dir]rpng-x.exe"
|
||||||
|
$ rpng2 == "$disk:[dir]rpng2-x.exe"
|
||||||
|
$ wpng == "$disk:[dir]wpng.exe"
|
||||||
|
|
||||||
|
All three will print a basic usage screen when run without any command-
|
||||||
|
line arguments; see the book for more details. Note that the options
|
||||||
|
style is Unix-like, i.e., preceded by "-" rather than "/".
|
||||||
|
|
||||||
|
|
||||||
|
RUNNING THE PROGRAMS: (VERY) BRIEF INTRO
|
||||||
|
|
||||||
|
rpng is a simple PNG viewer that can display transparent PNGs with a
|
||||||
|
specified background color; for example,
|
||||||
|
|
||||||
|
rpng -bgcolor \#ff0000 toucan.png
|
||||||
|
|
||||||
|
would display the image with a red background. rpng2 is a progressive
|
||||||
|
viewer that simulates a web browser in some respects; it can display
|
||||||
|
images against either a background color or a dynamically generated
|
||||||
|
background image. For example:
|
||||||
|
|
||||||
|
rpng2 -bgpat 16 toucan.png
|
||||||
|
|
||||||
|
wpng is a purely command-line image converter from binary PBMPLUS/NetPBM
|
||||||
|
format (.pgm or .ppm) to PNG; for example,
|
||||||
|
|
||||||
|
wpng -time < toucan-notrans.ppm > toucan-notrans.png
|
||||||
|
|
||||||
|
would convert the specified PPM file (using redirection) to PNG, auto-
|
||||||
|
matically setting the PNG modification-time chunk.
|
||||||
|
|
||||||
|
All options can be abbreviated to the shortest unique value; for example,
|
||||||
|
"-bgc" for -bgcolor (versus "-bgp" for -bgpat), or "-g" for -gamma.
|
|
@ -0,0 +1,132 @@
|
||||||
|
$!------------------------------------------------------------------------------
|
||||||
|
$! make "PNG: The Definitive Guide" demo programs (for X) under OpenVMS
|
||||||
|
$!
|
||||||
|
$! Script created by Martin Zinser for libpng; modified by Greg Roelofs
|
||||||
|
$! for standalone pngbook source distribution.
|
||||||
|
$!
|
||||||
|
$!
|
||||||
|
$! Set locations where zlib and libpng sources live.
|
||||||
|
$!
|
||||||
|
$ zpath = ""
|
||||||
|
$ pngpath = ""
|
||||||
|
$!
|
||||||
|
$ if f$search("[---.zlib]zlib.h").nes."" then zpath = "[---.zlib]"
|
||||||
|
$ if f$search("[--]png.h").nes."" then pngpath = "[--]"
|
||||||
|
$!
|
||||||
|
$ if f$search("[-.zlib]zlib.h").nes."" then zpath = "[-.zlib]"
|
||||||
|
$ if f$search("[-.libpng]png.h").nes."" then pngpath = "[-.libpng]"
|
||||||
|
$!
|
||||||
|
$ if zpath .eqs. ""
|
||||||
|
$ then
|
||||||
|
$ write sys$output "zlib include not found. Exiting..."
|
||||||
|
$ exit 2
|
||||||
|
$ endif
|
||||||
|
$!
|
||||||
|
$ if pngpath .eqs. ""
|
||||||
|
$ then
|
||||||
|
$ write sys$output "libpng include not found. Exiting..."
|
||||||
|
$ exit 2
|
||||||
|
$ endif
|
||||||
|
$!
|
||||||
|
$! Look for the compiler used.
|
||||||
|
$!
|
||||||
|
$ ccopt="/include=(''zpath',''pngpath')"
|
||||||
|
$ if f$getsyi("HW_MODEL").ge.1024
|
||||||
|
$ then
|
||||||
|
$ ccopt = "/prefix=all"+ccopt
|
||||||
|
$ comp = "__decc__=1"
|
||||||
|
$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
|
||||||
|
$ else
|
||||||
|
$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
|
||||||
|
$ then
|
||||||
|
$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
|
||||||
|
$ if f$search("SYS$SYSTEM:VAXC.EXE").eqs.""
|
||||||
|
$ then
|
||||||
|
$ comp = "__gcc__=1"
|
||||||
|
$ CC :== GCC
|
||||||
|
$ else
|
||||||
|
$ comp = "__vaxc__=1"
|
||||||
|
$ endif
|
||||||
|
$ else
|
||||||
|
$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include:
|
||||||
|
$ ccopt = "/decc/prefix=all"+ccopt
|
||||||
|
$ comp = "__decc__=1"
|
||||||
|
$ endif
|
||||||
|
$ endif
|
||||||
|
$ open/write lopt lib.opt
|
||||||
|
$ write lopt "''pngpath'libpng.olb/lib"
|
||||||
|
$ write lopt "''zpath'libz.olb/lib"
|
||||||
|
$ close lopt
|
||||||
|
$ open/write xopt x11.opt
|
||||||
|
$ write xopt "sys$library:decw$xlibshr.exe/share"
|
||||||
|
$ close xopt
|
||||||
|
$!
|
||||||
|
$! Build 'em.
|
||||||
|
$!
|
||||||
|
$ write sys$output "Compiling PNG book programs ..."
|
||||||
|
$ CALL MAKE readpng.OBJ "cc ''CCOPT' readpng" -
|
||||||
|
readpng.c readpng.h
|
||||||
|
$ CALL MAKE readpng2.OBJ "cc ''CCOPT' readpng2" -
|
||||||
|
readpng2.c readpng2.h
|
||||||
|
$ CALL MAKE writepng.OBJ "cc ''CCOPT' writepng" -
|
||||||
|
writepng.c writepng.h
|
||||||
|
$ write sys$output "Building rpng-x..."
|
||||||
|
$ CALL MAKE rpng-x.OBJ "cc ''CCOPT' rpng-x" -
|
||||||
|
rpng-x.c readpng.h
|
||||||
|
$ call make rpng-x.exe -
|
||||||
|
"LINK rpng-x,readpng,lib.opt/opt,x11.opt/opt" -
|
||||||
|
rpng-x.obj readpng.obj
|
||||||
|
$ write sys$output "Building rpng2-x..."
|
||||||
|
$ CALL MAKE rpng2-x.OBJ "cc ''CCOPT' rpng2-x" -
|
||||||
|
rpng2-x.c readpng2.h
|
||||||
|
$ call make rpng2-x.exe -
|
||||||
|
"LINK rpng2-x,readpng2,lib.opt/opt,x11.opt/opt" -
|
||||||
|
rpng2-x.obj readpng2.obj
|
||||||
|
$ write sys$output "Building wpng..."
|
||||||
|
$ CALL MAKE wpng.OBJ "cc ''CCOPT' wpng" -
|
||||||
|
wpng.c writepng.h
|
||||||
|
$ call make wpng.exe -
|
||||||
|
"LINK wpng,writepng,lib.opt/opt" -
|
||||||
|
wpng.obj writepng.obj
|
||||||
|
$ exit
|
||||||
|
$!
|
||||||
|
$!
|
||||||
|
$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
|
||||||
|
$ V = 'F$Verify(0)
|
||||||
|
$! P1 = What we are trying to make
|
||||||
|
$! P2 = Command to make it
|
||||||
|
$! P3 - P8 What it depends on
|
||||||
|
$
|
||||||
|
$ If F$Search(P1) .Eqs. "" Then Goto Makeit
|
||||||
|
$ Time = F$CvTime(F$File(P1,"RDT"))
|
||||||
|
$arg=3
|
||||||
|
$Loop:
|
||||||
|
$ Argument = P'arg
|
||||||
|
$ If Argument .Eqs. "" Then Goto Exit
|
||||||
|
$ El=0
|
||||||
|
$Loop2:
|
||||||
|
$ File = F$Element(El," ",Argument)
|
||||||
|
$ If File .Eqs. " " Then Goto Endl
|
||||||
|
$ AFile = ""
|
||||||
|
$Loop3:
|
||||||
|
$ OFile = AFile
|
||||||
|
$ AFile = F$Search(File)
|
||||||
|
$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
|
||||||
|
$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
|
||||||
|
$ Goto Loop3
|
||||||
|
$NextEL:
|
||||||
|
$ El = El + 1
|
||||||
|
$ Goto Loop2
|
||||||
|
$EndL:
|
||||||
|
$ arg=arg+1
|
||||||
|
$ If arg .Le. 8 Then Goto Loop
|
||||||
|
$ Goto Exit
|
||||||
|
$
|
||||||
|
$Makeit:
|
||||||
|
$ VV=F$VERIFY(0)
|
||||||
|
$ write sys$output P2
|
||||||
|
$ 'P2
|
||||||
|
$ VV='F$Verify(VV)
|
||||||
|
$Exit:
|
||||||
|
$ If V Then Set Verify
|
||||||
|
$ENDSUBROUTINE
|
|
@ -0,0 +1,323 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rpng - simple PNG display program readpng.c
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2007,2017 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "png.h" /* libpng header */
|
||||||
|
#include "readpng.h" /* typedefs, common macros, public prototypes */
|
||||||
|
|
||||||
|
/* future versions of libpng will provide this macro: */
|
||||||
|
#ifndef png_jmpbuf
|
||||||
|
# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static png_structp png_ptr = NULL;
|
||||||
|
static png_infop info_ptr = NULL;
|
||||||
|
|
||||||
|
png_uint_32 width, height;
|
||||||
|
int bit_depth, color_type;
|
||||||
|
uch *image_data = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void readpng_version_info(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
|
||||||
|
PNG_LIBPNG_VER_STRING, png_libpng_ver);
|
||||||
|
fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
|
||||||
|
ZLIB_VERSION, zlib_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
|
||||||
|
|
||||||
|
int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
|
||||||
|
{
|
||||||
|
uch sig[8];
|
||||||
|
|
||||||
|
|
||||||
|
/* first do a quick check that the file really is a PNG image; could
|
||||||
|
* have used slightly more general png_sig_cmp() function instead */
|
||||||
|
|
||||||
|
fread(sig, 1, 8, infile);
|
||||||
|
if (png_sig_cmp(sig, 0, 8))
|
||||||
|
return 1; /* bad signature */
|
||||||
|
|
||||||
|
|
||||||
|
/* could pass pointers to user-defined error handlers instead of NULLs: */
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), NULL, NULL,
|
||||||
|
NULL);
|
||||||
|
if (!png_ptr)
|
||||||
|
return 4; /* out of memory */
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr) {
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
return 4; /* out of memory */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* we could create a second info struct here (end_info), but it's only
|
||||||
|
* useful if we want to keep pre- and post-IDAT chunk info separated
|
||||||
|
* (mainly for PNG-aware image editors and converters) */
|
||||||
|
|
||||||
|
|
||||||
|
/* setjmp() must be called in every function that calls a PNG-reading
|
||||||
|
* libpng function */
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
png_init_io(png_ptr, infile);
|
||||||
|
png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
|
||||||
|
|
||||||
|
png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
|
||||||
|
|
||||||
|
|
||||||
|
/* alternatively, could make separate calls to png_get_image_width(),
|
||||||
|
* etc., but want bit_depth and color_type for later [don't care about
|
||||||
|
* compression_type and filter_type => NULLs] */
|
||||||
|
|
||||||
|
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
*pWidth = width;
|
||||||
|
*pHeight = height;
|
||||||
|
|
||||||
|
|
||||||
|
/* OK, that's all we need for now; return happy */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
|
||||||
|
* scales values to 8-bit if necessary */
|
||||||
|
|
||||||
|
int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
|
||||||
|
{
|
||||||
|
png_color_16p pBackground;
|
||||||
|
|
||||||
|
|
||||||
|
/* setjmp() must be called in every function that calls a PNG-reading
|
||||||
|
* libpng function */
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* it is not obvious from the libpng documentation, but this function
|
||||||
|
* takes a pointer to a pointer, and it always returns valid red, green
|
||||||
|
* and blue values, regardless of color_type: */
|
||||||
|
|
||||||
|
png_get_bKGD(png_ptr, info_ptr, &pBackground);
|
||||||
|
|
||||||
|
|
||||||
|
/* however, it always returns the raw bKGD data, regardless of any
|
||||||
|
* bit-depth transformations, so check depth and adjust if necessary */
|
||||||
|
|
||||||
|
if (bit_depth == 16) {
|
||||||
|
*red = pBackground->red >> 8;
|
||||||
|
*green = pBackground->green >> 8;
|
||||||
|
*blue = pBackground->blue >> 8;
|
||||||
|
} else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
|
||||||
|
if (bit_depth == 1)
|
||||||
|
*red = *green = *blue = pBackground->gray? 255 : 0;
|
||||||
|
else if (bit_depth == 2)
|
||||||
|
*red = *green = *blue = (255/3) * pBackground->gray;
|
||||||
|
else /* bit_depth == 4 */
|
||||||
|
*red = *green = *blue = (255/15) * pBackground->gray;
|
||||||
|
} else {
|
||||||
|
*red = (uch)pBackground->red;
|
||||||
|
*green = (uch)pBackground->green;
|
||||||
|
*blue = (uch)pBackground->blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* display_exponent == LUT_exponent * CRT_exponent */
|
||||||
|
|
||||||
|
uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
|
||||||
|
{
|
||||||
|
double gamma;
|
||||||
|
png_uint_32 i, rowbytes;
|
||||||
|
png_bytepp row_pointers = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* setjmp() must be called in every function that calls a PNG-reading
|
||||||
|
* libpng function */
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
free(image_data);
|
||||||
|
image_data = NULL;
|
||||||
|
free(row_pointers);
|
||||||
|
row_pointers = NULL;
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
|
||||||
|
* transparency chunks to full alpha channel; strip 16-bit-per-sample
|
||||||
|
* images to 8 bits per sample; and convert grayscale to RGB[A] */
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
#ifdef PNG_READ_16_TO_8_SUPPORTED
|
||||||
|
if (bit_depth == 16)
|
||||||
|
# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
|
||||||
|
png_set_scale_16(png_ptr);
|
||||||
|
# else
|
||||||
|
png_set_strip_16(png_ptr);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||||
|
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||||
|
png_set_gray_to_rgb(png_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
/* unlike the example in the libpng documentation, we have *no* idea where
|
||||||
|
* this file may have come from--so if it doesn't have a file gamma, don't
|
||||||
|
* do any correction ("do no harm") */
|
||||||
|
|
||||||
|
if (png_get_gAMA(png_ptr, info_ptr, &gamma))
|
||||||
|
png_set_gamma(png_ptr, display_exponent, gamma);
|
||||||
|
|
||||||
|
|
||||||
|
/* all transformations have been registered; now update info_ptr data,
|
||||||
|
* get rowbytes and channels, and allocate image memory */
|
||||||
|
|
||||||
|
png_read_update_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
*pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
*pChannels = (int)png_get_channels(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
/* Guard against integer overflow */
|
||||||
|
if (height > ((size_t)(-1))/rowbytes) {
|
||||||
|
fprintf(stderr, "readpng: image_data buffer would be too large\n",
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
free(image_data);
|
||||||
|
image_data = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n",
|
||||||
|
*pChannels, rowbytes, height));
|
||||||
|
|
||||||
|
|
||||||
|
/* set the individual row_pointers to point at the correct offsets */
|
||||||
|
|
||||||
|
for (i = 0; i < height; ++i)
|
||||||
|
row_pointers[i] = image_data + i*rowbytes;
|
||||||
|
|
||||||
|
|
||||||
|
/* now we can go ahead and just read the whole image */
|
||||||
|
|
||||||
|
png_read_image(png_ptr, row_pointers);
|
||||||
|
|
||||||
|
|
||||||
|
/* and we're done! (png_read_end() can be omitted if no processing of
|
||||||
|
* post-IDAT text/time/etc. is desired) */
|
||||||
|
|
||||||
|
free(row_pointers);
|
||||||
|
row_pointers = NULL;
|
||||||
|
|
||||||
|
png_read_end(png_ptr, NULL);
|
||||||
|
|
||||||
|
return image_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void readpng_cleanup(int free_image_data)
|
||||||
|
{
|
||||||
|
if (free_image_data && image_data) {
|
||||||
|
free(image_data);
|
||||||
|
image_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (png_ptr && info_ptr) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
png_ptr = NULL;
|
||||||
|
info_ptr = NULL;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rpng - simple PNG display program readpng.h
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
# define TRUE 1
|
||||||
|
# define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
# define MAX(a,b) ((a) > (b)? (a) : (b))
|
||||||
|
# define MIN(a,b) ((a) < (b)? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
|
||||||
|
#else
|
||||||
|
# define Trace(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char uch;
|
||||||
|
typedef unsigned short ush;
|
||||||
|
typedef unsigned long ulg;
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes for public functions in readpng.c */
|
||||||
|
|
||||||
|
void readpng_version_info(void);
|
||||||
|
|
||||||
|
int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
|
||||||
|
|
||||||
|
int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
|
||||||
|
|
||||||
|
uch *readpng_get_image(double display_exponent, int *pChannels,
|
||||||
|
ulg *pRowbytes);
|
||||||
|
|
||||||
|
void readpng_cleanup(int free_image_data);
|
|
@ -0,0 +1,521 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rpng2 - progressive-model PNG display program readpng2.c
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2015 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
2015-11-12 - Check return value of png_get_bKGD() (Glenn R-P)
|
||||||
|
2017-04-22 - Guard against integer overflow (Glenn R-P)
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h> /* for exit() prototype */
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
#include "png.h" /* libpng header from the local directory */
|
||||||
|
#include "readpng2.h" /* typedefs, common macros, public prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
/* local prototypes */
|
||||||
|
|
||||||
|
static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr);
|
||||||
|
static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row,
|
||||||
|
png_uint_32 row_num, int pass);
|
||||||
|
static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr);
|
||||||
|
static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg);
|
||||||
|
static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void readpng2_version_info(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " Compiled with libpng %s; using libpng %s\n",
|
||||||
|
PNG_LIBPNG_VER_STRING, png_libpng_ver);
|
||||||
|
|
||||||
|
fprintf(stderr, " and with zlib %s; using zlib %s.\n",
|
||||||
|
ZLIB_VERSION, zlib_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int readpng2_check_sig(uch *sig, int num)
|
||||||
|
{
|
||||||
|
return !png_sig_cmp(sig, 0, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 for success, 2 for libpng problem, 4 for out of memory */
|
||||||
|
|
||||||
|
int readpng2_init(mainprog_info *mainprog_ptr)
|
||||||
|
{
|
||||||
|
png_structp png_ptr; /* note: temporary variables! */
|
||||||
|
png_infop info_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* could also replace libpng warning-handler (final NULL), but no need: */
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), mainprog_ptr,
|
||||||
|
readpng2_error_handler, readpng2_warning_handler);
|
||||||
|
if (!png_ptr)
|
||||||
|
return 4; /* out of memory */
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr) {
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
return 4; /* out of memory */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* we could create a second info struct here (end_info), but it's only
|
||||||
|
* useful if we want to keep pre- and post-IDAT chunk info separated
|
||||||
|
* (mainly for PNG-aware image editors and converters) */
|
||||||
|
|
||||||
|
|
||||||
|
/* setjmp() must be called in every function that calls a PNG-reading
|
||||||
|
* libpng function, unless an alternate error handler was installed--
|
||||||
|
* but compatible error handlers must either use longjmp() themselves
|
||||||
|
* (as in this program) or exit immediately, so here we are: */
|
||||||
|
|
||||||
|
if (setjmp(mainprog_ptr->jmpbuf)) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||||
|
/* prepare the reader to ignore all recognized chunks whose data won't be
|
||||||
|
* used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT,
|
||||||
|
* IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */
|
||||||
|
{
|
||||||
|
/* These byte strings were copied from png.h. If a future version
|
||||||
|
* of readpng2.c recognizes more chunks, add them to this list.
|
||||||
|
*/
|
||||||
|
static const png_byte chunks_to_process[] = {
|
||||||
|
98, 75, 71, 68, '\0', /* bKGD */
|
||||||
|
103, 65, 77, 65, '\0', /* gAMA */
|
||||||
|
115, 82, 71, 66, '\0', /* sRGB */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Ignore all chunks except for IHDR, PLTE, tRNS, IDAT, and IEND */
|
||||||
|
png_set_keep_unknown_chunks(png_ptr, -1 /* PNG_HANDLE_CHUNK_NEVER */,
|
||||||
|
NULL, -1);
|
||||||
|
|
||||||
|
/* But do not ignore chunks in the "chunks_to_process" list */
|
||||||
|
png_set_keep_unknown_chunks(png_ptr,
|
||||||
|
0 /* PNG_HANDLE_CHUNK_AS_DEFAULT */, chunks_to_process,
|
||||||
|
sizeof(chunks_to_process)/5);
|
||||||
|
}
|
||||||
|
#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */
|
||||||
|
|
||||||
|
|
||||||
|
/* instead of doing png_init_io() here, now we set up our callback
|
||||||
|
* functions for progressive decoding */
|
||||||
|
|
||||||
|
png_set_progressive_read_fn(png_ptr, mainprog_ptr,
|
||||||
|
readpng2_info_callback, readpng2_row_callback, readpng2_end_callback);
|
||||||
|
|
||||||
|
|
||||||
|
/* make sure we save our pointers for use in readpng2_decode_data() */
|
||||||
|
|
||||||
|
mainprog_ptr->png_ptr = png_ptr;
|
||||||
|
mainprog_ptr->info_ptr = info_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* and that's all there is to initialization */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 for success, 2 for libpng (longjmp) problem */
|
||||||
|
|
||||||
|
int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
||||||
|
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* setjmp() must be called in every function that calls a PNG-reading
|
||||||
|
* libpng function */
|
||||||
|
|
||||||
|
if (setjmp(mainprog_ptr->jmpbuf)) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
mainprog_ptr->png_ptr = NULL;
|
||||||
|
mainprog_ptr->info_ptr = NULL;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* hand off the next chunk of input data to libpng for decoding */
|
||||||
|
|
||||||
|
png_process_data(png_ptr, info_ptr, rawbuf, length);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||||
|
{
|
||||||
|
mainprog_info *mainprog_ptr;
|
||||||
|
int color_type, bit_depth;
|
||||||
|
png_uint_32 width, height;
|
||||||
|
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||||
|
double gamma;
|
||||||
|
#else
|
||||||
|
png_fixed_point gamma;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* setjmp() doesn't make sense here, because we'd either have to exit(),
|
||||||
|
* longjmp() ourselves, or return control to libpng, which doesn't want
|
||||||
|
* to see us again. By not doing anything here, libpng will instead jump
|
||||||
|
* to readpng2_decode_data(), which can return an error value to the main
|
||||||
|
* program. */
|
||||||
|
|
||||||
|
|
||||||
|
/* retrieve the pointer to our special-purpose struct, using the png_ptr
|
||||||
|
* that libpng passed back to us (i.e., not a global this time--there's
|
||||||
|
* no real difference for a single image, but for a multithreaded browser
|
||||||
|
* decoding several PNG images at the same time, one needs to avoid mixing
|
||||||
|
* up different images' structs) */
|
||||||
|
|
||||||
|
mainprog_ptr = png_get_progressive_ptr(png_ptr);
|
||||||
|
|
||||||
|
if (mainprog_ptr == NULL) { /* we be hosed */
|
||||||
|
fprintf(stderr,
|
||||||
|
"readpng2 error: main struct not recoverable in info_callback.\n");
|
||||||
|
fflush(stderr);
|
||||||
|
return;
|
||||||
|
/*
|
||||||
|
* Alternatively, we could call our error-handler just like libpng
|
||||||
|
* does, which would effectively terminate the program. Since this
|
||||||
|
* can only happen if png_ptr gets redirected somewhere odd or the
|
||||||
|
* main PNG struct gets wiped, we're probably toast anyway. (If
|
||||||
|
* png_ptr itself is NULL, we would not have been called.)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* this is just like in the non-progressive case */
|
||||||
|
|
||||||
|
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
mainprog_ptr->width = (ulg)width;
|
||||||
|
mainprog_ptr->height = (ulg)height;
|
||||||
|
|
||||||
|
|
||||||
|
/* since we know we've read all of the PNG file's "header" (i.e., up
|
||||||
|
* to IDAT), we can check for a background color here */
|
||||||
|
|
||||||
|
if (mainprog_ptr->need_bgcolor)
|
||||||
|
{
|
||||||
|
png_color_16p pBackground;
|
||||||
|
|
||||||
|
/* it is not obvious from the libpng documentation, but this function
|
||||||
|
* takes a pointer to a pointer, and it always returns valid red,
|
||||||
|
* green and blue values, regardless of color_type: */
|
||||||
|
if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
|
||||||
|
{
|
||||||
|
|
||||||
|
/* however, it always returns the raw bKGD data, regardless of any
|
||||||
|
* bit-depth transformations, so check depth and adjust if necessary
|
||||||
|
*/
|
||||||
|
if (bit_depth == 16) {
|
||||||
|
mainprog_ptr->bg_red = pBackground->red >> 8;
|
||||||
|
mainprog_ptr->bg_green = pBackground->green >> 8;
|
||||||
|
mainprog_ptr->bg_blue = pBackground->blue >> 8;
|
||||||
|
} else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
|
||||||
|
if (bit_depth == 1)
|
||||||
|
mainprog_ptr->bg_red = mainprog_ptr->bg_green =
|
||||||
|
mainprog_ptr->bg_blue = pBackground->gray? 255 : 0;
|
||||||
|
else if (bit_depth == 2)
|
||||||
|
mainprog_ptr->bg_red = mainprog_ptr->bg_green =
|
||||||
|
mainprog_ptr->bg_blue = (255/3) * pBackground->gray;
|
||||||
|
else /* bit_depth == 4 */
|
||||||
|
mainprog_ptr->bg_red = mainprog_ptr->bg_green =
|
||||||
|
mainprog_ptr->bg_blue = (255/15) * pBackground->gray;
|
||||||
|
} else {
|
||||||
|
mainprog_ptr->bg_red = (uch)pBackground->red;
|
||||||
|
mainprog_ptr->bg_green = (uch)pBackground->green;
|
||||||
|
mainprog_ptr->bg_blue = (uch)pBackground->blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* as before, let libpng expand palette images to RGB, low-bit-depth
|
||||||
|
* grayscale images to 8 bits, transparency chunks to full alpha channel;
|
||||||
|
* strip 16-bit-per-sample images to 8 bits per sample; and convert
|
||||||
|
* grayscale to RGB[A] */
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
#ifdef PNG_READ_16_TO_8_SUPPORTED
|
||||||
|
if (bit_depth == 16)
|
||||||
|
# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
|
||||||
|
png_set_scale_16(png_ptr);
|
||||||
|
# else
|
||||||
|
png_set_strip_16(png_ptr);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||||
|
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||||
|
png_set_gray_to_rgb(png_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
/* Unlike the basic viewer, which was designed to operate on local files,
|
||||||
|
* this program is intended to simulate a web browser--even though we
|
||||||
|
* actually read from a local file, too. But because we are pretending
|
||||||
|
* that most of the images originate on the Internet, we follow the recom-
|
||||||
|
* mendation of the sRGB proposal and treat unlabelled images (no gAMA
|
||||||
|
* chunk) as existing in the sRGB color space. That is, we assume that
|
||||||
|
* such images have a file gamma of 0.45455, which corresponds to a PC-like
|
||||||
|
* display system. This change in assumptions will have no effect on a
|
||||||
|
* PC-like system, but on a Mac, SGI, NeXT or other system with a non-
|
||||||
|
* identity lookup table, it will darken unlabelled images, which effec-
|
||||||
|
* tively favors images from PC-like systems over those originating on
|
||||||
|
* the local platform. Note that mainprog_ptr->display_exponent is the
|
||||||
|
* "gamma" value for the entire display system, i.e., the product of
|
||||||
|
* LUT_exponent and CRT_exponent. */
|
||||||
|
|
||||||
|
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||||
|
if (png_get_gAMA(png_ptr, info_ptr, &gamma))
|
||||||
|
png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma);
|
||||||
|
else
|
||||||
|
png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455);
|
||||||
|
#else
|
||||||
|
if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma))
|
||||||
|
png_set_gamma_fixed(png_ptr,
|
||||||
|
(png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma);
|
||||||
|
else
|
||||||
|
png_set_gamma_fixed(png_ptr,
|
||||||
|
(png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* we'll let libpng expand interlaced images, too */
|
||||||
|
|
||||||
|
mainprog_ptr->passes = png_set_interlace_handling(png_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
/* all transformations have been registered; now update info_ptr data and
|
||||||
|
* then get rowbytes and channels */
|
||||||
|
|
||||||
|
png_read_update_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
mainprog_ptr->rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
mainprog_ptr->channels = png_get_channels(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
/* Call the main program to allocate memory for the image buffer and
|
||||||
|
* initialize windows and whatnot. (The old-style function-pointer
|
||||||
|
* invocation is used for compatibility with a few supposedly ANSI
|
||||||
|
* compilers that nevertheless barf on "fn_ptr()"-style syntax.) */
|
||||||
|
|
||||||
|
(*mainprog_ptr->mainprog_init)();
|
||||||
|
|
||||||
|
|
||||||
|
/* and that takes care of initialization */
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row,
|
||||||
|
png_uint_32 row_num, int pass)
|
||||||
|
{
|
||||||
|
mainprog_info *mainprog_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* first check whether the row differs from the previous pass; if not,
|
||||||
|
* nothing to combine or display */
|
||||||
|
|
||||||
|
if (!new_row)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
/* retrieve the pointer to our special-purpose struct so we can access
|
||||||
|
* the old rows and image-display callback function */
|
||||||
|
|
||||||
|
mainprog_ptr = png_get_progressive_ptr(png_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
/* save the pass number for optional use by the front end */
|
||||||
|
|
||||||
|
mainprog_ptr->pass = pass;
|
||||||
|
|
||||||
|
|
||||||
|
/* have libpng either combine the new row data with the existing row data
|
||||||
|
* from previous passes (if interlaced) or else just copy the new row
|
||||||
|
* into the main program's image buffer */
|
||||||
|
|
||||||
|
png_progressive_combine_row(png_ptr, mainprog_ptr->row_pointers[row_num],
|
||||||
|
new_row);
|
||||||
|
|
||||||
|
|
||||||
|
/* finally, call the display routine in the main program with the number
|
||||||
|
* of the row we just updated */
|
||||||
|
|
||||||
|
(*mainprog_ptr->mainprog_display_row)(row_num);
|
||||||
|
|
||||||
|
|
||||||
|
/* and we're ready for more */
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr)
|
||||||
|
{
|
||||||
|
mainprog_info *mainprog_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* retrieve the pointer to our special-purpose struct */
|
||||||
|
|
||||||
|
mainprog_ptr = png_get_progressive_ptr(png_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
/* let the main program know that it should flush any buffered image
|
||||||
|
* data to the display now and set a "done" flag or whatever, but note
|
||||||
|
* that it SHOULD NOT DESTROY THE PNG STRUCTS YET--in other words, do
|
||||||
|
* NOT call readpng2_cleanup() either here or in the finish_display()
|
||||||
|
* routine; wait until control returns to the main program via
|
||||||
|
* readpng2_decode_data() */
|
||||||
|
|
||||||
|
(*mainprog_ptr->mainprog_finish_display)();
|
||||||
|
|
||||||
|
|
||||||
|
/* all done */
|
||||||
|
|
||||||
|
(void)info_ptr; /* Unused */
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void readpng2_cleanup(mainprog_info *mainprog_ptr)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
||||||
|
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
||||||
|
|
||||||
|
if (png_ptr && info_ptr)
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
|
||||||
|
mainprog_ptr->png_ptr = NULL;
|
||||||
|
mainprog_ptr->info_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "readpng2 libpng warning: %s\n", msg);
|
||||||
|
fflush(stderr);
|
||||||
|
(void)png_ptr; /* Unused */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg)
|
||||||
|
{
|
||||||
|
mainprog_info *mainprog_ptr;
|
||||||
|
|
||||||
|
/* This function, aside from the extra step of retrieving the "error
|
||||||
|
* pointer" (below) and the fact that it exists within the application
|
||||||
|
* rather than within libpng, is essentially identical to libpng's
|
||||||
|
* default error handler. The second point is critical: since both
|
||||||
|
* setjmp() and longjmp() are called from the same code, they are
|
||||||
|
* guaranteed to have compatible notions of how big a jmp_buf is,
|
||||||
|
* regardless of whether _BSD_SOURCE or anything else has (or has not)
|
||||||
|
* been defined. */
|
||||||
|
|
||||||
|
fprintf(stderr, "readpng2 libpng error: %s\n", msg);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
mainprog_ptr = png_get_error_ptr(png_ptr);
|
||||||
|
if (mainprog_ptr == NULL) { /* we are completely hosed now */
|
||||||
|
fprintf(stderr,
|
||||||
|
"readpng2 severe error: jmpbuf not recoverable; terminating.\n");
|
||||||
|
fflush(stderr);
|
||||||
|
exit(99);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we have our data structure we can use the information in it
|
||||||
|
* to return control to our own higher level code (all the points
|
||||||
|
* where 'setjmp' is called in this file.) This will work with other
|
||||||
|
* error handling mechanisms as well - libpng always calls png_error
|
||||||
|
* when it can proceed no further, thus, so long as the error handler
|
||||||
|
* is intercepted, application code can do its own error recovery.
|
||||||
|
*/
|
||||||
|
longjmp(mainprog_ptr->jmpbuf, 1);
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rpng2 - progressive-model PNG display program readpng2.h
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
# define TRUE 1
|
||||||
|
# define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
# define MAX(a,b) ((a) > (b)? (a) : (b))
|
||||||
|
# define MIN(a,b) ((a) < (b)? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
|
||||||
|
#else
|
||||||
|
# define Trace(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum rpng2_states {
|
||||||
|
kPreInit = 0,
|
||||||
|
kWindowInit,
|
||||||
|
kDone
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned char uch;
|
||||||
|
typedef unsigned short ush;
|
||||||
|
typedef unsigned long ulg;
|
||||||
|
|
||||||
|
typedef struct _mainprog_info {
|
||||||
|
double display_exponent;
|
||||||
|
ulg width;
|
||||||
|
ulg height;
|
||||||
|
void *png_ptr;
|
||||||
|
void *info_ptr;
|
||||||
|
void (*mainprog_init)(void);
|
||||||
|
void (*mainprog_display_row)(ulg row_num);
|
||||||
|
void (*mainprog_finish_display)(void);
|
||||||
|
uch *image_data;
|
||||||
|
uch **row_pointers;
|
||||||
|
jmp_buf jmpbuf;
|
||||||
|
int passes; /* not used */
|
||||||
|
int pass;
|
||||||
|
int rowbytes;
|
||||||
|
int channels;
|
||||||
|
int need_bgcolor;
|
||||||
|
int state;
|
||||||
|
uch bg_red;
|
||||||
|
uch bg_green;
|
||||||
|
uch bg_blue;
|
||||||
|
} mainprog_info;
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes for public functions in readpng2.c */
|
||||||
|
|
||||||
|
void readpng2_version_info(void);
|
||||||
|
|
||||||
|
int readpng2_check_sig(uch *sig, int num);
|
||||||
|
|
||||||
|
int readpng2_init(mainprog_info *mainprog_ptr);
|
||||||
|
|
||||||
|
int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length);
|
||||||
|
|
||||||
|
void readpng2_cleanup(mainprog_info *mainprog_ptr);
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rpng - simple PNG display program readppm.c
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This is a special-purpose replacement for readpng.c that allows binary
|
||||||
|
PPM files to be used in place of PNG images.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2007,2017 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "readpng.h" /* typedefs, common macros, public prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
ulg width, height;
|
||||||
|
int bit_depth, color_type, channels;
|
||||||
|
uch *image_data = NULL;
|
||||||
|
FILE *saved_infile;
|
||||||
|
|
||||||
|
|
||||||
|
void readpng_version_info()
|
||||||
|
{
|
||||||
|
fprintf(stderr, " Compiled without libpng, zlib or PBMPLUS/NetPBM.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
|
||||||
|
|
||||||
|
int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
|
||||||
|
{
|
||||||
|
static uch ppmline[256];
|
||||||
|
int maxval;
|
||||||
|
|
||||||
|
|
||||||
|
saved_infile = infile;
|
||||||
|
|
||||||
|
fgets(ppmline, 256, infile);
|
||||||
|
if (ppmline[0] != 'P' || ppmline[1] != '6') {
|
||||||
|
fprintf(stderr, "ERROR: not a PPM file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* possible color types: P5 = grayscale (0), P6 = RGB (2), P8 = RGBA (6) */
|
||||||
|
if (ppmline[1] == '6') {
|
||||||
|
color_type = 2;
|
||||||
|
channels = 3;
|
||||||
|
} else if (ppmline[1] == '8') {
|
||||||
|
color_type = 6;
|
||||||
|
channels = 4;
|
||||||
|
} else /* if (ppmline[1] == '5') */ {
|
||||||
|
color_type = 0;
|
||||||
|
channels = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
fgets(ppmline, 256, infile);
|
||||||
|
} while (ppmline[0] == '#');
|
||||||
|
sscanf(ppmline, "%lu %lu", &width, &height);
|
||||||
|
|
||||||
|
do {
|
||||||
|
fgets(ppmline, 256, infile);
|
||||||
|
} while (ppmline[0] == '#');
|
||||||
|
sscanf(ppmline, "%d", &maxval);
|
||||||
|
if (maxval != 255) {
|
||||||
|
fprintf(stderr, "ERROR: maxval = %d\n", maxval);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
bit_depth = 8;
|
||||||
|
|
||||||
|
*pWidth = width;
|
||||||
|
*pHeight = height;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
|
||||||
|
* scales values to 8-bit if necessary */
|
||||||
|
|
||||||
|
int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* display_exponent == LUT_exponent * CRT_exponent */
|
||||||
|
|
||||||
|
uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
|
||||||
|
{
|
||||||
|
ulg rowbytes;
|
||||||
|
|
||||||
|
|
||||||
|
/* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
|
||||||
|
* transparency chunks to full alpha channel; strip 16-bit-per-sample
|
||||||
|
* images to 8 bits per sample; and convert grayscale to RGB[A] */
|
||||||
|
|
||||||
|
/* GRR WARNING: grayscale needs to be expanded and channels reset! */
|
||||||
|
|
||||||
|
*pRowbytes = rowbytes = channels*width;
|
||||||
|
*pChannels = channels;
|
||||||
|
|
||||||
|
Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height));
|
||||||
|
|
||||||
|
/* Guard against integer overflow */
|
||||||
|
if (height > ((size_t)(-1))/rowbytes) {
|
||||||
|
fprintf(stderr, PROGNAME ": image_data buffer would be too large\n",
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now we can go ahead and just read the whole image */
|
||||||
|
|
||||||
|
if (fread(image_data, 1L, rowbytes*height, saved_infile) <
|
||||||
|
rowbytes*height) {
|
||||||
|
free (image_data);
|
||||||
|
image_data = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void readpng_cleanup(int free_image_data)
|
||||||
|
{
|
||||||
|
if (free_image_data && image_data) {
|
||||||
|
free(image_data);
|
||||||
|
image_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,735 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rpng - simple PNG display program rpng-win.c
|
||||||
|
|
||||||
|
This program decodes and displays PNG images, with gamma correction and
|
||||||
|
optionally with a user-specified background color (in case the image has
|
||||||
|
transparency). It is very nearly the most basic PNG viewer possible.
|
||||||
|
This version is for 32-bit Windows; it may compile under 16-bit Windows
|
||||||
|
with a little tweaking (or maybe not).
|
||||||
|
|
||||||
|
to do:
|
||||||
|
- handle quoted command-line args (especially filenames with spaces)
|
||||||
|
- have minimum window width: oh well
|
||||||
|
- use %.1023s to simplify truncation of title-bar string?
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
- 1.00: initial public release
|
||||||
|
- 1.01: modified to allow abbreviated options; fixed long/ulong mis-
|
||||||
|
match; switched to png_jmpbuf() macro
|
||||||
|
- 1.02: added extra set of parentheses to png_jmpbuf() macro; fixed
|
||||||
|
command-line parsing bug
|
||||||
|
- 1.10: enabled "message window"/console (thanks to David Geldreich)
|
||||||
|
- 2.00: dual-licensed (added GNU GPL)
|
||||||
|
- 2.01: fixed improper display of usage screen on PNG error(s)
|
||||||
|
- 2.02: check for integer overflow (Glenn R-P)
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2008, 2017 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define PROGNAME "rpng-win"
|
||||||
|
#define LONGNAME "Simple PNG Viewer for Windows"
|
||||||
|
#define VERSION "2.01 of 16 March 2008"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
/* getch replacement. Turns out, we don't really need this,
|
||||||
|
* but leave it here if we ever enable any of the uses of
|
||||||
|
* _getch in the main code
|
||||||
|
*/
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <termio.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
int repl_getch( void )
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
int fd = fileno(stdin);
|
||||||
|
struct termio old_tty, new_tty;
|
||||||
|
|
||||||
|
ioctl(fd, TCGETA, &old_tty);
|
||||||
|
new_tty = old_tty;
|
||||||
|
new_tty.c_lflag &= ~(ICANON | ECHO | ISIG);
|
||||||
|
ioctl(fd, TCSETA, &new_tty);
|
||||||
|
fread(&ch, 1, sizeof(ch), stdin);
|
||||||
|
ioctl(fd, TCSETA, &old_tty);
|
||||||
|
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
#define _getch repl_getch
|
||||||
|
#else
|
||||||
|
#include <conio.h> /* only for _getch() */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* #define DEBUG : this enables the Trace() macros */
|
||||||
|
|
||||||
|
#include "readpng.h" /* typedefs, common macros, readpng prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
/* could just include png.h, but this macro is the only thing we need
|
||||||
|
* (name and typedefs changed to local versions); note that side effects
|
||||||
|
* only happen with alpha (which could easily be avoided with
|
||||||
|
* "ush acopy = (alpha);") */
|
||||||
|
|
||||||
|
#define alpha_composite(composite, fg, alpha, bg) { \
|
||||||
|
ush temp = ((ush)(fg)*(ush)(alpha) + \
|
||||||
|
(ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
|
||||||
|
(composite) = (uch)((temp + (temp >> 8)) >> 8); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* local prototypes */
|
||||||
|
static int rpng_win_create_window(HINSTANCE hInst, int showmode);
|
||||||
|
static int rpng_win_display_image(void);
|
||||||
|
static void rpng_win_cleanup(void);
|
||||||
|
LRESULT CALLBACK rpng_win_wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
|
|
||||||
|
static char titlebar[1024];
|
||||||
|
static char *progname = PROGNAME;
|
||||||
|
static char *appname = LONGNAME;
|
||||||
|
static char *filename;
|
||||||
|
static FILE *infile;
|
||||||
|
|
||||||
|
static char *bgstr;
|
||||||
|
static uch bg_red=0, bg_green=0, bg_blue=0;
|
||||||
|
|
||||||
|
static double display_exponent;
|
||||||
|
|
||||||
|
static ulg image_width, image_height, image_rowbytes;
|
||||||
|
static int image_channels;
|
||||||
|
static uch *image_data;
|
||||||
|
|
||||||
|
/* Windows-specific variables */
|
||||||
|
static ulg wimage_rowbytes;
|
||||||
|
static uch *dib;
|
||||||
|
static uch *wimage_data;
|
||||||
|
static BITMAPINFOHEADER *bmih;
|
||||||
|
|
||||||
|
static HWND global_hwnd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
|
||||||
|
{
|
||||||
|
char *args[1024]; /* arbitrary limit, but should suffice */
|
||||||
|
char *p, *q, **argv = args;
|
||||||
|
int argc = 0;
|
||||||
|
int rc, alen, flen;
|
||||||
|
int error = 0;
|
||||||
|
int have_bg = FALSE;
|
||||||
|
double LUT_exponent; /* just the lookup table */
|
||||||
|
double CRT_exponent = 2.2; /* just the monitor */
|
||||||
|
double default_display_exponent; /* whole display system */
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
|
||||||
|
filename = (char *)NULL;
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
/* First reenable console output, which normally goes to the bit bucket
|
||||||
|
* for windowed apps. Closing the console window will terminate the
|
||||||
|
* app. Thanks to David.Geldreich at realviz.com for supplying the magical
|
||||||
|
* incantation. */
|
||||||
|
|
||||||
|
AllocConsole();
|
||||||
|
freopen("CONOUT$", "a", stderr);
|
||||||
|
freopen("CONOUT$", "a", stdout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Next set the default value for our display-system exponent, i.e.,
|
||||||
|
* the product of the CRT exponent and the exponent corresponding to
|
||||||
|
* the frame-buffer's lookup table (LUT), if any. This is not an
|
||||||
|
* exhaustive list of LUT values (e.g., OpenStep has a lot of weird
|
||||||
|
* ones), but it should cover 99% of the current possibilities. And
|
||||||
|
* yes, these ifdefs are completely wasted in a Windows program... */
|
||||||
|
|
||||||
|
#if defined(NeXT)
|
||||||
|
LUT_exponent = 1.0 / 2.2;
|
||||||
|
/*
|
||||||
|
if (some_next_function_that_returns_gamma(&next_gamma))
|
||||||
|
LUT_exponent = 1.0 / next_gamma;
|
||||||
|
*/
|
||||||
|
#elif defined(sgi)
|
||||||
|
LUT_exponent = 1.0 / 1.7;
|
||||||
|
/* there doesn't seem to be any documented function to get the
|
||||||
|
* "gamma" value, so we do it the hard way */
|
||||||
|
infile = fopen("/etc/config/system.glGammaVal", "r");
|
||||||
|
if (infile) {
|
||||||
|
double sgi_gamma;
|
||||||
|
|
||||||
|
fgets(tmpline, 80, infile);
|
||||||
|
fclose(infile);
|
||||||
|
sgi_gamma = atof(tmpline);
|
||||||
|
if (sgi_gamma > 0.0)
|
||||||
|
LUT_exponent = 1.0 / sgi_gamma;
|
||||||
|
}
|
||||||
|
#elif defined(Macintosh)
|
||||||
|
LUT_exponent = 1.8 / 2.61;
|
||||||
|
/*
|
||||||
|
if (some_mac_function_that_returns_gamma(&mac_gamma))
|
||||||
|
LUT_exponent = mac_gamma / 2.61;
|
||||||
|
*/
|
||||||
|
#else
|
||||||
|
LUT_exponent = 1.0; /* assume no LUT: most PCs */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
|
||||||
|
default_display_exponent = LUT_exponent * CRT_exponent;
|
||||||
|
|
||||||
|
|
||||||
|
/* If the user has set the SCREEN_GAMMA environment variable as suggested
|
||||||
|
* (somewhat imprecisely) in the libpng documentation, use that; otherwise
|
||||||
|
* use the default value we just calculated. Either way, the user may
|
||||||
|
* override this via a command-line option. */
|
||||||
|
|
||||||
|
if ((p = getenv("SCREEN_GAMMA")) != NULL)
|
||||||
|
display_exponent = atof(p);
|
||||||
|
else
|
||||||
|
display_exponent = default_display_exponent;
|
||||||
|
|
||||||
|
|
||||||
|
/* Windows really hates command lines, so we have to set up our own argv.
|
||||||
|
* Note that we do NOT bother with quoted arguments here, so don't use
|
||||||
|
* filenames with spaces in 'em! */
|
||||||
|
|
||||||
|
argv[argc++] = PROGNAME;
|
||||||
|
p = cmd;
|
||||||
|
for (;;) {
|
||||||
|
if (*p == ' ')
|
||||||
|
while (*++p == ' ')
|
||||||
|
;
|
||||||
|
/* now p points at the first non-space after some spaces */
|
||||||
|
if (*p == '\0')
|
||||||
|
break; /* nothing after the spaces: done */
|
||||||
|
argv[argc++] = q = p;
|
||||||
|
while (*q && *q != ' ')
|
||||||
|
++q;
|
||||||
|
/* now q points at a space or the end of the string */
|
||||||
|
if (*q == '\0')
|
||||||
|
break; /* last argv already terminated; quit */
|
||||||
|
*q = '\0'; /* change space to terminator */
|
||||||
|
p = q + 1;
|
||||||
|
}
|
||||||
|
argv[argc] = NULL; /* terminate the argv array itself */
|
||||||
|
|
||||||
|
|
||||||
|
/* Now parse the command line for options and the PNG filename. */
|
||||||
|
|
||||||
|
while (*++argv && !error) {
|
||||||
|
if (!strncmp(*argv, "-gamma", 2)) {
|
||||||
|
if (!*++argv)
|
||||||
|
++error;
|
||||||
|
else {
|
||||||
|
display_exponent = atof(*argv);
|
||||||
|
if (display_exponent <= 0.0)
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
} else if (!strncmp(*argv, "-bgcolor", 2)) {
|
||||||
|
if (!*++argv)
|
||||||
|
++error;
|
||||||
|
else {
|
||||||
|
bgstr = *argv;
|
||||||
|
if (strlen(bgstr) != 7 || bgstr[0] != '#')
|
||||||
|
++error;
|
||||||
|
else
|
||||||
|
have_bg = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (**argv != '-') {
|
||||||
|
filename = *argv;
|
||||||
|
if (argv[1]) /* shouldn't be any more args after filename */
|
||||||
|
++error;
|
||||||
|
} else
|
||||||
|
++error; /* not expecting any other options */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filename)
|
||||||
|
++error;
|
||||||
|
|
||||||
|
|
||||||
|
/* print usage screen if any errors up to this point */
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
int ch;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname);
|
||||||
|
readpng_version_info();
|
||||||
|
fprintf(stderr, "\n"
|
||||||
|
"Usage: %s [-gamma exp] [-bgcolor bg] file.png\n"
|
||||||
|
" exp \ttransfer-function exponent (``gamma'') of the display\n"
|
||||||
|
"\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
|
||||||
|
"\t\t to the product of the lookup-table exponent (varies)\n"
|
||||||
|
"\t\t and the CRT exponent (usually 2.2); must be positive\n"
|
||||||
|
" bg \tdesired background color in 7-character hex RGB format\n"
|
||||||
|
"\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
|
||||||
|
"\t\t used with transparent images\n"
|
||||||
|
"\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n"
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
"Press Q or Esc to quit this usage screen.\n"
|
||||||
|
#endif
|
||||||
|
"\n", PROGNAME, default_display_exponent);
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
do
|
||||||
|
ch = _getch();
|
||||||
|
while (ch != 'q' && ch != 'Q' && ch != 0x1B);
|
||||||
|
#endif
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!(infile = fopen(filename, "rb"))) {
|
||||||
|
fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
|
||||||
|
++error;
|
||||||
|
} else {
|
||||||
|
if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
|
||||||
|
switch (rc) {
|
||||||
|
case 1:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": [%s] is not a PNG file: incorrect signature\n",
|
||||||
|
filename);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": [%s] has bad IHDR (libpng longjmp)\n", filename);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(stderr, PROGNAME ": insufficient memory\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": unknown readpng_init() error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
if (error)
|
||||||
|
fclose(infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
int ch;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fprintf(stderr, PROGNAME ": aborting.\n");
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
do
|
||||||
|
ch = _getch();
|
||||||
|
while (ch != 'q' && ch != 'Q' && ch != 0x1B);
|
||||||
|
#endif
|
||||||
|
exit(2);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n [console window: closing this window will terminate %s]\n\n",
|
||||||
|
PROGNAME);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set the title-bar string, but make sure buffer doesn't overflow */
|
||||||
|
|
||||||
|
alen = strlen(appname);
|
||||||
|
flen = strlen(filename);
|
||||||
|
if (alen + flen + 3 > 1023)
|
||||||
|
sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
|
||||||
|
else
|
||||||
|
sprintf(titlebar, "%s: %s", appname, filename);
|
||||||
|
|
||||||
|
|
||||||
|
/* if the user didn't specify a background color on the command line,
|
||||||
|
* check for one in the PNG file--if not, the initialized values of 0
|
||||||
|
* (black) will be used */
|
||||||
|
|
||||||
|
if (have_bg) {
|
||||||
|
unsigned r, g, b; /* this approach quiets compiler warnings */
|
||||||
|
|
||||||
|
sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
|
||||||
|
bg_red = (uch)r;
|
||||||
|
bg_green = (uch)g;
|
||||||
|
bg_blue = (uch)b;
|
||||||
|
} else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
|
||||||
|
readpng_cleanup(TRUE);
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": libpng error while checking for background color\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* do the basic Windows initialization stuff, make the window and fill it
|
||||||
|
* with the background color */
|
||||||
|
|
||||||
|
if (rpng_win_create_window(hInst, showmode))
|
||||||
|
exit(2);
|
||||||
|
|
||||||
|
|
||||||
|
/* decode the image, all at once */
|
||||||
|
|
||||||
|
Trace((stderr, "calling readpng_get_image()\n"))
|
||||||
|
image_data = readpng_get_image(display_exponent, &image_channels,
|
||||||
|
&image_rowbytes);
|
||||||
|
Trace((stderr, "done with readpng_get_image()\n"))
|
||||||
|
|
||||||
|
|
||||||
|
/* done with PNG file, so clean up to minimize memory usage (but do NOT
|
||||||
|
* nuke image_data!) */
|
||||||
|
|
||||||
|
readpng_cleanup(FALSE);
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
if (!image_data) {
|
||||||
|
fprintf(stderr, PROGNAME ": unable to decode PNG image\n");
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* display image (composite with background if requested) */
|
||||||
|
|
||||||
|
Trace((stderr, "calling rpng_win_display_image()\n"))
|
||||||
|
if (rpng_win_display_image()) {
|
||||||
|
free(image_data);
|
||||||
|
exit(4);
|
||||||
|
}
|
||||||
|
Trace((stderr, "done with rpng_win_display_image()\n"))
|
||||||
|
|
||||||
|
|
||||||
|
/* wait for the user to tell us when to quit */
|
||||||
|
|
||||||
|
printf(
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
"Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"
|
||||||
|
#else
|
||||||
|
"Done. Press mouse button 1 (within image window) to quit.\n"
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* OK, we're done: clean up all image and Windows resources and go away */
|
||||||
|
|
||||||
|
rpng_win_cleanup();
|
||||||
|
|
||||||
|
return msg.wParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int rpng_win_create_window(HINSTANCE hInst, int showmode)
|
||||||
|
{
|
||||||
|
uch *dest;
|
||||||
|
int extra_width, extra_height;
|
||||||
|
ulg i, j;
|
||||||
|
WNDCLASSEX wndclass;
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Allocate memory for the display-specific version of the image (round up
|
||||||
|
to multiple of 4 for Windows DIB).
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
wimage_rowbytes = ((3*image_width + 3L) >> 2) << 2;
|
||||||
|
|
||||||
|
/* Guard against integer overflow */
|
||||||
|
if (image_height > ((size_t)(-1))/wimage_rowbytes) {
|
||||||
|
fprintf(stderr, PROGNAME ": image_data buffer would be too large\n");
|
||||||
|
return 4; /* fail */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) +
|
||||||
|
wimage_rowbytes*image_height)))
|
||||||
|
{
|
||||||
|
return 4; /* fail */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Initialize the DIB. Negative height means to use top-down BMP ordering
|
||||||
|
(must be uncompressed, but that's what we want). Bit count of 1, 4 or 8
|
||||||
|
implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values
|
||||||
|
directly => wimage_data begins immediately after BMP header.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
memset(dib, 0, sizeof(BITMAPINFOHEADER));
|
||||||
|
bmih = (BITMAPINFOHEADER *)dib;
|
||||||
|
bmih->biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
bmih->biWidth = image_width;
|
||||||
|
bmih->biHeight = -((long)image_height);
|
||||||
|
bmih->biPlanes = 1;
|
||||||
|
bmih->biBitCount = 24;
|
||||||
|
bmih->biCompression = 0;
|
||||||
|
wimage_data = dib + sizeof(BITMAPINFOHEADER);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Fill in background color (black by default); data are in BGR order.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
for (j = 0; j < image_height; ++j) {
|
||||||
|
dest = wimage_data + j*wimage_rowbytes;
|
||||||
|
for (i = image_width; i > 0; --i) {
|
||||||
|
*dest++ = bg_blue;
|
||||||
|
*dest++ = bg_green;
|
||||||
|
*dest++ = bg_red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Set the window parameters.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
memset(&wndclass, 0, sizeof(wndclass));
|
||||||
|
|
||||||
|
wndclass.cbSize = sizeof(wndclass);
|
||||||
|
wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wndclass.lpfnWndProc = rpng_win_wndproc;
|
||||||
|
wndclass.hInstance = hInst;
|
||||||
|
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
|
||||||
|
wndclass.lpszMenuName = NULL;
|
||||||
|
wndclass.lpszClassName = progname;
|
||||||
|
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
|
||||||
|
RegisterClassEx(&wndclass);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Finally, create the window.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
extra_width = 2*(GetSystemMetrics(SM_CXBORDER) +
|
||||||
|
GetSystemMetrics(SM_CXDLGFRAME));
|
||||||
|
extra_height = 2*(GetSystemMetrics(SM_CYBORDER) +
|
||||||
|
GetSystemMetrics(SM_CYDLGFRAME)) +
|
||||||
|
GetSystemMetrics(SM_CYCAPTION);
|
||||||
|
|
||||||
|
global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, image_width+extra_width,
|
||||||
|
image_height+extra_height, NULL, NULL, hInst, NULL);
|
||||||
|
|
||||||
|
ShowWindow(global_hwnd, showmode);
|
||||||
|
UpdateWindow(global_hwnd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} /* end function rpng_win_create_window() */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int rpng_win_display_image()
|
||||||
|
{
|
||||||
|
uch *src, *dest;
|
||||||
|
uch r, g, b, a;
|
||||||
|
ulg i, row, lastrow;
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
|
|
||||||
|
Trace((stderr, "beginning display loop (image_channels == %d)\n",
|
||||||
|
image_channels))
|
||||||
|
Trace((stderr, "(width = %ld, rowbytes = %ld, wimage_rowbytes = %d)\n",
|
||||||
|
image_width, image_rowbytes, wimage_rowbytes))
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Blast image data to buffer. This whole routine takes place before the
|
||||||
|
message loop begins, so there's no real point in any pseudo-progressive
|
||||||
|
display...
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
for (lastrow = row = 0; row < image_height; ++row) {
|
||||||
|
src = image_data + row*image_rowbytes;
|
||||||
|
dest = wimage_data + row*wimage_rowbytes;
|
||||||
|
if (image_channels == 3) {
|
||||||
|
for (i = image_width; i > 0; --i) {
|
||||||
|
r = *src++;
|
||||||
|
g = *src++;
|
||||||
|
b = *src++;
|
||||||
|
*dest++ = b;
|
||||||
|
*dest++ = g; /* note reverse order */
|
||||||
|
*dest++ = r;
|
||||||
|
}
|
||||||
|
} else /* if (image_channels == 4) */ {
|
||||||
|
for (i = image_width; i > 0; --i) {
|
||||||
|
r = *src++;
|
||||||
|
g = *src++;
|
||||||
|
b = *src++;
|
||||||
|
a = *src++;
|
||||||
|
if (a == 255) {
|
||||||
|
*dest++ = b;
|
||||||
|
*dest++ = g;
|
||||||
|
*dest++ = r;
|
||||||
|
} else if (a == 0) {
|
||||||
|
*dest++ = bg_blue;
|
||||||
|
*dest++ = bg_green;
|
||||||
|
*dest++ = bg_red;
|
||||||
|
} else {
|
||||||
|
/* this macro (copied from png.h) composites the
|
||||||
|
* foreground and background values and puts the
|
||||||
|
* result into the first argument; there are no
|
||||||
|
* side effects with the first argument */
|
||||||
|
alpha_composite(*dest++, b, a, bg_blue);
|
||||||
|
alpha_composite(*dest++, g, a, bg_green);
|
||||||
|
alpha_composite(*dest++, r, a, bg_red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* display after every 16 lines */
|
||||||
|
if (((row+1) & 0xf) == 0) {
|
||||||
|
rect.left = 0L;
|
||||||
|
rect.top = (LONG)lastrow;
|
||||||
|
rect.right = (LONG)image_width; /* possibly off by one? */
|
||||||
|
rect.bottom = (LONG)lastrow + 16L; /* possibly off by one? */
|
||||||
|
InvalidateRect(global_hwnd, &rect, FALSE);
|
||||||
|
UpdateWindow(global_hwnd); /* similar to XFlush() */
|
||||||
|
lastrow = row + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace((stderr, "calling final image-flush routine\n"))
|
||||||
|
if (lastrow < image_height) {
|
||||||
|
rect.left = 0L;
|
||||||
|
rect.top = (LONG)lastrow;
|
||||||
|
rect.right = (LONG)image_width; /* possibly off by one? */
|
||||||
|
rect.bottom = (LONG)image_height; /* possibly off by one? */
|
||||||
|
InvalidateRect(global_hwnd, &rect, FALSE);
|
||||||
|
UpdateWindow(global_hwnd); /* similar to XFlush() */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
last param determines whether or not background is wiped before paint
|
||||||
|
InvalidateRect(global_hwnd, NULL, TRUE);
|
||||||
|
UpdateWindow(global_hwnd);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void rpng_win_cleanup()
|
||||||
|
{
|
||||||
|
if (image_data) {
|
||||||
|
free(image_data);
|
||||||
|
image_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dib) {
|
||||||
|
free(dib);
|
||||||
|
dib = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LRESULT CALLBACK rpng_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP)
|
||||||
|
{
|
||||||
|
HDC hdc;
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
switch (iMsg) {
|
||||||
|
case WM_CREATE:
|
||||||
|
/* one-time processing here, if any */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_PAINT:
|
||||||
|
hdc = BeginPaint(hwnd, &ps);
|
||||||
|
/* dest */
|
||||||
|
rc = StretchDIBits(hdc, 0, 0, image_width, image_height,
|
||||||
|
/* source */
|
||||||
|
0, 0, image_width, image_height,
|
||||||
|
wimage_data, (BITMAPINFO *)bmih,
|
||||||
|
/* iUsage: no clue */
|
||||||
|
0, SRCCOPY);
|
||||||
|
EndPaint(hwnd, &ps);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* wait for the user to tell us when to quit */
|
||||||
|
case WM_CHAR:
|
||||||
|
switch (wP) { /* only need one, so ignore repeat count */
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
case 0x1B: /* Esc key */
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_LBUTTONDOWN: /* another way of quitting */
|
||||||
|
case WM_DESTROY:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProc(hwnd, iMsg, wP, lP);
|
||||||
|
}
|
|
@ -0,0 +1,911 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rpng - simple PNG display program rpng-x.c
|
||||||
|
|
||||||
|
This program decodes and displays PNG images, with gamma correction and
|
||||||
|
optionally with a user-specified background color (in case the image has
|
||||||
|
transparency). It is very nearly the most basic PNG viewer possible.
|
||||||
|
This version is for the X Window System (tested by author under Unix and
|
||||||
|
by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking).
|
||||||
|
|
||||||
|
to do:
|
||||||
|
- 8-bit (colormapped) X support
|
||||||
|
- use %.1023s to simplify truncation of title-bar string?
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
- 1.01: initial public release
|
||||||
|
- 1.02: modified to allow abbreviated options; fixed long/ulong mis-
|
||||||
|
match; switched to png_jmpbuf() macro
|
||||||
|
- 1.10: added support for non-default visuals; fixed X pixel-conversion
|
||||||
|
- 1.11: added extra set of parentheses to png_jmpbuf() macro; fixed
|
||||||
|
command-line parsing bug
|
||||||
|
- 1.12: fixed some small X memory leaks (thanks to François Petitjean)
|
||||||
|
- 1.13: fixed XFreeGC() crash bug (thanks to Patrick Welche)
|
||||||
|
- 1.14: added support for X resources (thanks to Gerhard Niklasch)
|
||||||
|
- 2.00: dual-licensed (added GNU GPL)
|
||||||
|
- 2.01: fixed improper display of usage screen on PNG error(s)
|
||||||
|
- 2.02: Added "void(argc);" statement to quiet pedantic compiler warnings
|
||||||
|
about unused variable (GR-P)
|
||||||
|
- 2.03: check for integer overflow (Glenn R-P)
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2008, 2017 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define PROGNAME "rpng-x"
|
||||||
|
#define LONGNAME "Simple PNG Viewer for X"
|
||||||
|
#define VERSION "2.02 of 15 June 2014"
|
||||||
|
#define RESNAME "rpng" /* our X resource application name */
|
||||||
|
#define RESCLASS "Rpng" /* our X resource class name */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/Xos.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
|
/* #define DEBUG : this enables the Trace() macros */
|
||||||
|
|
||||||
|
#include "readpng.h" /* typedefs, common macros, readpng prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
/* could just include png.h, but this macro is the only thing we need
|
||||||
|
* (name and typedefs changed to local versions); note that side effects
|
||||||
|
* only happen with alpha (which could easily be avoided with
|
||||||
|
* "ush acopy = (alpha);") */
|
||||||
|
|
||||||
|
#define alpha_composite(composite, fg, alpha, bg) { \
|
||||||
|
ush temp = ((ush)(fg)*(ush)(alpha) + \
|
||||||
|
(ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
|
||||||
|
(composite) = (uch)((temp + (temp >> 8)) >> 8); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* local prototypes */
|
||||||
|
static int rpng_x_create_window(void);
|
||||||
|
static int rpng_x_display_image(void);
|
||||||
|
static void rpng_x_cleanup(void);
|
||||||
|
static int rpng_x_msb(ulg u32val);
|
||||||
|
|
||||||
|
|
||||||
|
static char titlebar[1024], *window_name = titlebar;
|
||||||
|
static char *appname = LONGNAME;
|
||||||
|
static char *icon_name = PROGNAME;
|
||||||
|
static char *res_name = RESNAME;
|
||||||
|
static char *res_class = RESCLASS;
|
||||||
|
static char *filename;
|
||||||
|
static FILE *infile;
|
||||||
|
|
||||||
|
static char *bgstr;
|
||||||
|
static uch bg_red=0, bg_green=0, bg_blue=0;
|
||||||
|
|
||||||
|
static double display_exponent;
|
||||||
|
|
||||||
|
static ulg image_width, image_height, image_rowbytes;
|
||||||
|
static int image_channels;
|
||||||
|
static uch *image_data;
|
||||||
|
|
||||||
|
/* X-specific variables */
|
||||||
|
static char *displayname;
|
||||||
|
static XImage *ximage;
|
||||||
|
static Display *display;
|
||||||
|
static int depth;
|
||||||
|
static Visual *visual;
|
||||||
|
static XVisualInfo *visual_list;
|
||||||
|
static int RShift, GShift, BShift;
|
||||||
|
static ulg RMask, GMask, BMask;
|
||||||
|
static Window window;
|
||||||
|
static GC gc;
|
||||||
|
static Colormap colormap;
|
||||||
|
|
||||||
|
static int have_nondefault_visual = FALSE;
|
||||||
|
static int have_colormap = FALSE;
|
||||||
|
static int have_window = FALSE;
|
||||||
|
static int have_gc = FALSE;
|
||||||
|
/*
|
||||||
|
ulg numcolors=0, pixels[256];
|
||||||
|
ush reds[256], greens[256], blues[256];
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
#ifdef sgi
|
||||||
|
char tmpline[80];
|
||||||
|
#endif
|
||||||
|
char *p;
|
||||||
|
int rc, alen, flen;
|
||||||
|
int error = 0;
|
||||||
|
int have_bg = FALSE;
|
||||||
|
double LUT_exponent; /* just the lookup table */
|
||||||
|
double CRT_exponent = 2.2; /* just the monitor */
|
||||||
|
double default_display_exponent; /* whole display system */
|
||||||
|
XEvent e;
|
||||||
|
KeySym k;
|
||||||
|
|
||||||
|
|
||||||
|
displayname = (char *)NULL;
|
||||||
|
filename = (char *)NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* First set the default value for our display-system exponent, i.e.,
|
||||||
|
* the product of the CRT exponent and the exponent corresponding to
|
||||||
|
* the frame-buffer's lookup table (LUT), if any. This is not an
|
||||||
|
* exhaustive list of LUT values (e.g., OpenStep has a lot of weird
|
||||||
|
* ones), but it should cover 99% of the current possibilities. */
|
||||||
|
|
||||||
|
#if defined(NeXT)
|
||||||
|
LUT_exponent = 1.0 / 2.2;
|
||||||
|
/*
|
||||||
|
if (some_next_function_that_returns_gamma(&next_gamma))
|
||||||
|
LUT_exponent = 1.0 / next_gamma;
|
||||||
|
*/
|
||||||
|
#elif defined(sgi)
|
||||||
|
LUT_exponent = 1.0 / 1.7;
|
||||||
|
/* there doesn't seem to be any documented function to get the
|
||||||
|
* "gamma" value, so we do it the hard way */
|
||||||
|
infile = fopen("/etc/config/system.glGammaVal", "r");
|
||||||
|
if (infile) {
|
||||||
|
double sgi_gamma;
|
||||||
|
|
||||||
|
fgets(tmpline, 80, infile);
|
||||||
|
fclose(infile);
|
||||||
|
sgi_gamma = atof(tmpline);
|
||||||
|
if (sgi_gamma > 0.0)
|
||||||
|
LUT_exponent = 1.0 / sgi_gamma;
|
||||||
|
}
|
||||||
|
#elif defined(Macintosh)
|
||||||
|
LUT_exponent = 1.8 / 2.61;
|
||||||
|
/*
|
||||||
|
if (some_mac_function_that_returns_gamma(&mac_gamma))
|
||||||
|
LUT_exponent = mac_gamma / 2.61;
|
||||||
|
*/
|
||||||
|
#else
|
||||||
|
LUT_exponent = 1.0; /* assume no LUT: most PCs */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
|
||||||
|
default_display_exponent = LUT_exponent * CRT_exponent;
|
||||||
|
|
||||||
|
|
||||||
|
/* If the user has set the SCREEN_GAMMA environment variable as suggested
|
||||||
|
* (somewhat imprecisely) in the libpng documentation, use that; otherwise
|
||||||
|
* use the default value we just calculated. Either way, the user may
|
||||||
|
* override this via a command-line option. */
|
||||||
|
|
||||||
|
if ((p = getenv("SCREEN_GAMMA")) != NULL)
|
||||||
|
display_exponent = atof(p);
|
||||||
|
else
|
||||||
|
display_exponent = default_display_exponent;
|
||||||
|
|
||||||
|
|
||||||
|
/* Now parse the command line for options and the PNG filename. */
|
||||||
|
|
||||||
|
while (*++argv && !error) {
|
||||||
|
if (!strncmp(*argv, "-display", 2)) {
|
||||||
|
if (!*++argv)
|
||||||
|
++error;
|
||||||
|
else
|
||||||
|
displayname = *argv;
|
||||||
|
} else if (!strncmp(*argv, "-gamma", 2)) {
|
||||||
|
if (!*++argv)
|
||||||
|
++error;
|
||||||
|
else {
|
||||||
|
display_exponent = atof(*argv);
|
||||||
|
if (display_exponent <= 0.0)
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
} else if (!strncmp(*argv, "-bgcolor", 2)) {
|
||||||
|
if (!*++argv)
|
||||||
|
++error;
|
||||||
|
else {
|
||||||
|
bgstr = *argv;
|
||||||
|
if (strlen(bgstr) != 7 || bgstr[0] != '#')
|
||||||
|
++error;
|
||||||
|
else
|
||||||
|
have_bg = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (**argv != '-') {
|
||||||
|
filename = *argv;
|
||||||
|
if (argv[1]) /* shouldn't be any more args after filename */
|
||||||
|
++error;
|
||||||
|
} else
|
||||||
|
++error; /* not expecting any other options */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filename)
|
||||||
|
++error;
|
||||||
|
|
||||||
|
|
||||||
|
/* print usage screen if any errors up to this point */
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
|
||||||
|
readpng_version_info();
|
||||||
|
fprintf(stderr, "\n"
|
||||||
|
"Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
|
||||||
|
" xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
|
||||||
|
" exp \ttransfer-function exponent (``gamma'') of the display\n"
|
||||||
|
"\t\t system in floating-point format (e.g., ``%.1f''); equal\n",
|
||||||
|
PROGNAME, default_display_exponent);
|
||||||
|
|
||||||
|
fprintf(stderr, "\n"
|
||||||
|
"\t\t to the product of the lookup-table exponent (varies)\n"
|
||||||
|
"\t\t and the CRT exponent (usually 2.2); must be positive\n"
|
||||||
|
" bg \tdesired background color in 7-character hex RGB format\n"
|
||||||
|
"\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
|
||||||
|
"\t\t used with transparent images\n"
|
||||||
|
"\nPress Q, Esc or mouse button 1 (within image window, after image\n"
|
||||||
|
"is displayed) to quit.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!(infile = fopen(filename, "rb"))) {
|
||||||
|
fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
|
||||||
|
++error;
|
||||||
|
} else {
|
||||||
|
if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
|
||||||
|
switch (rc) {
|
||||||
|
case 1:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": [%s] is not a PNG file: incorrect signature\n",
|
||||||
|
filename);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": [%s] has bad IHDR (libpng longjmp)\n", filename);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(stderr, PROGNAME ": insufficient memory\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": unknown readpng_init() error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++error;
|
||||||
|
} else {
|
||||||
|
display = XOpenDisplay(displayname);
|
||||||
|
if (!display) {
|
||||||
|
readpng_cleanup(TRUE);
|
||||||
|
fprintf(stderr, PROGNAME ": can't open X display [%s]\n",
|
||||||
|
displayname? displayname : "default");
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error)
|
||||||
|
fclose(infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
fprintf(stderr, PROGNAME ": aborting.\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set the title-bar string, but make sure buffer doesn't overflow */
|
||||||
|
|
||||||
|
alen = strlen(appname);
|
||||||
|
flen = strlen(filename);
|
||||||
|
if (alen + flen + 3 > 1023)
|
||||||
|
sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
|
||||||
|
else
|
||||||
|
sprintf(titlebar, "%s: %s", appname, filename);
|
||||||
|
|
||||||
|
|
||||||
|
/* if the user didn't specify a background color on the command line,
|
||||||
|
* check for one in the PNG file--if not, the initialized values of 0
|
||||||
|
* (black) will be used */
|
||||||
|
|
||||||
|
if (have_bg) {
|
||||||
|
unsigned r, g, b; /* this approach quiets compiler warnings */
|
||||||
|
|
||||||
|
sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
|
||||||
|
bg_red = (uch)r;
|
||||||
|
bg_green = (uch)g;
|
||||||
|
bg_blue = (uch)b;
|
||||||
|
} else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
|
||||||
|
readpng_cleanup(TRUE);
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": libpng error while checking for background color\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* do the basic X initialization stuff, make the window and fill it
|
||||||
|
* with the background color */
|
||||||
|
|
||||||
|
if (rpng_x_create_window())
|
||||||
|
exit(2);
|
||||||
|
|
||||||
|
|
||||||
|
/* decode the image, all at once */
|
||||||
|
|
||||||
|
Trace((stderr, "calling readpng_get_image()\n"))
|
||||||
|
image_data = readpng_get_image(display_exponent, &image_channels,
|
||||||
|
&image_rowbytes);
|
||||||
|
Trace((stderr, "done with readpng_get_image()\n"))
|
||||||
|
|
||||||
|
|
||||||
|
/* done with PNG file, so clean up to minimize memory usage (but do NOT
|
||||||
|
* nuke image_data!) */
|
||||||
|
|
||||||
|
readpng_cleanup(FALSE);
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
if (!image_data) {
|
||||||
|
fprintf(stderr, PROGNAME ": unable to decode PNG image\n");
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* display image (composite with background if requested) */
|
||||||
|
|
||||||
|
Trace((stderr, "calling rpng_x_display_image()\n"))
|
||||||
|
if (rpng_x_display_image()) {
|
||||||
|
free(image_data);
|
||||||
|
exit(4);
|
||||||
|
}
|
||||||
|
Trace((stderr, "done with rpng_x_display_image()\n"))
|
||||||
|
|
||||||
|
|
||||||
|
/* wait for the user to tell us when to quit */
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
do
|
||||||
|
XNextEvent(display, &e);
|
||||||
|
while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
|
||||||
|
!(e.type == KeyPress && /* v--- or 1 for shifted keys */
|
||||||
|
((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
|
||||||
|
|
||||||
|
|
||||||
|
/* OK, we're done: clean up all image and X resources and go away */
|
||||||
|
|
||||||
|
rpng_x_cleanup();
|
||||||
|
|
||||||
|
(void)argc; /* Unused */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int rpng_x_create_window(void)
|
||||||
|
{
|
||||||
|
uch *xdata;
|
||||||
|
int need_colormap = FALSE;
|
||||||
|
int screen, pad;
|
||||||
|
ulg bg_pixel = 0L;
|
||||||
|
ulg attrmask;
|
||||||
|
Window root;
|
||||||
|
XEvent e;
|
||||||
|
XGCValues gcvalues;
|
||||||
|
XSetWindowAttributes attr;
|
||||||
|
XTextProperty windowName, *pWindowName = &windowName;
|
||||||
|
XTextProperty iconName, *pIconName = &iconName;
|
||||||
|
XVisualInfo visual_info;
|
||||||
|
XSizeHints *size_hints;
|
||||||
|
XWMHints *wm_hints;
|
||||||
|
XClassHint *class_hints;
|
||||||
|
|
||||||
|
|
||||||
|
screen = DefaultScreen(display);
|
||||||
|
depth = DisplayPlanes(display, screen);
|
||||||
|
root = RootWindow(display, screen);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
XSynchronize(display, True);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* GRR: add 8-bit support */
|
||||||
|
if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n",
|
||||||
|
depth);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMatchVisualInfo(display, screen, depth,
|
||||||
|
(depth == 8)? PseudoColor : TrueColor, &visual_info);
|
||||||
|
visual = visual_info.visual;
|
||||||
|
#else
|
||||||
|
if (depth != 16 && depth != 24 && depth != 32) {
|
||||||
|
int visuals_matched = 0;
|
||||||
|
|
||||||
|
Trace((stderr, "default depth is %d: checking other visuals\n",
|
||||||
|
depth))
|
||||||
|
|
||||||
|
/* 24-bit first */
|
||||||
|
visual_info.screen = screen;
|
||||||
|
visual_info.depth = 24;
|
||||||
|
visual_list = XGetVisualInfo(display,
|
||||||
|
VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
|
||||||
|
if (visuals_matched == 0) {
|
||||||
|
/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
|
||||||
|
fprintf(stderr, "default screen depth %d not supported, and no"
|
||||||
|
" 24-bit visuals found\n", depth);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
|
||||||
|
visuals_matched))
|
||||||
|
visual = visual_list[0].visual;
|
||||||
|
depth = visual_list[0].depth;
|
||||||
|
/*
|
||||||
|
colormap_size = visual_list[0].colormap_size;
|
||||||
|
visual_class = visual->class;
|
||||||
|
visualID = XVisualIDFromVisual(visual);
|
||||||
|
*/
|
||||||
|
have_nondefault_visual = TRUE;
|
||||||
|
need_colormap = TRUE;
|
||||||
|
} else {
|
||||||
|
XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
|
||||||
|
visual = visual_info.visual;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RMask = visual->red_mask;
|
||||||
|
GMask = visual->green_mask;
|
||||||
|
BMask = visual->blue_mask;
|
||||||
|
|
||||||
|
/* GRR: add/check 8-bit support */
|
||||||
|
if (depth == 8 || need_colormap) {
|
||||||
|
colormap = XCreateColormap(display, root, visual, AllocNone);
|
||||||
|
if (!colormap) {
|
||||||
|
fprintf(stderr, "XCreateColormap() failed\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
have_colormap = TRUE;
|
||||||
|
}
|
||||||
|
if (depth == 15 || depth == 16) {
|
||||||
|
RShift = 15 - rpng_x_msb(RMask); /* these are right-shifts */
|
||||||
|
GShift = 15 - rpng_x_msb(GMask);
|
||||||
|
BShift = 15 - rpng_x_msb(BMask);
|
||||||
|
} else if (depth > 16) {
|
||||||
|
#define NO_24BIT_MASKS
|
||||||
|
#ifdef NO_24BIT_MASKS
|
||||||
|
RShift = rpng_x_msb(RMask) - 7; /* these are left-shifts */
|
||||||
|
GShift = rpng_x_msb(GMask) - 7;
|
||||||
|
BShift = rpng_x_msb(BMask) - 7;
|
||||||
|
#else
|
||||||
|
RShift = 7 - rpng_x_msb(RMask); /* these are right-shifts, too */
|
||||||
|
GShift = 7 - rpng_x_msb(GMask);
|
||||||
|
BShift = 7 - rpng_x_msb(BMask);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
|
||||||
|
fprintf(stderr, "rpng internal logic error: negative X shift(s)!\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Finally, create the window.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
attr.backing_store = Always;
|
||||||
|
attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
|
||||||
|
attrmask = CWBackingStore | CWEventMask;
|
||||||
|
if (have_nondefault_visual) {
|
||||||
|
attr.colormap = colormap;
|
||||||
|
attr.background_pixel = 0;
|
||||||
|
attr.border_pixel = 1;
|
||||||
|
attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0,
|
||||||
|
depth, InputOutput, visual, attrmask, &attr);
|
||||||
|
|
||||||
|
if (window == None) {
|
||||||
|
fprintf(stderr, "XCreateWindow() failed\n");
|
||||||
|
return 2;
|
||||||
|
} else
|
||||||
|
have_window = TRUE;
|
||||||
|
|
||||||
|
if (depth == 8)
|
||||||
|
XSetWindowColormap(display, window, colormap);
|
||||||
|
|
||||||
|
if (!XStringListToTextProperty(&window_name, 1, pWindowName))
|
||||||
|
pWindowName = NULL;
|
||||||
|
if (!XStringListToTextProperty(&icon_name, 1, pIconName))
|
||||||
|
pIconName = NULL;
|
||||||
|
|
||||||
|
/* OK if any hints allocation fails; XSetWMProperties() allows NULLs */
|
||||||
|
|
||||||
|
if ((size_hints = XAllocSizeHints()) != NULL) {
|
||||||
|
/* window will not be resizable */
|
||||||
|
size_hints->flags = PMinSize | PMaxSize;
|
||||||
|
size_hints->min_width = size_hints->max_width = (int)image_width;
|
||||||
|
size_hints->min_height = size_hints->max_height = (int)image_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((wm_hints = XAllocWMHints()) != NULL) {
|
||||||
|
wm_hints->initial_state = NormalState;
|
||||||
|
wm_hints->input = True;
|
||||||
|
/* wm_hints->icon_pixmap = icon_pixmap; */
|
||||||
|
wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((class_hints = XAllocClassHint()) != NULL) {
|
||||||
|
class_hints->res_name = res_name;
|
||||||
|
class_hints->res_class = res_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
|
||||||
|
size_hints, wm_hints, class_hints);
|
||||||
|
|
||||||
|
/* various properties and hints no longer needed; free memory */
|
||||||
|
if (pWindowName)
|
||||||
|
XFree(pWindowName->value);
|
||||||
|
if (pIconName)
|
||||||
|
XFree(pIconName->value);
|
||||||
|
if (size_hints)
|
||||||
|
XFree(size_hints);
|
||||||
|
if (wm_hints)
|
||||||
|
XFree(wm_hints);
|
||||||
|
if (class_hints)
|
||||||
|
XFree(class_hints);
|
||||||
|
|
||||||
|
XMapWindow(display, window);
|
||||||
|
|
||||||
|
gc = XCreateGC(display, window, 0, &gcvalues);
|
||||||
|
have_gc = TRUE;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Fill window with the specified background color.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
if (depth == 24 || depth == 32) {
|
||||||
|
bg_pixel = ((ulg)bg_red << RShift) |
|
||||||
|
((ulg)bg_green << GShift) |
|
||||||
|
((ulg)bg_blue << BShift);
|
||||||
|
} else if (depth == 16) {
|
||||||
|
bg_pixel = ((((ulg)bg_red << 8) >> RShift) & RMask) |
|
||||||
|
((((ulg)bg_green << 8) >> GShift) & GMask) |
|
||||||
|
((((ulg)bg_blue << 8) >> BShift) & BMask);
|
||||||
|
} else /* depth == 8 */ {
|
||||||
|
|
||||||
|
/* GRR: add 8-bit support */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
XSetForeground(display, gc, bg_pixel);
|
||||||
|
XFillRectangle(display, window, gc, 0, 0, image_width, image_height);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Wait for first Expose event to do any drawing, then flush.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
do
|
||||||
|
XNextEvent(display, &e);
|
||||||
|
while (e.type != Expose || e.xexpose.count);
|
||||||
|
|
||||||
|
XFlush(display);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
Allocate memory for the X- and display-specific version of the image.
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
if (depth == 24 || depth == 32) {
|
||||||
|
xdata = (uch *)malloc(4*image_width*image_height);
|
||||||
|
pad = 32;
|
||||||
|
} else if (depth == 16) {
|
||||||
|
xdata = (uch *)malloc(2*image_width*image_height);
|
||||||
|
pad = 16;
|
||||||
|
} else /* depth == 8 */ {
|
||||||
|
xdata = (uch *)malloc(image_width*image_height);
|
||||||
|
pad = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xdata) {
|
||||||
|
fprintf(stderr, PROGNAME ": unable to allocate image memory\n");
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
|
||||||
|
(char *)xdata, image_width, image_height, pad, 0);
|
||||||
|
|
||||||
|
if (!ximage) {
|
||||||
|
fprintf(stderr, PROGNAME ": XCreateImage() failed\n");
|
||||||
|
free(xdata);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* to avoid testing the byte order every pixel (or doubling the size of
|
||||||
|
* the drawing routine with a giant if-test), we arbitrarily set the byte
|
||||||
|
* order to MSBFirst and let Xlib worry about inverting things on little-
|
||||||
|
* endian machines (like Linux/x86, old VAXen, etc.)--this is not the most
|
||||||
|
* efficient approach (the giant if-test would be better), but in the
|
||||||
|
* interest of clarity, we take the easy way out... */
|
||||||
|
|
||||||
|
ximage->byte_order = MSBFirst;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} /* end function rpng_x_create_window() */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int rpng_x_display_image(void)
|
||||||
|
{
|
||||||
|
uch *src;
|
||||||
|
char *dest;
|
||||||
|
uch r, g, b, a;
|
||||||
|
ulg i, row, lastrow = 0;
|
||||||
|
ulg pixel;
|
||||||
|
int ximage_rowbytes = ximage->bytes_per_line;
|
||||||
|
/* int bpp = ximage->bits_per_pixel; */
|
||||||
|
|
||||||
|
|
||||||
|
Trace((stderr, "beginning display loop (image_channels == %d)\n",
|
||||||
|
image_channels))
|
||||||
|
Trace((stderr, " (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n",
|
||||||
|
image_width, image_rowbytes, ximage_rowbytes))
|
||||||
|
Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel))
|
||||||
|
Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst?
|
||||||
|
"MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
|
||||||
|
|
||||||
|
if (depth == 24 || depth == 32) {
|
||||||
|
ulg red, green, blue;
|
||||||
|
|
||||||
|
for (lastrow = row = 0; row < image_height; ++row) {
|
||||||
|
src = image_data + row*image_rowbytes;
|
||||||
|
dest = ximage->data + row*ximage_rowbytes;
|
||||||
|
if (image_channels == 3) {
|
||||||
|
for (i = image_width; i > 0; --i) {
|
||||||
|
red = *src++;
|
||||||
|
green = *src++;
|
||||||
|
blue = *src++;
|
||||||
|
#ifdef NO_24BIT_MASKS
|
||||||
|
pixel = (red << RShift) |
|
||||||
|
(green << GShift) |
|
||||||
|
(blue << BShift);
|
||||||
|
/* recall that we set ximage->byte_order = MSBFirst above */
|
||||||
|
/* GRR BUG: this assumes bpp == 32, but may be 24: */
|
||||||
|
*dest++ = (char)((pixel >> 24) & 0xff);
|
||||||
|
*dest++ = (char)((pixel >> 16) & 0xff);
|
||||||
|
*dest++ = (char)((pixel >> 8) & 0xff);
|
||||||
|
*dest++ = (char)( pixel & 0xff);
|
||||||
|
#else
|
||||||
|
red = (RShift < 0)? red << (-RShift) : red >> RShift;
|
||||||
|
green = (GShift < 0)? green << (-GShift) : green >> GShift;
|
||||||
|
blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
|
||||||
|
pixel = (red & RMask) | (green & GMask) | (blue & BMask);
|
||||||
|
/* recall that we set ximage->byte_order = MSBFirst above */
|
||||||
|
*dest++ = (char)((pixel >> 24) & 0xff);
|
||||||
|
*dest++ = (char)((pixel >> 16) & 0xff);
|
||||||
|
*dest++ = (char)((pixel >> 8) & 0xff);
|
||||||
|
*dest++ = (char)( pixel & 0xff);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else /* if (image_channels == 4) */ {
|
||||||
|
for (i = image_width; i > 0; --i) {
|
||||||
|
r = *src++;
|
||||||
|
g = *src++;
|
||||||
|
b = *src++;
|
||||||
|
a = *src++;
|
||||||
|
if (a == 255) {
|
||||||
|
red = r;
|
||||||
|
green = g;
|
||||||
|
blue = b;
|
||||||
|
} else if (a == 0) {
|
||||||
|
red = bg_red;
|
||||||
|
green = bg_green;
|
||||||
|
blue = bg_blue;
|
||||||
|
} else {
|
||||||
|
/* this macro (from png.h) composites the foreground
|
||||||
|
* and background values and puts the result into the
|
||||||
|
* first argument */
|
||||||
|
alpha_composite(red, r, a, bg_red);
|
||||||
|
alpha_composite(green, g, a, bg_green);
|
||||||
|
alpha_composite(blue, b, a, bg_blue);
|
||||||
|
}
|
||||||
|
pixel = (red << RShift) |
|
||||||
|
(green << GShift) |
|
||||||
|
(blue << BShift);
|
||||||
|
/* recall that we set ximage->byte_order = MSBFirst above */
|
||||||
|
*dest++ = (char)((pixel >> 24) & 0xff);
|
||||||
|
*dest++ = (char)((pixel >> 16) & 0xff);
|
||||||
|
*dest++ = (char)((pixel >> 8) & 0xff);
|
||||||
|
*dest++ = (char)( pixel & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* display after every 16 lines */
|
||||||
|
if (((row+1) & 0xf) == 0) {
|
||||||
|
XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
|
||||||
|
(int)lastrow, image_width, 16);
|
||||||
|
XFlush(display);
|
||||||
|
lastrow = row + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (depth == 16) {
|
||||||
|
ush red, green, blue;
|
||||||
|
|
||||||
|
for (lastrow = row = 0; row < image_height; ++row) {
|
||||||
|
src = image_data + row*image_rowbytes;
|
||||||
|
dest = ximage->data + row*ximage_rowbytes;
|
||||||
|
if (image_channels == 3) {
|
||||||
|
for (i = image_width; i > 0; --i) {
|
||||||
|
red = ((ush)(*src) << 8);
|
||||||
|
++src;
|
||||||
|
green = ((ush)(*src) << 8);
|
||||||
|
++src;
|
||||||
|
blue = ((ush)(*src) << 8);
|
||||||
|
++src;
|
||||||
|
pixel = ((red >> RShift) & RMask) |
|
||||||
|
((green >> GShift) & GMask) |
|
||||||
|
((blue >> BShift) & BMask);
|
||||||
|
/* recall that we set ximage->byte_order = MSBFirst above */
|
||||||
|
*dest++ = (char)((pixel >> 8) & 0xff);
|
||||||
|
*dest++ = (char)( pixel & 0xff);
|
||||||
|
}
|
||||||
|
} else /* if (image_channels == 4) */ {
|
||||||
|
for (i = image_width; i > 0; --i) {
|
||||||
|
r = *src++;
|
||||||
|
g = *src++;
|
||||||
|
b = *src++;
|
||||||
|
a = *src++;
|
||||||
|
if (a == 255) {
|
||||||
|
red = ((ush)r << 8);
|
||||||
|
green = ((ush)g << 8);
|
||||||
|
blue = ((ush)b << 8);
|
||||||
|
} else if (a == 0) {
|
||||||
|
red = ((ush)bg_red << 8);
|
||||||
|
green = ((ush)bg_green << 8);
|
||||||
|
blue = ((ush)bg_blue << 8);
|
||||||
|
} else {
|
||||||
|
/* this macro (from png.h) composites the foreground
|
||||||
|
* and background values and puts the result back into
|
||||||
|
* the first argument (== fg byte here: safe) */
|
||||||
|
alpha_composite(r, r, a, bg_red);
|
||||||
|
alpha_composite(g, g, a, bg_green);
|
||||||
|
alpha_composite(b, b, a, bg_blue);
|
||||||
|
red = ((ush)r << 8);
|
||||||
|
green = ((ush)g << 8);
|
||||||
|
blue = ((ush)b << 8);
|
||||||
|
}
|
||||||
|
pixel = ((red >> RShift) & RMask) |
|
||||||
|
((green >> GShift) & GMask) |
|
||||||
|
((blue >> BShift) & BMask);
|
||||||
|
/* recall that we set ximage->byte_order = MSBFirst above */
|
||||||
|
*dest++ = (char)((pixel >> 8) & 0xff);
|
||||||
|
*dest++ = (char)( pixel & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* display after every 16 lines */
|
||||||
|
if (((row+1) & 0xf) == 0) {
|
||||||
|
XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
|
||||||
|
(int)lastrow, image_width, 16);
|
||||||
|
XFlush(display);
|
||||||
|
lastrow = row + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else /* depth == 8 */ {
|
||||||
|
|
||||||
|
/* GRR: add 8-bit support */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace((stderr, "calling final XPutImage()\n"))
|
||||||
|
if (lastrow < image_height) {
|
||||||
|
XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
|
||||||
|
(int)lastrow, image_width, image_height-lastrow);
|
||||||
|
XFlush(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void rpng_x_cleanup(void)
|
||||||
|
{
|
||||||
|
if (image_data) {
|
||||||
|
free(image_data);
|
||||||
|
image_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ximage) {
|
||||||
|
if (ximage->data) {
|
||||||
|
free(ximage->data); /* we allocated it, so we free it */
|
||||||
|
ximage->data = (char *)NULL; /* instead of XDestroyImage() */
|
||||||
|
}
|
||||||
|
XDestroyImage(ximage);
|
||||||
|
ximage = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_gc)
|
||||||
|
XFreeGC(display, gc);
|
||||||
|
|
||||||
|
if (have_window)
|
||||||
|
XDestroyWindow(display, window);
|
||||||
|
|
||||||
|
if (have_colormap)
|
||||||
|
XFreeColormap(display, colormap);
|
||||||
|
|
||||||
|
if (have_nondefault_visual)
|
||||||
|
XFree(visual_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int rpng_x_msb(ulg u32val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 31; i >= 0; --i) {
|
||||||
|
if (u32val & 0x80000000L)
|
||||||
|
break;
|
||||||
|
u32val <<= 1;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,865 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wpng - simple PNG-writing program wpng.c
|
||||||
|
|
||||||
|
This program converts certain NetPBM binary files (grayscale and RGB,
|
||||||
|
maxval = 255) to PNG. Non-interlaced PNGs are written progressively;
|
||||||
|
interlaced PNGs are read and written in one memory-intensive blast.
|
||||||
|
|
||||||
|
Thanks to Jean-loup Gailly for providing the necessary trick to read
|
||||||
|
interactive text from the keyboard while stdin is redirected. Thanks
|
||||||
|
to Cosmin Truta for Cygwin fixes.
|
||||||
|
|
||||||
|
NOTE: includes provisional support for PNM type "8" (portable alphamap)
|
||||||
|
images, presumed to be a 32-bit interleaved RGBA format; no pro-
|
||||||
|
vision for possible interleaved grayscale+alpha (16-bit) format.
|
||||||
|
THIS IS UNLIKELY TO BECOME AN OFFICIAL NETPBM ALPHA FORMAT!
|
||||||
|
|
||||||
|
to do:
|
||||||
|
- delete output file if quit before calling any writepng routines
|
||||||
|
- process backspace with -text option under DOS/Win? (currently get ^H)
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
- 1.01: initial public release
|
||||||
|
- 1.02: modified to allow abbreviated options
|
||||||
|
- 1.03: removed extraneous character from usage screen; fixed bug in
|
||||||
|
command-line parsing
|
||||||
|
- 1.04: fixed DOS/OS2/Win32 detection, including partial Cygwin fix
|
||||||
|
(see http://home.att.net/~perlspinr/diffs/GregBook_cygwin.diff)
|
||||||
|
- 2.00: dual-licensed (added GNU GPL)
|
||||||
|
- 2.01: check for integer overflow (Glenn R-P)
|
||||||
|
|
||||||
|
[REPORTED BUG (win32 only): "contrib/gregbook/wpng.c - cmd line
|
||||||
|
dose not work! In order to do something useful I needed to redirect
|
||||||
|
both input and output, with cygwin and with bcc32 as well. Under
|
||||||
|
Linux, the same wpng appears to work fine. I don't know what is
|
||||||
|
the problem."]
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2007, 2017 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define PROGNAME "wpng"
|
||||||
|
#define VERSION "2.00 of 2 June 2007"
|
||||||
|
#define APPNAME "Simple PGM/PPM/PAM to PNG Converter"
|
||||||
|
|
||||||
|
#if defined(__MSDOS__) || defined(__OS2__)
|
||||||
|
# define DOS_OS2_W32
|
||||||
|
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||||
|
# ifndef __GNUC__ /* treat Win32 native ports of gcc as Unix environments */
|
||||||
|
# define DOS_OS2_W32
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <setjmp.h> /* for jmpbuf declaration in writepng.h */
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef DOS_OS2_W32
|
||||||
|
# include <io.h> /* for isatty(), setmode() prototypes */
|
||||||
|
# include <fcntl.h> /* O_BINARY for fdopen() without text translation */
|
||||||
|
# ifdef __EMX__
|
||||||
|
# ifndef getch
|
||||||
|
# define getch() _read_kbd(0, 1, 0) /* need getche() */
|
||||||
|
# endif
|
||||||
|
# else /* !__EMX__ */
|
||||||
|
# ifdef __GO32__
|
||||||
|
# include <pc.h>
|
||||||
|
# define getch() getkey() /* GRR: need getche() */
|
||||||
|
# else
|
||||||
|
# include <conio.h> /* for getche() console input */
|
||||||
|
# endif
|
||||||
|
# endif /* ?__EMX__ */
|
||||||
|
# define FGETS(buf,len,stream) dos_kbd_gets(buf,len)
|
||||||
|
#else
|
||||||
|
# include <unistd.h> /* for isatty() prototype */
|
||||||
|
# define FGETS fgets
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* #define DEBUG : this enables the Trace() macros */
|
||||||
|
|
||||||
|
/* #define FORBID_LATIN1_CTRL : this requires the user to re-enter any
|
||||||
|
text that includes control characters discouraged by the PNG spec; text
|
||||||
|
that includes an escape character (27) must be re-entered regardless */
|
||||||
|
|
||||||
|
#include "writepng.h" /* typedefs, common macros, writepng prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* local prototypes */
|
||||||
|
|
||||||
|
static int wpng_isvalid_latin1(uch *p, int len);
|
||||||
|
static void wpng_cleanup(void);
|
||||||
|
|
||||||
|
#ifdef DOS_OS2_W32
|
||||||
|
static char *dos_kbd_gets(char *buf, int len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static mainprog_info wpng_info; /* lone global */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
#ifndef DOS_OS2_W32
|
||||||
|
FILE *keybd;
|
||||||
|
#endif
|
||||||
|
#ifdef sgi
|
||||||
|
FILE *tmpfile; /* or we could just use keybd, since no overlap */
|
||||||
|
char tmpline[80];
|
||||||
|
#endif
|
||||||
|
char *inname = NULL, outname[256];
|
||||||
|
char *p, pnmchar, pnmline[256];
|
||||||
|
char *bgstr, *textbuf = NULL;
|
||||||
|
ulg rowbytes;
|
||||||
|
int rc, len = 0;
|
||||||
|
int error = 0;
|
||||||
|
int text = FALSE;
|
||||||
|
int maxval;
|
||||||
|
double LUT_exponent; /* just the lookup table */
|
||||||
|
double CRT_exponent = 2.2; /* just the monitor */
|
||||||
|
double default_display_exponent; /* whole display system */
|
||||||
|
double default_gamma = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
wpng_info.infile = NULL;
|
||||||
|
wpng_info.outfile = NULL;
|
||||||
|
wpng_info.image_data = NULL;
|
||||||
|
wpng_info.row_pointers = NULL;
|
||||||
|
wpng_info.filter = FALSE;
|
||||||
|
wpng_info.interlaced = FALSE;
|
||||||
|
wpng_info.have_bg = FALSE;
|
||||||
|
wpng_info.have_time = FALSE;
|
||||||
|
wpng_info.have_text = 0;
|
||||||
|
wpng_info.gamma = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
/* First get the default value for our display-system exponent, i.e.,
|
||||||
|
* the product of the CRT exponent and the exponent corresponding to
|
||||||
|
* the frame-buffer's lookup table (LUT), if any. If the PNM image
|
||||||
|
* looks correct on the user's display system, its file gamma is the
|
||||||
|
* inverse of this value. (Note that this is not an exhaustive list
|
||||||
|
* of LUT values--e.g., OpenStep has a lot of weird ones--but it should
|
||||||
|
* cover 99% of the current possibilities. This section must ensure
|
||||||
|
* that default_display_exponent is positive.) */
|
||||||
|
|
||||||
|
#if defined(NeXT)
|
||||||
|
/* third-party utilities can modify the default LUT exponent */
|
||||||
|
LUT_exponent = 1.0 / 2.2;
|
||||||
|
/*
|
||||||
|
if (some_next_function_that_returns_gamma(&next_gamma))
|
||||||
|
LUT_exponent = 1.0 / next_gamma;
|
||||||
|
*/
|
||||||
|
#elif defined(sgi)
|
||||||
|
LUT_exponent = 1.0 / 1.7;
|
||||||
|
/* there doesn't seem to be any documented function to
|
||||||
|
* get the "gamma" value, so we do it the hard way */
|
||||||
|
tmpfile = fopen("/etc/config/system.glGammaVal", "r");
|
||||||
|
if (tmpfile) {
|
||||||
|
double sgi_gamma;
|
||||||
|
|
||||||
|
fgets(tmpline, 80, tmpfile);
|
||||||
|
fclose(tmpfile);
|
||||||
|
sgi_gamma = atof(tmpline);
|
||||||
|
if (sgi_gamma > 0.0)
|
||||||
|
LUT_exponent = 1.0 / sgi_gamma;
|
||||||
|
}
|
||||||
|
#elif defined(Macintosh)
|
||||||
|
LUT_exponent = 1.8 / 2.61;
|
||||||
|
/*
|
||||||
|
if (some_mac_function_that_returns_gamma(&mac_gamma))
|
||||||
|
LUT_exponent = mac_gamma / 2.61;
|
||||||
|
*/
|
||||||
|
#else
|
||||||
|
LUT_exponent = 1.0; /* assume no LUT: most PCs */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
|
||||||
|
default_display_exponent = LUT_exponent * CRT_exponent;
|
||||||
|
|
||||||
|
|
||||||
|
/* If the user has set the SCREEN_GAMMA environment variable as suggested
|
||||||
|
* (somewhat imprecisely) in the libpng documentation, use that; otherwise
|
||||||
|
* use the default value we just calculated. Either way, the user may
|
||||||
|
* override this via a command-line option. */
|
||||||
|
|
||||||
|
if ((p = getenv("SCREEN_GAMMA")) != NULL) {
|
||||||
|
double exponent = atof(p);
|
||||||
|
|
||||||
|
if (exponent > 0.0)
|
||||||
|
default_gamma = 1.0 / exponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (default_gamma == 0.0)
|
||||||
|
default_gamma = 1.0 / default_display_exponent;
|
||||||
|
|
||||||
|
|
||||||
|
/* Now parse the command line for options and the PNM filename. */
|
||||||
|
|
||||||
|
while (*++argv && !error) {
|
||||||
|
if (!strncmp(*argv, "-i", 2)) {
|
||||||
|
wpng_info.interlaced = TRUE;
|
||||||
|
} else if (!strncmp(*argv, "-time", 3)) {
|
||||||
|
wpng_info.modtime = time(NULL);
|
||||||
|
wpng_info.have_time = TRUE;
|
||||||
|
} else if (!strncmp(*argv, "-text", 3)) {
|
||||||
|
text = TRUE;
|
||||||
|
} else if (!strncmp(*argv, "-gamma", 2)) {
|
||||||
|
if (!*++argv)
|
||||||
|
++error;
|
||||||
|
else {
|
||||||
|
wpng_info.gamma = atof(*argv);
|
||||||
|
if (wpng_info.gamma <= 0.0)
|
||||||
|
++error;
|
||||||
|
else if (wpng_info.gamma > 1.01)
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
" warning: file gammas are usually less than 1.0\n");
|
||||||
|
}
|
||||||
|
} else if (!strncmp(*argv, "-bgcolor", 4)) {
|
||||||
|
if (!*++argv)
|
||||||
|
++error;
|
||||||
|
else {
|
||||||
|
bgstr = *argv;
|
||||||
|
if (strlen(bgstr) != 7 || bgstr[0] != '#')
|
||||||
|
++error;
|
||||||
|
else {
|
||||||
|
unsigned r, g, b; /* this way quiets compiler warnings */
|
||||||
|
|
||||||
|
sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
|
||||||
|
wpng_info.bg_red = (uch)r;
|
||||||
|
wpng_info.bg_green = (uch)g;
|
||||||
|
wpng_info.bg_blue = (uch)b;
|
||||||
|
wpng_info.have_bg = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (**argv != '-') {
|
||||||
|
inname = *argv;
|
||||||
|
if (argv[1]) /* shouldn't be any more args after filename */
|
||||||
|
++error;
|
||||||
|
} else
|
||||||
|
++error; /* not expecting any other options */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* open the input and output files, or register an error and abort */
|
||||||
|
|
||||||
|
if (!inname) {
|
||||||
|
if (isatty(0)) {
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": must give input filename or provide image data via stdin\n");
|
||||||
|
++error;
|
||||||
|
} else {
|
||||||
|
#ifdef DOS_OS2_W32
|
||||||
|
/* some buggy C libraries require BOTH setmode() and fdopen(bin) */
|
||||||
|
setmode(fileno(stdin), O_BINARY);
|
||||||
|
setmode(fileno(stdout), O_BINARY);
|
||||||
|
#endif
|
||||||
|
if ((wpng_info.infile = fdopen(fileno(stdin), "rb")) == NULL) {
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": unable to reopen stdin in binary mode\n");
|
||||||
|
++error;
|
||||||
|
} else
|
||||||
|
if ((wpng_info.outfile = fdopen(fileno(stdout), "wb")) == NULL) {
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": unable to reopen stdout in binary mode\n");
|
||||||
|
fclose(wpng_info.infile);
|
||||||
|
++error;
|
||||||
|
} else
|
||||||
|
wpng_info.filter = TRUE;
|
||||||
|
}
|
||||||
|
} else if ((len = strlen(inname)) > 250) {
|
||||||
|
fprintf(stderr, PROGNAME ": input filename is too long [%d chars]\n",
|
||||||
|
len);
|
||||||
|
++error;
|
||||||
|
} else if (!(wpng_info.infile = fopen(inname, "rb"))) {
|
||||||
|
fprintf(stderr, PROGNAME ": can't open input file [%s]\n", inname);
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
fgets(pnmline, 256, wpng_info.infile);
|
||||||
|
if (pnmline[0] != 'P' || ((pnmchar = pnmline[1]) != '5' &&
|
||||||
|
pnmchar != '6' && pnmchar != '8'))
|
||||||
|
{
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": input file [%s] is not a binary PGM, PPM or PAM file\n",
|
||||||
|
inname);
|
||||||
|
++error;
|
||||||
|
} else {
|
||||||
|
wpng_info.pnmtype = (int)(pnmchar - '0');
|
||||||
|
if (wpng_info.pnmtype != 8)
|
||||||
|
wpng_info.have_bg = FALSE; /* no need for bg if opaque */
|
||||||
|
do {
|
||||||
|
fgets(pnmline, 256, wpng_info.infile); /* lose any comments */
|
||||||
|
} while (pnmline[0] == '#');
|
||||||
|
sscanf(pnmline, "%ld %ld", &wpng_info.width, &wpng_info.height);
|
||||||
|
do {
|
||||||
|
fgets(pnmline, 256, wpng_info.infile); /* more comment lines */
|
||||||
|
} while (pnmline[0] == '#');
|
||||||
|
sscanf(pnmline, "%d", &maxval);
|
||||||
|
if (wpng_info.width <= 0L || wpng_info.height <= 0L ||
|
||||||
|
maxval != 255)
|
||||||
|
{
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": only positive width/height, maxval == 255 allowed \n");
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
wpng_info.sample_depth = 8; /* <==> maxval 255 */
|
||||||
|
|
||||||
|
if (!wpng_info.filter) {
|
||||||
|
/* make outname from inname */
|
||||||
|
if ((p = strrchr(inname, '.')) == NULL ||
|
||||||
|
(p - inname) != (len - 4))
|
||||||
|
{
|
||||||
|
strcpy(outname, inname);
|
||||||
|
strcpy(outname+len, ".png");
|
||||||
|
} else {
|
||||||
|
len -= 4;
|
||||||
|
strncpy(outname, inname, len);
|
||||||
|
strcpy(outname+len, ".png");
|
||||||
|
}
|
||||||
|
/* check if outname already exists; if not, open */
|
||||||
|
if ((wpng_info.outfile = fopen(outname, "rb")) != NULL) {
|
||||||
|
fprintf(stderr, PROGNAME ": output file exists [%s]\n",
|
||||||
|
outname);
|
||||||
|
fclose(wpng_info.outfile);
|
||||||
|
++error;
|
||||||
|
} else if (!(wpng_info.outfile = fopen(outname, "wb"))) {
|
||||||
|
fprintf(stderr, PROGNAME ": can't open output file [%s]\n",
|
||||||
|
outname);
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
fclose(wpng_info.infile);
|
||||||
|
wpng_info.infile = NULL;
|
||||||
|
if (wpng_info.filter) {
|
||||||
|
fclose(wpng_info.outfile);
|
||||||
|
wpng_info.outfile = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* if we had any errors, print usage and die horrible death...arrr! */
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, APPNAME);
|
||||||
|
writepng_version_info();
|
||||||
|
fprintf(stderr, "\n"
|
||||||
|
"Usage: %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] pnmfile\n"
|
||||||
|
"or: ... | %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] | ...\n"
|
||||||
|
" exp \ttransfer-function exponent (``gamma'') of the image in\n"
|
||||||
|
"\t\t floating-point format (e.g., ``%.5f''); if image looks\n"
|
||||||
|
"\t\t correct on given display system, image gamma is equal to\n"
|
||||||
|
"\t\t inverse of display-system exponent, i.e., 1 / (LUT * CRT)\n"
|
||||||
|
"\t\t (where LUT = lookup-table exponent and CRT = CRT exponent;\n"
|
||||||
|
"\t\t first varies, second is usually 2.2, all are positive)\n"
|
||||||
|
" bg \tdesired background color for alpha-channel images, in\n"
|
||||||
|
"\t\t 7-character hex RGB format (e.g., ``#ff7700'' for orange:\n"
|
||||||
|
"\t\t same as HTML colors)\n"
|
||||||
|
" -text\tprompt interactively for text info (tEXt chunks)\n"
|
||||||
|
" -time\tinclude a tIME chunk (last modification time)\n"
|
||||||
|
" -interlace\twrite interlaced PNG image\n"
|
||||||
|
"\n"
|
||||||
|
"pnmfile or stdin must be a binary PGM (`P5'), PPM (`P6') or (extremely\n"
|
||||||
|
"unofficial and unsupported!) PAM (`P8') file. Currently it is required\n"
|
||||||
|
"to have maxval == 255 (i.e., no scaling). If pnmfile is specified, it\n"
|
||||||
|
"is converted to the corresponding PNG file with the same base name but a\n"
|
||||||
|
"``.png'' extension; files read from stdin are converted and sent to stdout.\n"
|
||||||
|
"The conversion is progressive (low memory usage) unless interlacing is\n"
|
||||||
|
"requested; in that case the whole image will be buffered in memory and\n"
|
||||||
|
"written in one call.\n"
|
||||||
|
"\n", PROGNAME, PROGNAME, default_gamma);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* prepare the text buffers for libpng's use; note that even though
|
||||||
|
* PNG's png_text struct includes a length field, we don't have to fill
|
||||||
|
* it out */
|
||||||
|
|
||||||
|
if (text &&
|
||||||
|
#ifndef DOS_OS2_W32
|
||||||
|
(keybd = fdopen(fileno(stderr), "r")) != NULL &&
|
||||||
|
#endif
|
||||||
|
(textbuf = (char *)malloc((5 + 9)*75)) != NULL)
|
||||||
|
{
|
||||||
|
int i, valid, result;
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"Enter text info (no more than 72 characters per line);\n");
|
||||||
|
fprintf(stderr, "to skip a field, hit the <Enter> key.\n");
|
||||||
|
/* note: just <Enter> leaves len == 1 */
|
||||||
|
|
||||||
|
do {
|
||||||
|
valid = TRUE;
|
||||||
|
p = textbuf + TEXT_TITLE_OFFSET;
|
||||||
|
fprintf(stderr, " Title: ");
|
||||||
|
fflush(stderr);
|
||||||
|
if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
|
||||||
|
if (p[len-1] == '\n')
|
||||||
|
p[--len] = '\0';
|
||||||
|
wpng_info.title = p;
|
||||||
|
wpng_info.have_text |= TEXT_TITLE;
|
||||||
|
if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
|
||||||
|
fprintf(stderr, " " PROGNAME " warning: character code"
|
||||||
|
" %u is %sdiscouraged by the PNG\n specification "
|
||||||
|
"[first occurrence was at character position #%d]\n",
|
||||||
|
(unsigned)p[result], (p[result] == 27)? "strongly " : "",
|
||||||
|
result+1);
|
||||||
|
fflush(stderr);
|
||||||
|
#ifdef FORBID_LATIN1_CTRL
|
||||||
|
wpng_info.have_text &= ~TEXT_TITLE;
|
||||||
|
valid = FALSE;
|
||||||
|
#else
|
||||||
|
if (p[result] == 27) { /* escape character */
|
||||||
|
wpng_info.have_text &= ~TEXT_TITLE;
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!valid);
|
||||||
|
|
||||||
|
do {
|
||||||
|
valid = TRUE;
|
||||||
|
p = textbuf + TEXT_AUTHOR_OFFSET;
|
||||||
|
fprintf(stderr, " Author: ");
|
||||||
|
fflush(stderr);
|
||||||
|
if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
|
||||||
|
if (p[len-1] == '\n')
|
||||||
|
p[--len] = '\0';
|
||||||
|
wpng_info.author = p;
|
||||||
|
wpng_info.have_text |= TEXT_AUTHOR;
|
||||||
|
if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
|
||||||
|
fprintf(stderr, " " PROGNAME " warning: character code"
|
||||||
|
" %u is %sdiscouraged by the PNG\n specification "
|
||||||
|
"[first occurrence was at character position #%d]\n",
|
||||||
|
(unsigned)p[result], (p[result] == 27)? "strongly " : "",
|
||||||
|
result+1);
|
||||||
|
fflush(stderr);
|
||||||
|
#ifdef FORBID_LATIN1_CTRL
|
||||||
|
wpng_info.have_text &= ~TEXT_AUTHOR;
|
||||||
|
valid = FALSE;
|
||||||
|
#else
|
||||||
|
if (p[result] == 27) { /* escape character */
|
||||||
|
wpng_info.have_text &= ~TEXT_AUTHOR;
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!valid);
|
||||||
|
|
||||||
|
do {
|
||||||
|
valid = TRUE;
|
||||||
|
p = textbuf + TEXT_DESC_OFFSET;
|
||||||
|
fprintf(stderr, " Description (up to 9 lines):\n");
|
||||||
|
for (i = 1; i < 10; ++i) {
|
||||||
|
fprintf(stderr, " [%d] ", i);
|
||||||
|
fflush(stderr);
|
||||||
|
if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1)
|
||||||
|
p += len; /* now points at NULL; char before is newline */
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((len = p - (textbuf + TEXT_DESC_OFFSET)) > 1) {
|
||||||
|
if (p[-1] == '\n') {
|
||||||
|
p[-1] = '\0';
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
wpng_info.desc = textbuf + TEXT_DESC_OFFSET;
|
||||||
|
wpng_info.have_text |= TEXT_DESC;
|
||||||
|
p = textbuf + TEXT_DESC_OFFSET;
|
||||||
|
if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
|
||||||
|
fprintf(stderr, " " PROGNAME " warning: character code"
|
||||||
|
" %u is %sdiscouraged by the PNG\n specification "
|
||||||
|
"[first occurrence was at character position #%d]\n",
|
||||||
|
(unsigned)p[result], (p[result] == 27)? "strongly " : "",
|
||||||
|
result+1);
|
||||||
|
fflush(stderr);
|
||||||
|
#ifdef FORBID_LATIN1_CTRL
|
||||||
|
wpng_info.have_text &= ~TEXT_DESC;
|
||||||
|
valid = FALSE;
|
||||||
|
#else
|
||||||
|
if (p[result] == 27) { /* escape character */
|
||||||
|
wpng_info.have_text &= ~TEXT_DESC;
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!valid);
|
||||||
|
|
||||||
|
do {
|
||||||
|
valid = TRUE;
|
||||||
|
p = textbuf + TEXT_COPY_OFFSET;
|
||||||
|
fprintf(stderr, " Copyright: ");
|
||||||
|
fflush(stderr);
|
||||||
|
if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
|
||||||
|
if (p[len-1] == '\n')
|
||||||
|
p[--len] = '\0';
|
||||||
|
wpng_info.copyright = p;
|
||||||
|
wpng_info.have_text |= TEXT_COPY;
|
||||||
|
if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
|
||||||
|
fprintf(stderr, " " PROGNAME " warning: character code"
|
||||||
|
" %u is %sdiscouraged by the PNG\n specification "
|
||||||
|
"[first occurrence was at character position #%d]\n",
|
||||||
|
(unsigned)p[result], (p[result] == 27)? "strongly " : "",
|
||||||
|
result+1);
|
||||||
|
fflush(stderr);
|
||||||
|
#ifdef FORBID_LATIN1_CTRL
|
||||||
|
wpng_info.have_text &= ~TEXT_COPY;
|
||||||
|
valid = FALSE;
|
||||||
|
#else
|
||||||
|
if (p[result] == 27) { /* escape character */
|
||||||
|
wpng_info.have_text &= ~TEXT_COPY;
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!valid);
|
||||||
|
|
||||||
|
do {
|
||||||
|
valid = TRUE;
|
||||||
|
p = textbuf + TEXT_EMAIL_OFFSET;
|
||||||
|
fprintf(stderr, " E-mail: ");
|
||||||
|
fflush(stderr);
|
||||||
|
if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
|
||||||
|
if (p[len-1] == '\n')
|
||||||
|
p[--len] = '\0';
|
||||||
|
wpng_info.email = p;
|
||||||
|
wpng_info.have_text |= TEXT_EMAIL;
|
||||||
|
if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
|
||||||
|
fprintf(stderr, " " PROGNAME " warning: character code"
|
||||||
|
" %u is %sdiscouraged by the PNG\n specification "
|
||||||
|
"[first occurrence was at character position #%d]\n",
|
||||||
|
(unsigned)p[result], (p[result] == 27)? "strongly " : "",
|
||||||
|
result+1);
|
||||||
|
fflush(stderr);
|
||||||
|
#ifdef FORBID_LATIN1_CTRL
|
||||||
|
wpng_info.have_text &= ~TEXT_EMAIL;
|
||||||
|
valid = FALSE;
|
||||||
|
#else
|
||||||
|
if (p[result] == 27) { /* escape character */
|
||||||
|
wpng_info.have_text &= ~TEXT_EMAIL;
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!valid);
|
||||||
|
|
||||||
|
do {
|
||||||
|
valid = TRUE;
|
||||||
|
p = textbuf + TEXT_URL_OFFSET;
|
||||||
|
fprintf(stderr, " URL: ");
|
||||||
|
fflush(stderr);
|
||||||
|
if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
|
||||||
|
if (p[len-1] == '\n')
|
||||||
|
p[--len] = '\0';
|
||||||
|
wpng_info.url = p;
|
||||||
|
wpng_info.have_text |= TEXT_URL;
|
||||||
|
if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
|
||||||
|
fprintf(stderr, " " PROGNAME " warning: character code"
|
||||||
|
" %u is %sdiscouraged by the PNG\n specification "
|
||||||
|
"[first occurrence was at character position #%d]\n",
|
||||||
|
(unsigned)p[result], (p[result] == 27)? "strongly " : "",
|
||||||
|
result+1);
|
||||||
|
fflush(stderr);
|
||||||
|
#ifdef FORBID_LATIN1_CTRL
|
||||||
|
wpng_info.have_text &= ~TEXT_URL;
|
||||||
|
valid = FALSE;
|
||||||
|
#else
|
||||||
|
if (p[result] == 27) { /* escape character */
|
||||||
|
wpng_info.have_text &= ~TEXT_URL;
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!valid);
|
||||||
|
|
||||||
|
#ifndef DOS_OS2_W32
|
||||||
|
fclose(keybd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (text) {
|
||||||
|
fprintf(stderr, PROGNAME ": unable to allocate memory for text\n");
|
||||||
|
text = FALSE;
|
||||||
|
wpng_info.have_text = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* allocate libpng stuff, initialize transformations, write pre-IDAT data */
|
||||||
|
|
||||||
|
if ((rc = writepng_init(&wpng_info)) != 0) {
|
||||||
|
switch (rc) {
|
||||||
|
case 2:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": libpng initialization problem (longjmp)\n");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(stderr, PROGNAME ": insufficient memory\n");
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": internal logic error (unexpected PNM type)\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": unknown writepng_init() error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* free textbuf, since it's a completely local variable and all text info
|
||||||
|
* has just been written to the PNG file */
|
||||||
|
|
||||||
|
if (text && textbuf) {
|
||||||
|
free(textbuf);
|
||||||
|
textbuf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* calculate rowbytes on basis of image type; note that this becomes much
|
||||||
|
* more complicated if we choose to support PBM type, ASCII PNM types, or
|
||||||
|
* 16-bit-per-sample binary data [currently not an official NetPBM type] */
|
||||||
|
|
||||||
|
if (wpng_info.pnmtype == 5)
|
||||||
|
rowbytes = wpng_info.width;
|
||||||
|
else if (wpng_info.pnmtype == 6)
|
||||||
|
rowbytes = wpng_info.width * 3;
|
||||||
|
else /* if (wpng_info.pnmtype == 8) */
|
||||||
|
rowbytes = wpng_info.width * 4;
|
||||||
|
|
||||||
|
|
||||||
|
/* read and write the image, either in its entirety (if writing interlaced
|
||||||
|
* PNG) or row by row (if non-interlaced) */
|
||||||
|
|
||||||
|
fprintf(stderr, "Encoding image data...\n");
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
if (wpng_info.interlaced) {
|
||||||
|
long i;
|
||||||
|
ulg bytes;
|
||||||
|
ulg image_bytes;
|
||||||
|
|
||||||
|
/* Guard against integer overflow */
|
||||||
|
if (wpng_info_height > ((size_t)(-1)/rowbytes ||
|
||||||
|
wpng_info_height > ((ulg)(-1)/rowbytes) {
|
||||||
|
fprintf(stderr, PROGNAME ": image_data buffer too large\n");
|
||||||
|
writepng_cleanup(&wpng_info);
|
||||||
|
wpng_cleanup();
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
image_bytes = rowbytes * wpng_info.height;
|
||||||
|
|
||||||
|
wpng_info.image_data = (uch *)malloc(image_bytes);
|
||||||
|
wpng_info.row_pointers = (uch **)malloc(wpng_info.height*sizeof(uch *));
|
||||||
|
if (wpng_info.image_data == NULL || wpng_info.row_pointers == NULL) {
|
||||||
|
fprintf(stderr, PROGNAME ": insufficient memory for image data\n");
|
||||||
|
writepng_cleanup(&wpng_info);
|
||||||
|
wpng_cleanup();
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
for (i = 0; i < wpng_info.height; ++i)
|
||||||
|
wpng_info.row_pointers[i] = wpng_info.image_data + i*rowbytes;
|
||||||
|
bytes = fread(wpng_info.image_data, 1, image_bytes, wpng_info.infile);
|
||||||
|
if (bytes != image_bytes) {
|
||||||
|
fprintf(stderr, PROGNAME ": expected %lu bytes, got %lu bytes\n",
|
||||||
|
image_bytes, bytes);
|
||||||
|
fprintf(stderr, " (continuing anyway)\n");
|
||||||
|
}
|
||||||
|
if (writepng_encode_image(&wpng_info) != 0) {
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": libpng problem (longjmp) while writing image data\n");
|
||||||
|
writepng_cleanup(&wpng_info);
|
||||||
|
wpng_cleanup();
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else /* not interlaced: write progressively (row by row) */ {
|
||||||
|
long j;
|
||||||
|
ulg bytes;
|
||||||
|
|
||||||
|
wpng_info.image_data = (uch *)malloc(rowbytes);
|
||||||
|
if (wpng_info.image_data == NULL) {
|
||||||
|
fprintf(stderr, PROGNAME ": insufficient memory for row data\n");
|
||||||
|
writepng_cleanup(&wpng_info);
|
||||||
|
wpng_cleanup();
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
error = 0;
|
||||||
|
for (j = wpng_info.height; j > 0L; --j) {
|
||||||
|
bytes = fread(wpng_info.image_data, 1, rowbytes, wpng_info.infile);
|
||||||
|
if (bytes != rowbytes) {
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": expected %lu bytes, got %lu bytes (row %ld)\n", rowbytes,
|
||||||
|
bytes, wpng_info.height-j);
|
||||||
|
++error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (writepng_encode_row(&wpng_info) != 0) {
|
||||||
|
fprintf(stderr, PROGNAME
|
||||||
|
": libpng problem (longjmp) while writing row %ld\n",
|
||||||
|
wpng_info.height-j);
|
||||||
|
++error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
writepng_cleanup(&wpng_info);
|
||||||
|
wpng_cleanup();
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
if (writepng_encode_finish(&wpng_info) != 0) {
|
||||||
|
fprintf(stderr, PROGNAME ": error on final libpng call\n");
|
||||||
|
writepng_cleanup(&wpng_info);
|
||||||
|
wpng_cleanup();
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* OK, we're done (successfully): clean up all resources and quit */
|
||||||
|
|
||||||
|
fprintf(stderr, "Done.\n");
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
writepng_cleanup(&wpng_info);
|
||||||
|
wpng_cleanup();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int wpng_isvalid_latin1(uch *p, int len)
|
||||||
|
{
|
||||||
|
int i, result = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
if (p[i] == 10 || (p[i] > 31 && p[i] < 127) || p[i] > 160)
|
||||||
|
continue; /* character is completely OK */
|
||||||
|
if (result < 0 || (p[result] != 27 && p[i] == 27))
|
||||||
|
result = i; /* mark location of first questionable one */
|
||||||
|
} /* or of first escape character (bad) */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void wpng_cleanup(void)
|
||||||
|
{
|
||||||
|
if (wpng_info.outfile) {
|
||||||
|
fclose(wpng_info.outfile);
|
||||||
|
wpng_info.outfile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpng_info.infile) {
|
||||||
|
fclose(wpng_info.infile);
|
||||||
|
wpng_info.infile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpng_info.image_data) {
|
||||||
|
free(wpng_info.image_data);
|
||||||
|
wpng_info.image_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpng_info.row_pointers) {
|
||||||
|
free(wpng_info.row_pointers);
|
||||||
|
wpng_info.row_pointers = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DOS_OS2_W32
|
||||||
|
|
||||||
|
static char *dos_kbd_gets(char *buf, int len)
|
||||||
|
{
|
||||||
|
int ch, count=0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
buf[count++] = ch = getche();
|
||||||
|
} while (ch != '\r' && count < len-1);
|
||||||
|
|
||||||
|
buf[count--] = '\0'; /* terminate string */
|
||||||
|
if (buf[count] == '\r') /* Enter key makes CR, so change to newline */
|
||||||
|
buf[count] = '\n';
|
||||||
|
|
||||||
|
fprintf(stderr, "\n"); /* Enter key does *not* cause a newline */
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DOS_OS2_W32 */
|
|
@ -0,0 +1,401 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wpng - simple PNG-writing program writepng.c
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2007, 2017 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h> /* for exit() prototype */
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "png.h" /* libpng header, includes setjmp.h */
|
||||||
|
#include "writepng.h" /* typedefs, common macros, public prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
/* local prototype */
|
||||||
|
|
||||||
|
static void writepng_error_handler(png_structp png_ptr, png_const_charp msg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void writepng_version_info(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
|
||||||
|
PNG_LIBPNG_VER_STRING, png_libpng_ver);
|
||||||
|
fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
|
||||||
|
ZLIB_VERSION, zlib_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for
|
||||||
|
* unexpected pnmtype; note that outfile might be stdout */
|
||||||
|
|
||||||
|
int writepng_init(mainprog_info *mainprog_ptr)
|
||||||
|
{
|
||||||
|
png_structp png_ptr; /* note: temporary variables! */
|
||||||
|
png_infop info_ptr;
|
||||||
|
int color_type, interlace_type;
|
||||||
|
|
||||||
|
|
||||||
|
/* could also replace libpng warning-handler (final NULL), but no need: */
|
||||||
|
|
||||||
|
png_ptr = png_create_write_struct(png_get_libpng_ver(NULL), mainprog_ptr,
|
||||||
|
writepng_error_handler, NULL);
|
||||||
|
if (!png_ptr)
|
||||||
|
return 4; /* out of memory */
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr) {
|
||||||
|
png_destroy_write_struct(&png_ptr, NULL);
|
||||||
|
return 4; /* out of memory */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* setjmp() must be called in every function that calls a PNG-writing
|
||||||
|
* libpng function, unless an alternate error handler was installed--
|
||||||
|
* but compatible error handlers must either use longjmp() themselves
|
||||||
|
* (as in this program) or some other method to return control to
|
||||||
|
* application code, so here we go: */
|
||||||
|
|
||||||
|
if (setjmp(mainprog_ptr->jmpbuf)) {
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* make sure outfile is (re)opened in BINARY mode */
|
||||||
|
|
||||||
|
png_init_io(png_ptr, mainprog_ptr->outfile);
|
||||||
|
|
||||||
|
|
||||||
|
/* set the compression levels--in general, always want to leave filtering
|
||||||
|
* turned on (except for palette images) and allow all of the filters,
|
||||||
|
* which is the default; want 32K zlib window, unless entire image buffer
|
||||||
|
* is 16K or smaller (unknown here)--also the default; usually want max
|
||||||
|
* compression (NOT the default); and remaining compression flags should
|
||||||
|
* be left alone */
|
||||||
|
|
||||||
|
png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
|
||||||
|
/*
|
||||||
|
>> this is default for no filtering; Z_FILTERED is default otherwise:
|
||||||
|
png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
|
||||||
|
>> these are all defaults:
|
||||||
|
png_set_compression_mem_level(png_ptr, 8);
|
||||||
|
png_set_compression_window_bits(png_ptr, 15);
|
||||||
|
png_set_compression_method(png_ptr, 8);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* set the image parameters appropriately */
|
||||||
|
|
||||||
|
if (mainprog_ptr->pnmtype == 5)
|
||||||
|
color_type = PNG_COLOR_TYPE_GRAY;
|
||||||
|
else if (mainprog_ptr->pnmtype == 6)
|
||||||
|
color_type = PNG_COLOR_TYPE_RGB;
|
||||||
|
else if (mainprog_ptr->pnmtype == 8)
|
||||||
|
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||||
|
else {
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 :
|
||||||
|
PNG_INTERLACE_NONE;
|
||||||
|
|
||||||
|
png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
|
||||||
|
mainprog_ptr->sample_depth, color_type, interlace_type,
|
||||||
|
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
|
if (mainprog_ptr->gamma > 0.0)
|
||||||
|
png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma);
|
||||||
|
|
||||||
|
if (mainprog_ptr->have_bg) { /* we know it's RGBA, not gray+alpha */
|
||||||
|
png_color_16 background;
|
||||||
|
|
||||||
|
background.red = mainprog_ptr->bg_red;
|
||||||
|
background.green = mainprog_ptr->bg_green;
|
||||||
|
background.blue = mainprog_ptr->bg_blue;
|
||||||
|
png_set_bKGD(png_ptr, info_ptr, &background);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mainprog_ptr->have_time) {
|
||||||
|
png_time modtime;
|
||||||
|
|
||||||
|
png_convert_from_time_t(&modtime, mainprog_ptr->modtime);
|
||||||
|
png_set_tIME(png_ptr, info_ptr, &modtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mainprog_ptr->have_text) {
|
||||||
|
png_text text[6];
|
||||||
|
int num_text = 0;
|
||||||
|
|
||||||
|
if (mainprog_ptr->have_text & TEXT_TITLE) {
|
||||||
|
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
text[num_text].key = "Title";
|
||||||
|
text[num_text].text = mainprog_ptr->title;
|
||||||
|
++num_text;
|
||||||
|
}
|
||||||
|
if (mainprog_ptr->have_text & TEXT_AUTHOR) {
|
||||||
|
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
text[num_text].key = "Author";
|
||||||
|
text[num_text].text = mainprog_ptr->author;
|
||||||
|
++num_text;
|
||||||
|
}
|
||||||
|
if (mainprog_ptr->have_text & TEXT_DESC) {
|
||||||
|
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
text[num_text].key = "Description";
|
||||||
|
text[num_text].text = mainprog_ptr->desc;
|
||||||
|
++num_text;
|
||||||
|
}
|
||||||
|
if (mainprog_ptr->have_text & TEXT_COPY) {
|
||||||
|
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
text[num_text].key = "Copyright";
|
||||||
|
text[num_text].text = mainprog_ptr->copyright;
|
||||||
|
++num_text;
|
||||||
|
}
|
||||||
|
if (mainprog_ptr->have_text & TEXT_EMAIL) {
|
||||||
|
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
text[num_text].key = "E-mail";
|
||||||
|
text[num_text].text = mainprog_ptr->email;
|
||||||
|
++num_text;
|
||||||
|
}
|
||||||
|
if (mainprog_ptr->have_text & TEXT_URL) {
|
||||||
|
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
|
text[num_text].key = "URL";
|
||||||
|
text[num_text].text = mainprog_ptr->url;
|
||||||
|
++num_text;
|
||||||
|
}
|
||||||
|
png_set_text(png_ptr, info_ptr, text, num_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* write all chunks up to (but not including) first IDAT */
|
||||||
|
|
||||||
|
png_write_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
|
||||||
|
/* if we wanted to write any more text info *after* the image data, we
|
||||||
|
* would set up text struct(s) here and call png_set_text() again, with
|
||||||
|
* just the new data; png_set_tIME() could also go here, but it would
|
||||||
|
* have no effect since we already called it above (only one tIME chunk
|
||||||
|
* allowed) */
|
||||||
|
|
||||||
|
|
||||||
|
/* set up the transformations: for now, just pack low-bit-depth pixels
|
||||||
|
* into bytes (one, two or four pixels per byte) */
|
||||||
|
|
||||||
|
png_set_packing(png_ptr);
|
||||||
|
/* png_set_shift(png_ptr, &sig_bit); to scale low-bit-depth values */
|
||||||
|
|
||||||
|
|
||||||
|
/* make sure we save our pointers for use in writepng_encode_image() */
|
||||||
|
|
||||||
|
mainprog_ptr->png_ptr = png_ptr;
|
||||||
|
mainprog_ptr->info_ptr = info_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* OK, that's all we need to do for now; return happy */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 for success, 2 for libpng (longjmp) problem */
|
||||||
|
|
||||||
|
int writepng_encode_image(mainprog_info *mainprog_ptr)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
||||||
|
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* as always, setjmp() must be called in every function that calls a
|
||||||
|
* PNG-writing libpng function */
|
||||||
|
|
||||||
|
if (setjmp(mainprog_ptr->jmpbuf)) {
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
mainprog_ptr->png_ptr = NULL;
|
||||||
|
mainprog_ptr->info_ptr = NULL;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* and now we just write the whole image; libpng takes care of interlacing
|
||||||
|
* for us */
|
||||||
|
|
||||||
|
png_write_image(png_ptr, mainprog_ptr->row_pointers);
|
||||||
|
|
||||||
|
|
||||||
|
/* since that's it, we also close out the end of the PNG file now--if we
|
||||||
|
* had any text or time info to write after the IDATs, second argument
|
||||||
|
* would be info_ptr, but we optimize slightly by sending NULL pointer: */
|
||||||
|
|
||||||
|
png_write_end(png_ptr, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 if succeeds, 2 if libpng problem */
|
||||||
|
|
||||||
|
int writepng_encode_row(mainprog_info *mainprog_ptr) /* NON-interlaced only! */
|
||||||
|
{
|
||||||
|
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
||||||
|
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* as always, setjmp() must be called in every function that calls a
|
||||||
|
* PNG-writing libpng function */
|
||||||
|
|
||||||
|
if (setjmp(mainprog_ptr->jmpbuf)) {
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
mainprog_ptr->png_ptr = NULL;
|
||||||
|
mainprog_ptr->info_ptr = NULL;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* image_data points at our one row of image data */
|
||||||
|
|
||||||
|
png_write_row(png_ptr, mainprog_ptr->image_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* returns 0 if succeeds, 2 if libpng problem */
|
||||||
|
|
||||||
|
int writepng_encode_finish(mainprog_info *mainprog_ptr) /* NON-interlaced! */
|
||||||
|
{
|
||||||
|
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
||||||
|
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
/* as always, setjmp() must be called in every function that calls a
|
||||||
|
* PNG-writing libpng function */
|
||||||
|
|
||||||
|
if (setjmp(mainprog_ptr->jmpbuf)) {
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
mainprog_ptr->png_ptr = NULL;
|
||||||
|
mainprog_ptr->info_ptr = NULL;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* close out PNG file; if we had any text or time info to write after
|
||||||
|
* the IDATs, second argument would be info_ptr: */
|
||||||
|
|
||||||
|
png_write_end(png_ptr, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void writepng_cleanup(mainprog_info *mainprog_ptr)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
||||||
|
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
||||||
|
|
||||||
|
if (png_ptr && info_ptr)
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void writepng_error_handler(png_structp png_ptr, png_const_charp msg)
|
||||||
|
{
|
||||||
|
mainprog_info *mainprog_ptr;
|
||||||
|
|
||||||
|
/* This function, aside from the extra step of retrieving the "error
|
||||||
|
* pointer" (below) and the fact that it exists within the application
|
||||||
|
* rather than within libpng, is essentially identical to libpng's
|
||||||
|
* default error handler. The second point is critical: since both
|
||||||
|
* setjmp() and longjmp() are called from the same code, they are
|
||||||
|
* guaranteed to have compatible notions of how big a jmp_buf is,
|
||||||
|
* regardless of whether _BSD_SOURCE or anything else has (or has not)
|
||||||
|
* been defined. */
|
||||||
|
|
||||||
|
fprintf(stderr, "writepng libpng error: %s\n", msg);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
mainprog_ptr = png_get_error_ptr(png_ptr);
|
||||||
|
if (mainprog_ptr == NULL) { /* we are completely hosed now */
|
||||||
|
fprintf(stderr,
|
||||||
|
"writepng severe error: jmpbuf not recoverable; terminating.\n");
|
||||||
|
fflush(stderr);
|
||||||
|
exit(99);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we have our data structure we can use the information in it
|
||||||
|
* to return control to our own higher level code (all the points
|
||||||
|
* where 'setjmp' is called in this file.) This will work with other
|
||||||
|
* error handling mechanisms as well - libpng always calls png_error
|
||||||
|
* when it can proceed no further, thus, so long as the error handler
|
||||||
|
* is intercepted, application code can do its own error recovery.
|
||||||
|
*/
|
||||||
|
longjmp(mainprog_ptr->jmpbuf, 1);
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wpng - simple PNG-writing program writepng.h
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is," without warranty of any kind,
|
||||||
|
express or implied. In no event shall the author or contributors
|
||||||
|
be held liable for any damages arising in any way from the use of
|
||||||
|
this software.
|
||||||
|
|
||||||
|
The contents of this file are DUAL-LICENSED. You may modify and/or
|
||||||
|
redistribute this software according to the terms of one of the
|
||||||
|
following two licenses (at your option):
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 1 ("BSD-like with advertising clause"):
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute
|
||||||
|
it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, disclaimer, and this list of conditions in the documenta-
|
||||||
|
tion and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this
|
||||||
|
software must display the following acknowledgment:
|
||||||
|
|
||||||
|
This product includes software developed by Greg Roelofs
|
||||||
|
and contributors for the book, "PNG: The Definitive Guide,"
|
||||||
|
published by O'Reilly and Associates.
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE 2 (GNU GPL v2 or later):
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
# define TRUE 1
|
||||||
|
# define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
# define MAX(a,b) ((a) > (b)? (a) : (b))
|
||||||
|
# define MIN(a,b) ((a) < (b)? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
|
||||||
|
#else
|
||||||
|
# define Trace(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TEXT_TITLE 0x01
|
||||||
|
#define TEXT_AUTHOR 0x02
|
||||||
|
#define TEXT_DESC 0x04
|
||||||
|
#define TEXT_COPY 0x08
|
||||||
|
#define TEXT_EMAIL 0x10
|
||||||
|
#define TEXT_URL 0x20
|
||||||
|
|
||||||
|
#define TEXT_TITLE_OFFSET 0
|
||||||
|
#define TEXT_AUTHOR_OFFSET 72
|
||||||
|
#define TEXT_COPY_OFFSET (2*72)
|
||||||
|
#define TEXT_EMAIL_OFFSET (3*72)
|
||||||
|
#define TEXT_URL_OFFSET (4*72)
|
||||||
|
#define TEXT_DESC_OFFSET (5*72)
|
||||||
|
|
||||||
|
typedef unsigned char uch;
|
||||||
|
typedef unsigned short ush;
|
||||||
|
typedef unsigned long ulg;
|
||||||
|
|
||||||
|
typedef struct _mainprog_info {
|
||||||
|
double gamma;
|
||||||
|
long width;
|
||||||
|
long height;
|
||||||
|
time_t modtime;
|
||||||
|
FILE *infile;
|
||||||
|
FILE *outfile;
|
||||||
|
void *png_ptr;
|
||||||
|
void *info_ptr;
|
||||||
|
uch *image_data;
|
||||||
|
uch **row_pointers;
|
||||||
|
char *title;
|
||||||
|
char *author;
|
||||||
|
char *desc;
|
||||||
|
char *copyright;
|
||||||
|
char *email;
|
||||||
|
char *url;
|
||||||
|
int filter; /* command-line-filter flag, not PNG row filter! */
|
||||||
|
int pnmtype;
|
||||||
|
int sample_depth;
|
||||||
|
int interlaced;
|
||||||
|
int have_bg;
|
||||||
|
int have_time;
|
||||||
|
int have_text;
|
||||||
|
jmp_buf jmpbuf;
|
||||||
|
uch bg_red;
|
||||||
|
uch bg_green;
|
||||||
|
uch bg_blue;
|
||||||
|
} mainprog_info;
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes for public functions in writepng.c */
|
||||||
|
|
||||||
|
void writepng_version_info(void);
|
||||||
|
|
||||||
|
int writepng_init(mainprog_info *mainprog_ptr);
|
||||||
|
|
||||||
|
int writepng_encode_image(mainprog_info *mainprog_ptr);
|
||||||
|
|
||||||
|
int writepng_encode_row(mainprog_info *mainprog_ptr);
|
||||||
|
|
||||||
|
int writepng_encode_finish(mainprog_info *mainprog_ptr);
|
||||||
|
|
||||||
|
void writepng_cleanup(mainprog_info *mainprog_ptr);
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* Fake a PNG - just write it out directly.
|
||||||
|
*
|
||||||
|
* COPYRIGHT: Written by John Cunningham Bowler, 2014.
|
||||||
|
* To the extent possible under law, the author has waived all copyright and
|
||||||
|
* related or neighboring rights to this work. This work is published from:
|
||||||
|
* United States.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <zlib.h> /* for crc32 */
|
||||||
|
|
||||||
|
void
|
||||||
|
put_uLong(uLong val)
|
||||||
|
{
|
||||||
|
putchar(val >> 24);
|
||||||
|
putchar(val >> 16);
|
||||||
|
putchar(val >> 8);
|
||||||
|
putchar(val >> 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
put_chunk(const unsigned char *chunk, uInt length)
|
||||||
|
{
|
||||||
|
uLong crc;
|
||||||
|
|
||||||
|
put_uLong(length-4); /* Exclude the tag */
|
||||||
|
|
||||||
|
fwrite(chunk, length, 1, stdout);
|
||||||
|
|
||||||
|
crc = crc32(0, Z_NULL, 0);
|
||||||
|
put_uLong(crc32(crc, chunk, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char signature[] =
|
||||||
|
{
|
||||||
|
137, 80, 78, 71, 13, 10, 26, 10
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned char IHDR[] =
|
||||||
|
{
|
||||||
|
73, 72, 68, 82, /* IHDR */
|
||||||
|
0, 0, 0, 1, /* width */
|
||||||
|
0, 0, 0, 1, /* height */
|
||||||
|
1, /* bit depth */
|
||||||
|
0, /* color type: greyscale */
|
||||||
|
0, /* compression method */
|
||||||
|
0, /* filter method */
|
||||||
|
0 /* interlace method: none */
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned char unknown[] =
|
||||||
|
{
|
||||||
|
'u', 'n', 'K', 'n' /* "unKn" - private safe to copy */
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
fwrite(signature, sizeof signature, 1, stdout);
|
||||||
|
put_chunk(IHDR, sizeof IHDR);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
put_chunk(unknown, sizeof unknown);
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013 John Cunningham Bowler
|
||||||
|
#
|
||||||
|
# This code is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h
|
||||||
|
#
|
||||||
|
# Generate a set of PNG test images. The images are generated in a
|
||||||
|
# sub-directory called 'tests' by default, however a command line argument will
|
||||||
|
# change that name. The generation requires a built version of makepng in the
|
||||||
|
# current directory.
|
||||||
|
#
|
||||||
|
usage(){
|
||||||
|
exec >&2
|
||||||
|
echo "$0 [<directory>]"
|
||||||
|
echo ' Generate a set of PNG test files in "directory" ("tests" by default)'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
mp="$PWD/makepng"
|
||||||
|
test -x "$mp" || {
|
||||||
|
exec >&2
|
||||||
|
echo "$0: the 'makepng' program must exist"
|
||||||
|
echo " in the directory within which this program:"
|
||||||
|
echo " $mp"
|
||||||
|
echo " is executed"
|
||||||
|
usage
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just one argument: the directory
|
||||||
|
testdir="tests"
|
||||||
|
test $# -gt 1 && {
|
||||||
|
testdir="$1"
|
||||||
|
shift
|
||||||
|
}
|
||||||
|
test $# -eq 0 || usage
|
||||||
|
|
||||||
|
# Take care not to clobber something
|
||||||
|
if test -e "$testdir"
|
||||||
|
then
|
||||||
|
test -d "$testdir" || usage
|
||||||
|
else
|
||||||
|
# mkdir -p isn't portable, so do the following
|
||||||
|
mkdir "$testdir" 2>/dev/null || mkdir -p "$testdir" || usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This fails in a very satisfactory way if it's not accessible
|
||||||
|
cd "$testdir"
|
||||||
|
:>"test$$.png" || {
|
||||||
|
exec >&2
|
||||||
|
echo "$testdir: directory not writable"
|
||||||
|
usage
|
||||||
|
}
|
||||||
|
rm "test$$.png" || {
|
||||||
|
exec >&2
|
||||||
|
echo "$testdir: you have create but not write privileges here."
|
||||||
|
echo " This is unexpected. You have a spurion; "'"'"test$$.png"'"'"."
|
||||||
|
echo " You need to remove this yourself. Try a different directory."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now call makepng ($mp) to create every file we can think of with a
|
||||||
|
# reasonable name
|
||||||
|
doit(){
|
||||||
|
for gamma in "" --sRGB --linear --1.8
|
||||||
|
do
|
||||||
|
case "$gamma" in
|
||||||
|
"")
|
||||||
|
gname=;;
|
||||||
|
--sRGB)
|
||||||
|
gname="-srgb";;
|
||||||
|
--linear)
|
||||||
|
gname="-lin";;
|
||||||
|
--1.8)
|
||||||
|
gname="-18";;
|
||||||
|
*)
|
||||||
|
gname="-$gamma";;
|
||||||
|
esac
|
||||||
|
"$mp" $gamma "$1" "$2" "test-$1-$2$gname.png"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
#
|
||||||
|
for ct in gray palette
|
||||||
|
do
|
||||||
|
for bd in 1 2 4 8
|
||||||
|
do
|
||||||
|
doit "$ct" "$bd"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
#
|
||||||
|
doit "gray" "16"
|
||||||
|
#
|
||||||
|
for ct in gray-alpha rgb rgb-alpha
|
||||||
|
do
|
||||||
|
for bd in 8 16
|
||||||
|
do
|
||||||
|
doit "$ct" "$bd"
|
||||||
|
done
|
||||||
|
done
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,165 @@
|
||||||
|
/* contrib/libtests/pngstest-errors.h
|
||||||
|
*
|
||||||
|
* BUILT USING: libpng version 1.6.19beta03 - September 25, 2015
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* THIS IS A MACHINE GENERATED FILE: do not edit it directly!
|
||||||
|
* Instead run:
|
||||||
|
*
|
||||||
|
* pngstest --accumulate
|
||||||
|
*
|
||||||
|
* on as many PNG files as possible; at least PNGSuite and
|
||||||
|
* contrib/libtests/testpngs.
|
||||||
|
*/
|
||||||
|
static png_uint_16 gpc_error[16/*in*/][16/*out*/][4/*a*/] =
|
||||||
|
{
|
||||||
|
{ /* input: sRGB-gray */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 372, 0 }, { 0, 0, 372, 0 }, { 0, 0, 372, 0 }, { 0, 0, 372, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: sRGB-gray+alpha */
|
||||||
|
{ 0, 19, 0, 0 }, { 0, 0, 0, 0 }, { 0, 20, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 897, 788, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: sRGB-rgb */
|
||||||
|
{ 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 893, 0 }, { 0, 0, 893, 0 }, { 0, 0, 811, 0 }, { 0, 0, 811, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: sRGB-rgb+alpha */
|
||||||
|
{ 0, 16, 17, 0 }, { 0, 17, 17, 0 }, { 0, 19, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 850, 875, 0 }, { 0, 850, 875, 0 }, { 0, 897, 788, 0 }, { 0, 897, 788, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: linear-gray */
|
||||||
|
{ 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: linear-gray+alpha */
|
||||||
|
{ 0, 74, 9, 0 }, { 0, 20, 9, 0 }, { 0, 74, 9, 0 }, { 0, 20, 9, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 1, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: linear-rgb */
|
||||||
|
{ 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 },
|
||||||
|
{ 0, 0, 4, 0 }, { 0, 0, 4, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: linear-rgb+alpha */
|
||||||
|
{ 0, 126, 143, 0 }, { 0, 11, 7, 0 }, { 0, 74, 9, 0 }, { 0, 17, 9, 0 },
|
||||||
|
{ 0, 4, 4, 0 }, { 0, 5, 4, 0 }, { 0, 0, 0, 0 }, { 0, 1, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-gray */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-gray+alpha */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-rgb */
|
||||||
|
{ 0, 0, 13, 0 }, { 0, 0, 13, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 },
|
||||||
|
{ 0, 0, 673, 0 }, { 0, 0, 673, 0 }, { 0, 0, 674, 0 }, { 0, 0, 674, 0 },
|
||||||
|
{ 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 460, 0 }, { 0, 0, 460, 0 }, { 0, 0, 263, 0 }, { 0, 0, 263, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-rgb+alpha */
|
||||||
|
{ 0, 6, 8, 0 }, { 0, 7, 8, 0 }, { 0, 75, 9, 0 }, { 0, 9, 9, 0 },
|
||||||
|
{ 0, 585, 427, 0 }, { 0, 585, 427, 0 }, { 0, 717, 514, 0 }, { 0, 717, 514, 0 },
|
||||||
|
{ 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 13323, 460, 0 }, { 0, 427, 460, 0 }, { 0, 16480, 263, 0 }, { 0, 243, 263, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-gray */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 282, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-gray+alpha */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 253, 282, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-rgb */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 265, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-rgb+alpha */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 243, 265, 0 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static png_uint_16 gpc_error_via_linear[16][4/*out*/][4] =
|
||||||
|
{
|
||||||
|
{ /* input: sRGB-gray */
|
||||||
|
{ 0, 0, 7, 0 }, { 0, 0, 7, 0 }, { 0, 0, 7, 0 }, { 0, 0, 7, 0 }
|
||||||
|
}, { /* input: sRGB-gray+alpha */
|
||||||
|
{ 0, 15, 15, 0 }, { 0, 186, 15, 0 }, { 0, 15, 15, 0 }, { 0, 186, 15, 0 }
|
||||||
|
}, { /* input: sRGB-rgb */
|
||||||
|
{ 0, 0, 20, 0 }, { 0, 0, 20, 0 }, { 0, 0, 15, 0 }, { 0, 0, 15, 0 }
|
||||||
|
}, { /* input: sRGB-rgb+alpha */
|
||||||
|
{ 0, 16, 17, 0 }, { 0, 187, 17, 0 }, { 0, 15, 15, 0 }, { 0, 186, 15, 0 }
|
||||||
|
}, { /* input: linear-gray */
|
||||||
|
{ 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }
|
||||||
|
}, { /* input: linear-gray+alpha */
|
||||||
|
{ 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
|
||||||
|
}, { /* input: linear-rgb */
|
||||||
|
{ 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 1, 0 }
|
||||||
|
}, { /* input: linear-rgb+alpha */
|
||||||
|
{ 0, 1, 1, 0 }, { 0, 9, 1, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-gray */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-gray+alpha */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-rgb */
|
||||||
|
{ 0, 0, 13, 0 }, { 0, 0, 13, 0 }, { 0, 0, 14, 0 }, { 0, 0, 14, 0 }
|
||||||
|
}, { /* input: color-mapped-sRGB-rgb+alpha */
|
||||||
|
{ 0, 4, 8, 0 }, { 0, 9, 8, 0 }, { 0, 9, 5, 0 }, { 0, 32, 5, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-gray */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-gray+alpha */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-rgb */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}, { /* input: color-mapped-linear-rgb+alpha */
|
||||||
|
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static png_uint_16 gpc_error_to_colormap[8/*i*/][8/*o*/][4] =
|
||||||
|
{
|
||||||
|
{ /* input: sRGB-gray */
|
||||||
|
{ 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 }, { 0, 0, 9, 0 },
|
||||||
|
{ 0, 0, 560, 0 }, { 0, 0, 560, 0 }, { 0, 0, 560, 0 }, { 0, 0, 560, 0 }
|
||||||
|
}, { /* input: sRGB-gray+alpha */
|
||||||
|
{ 0, 19, 9, 0 }, { 0, 255, 9, 25 }, { 0, 88, 9, 0 }, { 0, 255, 9, 25 },
|
||||||
|
{ 0, 1012, 928, 0 }, { 0, 16026, 928, 6425 }, { 0, 1012, 928, 0 }, { 0, 16026, 928, 6425 }
|
||||||
|
}, { /* input: sRGB-rgb */
|
||||||
|
{ 0, 0, 19, 0 }, { 0, 0, 19, 0 }, { 0, 0, 25, 0 }, { 0, 0, 25, 0 },
|
||||||
|
{ 0, 0, 962, 0 }, { 0, 0, 962, 0 }, { 0, 0, 13677, 0 }, { 0, 0, 13677, 0 }
|
||||||
|
}, { /* input: sRGB-rgb+alpha */
|
||||||
|
{ 0, 63, 77, 0 }, { 0, 255, 19, 25 }, { 0, 225, 25, 0 }, { 0, 255, 25, 67 },
|
||||||
|
{ 0, 17534, 18491, 0 }, { 0, 15736, 2824, 6425 }, { 0, 14019, 13677, 0 }, { 0, 50115, 13677, 17219 }
|
||||||
|
}, { /* input: linear-gray */
|
||||||
|
{ 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 73, 0 },
|
||||||
|
{ 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }, { 0, 0, 18817, 0 }
|
||||||
|
}, { /* input: linear-gray+alpha */
|
||||||
|
{ 0, 74, 74, 0 }, { 0, 255, 74, 25 }, { 0, 99, 74, 0 }, { 0, 255, 74, 25 },
|
||||||
|
{ 0, 18919, 18907, 0 }, { 0, 24549, 18907, 6553 }, { 0, 18919, 18907, 0 }, { 0, 24549, 18907, 6553 }
|
||||||
|
}, { /* input: linear-rgb */
|
||||||
|
{ 0, 0, 73, 0 }, { 0, 0, 73, 0 }, { 0, 0, 98, 0 }, { 0, 0, 98, 0 },
|
||||||
|
{ 0, 0, 18664, 0 }, { 0, 0, 18664, 0 }, { 0, 0, 24998, 0 }, { 0, 0, 24998, 0 }
|
||||||
|
}, { /* input: linear-rgb+alpha */
|
||||||
|
{ 0, 181, 196, 0 }, { 0, 255, 61, 25 }, { 206, 187, 98, 0 }, { 0, 255, 98, 67 },
|
||||||
|
{ 0, 18141, 18137, 0 }, { 0, 17494, 17504, 6553 }, { 0, 24979, 24992, 0 }, { 0, 49172, 24992, 17347 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* END MACHINE GENERATED */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,114 @@
|
||||||
|
|
||||||
|
/* readpng.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 John Cunningham Bowler
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* Load an arbitrary number of PNG files (from the command line, or, if there
|
||||||
|
* are no arguments on the command line, from stdin) then run a time test by
|
||||||
|
* reading each file by row. The test does nothing with the read result and
|
||||||
|
* does no transforms. The only output is a time as a floating point number of
|
||||||
|
* seconds with 9 decimal digits.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define the following to use this test against your installed libpng, rather
|
||||||
|
* than the one being built here:
|
||||||
|
*/
|
||||||
|
#ifdef PNG_FREESTANDING_TESTS
|
||||||
|
# include <png.h>
|
||||||
|
#else
|
||||||
|
# include "../../png.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_png(FILE *fp)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
||||||
|
png_infop info_ptr = NULL;
|
||||||
|
png_bytep row = NULL, display = NULL;
|
||||||
|
|
||||||
|
if (png_ptr == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
if (row != NULL) free(row);
|
||||||
|
if (display != NULL) free(display);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (info_ptr == NULL)
|
||||||
|
png_error(png_ptr, "OOM allocating info structure");
|
||||||
|
|
||||||
|
png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0);
|
||||||
|
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
/* Failure to initialize these is harmless */
|
||||||
|
row = malloc(rowbytes);
|
||||||
|
display = malloc(rowbytes);
|
||||||
|
|
||||||
|
if (row == NULL || display == NULL)
|
||||||
|
png_error(png_ptr, "OOM allocating row buffers");
|
||||||
|
|
||||||
|
{
|
||||||
|
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||||
|
# ifdef PNG_READ_INTERLACING_SUPPORTED
|
||||||
|
int passes = png_set_interlace_handling(png_ptr);
|
||||||
|
# else /* !READ_INTERLACING */
|
||||||
|
int passes = png_get_interlace_type(png_ptr, info_ptr) ==
|
||||||
|
PNG_INTERLACE_ADAM7 ? PNG_INTERLACE_ADAM7_PASSES : 1;
|
||||||
|
# endif /* !READ_INTERLACING */
|
||||||
|
int pass;
|
||||||
|
|
||||||
|
png_start_read_image(png_ptr);
|
||||||
|
|
||||||
|
for (pass = 0; pass < passes; ++pass)
|
||||||
|
{
|
||||||
|
png_uint_32 y = height;
|
||||||
|
|
||||||
|
# ifndef PNG_READ_INTERLACING_SUPPORTED
|
||||||
|
if (passes == PNG_INTERLACE_ADAM7_PASSES)
|
||||||
|
y = PNG_PASS_ROWS(y, pass);
|
||||||
|
# endif /* READ_INTERLACING */
|
||||||
|
|
||||||
|
/* NOTE: this trashes the row each time; interlace handling won't
|
||||||
|
* work, but this avoids memory thrashing for speed testing.
|
||||||
|
*/
|
||||||
|
while (y-- > 0)
|
||||||
|
png_read_row(png_ptr, row, display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure to read to the end of the file: */
|
||||||
|
png_read_end(png_ptr, info_ptr);
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
free(row);
|
||||||
|
free(display);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
/* Exit code 0 on success. */
|
||||||
|
return !read_png(stdin);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,607 @@
|
||||||
|
|
||||||
|
/* timepng.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013,2016 John Cunningham Bowler
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* Load an arbitrary number of PNG files (from the command line, or, if there
|
||||||
|
* are no arguments on the command line, from stdin) then run a time test by
|
||||||
|
* reading each file by row or by image (possibly with transforms in the latter
|
||||||
|
* case). The only output is a time as a floating point number of seconds with
|
||||||
|
* 9 decimal digits.
|
||||||
|
*/
|
||||||
|
#define _POSIX_C_SOURCE 199309L /* for clock_gettime */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define the following to use this test against your installed libpng, rather
|
||||||
|
* than the one being built here:
|
||||||
|
*/
|
||||||
|
#ifdef PNG_FREESTANDING_TESTS
|
||||||
|
# include <png.h>
|
||||||
|
#else
|
||||||
|
# include "../../png.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The following is to support direct compilation of this file as C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# define voidcast(type, value) static_cast<type>(value)
|
||||||
|
#else
|
||||||
|
# define voidcast(type, value) (value)
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/* 'CLOCK_PROCESS_CPUTIME_ID' is one of the clock timers for clock_gettime. It
|
||||||
|
* need not be supported even when clock_gettime is available. It returns the
|
||||||
|
* 'CPU' time the process has consumed. 'CPU' time is assumed to include time
|
||||||
|
* when the CPU is actually blocked by a pending cache fill but not time
|
||||||
|
* waiting for page faults. The attempt is to get a measure of the actual time
|
||||||
|
* the implementation takes to read a PNG ignoring the potentially very large IO
|
||||||
|
* overhead.
|
||||||
|
*/
|
||||||
|
#if defined (CLOCK_PROCESS_CPUTIME_ID) && defined(PNG_STDIO_SUPPORTED) &&\
|
||||||
|
defined(PNG_EASY_ACCESS_SUPPORTED) &&\
|
||||||
|
(PNG_LIBPNG_VER >= 10700 ? defined(PNG_READ_PNG_SUPPORTED) :\
|
||||||
|
defined (PNG_SEQUENTIAL_READ_SUPPORTED) &&\
|
||||||
|
defined(PNG_INFO_IMAGE_SUPPORTED))
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FILE *input;
|
||||||
|
FILE *output;
|
||||||
|
} io_data;
|
||||||
|
|
||||||
|
static PNG_CALLBACK(void, read_and_copy,
|
||||||
|
(png_structp png_ptr, png_bytep buffer, size_t cb))
|
||||||
|
{
|
||||||
|
io_data *io = (io_data*)png_get_io_ptr(png_ptr);
|
||||||
|
|
||||||
|
if (fread(buffer, cb, 1, io->input) != 1)
|
||||||
|
png_error(png_ptr, strerror(errno));
|
||||||
|
|
||||||
|
if (fwrite(buffer, cb, 1, io->output) != 1)
|
||||||
|
{
|
||||||
|
perror("temporary file");
|
||||||
|
fprintf(stderr, "temporary file PNG write failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_by_row(png_structp png_ptr, png_infop info_ptr,
|
||||||
|
FILE *write_ptr, FILE *read_ptr)
|
||||||
|
{
|
||||||
|
/* These don't get freed on error, this is fine; the program immediately
|
||||||
|
* exits.
|
||||||
|
*/
|
||||||
|
png_bytep row = NULL, display = NULL;
|
||||||
|
io_data io_copy;
|
||||||
|
|
||||||
|
if (write_ptr != NULL)
|
||||||
|
{
|
||||||
|
/* Set up for a copy to the temporary file: */
|
||||||
|
io_copy.input = read_ptr;
|
||||||
|
io_copy.output = write_ptr;
|
||||||
|
png_set_read_fn(png_ptr, &io_copy, read_and_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
row = voidcast(png_bytep,malloc(rowbytes));
|
||||||
|
display = voidcast(png_bytep,malloc(rowbytes));
|
||||||
|
|
||||||
|
if (row == NULL || display == NULL)
|
||||||
|
png_error(png_ptr, "OOM allocating row buffers");
|
||||||
|
|
||||||
|
{
|
||||||
|
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||||
|
int passes = png_set_interlace_handling(png_ptr);
|
||||||
|
int pass;
|
||||||
|
|
||||||
|
png_start_read_image(png_ptr);
|
||||||
|
|
||||||
|
for (pass = 0; pass < passes; ++pass)
|
||||||
|
{
|
||||||
|
png_uint_32 y = height;
|
||||||
|
|
||||||
|
/* NOTE: this trashes the row each time; interlace handling won't
|
||||||
|
* work, but this avoids memory thrashing for speed testing and is
|
||||||
|
* somewhat representative of an application that works row-by-row.
|
||||||
|
*/
|
||||||
|
while (y-- > 0)
|
||||||
|
png_read_row(png_ptr, row, display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure to read to the end of the file: */
|
||||||
|
png_read_end(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
/* Free this up: */
|
||||||
|
free(row);
|
||||||
|
free(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PNG_CALLBACK(void, no_warnings, (png_structp png_ptr,
|
||||||
|
png_const_charp warning))
|
||||||
|
{
|
||||||
|
(void)png_ptr;
|
||||||
|
(void)warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_png(FILE *fp, png_int_32 transforms, FILE *write_file)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,
|
||||||
|
no_warnings);
|
||||||
|
png_infop info_ptr = NULL;
|
||||||
|
|
||||||
|
if (png_ptr == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef PNG_BENIGN_ERRORS_SUPPORTED
|
||||||
|
png_set_benign_errors(png_ptr, 1/*allowed*/);
|
||||||
|
# endif
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
|
||||||
|
if (info_ptr == NULL)
|
||||||
|
png_error(png_ptr, "OOM allocating info structure");
|
||||||
|
|
||||||
|
if (transforms < 0)
|
||||||
|
read_by_row(png_ptr, info_ptr, write_file, fp);
|
||||||
|
|
||||||
|
else
|
||||||
|
png_read_png(png_ptr, info_ptr, transforms, NULL/*params*/);
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mytime(struct timespec *t)
|
||||||
|
{
|
||||||
|
/* Do the timing using clock_gettime and the per-process timer. */
|
||||||
|
if (!clock_gettime(CLOCK_PROCESS_CPUTIME_ID, t))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
perror("CLOCK_PROCESS_CPUTIME_ID");
|
||||||
|
fprintf(stderr, "timepng: could not get the time\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int perform_one_test(FILE *fp, int nfiles, png_int_32 transforms)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct timespec before, after;
|
||||||
|
|
||||||
|
/* Clear out all errors: */
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
if (mytime(&before))
|
||||||
|
{
|
||||||
|
for (i=0; i<nfiles; ++i)
|
||||||
|
{
|
||||||
|
if (read_png(fp, transforms, NULL/*write*/))
|
||||||
|
{
|
||||||
|
if (ferror(fp))
|
||||||
|
{
|
||||||
|
perror("temporary file");
|
||||||
|
fprintf(stderr, "file %d: error reading PNG data\n", i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
perror("temporary file");
|
||||||
|
fprintf(stderr, "file %d: error from libpng\n", i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (mytime(&after))
|
||||||
|
{
|
||||||
|
/* Work out the time difference and print it - this is the only output,
|
||||||
|
* so flush it immediately.
|
||||||
|
*/
|
||||||
|
unsigned long s = after.tv_sec - before.tv_sec;
|
||||||
|
long ns = after.tv_nsec - before.tv_nsec;
|
||||||
|
|
||||||
|
if (ns < 0)
|
||||||
|
{
|
||||||
|
--s;
|
||||||
|
ns += 1000000000;
|
||||||
|
|
||||||
|
if (ns < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "timepng: bad clock from kernel\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%lu.%.9ld\n", s, ns);
|
||||||
|
fflush(stdout);
|
||||||
|
if (ferror(stdout))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "timepng: error writing output\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Successful return */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_one_file(FILE *fp, char *name)
|
||||||
|
{
|
||||||
|
FILE *ip = fopen(name, "rb");
|
||||||
|
|
||||||
|
if (ip != NULL)
|
||||||
|
{
|
||||||
|
/* Read the file using libpng; this detects errors and also deals with
|
||||||
|
* files which contain data beyond the end of the file.
|
||||||
|
*/
|
||||||
|
int ok = 0;
|
||||||
|
fpos_t pos;
|
||||||
|
|
||||||
|
if (fgetpos(fp, &pos))
|
||||||
|
{
|
||||||
|
/* Fatal error reading the start: */
|
||||||
|
perror("temporary file");
|
||||||
|
fprintf(stderr, "temporary file fgetpos error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_png(ip, -1/*by row*/, fp/*output*/))
|
||||||
|
{
|
||||||
|
if (ferror(ip))
|
||||||
|
{
|
||||||
|
perror(name);
|
||||||
|
fprintf(stderr, "%s: read error\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
ok = 1; /* read ok */
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s: file not added\n", name);
|
||||||
|
|
||||||
|
(void)fclose(ip);
|
||||||
|
|
||||||
|
/* An error in the output is fatal; exit immediately: */
|
||||||
|
if (ferror(fp))
|
||||||
|
{
|
||||||
|
perror("temporary file");
|
||||||
|
fprintf(stderr, "temporary file write error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Did not read the file successfully, simply rewind the temporary
|
||||||
|
* file. This must happen after the ferror check above to avoid clearing
|
||||||
|
* the error.
|
||||||
|
*/
|
||||||
|
if (fsetpos(fp, &pos))
|
||||||
|
{
|
||||||
|
perror("temporary file");
|
||||||
|
fprintf(stderr, "temporary file fsetpos error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* file open error: */
|
||||||
|
perror(name);
|
||||||
|
fprintf(stderr, "%s: open failed\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* file not added */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(FILE *fp)
|
||||||
|
{
|
||||||
|
if (fp != NULL) fclose(fp);
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage:\n"
|
||||||
|
" timepng --assemble <assembly> {files}\n"
|
||||||
|
" Read the files into <assembly>, output the count. Options are ignored.\n"
|
||||||
|
" timepng --dissemble <assembly> <count> [options]\n"
|
||||||
|
" Time <count> files from <assembly>, additional files may not be given.\n"
|
||||||
|
" Otherwise:\n"
|
||||||
|
" Read the files into a temporary file and time the decode\n"
|
||||||
|
"Transforms:\n"
|
||||||
|
" --by-image: read by image with png_read_png\n"
|
||||||
|
" --<transform>: implies by-image, use PNG_TRANSFORM_<transform>\n"
|
||||||
|
" Otherwise: read by row using png_read_row (to a single row buffer)\n"
|
||||||
|
/* ISO C90 string length max 509 */);fprintf(stderr,
|
||||||
|
"{files}:\n"
|
||||||
|
" PNG files to copy into the assembly and time. Invalid files are skipped\n"
|
||||||
|
" with appropriate error messages. If no files are given the list of files\n"
|
||||||
|
" is read from stdin with each file name terminated by a newline\n"
|
||||||
|
"Output:\n"
|
||||||
|
" For --assemble the output is the name of the assembly file followed by the\n"
|
||||||
|
" count of the files it contains; the arguments for --dissemble. Otherwise\n"
|
||||||
|
" the output is the total decode time in seconds.\n");
|
||||||
|
|
||||||
|
exit(99);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ok = 0;
|
||||||
|
int err = 0;
|
||||||
|
int nfiles = 0;
|
||||||
|
int transforms = -1; /* by row */
|
||||||
|
const char *assembly = NULL;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (argc > 2 && strcmp(argv[1], "--assemble") == 0)
|
||||||
|
{
|
||||||
|
/* Just build the test file, argv[2] is the file name. */
|
||||||
|
assembly = argv[2];
|
||||||
|
fp = fopen(assembly, "wb");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
perror(assembly);
|
||||||
|
fprintf(stderr, "timepng --assemble %s: could not open for write\n",
|
||||||
|
assembly);
|
||||||
|
usage(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
argv += 2;
|
||||||
|
argc -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (argc > 3 && strcmp(argv[1], "--dissemble") == 0)
|
||||||
|
{
|
||||||
|
fp = fopen(argv[2], "rb");
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
perror(argv[2]);
|
||||||
|
fprintf(stderr, "timepng --dissemble %s: could not open for read\n",
|
||||||
|
argv[2]);
|
||||||
|
usage(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
nfiles = atoi(argv[3]);
|
||||||
|
if (nfiles <= 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"timepng --dissemble <file> <count>: %s is not a count\n",
|
||||||
|
argv[3]);
|
||||||
|
exit(99);
|
||||||
|
}
|
||||||
|
#ifdef __COVERITY__
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nfiles &= PNG_UINT_31_MAX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
argv += 3;
|
||||||
|
argc -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
else /* Else use a temporary file */
|
||||||
|
{
|
||||||
|
#ifndef __COVERITY__
|
||||||
|
fp = tmpfile();
|
||||||
|
#else
|
||||||
|
/* Experimental. Coverity says tmpfile() is insecure because it
|
||||||
|
* generates predictable names.
|
||||||
|
*
|
||||||
|
* It is possible to satisfy Coverity by using mkstemp(); however,
|
||||||
|
* any platform supporting mkstemp() undoubtedly has a secure tmpfile()
|
||||||
|
* implementation as well, and doesn't need the fix. Note that
|
||||||
|
* the fix won't work on platforms that don't support mkstemp().
|
||||||
|
*
|
||||||
|
* https://www.securecoding.cert.org/confluence/display/c/
|
||||||
|
* FIO21-C.+Do+not+create+temporary+files+in+shared+directories
|
||||||
|
* says that most historic implementations of tmpfile() provide
|
||||||
|
* only a limited number of possible temporary file names
|
||||||
|
* (usually 26) before file names are recycled. That article also
|
||||||
|
* provides a secure solution that unfortunately depends upon mkstemp().
|
||||||
|
*/
|
||||||
|
char tmpfile[] = "timepng-XXXXXX";
|
||||||
|
int filedes;
|
||||||
|
umask(0177);
|
||||||
|
filedes = mkstemp(tmpfile);
|
||||||
|
if (filedes < 0)
|
||||||
|
fp = NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fp = fdopen(filedes,"w+");
|
||||||
|
/* Hide the filename immediately and ensure that the file does
|
||||||
|
* not exist after the program ends
|
||||||
|
*/
|
||||||
|
(void) unlink(tmpfile);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
perror("tmpfile");
|
||||||
|
fprintf(stderr, "timepng: could not open the temporary file\n");
|
||||||
|
exit(1); /* not a user error */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the transforms: */
|
||||||
|
while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-')
|
||||||
|
{
|
||||||
|
const char *opt = *++argv + 2;
|
||||||
|
|
||||||
|
--argc;
|
||||||
|
|
||||||
|
/* Transforms turn on the by-image processing and maybe set some
|
||||||
|
* transforms:
|
||||||
|
*/
|
||||||
|
if (transforms == -1)
|
||||||
|
transforms = PNG_TRANSFORM_IDENTITY;
|
||||||
|
|
||||||
|
if (strcmp(opt, "by-image") == 0)
|
||||||
|
{
|
||||||
|
/* handled above */
|
||||||
|
}
|
||||||
|
|
||||||
|
# define OPT(name) else if (strcmp(opt, #name) == 0)\
|
||||||
|
transforms |= PNG_TRANSFORM_ ## name
|
||||||
|
|
||||||
|
OPT(STRIP_16);
|
||||||
|
OPT(STRIP_ALPHA);
|
||||||
|
OPT(PACKING);
|
||||||
|
OPT(PACKSWAP);
|
||||||
|
OPT(EXPAND);
|
||||||
|
OPT(INVERT_MONO);
|
||||||
|
OPT(SHIFT);
|
||||||
|
OPT(BGR);
|
||||||
|
OPT(SWAP_ALPHA);
|
||||||
|
OPT(SWAP_ENDIAN);
|
||||||
|
OPT(INVERT_ALPHA);
|
||||||
|
OPT(STRIP_FILLER);
|
||||||
|
OPT(STRIP_FILLER_BEFORE);
|
||||||
|
OPT(STRIP_FILLER_AFTER);
|
||||||
|
OPT(GRAY_TO_RGB);
|
||||||
|
OPT(EXPAND_16);
|
||||||
|
OPT(SCALE_16);
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "timepng %s: unrecognized transform\n", opt);
|
||||||
|
usage(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the files: */
|
||||||
|
if (argc > 1 && nfiles > 0)
|
||||||
|
usage(fp); /* Additional files not valid with --dissemble */
|
||||||
|
|
||||||
|
else if (argc > 1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=1; i<argc; ++i)
|
||||||
|
{
|
||||||
|
if (nfiles == INT_MAX)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: skipped, too many files\n", argv[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (add_one_file(fp, argv[i]))
|
||||||
|
++nfiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (nfiles == 0) /* Read from stdin without --dissemble */
|
||||||
|
{
|
||||||
|
char filename[FILENAME_MAX+1];
|
||||||
|
|
||||||
|
while (fgets(filename, FILENAME_MAX+1, stdin))
|
||||||
|
{
|
||||||
|
size_t len = strlen(filename);
|
||||||
|
|
||||||
|
if (filename[len-1] == '\n')
|
||||||
|
{
|
||||||
|
filename[len-1] = 0;
|
||||||
|
if (nfiles == INT_MAX)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: skipped, too many files\n", filename);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (add_one_file(fp, filename))
|
||||||
|
++nfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "timepng: file name too long: ...%s\n",
|
||||||
|
filename+len-32);
|
||||||
|
err = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ferror(stdin))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "timepng: stdin: read error\n");
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the test, or produce the --assemble output: */
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
if (nfiles > 0)
|
||||||
|
{
|
||||||
|
if (assembly != NULL)
|
||||||
|
{
|
||||||
|
if (fflush(fp) && !ferror(fp) && fclose(fp))
|
||||||
|
{
|
||||||
|
perror(assembly);
|
||||||
|
fprintf(stderr, "%s: close failed\n", assembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%s %d\n", assembly, nfiles);
|
||||||
|
fflush(stdout);
|
||||||
|
ok = !ferror(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok = perform_one_test(fp, nfiles, transforms);
|
||||||
|
(void)fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
usage(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
(void)fclose(fp);
|
||||||
|
|
||||||
|
/* Exit code 0 on success. */
|
||||||
|
return ok == 0;
|
||||||
|
}
|
||||||
|
#else /* !sufficient support */
|
||||||
|
int main(void) { return 77; }
|
||||||
|
#endif /* !sufficient support */
|
|
@ -0,0 +1,83 @@
|
||||||
|
OPERATING SYSTEM SPECIFIC MIPS MSA DETECTION
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Detection of the ability to execute MIPS MSA on an MIPS processor requires
|
||||||
|
operating system support. (The information is not available in user mode.)
|
||||||
|
|
||||||
|
HOW TO USE THIS
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This directory contains C code fragments that can be included in mips/mips_init.c
|
||||||
|
by setting the macro PNG_MIPS_MSA_FILE to the file name in "" or <> at build
|
||||||
|
time. This setting is not recorded in pnglibconf.h and can be changed simply by
|
||||||
|
rebuilding mips/msa_init.o with the required macro definition.
|
||||||
|
|
||||||
|
For any of this code to be used the MIPS MSA code must be enabled and run time
|
||||||
|
checks must be supported. I.e.:
|
||||||
|
|
||||||
|
#if PNG_MIPS_MSA_OPT > 0
|
||||||
|
#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED
|
||||||
|
|
||||||
|
This is done in a 'configure' build by passing configure the argument:
|
||||||
|
|
||||||
|
--enable-mips-msa=check
|
||||||
|
|
||||||
|
Apart from the basic Linux implementation in contrib/mips-msa/linux.c this code
|
||||||
|
is unsupported. That means that it is not even compiled on a regular basis and
|
||||||
|
may be broken in any given minor release.
|
||||||
|
|
||||||
|
FILE FORMAT
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Each file documents its testing status as of the last time it was tested (which
|
||||||
|
may have been a long time ago):
|
||||||
|
|
||||||
|
STATUS: one of:
|
||||||
|
SUPPORTED: This indicates that the file is included in the regularly
|
||||||
|
performed test builds and bugs are fixed when discovered.
|
||||||
|
COMPILED: This indicates that the code did compile at least once. See the
|
||||||
|
more detailed description for the extent to which the result was
|
||||||
|
successful.
|
||||||
|
TESTED: This means the code was fully compiled into the libpng test programs
|
||||||
|
and these were run at least once.
|
||||||
|
|
||||||
|
BUG REPORTS: an email address to which to send reports of problems
|
||||||
|
|
||||||
|
The file is a fragment of C code. It should not define any 'extern' symbols;
|
||||||
|
everything should be static. It must define the function:
|
||||||
|
|
||||||
|
static int png_have_msa(png_structp png_ptr);
|
||||||
|
|
||||||
|
That function must return 1 if MIPS MSA instructions are supported, 0 if not.
|
||||||
|
It must not execute png_error unless it detects a bug. A png_error will prevent
|
||||||
|
the reading of the PNG and in the future, writing too.
|
||||||
|
|
||||||
|
BUG REPORTS
|
||||||
|
-----------
|
||||||
|
|
||||||
|
If you mail a bug report for any file that is not SUPPORTED there may only be
|
||||||
|
limited response. Consider fixing it and sending a patch to fix the problem -
|
||||||
|
this is more likely to result in action.
|
||||||
|
|
||||||
|
CONTRIBUTIONS
|
||||||
|
-------------
|
||||||
|
|
||||||
|
You may send contributions of new implementations to
|
||||||
|
png-mng-implement@sourceforge.net. Please write code in strict C90 C where
|
||||||
|
possible. Obviously OS dependencies are to be expected. If you submit code you
|
||||||
|
must have the authors permission and it must have a license that is acceptable
|
||||||
|
to the current maintainer; in particular that license must permit modification
|
||||||
|
and redistribution.
|
||||||
|
|
||||||
|
Please try to make the contribution a single file and give the file a clear and
|
||||||
|
unambiguous name that identifies the target OS. If multiple files really are
|
||||||
|
required put them all in a sub-directory.
|
||||||
|
|
||||||
|
You must also be prepared to handle bug reports from users of the code, either
|
||||||
|
by joining the png-mng-implement mailing list or by providing an email for the
|
||||||
|
"BUG REPORTS" entry or both. Please make sure that the header of the file
|
||||||
|
contains the STATUS and BUG REPORTS fields as above.
|
||||||
|
|
||||||
|
Please list the OS requirements as precisely as possible. Ideally you should
|
||||||
|
also list the environment in which the code has been tested and certainly list
|
||||||
|
any environments where you suspect it might not work.
|
|
@ -0,0 +1,67 @@
|
||||||
|
|
||||||
|
/* contrib/mips-msa/linux.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Cosmin Truta
|
||||||
|
* Copyright (c) 2016 Glenn Randers-Pehrson
|
||||||
|
* Written by Mandar Sahastrabuddhe, 2016.
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* SEE contrib/mips-msa/README before reporting bugs
|
||||||
|
*
|
||||||
|
* STATUS: SUPPORTED
|
||||||
|
* BUG REPORTS: png-mng-implement@sourceforge.net
|
||||||
|
*
|
||||||
|
* png_have_msa implemented for Linux by reading the widely available
|
||||||
|
* pseudo-file /proc/cpuinfo.
|
||||||
|
*
|
||||||
|
* This code is strict ANSI-C and is probably moderately portable; it does
|
||||||
|
* however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
png_have_msa(png_structp png_ptr)
|
||||||
|
{
|
||||||
|
FILE *f = fopen("/proc/cpuinfo", "rb");
|
||||||
|
|
||||||
|
char *string = "msa";
|
||||||
|
char word[10];
|
||||||
|
|
||||||
|
if (f != NULL)
|
||||||
|
{
|
||||||
|
while(!feof(f))
|
||||||
|
{
|
||||||
|
int ch = fgetc(f);
|
||||||
|
static int i = 0;
|
||||||
|
|
||||||
|
while(!(ch <= 32))
|
||||||
|
{
|
||||||
|
word[i++] = ch;
|
||||||
|
ch = fgetc(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int val = strcmp(string, word);
|
||||||
|
|
||||||
|
if (val == 0) {
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
memset(word, 0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
#ifdef PNG_WARNINGS_SUPPORTED
|
||||||
|
else
|
||||||
|
png_warning(png_ptr, "/proc/cpuinfo open failed");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Copyright 2016 Google Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
FROM gcr.io/oss-fuzz-base/base-builder
|
||||||
|
MAINTAINER glennrp@gmail.com
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y make autoconf automake libtool
|
||||||
|
|
||||||
|
RUN git clone --depth 1 https://github.com/madler/zlib.git
|
||||||
|
RUN git clone --depth 1 https://github.com/glennrp/libpng.git
|
||||||
|
RUN cp libpng/contrib/oss-fuzz/build.sh $SRC
|
||||||
|
WORKDIR libpng
|
|
@ -0,0 +1,36 @@
|
||||||
|
Copyright (c) 2017 Glenn Randers-Pehrson
|
||||||
|
|
||||||
|
This code is released under the libpng license.
|
||||||
|
For conditions of distribution and use, see the disclaimer
|
||||||
|
and license in png.h
|
||||||
|
|
||||||
|
Files in this directory are used by the oss-fuzz project
|
||||||
|
(https://github.com/google/oss-fuzz/tree/master/projects/libpng).
|
||||||
|
for "fuzzing" libpng.
|
||||||
|
|
||||||
|
They were licensed by Google Inc, using the BSD-like Chromium license,
|
||||||
|
which may be found at https://cs.chromium.org/chromium/src/LICENSE, or, if
|
||||||
|
noted in the source, under the Apache-2.0 license, which may
|
||||||
|
be found at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||||
|
If they have been modified, the derivatives are copyright Glenn Randers-Pehrson
|
||||||
|
and are released under the same licenses as the originals. Several of
|
||||||
|
the original files (libpng_read_fuzzer.options, png.dict, project.yaml)
|
||||||
|
had no licensing information; we assumed that these were under the Chromium
|
||||||
|
license. Any new files are released under the libpng license (see png.h).
|
||||||
|
|
||||||
|
The files are
|
||||||
|
Original
|
||||||
|
Filename or derived Copyright License
|
||||||
|
========================= ========== ================ ==========
|
||||||
|
Dockerfile* derived 2017, Glenn R-P Apache 2.0
|
||||||
|
build.sh derived 2017, Glenn R-P Apache 2.0
|
||||||
|
libpng_read_fuzzer.cc derived 2017, Glenn R-P Chromium
|
||||||
|
libpng_read_fuzzer.options original 2015, Chrome Devs Chromium
|
||||||
|
png.dict original 2015, Chrome Devs Chromium
|
||||||
|
README.txt (this file) original 2017, Glenn R-P libpng
|
||||||
|
|
||||||
|
* Dockerfile is a copy of the file used by oss-fuzz. build.sh,
|
||||||
|
png.dict and libpng_read_fuzzer.* are the actual files used by oss-fuzz,
|
||||||
|
which retrieves them from the libpng repository at Github.
|
||||||
|
|
||||||
|
To do: exercise the progressive reader and the png encoder.
|
|
@ -0,0 +1,50 @@
|
||||||
|
#!/bin/bash -eu
|
||||||
|
|
||||||
|
# Copyright 2017-2018 Glenn Randers-Pehrson
|
||||||
|
# Copyright 2016 Google Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Revisions by Glenn Randers-Pehrson, 2017:
|
||||||
|
# 1. Build only the library, not the tools (changed "make -j$(nproc) all" to
|
||||||
|
# "make -j$(nproc) libpng16.la").
|
||||||
|
# 2. Disabled WARNING and WRITE options in pnglibconf.dfa.
|
||||||
|
# 3. Build zlib alongside libpng
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# Disable logging via library build configuration control.
|
||||||
|
cat scripts/pnglibconf.dfa | \
|
||||||
|
sed -e "s/option STDIO/option STDIO disabled/" \
|
||||||
|
-e "s/option WARNING /option WARNING disabled/" \
|
||||||
|
-e "s/option WRITE enables WRITE_INT_FUNCTIONS/option WRITE disabled/" \
|
||||||
|
> scripts/pnglibconf.dfa.temp
|
||||||
|
mv scripts/pnglibconf.dfa.temp scripts/pnglibconf.dfa
|
||||||
|
|
||||||
|
# build the libpng library.
|
||||||
|
autoreconf -f -i
|
||||||
|
./configure --with-libpng-prefix=OSS_FUZZ_
|
||||||
|
make -j$(nproc) clean
|
||||||
|
make -j$(nproc) libpng16.la
|
||||||
|
|
||||||
|
# build libpng_read_fuzzer.
|
||||||
|
$CXX $CXXFLAGS -std=c++11 -I. \
|
||||||
|
$SRC/libpng/contrib/oss-fuzz/libpng_read_fuzzer.cc \
|
||||||
|
-o $OUT/libpng_read_fuzzer \
|
||||||
|
-lFuzzingEngine .libs/libpng16.a -lz
|
||||||
|
|
||||||
|
# add seed corpus.
|
||||||
|
find $SRC/libpng -name "*.png" | grep -v crashers | \
|
||||||
|
xargs zip $OUT/libpng_read_fuzzer_seed_corpus.zip
|
||||||
|
|
||||||
|
cp $SRC/libpng/contrib/oss-fuzz/*.dict \
|
||||||
|
$SRC/libpng/contrib/oss-fuzz/*.options $OUT/
|
|
@ -0,0 +1,208 @@
|
||||||
|
|
||||||
|
// libpng_read_fuzzer.cc
|
||||||
|
// Copyright 2017-2018 Glenn Randers-Pehrson
|
||||||
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that may
|
||||||
|
// be found in the LICENSE file https://cs.chromium.org/chromium/src/LICENSE
|
||||||
|
|
||||||
|
// The modifications in 2017 by Glenn Randers-Pehrson include
|
||||||
|
// 1. addition of a PNG_CLEANUP macro,
|
||||||
|
// 2. setting the option to ignore ADLER32 checksums,
|
||||||
|
// 3. adding "#include <string.h>" which is needed on some platforms
|
||||||
|
// to provide memcpy().
|
||||||
|
// 4. adding read_end_info() and creating an end_info structure.
|
||||||
|
// 5. adding calls to png_set_*() transforms commonly used by browsers.
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define PNG_INTERNAL
|
||||||
|
#include "png.h"
|
||||||
|
|
||||||
|
#define PNG_CLEANUP \
|
||||||
|
if(png_handler.png_ptr) \
|
||||||
|
{ \
|
||||||
|
if (png_handler.row_ptr) \
|
||||||
|
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||||
|
if (png_handler.end_info_ptr) \
|
||||||
|
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||||
|
&png_handler.end_info_ptr); \
|
||||||
|
else if (png_handler.info_ptr) \
|
||||||
|
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||||
|
nullptr); \
|
||||||
|
else \
|
||||||
|
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||||
|
png_handler.png_ptr = nullptr; \
|
||||||
|
png_handler.row_ptr = nullptr; \
|
||||||
|
png_handler.info_ptr = nullptr; \
|
||||||
|
png_handler.end_info_ptr = nullptr; \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BufState {
|
||||||
|
const uint8_t* data;
|
||||||
|
size_t bytes_left;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PngObjectHandler {
|
||||||
|
png_infop info_ptr = nullptr;
|
||||||
|
png_structp png_ptr = nullptr;
|
||||||
|
png_infop end_info_ptr = nullptr;
|
||||||
|
png_voidp row_ptr = nullptr;
|
||||||
|
BufState* buf_state = nullptr;
|
||||||
|
|
||||||
|
~PngObjectHandler() {
|
||||||
|
if (row_ptr)
|
||||||
|
png_free(png_ptr, row_ptr);
|
||||||
|
if (end_info_ptr)
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||||
|
else if (info_ptr)
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||||
|
else
|
||||||
|
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||||
|
delete buf_state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||||
|
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||||
|
if (length > buf_state->bytes_left) {
|
||||||
|
png_error(png_ptr, "read error");
|
||||||
|
}
|
||||||
|
memcpy(data, buf_state->data, length);
|
||||||
|
buf_state->bytes_left -= length;
|
||||||
|
buf_state->data += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* limited_malloc(png_structp, png_alloc_size_t size) {
|
||||||
|
// libpng may allocate large amounts of memory that the fuzzer reports as
|
||||||
|
// an error. In order to silence these errors, make libpng fail when trying
|
||||||
|
// to allocate a large amount. This allocator used to be in the Chromium
|
||||||
|
// version of this fuzzer.
|
||||||
|
// This number is chosen to match the default png_user_chunk_malloc_max.
|
||||||
|
if (size > 8000000)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_free(png_structp, png_voidp ptr) {
|
||||||
|
return free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int kPngHeaderSize = 8;
|
||||||
|
|
||||||
|
// Entry point for LibFuzzer.
|
||||||
|
// Roughly follows the libpng book example:
|
||||||
|
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
|
if (size < kPngHeaderSize) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> v(data, data + size);
|
||||||
|
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||||
|
// not a PNG.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PngObjectHandler png_handler;
|
||||||
|
png_handler.png_ptr = nullptr;
|
||||||
|
png_handler.row_ptr = nullptr;
|
||||||
|
png_handler.info_ptr = nullptr;
|
||||||
|
png_handler.end_info_ptr = nullptr;
|
||||||
|
|
||||||
|
png_handler.png_ptr = png_create_read_struct
|
||||||
|
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
|
if (!png_handler.png_ptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||||
|
if (!png_handler.info_ptr) {
|
||||||
|
PNG_CLEANUP
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_handler.end_info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||||
|
if (!png_handler.end_info_ptr) {
|
||||||
|
PNG_CLEANUP
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a custom allocator that fails for large allocations to avoid OOM.
|
||||||
|
png_set_mem_fn(png_handler.png_ptr, nullptr, limited_malloc, default_free);
|
||||||
|
|
||||||
|
png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
|
||||||
|
#ifdef PNG_IGNORE_ADLER32
|
||||||
|
png_set_option(png_handler.png_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Setting up reading from buffer.
|
||||||
|
png_handler.buf_state = new BufState();
|
||||||
|
png_handler.buf_state->data = data + kPngHeaderSize;
|
||||||
|
png_handler.buf_state->bytes_left = size - kPngHeaderSize;
|
||||||
|
png_set_read_fn(png_handler.png_ptr, png_handler.buf_state, user_read_data);
|
||||||
|
png_set_sig_bytes(png_handler.png_ptr, kPngHeaderSize);
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
|
||||||
|
PNG_CLEANUP
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reading.
|
||||||
|
png_read_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||||
|
|
||||||
|
// reset error handler to put png_deleter into scope.
|
||||||
|
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
|
||||||
|
PNG_CLEANUP
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_uint_32 width, height;
|
||||||
|
int bit_depth, color_type, interlace_type, compression_type;
|
||||||
|
int filter_type;
|
||||||
|
|
||||||
|
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||||
|
&height, &bit_depth, &color_type, &interlace_type,
|
||||||
|
&compression_type, &filter_type)) {
|
||||||
|
PNG_CLEANUP
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is going to be too slow.
|
||||||
|
if (width && height > 100000000 / width) {
|
||||||
|
PNG_CLEANUP
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set several transforms that browsers typically use:
|
||||||
|
png_set_gray_to_rgb(png_handler.png_ptr);
|
||||||
|
png_set_expand(png_handler.png_ptr);
|
||||||
|
png_set_packing(png_handler.png_ptr);
|
||||||
|
png_set_scale_16(png_handler.png_ptr);
|
||||||
|
png_set_tRNS_to_alpha(png_handler.png_ptr);
|
||||||
|
|
||||||
|
int passes = png_set_interlace_handling(png_handler.png_ptr);
|
||||||
|
|
||||||
|
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||||
|
|
||||||
|
png_handler.row_ptr = png_malloc(
|
||||||
|
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||||
|
png_handler.info_ptr));
|
||||||
|
|
||||||
|
for (int pass = 0; pass < passes; ++pass) {
|
||||||
|
for (png_uint_32 y = 0; y < height; ++y) {
|
||||||
|
png_read_row(png_handler.png_ptr,
|
||||||
|
static_cast<png_bytep>(png_handler.row_ptr), nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
png_read_end(png_handler.png_ptr, png_handler.end_info_ptr);
|
||||||
|
|
||||||
|
PNG_CLEANUP
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
[libfuzzer]
|
||||||
|
dict = png.dict
|
|
@ -0,0 +1,39 @@
|
||||||
|
#
|
||||||
|
# AFL dictionary for PNG images
|
||||||
|
# -----------------------------
|
||||||
|
#
|
||||||
|
# Just the basic, standard-originating sections; does not include vendor
|
||||||
|
# extensions.
|
||||||
|
#
|
||||||
|
# Created by Michal Zalewski <lcamtuf@google.com>
|
||||||
|
#
|
||||||
|
|
||||||
|
header_png="\x89PNG\x0d\x0a\x1a\x0a"
|
||||||
|
|
||||||
|
section_IDAT="IDAT"
|
||||||
|
section_IEND="IEND"
|
||||||
|
section_IHDR="IHDR"
|
||||||
|
section_PLTE="PLTE"
|
||||||
|
section_bKGD="bKGD"
|
||||||
|
section_cHRM="cHRM"
|
||||||
|
section_eXIf="eXIf"
|
||||||
|
section_fRAc="fRAc"
|
||||||
|
section_gAMA="gAMA"
|
||||||
|
section_gIFg="gIFg"
|
||||||
|
section_gIFt="gIFt"
|
||||||
|
section_gIFx="gIFx"
|
||||||
|
section_hIST="hIST"
|
||||||
|
section_iCCP="iCCP"
|
||||||
|
section_iTXt="iTXt"
|
||||||
|
section_oFFs="oFFs"
|
||||||
|
section_pCAL="pCAL"
|
||||||
|
section_pHYs="pHYs"
|
||||||
|
section_sBIT="sBIT"
|
||||||
|
section_sCAL="sCAL"
|
||||||
|
section_sPLT="sPLT"
|
||||||
|
section_sRGB="sRGB"
|
||||||
|
section_sTER="sTER"
|
||||||
|
section_tEXt="tEXt"
|
||||||
|
section_tIME="tIME"
|
||||||
|
section_tRNS="tRNS"
|
||||||
|
section_zTXt="zTXt"
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
This demonstrates the use of PNG_USER_CONFIG, pngusr.h and pngusr.dfa
|
||||||
|
to build minimal decoder, encoder, and progressive reader applications.
|
||||||
|
|
||||||
|
See the individual README and pngusr.dfa files for more explanation.
|
|
@ -0,0 +1,10 @@
|
||||||
|
This demonstrates the use of PNG_USER_CONFIG, pngusr.h and pngusr.dfa
|
||||||
|
|
||||||
|
The makefile builds a minimal read-only decoder with embedded libpng
|
||||||
|
and zlib.
|
||||||
|
|
||||||
|
Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC
|
||||||
|
on the make command line.
|
||||||
|
|
||||||
|
If you prefer to use the shared libraries, go to contrib/pngminus
|
||||||
|
and build the png2pnm application there.
|
|
@ -0,0 +1,40 @@
|
||||||
|
# pngminim/decoder/pngusr.dfa
|
||||||
|
#
|
||||||
|
# Copyright (c) 2010-2013 Glenn Randers-Pehrson
|
||||||
|
#
|
||||||
|
# This code is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h
|
||||||
|
|
||||||
|
# First all the build options off:
|
||||||
|
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
# All that is required is some read code. This example switches
|
||||||
|
# on the sequential read code (see ../preader for a progressive
|
||||||
|
# read example).
|
||||||
|
|
||||||
|
option SEQUENTIAL_READ on
|
||||||
|
|
||||||
|
# You must choose fixed or floating point arithmetic:
|
||||||
|
# option FLOATING_POINT on
|
||||||
|
|
||||||
|
option FIXED_POINT on
|
||||||
|
|
||||||
|
# You must chose the internal fixed point implementation or to
|
||||||
|
# use the system floating point. The latter is considerably
|
||||||
|
# smaller (by about 1kbyte on an x86 system):
|
||||||
|
# option FLOATING_ARITHMETIC on
|
||||||
|
|
||||||
|
option FLOATING_ARITHMETIC off
|
||||||
|
|
||||||
|
# Your program will probably need other options. The example
|
||||||
|
# program here, pngm2pnm, requires the following. Take a look
|
||||||
|
# at pnglibconf.h to find out the full set of what has to be
|
||||||
|
# enabled to make the following work.
|
||||||
|
|
||||||
|
option SETJMP on
|
||||||
|
option STDIO on
|
||||||
|
option READ_EXPAND on
|
||||||
|
option READ_STRIP_16_TO_8 on
|
||||||
|
option USER_LIMITS on
|
|
@ -0,0 +1,23 @@
|
||||||
|
/* minrdpngconf.h: headers to make a minimal png-read-only library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, 2010-2013 Glenn Randers-Pehrson
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MINRDPNGCONF_H
|
||||||
|
#define MINRDPNGCONF_H
|
||||||
|
|
||||||
|
/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */
|
||||||
|
|
||||||
|
/* List options to turn off features of the build that do not
|
||||||
|
* affect the API (so are not recorded in pnglibconf.h)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PNG_ALIGN_TYPE PNG_ALIGN_NONE
|
||||||
|
|
||||||
|
#endif /* MINRDPNGCONF_H */
|
|
@ -0,0 +1,10 @@
|
||||||
|
This demonstrates the use of PNG_USER_CONFIG and pngusr.h
|
||||||
|
|
||||||
|
The makefile builds a minimal write-only encoder with embedded libpng
|
||||||
|
and zlib.
|
||||||
|
|
||||||
|
Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC
|
||||||
|
on the make command line.
|
||||||
|
|
||||||
|
If you prefer to use the shared libraries, go to contrib/pngminus
|
||||||
|
and build the pnm2png application there.
|
|
@ -0,0 +1,39 @@
|
||||||
|
# pngminim/encoder/pngusr.dfa
|
||||||
|
#
|
||||||
|
# Copyright (c) 2010-2013 Glenn Randers-Pehrson
|
||||||
|
#
|
||||||
|
# This code is released under the libpng license.
|
||||||
|
# For conditions of distribution and use, see the disclaimer
|
||||||
|
# and license in png.h
|
||||||
|
|
||||||
|
# First all the build options off:
|
||||||
|
|
||||||
|
everything = off
|
||||||
|
|
||||||
|
# Switch on the write code - this makes a minimalist encoder
|
||||||
|
|
||||||
|
option WRITE on
|
||||||
|
|
||||||
|
# These 2 options are required if you need to read PBM (P1 or P4) files.
|
||||||
|
option WRITE_INVERT on
|
||||||
|
option WRITE_PACK on
|
||||||
|
|
||||||
|
# You must choose fixed or floating point arithmetic:
|
||||||
|
# option FLOATING_POINT on
|
||||||
|
|
||||||
|
option FIXED_POINT on
|
||||||
|
|
||||||
|
# You must chose the internal fixed point implementation or to
|
||||||
|
# use the system floating point. The latter is considerably
|
||||||
|
# smaller (by about 1kbyte on an x86 system):
|
||||||
|
# option FLOATING_ARITHMETIC on
|
||||||
|
|
||||||
|
option FLOATING_ARITHMETIC off
|
||||||
|
|
||||||
|
# Your program will probably need other options. The example
|
||||||
|
# program here, pnm2pngm, requires the following. Take a look
|
||||||
|
# at pnglibconf.h to find out the full set of what has to be
|
||||||
|
# enabled to make the following work.
|
||||||
|
|
||||||
|
option SETJMP on
|
||||||
|
option STDIO on
|
|
@ -0,0 +1,23 @@
|
||||||
|
/* minwrpngconf.h: headers to make a minimal png-write-only library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, 2010-2013 Glenn Randers-Pehrson
|
||||||
|
*
|
||||||
|
* This code is released under the libpng license.
|
||||||
|
* For conditions of distribution and use, see the disclaimer
|
||||||
|
* and license in png.h
|
||||||
|
*
|
||||||
|
* Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MINWRPNGCONF_H
|
||||||
|
#define MINWRPNGCONF_H
|
||||||
|
|
||||||
|
/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */
|
||||||
|
|
||||||
|
/* List options to turn off features of the build that do not
|
||||||
|
* affect the API (so are not recorded in pnglibconf.h)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PNG_ALIGN_TYPE PNG_ALIGN_NONE
|
||||||
|
|
||||||
|
#endif /* MINWRPNGCONF_H */
|
|
@ -0,0 +1,15 @@
|
||||||
|
This demonstrates the use of PNG_USER_CONFIG and pngusr.h
|
||||||
|
|
||||||
|
The makefile builds a minimal read-only progressive decoder with
|
||||||
|
embedded libpng, zlib and your system's X library.
|
||||||
|
|
||||||
|
Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC
|
||||||
|
on the make command line.
|
||||||
|
|
||||||
|
Edit makefile if required, to find your X library and include files,
|
||||||
|
then
|
||||||
|
|
||||||
|
make ZLIBSRC=directory
|
||||||
|
|
||||||
|
If you prefer to use the shared libraries, go to contrib/gregbook
|
||||||
|
and build the rpng2-x application there.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue