diff --git a/.travis.yml b/.travis.yml index 25f3ca3e..29d306e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,51 +6,51 @@ matrix: - os: linux env: XCC=gcc HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= LIBCURL=--without-libcurl JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= LIBCURL=--without-libcurl JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= LIBCURL=--without-libcurl JPEG=--without-jpeg PNG=--without-png - os: osx env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= LIBCURL=--without-libcurl JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=i686-w64-mingw32-gcc HOST="--host=i686-w64-mingw32" PREFIX="/usr/i686-w64-mingw32" DEBUG="--enable--tests --enable-debug" WINE=wine + env: XCC=i686-w64-mingw32-gcc HOST="--host=i686-w64-mingw32" PREFIX="/usr/i686-w64-mingw32" DEBUG="--enable-tests --enable-debug" WINE=wine - os: linux env: XCC=i586-mingw32msvc-gcc HOST="--host=i586-mingw32msvc" PREFIX="/usr/i586-mingw32msvc" WINE=wine - os: linux - env: XCC=x86_64-w64-mingw32-gcc HOST="--host=x86_64-w64-mingw32" PREFIX="/usr/x86_64-w64-mingw32" DEBUG="--enable--tests --enable-debug" WINE=wine64 + env: XCC=x86_64-w64-mingw32-gcc HOST="--host=x86_64-w64-mingw32" PREFIX="/usr/x86_64-w64-mingw32" DEBUG="--enable-tests --enable-debug" WINE=wine64 - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= JPEG="--with-jpeg" PNG="--with-png" + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= JPEG="--with-jpeg" PNG="--with-png" - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= JPEG="--with-jpeg" PNG="--with-png" + env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= JPEG="--with-jpeg" PNG="--with-png" - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" JPEG=--without-jpeg PNG=--without-png - - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" JPEG=--without-jpeg PNG=--without-png +# - os: osx +# env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= GD="--with-gd" JPEG=--without-jpeg PNG=--without-png - - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= GD="--with-gd" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= GD="--with-gd" JPEG=--without-jpeg PNG=--without-png +# - os: osx +# env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= GD="--with-gd" JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png +# - os: osx +# env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png +# - os: osx +# env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG=--without-jpeg PNG=--without-png - - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG=--without-jpeg PNG=--without-png +# - os: osx +# env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - - os: osx - env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png + env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png +# - os: osx +# env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" LIBCURL="--with-libcurl" JPEG=--without-jpeg PNG=--without-png - os: linux - env: XCC=gcc HOST= PREFIX=/usr DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG="--with-jpeg" PNG="--with-png" LIBCURL="--with-libcurl" + env: XCC=gcc HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG="--with-jpeg" PNG="--with-png" LIBCURL="--with-libcurl" - os: osx - env: XCC=gcc HOST= PREFIX=/usr/local DEBUG="--enable--tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG="--with-jpeg" PNG="--with-png" LIBCURL="--with-libcurl" + env: XCC=gcc HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= GDKPIXBUF="--with-gdk-pixbuf2" GD="--with-gd" JPEG="--with-jpeg" PNG="--with-png" LIBCURL="--with-libcurl" - os: linux env: XCC=clang HOST= PREFIX=/usr DEBUG="--enable-tests --enable-debug" WINE= JPEG="--with-jpeg" PNG="--with-png" LIBCURL="--with-libcurl" GCOV="--enable-gcov" STATIC="--disable-shared" @@ -81,7 +81,7 @@ before_script: script: - "make" - "sudo make install" - - "make test | tee log | grep succeeded || (cat log|tail -n50; exit 1)" + - "make test | tee log | grep ^\\\\[ || (cat log|tail -n50; exit 1)" after_success: - "make valgrind || (cat valgrind.log && exit 1)" diff --git a/ChangeLog b/ChangeLog index 9b07017e..23e24f53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,80 @@ +2017-06-22 Hayaki Saito + + * src/fromsixel.c: Fix wrong HLS color handling + +2018-05-11 IWAMOTO Kouichi + + * src/tosixel.c: fix to use dcs_end_size with dcs_start use + dcs_start_size instead of dcs_end_size. + +2018-04-04 Yusuke Endoh + + * src/fromgif.c: Allow a deferred clear code in a GIF format + img2sixel says `corrupt GIF(reason: too many codes)` but this is a + wrong behavior. GIF decoder must do nothing when the table is + full. See Section "DEFERRED CLEAR CODE IN LZW COMPRESSION" in [this + document](https://www.w3.org/Graphics/GIF/spec-gif89a.txt). + +2017-05-03 Hayaki Saito + + * README.md: Fix stupid typo, a_dither -> x_dither. + * converters/shell-completion/bash/img2sixel, converters/shell- + completion/zsh/_img2sixel: Add shell completion info -d option + arguments a_dither/x_dither. + * converters/img2sixel.c: Fix typo a_dither -> x_dither + * src/encoder.c: Fix for Issue #57, lack of O_TRUNC when open() is + called. Thanks to @set135. + +2017-05-02 Hayaki Saito + + * Makefile.in, aclocal.m4, config.h.in, configure, + converters/Makefile.am, converters/Makefile.in: Add tests for + a_dither/x_dither + * src/encoder.c, src/quant.c, src/tosixel.c: Style fixes + * converters/img2sixel.c, include/sixel.h.in, + python/libsixel/__init__.py, src/encoder.c: Update comments and + help information + * Makefile.in, aclocal.m4, config.h.in, configure, configure.ac, + package.json: Update package version to 1.8.0 + * NEWS: Update NEWS + * include/sixel.h.in, python/libsixel/__init__.py: Add constants + SIXEL_DIFFUSE_{A,X}_DITHER to python interface + * src/loader.c: Minor fix + * Makefile.in, aclocal.m4, config.h.in, configure: pkg-config v0.29.2 + * Makefile.in, aclocal.m4, config.h.in, configure, configure.ac, + src/loader.c, src/stb_image.h: Use stb_image v2.15 + +2017-04-25 Hayaki Saito + + * src/tosixel.c: Fixed a bug that makes 15bpp dither no effect. + * src/tosixel.c: Strip trailing spaces + +2017-04-21 Hayaki Saito + + * converters/sixel2png.c: Show error details when sixel2png fails + * README.md: Amend fixes + * README.md: More information + +2017-04-19 Hayaki Saito + + * README.md: Additional catching-up + * README.md: Catching up + +2017-04-11 Hayaki Saito + + * src/sixel.5: Fix a type fixed a typo pointed out by + @silverhammermba(#58). + * converters/img2sixel.c, converters/sixel2png.c, src/loader.c: Print + configuration info about libsixel, with "img2sixel -V" + +2016-12-18 Hayaki Saito + + * README.md: Update README + +2016-12-10 Hayaki Saito + + * ChangeLog, Makefile.in: Update ChangeLog + 2016-12-08 Hayaki Saito * Makefile.in, README.md, configure, configure.ac, package.json: @@ -12,8 +89,20 @@ * .travis.yml: travis: change --prefix path to /usr/local in OSX build +2016-10-08 Øyvind Kolås + + * include/sixel.h.in, src/encoder.c, src/quant.c, src/tosixel.c: add + positional/ordered dithers a_dither and x_dither These are + dithering methods arising from searching the paramater spaces for + simple 2d pattern / pseudo random number generators - optimizing a + fitness metric of both statistical measures and human perceptual + preference - see http://pippin.gimp.org/a_dither/ - these dithering + methods are similar to other AM/FM hybrid digital halftoning + methods. + 2016-10-10 Hayaki Saito + * src/tosixel.c: Small fix for wrong error message * configure, configure.ac: Build with -Bsymbolic option if it's available diff --git a/LICENSE.pnmcolormap b/LICENSE.pnmcolormap index f9758404..0b8ab89f 100644 --- a/LICENSE.pnmcolormap +++ b/LICENSE.pnmcolormap @@ -1,5 +1,5 @@ - Derived from ppmquant, originally by Jef Poskanzer. + src/quant.c is derived from ppmquant, originally by Jef Poskanzer. Copyright (C) 1989, 1991 by Jef Poskanzer. Copyright (C) 2001 by Bryan Henderson. diff --git a/Makefile.in b/Makefile.in index 40c907f2..ba70240b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -648,7 +648,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -674,7 +674,7 @@ dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -692,7 +692,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -702,7 +702,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac diff --git a/NEWS b/NEWS index 765e7add..8e282727 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,43 @@ + ------------------------------ - What's new in libsixel-1.7 ? + What's new in libsixel-1.8 ? ------------------------------ +* core: Upgrade stb_image to 2.19. + +* core: Introduce new dithering method, a_dither / x_dither (http://pippin.gimp.org/a_dither/). + Thanks to @hodefoting. + https://github.com/saitoha/libsixel/pull/53 + +* core: Fix wrong HLS color handling. + https://github.com/saitoha/libsixel/commit/0fb35d22e7ba4ed8bce3be42791e6b39c3187b89 + +* core: Improve quality of 15bpp(hi-color mode) dither. + https://github.com/saitoha/libsixel/commit/42f34283defea67c2d6294af4bd7dcb4fdf9f046 + +* img2sixel: Allow a deferred clear code in a GIF format + GIF decoder must do nothing when the table is full. + See Section "DEFERRED CLEAR CODE IN LZW COMPRESSION" in + https://www.w3.org/Graphics/GIF/spec-gif89a.txt. + Thanks to @mame. + https://github.com/saitoha/libsixel/pull/63 + +* img2sixel: Marks -D option (read source images from stdin continuously) as deprecated + https://github.com/saitoha/libsixel/commit/9c8ffa62203899d866fc28e3ab7c6dfd9a0019b1 + +* Some bug fixes and minor improvements. + Thanks to @set135, @ttdoda. + +* Announcement for package maintainers: + Immutable tarball is provided, because GitHub auto-generated tarball may be not immutable. + + https://github.com/saitoha/libsixel/releases/download/v1.8.0/libsixel-1.8.0.tar.gz + + For details, see https://github.com/saitoha/libsixel/issues/64 . + + ------------------------------ + What's new in libsixel-1.7 ? + ------------------------------ * core: Upgrade stb_image to 2.12. * core: Upgrade stb_image_write.h to v1.02. diff --git a/README.md b/README.md index a24e5647..346ffa20 100644 --- a/README.md +++ b/README.md @@ -64,13 +64,27 @@ Furthermore some information of SIXEL-ready SDL applications are reported. ([movie](https://www.youtube.com/watch?v=XubH2W39Xtc)) -### X11 on SIXEL terminals +### Langage Bindings -[Xsixel](https://github.com/saitoha/xserver-sixel) is a kdrive server implementation for SIXEL terminals. +#### [libsixel-python](https://pypi.python.org/pypi/libsixel-python/0.4.0) - ![Xsixel](https://raw.githubusercontent.com/saitoha/libsixel/data/data/xsixel.png) + [converter.py](https://github.com/saitoha/libsixel/blob/master/examples/python/converter.py) example depends on it. - ![Xsixel Blue Print](https://raw.githubusercontent.com/saitoha/libsixel/data/data/HowToBuildTerminalGUI.png) +#### [mruby-sixel](https://github.com/kjunichi/mruby-sixel) + + Used by [mruby-webcam](https://github.com/kjunichi/mruby-webcam). + +#### [libsixel-p6](https://github.com/timo/libsixel-p6) + + A [perl6](https://perl6.org/) bindings for libsixel + +#### [sixel-sys](https://github.com/AdnoC/sixel-sys) + + [Rust](https://www.rust-lang.org/) FFI bindings for libsixel + +#### [sixel-rs](https://github.com/AdnoC/sixel-rs) + + A safe [Rust](https://www.rust-lang.org/) wrapper for libsixel ### W3M integration @@ -87,6 +101,15 @@ It also works with [ranger](https://github.com/hut/ranger). ![w3m-yaimg-sixel](https://raw.githubusercontent.com/saitoha/libsixel/data/data/w3m-yaimg-sixel.jpg) +### X11 on SIXEL terminals + +[Xsixel](https://github.com/saitoha/xserver-sixel) is a kdrive server implementation for SIXEL terminals. + + ![Xsixel](https://raw.githubusercontent.com/saitoha/libsixel/data/data/xsixel.png) + + ![Xsixel Blue Print](https://raw.githubusercontent.com/saitoha/libsixel/data/data/HowToBuildTerminalGUI.png) + + ### GNU Screen integration [Arakiken's GNU Screen fork(sixel branch)](https://bitbucket.org/arakiken/screen/branch/sixel) @@ -146,6 +169,28 @@ Some NetBSD/OpenBSD users are doing amazing challenges. ### Other +#### [sixelSPAD](https://github.com/nilqed/sixelSPAD) + + [screenshot](https://nilqed.github.io/drawfe/) + + Includes 2 commands [fricas2sixel](https://github.com/nilqed/sixelSPAD/blob/master/bin/fricas2sixel) + and [latex2sixel](https://github.com/nilqed/sixelSPAD/blob/master/bin/latex2sixel). + + ![latex2sixel](https://raw.githubusercontent.com/saitoha/libsixel/data/data/latex2sixel.jpg) + +#### [Neofetch](https://github.com/dylanaraps/neofetch) + + Now `sixel` backend is implemented. + See https://github.com/dylanaraps/neofetch/wiki/Image-Backends#sixel + + ![neofetch](https://raw.githubusercontent.com/saitoha/libsixel/data/data/neofetch.png) + +#### [termplay](https://github.com/jD91mZM2/termplay) + + Depends on [sixel-sys](https://github.com/AdnoC/sixel-sys), `--converter=sixel` option is supported. + + [![termplay](https://github.com/saitoha/libsixel/blob/data/data/termplay.png)](https://youtu.be/sOHU1b-Ih90) + #### [sixelPreviewer](https://github.com/mikoto2000/sixelPreviewer) Simple scripts and development environment for realtime edit-previewing for dot, svg, markdown, ...etc. @@ -275,8 +320,7 @@ $ xterm -xrm "XTerm*decTerminalID: vt340" -xrm "XTerm*numColorRegisters: 256" [https://mintty.github.io/](https://mintty.github.io/) - cancer - - [https://github.com/meh/cancer](https://github.com/meh/cancer) + [https://github.com/meh/cancer/](https://github.com/meh/cancer) ## Install @@ -295,6 +339,8 @@ You can install libsixel via the following package systems. - [Portage](http://packages.gentoo.org/package/media-libs/libsixel) - [Ubuntu](https://launchpad.net/ubuntu/+source/libsixel) - [NixOS](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/libsixel/default.nix) +- [OpenBSD Ports](http://openports.se/graphics/libsixel) +- [Fedora Copr](https://copr.fedorainfracloud.org/coprs/saahriktu/libsixel/) ### Build from source package @@ -391,6 +437,10 @@ Options: jajuni -> Jarvis, Judice & Ninke stucki -> Stucki's method burkes -> Burkes' method + a_dither -> positionally stable + arithmetic dither + x_dither -> positionally stable + arithmetic xor based dither -f FINDTYPE, --find-largest=FINDTYPE choose method for finding the largest dimension of median cut boxes for @@ -519,7 +569,7 @@ Options: -P, --penetrate penetrate GNU Screen using DCS pass-through sequence -D, --pipe-mode read source images from stdin - continuously + continuously (deprecated) -v, --verbose show debugging info -V, --version show version and license info -H, --help show this help @@ -1014,6 +1064,9 @@ The MIT License (MIT) - [@vrtsds](https://github.com/vrtsds/) - [@waywardmonkeys](https://github.com/waywardmonkeys/) - [@yoshikaw](https://github.com/yoshikaw/) +- [@turenar](https://github.com/turenar/) +- [@mame](https://github.com/mame/) +- [@hodefoting](https://github.com/hodefoting/) ## Contributing @@ -1273,6 +1326,26 @@ We are greatly inspired by the quality of ImageMagick and added some resampling sayaka-chan(Vala version) also includes SIXEL converter. +- [rust-sixel](https://github.com/meh/rust-sixel) + + A SIXEL encoder written in rust. + + +- [forth-sixel](https://hub.darcs.net/pointfree/forth-sixel) + + A SIXEL encoder written in forth. + + +- [ff2sixel](https://github.com/labdsf/ff2sixel) + + An utility to convert farbfeld images to Sixels. + + +- [tv](https://github.com/hodefoting/tv) + + terminal/commandline image viewer + + - [xpr(x11-apps)](ftp://ftp.x.org/pub/unsupported/programs/xpr/) xpr(1) can convert a xwd(X window dump) format image into a sixel @@ -1284,7 +1357,7 @@ We are greatly inspired by the quality of ImageMagick and added some resampling - [GNUPLOT](http://www.gnuplot.info/) - Recent version of GNUPLOT supports new terminal driver "sixel". + Recent version of GNUPLOT supports new terminal driver "sixeltek(sixel)" / "sixelgd". ![GNUPLOT](https://raw.githubusercontent.com/saitoha/libsixel/data/data/gnuplot.png) @@ -1309,6 +1382,23 @@ We are greatly inspired by the quality of ImageMagick and added some resampling ![ImageMagick](https://raw.githubusercontent.com/saitoha/libsixel/data/data/imagemagick.png) +- [lsix](https://github.com/hackerb9/lsix) + + Like "ls", but for images. Shows thumbnails in terminal using sixel graphics. + ![lsix](https://raw.githubusercontent.com/saitoha/libsixel/data/data/lsix.jpg) + + +- [sixeldraw](https://github.com/aiju/sixeldraw) + + Sixel support for p9p devdraw + + cmapcube on xterm with DEVDRAW=sixeldraw + [![sixeldraw2](https://raw.githubusercontent.com/saitoha/libsixel/data/data/sixeldraw2.png)](https://youtu.be/EOvSrt7Yi00) + + acme on xterm with DEVDRAW=sixeldraw SNARF=1 + [![sixeldraw1](https://raw.githubusercontent.com/saitoha/libsixel/data/data/sixeldraw1.png)](https://youtu.be/eGjSEjxiDjE) + + - [ZX81 Emulator](http://rullf2.xs4all.nl/sg/zx81ce.html) A ZX81 emulator producing Sixel Image Files @@ -1385,3 +1475,10 @@ We are greatly inspired by the quality of ImageMagick and added some resampling thin-wrapper for pysixel and matplotlib + +- [ame.sh](https://github.com/hamano/ame.sh) + +- [matplotlib-sixel](https://github.com/koppa/matplotlib-sixel) + +- [gr framework](http://gr-framework.org/) + diff --git a/aclocal.m4 b/aclocal.m4 index 3d6ef745..1916ae43 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,9 +20,9 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -dnl serial 11 (pkg-config-0.29.1) -dnl +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl @@ -63,7 +63,7 @@ dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29.1]) +[m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ @@ -164,7 +164,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no -AC_MSG_CHECKING([for $1]) +AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) @@ -174,11 +174,11 @@ and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else + else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs @@ -195,7 +195,7 @@ installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -296,7 +296,7 @@ AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR -# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# Copyright (C) 2002-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -311,7 +311,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.15], [], +m4_if([$1], [1.15.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -327,14 +327,14 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.15])dnl +[AM_AUTOMAKE_VERSION([1.15.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -386,7 +386,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd` # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -417,7 +417,7 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -608,7 +608,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -684,7 +684,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -881,7 +881,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -902,7 +902,7 @@ if test x"${install_sh+set}" != xset; then fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# Copyright (C) 2003-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -923,7 +923,7 @@ AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -973,7 +973,7 @@ rm -f confinc confmf # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1012,7 +1012,7 @@ fi # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1041,7 +1041,7 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1088,7 +1088,7 @@ AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1121,8 +1121,9 @@ AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). + dnl FIXME: Remove the need to hard-code Python versions here. m4_define_default([_AM_PYTHON_INTERPRETER_LIST], -[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl +[python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) @@ -1323,7 +1324,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1342,7 +1343,7 @@ AC_DEFUN([AM_RUN_LOG], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1423,7 +1424,7 @@ AC_CONFIG_COMMANDS_PRE( rm -f conftest.file ]) -# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# Copyright (C) 2009-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1483,7 +1484,7 @@ AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1511,7 +1512,7 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# Copyright (C) 2006-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1530,7 +1531,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# Copyright (C) 2004-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/compile b/compile index a85b723c..2ab71e4e 100755 --- a/compile +++ b/compile @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-10-14.11; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -255,7 +255,8 @@ EOF echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -342,6 +343,6 @@ exit $ret # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config.guess b/config.guess index 6c32c864..2193702b 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2014-11-04' +timestamp='2017-05-27' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ timestamp='2014-11-04' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -168,19 +168,29 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. + # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ @@ -197,6 +207,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need @@ -207,13 +224,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` @@ -223,6 +240,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; @@ -235,6 +256,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -251,42 +275,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 @@ -359,16 +383,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build - SUN_ARCH="i386" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` @@ -393,7 +417,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} @@ -618,13 +642,13 @@ EOF sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi @@ -663,11 +687,11 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build @@ -680,12 +704,12 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -790,14 +814,14 @@ EOF echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) @@ -813,10 +837,11 @@ EOF UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin @@ -879,7 +904,7 @@ EOF exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix @@ -902,7 +927,7 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) @@ -933,6 +958,9 @@ EOF crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; @@ -945,6 +973,9 @@ EOF ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; + k1om:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; @@ -970,6 +1001,9 @@ EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; @@ -1002,6 +1036,9 @@ EOF ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; @@ -1021,7 +1058,7 @@ EOF echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} @@ -1100,7 +1137,7 @@ EOF # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1249,6 +1286,9 @@ EOF SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1262,16 +1302,23 @@ EOF UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub @@ -1286,7 +1333,7 @@ EOF exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi @@ -1295,15 +1342,18 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) + NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; - NSR-?:NONSTOP_KERNEL:*:*) + NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk${UNAME_RELEASE} + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; @@ -1317,7 +1367,7 @@ EOF # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" @@ -1359,7 +1409,7 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos @@ -1370,23 +1420,25 @@ EOF x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; esac cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp diff --git a/config.h.in b/config.h.in index f7fb6d05..094ea297 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* define 1 if GCC supports -Bsymbolic */ +#undef HAVE_BSYMBOLIC + /* Define to 1 if you have the `calloc' function. */ #undef HAVE_CALLOC @@ -96,6 +99,9 @@ /* define 1 if GCC supports -Wuninitialized */ #undef HAVE_DIAGNOSTIC_UNINITIALIZED +/* define 1 if GCC supports -Wunused-function */ +#undef HAVE_DIAGNOSTIC_UNUSED_FUNCTION + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H @@ -163,6 +169,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + /* Define to 1 if you have the `pow' function. */ #undef HAVE_POW @@ -245,9 +254,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define to 1 if you have the `usleep' function. */ -#undef HAVE_USLEEP - /* Define to 1 if the system has the `deprecated' variable attribute */ #undef HAVE_VAR_ATTRIBUTE_DEPRECATED diff --git a/config.sub b/config.sub index 7ffe3737..40ea5dfe 100755 --- a/config.sub +++ b/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2014-12-03' +timestamp='2017-04-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -33,7 +33,7 @@ timestamp='2014-12-03' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -53,8 +53,7 @@ timestamp='2014-12-03' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. @@ -68,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -117,8 +116,8 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` @@ -255,15 +254,16 @@ case $basic_machine in | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ + | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -301,11 +301,12 @@ case $basic_machine in | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -314,6 +315,7 @@ case $basic_machine in | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ + | wasm32 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) @@ -376,17 +378,18 @@ case $basic_machine in | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -427,13 +430,15 @@ case $basic_machine in | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -442,6 +447,7 @@ case $basic_machine in | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -518,6 +524,9 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -638,6 +647,14 @@ case $basic_machine in basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -933,6 +950,9 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -1017,7 +1037,7 @@ case $basic_machine in ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) @@ -1027,7 +1047,7 @@ case $basic_machine in ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) @@ -1228,6 +1248,9 @@ case $basic_machine in basic_machine=a29k-wrs os=-vxworks ;; + wasm32) + basic_machine=wasm32-unknown + ;; w65*) basic_machine=w65-wdc os=-none @@ -1373,18 +1396,18 @@ case $os in | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ @@ -1393,7 +1416,8 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1525,6 +1549,8 @@ case $os in ;; -nacl*) ;; + -ios) + ;; -none) ;; *) @@ -1620,6 +1646,9 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; diff --git a/configure b/configure index fbac2e0f..2e205092 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sixel 1.7.3. +# Generated by GNU Autoconf 2.69 for sixel 1.8.0. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sixel' PACKAGE_TARNAME='sixel' -PACKAGE_VERSION='1.7.3' -PACKAGE_STRING='sixel 1.7.3' +PACKAGE_VERSION='1.8.0' +PACKAGE_STRING='sixel 1.8.0' PACKAGE_BUGREPORT='saitoha@me.com' PACKAGE_URL='' @@ -1393,7 +1393,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sixel 1.7.3 to adapt to many kinds of systems. +\`configure' configures sixel 1.8.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1463,7 +1463,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sixel 1.7.3:";; + short | recursive ) echo "Configuration of sixel 1.8.0:";; esac cat <<\_ACEOF @@ -1612,7 +1612,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sixel configure 1.7.3 +sixel configure 1.8.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2027,7 +2027,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sixel $as_me 1.7.3, which was +It was created by sixel $as_me 1.8.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2970,7 +2970,7 @@ fi # Define the identity of the package. PACKAGE='sixel' - VERSION='1.7.3' + VERSION='1.8.0' cat >>confdefs.h <<_ACEOF @@ -13304,11 +13304,12 @@ fi +CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wall" >&5 -$as_echo_n "checking if $CC supports -Wall... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -std=c99" >&5 +$as_echo_n "checking if $CC supports -std=c99... " >&6; } saved_cflags="$CFLAGS" - CFLAGS="-Wall -Werror" + CFLAGS="-std=c99 -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13323,7 +13324,7 @@ _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - AM_CFLAGS="$AM_CFLAGS -Wall" + CFLAGS="$CFLAGS -std=c99" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -13333,10 +13334,10 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wextra" >&5 -$as_echo_n "checking if $CC supports -Wextra... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wall" >&5 +$as_echo_n "checking if $CC supports -Wall... " >&6; } saved_cflags="$CFLAGS" - CFLAGS="-Wextra -Werror" + CFLAGS="-Wall -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13351,7 +13352,7 @@ _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - AM_CFLAGS="$AM_CFLAGS -Wextra" + AM_CFLAGS="$AM_CFLAGS -Wall" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -13361,10 +13362,10 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wpedantic" >&5 -$as_echo_n "checking if $CC supports -Wpedantic... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wextra" >&5 +$as_echo_n "checking if $CC supports -Wextra... " >&6; } saved_cflags="$CFLAGS" - CFLAGS="-Wpedantic -Werror" + CFLAGS="-Wextra -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13379,7 +13380,7 @@ _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - AM_CFLAGS="$AM_CFLAGS -Wpedantic" + AM_CFLAGS="$AM_CFLAGS -Wextra" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -13440,9 +13441,11 @@ $as_echo "yes" >&6; } $as_echo "#define HAVE_DIAGNOSTIC_SIGN_CONVERSION 1" >>confdefs.h else - : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext] +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" @@ -13469,9 +13472,11 @@ $as_echo "yes" >&6; } $as_echo "#define HAVE_DIAGNOSTIC_UNINITIALIZED 1" >>confdefs.h else - : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext] +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" @@ -13493,7 +13498,7 @@ _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - AM_CFLAGS="$AM_CFLAGS -Wstrict-overflow" + AM_CFLAGS="$AM_CFLAGS -Wstrict-overflow=1" $as_echo "#define HAVE_DIAGNOSTIC_STRICT_OVERFLOW 1" >>confdefs.h @@ -13599,6 +13604,37 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wunused-function" >&5 +$as_echo_n "checking if $CC supports -Wunused-function... " >&6; } + saved_cflags="$CFLAGS" + CFLAGS="-Wunused-function -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + AM_CFLAGS="$AM_CFLAGS -Wunused-function" + +$as_echo "#define HAVE_DIAGNOSTIC_UNUSED_FUNCTION 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$saved_cflags" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Bsymbolic" >&5 $as_echo_n "checking if $CC supports -Bsymbolic... " >&6; } saved_cflags="$CFLAGS" @@ -13926,7 +13962,7 @@ for ac_func in memcpy \ setmode \ _setmode \ signal \ - usleep \ + nanosleep \ strdup \ strtoul \ calloc \ @@ -14038,8 +14074,8 @@ if test x$with_gdk_pixbuf2 != xno; then if test x${PKG_CONFIG} != x; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GDK_PIXBUF" >&5 -$as_echo_n "checking for GDK_PIXBUF... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdk-pixbuf-2.0" >&5 +$as_echo_n "checking for gdk-pixbuf-2.0... " >&6; } if test -n "$GDK_PIXBUF_CFLAGS"; then pkg_cv_GDK_PIXBUF_CFLAGS="$GDK_PIXBUF_CFLAGS" @@ -14079,7 +14115,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -14097,7 +14133,7 @@ fi have_gdk_pixbuf2=no elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_gdk_pixbuf2=no else @@ -14206,8 +14242,8 @@ fi if test x$have_gd != xyes -a ! -d "$with_gd"; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GD" >&5 -$as_echo_n "checking for GD... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdlib" >&5 +$as_echo_n "checking for gdlib... " >&6; } if test -n "$GD_CFLAGS"; then pkg_cv_GD_CFLAGS="$GD_CFLAGS" @@ -14247,7 +14283,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -14265,7 +14301,7 @@ fi have_gd=no elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_gd=no else @@ -14991,8 +15027,8 @@ fi if test x${PKG_CONFIG} != x; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBCURL" >&5 -$as_echo_n "checking for LIBCURL... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcurl" >&5 +$as_echo_n "checking for libcurl... " >&6; } if test -n "$LIBCURL_CFLAGS"; then pkg_cv_LIBCURL_CFLAGS="$LIBCURL_CFLAGS" @@ -15032,7 +15068,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15050,7 +15086,7 @@ fi have_curl=no elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_curl=no else @@ -15158,8 +15194,8 @@ fi if test x${PKG_CONFIG} != x; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBJPEG" >&5 -$as_echo_n "checking for LIBJPEG... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libjpeg" >&5 +$as_echo_n "checking for libjpeg... " >&6; } if test -n "$LIBJPEG_CFLAGS"; then pkg_cv_LIBJPEG_CFLAGS="$LIBJPEG_CFLAGS" @@ -15199,7 +15235,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15217,7 +15253,7 @@ fi have_jpeg=no elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_jpeg=no else @@ -15328,8 +15364,8 @@ fi if test x${PKG_CONFIG} != x; then pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBPNG" >&5 -$as_echo_n "checking for LIBPNG... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpng" >&5 +$as_echo_n "checking for libpng... " >&6; } if test -n "$LIBPNG_CFLAGS"; then pkg_cv_LIBPNG_CFLAGS="$LIBPNG_CFLAGS" @@ -15369,7 +15405,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15387,7 +15423,7 @@ fi have_png=no elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_png=no else @@ -15490,7 +15526,7 @@ if ${am_cv_pathless_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else - for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do + for am_cv_pathless_PYTHON in python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do test "$am_cv_pathless_PYTHON" = none && break prog="import sys # split strings by '.' and convert to numeric. Append some zeros @@ -16337,7 +16373,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sixel $as_me 1.7.3, which was +This file was extended by sixel $as_me 1.8.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16403,7 +16439,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sixel config.status 1.7.3 +sixel config.status 1.8.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index e09719ae..d5d130dc 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) LT_PREREQ([2.4]) -AC_INIT([sixel], [1.7.3], [saitoha@me.com]) +AC_INIT([sixel], [1.8.0], [saitoha@me.com]) LS_LT_CURRENT=1 LS_LT_REVISION=6 LS_LT_AGE=0 @@ -182,19 +182,20 @@ AC_DEFUN([LS_CHECK_CFLAG], [ CFLAGS="$saved_cflags" ]) +CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L" +LS_CHECK_CFLAG([-std=c99], [CFLAGS="$CFLAGS -std=c99"], []) LS_CHECK_CFLAG([-Wall],[AM_CFLAGS="$AM_CFLAGS -Wall"], []) LS_CHECK_CFLAG([-Wextra],[AM_CFLAGS="$AM_CFLAGS -Wextra"], []) -LS_CHECK_CFLAG([-Wpedantic],[AM_CFLAGS="$AM_CFLAGS -Wpedantic"], []) LS_CHECK_CFLAG([-Wformat=2],[AM_CFLAGS="$AM_CFLAGS -Wformat=2"], []) LS_CHECK_CFLAG([-Wsign-conversion], - [AM_CFLAGS="$AM_CFLAGS -Wsign-conversion"] + [AM_CFLAGS="$AM_CFLAGS -Wsign-conversion" AC_DEFINE(HAVE_DIAGNOSTIC_SIGN_CONVERSION, 1, [define 1 if GCC supports -Wsign-conversion])]) LS_CHECK_CFLAG([-Wuninitialized], - [AM_CFLAGS="$AM_CFLAGS -Wuninitialized"] + [AM_CFLAGS="$AM_CFLAGS -Wuninitialized" AC_DEFINE(HAVE_DIAGNOSTIC_UNINITIALIZED, 1, [define 1 if GCC supports -Wuninitialized])]) LS_CHECK_CFLAG([-Wstrict-overflow], - [AM_CFLAGS="$AM_CFLAGS -Wstrict-overflow" - AC_DEFINE(HAVE_DIAGNOSTIC_STRICT_OVERFLOW, 1, [define 1 if GCC supports -Wstrict-overeflow])]) + [AM_CFLAGS="$AM_CFLAGS -Wstrict-overflow=1" + AC_DEFINE(HAVE_DIAGNOSTIC_STRICT_OVERFLOW, 1, [define 1 if GCC supports -Wstrict-overeflow=1])]) LS_CHECK_CFLAG([-Wshadow], [AM_CFLAGS="$AM_CFLAGS -Wshadow" AC_DEFINE(HAVE_DIAGNOSTIC_SHADOW, 1, [define 1 if GCC supports -Wshadow])]) @@ -204,6 +205,9 @@ LS_CHECK_CFLAG([-Wdouble-promotion], LS_CHECK_CFLAG([-Wswitch-default], [AM_CFLAGS="$AM_CFLAGS -Wswitch-default" AC_DEFINE(HAVE_DIAGNOSTIC_SWITCH_DEFAULT, 1, [define 1 if GCC supports -Wswitch-default])]) +LS_CHECK_CFLAG([-Wunused-function], + [AM_CFLAGS="$AM_CFLAGS -Wunused-function" + AC_DEFINE(HAVE_DIAGNOSTIC_UNUSED_FUNCTION, 1, [define 1 if GCC supports -Wunused-function])]) LS_CHECK_CFLAG([-Bsymbolic], [AM_CFLAGS="$AM_CFLAGS -Bsymbolic" AC_DEFINE(HAVE_BSYMBOLIC, 1, [define 1 if GCC supports -Bsymbolic])]) @@ -267,7 +271,7 @@ AC_CHECK_FUNCS([memcpy \ setmode \ _setmode \ signal \ - usleep \ + nanosleep \ strdup \ strtoul \ calloc \ diff --git a/converters/Makefile.am b/converters/Makefile.am index b0a21eef..7318528b 100644 --- a/converters/Makefile.am +++ b/converters/Makefile.am @@ -40,7 +40,10 @@ check: test_impl test: all test_impl test_impl: + @echo '[start]' if WANT_IMG2SIXEL + + @echo '[test1] invalid option handling' touch testfile chmod -r testfile test ! $$($(WINE) ./img2sixel testfile) @@ -70,9 +73,15 @@ if WANT_IMG2SIXEL test ! $$($(WINE) ./img2sixel -I -p8 $(top_srcdir)/images/snake.png) test ! $$($(WINE) ./img2sixel -p64 -bxterm256 $(top_srcdir)/images/snake.png) test ! $$($(WINE) ./img2sixel -8 -P $(top_srcdir)/images/snake.png) + + @echo '[test2] STDIN handling' test ! $$(echo -n a | $(WINE) ./img2sixel) + + @echo '[test3] print information' $(WINE) ./img2sixel -H $(WINE) ./img2sixel -V + + @echo '[test4] conversion options' $(WINE) ./img2sixel $(top_srcdir)/images/snake.jpg -datkinson -flum -saverage | $(WINE) ./img2sixel | tee snake.sixel $(WINE) ./img2sixel -w50% -h150% -dfs -Bblue -thls -shistogram < $(top_srcdir)/images/snake.jpg | tee snake2.sixel $(WINE) ./img2sixel -w2100 -h2100 -djajuni -bxterm256 -o snake3.sixel < $(top_srcdir)/images/snake.jpg @@ -98,8 +107,8 @@ if WANT_IMG2SIXEL $(WINE) ./img2sixel $(top_srcdir)/images/snake-grayscale.png $(WINE) ./img2sixel -m $(top_srcdir)/images/map8-palette.png $(top_srcdir)/images/snake-grayscale.png $(WINE) ./img2sixel -m $(top_srcdir)/images/snake-grayscale.png $(top_srcdir)/images/snake.png - $(WINE) ./img2sixel -c200x200+100+100 $(top_srcdir)/images/snake-grayscale.png - $(WINE) ./img2sixel -c200x200+100+100 -w400 $(top_srcdir)/images/snake-grayscale.png + $(WINE) ./img2sixel -c200x200+100+100 -dx_dither $(top_srcdir)/images/snake-grayscale.png + $(WINE) ./img2sixel -c200x200+100+100 -w400 -da_dither $(top_srcdir)/images/snake-grayscale.png $(WINE) ./img2sixel -I $(top_srcdir)/images/snake-grayscale.png $(WINE) ./img2sixel -I $(top_srcdir)/images/snake-grayscale.jpg $(WINE) ./img2sixel -m $(top_srcdir)/images/map8.six -m $(top_srcdir)/images/map8.six $(top_srcdir)/images/snake.six @@ -108,6 +117,8 @@ if WANT_IMG2SIXEL $(WINE) ./img2sixel -bxterm16 $(top_srcdir)/images/snake.six $(WINE) ./img2sixel -e $(top_srcdir)/images/snake.six $(WINE) ./img2sixel -I $(top_srcdir)/images/snake.six + $(WINE) ./img2sixel -I -da_dither -w100 $(top_srcdir)/images/snake.six + $(WINE) ./img2sixel -I -dx_dither -h100 $(top_srcdir)/images/snake.six $(WINE) ./img2sixel -I -c2000x100+40+20 -wauto -h200 -qhigh -dfs -rbilinear -trgb $(top_srcdir)/images/snake.ppm $(WINE) ./img2sixel -I -v -w200 -hauto -c100x1000+40+20 -qlow -dnone -rhamming -thls $(top_srcdir)/images/snake.bmp $(WINE) ./img2sixel -m $(top_srcdir)/images/map8.png -w200 -fauto -rwelsh $(top_srcdir)/images/egret.jpg @@ -119,21 +130,34 @@ if WANT_IMG2SIXEL $(WINE) ./img2sixel -e -h140 -rlanczos4 -P $(top_srcdir)/images/snake.jpg $(WINE) ./img2sixel -e -i -P $(top_srcdir)/images/snake.jpg > /dev/null $(WINE) ./img2sixel -w2047 -h2047 $(top_srcdir)/images/snake.png | $(WINE) ./img2sixel > /dev/null + + @echo '[test5] DCS arguments handling' seq 0 10 | while read i; do \ seq 0 2 | while read j; do \ - $(WINE) ./img2sixel $(top_srcdir)/images/map8.png | \ + $(WINE) ./img2sixel $(top_srcdir)/images/map8.png | \ sed "s/Pq/P$${i};;$${j}q/" | \ $(WINE) ./img2sixel; \ done; \ done + + @echo + @echo '[test6] DCS format variations' $(WINE) ./img2sixel $(top_srcdir)/images/snake.png| sed 's/C/C:/g'| tr : '\t'| $(WINE) ./img2sixel $(WINE) ./img2sixel $(top_srcdir)/images/snake.png| sed 's/"1;1;600;450/"1;1;700;500/'| $(WINE) ./img2sixel + + @echo + @echo '[test7] animation' $(WINE) ./img2sixel -ldisable -dnone -u -lauto $(top_srcdir)/images/seq2gif.gif $(WINE) ./img2sixel -ldisable -dnone -g $(top_srcdir)/images/seq2gif.gif $(WINE) ./img2sixel -ldisable -dnone -u -g $(top_srcdir)/images/seq2gif.gif $(WINE) ./img2sixel -S -datkinson $(top_srcdir)/images/seq2gif.gif + + @echo + @echo '[test8] progressive jpeg' $(WINE) ./img2sixel $(top_srcdir)/images/snake-progressive.jpg if HAVE_PNG + @echo + @echo '[test9] various PNG' $(WINE) ./img2sixel $(top_srcdir)/images/pngsuite/basic/basn0g01.png $(WINE) ./img2sixel $(top_srcdir)/images/pngsuite/basic/basn0g02.png $(WINE) ./img2sixel $(top_srcdir)/images/pngsuite/basic/basn0g04.png @@ -199,6 +223,8 @@ if HAVE_PNG $(WINE) ./img2sixel -w32 -B\#fff $(top_srcdir)/images/pngsuite/background/bgyn6a16.png endif if HAVE_CURL + @echo + @echo '[test10] curl' test ! $$($(WINE) ./img2sixel file:///test) test ! $$($(WINE) ./img2sixel https:///test) $(WINE) ./img2sixel file:///$$(pwd)/$(top_srcdir)/images/snake.jpg @@ -218,6 +244,7 @@ if HAVE_CURL fi endif if WANT_SIXEL2PNG + @echo '[test11] sixel2png' test ! $$($(WINE) ./sixel2png -i unknown.sixel) test ! $$($(WINE) ./sixel2png -% < snake.sixel) test ! $$($(WINE) ./sixel2png invalid_filename < snake.sixel) @@ -228,17 +255,9 @@ if WANT_SIXEL2PNG $(WINE) ./sixel2png - - < snake3.sixel > snake3.png $(WINE) ./sixel2png -i snake.sixel -o snake4.png endif + + @echo '[test13] documentation' $(WINE) ./img2sixel -H| grep ^\ \*\-|sed 's/^\ *//'| cut -f1 -d' '| cut -f1 -d, > options1.txt - rm -f sixel.pipe - if test "$(WINE)" = "" && which mkfifo && which pkill; then \ - mkfifo sixel.pipe; \ - ($(WINE) ./img2sixel -D < sixel.pipe&); \ - cat $(top_srcdir)/images/snake.jpg > sixel.pipe; \ - echo -n > sixel.pipe; \ - sleep 1; \ - rm -f sixel.pipe; \ - pkill img2sixel; \ - fi || true grep ^\.B $(top_srcdir)/converters/img2sixel.1 | cut -f2 -d " " | grep "^\\\\" | tr -d '\\' | tr -d , > options2.txt grep ' --' $(top_srcdir)/converters/shell-completion/bash/img2sixel| grep -v "' "| sed 's/.* \(-.\) .*/\1/' > options3.txt grep '{-' $(top_srcdir)/converters/shell-completion/zsh/_img2sixel|cut -f1 -d,|cut -f2 -d'{' > options4.txt @@ -246,7 +265,8 @@ endif diff options2.txt options3.txt diff options3.txt options4.txt endif - @echo succeeded + + @echo '[succeeded]' winetest: all WINE=wine $(MAKE) test diff --git a/converters/Makefile.in b/converters/Makefile.in index b10b5092..54ed81a0 100644 --- a/converters/Makefile.in +++ b/converters/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1007,6 +1007,9 @@ check: test_impl test: all test_impl test_impl: + @echo '[start]' + +@WANT_IMG2SIXEL_TRUE@ @echo '[test1] invalid option handling' @WANT_IMG2SIXEL_TRUE@ touch testfile @WANT_IMG2SIXEL_TRUE@ chmod -r testfile @WANT_IMG2SIXEL_TRUE@ test ! $$($(WINE) ./img2sixel testfile) @@ -1036,9 +1039,15 @@ test_impl: @WANT_IMG2SIXEL_TRUE@ test ! $$($(WINE) ./img2sixel -I -p8 $(top_srcdir)/images/snake.png) @WANT_IMG2SIXEL_TRUE@ test ! $$($(WINE) ./img2sixel -p64 -bxterm256 $(top_srcdir)/images/snake.png) @WANT_IMG2SIXEL_TRUE@ test ! $$($(WINE) ./img2sixel -8 -P $(top_srcdir)/images/snake.png) + +@WANT_IMG2SIXEL_TRUE@ @echo '[test2] STDIN handling' @WANT_IMG2SIXEL_TRUE@ test ! $$(echo -n a | $(WINE) ./img2sixel) + +@WANT_IMG2SIXEL_TRUE@ @echo '[test3] print information' @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -H @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -V + +@WANT_IMG2SIXEL_TRUE@ @echo '[test4] conversion options' @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/snake.jpg -datkinson -flum -saverage | $(WINE) ./img2sixel | tee snake.sixel @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -w50% -h150% -dfs -Bblue -thls -shistogram < $(top_srcdir)/images/snake.jpg | tee snake2.sixel @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -w2100 -h2100 -djajuni -bxterm256 -o snake3.sixel < $(top_srcdir)/images/snake.jpg @@ -1064,8 +1073,8 @@ test_impl: @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/snake-grayscale.png @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -m $(top_srcdir)/images/map8-palette.png $(top_srcdir)/images/snake-grayscale.png @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -m $(top_srcdir)/images/snake-grayscale.png $(top_srcdir)/images/snake.png -@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -c200x200+100+100 $(top_srcdir)/images/snake-grayscale.png -@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -c200x200+100+100 -w400 $(top_srcdir)/images/snake-grayscale.png +@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -c200x200+100+100 -dx_dither $(top_srcdir)/images/snake-grayscale.png +@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -c200x200+100+100 -w400 -da_dither $(top_srcdir)/images/snake-grayscale.png @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -I $(top_srcdir)/images/snake-grayscale.png @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -I $(top_srcdir)/images/snake-grayscale.jpg @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -m $(top_srcdir)/images/map8.six -m $(top_srcdir)/images/map8.six $(top_srcdir)/images/snake.six @@ -1074,6 +1083,8 @@ test_impl: @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -bxterm16 $(top_srcdir)/images/snake.six @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -e $(top_srcdir)/images/snake.six @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -I $(top_srcdir)/images/snake.six +@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -I -da_dither -w100 $(top_srcdir)/images/snake.six +@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -I -dx_dither -h100 $(top_srcdir)/images/snake.six @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -I -c2000x100+40+20 -wauto -h200 -qhigh -dfs -rbilinear -trgb $(top_srcdir)/images/snake.ppm @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -I -v -w200 -hauto -c100x1000+40+20 -qlow -dnone -rhamming -thls $(top_srcdir)/images/snake.bmp @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -m $(top_srcdir)/images/map8.png -w200 -fauto -rwelsh $(top_srcdir)/images/egret.jpg @@ -1085,20 +1096,33 @@ test_impl: @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -e -h140 -rlanczos4 -P $(top_srcdir)/images/snake.jpg @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -e -i -P $(top_srcdir)/images/snake.jpg > /dev/null @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -w2047 -h2047 $(top_srcdir)/images/snake.png | $(WINE) ./img2sixel > /dev/null + +@WANT_IMG2SIXEL_TRUE@ @echo '[test5] DCS arguments handling' @WANT_IMG2SIXEL_TRUE@ seq 0 10 | while read i; do \ @WANT_IMG2SIXEL_TRUE@ seq 0 2 | while read j; do \ -@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/map8.png | \ +@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/map8.png | \ @WANT_IMG2SIXEL_TRUE@ sed "s/Pq/P$${i};;$${j}q/" | \ @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel; \ @WANT_IMG2SIXEL_TRUE@ done; \ @WANT_IMG2SIXEL_TRUE@ done + +@WANT_IMG2SIXEL_TRUE@ @echo +@WANT_IMG2SIXEL_TRUE@ @echo '[test6] DCS format variations' @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/snake.png| sed 's/C/C:/g'| tr : '\t'| $(WINE) ./img2sixel @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/snake.png| sed 's/"1;1;600;450/"1;1;700;500/'| $(WINE) ./img2sixel + +@WANT_IMG2SIXEL_TRUE@ @echo +@WANT_IMG2SIXEL_TRUE@ @echo '[test7] animation' @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -ldisable -dnone -u -lauto $(top_srcdir)/images/seq2gif.gif @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -ldisable -dnone -g $(top_srcdir)/images/seq2gif.gif @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -ldisable -dnone -u -g $(top_srcdir)/images/seq2gif.gif @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -S -datkinson $(top_srcdir)/images/seq2gif.gif + +@WANT_IMG2SIXEL_TRUE@ @echo +@WANT_IMG2SIXEL_TRUE@ @echo '[test8] progressive jpeg' @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/snake-progressive.jpg +@HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ @echo +@HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ @echo '[test9] various PNG' @HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/pngsuite/basic/basn0g01.png @HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/pngsuite/basic/basn0g02.png @HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel $(top_srcdir)/images/pngsuite/basic/basn0g04.png @@ -1162,6 +1186,8 @@ test_impl: @HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -w32 -B\#fff $(top_srcdir)/images/pngsuite/background/bggn4a16.png @HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -w32 -B\#fff $(top_srcdir)/images/pngsuite/background/bgwn6a08.png @HAVE_PNG_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -w32 -B\#fff $(top_srcdir)/images/pngsuite/background/bgyn6a16.png +@HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ @echo +@HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ @echo '[test10] curl' @HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ test ! $$($(WINE) ./img2sixel file:///test) @HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ test ! $$($(WINE) ./img2sixel https:///test) @HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel file:///$$(pwd)/$(top_srcdir)/images/snake.jpg @@ -1179,6 +1205,7 @@ test_impl: @HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ sleep 1; \ @HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -k 'https://localhost:4443/snake.sixel'; \ @HAVE_CURL_TRUE@@WANT_IMG2SIXEL_TRUE@ fi +@WANT_IMG2SIXEL_TRUE@@WANT_SIXEL2PNG_TRUE@ @echo '[test11] sixel2png' @WANT_IMG2SIXEL_TRUE@@WANT_SIXEL2PNG_TRUE@ test ! $$($(WINE) ./sixel2png -i unknown.sixel) @WANT_IMG2SIXEL_TRUE@@WANT_SIXEL2PNG_TRUE@ test ! $$($(WINE) ./sixel2png -% < snake.sixel) @WANT_IMG2SIXEL_TRUE@@WANT_SIXEL2PNG_TRUE@ test ! $$($(WINE) ./sixel2png invalid_filename < snake.sixel) @@ -1188,24 +1215,17 @@ test_impl: @WANT_IMG2SIXEL_TRUE@@WANT_SIXEL2PNG_TRUE@ $(WINE) ./sixel2png < snake2.sixel > snake2.png @WANT_IMG2SIXEL_TRUE@@WANT_SIXEL2PNG_TRUE@ $(WINE) ./sixel2png - - < snake3.sixel > snake3.png @WANT_IMG2SIXEL_TRUE@@WANT_SIXEL2PNG_TRUE@ $(WINE) ./sixel2png -i snake.sixel -o snake4.png + +@WANT_IMG2SIXEL_TRUE@ @echo '[test13] documentation' @WANT_IMG2SIXEL_TRUE@ $(WINE) ./img2sixel -H| grep ^\ \*\-|sed 's/^\ *//'| cut -f1 -d' '| cut -f1 -d, > options1.txt -@WANT_IMG2SIXEL_TRUE@ rm -f sixel.pipe -@WANT_IMG2SIXEL_TRUE@ if test "$(WINE)" = "" && which mkfifo && which pkill; then \ -@WANT_IMG2SIXEL_TRUE@ mkfifo sixel.pipe; \ -@WANT_IMG2SIXEL_TRUE@ ($(WINE) ./img2sixel -D < sixel.pipe&); \ -@WANT_IMG2SIXEL_TRUE@ cat $(top_srcdir)/images/snake.jpg > sixel.pipe; \ -@WANT_IMG2SIXEL_TRUE@ echo -n > sixel.pipe; \ -@WANT_IMG2SIXEL_TRUE@ sleep 1; \ -@WANT_IMG2SIXEL_TRUE@ rm -f sixel.pipe; \ -@WANT_IMG2SIXEL_TRUE@ pkill img2sixel; \ -@WANT_IMG2SIXEL_TRUE@ fi || true @WANT_IMG2SIXEL_TRUE@ grep ^\.B $(top_srcdir)/converters/img2sixel.1 | cut -f2 -d " " | grep "^\\\\" | tr -d '\\' | tr -d , > options2.txt @WANT_IMG2SIXEL_TRUE@ grep ' --' $(top_srcdir)/converters/shell-completion/bash/img2sixel| grep -v "' "| sed 's/.* \(-.\) .*/\1/' > options3.txt @WANT_IMG2SIXEL_TRUE@ grep '{-' $(top_srcdir)/converters/shell-completion/zsh/_img2sixel|cut -f1 -d,|cut -f2 -d'{' > options4.txt @WANT_IMG2SIXEL_TRUE@ diff options1.txt options2.txt @WANT_IMG2SIXEL_TRUE@ diff options2.txt options3.txt @WANT_IMG2SIXEL_TRUE@ diff options3.txt options4.txt - @echo succeeded + + @echo '[succeeded]' winetest: all WINE=wine $(MAKE) test diff --git a/converters/img2sixel.1 b/converters/img2sixel.1 index d7ad9d96..4e19180a 100644 --- a/converters/img2sixel.1 +++ b/converters/img2sixel.1 @@ -82,7 +82,7 @@ choose diffusion method which used with color reduction. .br auto -> choose diffusion type automatically (default) .br -none -> do not diffusion +none -> do not diffuse .br fs -> Floyd-Steinberg method .br @@ -93,6 +93,10 @@ jajuni -> Jarvis, Judice & Ninke stucki -> Stucki's method .br burkes -> Burkes' method +.br +a_dither -> positionally stable arithmetic dither +.br +a_dither -> positionally stable arithmetic xor based dither .TP 5 .B \-f \fIFINDTYPE\fP, \-\-find\-largest=\fIFINDTYPE\fP choose method for finding the largest dimension of median @@ -254,7 +258,7 @@ rgb:rrrr/gggg/bbbb .B \-P, \-\-penetrate penetrate GNU Screen using DCS pass-through sequence. .TP 5 -.B \-D, \-\-pipe\-mode +.B \-D, \-\-pipe\-mode (deprecated) read source images from stdin continuously. .TP 5 .B \-v, \-\-verbose @@ -487,6 +491,11 @@ haru (@uobikiemukot) Vertis Sidus (@vrtsds) Bruce Mitchener (@waywardmonkeys) Kazuhiro YOSHIKAWA (@yoshikaw) +Turenar +Yusuke Endoh +mattn +Akinori Hattori +Øyvind Kolås .fi diff --git a/converters/img2sixel.c b/converters/img2sixel.c index 6ee1d285..9c213b90 100644 --- a/converters/img2sixel.c +++ b/converters/img2sixel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -56,7 +56,40 @@ static void show_version(void) { printf("img2sixel " PACKAGE_VERSION "\n" - "Copyright (C) 2014,2015 Hayaki Saito .\n" + "\n" + "configured with:\n" + " libcurl: " +#ifdef HAVE_LIBCURL + "yes\n" +#else + "no\n" +#endif + " libpng: " +#ifdef HAVE_LIBPNG + "yes\n" +#else + "no\n" +#endif + " libjpeg: " +#ifdef HAVE_JPEG + "yes\n" +#else + "no\n" +#endif + " gdk-pixbuf2: " +#ifdef HAVE_GDK_PIXBUF2 + "yes\n" +#else + "no\n" +#endif + " GD: " +#ifdef HAVE_GD + "yes\n" +#else + "no\n" +#endif + "\n" + "Copyright (C) 2014-2018 Hayaki Saito .\n" "\n" "Permission is hereby granted, free of charge, to any person obtaining a copy of\n" "this software and associated documentation files (the \"Software\"), to deal in\n" @@ -135,6 +168,10 @@ void show_help(void) " jajuni -> Jarvis, Judice & Ninke\n" " stucki -> Stucki's method\n" " burkes -> Burkes' method\n" + " a_dither -> positionally stable\n" + " arithmetic dither\n" + " x_dither -> positionally stable\n" + " arithmetic xor based dither\n" "-f FINDTYPE, --find-largest=FINDTYPE\n" " choose method for finding the largest\n" " dimension of median cut boxes for\n" @@ -267,7 +304,7 @@ void show_help(void) "-P, --penetrate penetrate GNU Screen using DCS\n" " pass-through sequence\n" "-D, --pipe-mode read source images from stdin\n" - " continuously\n" + " continuously (deprecated)\n" "-v, --verbose show debugging info\n" "-V, --version show version and license info\n" "-H, --help show this help\n" @@ -305,11 +342,11 @@ main(int argc, char *argv[]) { SIXELSTATUS status = SIXEL_FALSE; int n; + sixel_encoder_t *encoder = NULL; #if HAVE_GETOPT_LONG int long_opt; int option_index; #endif /* HAVE_GETOPT_LONG */ - sixel_encoder_t *encoder = NULL; char const *optstring = "o:78Rp:m:eb:Id:f:s:c:w:h:r:q:kil:t:ugvSn:PE:B:C:DVH"; #if HAVE_GETOPT_LONG struct option long_options[] = { @@ -363,7 +400,8 @@ main(int argc, char *argv[]) #else n = getopt(argc, argv, optstring); #endif /* HAVE_GETOPT_LONG */ - if (n == -1) { + + if (n == (-1)) { break; } #if HAVE_GETOPT_LONG @@ -371,6 +409,7 @@ main(int argc, char *argv[]) n = long_opt; } #endif /* HAVE_GETOPT_LONG */ + switch (n) { case 'V': show_version(); diff --git a/converters/shell-completion/bash/img2sixel b/converters/shell-completion/bash/img2sixel index 0d9fdd7b..028651bd 100644 --- a/converters/shell-completion/bash/img2sixel +++ b/converters/shell-completion/bash/img2sixel @@ -43,7 +43,9 @@ _img2sixel() atkinson \ jajuni \ stucki \ - burkes' -- "$cur" ) ) + burkes \ + a_dither \ + x_dither' -- "$cur" ) ) return 0 ;; -f|--find-largest) diff --git a/converters/shell-completion/zsh/_img2sixel b/converters/shell-completion/zsh/_img2sixel index 12621d0c..aafd0899 100644 --- a/converters/shell-completion/zsh/_img2sixel +++ b/converters/shell-completion/zsh/_img2sixel @@ -22,7 +22,9 @@ _diffusiontype() { "atkinson[Bill Atkinson's method]" \ 'jajuni[Jarvis, Judice & Ninke method]' \ "stucki[Stucki's method]" \ - "burkes[Burkes' method]" + "burkes[Burkes' method]" \ + 'a_dither[positionally stable arithmetic dither]' \ + 'x_dither[positionally stable arithmetic xor based dither]' } _findtype() { diff --git a/converters/sixel2png.c b/converters/sixel2png.c index eecd0722..9ea97706 100644 --- a/converters/sixel2png.c +++ b/converters/sixel2png.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2017 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -60,12 +60,45 @@ #include - +/* output version info to STDOUT */ static void show_version(void) { printf("sixel2png " PACKAGE_VERSION "\n" - "Copyright (C) 2014,2015 Hayaki Saito .\n" + "\n" + "configured with:\n" + " libcurl: " +#ifdef HAVE_LIBCURL + "yes\n" +#else + "no\n" +#endif + " libpng: " +#ifdef HAVE_LIBPNG + "yes\n" +#else + "no\n" +#endif + " libjpeg: " +#ifdef HAVE_JPEG + "yes\n" +#else + "no\n" +#endif + " gdk-pixbuf2: " +#ifdef HAVE_GDK_PIXBUF2 + "yes\n" +#else + "no\n" +#endif + " GD: " +#ifdef HAVE_GD + "yes\n" +#else + "no\n" +#endif + "\n" + "Copyright (C) 2014-2017 Hayaki Saito .\n" "\n" "Permission is hereby granted, free of charge, to any person obtaining a copy of\n" "this software and associated documentation files (the \"Software\"), to deal in\n" @@ -123,14 +156,15 @@ main(int argc, char *argv[]) {"help", no_argument, &long_opt, 'H'}, {0, 0, 0, 0} }; +#endif /* HAVE_GETOPT_LONG */ status = sixel_decoder_new(&decoder, NULL); if (SIXEL_FAILED(status)) { - goto end; + goto error; } -#endif /* HAVE_GETOPT_LONG */ for (;;) { + #if HAVE_GETOPT_LONG n = getopt_long(argc, argv, optstring, long_options, &option_index); @@ -195,6 +229,12 @@ main(int argc, char *argv[]) argerr: show_help(); +error: + fprintf(stderr, "%s\n%s\n", + sixel_helper_format_error(status), + sixel_helper_get_additional_message()); + status = (-1); + end: sixel_decoder_unref(decoder); return status; diff --git a/depcomp b/depcomp index fc98710e..b39f98f9 100755 --- a/depcomp +++ b/depcomp @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2013-05-30.07; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # 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 @@ -786,6 +786,6 @@ exit 0 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/include/Makefile.in b/include/Makefile.in index b3acb75a..10993de8 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/include/sixel.h.in b/include/sixel.h.in index d453ecb8..7ffe90fa 100644 --- a/include/sixel.h.in +++ b/include/sixel.h.in @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014,2015 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -89,6 +89,8 @@ typedef int SIXELSTATUS; #define SIXEL_DIFFUSE_JAJUNI 0x4 /* diffuse with Jarvis, Judice & Ninke method */ #define SIXEL_DIFFUSE_STUCKI 0x5 /* diffuse with Stucki's method */ #define SIXEL_DIFFUSE_BURKES 0x6 /* diffuse with Burkes' method */ +#define SIXEL_DIFFUSE_A_DITHER 0x7 /* positionally stable arithmetic dither */ +#define SIXEL_DIFFUSE_X_DITHER 0x8 /* positionally stable arithmetic xor based dither */ /* quality modes */ #define SIXEL_QUALITY_AUTO 0x0 /* choose quality mode automatically */ @@ -99,7 +101,7 @@ typedef int SIXELSTATUS; /* built-in dither */ #define SIXEL_BUILTIN_MONO_DARK 0x0 /* monochrome terminal with dark background */ -#define SIXEL_BUILTIN_MONO_LIGHT 0x1 /* monochrome terminal with dark background */ +#define SIXEL_BUILTIN_MONO_LIGHT 0x1 /* monochrome terminal with light background */ #define SIXEL_BUILTIN_XTERM16 0x2 /* xterm 16color */ #define SIXEL_BUILTIN_XTERM256 0x3 /* xterm 256color */ #define SIXEL_BUILTIN_VT340_MONO 0x4 /* vt340 monochrome */ @@ -210,6 +212,10 @@ typedef int SIXELSTATUS; jajuni -> Jarvis, Judice & Ninke stucki -> Stucki's method burkes -> Burkes' method + a_dither -> positionally stable + arithmetic dither + a_dither -> positionally stable + arithmetic xor based dither */ #define SIXEL_OPTFLAG_FIND_LARGEST ('f') /* -f FINDTYPE, --find-largest=FINDTYPE: choose method for finding the largest @@ -354,7 +360,7 @@ typedef int SIXELSTATUS; #define SIXEL_OPTFLAG_PENETRATE ('P') /* -P, --penetrate: penetrate GNU Screen using DCS pass-through sequence */ -#define SIXEL_OPTFLAG_PIPE_MODE ('D') /* -D, --pipe-mode: +#define SIXEL_OPTFLAG_PIPE_MODE ('D') /* -D, --pipe-mode: (deprecated) read source images from stdin continuously */ #define SIXEL_OPTFLAG_VERBOSE ('v') /* -v, --verbose: show debugging info */ #define SIXEL_OPTFLAG_VERSION ('V') /* -V, --version: show version and license info */ @@ -364,7 +370,7 @@ typedef int SIXELSTATUS; /* output character size */ enum characterSize { CSIZE_7BIT = 0, /* 7bit character */ - CSIZE_8BIT = 1, /* 8bit character */ + CSIZE_8BIT = 1 /* 8bit character */ }; /* method for finding the largest dimension for splitting, @@ -394,7 +400,9 @@ enum methodForDiffuse { DIFFUSE_FS = 3, /* diffuse with Floyd-Steinberg method */ DIFFUSE_JAJUNI = 4, /* diffuse with Jarvis, Judice & Ninke method */ DIFFUSE_STUCKI = 5, /* diffuse with Stucki's method */ - DIFFUSE_BURKES = 6 /* diffuse with Burkes' method */ + DIFFUSE_BURKES = 6, /* diffuse with Burkes' method */ + DIFFUSE_A_DITHER = 7, /* positionally stable arithmetic dither */ + DIFFUSE_X_DITHER = 8 /* positionally stable arithmetic xor based dither */ }; /* quality modes */ @@ -403,7 +411,7 @@ enum qualityMode { QUALITY_HIGH = 1, /* high quality palette construction */ QUALITY_LOW = 2, /* low quality palette construction */ QUALITY_FULL = 3, /* full quality palette construction */ - QUALITY_HIGHCOLOR = 4, /* high color */ + QUALITY_HIGHCOLOR = 4 /* high color */ }; /* built-in dither */ @@ -413,14 +421,14 @@ enum builtinDither { BUILTIN_XTERM16 = 2, /* xterm 16color */ BUILTIN_XTERM256 = 3, /* xterm 256color */ BUILTIN_VT340_MONO = 4, /* vt340 monochrome */ - BUILTIN_VT340_COLOR = 5, /* vt340 color */ + BUILTIN_VT340_COLOR = 5 /* vt340 color */ }; /* offset value of enum pixelFormat */ enum formatType { FORMATTYPE_COLOR = 0, FORMATTYPE_GRAYSCALE = 1 << 6, - FORMATTYPE_PALETTE = 1 << 7, + FORMATTYPE_PALETTE = 1 << 7 }; /* pixelformat type of input image @@ -443,21 +451,21 @@ enum pixelFormat { PIXELFORMAT_PAL1 = FORMATTYPE_PALETTE | 0x00, /* 1bpp palette */ PIXELFORMAT_PAL2 = FORMATTYPE_PALETTE | 0x01, /* 2bpp palette */ PIXELFORMAT_PAL4 = FORMATTYPE_PALETTE | 0x02, /* 4bpp palette */ - PIXELFORMAT_PAL8 = FORMATTYPE_PALETTE | 0x03, /* 8bpp palette */ + PIXELFORMAT_PAL8 = FORMATTYPE_PALETTE | 0x03 /* 8bpp palette */ }; /* palette type */ enum paletteType { PALETTETYPE_AUTO = 0, /* choose palette type automatically */ PALETTETYPE_HLS = 1, /* HLS colorspace */ - PALETTETYPE_RGB = 2, /* RGB colorspace */ + PALETTETYPE_RGB = 2 /* RGB colorspace */ }; /* policies of SIXEL encoding */ enum encodePolicy { ENCODEPOLICY_AUTO = 0, /* choose encoding policy automatically */ ENCODEPOLICY_FAST = 1, /* encode as fast as possible */ - ENCODEPOLICY_SIZE = 2, /* encode to as small sixel sequence as possible */ + ENCODEPOLICY_SIZE = 2 /* encode to as small sixel sequence as possible */ }; /* method for re-sampling */ @@ -471,7 +479,7 @@ enum methodForResampling { RES_BICUBIC = 6, /* Use bicubic filter */ RES_LANCZOS2 = 7, /* Use lanczos-2 filter */ RES_LANCZOS3 = 8, /* Use lanczos-3 filter */ - RES_LANCZOS4 = 9, /* Use lanczos-4 filter */ + RES_LANCZOS4 = 9 /* Use lanczos-4 filter */ }; #endif @@ -870,14 +878,14 @@ enum imageFormat { FORMAT_PNM = 8, /* read only */ FORMAT_GD2 = 9, /* read only with --with-gd configure option */ FORMAT_PSD = 10, /* read only */ - FORMAT_HDR = 11, /* read only */ + FORMAT_HDR = 11 /* read only */ }; /* loop mode */ enum loopControl { LOOP_AUTO = 0, /* honer the setting of GIF header */ LOOP_FORCE = 1, /* always enable loop */ - LOOP_DISABLE = 2, /* always disable loop */ + LOOP_DISABLE = 2 /* always disable loop */ }; #endif diff --git a/install-sh b/install-sh index 0b0fdcbb..0360b79e 100755 --- a/install-sh +++ b/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2013-12-25.23; # UTC +scriptversion=2016-01-11.22; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -496,6 +496,6 @@ done # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/missing b/missing index f62bbae3..c6e37958 100755 --- a/missing +++ b/missing @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2013-10-28.13; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -210,6 +210,6 @@ exit $st # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/package.json b/package.json index 0ac88b06..f7c305ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "libsixel", - "version": "1.7.3", + "version": "1.8.0", "repo": "saitoha/libsixel", "description": "A lightweight, fast implementation of DEC SIXEL graphics codec", "keywords": ["terminal", "graphics", "image", "sixel"], diff --git a/py-compile b/py-compile index bc203914..3693d96b 100755 --- a/py-compile +++ b/py-compile @@ -1,9 +1,9 @@ #!/bin/sh # py-compile - Compile a Python program -scriptversion=2011-06-08.12; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 2000-2014 Free Software Foundation, Inc. +# Copyright (C) 2000-2017 Free Software Foundation, Inc. # 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 @@ -165,6 +165,6 @@ sys.stdout.write('\n')" 2>/dev/null || : # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/python/LICENSE b/python/LICENSE index 6e0ba162..8bf6d930 100644 --- a/python/LICENSE +++ b/python/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014,2015 Hayaki Saito +Copyright (c) 2014-2018 Hayaki Saito Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/python/Makefile.am b/python/Makefile.am index f8143b9d..6a6d6d20 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -2,7 +2,7 @@ CLEANFILES=libsixel/*.pyc clean-local: - -rm -rf libsixel_python.egg-info build dist + rm -rf libsixel_python.egg-info build dist if HAVE_PYTHON libsixeldir = $(pythondir)/libsixel diff --git a/python/Makefile.in b/python/Makefile.in index bc86988d..d82d8cd6 100644 --- a/python/Makefile.in +++ b/python/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -561,7 +561,7 @@ uninstall-am: uninstall-libsixelPYTHON clean-local: - -rm -rf libsixel_python.egg-info build dist + rm -rf libsixel_python.egg-info build dist check: check-am diff --git a/python/libsixel/__init__.py b/python/libsixel/__init__.py index 8a57a4ff..c95f2a27 100644 --- a/python/libsixel/__init__.py +++ b/python/libsixel/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014-2016 Hayaki Saito +# Copyright (c) 2014-2017 Hayaki Saito # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in @@ -72,6 +72,8 @@ def SIXEL_FAILED(status): SIXEL_DIFFUSE_JAJUNI = 0x4 # diffuse with Jarvis, Judice & Ninke method SIXEL_DIFFUSE_STUCKI = 0x5 # diffuse with Stucki's method SIXEL_DIFFUSE_BURKES = 0x6 # diffuse with Burkes' method +SIXEL_DIFFUSE_A_DITHER = 0x7 # positionally stable arithmetic dither +SIXEL_DIFFUSE_X_DITHER = 0x8 # positionally stable arithmetic xor based dither # quality modes SIXEL_QUALITY_AUTO = 0x0 # choose quality mode automatically @@ -82,7 +84,7 @@ def SIXEL_FAILED(status): # built-in dither SIXEL_BUILTIN_MONO_DARK = 0x0 # monochrome terminal with dark background -SIXEL_BUILTIN_MONO_LIGHT = 0x1 # monochrome terminal with dark background +SIXEL_BUILTIN_MONO_LIGHT = 0x1 # monochrome terminal with light background SIXEL_BUILTIN_XTERM16 = 0x2 # xterm 16color SIXEL_BUILTIN_XTERM256 = 0x3 # xterm 256color SIXEL_BUILTIN_VT340_MONO = 0x4 # vt340 monochrome @@ -107,6 +109,8 @@ def SIXEL_FAILED(status): SIXEL_PIXELFORMAT_BGR888 = (SIXEL_FORMATTYPE_COLOR | 0x06) # 24bpp SIXEL_PIXELFORMAT_ARGB8888 = (SIXEL_FORMATTYPE_COLOR | 0x10) # 32bpp SIXEL_PIXELFORMAT_RGBA8888 = (SIXEL_FORMATTYPE_COLOR | 0x11) # 32bpp +SIXEL_PIXELFORMAT_ABGR8888 = (SIXEL_FORMATTYPE_COLOR | 0x12) # 32bpp +SIXEL_PIXELFORMAT_BGRA8888 = (SIXEL_FORMATTYPE_COLOR | 0x13) # 32bpp SIXEL_PIXELFORMAT_G1 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x00) # 1bpp grayscale SIXEL_PIXELFORMAT_G2 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x01) # 2bpp grayscale SIXEL_PIXELFORMAT_G4 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x02) # 4bpp grayscale @@ -190,6 +194,10 @@ def SIXEL_FAILED(status): # jajuni -> Jarvis, Judice & Ninke # stucki -> Stucki's method # burkes -> Burkes' method + # a_dither -> positionally stable + # arithmetic dither + # x_dither -> positionally stable + # arithmetic xor based dither SIXEL_OPTFLAG_FIND_LARGEST = 'f' # -f FINDTYPE, --find-largest=FINDTYPE: # choose method for finding the largest @@ -334,7 +342,7 @@ def SIXEL_FAILED(status): SIXEL_OPTFLAG_PENETRATE = 'P' # -P, --penetrate: # penetrate GNU Screen using DCS # pass-through sequence -SIXEL_OPTFLAG_PIPE_MODE = 'D' # -D, --pipe-mode: +SIXEL_OPTFLAG_PIPE_MODE = 'D' # -D, --pipe-mode: (deprecated) # read source images from stdin continuously SIXEL_OPTFLAG_VERBOSE = 'v' # -v, --verbose: show debugging info SIXEL_OPTFLAG_VERSION = 'V' # -V, --version: show version and license info diff --git a/python/setup.py b/python/setup.py index 9ba9ef67..950bb20d 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from setuptools import setup, find_packages -__version__ = '0.4.0' +__version__ = '0.5.0' __license__ = 'MIT' __author__ = 'Hayaki Saito' diff --git a/src/Makefile.in b/src/Makefile.in index 86a098c9..4296fead 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/src/allocator.c b/src/allocator.c index b9f7a8a3..b9b2d02a 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -307,7 +307,7 @@ test2(void) } -int +SIXELAPI int sixel_allocator_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/chunk.c b/src/chunk.c index 7d113293..45936d48 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -53,6 +53,10 @@ # include #endif +#if HAVE_SYS_SELECT_H +# include +#endif + #if !defined(HAVE_MEMCPY) # define memcpy(d, s, n) (bcopy ((s), (d), (n))) #endif @@ -225,7 +229,7 @@ open_binary_file( sixel_helper_set_additional_message("stat() failed."); goto end; } - if ((sb.st_mode & S_IFMT) == S_IFDIR) { + if (S_ISDIR(sb.st_mode)) { status = SIXEL_BAD_INPUT; sixel_helper_set_additional_message("specified path is directory."); goto end; @@ -585,7 +589,7 @@ test4(void) } -int +SIXELAPI int sixel_chunk_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/decoder.c b/src/decoder.c index 29b7d1b5..5c90fa3f 100644 --- a/src/decoder.c +++ b/src/decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -573,7 +573,7 @@ test8(void) } -int +SIXELAPI int sixel_decoder_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/dither.c b/src/dither.c index 7a4e91f3..90ae831f 100644 --- a/src/dither.c +++ b/src/dither.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -868,7 +868,7 @@ test2(void) } -int +SIXELAPI int sixel_dither_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/encoder.c b/src/encoder.c index 96cabdce..d711e11d 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -733,14 +733,15 @@ sixel_encoder_output_without_macro( sixel_encoder_t /* in */ *encoder) { SIXELSTATUS status = SIXEL_OK; - int dulation = 0; static unsigned char *p; int depth; char message[256]; int nwrite; -#if HAVE_USLEEP +#if HAVE_NANOSLEEP + int dulation; int delay; - useconds_t lag = 0; + int lag = 0; + struct timespec tv; # if HAVE_CLOCK clock_t start; # endif @@ -786,10 +787,10 @@ sixel_encoder_output_without_macro( status = SIXEL_BAD_ALLOCATION; goto end; } -#if HAVE_USLEEP && HAVE_CLOCK +#if HAVE_NANOSLEEP && HAVE_CLOCK start = clock(); #endif -#if HAVE_USLEEP +#if HAVE_NANOSLEEP delay = sixel_frame_get_delay(frame); if (delay > 0 && !encoder->fignore_delay) { # if HAVE_CLOCK @@ -799,9 +800,11 @@ sixel_encoder_output_without_macro( dulation = 0; # endif if (dulation < 10000 * delay) { - usleep((useconds_t)(10000 * delay - dulation)); + tv.tv_sec = 0; + tv.tv_nsec = (long)((10000 * delay - dulation) * 1000); + nanosleep(&tv, NULL); } else { - lag = (useconds_t)(10000 * delay - dulation); + lag = (int)(10000 * delay - dulation); } } #endif @@ -814,7 +817,7 @@ sixel_encoder_output_without_macro( } status = sixel_encode(p, width, height, depth, dither, output); - if (status != 0) { + if (status != SIXEL_OK) { goto end; } @@ -833,11 +836,12 @@ sixel_encoder_output_with_macro( sixel_encoder_t /* in */ *encoder) { SIXELSTATUS status = SIXEL_OK; - int dulation = 0; char buffer[256]; int nwrite; -#if HAVE_USLEEP - useconds_t lag = 0; +#if HAVE_NANOSLEEP + int dulation; + int lag = 0; + struct timespec tv; # if HAVE_CLOCK clock_t start; # endif @@ -845,11 +849,11 @@ sixel_encoder_output_with_macro( unsigned char *pixbuf; int width; int height; -#if HAVE_USLEEP +#if HAVE_NANOSLEEP int delay; #endif -#if HAVE_USLEEP && HAVE_CLOCK +#if HAVE_NANOSLEEP && HAVE_CLOCK start = clock(); #endif if (sixel_frame_get_loop_no(frame) == 0) { @@ -902,7 +906,7 @@ sixel_encoder_output_with_macro( "sixel_encoder_output_with_macro: sixel_write_callback() failed."); goto end; } -#if HAVE_USLEEP +#if HAVE_NANOSLEEP delay = sixel_frame_get_delay(frame); if (delay > 0 && !encoder->fignore_delay) { # if HAVE_CLOCK @@ -912,9 +916,11 @@ sixel_encoder_output_with_macro( dulation = 0; # endif if (dulation < 10000 * delay) { - usleep((useconds_t)(10000 * delay - dulation)); + tv.tv_sec = 0; + tv.tv_nsec = (long)((10000 * delay - dulation) * 1000); + nanosleep(&tv, NULL); } else { - lag = (useconds_t)(10000 * delay - dulation); + lag = (int)(10000 * delay - dulation); } } #endif @@ -977,7 +983,7 @@ sixel_encoder_encode_frame( /* evaluate -v option: print palette */ if (encoder->verbose) { - if (!(sixel_frame_get_pixelformat(frame) & SIXEL_FORMATTYPE_GRAYSCALE)) { + if ((sixel_frame_get_pixelformat(frame) & SIXEL_FORMATTYPE_PALETTE)) { sixel_debug_print_palette(dither); } } @@ -1275,8 +1281,8 @@ sixel_encoder_setopt( close(encoder->outfd); } encoder->outfd = open(value, - O_RDWR|O_CREAT, - S_IREAD|S_IWRITE); + O_RDWR|O_CREAT|O_TRUNC, + S_IRUSR|S_IWUSR); } break; case SIXEL_OPTFLAG_7BIT_MODE: /* 7 */ @@ -1351,6 +1357,10 @@ sixel_encoder_setopt( encoder->method_for_diffuse = SIXEL_DIFFUSE_STUCKI; } else if (strcmp(value, "burkes") == 0) { encoder->method_for_diffuse = SIXEL_DIFFUSE_BURKES; + } else if (strcmp(value, "a_dither") == 0) { + encoder->method_for_diffuse = SIXEL_DIFFUSE_A_DITHER; + } else if (strcmp(value, "x_dither") == 0) { + encoder->method_for_diffuse = SIXEL_DIFFUSE_X_DITHER; } else { sixel_helper_set_additional_message( "specified diffusion method is not supported."); @@ -1987,7 +1997,7 @@ test5(void) } -int +SIXELAPI int sixel_encoder_tests_main(void) { int nret = EXIT_FAILURE; @@ -2017,6 +2027,11 @@ sixel_encoder_tests_main(void) #endif /* HAVE_TESTS */ -/* emacs, -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ +/* emacs Local Variables: */ +/* emacs mode: c */ +/* emacs tab-width: 4 */ +/* emacs indent-tabs-mode: nil */ +/* emacs c-basic-offset: 4 */ +/* emacs End: */ /* vim: set expandtab ts=4 : */ /* EOF */ diff --git a/src/frame.c b/src/frame.c index d0ef3bfb..b32933d0 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -1028,7 +1028,7 @@ test6(void) } -int +SIXELAPI int sixel_frame_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/fromgif.c b/src/fromgif.c index b7865a0e..c13b0055 100644 --- a/src/fromgif.c +++ b/src/fromgif.c @@ -5,7 +5,7 @@ * Hayaki Saito modified this and re-licensed * it under the MIT license. * - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -353,16 +353,12 @@ gif_process_raster( goto end; } if (oldcode >= 0) { - p = &g->codes[avail++]; - if (avail > 4096) { - sixel_helper_set_additional_message( - "corrupt GIF(reason: too many codes)."); - status = SIXEL_RUNTIME_ERROR; - goto end; + if (avail < 4096) { + p = &g->codes[avail++]; + p->prefix = (signed short) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; } - p->prefix = (signed short) oldcode; - p->first = g->codes[oldcode].first; - p->suffix = (code == avail) ? p->first : g->codes[code].first; } else if (code == avail) { sixel_helper_set_additional_message( "corrupt GIF (reason: illegal code in raster)."); @@ -661,7 +657,7 @@ test1(void) } -int +SIXELAPI int sixel_fromgif_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/fromsixel.c b/src/fromsixel.c index ec58e668..7d8390a4 100644 --- a/src/fromsixel.c +++ b/src/fromsixel.c @@ -103,7 +103,7 @@ typedef enum parse_state { PS_DECSIXEL = 3, /* DECSIXEL body part ", $, -, ? ... ~ */ PS_DECGRA = 4, /* DECGRA Set Raster Attributes " Pan; Pad; Ph; Pv */ PS_DECGRI = 5, /* DECGRI Graphics Repeat Introducer ! Pn Ch */ - PS_DECGCI = 6, /* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */ + PS_DECGCI = 6 /* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */ } parse_state_t; typedef struct parser_context { @@ -153,7 +153,7 @@ hls_to_rgb(int hue, int lum, int sat) } c = (1.0 - c2) * sv; hpi = (int) (hv * 6.0); - x = (hpi & 1) ? c : 0.0; + x = c * (((hpi & 1) << 1) - 1) * ((hpi + (hpi & 1)) - hs / 60.0); m = lv - 0.5 * c; switch (hpi) { diff --git a/src/loader.c b/src/loader.c index d0b4d196..cb1e61f8 100644 --- a/src/loader.c +++ b/src/loader.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -117,7 +117,14 @@ stbi_free(void *p) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdouble-promotion" #endif +# if HAVE_DIAGNOSTIC_UNUSED_FUNCTION +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-function" +#endif #include "stb_image.h" +#if HAVE_DIAGNOSTIC_UNUSED_FUNCTION +# pragma GCC diagnostic pop +#endif #if HAVE_DIAGNOSTIC_DOUBLE_PROMOTION # pragma GCC diagnostic pop #endif @@ -316,12 +323,20 @@ load_png(unsigned char /* out */ **result, } if (bgcolor) { +# if HAVE_DEBUG + fprintf(stderr, "background color is specified [%02x, %02x, %02x]\n", + bgcolor[0], bgcolor[1], bgcolor[2]); +# endif background.red = bgcolor[0]; background.green = bgcolor[1]; background.blue = bgcolor[2]; background.gray = (bgcolor[0] + bgcolor[1] + bgcolor[2]) / 3; } else if (png_get_bKGD(png_ptr, info_ptr, &default_background) == PNG_INFO_bKGD) { memcpy(&background, default_background, sizeof(background)); +# if HAVE_DEBUG + fprintf(stderr, "background color is found [%02x, %02x, %02x]\n", + background.red, background.green, background.blue); +# endif } else { background.red = 0; background.green = 0; @@ -632,6 +647,7 @@ load_sixel(unsigned char /* out */ **result, } +/* detect whether given chunk is sixel stream */ static int chunk_is_sixel(sixel_chunk_t const *chunk) { @@ -668,6 +684,7 @@ chunk_is_sixel(sixel_chunk_t const *chunk) } +/* detect whether given chunk is PNM stream */ static int chunk_is_pnm(sixel_chunk_t const *chunk) { @@ -684,6 +701,7 @@ chunk_is_pnm(sixel_chunk_t const *chunk) #if HAVE_LIBPNG +/* detect whether given chunk is PNG stream */ static int chunk_is_png(sixel_chunk_t const *chunk) { @@ -698,6 +716,7 @@ chunk_is_png(sixel_chunk_t const *chunk) #endif /* HAVE_LIBPNG */ +/* detect whether given chunk is GIF stream */ static int chunk_is_gif(sixel_chunk_t const *chunk) { @@ -717,6 +736,7 @@ chunk_is_gif(sixel_chunk_t const *chunk) #if HAVE_JPEG +/* detect whether given chunk is JPEG stream */ static int chunk_is_jpeg(sixel_chunk_t const *chunk) { @@ -859,7 +879,7 @@ load_with_builtin( } stbi_allocator = pchunk->allocator; stbi__start_mem(&s, pchunk->buffer, (int)pchunk->size); - frame->pixels = stbi__load_main(&s, &frame->width, &frame->height, &depth, 3); + frame->pixels = stbi__load_and_postprocess_8bit(&s, &frame->width, &frame->height, &depth, 3); if (!frame->pixels) { sixel_helper_set_additional_message(stbi_failure_reason()); status = SIXEL_STBI_ERROR; @@ -1367,7 +1387,7 @@ test1(void) } -int +SIXELAPI int sixel_loader_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/pixelformat.c b/src/pixelformat.c index 0293cb60..5f28c642 100644 --- a/src/pixelformat.c +++ b/src/pixelformat.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -677,7 +677,7 @@ test10(void) } -int +SIXELAPI int sixel_pixelformat_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/quant.c b/src/quant.c index 9af05602..e100d675 100644 --- a/src/quant.c +++ b/src/quant.c @@ -22,7 +22,7 @@ * * ****************************************************************************** * - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -1030,6 +1030,17 @@ diffuse_burkes(unsigned char *data, int width, int height, } } +static float +mask_a (int x, int y, int c) +{ + return ((((x + c * 67) + y * 236) * 119) & 255 ) / 128.0 - 1.0; +} + +static float +mask_x (int x, int y, int c) +{ + return ((((x + c * 29) ^ y* 149) * 1234) & 511 ) / 256.0 - 1.0; +} /* lookup closest color from palette with "normal" strategy */ static int @@ -1245,13 +1256,15 @@ sixel_quant_apply_palette( sixel_allocator_t /* in */ *allocator) { typedef int component_t; + enum { max_depth = 4 }; SIXELSTATUS status = SIXEL_FALSE; int pos, n, x, y, sum1, sum2; component_t offset; int color_index; unsigned short *indextable; - unsigned char new_palette[256 * 4]; + unsigned char new_palette[256 * max_depth]; unsigned short migration_map[256]; + float (*f_mask) (int x, int y, int c) = NULL; void (*f_diffuse)(unsigned char *data, int width, int height, int x, int y, int depth, int offset); int (*f_lookup)(unsigned char const * const pixel, @@ -1267,27 +1280,42 @@ sixel_quant_apply_palette( switch (methodForDiffuse) { case SIXEL_DIFFUSE_NONE: f_diffuse = diffuse_none; + f_mask = mask_a; break; case SIXEL_DIFFUSE_ATKINSON: f_diffuse = diffuse_atkinson; + f_mask = mask_a; break; case SIXEL_DIFFUSE_FS: f_diffuse = diffuse_fs; + f_mask = mask_a; break; case SIXEL_DIFFUSE_JAJUNI: f_diffuse = diffuse_jajuni; + f_mask = mask_a; break; case SIXEL_DIFFUSE_STUCKI: f_diffuse = diffuse_stucki; + f_mask = mask_a; break; case SIXEL_DIFFUSE_BURKES: f_diffuse = diffuse_burkes; + f_mask = mask_a; + break; + case SIXEL_DIFFUSE_A_DITHER: + f_diffuse = diffuse_none; + f_mask = mask_a; + break; + case SIXEL_DIFFUSE_X_DITHER: + f_diffuse = diffuse_none; + f_mask = mask_x; break; default: quant_trace(stderr, "Internal error: invalid value of" " methodForDiffuse: %d\n", methodForDiffuse); f_diffuse = diffuse_none; + f_mask = mask_a; break; } } @@ -1333,38 +1361,85 @@ sixel_quant_apply_palette( memset(new_palette, 0x00, sizeof(256 * depth)); memset(migration_map, 0x00, sizeof(migration_map)); - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - pos = y * width + x; - color_index = f_lookup(data + (pos * depth), depth, - palette, reqcolor, indextable, complexion); - if (migration_map[color_index] == 0) { - result[pos] = *ncolors; - for (n = 0; n < depth; ++n) { - new_palette[*ncolors * depth + n] = palette[color_index * depth + n]; + if (f_mask) { + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + unsigned char copy[max_depth]; + int d; + int val; + + pos = y * width + x; + for (d = 0; d < depth; d ++) { + val = data[pos * depth + d] + f_mask(x, y, d) * 32; + copy[d] = val < 0 ? 0 : val > 255 ? 255 : val; + } + color_index = f_lookup(copy, depth, + palette, reqcolor, indextable, complexion); + if (migration_map[color_index] == 0) { + result[pos] = *ncolors; + for (n = 0; n < depth; ++n) { + new_palette[*ncolors * depth + n] = palette[color_index * depth + n]; + } + ++*ncolors; + migration_map[color_index] = *ncolors; + } else { + result[pos] = migration_map[color_index] - 1; } - ++*ncolors; - migration_map[color_index] = *ncolors; - } else { - result[pos] = migration_map[color_index] - 1; } - for (n = 0; n < depth; ++n) { - offset = data[pos * depth + n] - palette[color_index * depth + n]; - f_diffuse(data + n, width, height, x, y, depth, offset); + } + memcpy(palette, new_palette, (size_t)(*ncolors * depth)); + } else { + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + pos = y * width + x; + color_index = f_lookup(data + (pos * depth), depth, + palette, reqcolor, indextable, complexion); + if (migration_map[color_index] == 0) { + result[pos] = *ncolors; + for (n = 0; n < depth; ++n) { + new_palette[*ncolors * depth + n] = palette[color_index * depth + n]; + } + ++*ncolors; + migration_map[color_index] = *ncolors; + } else { + result[pos] = migration_map[color_index] - 1; + } + for (n = 0; n < depth; ++n) { + offset = data[pos * depth + n] - palette[color_index * depth + n]; + f_diffuse(data + n, width, height, x, y, depth, offset); + } } } + memcpy(palette, new_palette, (size_t)(*ncolors * depth)); } - memcpy(palette, new_palette, (size_t)(*ncolors * depth)); } else { - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - pos = y * width + x; - color_index = f_lookup(data + (pos * depth), depth, - palette, reqcolor, indextable, complexion); - result[pos] = color_index; - for (n = 0; n < depth; ++n) { - offset = data[pos * depth + n] - palette[color_index * depth + n]; - f_diffuse(data + n, width, height, x, y, depth, offset); + if (f_mask) { + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + unsigned char copy[max_depth]; + int d; + int val; + + pos = y * width + x; + for (d = 0; d < depth; d ++) { + val = data[pos * depth + d] + f_mask(x, y, d) * 32; + copy[d] = val < 0 ? 0 : val > 255 ? 255 : val; + } + result[pos] = f_lookup(copy, depth, + palette, reqcolor, indextable, complexion); + } + } + } else { + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + pos = y * width + x; + color_index = f_lookup(data + (pos * depth), depth, + palette, reqcolor, indextable, complexion); + result[pos] = color_index; + for (n = 0; n < depth; ++n) { + offset = data[pos * depth + n] - palette[color_index * depth + n]; + f_diffuse(data + n, width, height, x, y, depth, offset); + } } } } @@ -1411,7 +1486,7 @@ test1(void) } -int +SIXELAPI int sixel_quant_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/sixel.5 b/src/sixel.5 index 3cdd6afc..71c9ac53 100644 --- a/src/sixel.5 +++ b/src/sixel.5 @@ -19,7 +19,7 @@ tanasinn (Works with firefox) .br mlterm (Works on each of X, win32/cygwin and framebuffer version) .br -XTerm (configured with --enable-sixel-graphics and lanuched with "-ti 340" option) +XTerm (configured with --enable-sixel-graphics and launched with "-ti 340" option) .br yaft / yaftx (Works on framebuffer / X11 environment) .br diff --git a/src/status.c b/src/status.c index 932945df..7ba38be0 100644 --- a/src/status.c +++ b/src/status.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -311,7 +311,7 @@ test2(void) } -int +SIXELAPI int sixel_status_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/src/stb_image.h b/src/stb_image.h index a3c11299..d284fd09 100644 --- a/src/stb_image.h +++ b/src/stb_image.h @@ -1,5 +1,5 @@ -/* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h - no warranty implied; use at your own risk +/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk Do this: #define STB_IMAGE_IMPLEMENTATION @@ -21,7 +21,7 @@ avoid problematic images and only need the trivial interface JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) - PNG 1/2/4/8-bit-per-channel (16 bpc not supported) + PNG 1/2/4/8/16-bit-per-channel TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE @@ -42,136 +42,26 @@ Full documentation under "DOCUMENTATION" below. - Revision 2.00 release notes: - - - Progressive JPEG is now supported. - - - PPM and PGM binary formats are now supported, thanks to Ken Miller. - - - x86 platforms now make use of SSE2 SIMD instructions for - JPEG decoding, and ARM platforms can use NEON SIMD if requested. - This work was done by Fabian "ryg" Giesen. SSE2 is used by - default, but NEON must be enabled explicitly; see docs. - - With other JPEG optimizations included in this version, we see - 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup - on a JPEG on an ARM machine, relative to previous versions of this - library. The same results will not obtain for all JPGs and for all - x86/ARM machines. (Note that progressive JPEGs are significantly - slower to decode than regular JPEGs.) This doesn't mean that this - is the fastest JPEG decoder in the land; rather, it brings it - closer to parity with standard libraries. If you want the fastest - decode, look elsewhere. (See "Philosophy" section of docs below.) - - See final bullet items below for more info on SIMD. - - - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing - the memory allocator. Unlike other STBI libraries, these macros don't - support a context parameter, so if you need to pass a context in to - the allocator, you'll have to store it in a global or a thread-local - variable. - - - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and - STBI_NO_LINEAR. - STBI_NO_HDR: suppress implementation of .hdr reader format - STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API - - - You can suppress implementation of any of the decoders to reduce - your code footprint by #defining one or more of the following - symbols before creating the implementation. - - STBI_NO_JPEG - STBI_NO_PNG - STBI_NO_BMP - STBI_NO_PSD - STBI_NO_TGA - STBI_NO_GIF - STBI_NO_HDR - STBI_NO_PIC - STBI_NO_PNM (.ppm and .pgm) - - - You can request *only* certain decoders and suppress all other ones - (this will be more forward-compatible, as addition of new decoders - doesn't require you to disable them explicitly): - - STBI_ONLY_JPEG - STBI_ONLY_PNG - STBI_ONLY_BMP - STBI_ONLY_PSD - STBI_ONLY_TGA - STBI_ONLY_GIF - STBI_ONLY_HDR - STBI_ONLY_PIC - STBI_ONLY_PNM (.ppm and .pgm) - - Note that you can define multiples of these, and you will get all - of them ("only x" and "only y" is interpreted to mean "only x&y"). - - - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still - want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB - - - Compilation of all SIMD code can be suppressed with - #define STBI_NO_SIMD - It should not be necessary to disable SIMD unless you have issues - compiling (e.g. using an x86 compiler which doesn't support SSE - intrinsics or that doesn't support the method used to detect - SSE2 support at run-time), and even those can be reported as - bugs so I can refine the built-in compile-time checking to be - smarter. - - - The old STBI_SIMD system which allowed installing a user-defined - IDCT etc. has been removed. If you need this, don't upgrade. My - assumption is that almost nobody was doing this, and those who - were will find the built-in SIMD more satisfactory anyway. - - - RGB values computed for JPEG images are slightly different from - previous versions of stb_image. (This is due to using less - integer precision in SIMD.) The C code has been adjusted so - that the same RGB values will be computed regardless of whether - SIMD support is available, so your app should always produce - consistent results. But these results are slightly different from - previous versions. (Specifically, about 3% of available YCbCr values - will compute different RGB results from pre-1.49 versions by +-1; - most of the deviating values are one smaller in the G channel.) - - - If you must produce consistent results with previous versions of - stb_image, #define STBI_JPEG_OLD and you will get the same results - you used to; however, you will not get the SIMD speedups for - the YCbCr-to-RGB conversion step (although you should still see - significant JPEG speedup from the other changes). - - Please note that STBI_JPEG_OLD is a temporary feature; it will be - removed in future versions of the library. It is only intended for - near-term back-compatibility use. - - - Latest revision history: +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; - allocate large structures on the stack; + allocate large structures on the stack; correct channel count for PNG & BMP 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED - 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA - 2.07 (2015-09-13) partial animated GIF support - limited 16-bit PSD support - minor bugs, code cleanup, and compiler warnings - 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value - 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning - 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit - 2.03 (2015-04-12) additional corruption checking - stbi_set_flip_vertically_on_load - fix NEON support; fix mingw support - 2.02 (2015-01-19) fix incorrect assert, fix warning - 2.01 (2015-01-17) fix various warnings - 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG - 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD - progressive JPEG - PGM/PPM support - STBI_MALLOC,STBI_REALLOC,STBI_FREE - STBI_NO_*, STBI_ONLY_* - GIF bugfix See end of file for full revision history. @@ -186,34 +76,31 @@ Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) - urraka@github (animated gif) Junggon Kim (PNM comments) - Daniel Gibson (16-bit TGA) - - Optimizations & bugfixes - Fabian "ryg" Giesen + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) Arseny Kapoulkine + John-Mark Allen Bug & warning fixes Marc LeBlanc David Woo Guillaume George Martins Mozeiko - Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson - Dave Moore Roy Eltham Hayaki Saito Phil Jordan - Won Chun Luke Graham Johan Duparc Nathan Reed - the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis - Janez Zemva John Bartholomew Michal Cichon svdijk@github - Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson - Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github - Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan - Ryamond Barbiero Paul Du Bois Engin Manap snagar@github - Michaelangel007@github Oriol Ferrer Mesia socks-the-fox - Blazej Dariusz Roszkowski - - -LICENSE - -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish, and distribute this file as you see fit. - + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar + Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex + Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 + Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus + Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo + Christian Floisand Kevin Schmidt github:darealshinji + Blazej Dariusz Roszkowski github:Michaelangel007 */ #ifndef STBI_INCLUDE_STB_IMAGE_H @@ -222,10 +109,8 @@ publish, and distribute this file as you see fit. // DOCUMENTATION // // Limitations: -// - no 16-bit-per-channel PNG // - no 12-bit-per-channel JPEG // - no JPEGs with arithmetic coding -// - no 1-bit BMP // - GIF always returns *comp=4 // // Basic usage (see HDR discussion below for HDR usage): @@ -238,10 +123,10 @@ publish, and distribute this file as you see fit. // stbi_image_free(data) // // Standard parameters: -// int *x -- outputs image width in pixels -// int *y -- outputs image height in pixels -// int *comp -- outputs # of image components in image file -// int req_comp -- if non-zero, # of image components requested in result +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result // // The return value from an image loader is an 'unsigned char *' which points // to the pixel data, or NULL on an allocation failure or if the image is @@ -249,11 +134,12 @@ publish, and distribute this file as you see fit. // with each pixel consisting of N interleaved 8-bit components; the first // pixel pointed to is top-left-most in the image. There is no padding between // image scanlines or between pixels, regardless of format. The number of -// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. -// If req_comp is non-zero, *comp has the number of components that _would_ -// have been output otherwise. E.g. if you set req_comp to 4, you will always -// get RGBA output, but you can check *comp to see if it's trivially opaque -// because e.g. there were only 3 channels in the source image. +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. // // An output image with N components has the following components interleaved // in this order in each pixel: @@ -265,10 +151,10 @@ publish, and distribute this file as you see fit. // 4 red, green, blue, alpha // // If image loading fails for any reason, the return value will be NULL, -// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() -// can be queried for an extremely brief, end-user unfriendly explanation -// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid -// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly // more user-friendly ones. // // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. @@ -287,13 +173,13 @@ publish, and distribute this file as you see fit. // and for best performance I may provide less-easy-to-use APIs that give higher // performance, in addition to the easy to use ones. Nevertheless, it's important // to keep in mind that from the standpoint of you, a client of this library, -// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all. +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. // // Some secondary priorities arise directly from the first two, some of which // make more explicit reasons why performance can't be emphasized. // // - Portable ("ease of use") -// - Small footprint ("easy to maintain") +// - Small source code footprint ("easy to maintain") // - No dependencies ("ease of use") // // =========================================================================== @@ -325,13 +211,6 @@ publish, and distribute this file as you see fit. // (at least this is true for iOS and Android). Therefore, the NEON support is // toggled by a build flag: define STBI_NEON to get NEON loops. // -// The output of the JPEG decoder is slightly different from versions where -// SIMD support was introduced (that is, for versions before 1.49). The -// difference is only +-1 in the 8-bit RGB channels, and only on a small -// fraction of pixels. You can force the pre-1.49 behavior by defining -// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path -// and hence cost some performance. -// // If for some reason you do not want to use any of SIMD code, or if // you have issues compiling it, you can disable it entirely by // defining STBI_NO_SIMD. @@ -387,6 +266,41 @@ publish, and distribute this file as you see fit. // says there's premultiplied data (currently only happens in iPhone images, // and only if iPhone convert-to-rgb processing is on). // +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// #ifndef STBI_NO_STDIO @@ -397,7 +311,7 @@ publish, and distribute this file as you see fit. enum { - STBI_default = 0, // only used for req_comp + STBI_default = 0, // only used for desired_channels STBI_grey = 1, STBI_grey_alpha = 2, @@ -406,6 +320,7 @@ enum }; typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; #ifdef __cplusplus extern "C" { @@ -433,22 +348,48 @@ typedef struct int (*eof) (void *user); // returns nonzero if we are at end of file/data } stbi_io_callbacks; -STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); -STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp); -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp); +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + #ifndef STBI_NO_STDIO -STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); // for stbi_load_from_file, file pointer is left pointing immediately after image #endif +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// #ifndef STBI_NO_LINEAR - STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); - STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); - STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO - STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif #endif @@ -481,11 +422,14 @@ STBIDEF void stbi_image_free (void *retval_from_stbi_load); // get image dimensions & components without fully decoding STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); #ifndef STBI_NO_STDIO -STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); - +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); #endif @@ -566,9 +510,10 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch #include // ptrdiff_t on osx #include #include +#include #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) -#include // ldexp +#include // ldexp, pow #endif #ifndef STBI_NO_STDIO @@ -649,12 +594,14 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI__X86_TARGET #endif -#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) -// NOTE: not clear do we actually need this for the 64-bit path? +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, -// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; -// this is just broken and gcc are jerks for not fixing it properly -// http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. #define STBI_NO_SIMD #endif @@ -702,7 +649,7 @@ static int stbi__cpuid3(void) #define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name -static int stbi__sse2_available() +static int stbi__sse2_available(void) { int info3 = stbi__cpuid3(); return ((info3 >> 26) & 1) != 0; @@ -710,16 +657,12 @@ static int stbi__sse2_available() #else // assume GCC-style if not VC++ #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) -static int stbi__sse2_available() +static int stbi__sse2_available(void) { -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later - // GCC 4.8+ has a nice way to do this - return __builtin_cpu_supports("sse2"); -#else - // portable way to do this, preferably without using GCC inline ASM? - // just bail for now. - return 0; -#endif + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; } #endif #endif @@ -827,57 +770,73 @@ static void stbi__rewind(stbi__context *s) s->img_buffer_end = s->img_buffer_original_end; } +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + #ifndef STBI_NO_JPEG static int stbi__jpeg_test(stbi__context *s); -static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNG static int stbi__png_test(stbi__context *s); -static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); #endif #ifndef STBI_NO_BMP static int stbi__bmp_test(stbi__context *s); -static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_TGA static int stbi__tga_test(stbi__context *s); -static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PSD static int stbi__psd_test(stbi__context *s); -static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); #endif #ifndef STBI_NO_HDR static int stbi__hdr_test(stbi__context *s); -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PIC static int stbi__pic_test(stbi__context *s); -static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_GIF static int stbi__gif_test(stbi__context *s); -static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNM static int stbi__pnm_test(stbi__context *s); -static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); #endif @@ -900,6 +859,81 @@ static void *stbi__malloc(size_t size) return STBI_MALLOC(size); } +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + // stbi__err - error // stbi__errpf - error returning pointer to float // stbi__errpuc - error returning pointer to unsigned char @@ -935,33 +969,38 @@ STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) stbi__vertically_flip_on_load = flag_true_if_should_flip; } -static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + #ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PNG - if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_BMP - if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_GIF - if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PSD - if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); #endif #ifndef STBI_NO_PIC - if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PNM - if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { - float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); } #endif @@ -969,56 +1008,137 @@ static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *com #ifndef STBI_NO_TGA // test tga last because it's a crappy test! if (stbi__tga_test(s)) - return stbi__tga_load(s,x,y,comp,req_comp); + return stbi__tga_load(s,x,y,comp,req_comp, ri); #endif return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); } -static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) { - unsigned char *result = stbi__load_main(s, x, y, comp, req_comp); + int i; + int img_len = w * h * channels; + stbi_uc *reduced; - if (stbi__vertically_flip_on_load && result != NULL) { - int w = *x, h = *y; - int depth = req_comp ? req_comp : *comp; - int row,col,z; - stbi_uc temp; - - // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once - for (row = 0; row < (h>>1); row++) { - for (col = 0; col < w; col++) { - for (z = 0; z < depth; z++) { - temp = result[(row * w + col) * depth + z]; - result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; - result[((h - row - 1) * w + col) * depth + z] = temp; - } - } + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; } } +} - return result; +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } } +#endif -#ifndef STBI_NO_HDR +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR) static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) { if (stbi__vertically_flip_on_load && result != NULL) { - int w = *x, h = *y; - int depth = req_comp ? req_comp : *comp; - int row,col,z; - float temp; - - // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once - for (row = 0; row < (h>>1); row++) { - for (col = 0; col < w; col++) { - for (z = 0; z < depth; z++) { - temp = result[(row * w + col) * depth + z]; - result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; - result[((h - row - 1) * w + col) * depth + z] = temp; - } - } - } + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); } } #endif @@ -1053,42 +1173,98 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req unsigned char *result; stbi__context s; stbi__start_file(&s,f); - result = stbi__load_flip(&s,x,y,comp,req_comp); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); if (result) { // need to 'unget' all the characters in the IO buffer fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); } return result; } + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + #endif //!STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_mem(&s,buffer,len); - return stbi__load_flip(&s,x,y,comp,req_comp); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__load_flip(&s,x,y,comp,req_comp); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + #ifndef STBI_NO_LINEAR static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { unsigned char *data; #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { - float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp); + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); if (hdr_data) stbi__float_postprocess(hdr_data,x,y,comp,req_comp); return hdr_data; } #endif - data = stbi__load_flip(s, x, y, comp, req_comp); + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); if (data) return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); @@ -1158,12 +1334,16 @@ STBIDEF int stbi_is_hdr (char const *filename) return result; } -STBIDEF int stbi_is_hdr_from_file(FILE *f) +STBIDEF int stbi_is_hdr_from_file(FILE *f) { #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; stbi__context s; stbi__start_file(&s,f); - return stbi__hdr_test(&s); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; #else STBI_NOTUSED(f); return 0; @@ -1346,7 +1526,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - good = (unsigned char *) stbi__malloc(req_comp * x * y); + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); if (good == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); @@ -1356,26 +1536,75 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r unsigned char *src = data + j * x * img_n ; unsigned char *dest = good + j * x * req_comp; - #define COMBO(a,b) ((a)*8+(b)) - #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros - switch (COMBO(img_n, req_comp)) { - CASE(1,2) dest[0]=src[0], dest[1]=255; break; - CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; - CASE(2,1) dest[0]=src[0]; break; - CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; - CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; - CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; - CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; - CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; default: STBI_ASSERT(0); } - #undef CASE + #undef STBI__CASE } STBI_FREE(data); @@ -1386,7 +1615,9 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) { int i,k,n; - float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; @@ -1406,7 +1637,9 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) { int i,k,n; - stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; @@ -1471,7 +1704,7 @@ typedef struct stbi__context *s; stbi__huffman huff_dc[4]; stbi__huffman huff_ac[4]; - stbi_uc dequant[4][64]; + stbi__uint16 dequant[4][64]; stbi__int16 fast_ac[4][1 << FAST_BITS]; // sizes for components, interleaved MCUs @@ -1507,6 +1740,8 @@ typedef struct int succ_high; int succ_low; int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag int rgb; int scan_n, order[4]; @@ -1520,7 +1755,8 @@ typedef struct static int stbi__build_huffman(stbi__huffman *h, int *count) { - int i,j,k=0,code; + int i,j,k=0; + unsigned int code; // build size list for each symbol (from JPEG spec) for (i=0; i < 16; ++i) for (j=0; j < count[i]; ++j) @@ -1536,7 +1772,7 @@ static int stbi__build_huffman(stbi__huffman *h, int *count) if (h->size[k] == j) { while (h->size[k] == j) h->code[k++] = (stbi__uint16) (code++); - if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); } // compute largest code + 1 for this size, preshifted as needed later h->maxcode[j] = code << (16-j); @@ -1577,10 +1813,10 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) // magnitude code followed by receive_extend code int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); int m = 1 << (magbits - 1); - if (k < m) k += (-1 << magbits) + 1; + if (k < m) k += (~0U << magbits) + 1; // if the result is small enough, we can fit it in fast_ac table if (k >= -128 && k <= 127) - fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); } } } @@ -1589,9 +1825,10 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) static void stbi__grow_buffer_unsafe(stbi__jpeg *j) { do { - int b = j->nomore ? 0 : stbi__get8(j->s); + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); if (b == 0xff) { int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; @@ -1604,7 +1841,7 @@ static void stbi__grow_buffer_unsafe(stbi__jpeg *j) } // (1 << n) - 1 -static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; // decode a jpeg huffman value from the bitstream stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) @@ -1657,7 +1894,7 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) } // bias[n] = (-1<s); if (x != 0xff) return STBI__MARKER_none; while (x == 0xff) - x = stbi__get8(j->s); + x = stbi__get8(j->s); // consume repeated 0xff fill bytes return x; } @@ -2440,7 +2677,7 @@ static void stbi__jpeg_reset(stbi__jpeg *j) j->code_bits = 0; j->code_buffer = 0; j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; j->marker = STBI__MARKER_none; j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; j->eob_run = 0; @@ -2572,7 +2809,7 @@ static int stbi__parse_entropy_coded_data(stbi__jpeg *z) } } -static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant) +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) { int i; for (i=0; i < 64; ++i) @@ -2614,13 +2851,14 @@ static int stbi__process_marker(stbi__jpeg *z, int m) L = stbi__get16be(z->s)-2; while (L > 0) { int q = stbi__get8(z->s); - int p = q >> 4; + int p = q >> 4, sixteen = (p != 0); int t = q & 15,i; - if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); - L -= 65; + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); } return L==0; @@ -2653,12 +2891,50 @@ static int stbi__process_marker(stbi__jpeg *z, int m) } return L==0; } + // check for comment block or APP blocks if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - stbi__skip(z->s, stbi__get16be(z->s)-2); + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); return 1; } - return 0; + + return stbi__err("unknown marker","Corrupt JPEG"); } // after we see SOS @@ -2701,6 +2977,28 @@ static int stbi__process_scan_header(stbi__jpeg *z) return 1; } +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + static int stbi__process_frame_header(stbi__jpeg *z, int scan) { stbi__context *s = z->s; @@ -2710,7 +3008,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires c = stbi__get8(s); - if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); s->img_n = c; for (i=0; i < c; ++i) { z->img_comp[i].data = NULL; @@ -2721,15 +3019,10 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) z->rgb = 0; for (i=0; i < s->img_n; ++i) { - static unsigned char rgb[3] = { 'R', 'G', 'B' }; + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); - if (z->img_comp[i].id != i+1) // JFIF requires - if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files! - // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format) - if (z->img_comp[i].id != rgb[i]) - return stbi__err("bad component ID","Corrupt JPEG"); - ++z->rgb; - } + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); @@ -2738,7 +3031,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) if (scan != STBI__SCAN_load) return 1; - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); for (i=0; i < s->img_n; ++i) { if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; @@ -2750,6 +3043,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) z->img_v_max = v_max; z->img_mcu_w = h_max * 8; z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; @@ -2761,28 +3055,27 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) // the bogus oversized data from using interleaved MCUs and their // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; - z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); - - if (z->img_comp[i].raw_data == NULL) { - for(--i; i >= 0; --i) { - STBI_FREE(z->img_comp[i].raw_data); - z->img_comp[i].raw_data = NULL; - } - return stbi__err("outofmem", "Out of memory"); - } + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); // align blocks for idct using mmx/sse z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); - z->img_comp[i].linebuf = NULL; if (z->progressive) { - z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; - z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; - z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); - } else { - z->img_comp[i].coeff = 0; - z->img_comp[i].raw_coeff = 0; } } @@ -2801,6 +3094,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) { int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); @@ -2842,12 +3137,15 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) if (x == 255) { j->marker = stbi__get8(j->s); break; - } else if (x != 0) { - return stbi__err("junk before marker", "Corrupt JPEG"); } } // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); } else { if (!stbi__process_marker(j, m)) return 0; } @@ -3066,38 +3364,9 @@ static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_ return out; } -#ifdef STBI_JPEG_OLD -// this is the same YCbCr-to-RGB calculation that stb_image has used -// historically before the algorithm changes in 1.49 -#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) -static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) -{ - int i; - for (i=0; i < count; ++i) { - int y_fixed = (y[i] << 16) + 32768; // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr*float2fixed(1.40200f); - g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); - b = y_fixed + cb*float2fixed(1.77200f); - r >>= 16; - g >>= 16; - b >>= 16; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#else // this is a reduced-precision calculation of YCbCr-to-RGB introduced // to make sure the code produces the same results in both SIMD and scalar -#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) { int i; @@ -3106,9 +3375,9 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; @@ -3122,7 +3391,6 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc out += step; } } -#endif #if defined(STBI_SSE2) || defined(STBI_NEON) static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) @@ -3241,9 +3509,9 @@ static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc cons int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; @@ -3269,18 +3537,14 @@ static void stbi__setup_jpeg(stbi__jpeg *j) #ifdef STBI_SSE2 if (stbi__sse2_available()) { j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; } #endif #ifdef STBI_NEON j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; #endif } @@ -3288,23 +3552,7 @@ static void stbi__setup_jpeg(stbi__jpeg *j) // clean up the temporary component buffers static void stbi__cleanup_jpeg(stbi__jpeg *j) { - int i; - for (i=0; i < j->s->img_n; ++i) { - if (j->img_comp[i].raw_data) { - STBI_FREE(j->img_comp[i].raw_data); - j->img_comp[i].raw_data = NULL; - j->img_comp[i].data = NULL; - } - if (j->img_comp[i].raw_coeff) { - STBI_FREE(j->img_comp[i].raw_coeff); - j->img_comp[i].raw_coeff = 0; - j->img_comp[i].coeff = 0; - } - if (j->img_comp[i].linebuf) { - STBI_FREE(j->img_comp[i].linebuf); - j->img_comp[i].linebuf = NULL; - } - } + stbi__free_jpeg_components(j, j->s->img_n, 0); } typedef struct @@ -3317,9 +3565,16 @@ typedef struct int ypos; // which pre-expansion row we're on } stbi__resample; +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { - int n, decode_n; + int n, decode_n, is_rgb; z->s->img_n = 0; // make stbi__cleanup_jpeg safe // validate req_comp @@ -3329,9 +3584,11 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } // determine actual number of components to generate - n = req_comp ? req_comp : z->s->img_n; + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; - if (z->s->img_n == 3 && n < 3) + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) decode_n = 1; else decode_n = z->s->img_n; @@ -3368,7 +3625,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } // can't error after this so, this is safe - output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } // now go ahead and resample @@ -3391,7 +3648,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (n >= 3) { stbi_uc *y = coutput[0]; if (z->s->img_n == 3) { - if (z->rgb == 3) { + if (is_rgb) { for (i=0; i < z->s->img_x; ++i) { out[0] = y[i]; out[1] = coutput[1][i]; @@ -3399,7 +3656,29 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp out[3] = 255; out += n; } - } else { + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } } else @@ -3409,25 +3688,54 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp out += n; } } else { - stbi_uc *y = coutput[0]; - if (n == 1) - for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; - else - for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } } } stbi__cleanup_jpeg(z); *out_x = z->s->img_x; *out_y = z->s->img_y; - if (comp) *comp = z->s->img_n; // report original components, not output + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output return output; } } -static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); result = load_jpeg_image(j, x,y,comp,req_comp); @@ -3438,11 +3746,12 @@ static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *com static int stbi__jpeg_test(stbi__context *s) { int r; - stbi__jpeg j; - j.s = s; - stbi__setup_jpeg(&j); - r = stbi__decode_jpeg_header(&j, STBI__SCAN_type); + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); stbi__rewind(s); + STBI_FREE(j); return r; } @@ -3454,7 +3763,7 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) } if (x) *x = j->s->img_x; if (y) *y = j->s->img_y; - if (comp) *comp = j->s->img_n; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; return 1; } @@ -3511,7 +3820,7 @@ stbi_inline static int stbi__bit_reverse(int v, int bits) return stbi__bitreverse16(v) >> (16-bits); } -static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) { int i,k=0; int code, next_code[16], sizes[17]; @@ -3654,18 +3963,18 @@ static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room return 1; } -static int stbi__zlength_base[31] = { +static const int stbi__zlength_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; -static int stbi__zlength_extra[31]= +static const int stbi__zlength_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; -static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; -static int stbi__zdist_extra[32] = +static const int stbi__zdist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; static int stbi__parse_huffman_block(stbi__zbuf *a) @@ -3712,7 +4021,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) static int stbi__compute_huffman_codes(stbi__zbuf *a) { - static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; stbi__zhuffman z_codelength; stbi_uc lencodes[286+32+137];//padding for maximum single op stbi_uc codelength_sizes[19]; @@ -3721,6 +4030,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) int hlit = stbi__zreceive(a,5) + 257; int hdist = stbi__zreceive(a,5) + 1; int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; memset(codelength_sizes, 0, sizeof(codelength_sizes)); for (i=0; i < hclen; ++i) { @@ -3730,27 +4040,29 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; n = 0; - while (n < hlit + hdist) { + while (n < ntot) { int c = stbi__zhuffman_decode(a, &z_codelength); if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); if (c < 16) lencodes[n++] = (stbi_uc) c; - else if (c == 16) { - c = stbi__zreceive(a,2)+3; - memset(lencodes+n, lencodes[n-1], c); - n += c; - } else if (c == 17) { - c = stbi__zreceive(a,3)+3; - memset(lencodes+n, 0, c); - n += c; - } else { - STBI_ASSERT(c == 18); - c = stbi__zreceive(a,7)+11; - memset(lencodes+n, 0, c); + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); n += c; } } - if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; return 1; @@ -3798,9 +4110,24 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) return 1; } -// @TODO: should statically initialize these for optimal thread safety -static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; -static void stbi__init_zdefaults(void) +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: { int i; // use <= to match clearly with spec for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; @@ -3810,6 +4137,7 @@ static void stbi__init_zdefaults(void) for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; } +*/ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) { @@ -3828,7 +4156,6 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) } else { if (type == 1) { // use fixed code lengths - if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; } else { @@ -3953,7 +4280,7 @@ static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) static int stbi__check_png_header(stbi__context *s) { - static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; int i; for (i=0; i < 8; ++i) if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); @@ -3999,7 +4326,7 @@ static int stbi__paeth(int a, int b, int c) return c; } -static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) @@ -4016,20 +4343,21 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r int width = x; STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_len = (img_width_bytes + 1) * y; - if (s->img_x == x && s->img_y == y) { - if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); - } else { // interlaced: - if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); - } + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); for (j=0; j < y; ++j) { stbi_uc *cur = a->out + stride*j; - stbi_uc *prior = cur - stride; + stbi_uc *prior; int filter = *raw++; if (filter > 4) @@ -4041,6 +4369,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r filter_bytes = 1; width = img_width_bytes; } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; @@ -4081,37 +4410,37 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r // this is a little gross, so that we don't switch per-pixel or per-component if (depth < 8 || img_n == out_n) { int nk = (width - 1)*filter_bytes; - #define CASE(f) \ + #define STBI__CASE(f) \ case f: \ for (k=0; k < nk; ++k) switch (filter) { // "none" filter turns into a memcpy here; make that explicit. case STBI__F_none: memcpy(cur, raw, nk); break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; - CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; } - #undef CASE + #undef STBI__CASE raw += nk; } else { STBI_ASSERT(img_n+1 == out_n); - #define CASE(f) \ + #define STBI__CASE(f) \ case f: \ for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ for (k=0; k < filter_bytes; ++k) switch (filter) { - CASE(STBI__F_none) cur[k] = raw[k]; break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break; - CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break; + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; } - #undef CASE + #undef STBI__CASE // the loop above sets the high byte of the pixels' alpha, but for // 16 bit png files we also need the low byte set. we'll do that here. @@ -4214,13 +4543,15 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) { + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; stbi_uc *final; int p; if (!interlaced) return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); // de-interlacing - final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; @@ -4240,8 +4571,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3 for (i=0; i < x; ++i) { int out_y = j*yspc[p]+yorig[p]; int out_x = i*xspc[p]+xorig[p]; - memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, - a->out + (j*x+i)*out_n, out_n); + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); } } STBI_FREE(a->out); @@ -4309,7 +4640,7 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; stbi_uc *p, *temp_out, *orig = a->out; - p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); if (p == NULL) return stbi__err("outofmem", "Out of memory"); // between here and free(out) below, exitting would leak @@ -4341,26 +4672,6 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int return 1; } -static int stbi__reduce_png(stbi__png *p) -{ - int i; - int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n; - stbi_uc *reduced; - stbi__uint16 *orig = (stbi__uint16*)p->out; - - if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data - - reduced = (stbi_uc *)stbi__malloc(img_len); - if (p == NULL) return stbi__err("outofmem", "Out of memory"); - - for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling - - p->out = reduced; - STBI_FREE(orig); - - return 1; -} - static int stbi__unpremultiply_on_load = 0; static int stbi__de_iphone_flag = 0; @@ -4395,9 +4706,10 @@ static void stbi__de_iphone(stbi__png *z) stbi_uc a = p[3]; stbi_uc t = p[0]; if (a) { - p[0] = p[2] * 255 / a; - p[1] = p[1] * 255 / a; - p[2] = t * 255 / a; + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; } else { p[0] = p[2]; p[2] = t; @@ -4416,7 +4728,7 @@ static void stbi__de_iphone(stbi__png *z) } } -#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { @@ -4451,7 +4763,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); @@ -4500,7 +4812,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; if (z->depth == 16) { - for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is } else { for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger } @@ -4560,6 +4872,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (req_comp >= 3) s->img_out_n = req_comp; if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; } STBI_FREE(z->expanded); z->expanded = NULL; return 1; @@ -4587,20 +4902,22 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) } } -static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp) +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) { - unsigned char *result=NULL; + void *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - if (p->depth == 16) { - if (!stbi__reduce_png(p)) { - return result; - } - } + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { - result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); p->s->img_out_n = req_comp; if (result == NULL) return result; } @@ -4615,11 +4932,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req return result; } -static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi__png p; p.s = s; - return stbi__do_png(&p, x,y,comp,req_comp); + return stbi__do_png(&p, x,y,comp,req_comp, ri); } static int stbi__png_test(stbi__context *s) @@ -4648,6 +4965,19 @@ static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) p.s = s; return stbi__png_info_raw(&p, x, y, comp); } + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} #endif // Microsoft/Windows BMP image @@ -4699,21 +5029,27 @@ static int stbi__bitcount(unsigned int a) return a & 0xff; } +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. static int stbi__shiftsigned(int v, int shift, int bits) { - int result; - int z=0; - - if (shift < 0) v <<= -shift; - else v >>= shift; - result = v; - - z = bits; - while (z < 8) { - result += v >> z; - z += bits; - } - return result; + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v >= 0 && v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; } typedef struct @@ -4732,7 +5068,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); info->mr = info->mg = info->mb = info->ma = 0; - + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { s->img_x = stbi__get16le(s); @@ -4743,7 +5079,6 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) } if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); info->bpp = stbi__get16le(s); - if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); if (hsz != 12) { int compress = stbi__get32le(s); if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); @@ -4807,7 +5142,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) } -static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; unsigned int mr=0,mg=0,mb=0,ma=0, all_a; @@ -4815,8 +5150,9 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int int psize=0,i,j,width; int flip_vertically, pad, target; stbi__bmp_data info; + STBI_NOTUSED(ri); - info.all_a = 255; + info.all_a = 255; if (stbi__bmp_parse_header(s, &info) == NULL) return NULL; // error code already set @@ -4843,7 +5179,11 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int else target = s->img_n; // if they want monochrome, we'll post-convert - out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (info.bpp < 16) { int z=0; @@ -4856,29 +5196,47 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int pal[i][3] = 255; } stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); - if (info.bpp == 4) width = (s->img_x + 1) >> 1; + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; else if (info.bpp == 8) width = s->img_x; else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } pad = (-width)&3; - for (j=0; j < (int) s->img_y; ++j) { - for (i=0; i < (int) s->img_x; i += 2) { - int v=stbi__get8(s),v2=0; - if (info.bpp == 4) { - v2 = v & 15; - v >>= 4; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } } - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - if (i+1 == (int) s->img_x) break; - v = (info.bpp == 8) ? stbi__get8(s) : v2; - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); } - stbi__skip(s, pad); } } else { int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; @@ -4919,7 +5277,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int int bpp = info.bpp; for (i=0; i < (int) s->img_x; ++i) { stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); - int a; + unsigned int a; out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); @@ -4931,7 +5289,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int stbi__skip(s, pad); } } - + // if alpha channel is all 0s, replace with all 255s if (target == 4 && all_a == 0) for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) @@ -4967,14 +5325,14 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) { // only RGB or RGBA (incl. 16bit) or grey allowed - if(is_rgb16) *is_rgb16 = 0; + if (is_rgb16) *is_rgb16 = 0; switch(bits_per_pixel) { case 8: return STBI_grey; case 16: if(is_grey) return STBI_grey_alpha; - // else: fall-through + // fallthrough case 15: if(is_rgb16) *is_rgb16 = 1; - return STBI_rgb; - case 24: // fall-through + return STBI_rgb; + case 24: // fallthrough case 32: return bits_per_pixel/8; default: return 0; } @@ -5077,18 +5435,18 @@ static int stbi__tga_test(stbi__context *s) } // read 16bit value and convert to 24bit RGB -void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) { - stbi__uint16 px = stbi__get16le(s); + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); stbi__uint16 fiveBitMask = 31; // we have 3 channels with 5bits each int r = (px >> 10) & fiveBitMask; int g = (px >> 5) & fiveBitMask; int b = px & fiveBitMask; // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later - out[0] = (r * 255)/31; - out[1] = (g * 255)/31; - out[2] = (b * 255)/31; + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); // some people claim that the most significant bit might be used for alpha // (possibly if an alpha-bit is set in the "image descriptor byte") @@ -5096,7 +5454,7 @@ void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) // so let's treat all 15 and 16bit TGAs as RGB with no alpha. } -static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { // read in the TGA header stuff int tga_offset = stbi__get8(s); @@ -5118,10 +5476,11 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int unsigned char *tga_data; unsigned char *tga_palette = NULL; int i, j; - unsigned char raw_data[4]; + unsigned char raw_data[4] = {0}; int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; + STBI_NOTUSED(ri); // do a tiny bit of precessing if ( tga_image_type >= 8 ) @@ -5143,7 +5502,10 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int *y = tga_height; if (comp) *comp = tga_comp; - tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); // skip to the data's starting position (offset usually = 0) @@ -5162,7 +5524,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int // any data to skip? (offset usually = 0) stbi__skip(s, tga_palette_start ); // load the palette - tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp ); + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); if (!tga_palette) { STBI_FREE(tga_data); return stbi__errpuc("outofmem", "Out of memory"); @@ -5298,14 +5660,53 @@ static int stbi__psd_test(stbi__context *s) return r; } -static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { - int pixelCount; + int pixelCount; int channelCount, compression; - int channel, i, count, len; + int channel, i; int bitdepth; int w,h; stbi_uc *out; + STBI_NOTUSED(ri); // Check identifier if (stbi__get32be(s) != 0x38425053) // "8BPS" @@ -5362,8 +5763,18 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int if (compression > 1) return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + // Create the destination image. - out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); pixelCount = w*h; @@ -5395,82 +5806,86 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int *p = (channel == 3 ? 255 : 0); } else { // Read the RLE data. - count = 0; - while (count < pixelCount) { - len = stbi__get8(s); - if (len == 128) { - // No-op. - } else if (len < 128) { - // Copy next len+1 bytes literally. - len++; - count += len; - while (len) { - *p = stbi__get8(s); - p += 4; - len--; - } - } else if (len > 128) { - stbi_uc val; - // Next -len+1 bytes in the dest are replicated from next source byte. - // (Interpret len as a negative 8-bit int.) - len ^= 0x0FF; - len += 2; - val = stbi__get8(s); - count += len; - while (len) { - *p = val; - p += 4; - len--; - } - } + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); } } } } else { // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) - // where each channel consists of an 8-bit value for each pixel in the image. + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. // Read the data by channel. for (channel = 0; channel < 4; channel++) { - stbi_uc *p; - - p = out + channel; if (channel >= channelCount) { // Fill this channel with default data. - stbi_uc val = channel == 3 ? 255 : 0; - for (i = 0; i < pixelCount; i++, p += 4) - *p = val; - } else { - // Read the data. - if (bitdepth == 16) { - for (i = 0; i < pixelCount; i++, p += 4) - *p = (stbi_uc) (stbi__get16be(s) >> 8); + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get8(s); + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } } } } } + // remove weird white matte from PSD if (channelCount >= 4) { - for (i=0; i < w*h; ++i) { - unsigned char *pixel = out + 4*i; - if (pixel[3] != 0 && pixel[3] != 255) { - // remove weird white matte from PSD - float a = pixel[3] / 255.0f; - float ra = 1.0f / a; - float inv_a = 255.0f * (1 - ra); - pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); - pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); - pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } } } } + // convert to desired output format if (req_comp && req_comp != 4) { - out = stbi__convert_format(out, 4, req_comp, w, h); + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); if (out == NULL) return out; // stbi__convert_format frees input on failure } @@ -5654,10 +6069,13 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c return result; } -static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp) +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) { stbi_uc *result; - int i, x,y; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; for (i=0; i<92; ++i) stbi__get8(s); @@ -5665,14 +6083,14 @@ static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int re x = stbi__get16be(s); y = stbi__get16be(s); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); - if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); stbi__get32be(s); //skip `ratio' stbi__get16be(s); //skip `fields' stbi__get16be(s); //skip `pad' // intermediate buffer is RGBA - result = (stbi_uc *) stbi__malloc(x*y*4); + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); memset(result, 0xff, x*y*4); if (!stbi__pic_load_core(s,x,y,comp, result)) { @@ -5709,11 +6127,13 @@ typedef struct typedef struct { int w,h; - stbi_uc *out, *old_out; // output buffer (always 4 components) - int flags, bgindex, ratio, transparent, eflags, delay; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; stbi_uc pal[256][4]; stbi_uc lpal[256][4]; - stbi__gif_lzw codes[4096]; + stbi__gif_lzw codes[8192]; stbi_uc *color_table; int parse, step; int lflags; @@ -5721,6 +6141,7 @@ typedef struct int max_x, max_y; int cur_x, cur_y; int line_size; + int delay; } stbi__gif; static int stbi__gif_test_raw(stbi__context *s) @@ -5796,6 +6217,7 @@ static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) { stbi_uc *p, *c; + int idx; // recurse to decode the prefixes, since the linked-list is backwards, // and working backwards through an interleaved image would be nasty @@ -5804,10 +6226,12 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) if (g->cur_y >= g->max_y) return; - p = &g->out[g->cur_x + g->cur_y]; - c = &g->color_table[g->codes[code].suffix * 4]; + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; - if (c[3] >= 128) { + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; p[0] = c[2]; p[1] = c[1]; p[2] = c[0]; @@ -5881,11 +6305,16 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) stbi__skip(s,len); return g->out; } else if (code <= avail) { - if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } if (oldcode >= 0) { p = &g->codes[avail++]; - if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + p->prefix = (stbi__int16) oldcode; p->first = g->codes[oldcode].first; p->suffix = (code == avail) ? p->first : g->codes[code].first; @@ -5907,59 +6336,72 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) } } -static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1) -{ - int x, y; - stbi_uc *c = g->pal[g->bgindex]; - for (y = y0; y < y1; y += 4 * g->w) { - for (x = x0; x < x1; x += 4) { - stbi_uc *p = &g->out[y + x]; - p[0] = c[2]; - p[1] = c[1]; - p[2] = c[0]; - p[3] = 0; - } - } -} - // this function is designed to support animated gifs, although stb_image doesn't support it -static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) -{ - int i; - stbi_uc *prev_out = 0; - - if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) - return 0; // stbi__g_failure_reason set by stbi__gif_header +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->history = (stbi_uc *) stbi__malloc(g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "tranparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to teh color that was there the previous frame. + memset( g->out, 0x00, 4 * g->w * g->h ); + memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent) + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; - prev_out = g->out; - g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); - if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } - switch ((g->eflags & 0x1C) >> 2) { - case 0: // unspecified (also always used on 1st frame) - stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h); - break; - case 1: // do not dispose - if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); - g->old_out = prev_out; - break; - case 2: // dispose to background - if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); - stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y); - break; - case 3: // dispose to previous - if (g->old_out) { - for (i = g->start_y; i < g->max_y; i += 4 * g->w) - memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x); + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } } - break; + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); } + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + for (;;) { - switch (stbi__get8(s)) { + int tag = stbi__get8(s); + switch (tag) { case 0x2C: /* Image Descriptor */ { - int prev_trans = -1; stbi__int32 x, y, w, h; stbi_uc *o; @@ -5992,19 +6434,24 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); g->color_table = (stbi_uc *) g->lpal; } else if (g->flags & 0x80) { - if (g->transparent >= 0 && (g->eflags & 0x01)) { - prev_trans = g->pal[g->transparent][3]; - g->pal[g->transparent][3] = 0; - } g->color_table = (stbi_uc *) g->pal; } else - return stbi__errpuc("missing color table", "Corrupt GIF"); - + return stbi__errpuc("missing color table", "Corrupt GIF"); + o = stbi__process_gif_raster(s, g); if (o == NULL) return NULL; - if (prev_trans != -1) - g->pal[g->transparent][3] = (stbi_uc) prev_trans; + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } return o; } @@ -6012,19 +6459,35 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i case 0x21: // Comment Extension. { int len; - if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. len = stbi__get8(s); if (len == 4) { g->eflags = stbi__get8(s); - g->delay = stbi__get16le(s); - g->transparent = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } } else { stbi__skip(s, len); break; } - } - while ((len = stbi__get8(s)) != 0) + } + while ((len = stbi__get8(s)) != 0) { stbi__skip(s, len); + } break; } @@ -6035,27 +6498,92 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i return stbi__errpuc("unknown code", "Corrupt GIF"); } } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } - STBI_NOTUSED(req_comp); + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } } -static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *u = 0; - stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); - memset(g, 0, sizeof(*g)); + stbi__gif g; + memset(&g, 0, sizeof(g)); - u = stbi__gif_load_next(s, g, comp, req_comp); + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { - *x = g->w; - *y = g->h; + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. if (req_comp && req_comp != 4) - u = stbi__convert_format(u, 4, req_comp, g->w, g->h); + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); } - else if (g->out) - STBI_FREE(g->out); - STBI_FREE(g); + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + return u; } @@ -6069,20 +6597,24 @@ static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) // Radiance RGBE HDR loader // originally by Nicolas Schulz #ifndef STBI_NO_HDR -static int stbi__hdr_test_core(stbi__context *s) +static int stbi__hdr_test_core(stbi__context *s, const char *signature) { - const char *signature = "#?RADIANCE\n"; int i; for (i=0; signature[i]; ++i) if (stbi__get8(s) != signature[i]) - return 0; + return 0; + stbi__rewind(s); return 1; } static int stbi__hdr_test(stbi__context* s) { - int r = stbi__hdr_test_core(s); + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } return r; } @@ -6136,7 +6668,7 @@ static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) } } -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { char buffer[STBI__HDR_BUFLEN]; char *token; @@ -6147,10 +6679,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re int len; unsigned char count, value; int i, j, k, c1,c2, z; - + const char *headerToken; + STBI_NOTUSED(ri); // Check identifier - if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) return stbi__errpf("not HDR", "Corrupt HDR image"); // Parse header @@ -6179,8 +6713,13 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re if (comp) *comp = 3; if (req_comp == 0) req_comp = 3; + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + // Read data - hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); // Load image data // image data is stored as some number of sca @@ -6219,20 +6758,29 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re len <<= 8; len |= stbi__get8(s); if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } - if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } for (k = 0; k < 4; ++k) { + int nleft; i = 0; - while (i < width) { + while ((nleft = width - i) > 0) { count = stbi__get8(s); if (count > 128) { // Run value = stbi__get8(s); count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = value; } else { // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = stbi__get8(s); } @@ -6241,7 +6789,8 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re for (i=0; i < width; ++i) stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); } - STBI_FREE(scanline); + if (scanline) + STBI_FREE(scanline); } return hdr_data; @@ -6252,6 +6801,11 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) char buffer[STBI__HDR_BUFLEN]; char *token; int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; if (stbi__hdr_test(s) == 0) { stbi__rewind( s ); @@ -6293,14 +6847,14 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) void *p; stbi__bmp_data info; - info.all_a = 255; + info.all_a = 255; p = stbi__bmp_parse_header(s, &info); stbi__rewind( s ); if (p == NULL) return 0; - *x = s->img_x; - *y = s->img_y; - *comp = info.ma ? 4 : 3; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) *comp = info.ma ? 4 : 3; return 1; } #endif @@ -6308,7 +6862,10 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) #ifndef STBI_NO_PSD static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) { - int channelCount; + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; @@ -6325,7 +6882,8 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) } *y = stbi__get32be(s); *x = stbi__get32be(s); - if (stbi__get16be(s) != 8) { + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { stbi__rewind( s ); return 0; } @@ -6336,14 +6894,45 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) *comp = 4; return 1; } + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + (void) stbi__get32be(s); + (void) stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} #endif #ifndef STBI_NO_PIC static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) { - int act_comp=0,num_packets=0,chained; + int act_comp=0,num_packets=0,chained,dummy; stbi__pic_packet packets[10]; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { stbi__rewind(s); return 0; @@ -6419,16 +7008,22 @@ static int stbi__pnm_test(stbi__context *s) return 1; } -static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; + STBI_NOTUSED(ri); + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) return 0; + *x = s->img_x; *y = s->img_y; - *comp = s->img_n; + if (comp) *comp = s->img_n; - out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y); + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); stbi__getn(s, out, s->img_n * s->img_x * s->img_y); @@ -6477,16 +7072,20 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c) static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) { - int maxv; + int maxv, dummy; char c, p, t; - stbi__rewind( s ); + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); // Get identifier p = (char) stbi__get8(s); t = (char) stbi__get8(s); if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind( s ); + stbi__rewind(s); return 0; } @@ -6552,6 +7151,19 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) return stbi__err("unknown image type", "Image not of any known type, or corrupt"); } +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + #ifndef STBI_NO_STDIO STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) { @@ -6573,6 +7185,27 @@ STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) fseek(f,pos,SEEK_SET); return r; } + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} #endif // !STBI_NO_STDIO STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) @@ -6589,10 +7222,43 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int return stbi__info_main(&s,x,y,comp); } +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + #endif // STB_IMAGE_IMPLEMENTATION /* revision history: + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) allocate large structures on the stack remove white matting for transparent PSD @@ -6753,3 +7419,46 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int 0.50 (2006-11-19) first released version */ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/src/tosixel.c b/src/tosixel.c index 781d304b..0166dc4f 100644 --- a/src/tosixel.c +++ b/src/tosixel.c @@ -43,8 +43,8 @@ #define SCREEN_PACKET_SIZE 256 enum { - PALETTE_HIT = 1, - PALETTE_CHANGE = 2, + PALETTE_HIT = 1, + PALETTE_CHANGE = 2 }; /* implementation */ @@ -518,7 +518,7 @@ sixel_encode_body( sizeof(unsigned char)); if (map == NULL) { sixel_helper_set_additional_message( - "sixel_encode_body: sixel_allocator_malloc() failed."); + "sixel_encode_body: sixel_allocator_calloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } @@ -824,7 +824,6 @@ sixel_encode_dither( return status; } - static void dither_func_none(unsigned char *data, int width) { @@ -1167,6 +1166,50 @@ dither_func_burkes(unsigned char *data, int width) } +static void +dither_func_a_dither(unsigned char *data, int width, int x, int y) +{ + int c; + float value; + float mask; + + (void) width; /* unused */ + + for (c = 0; c < 3; c ++) { + mask = (((x + c * 17) + y * 236) * 119) & 255; + mask = ((mask - 128) / 256.0f) ; + value = data[c] + mask; + if (value < 0) { + value = 0; + } + value = value > 255 ? 255 : value; + data[c] = value; + } +} + + +static void +dither_func_x_dither(unsigned char *data, int width, int x, int y) +{ + int c; + float value; + float mask; + + (void) width; /* unused */ + + for (c = 0; c < 3; c ++) { + mask = (((x + c * 17) ^ y * 236) * 1234) & 511; + mask = ((mask - 128) / 512.0f) ; + value = data[c] + mask; + if (value < 0) { + value = 0; + } + value = value > 255 ? 255 : value; + data[c] = value; + } +} + + static void sixel_apply_15bpp_dither( unsigned char *pixels, @@ -1200,6 +1243,12 @@ sixel_apply_15bpp_dither( dither_func_burkes(pixels, width); } break; + case SIXEL_DIFFUSE_A_DITHER: + dither_func_a_dither(pixels, width, x, y); + break; + case SIXEL_DIFFUSE_X_DITHER: + dither_func_x_dither(pixels, width, x, y); + break; case SIXEL_DIFFUSE_NONE: default: dither_func_none(pixels, width); @@ -1282,12 +1331,13 @@ sixel_encode_highcolor( if (*mptr) { *dst = 255; } else { - pix = ((pixels[0] & 0xf8) << 7) | - ((pixels[1] & 0xf8) << 2) | - ((pixels[2] >> 3) & 0x1f); sixel_apply_15bpp_dither(pixels, x, y, width, height, dither->method_for_diffuse); + pix = ((pixels[0] & 0xf8) << 7) | + ((pixels[1] & 0xf8) << 2) | + ((pixels[2] >> 3) & 0x1f); + if (!rgbhit[pix]) { while (1) { if (nextpal >= 255) { diff --git a/src/writer.c b/src/writer.c index 49db99af..bd3abf70 100644 --- a/src/writer.c +++ b/src/writer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Hayaki Saito + * Copyright (c) 2014-2018 Hayaki Saito * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -551,7 +551,7 @@ test6(void) } -int +SIXELAPI int sixel_writer_tests_main(void) { int nret = EXIT_FAILURE; diff --git a/tools/Makefile.in b/tools/Makefile.in index d36c1d07..63aa7bc3 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it,