Repository: Beyka/Android-TiffBitmapFactory
Branch: master
Commit: 05b455b32a77
Files: 513
Total size: 6.1 MB
Directory structure:
gitextract_fbcwkp2b/
├── .gitignore
├── CHANGELOG.txt
├── README.md
├── build.gradle
├── license.txt
├── proguard-rules.pro
└── src/
├── androidTest/
│ └── java/
│ └── org/
│ └── beyka/
│ └── tiffbitmapfactory/
│ └── ApplicationTest.java
└── main/
├── .gitignore
├── AndroidManifest.xml
├── java/
│ └── org/
│ └── beyka/
│ └── tiffbitmapfactory/
│ ├── CompressionScheme.java
│ ├── DecodeArea.java
│ ├── FillOrder.java
│ ├── IProgressListener.java
│ ├── ImageFormat.java
│ ├── Orientation.java
│ ├── Photometric.java
│ ├── PlanarConfig.java
│ ├── ResolutionUnit.java
│ ├── TiffBitmapFactory.java
│ ├── TiffConverter.java
│ ├── TiffSaver.java
│ └── exceptions/
│ ├── CantOpenFileException.java
│ ├── DecodeTiffException.java
│ └── NotEnoughtMemoryException.java
├── jni/
│ ├── Android.mk
│ ├── Application.mk
│ ├── BMP.h
│ ├── BaseTiffConverter.cpp
│ ├── BaseTiffConverter.h
│ ├── BitmapReader.cpp
│ ├── BitmapReader.h
│ ├── BmpToTiffConverter.cpp
│ ├── BmpToTiffConverter.h
│ ├── JpgToTiffConverter.cpp
│ ├── JpgToTiffConverter.h
│ ├── NativeDecoder.cpp
│ ├── NativeDecoder.h
│ ├── NativeExceptions.cpp
│ ├── NativeExceptions.h
│ ├── NativeTiffBitmapFactory.cpp
│ ├── NativeTiffBitmapFactory.h
│ ├── NativeTiffConverter.cpp
│ ├── NativeTiffConverter.h
│ ├── NativeTiffSaver.cpp
│ ├── NativeTiffSaver.h
│ ├── PngToTiffConverter.cpp
│ ├── PngToTiffConverter.h
│ ├── TiffToBmpConverter.cpp
│ ├── TiffToBmpConverter.h
│ ├── TiffToJpgConverter.cpp
│ ├── TiffToJpgConverter.h
│ ├── TiffToPngConverter.cpp
│ ├── TiffToPngConverter.h
│ ├── jpeg/
│ │ ├── jconfig.h
│ │ ├── jerror.h
│ │ ├── jmorecfg.h
│ │ └── jpeglib.h
│ ├── libs/
│ │ ├── arm64-v8a/
│ │ │ ├── libjpeg.a
│ │ │ └── libpng.a
│ │ ├── armeabi/
│ │ │ ├── libjpeg.a
│ │ │ └── libpng.a
│ │ ├── armeabi-v7a/
│ │ │ ├── libjpeg.a
│ │ │ └── libpng.a
│ │ ├── mips/
│ │ │ ├── libjpeg.a
│ │ │ └── libpng.a
│ │ ├── mips64/
│ │ │ ├── libjpeg.a
│ │ │ └── libpng.a
│ │ ├── x86/
│ │ │ ├── libjpeg.a
│ │ │ └── libpng.a
│ │ └── x86_64/
│ │ ├── libjpeg.a
│ │ └── libpng.a
│ ├── png/
│ │ ├── config.h
│ │ ├── png.h
│ │ ├── pngconf.h
│ │ └── pngpriv.h
│ ├── tiff/
│ │ ├── Android.mk
│ │ ├── COPYRIGHT
│ │ ├── ChangeLog
│ │ ├── HOWTO-RELEASE
│ │ ├── Makefile.am
│ │ ├── Makefile.in
│ │ ├── Makefile.vc
│ │ ├── README
│ │ ├── README.android
│ │ ├── README.vms
│ │ ├── RELEASE-DATE
│ │ ├── SConstruct
│ │ ├── TODO
│ │ ├── VERSION
│ │ ├── aclocal.m4
│ │ ├── autogen.sh
│ │ ├── build/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ └── README
│ │ ├── config/
│ │ │ ├── compile
│ │ │ ├── config.guess
│ │ │ ├── config.sub
│ │ │ ├── depcomp
│ │ │ ├── install-sh
│ │ │ ├── ltmain.sh
│ │ │ ├── missing
│ │ │ └── mkinstalldirs
│ │ ├── configure
│ │ ├── configure.ac
│ │ ├── configure.com
│ │ ├── contrib/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ ├── README
│ │ │ ├── acorn/
│ │ │ │ ├── Makefile.acorn
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── ReadMe
│ │ │ │ ├── SetVars
│ │ │ │ ├── cleanlib
│ │ │ │ ├── convert
│ │ │ │ └── install
│ │ │ ├── addtiffo/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── Makefile.vc
│ │ │ │ ├── README
│ │ │ │ ├── addtiffo.c
│ │ │ │ ├── tif_overview.c
│ │ │ │ ├── tif_ovrcache.c
│ │ │ │ └── tif_ovrcache.h
│ │ │ ├── dbs/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── tiff-bi.c
│ │ │ │ ├── tiff-grayscale.c
│ │ │ │ ├── tiff-palette.c
│ │ │ │ ├── tiff-rgb.c
│ │ │ │ └── xtiff/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── patchlevel.h
│ │ │ │ ├── xtiff.c
│ │ │ │ └── xtifficon.h
│ │ │ ├── iptcutil/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── iptcutil.c
│ │ │ │ ├── test.iptc
│ │ │ │ └── test.txt
│ │ │ ├── mac-cw/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── Makefile.script
│ │ │ │ ├── README
│ │ │ │ ├── mac_main.c
│ │ │ │ ├── mac_main.h
│ │ │ │ ├── metrowerks.note
│ │ │ │ ├── mkg3_main.c
│ │ │ │ └── version.h
│ │ │ ├── mac-mpw/
│ │ │ │ ├── BUILD.mpw
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── libtiff.make
│ │ │ │ ├── mactrans.c
│ │ │ │ ├── port.make
│ │ │ │ ├── tools.make
│ │ │ │ └── top.make
│ │ │ ├── mfs/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ └── mfs_file.c
│ │ │ ├── pds/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── tif_imageiter.c
│ │ │ │ ├── tif_imageiter.h
│ │ │ │ ├── tif_pdsdirread.c
│ │ │ │ └── tif_pdsdirwrite.c
│ │ │ ├── ras/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── ras2tif.c
│ │ │ │ └── tif2ras.c
│ │ │ ├── stream/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── tiffstream.cpp
│ │ │ │ └── tiffstream.h
│ │ │ ├── tags/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── README
│ │ │ │ ├── listtif.c
│ │ │ │ ├── maketif.c
│ │ │ │ ├── xtif_dir.c
│ │ │ │ ├── xtiffio.h
│ │ │ │ └── xtiffiop.h
│ │ │ └── win_dib/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ ├── Makefile.w95
│ │ │ ├── README.Tiffile
│ │ │ ├── README.tiff2dib
│ │ │ ├── Tiffile.cpp
│ │ │ └── tiff2dib.c
│ │ ├── html/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ ├── TIFFTechNote2.html
│ │ │ ├── addingtags.html
│ │ │ ├── bugs.html
│ │ │ ├── build.html
│ │ │ ├── contrib.html
│ │ │ ├── document.html
│ │ │ ├── images/
│ │ │ │ ├── Makefile.am
│ │ │ │ └── Makefile.in
│ │ │ ├── images.html
│ │ │ ├── index.html
│ │ │ ├── internals.html
│ │ │ ├── intro.html
│ │ │ ├── libtiff.html
│ │ │ ├── man/
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── Makefile.in
│ │ │ │ ├── TIFFClose.3tiff.html
│ │ │ │ ├── TIFFDataWidth.3tiff.html
│ │ │ │ ├── TIFFError.3tiff.html
│ │ │ │ ├── TIFFFlush.3tiff.html
│ │ │ │ ├── TIFFGetField.3tiff.html
│ │ │ │ ├── TIFFOpen.3tiff.html
│ │ │ │ ├── TIFFPrintDirectory.3tiff.html
│ │ │ │ ├── TIFFRGBAImage.3tiff.html
│ │ │ │ ├── TIFFReadDirectory.3tiff.html
│ │ │ │ ├── TIFFReadEncodedStrip.3tiff.html
│ │ │ │ ├── TIFFReadEncodedTile.3tiff.html
│ │ │ │ ├── TIFFReadRGBAImage.3tiff.html
│ │ │ │ ├── TIFFReadRGBAStrip.3tiff.html
│ │ │ │ ├── TIFFReadRGBATile.3tiff.html
│ │ │ │ ├── TIFFReadRawStrip.3tiff.html
│ │ │ │ ├── TIFFReadRawTile.3tiff.html
│ │ │ │ ├── TIFFReadScanline.3tiff.html
│ │ │ │ ├── TIFFReadTile.3tiff.html
│ │ │ │ ├── TIFFSetDirectory.3tiff.html
│ │ │ │ ├── TIFFSetField.3tiff.html
│ │ │ │ ├── TIFFWarning.3tiff.html
│ │ │ │ ├── TIFFWriteDirectory.3tiff.html
│ │ │ │ ├── TIFFWriteEncodedStrip.3tiff.html
│ │ │ │ ├── TIFFWriteEncodedTile.3tiff.html
│ │ │ │ ├── TIFFWriteRawStrip.3tiff.html
│ │ │ │ ├── TIFFWriteRawTile.3tiff.html
│ │ │ │ ├── TIFFWriteScanline.3tiff.html
│ │ │ │ ├── TIFFWriteTile.3tiff.html
│ │ │ │ ├── TIFFbuffer.3tiff.html
│ │ │ │ ├── TIFFcodec.3tiff.html
│ │ │ │ ├── TIFFcolor.3tiff.html
│ │ │ │ ├── TIFFmemory.3tiff.html
│ │ │ │ ├── TIFFquery.3tiff.html
│ │ │ │ ├── TIFFsize.3tiff.html
│ │ │ │ ├── TIFFstrip.3tiff.html
│ │ │ │ ├── TIFFswab.3tiff.html
│ │ │ │ ├── TIFFtile.3tiff.html
│ │ │ │ ├── fax2ps.1.html
│ │ │ │ ├── fax2tiff.1.html
│ │ │ │ ├── gif2tiff.1.html
│ │ │ │ ├── index.html
│ │ │ │ ├── libtiff.3tiff.html
│ │ │ │ ├── pal2rgb.1.html
│ │ │ │ ├── ppm2tiff.1.html
│ │ │ │ ├── ras2tiff.1.html
│ │ │ │ ├── raw2tiff.1.html
│ │ │ │ ├── rgb2ycbcr.1.html
│ │ │ │ ├── sgi2tiff.1.html
│ │ │ │ ├── thumbnail.1.html
│ │ │ │ ├── tiff2bw.1.html
│ │ │ │ ├── tiff2pdf.1.html
│ │ │ │ ├── tiff2ps.1.html
│ │ │ │ ├── tiff2rgba.1.html
│ │ │ │ ├── tiffcmp.1.html
│ │ │ │ ├── tiffcp.1.html
│ │ │ │ ├── tiffcrop.1.html
│ │ │ │ ├── tiffdither.1.html
│ │ │ │ ├── tiffdump.1.html
│ │ │ │ ├── tiffgt.1.html
│ │ │ │ ├── tiffinfo.1.html
│ │ │ │ ├── tiffmedian.1.html
│ │ │ │ ├── tiffset.1.html
│ │ │ │ ├── tiffsplit.1.html
│ │ │ │ └── tiffsv.1.html
│ │ │ ├── misc.html
│ │ │ ├── support.html
│ │ │ ├── tools.html
│ │ │ ├── v3.4beta007.html
│ │ │ ├── v3.4beta016.html
│ │ │ ├── v3.4beta018.html
│ │ │ ├── v3.4beta024.html
│ │ │ ├── v3.4beta028.html
│ │ │ ├── v3.4beta029.html
│ │ │ ├── v3.4beta031.html
│ │ │ ├── v3.4beta032.html
│ │ │ ├── v3.4beta033.html
│ │ │ ├── v3.4beta034.html
│ │ │ ├── v3.4beta035.html
│ │ │ ├── v3.4beta036.html
│ │ │ ├── v3.5.1.html
│ │ │ ├── v3.5.2.html
│ │ │ ├── v3.5.3.html
│ │ │ ├── v3.5.4.html
│ │ │ ├── v3.5.5.html
│ │ │ ├── v3.5.6-beta.html
│ │ │ ├── v3.5.7.html
│ │ │ ├── v3.6.0.html
│ │ │ ├── v3.6.1.html
│ │ │ ├── v3.7.0.html
│ │ │ ├── v3.7.0alpha.html
│ │ │ ├── v3.7.0beta.html
│ │ │ ├── v3.7.0beta2.html
│ │ │ ├── v3.7.1.html
│ │ │ ├── v3.7.2.html
│ │ │ ├── v3.7.3.html
│ │ │ ├── v3.7.4.html
│ │ │ ├── v3.8.0.html
│ │ │ ├── v3.8.1.html
│ │ │ ├── v3.8.2.html
│ │ │ ├── v3.9.0beta.html
│ │ │ ├── v3.9.1.html
│ │ │ └── v3.9.2.html
│ │ ├── libtiff/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ ├── Makefile.vc
│ │ │ ├── SConstruct
│ │ │ ├── libtiff.def
│ │ │ ├── mkg3states.c
│ │ │ ├── t4.h
│ │ │ ├── tif_acorn.c
│ │ │ ├── tif_apple.c
│ │ │ ├── tif_atari.c
│ │ │ ├── tif_aux.c
│ │ │ ├── tif_close.c
│ │ │ ├── tif_codec.c
│ │ │ ├── tif_color.c
│ │ │ ├── tif_compress.c
│ │ │ ├── tif_config.h
│ │ │ ├── tif_config.h-vms
│ │ │ ├── tif_config.h.in
│ │ │ ├── tif_config.vc.h
│ │ │ ├── tif_config.wince.h
│ │ │ ├── tif_dir.c
│ │ │ ├── tif_dir.h
│ │ │ ├── tif_dirinfo.c
│ │ │ ├── tif_dirread.c
│ │ │ ├── tif_dirwrite.c
│ │ │ ├── tif_dumpmode.c
│ │ │ ├── tif_error.c
│ │ │ ├── tif_extension.c
│ │ │ ├── tif_fax3.c
│ │ │ ├── tif_fax3.h
│ │ │ ├── tif_fax3sm.c
│ │ │ ├── tif_flush.c
│ │ │ ├── tif_getimage.c
│ │ │ ├── tif_jbig.c
│ │ │ ├── tif_jpeg.c
│ │ │ ├── tif_luv.c
│ │ │ ├── tif_lzw.c
│ │ │ ├── tif_msdos.c
│ │ │ ├── tif_next.c
│ │ │ ├── tif_ojpeg.c
│ │ │ ├── tif_open.c
│ │ │ ├── tif_packbits.c
│ │ │ ├── tif_pixarlog.c
│ │ │ ├── tif_predict.c
│ │ │ ├── tif_predict.h
│ │ │ ├── tif_print.c
│ │ │ ├── tif_read.c
│ │ │ ├── tif_stream.cxx
│ │ │ ├── tif_strip.c
│ │ │ ├── tif_swab.c
│ │ │ ├── tif_thunder.c
│ │ │ ├── tif_tile.c
│ │ │ ├── tif_unix.c
│ │ │ ├── tif_version.c
│ │ │ ├── tif_warning.c
│ │ │ ├── tif_win3.c
│ │ │ ├── tif_win32.c
│ │ │ ├── tif_write.c
│ │ │ ├── tif_zip.c
│ │ │ ├── tiff.h
│ │ │ ├── tiffconf.h
│ │ │ ├── tiffconf.h.in
│ │ │ ├── tiffconf.vc.h
│ │ │ ├── tiffconf.wince.h
│ │ │ ├── tiffio.h
│ │ │ ├── tiffio.hxx
│ │ │ ├── tiffiop.h
│ │ │ ├── tiffvers.h
│ │ │ └── uvcode.h
│ │ ├── m4/
│ │ │ ├── acinclude.m4
│ │ │ ├── libtool.m4
│ │ │ ├── ltoptions.m4
│ │ │ ├── ltsugar.m4
│ │ │ ├── ltversion.m4
│ │ │ └── lt~obsolete.m4
│ │ ├── man/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ ├── TIFFClose.3tiff
│ │ │ ├── TIFFDataWidth.3tiff
│ │ │ ├── TIFFError.3tiff
│ │ │ ├── TIFFFlush.3tiff
│ │ │ ├── TIFFGetField.3tiff
│ │ │ ├── TIFFOpen.3tiff
│ │ │ ├── TIFFPrintDirectory.3tiff
│ │ │ ├── TIFFRGBAImage.3tiff
│ │ │ ├── TIFFReadDirectory.3tiff
│ │ │ ├── TIFFReadEncodedStrip.3tiff
│ │ │ ├── TIFFReadEncodedTile.3tiff
│ │ │ ├── TIFFReadRGBAImage.3tiff
│ │ │ ├── TIFFReadRGBAStrip.3tiff
│ │ │ ├── TIFFReadRGBATile.3tiff
│ │ │ ├── TIFFReadRawStrip.3tiff
│ │ │ ├── TIFFReadRawTile.3tiff
│ │ │ ├── TIFFReadScanline.3tiff
│ │ │ ├── TIFFReadTile.3tiff
│ │ │ ├── TIFFSetDirectory.3tiff
│ │ │ ├── TIFFSetField.3tiff
│ │ │ ├── TIFFWarning.3tiff
│ │ │ ├── TIFFWriteDirectory.3tiff
│ │ │ ├── TIFFWriteEncodedStrip.3tiff
│ │ │ ├── TIFFWriteEncodedTile.3tiff
│ │ │ ├── TIFFWriteRawStrip.3tiff
│ │ │ ├── TIFFWriteRawTile.3tiff
│ │ │ ├── TIFFWriteScanline.3tiff
│ │ │ ├── TIFFWriteTile.3tiff
│ │ │ ├── TIFFbuffer.3tiff
│ │ │ ├── TIFFcodec.3tiff
│ │ │ ├── TIFFcolor.3tiff
│ │ │ ├── TIFFmemory.3tiff
│ │ │ ├── TIFFquery.3tiff
│ │ │ ├── TIFFsize.3tiff
│ │ │ ├── TIFFstrip.3tiff
│ │ │ ├── TIFFswab.3tiff
│ │ │ ├── TIFFtile.3tiff
│ │ │ ├── bmp2tiff.1
│ │ │ ├── fax2ps.1
│ │ │ ├── fax2tiff.1
│ │ │ ├── gif2tiff.1
│ │ │ ├── libtiff.3tiff
│ │ │ ├── pal2rgb.1
│ │ │ ├── ppm2tiff.1
│ │ │ ├── ras2tiff.1
│ │ │ ├── raw2tiff.1
│ │ │ ├── rgb2ycbcr.1
│ │ │ ├── sgi2tiff.1
│ │ │ ├── thumbnail.1
│ │ │ ├── tiff2bw.1
│ │ │ ├── tiff2pdf.1
│ │ │ ├── tiff2ps.1
│ │ │ ├── tiff2rgba.1
│ │ │ ├── tiffcmp.1
│ │ │ ├── tiffcp.1
│ │ │ ├── tiffcrop.1
│ │ │ ├── tiffdither.1
│ │ │ ├── tiffdump.1
│ │ │ ├── tiffgt.1
│ │ │ ├── tiffinfo.1
│ │ │ ├── tiffmedian.1
│ │ │ ├── tiffset.1
│ │ │ ├── tiffsplit.1
│ │ │ └── tiffsv.1
│ │ ├── nmake.opt
│ │ ├── port/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ ├── Makefile.vc
│ │ │ ├── dummy.c
│ │ │ ├── getopt.c
│ │ │ ├── lfind.c
│ │ │ ├── libport.h
│ │ │ ├── strcasecmp.c
│ │ │ └── strtoul.c
│ │ ├── test/
│ │ │ ├── Makefile.am
│ │ │ ├── Makefile.in
│ │ │ ├── ascii_tag.c
│ │ │ ├── check_tag.c
│ │ │ ├── long_tag.c
│ │ │ ├── short_tag.c
│ │ │ ├── strip.c
│ │ │ ├── strip_rw.c
│ │ │ ├── test_arrays.c
│ │ │ └── test_arrays.h
│ │ └── tools/
│ │ ├── Makefile.am
│ │ ├── Makefile.in
│ │ ├── Makefile.vc
│ │ ├── bmp2tiff.c
│ │ ├── fax2ps.c
│ │ ├── fax2tiff.c
│ │ ├── gif2tiff.c
│ │ ├── pal2rgb.c
│ │ ├── ppm2tiff.c
│ │ ├── ras2tiff.c
│ │ ├── rasterfile.h
│ │ ├── raw2tiff.c
│ │ ├── rgb2ycbcr.c
│ │ ├── sgi2tiff.c
│ │ ├── sgisv.c
│ │ ├── thumbnail.c
│ │ ├── tiff2bw.c
│ │ ├── tiff2pdf.c
│ │ ├── tiff2ps.c
│ │ ├── tiff2rgba.c
│ │ ├── tiffcmp.c
│ │ ├── tiffcp.c
│ │ ├── tiffcrop.c
│ │ ├── tiffdither.c
│ │ ├── tiffdump.c
│ │ ├── tiffgt.c
│ │ ├── tiffinfo.c
│ │ ├── tiffmedian.c
│ │ ├── tiffset.c
│ │ ├── tiffsplit.c
│ │ └── ycbcr.c
│ ├── tiff.h
│ ├── tiffconf.h
│ ├── tiffio.h
│ └── tiffvers.h
└── res/
└── values/
└── strings.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/build
*.o
*.o.d
*.so
*.iml
================================================
FILE: CHANGELOG.txt
================================================
0.9.9.0
- Added support for decoding and converting files from file descriptors
0.9.8.7
- Fixed converting from JPG to TIFF with CCITTRLE, CCITTFAX3, CCITTFAX4 compression schemes
0.9.8.6
- Changed binary files (rebuild)
0.9.8.5
- Added signal handling of SIGSEGV signal before open tiff images to prevent many silent crashes from libtiff
0.9.8.4
- Added possibility to cancel background processing by interrupting of worker thread as usual in Java
0.9.8.3
-Fixed impossibility to convert full image without bounds
0.9.8.2
-Added handling of SIGSEGV crashes from libtiff
0.9.8
-Added support for dirrect converting files to TIFF and from TIFF
-Fixed bug causing crashing while saving tiff
0.9.7.6
-Added support for CCITT modified Huffman RLE (CCITTRLE) compression scheme
0.9.7.5
- Returned previous version of write bitmap to tiff algorithm with some improvements. This changes is due to an error of writing tiff data with bottom orientations
0.9.7.4
- Add converter utils
- Improved write and read algorithms
0.9.7.3
- Add possibility to decode part of image by specify decode area
0.9.7.2
- Changed saving algorithm to use android native bitmap
- Add progress listener for decoding process
0.9.7.1
- Added reading of various tiff tags
- Changed enums
0.9.7
- Added possibility to stop decoding that runs in separate thread
- Fixed crashing when decoding images with bad metadata
0.9.6.2
- Added support for TIFFTAG_XRESOLUTION, TIFFTAG_YRESOLUTION, TIFFTAG_RESOLUTIONUNIT
0.9.6
- Added support for CCITT Group 3 and CCITT Group 4 compression schemes
0.9.5.1
- Fixed decoding algorithm for stripped images
0.9.5
- Added algorithms for efficient memory usage
- Added switchers for throwing exceptions and using of tiff tag orientation
================================================
FILE: README.md
================================================
# Android-TiffBitmapFactory
TiffBitmapFactory is an Android library that allows opening and saving images in *.tif format (See [Wikipedia](https://en.wikipedia.org/wiki/Tagged_Image_File_Format)) on Android devices.
For decoding and encoding *.tif files it uses the native library [libtiff](https://github.com/dumganhar/libtiff). Also for images that compressed with jpeg compression scheme used [libjpeg9 for android](https://github.com/Suvitruf/libjpeg-version-9-android) (the IJG code). For converting from PNG to TIFF and from TIFF to PNG used library [libpng-android](https://github.com/julienr/libpng-android).
Just now it has possibility to open tif image as mutable bitmap, read count of directory in file, apply sample rate for bitmap decoding and choose directory to decode.
While saving there is available few(most popular) compression mods and some additiona fields that can be writen to file, like author or copyright.
Minimum Android API level 16
Supported architectures: all
### Installation
Just add to your gradle dependencies :
```
implementation 'io.github.beyka:Android-TiffBitmapFactory:0.9.9.1'
```
And do not forget to add WRITE_EXTERNAL_STORAGE permission to main project manifest
### Build from sources
To build native part of library use [Android-NDK-bundle](https://developer.android.com/tools/sdk/ndk/index.html).
{
public ApplicationTest() {
super(Application.class);
}
}
================================================
FILE: src/main/.gitignore
================================================
/obj/
================================================
FILE: src/main/AndroidManifest.xml
================================================
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/CompressionScheme.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 5.1.17.
*/
public enum CompressionScheme {
/**
* No compression
*/
NONE(1),
/**
* CCITT modified Huffman RLE
*/
CCITTRLE(2),
/**
* CCITT Group 3 fax encoding
*/
CCITTFAX3(3),
/**
* CCITT Group 4 fax encoding
*/
CCITTFAX4(4),
/**
* LZW
*/
LZW(5),
/**
* JPEG ('new-style' JPEG)
*/
JPEG(7),
PACKBITS(32773),
DEFLATE(32946),
ADOBE_DEFLATE(8),
/**
* All other compression schemes
*/
OTHER(0);
final int ordinal;
CompressionScheme(int ordinal) {
this.ordinal = ordinal;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/DecodeArea.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 10/24/17.
*/
/**
* Holder for points of decode area
*/
public class DecodeArea {
public int x;
public int y;
public int width;
public int height;
public DecodeArea(){}
public DecodeArea(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/FillOrder.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 4/16/17.
*/
public enum FillOrder {
/**
* Pixels with lower column values are stored in the higher-order bits of the byte.
*/
MSB2LSB(1),
/**
* Pixels with lower column values are stored in the lower-order bits of the byte.
*/
LSB2MSB(2);
final int ordinal;
FillOrder(int ordinal) {
this.ordinal = ordinal;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/IProgressListener.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 4/26/17.
*/
public interface IProgressListener {
public void reportProgress(long processedPixels, long totalPixels);
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/ImageFormat.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Supported image formats
*/
public enum ImageFormat {
UNKNOWN(0),
JPEG(1),
PNG(2),
TIFF(4),
BMP(5);
final int ordinal;
ImageFormat(int ordinal) {
this.ordinal = ordinal;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/Orientation.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 5.1.17.
*/
public enum Orientation {
TOP_LEFT(1),
TOP_RIGHT(2),
BOT_RIGHT(3),
BOT_LEFT(4),
LEFT_TOP(5),
RIGHT_TOP(6),
RIGHT_BOT(7),
LEFT_BOT(8),
UNAVAILABLE(0);
final int ordinal;
Orientation(int ordinal) {
this.ordinal = ordinal;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/Photometric.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 4/16/17.
*/
public enum Photometric {
/**
* WhiteIsZero. For bilevel and grayscale images: 0 is imaged as white.
*/
MINISWHITE(0),
/**
* BlackIsZero. For bilevel and grayscale images: 0 is imaged as black.
*/
MINISBLACK(1),
/**
* RGB value of (0,0,0) represents black, and (255,255,255) represents white, assuming 8-bit components. The components are stored in the indicated order: first Red, then Green, then Blue.
*/
RGB(2),
/**
* Palette color. In this model, a color is described with a single component. The value of the component is used as an index into the red, green and blue curves in the ColorMap field to retrieve an RGB triplet that defines the color. When PhotometricInterpretation=3 is used, ColorMap must be present and SamplesPerPixel must be 1.
*/
PALETTE(3),
/**
* Transparency Mask. This means that the image is used to define an irregularly shaped region of another image in the same TIFF file. SamplesPerPixel and BitsPerSample must be 1. PackBits compression is recommended. The 1-bits define the interior of the region; the 0-bits define the exterior of the region.
*/
MASK(4),
/**
* Seperated, usually CMYK.
*/
SEPARATED(5),
/**
* YCbCr
*/
YCBCR(6),
/**
* CIE L*a*b*
*/
CIELAB(8),
/**
* CIE L*a*b*, alternate encoding also known as ICC L*a*b*
*/
ICCLAB(9),
/**
* CIE L*a*b*, alternate encoding also known as ITU L*a*b*, defined in ITU-T Rec. T.42, used in the TIFF-F and TIFF-FX standard (RFC 2301). The Decode tag, if present, holds information about this particular CIE L*a*b* encoding.
*/
ITULAB(10),
/**
* LOGL
*/
LOGL(32844),
/**
* LOGLUV
*/
LOGLUV(32845),
/**
* Some unknown photometric
*/
OTHER(-1);
final int ordinal;
Photometric(int ordinal) {
this.ordinal = ordinal;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/PlanarConfig.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 4/16/17.
*/
public enum PlanarConfig {
CONTIG(1),
SEPARATE(2);
final int ordinal;
PlanarConfig(int ordinal) {
this.ordinal = ordinal;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/ResolutionUnit.java
================================================
package org.beyka.tiffbitmapfactory;
/**
* Created by beyka on 13.3.17.
*/
public enum ResolutionUnit {
NONE(1),
INCH(2),
CENTIMETER(3);
final int ordinal;
ResolutionUnit(int ordinal) {
this.ordinal = ordinal;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/TiffBitmapFactory.java
================================================
package org.beyka.tiffbitmapfactory;
import android.graphics.Bitmap;
import android.util.Log;
import org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException;
import org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException;
import org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException;
import java.io.File;
/**
* Created by alexeyba on 7/17/15.
*/
public class TiffBitmapFactory {
static {
System.loadLibrary("tiff");
System.loadLibrary("tifffactory");
}
public enum ImageConfig {
/**
* Each pixel is stored on 4 bytes. Each channel (RGB and alpha
* for translucency) is stored with 8 bits of precision (256
* possible values.)
*
* This configuration is very flexible and offers the best
* quality. It should be used whenever possible.
*/
ARGB_8888 (2),
/**
* Each pixel is stored on 2 bytes and only the RGB channels are
* encoded: red is stored with 5 bits of precision (32 possible
* values), green is stored with 6 bits of precision (64 possible
* values) and blue is stored with 5 bits of precision.
*
* This configuration can produce slight visual artifacts depending
* on the configuration of the source. For instance, without
* dithering, the result might show a greenish tint. To get better
* results dithering should be applied.
*
* This configuration may be useful when using opaque bitmaps
* that do not require high color fidelity.
*/
RGB_565 (4),
/**
* Each pixel is stored as a single translucency (alpha) channel.
* This is very useful to efficiently store masks for instance.
* No color information is stored.
* With this configuration, each pixel requires 1 byte of memory.
*/
ALPHA_8 (8);
final int ordinal;
ImageConfig(int ordinal) {
this.ordinal = ordinal;
}
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffBitmapFactory#decodeFileDescriptor(int)}.
*
* Decode file to bitmap with default options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param file - file to decode
* @return The decoded bitmap, or null if the image data could not be
* decoded
*
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when for decoding of image system need more memory than {@link Options#inAvailableMemory} or default value
*/
public static Bitmap decodeFile(File file) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
return decodeFile(file, new Options(), null);
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffBitmapFactory#decodeFileDescriptor(int, Options)}.
*
* Decode file to bitmap with specified options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param file - file to decode
* @param options - options for decoding
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if options is non-null, if options requested only the
* size be returned (in {@link Options#outWidth}, {@link Options#outHeight}, {@link Options#outDirectoryCount})
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when {@link Options#inAvailableMemory} not enought to decode image
*/
public static Bitmap decodeFile(File file, Options options) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
return decodeFile(file, options, null);
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffBitmapFactory#decodeFileDescriptor(int, Options, IProgressListener)}.
*
* Decode file to bitmap with specified options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param file - file to decode
* @param options - options for decoding
* @param listener - listener which will receive decoding progress
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if options is non-null, if options requested only the
* size be returned (in {@link Options#outWidth}, {@link Options#outHeight}, {@link Options#outDirectoryCount})
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when {@link Options#inAvailableMemory} not enought to decode image
*/
public static Bitmap decodeFile(File file, Options options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
long time = System.currentTimeMillis();
Log.i("THREAD", "Starting decode " + file.getAbsolutePath());
Bitmap mbp = nativeDecodePath(file.getAbsolutePath(), options, listener);
Log.w("THREAD", "elapsed ms: " + (System.currentTimeMillis() - time) + " for " + file.getAbsolutePath());
return mbp;
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffBitmapFactory#decodeFileDescriptor(int)}.
*
* Decode path to bitmap with default options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param path - file to decode
* @return The decoded bitmap, or null if the image data could not be
* decoded
*
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when for decoding of image system need more memory than {@link Options#inAvailableMemory} or default value
*/
public static Bitmap decodePath(String path) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
return decodePath(path, new Options(), null);
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffBitmapFactory#decodeFileDescriptor(int, Options)}.
*
* Decode path to bitmap with specified options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param path - file to decode
* @param options - options for decoding
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if options is non-null, if options requested only the
* size be returned (in {@link Options#outWidth}, {@link Options#outHeight}, {@link Options#outDirectoryCount})
*
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when for decoding of image system need more memory than {@link Options#inAvailableMemory} or default value
*/
public static Bitmap decodePath(String path, Options options) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
return decodePath(path, options);
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffBitmapFactory#decodeFileDescriptor(int, Options, IProgressListener)}.
*
* Decode path to bitmap with specified options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param path - file to decode
* @param options - options for decoding
* @param listener - listener which will receive decoding progress
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if options is non-null, if options requested only the
* size be returned (in {@link Options#outWidth}, {@link Options#outHeight}, {@link Options#outDirectoryCount})
*
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when for decoding of image system need more memory than {@link Options#inAvailableMemory} or default value
*/
public static Bitmap decodePath(String path, Options options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
long time = System.currentTimeMillis();
Log.i("THREAD", "Starting decode " + path);
Bitmap mbp = nativeDecodePath(path, options, listener);
Log.w("THREAD", "elapsed ms: " + (System.currentTimeMillis() - time) + " for " + path);
return mbp;
}
/**
* Decode file descriptor to bitmap with specified options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param fileDescriptor - file descriptor that represent file to decode
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if options is non-null, if options requested only the
* size be returned (in {@link Options#outWidth}, {@link Options#outHeight}, {@link Options#outDirectoryCount})
*
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when for decoding of image system need more memory than {@link Options#inAvailableMemory} or default value
*/
public static Bitmap decodeFileDescriptor(int fileDescriptor) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
return decodeFileDescriptor(fileDescriptor, new Options(), null);
}
/**
* Decode file descriptor to bitmap with specified options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param fileDescriptor - file descriptor that represent file to decode
* @param options - options for decoding
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if options is non-null, if options requested only the
* size be returned (in {@link Options#outWidth}, {@link Options#outHeight}, {@link Options#outDirectoryCount})
*
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when for decoding of image system need more memory than {@link Options#inAvailableMemory} or default value
*/
public static Bitmap decodeFileDescriptor(int fileDescriptor, Options options) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
return decodeFileDescriptor(fileDescriptor, options, null);
}
/**
* Decode file descriptor to bitmap with specified options. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
* @param fileDescriptor - file descriptor that represent file to decode
* @param options - options for decoding
* @param listener - listener which will receive decoding progress
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if options is non-null, if options requested only the
* size be returned (in {@link Options#outWidth}, {@link Options#outHeight}, {@link Options#outDirectoryCount})
*
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while decoding image
* @throws org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException when {@code file} not exist or {@code file} is not tiff image
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when for decoding of image system need more memory than {@link Options#inAvailableMemory} or default value
*/
public static Bitmap decodeFileDescriptor(int fileDescriptor, Options options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
long time = System.currentTimeMillis();
Log.i("THREAD", "Starting decode descriptor " + fileDescriptor);
Bitmap mbp = nativeDecodeFD(fileDescriptor, options, listener);
Log.w("THREAD", "elapsed ms: " + (System.currentTimeMillis() - time) + " for descriptor " + fileDescriptor);
return mbp;
}
private static native Bitmap nativeDecodePath(String path, Options options, IProgressListener listener);
private static native Bitmap nativeDecodeFD(int fd, Options options, IProgressListener listener);
/**
* Close detached file descriptor
* @param fd
*/
public static native void closeFd(int fd);
/**
* Options class to specify decoding parameterMs
*/
public static final class Options {
/**
* Create a default Options object, which if left unchanged will give
* the same result from the decoder as if null were passed.
*/
public Options() {
isStoped = false;
inThrowException = false;
inUseOrientationTag = false;
inSwapRedBlueColors = false;
inJustDecodeBounds = false;
inSampleSize = 1;
inDirectoryNumber = 0;
inAvailableMemory = 8000*8000*4;
outWidth = -1;
outHeight = -1;
outDirectoryCount = -1;
outImageOrientation = Orientation.UNAVAILABLE;
}
/**
* Uses for stoping of native thread
* @deprecated As of release 0.9.8.4, replaced by {@link Thread#interrupt()}
*/
private volatile boolean isStoped;
/**
* Stop native decoding thread
* If decoding is started in any thread except main, calling of this method will cause force stop of decoding and returning of null object.
* @deprecated As of release 0.9.8.4, replaced by {@link Thread#interrupt()}
*/
public void stop() {
isStoped = true;
}
/**
* If set to true decoder will rotate and flip image according to TIFFTAG_ORIENTATION.
* Otherwise image will be returned as it decoded.
* The specification considers this a baseline tag, but does add that support for orientations other than 1 is not a Baseline TIFF requirement.
* So for almost all cases this variable may be false.
* Default value is false
*/
public boolean inUseOrientationTag;
/**
* If set to true, decoder will throw exceptions if some errors appeared while decoding.
* Otherwise decoder will just return null.
* Default value is false
*/
public boolean inThrowException;
/**
* If set to true, the decoder will swap red and blue colors.
* Note: If you use this option then your image has wrong encoding
* Default value is false
*/
public boolean inSwapRedBlueColors;
/**
* If set to true, the decoder will return null (no bitmap), but
* the out... fields will still be set, allowing the caller to query
* the bitmap without having to allocate the memory for its pixels.
*/
public boolean inJustDecodeBounds;
/**
* If set to a value > 1, requests the decoder to subsample the original
* image, returning a smaller image to save memory. The sample size is
* the number of pixels in either dimension that correspond to a single
* pixel in the decoded bitmap. For example, inSampleSize == 4 returns
* an image that is 1/4 the width/height of the original, and 1/16 the
* number of pixels. Any value <= 1 is treated the same as 1. Note: the
* decoder uses a final value based on powers of 2, any other value will
* be rounded down to the nearest power of 2.
*/
public int inSampleSize;
/**
* Set directory to extract from image. Default value is 0.
* To get number of directories in file see {@link #outDirectoryCount}
*/
public int inDirectoryNumber;
/**
* Number of bytes that may be allocated during the Tiff file operations.
* -1 means memory is unlimited.
* Default value is 244Mb
*/
public long inAvailableMemory;
/**
* If this is non-null, the decoder will try to decode into this
* internal configuration. If it is null, or the request cannot be met,
* the decoder will use {@link ImageConfig#ARGB_8888} configuration.
*
* Numeration starts with 0
*
* Image are loaded with the {@link ImageConfig#ARGB_8888} config by
* default.
*
* In current version supported are {@link ImageConfig#ARGB_8888}, {@link ImageConfig#ALPHA_8} and {@link ImageConfig#RGB_565}
*/
public ImageConfig inPreferredConfig = ImageConfig.ARGB_8888;
/**
* If this field is non-null - Decoder will decode and return only area specified in {@link DecodeArea} object
* For decoding not full bitmap, but only part of it - create new {@link DecodeArea} object and specify:
* {@link DecodeArea#x x}, {@link DecodeArea#y y} - left top corner of decoding area
* {@link DecodeArea#width width} - width of decoding area
* {@link DecodeArea#height height} - height of decoding area
*/
public DecodeArea inDecodeArea;
/**
* The resulting width of the bitmap. If {@link #inJustDecodeBounds} is
* set to false, this will be width of the output bitmap after any
* scaling is applied. If true, it will be the width of the input image
* without any accounting for scaling.
*
* outWidth will be set to -1 if there is an error trying to decode.
*/
public int outWidth;
/**
* The resulting height of the bitmap. If {@link #inJustDecodeBounds} is
* set to false, this will be height of the output bitmap after any
* scaling is applied. If true, it will be the height of the input image
* without any accounting for scaling.
*
* outHeight will be set to -1 if there is an error trying to decode.
*/
public int outHeight;
/**
* The number of current directory.
* curDirectoryNumber will be set to -1 if there is an error trying to decode.
*/
public int outCurDirectoryNumber;
/**
* The count of directory in image file.
* outDirectoryCount will be set to -1 if there is an error trying to decode.
*/
public int outDirectoryCount;
/**
* This parameter returns orientation of decoded image
* For storing orientation uses {@link org.beyka.tiffbitmapfactory.Orientation ImageOrientation} enum
* If image wasn't decoded successful this parameter will be equal to {@link Orientation#UNAVAILABLE}
* This parameter is link to TIFFTAG_ORIENTATION tag
*/
public Orientation outImageOrientation;
/**
* This parameter returns compression scheme of decoded image
* For storing compression mode uses {@link CompressionScheme CompressionScheme} enum
* This parameter is link to TIFFTAG_COMPRESSION tag
*/
public CompressionScheme outCompressionScheme;
/**
* How the components of each pixel are stored.
* The specification defines these values:
*
* - 1 = Chunky format. The component values for each pixel are stored contiguously. For example, for RGB data, the data is stored as RGBRGBRGB
* - 2 = Planar format. The components are stored in separate component planes. For example, RGB data is stored with the Red components in one component plane, the Green in another, and the Blue in another.
*
* This parameter is link to TIFFTAG_PLANARCONFIG tag
*/
public PlanarConfig outPlanarConfig;
/**
* The number of components per pixel.
* SamplesPerPixel is usually 1 for bilevel, grayscale, and palette-color images. SamplesPerPixel is usually 3 for RGB images. If this value is higher, ExtraSamples should give an indication of the meaning of the additional channels.
*/
public int outSamplePerPixel;
/**
* Number of bits per component.
*/
public int outBitsPerSample;
/**
* The number of pixels per {@link org.beyka.tiffbitmapfactory.TiffBitmapFactory.Options#outResolutionUnit} in the ImageWidth direction.
*/
public float outXResolution;
/**
* The number of pixels per {@link org.beyka.tiffbitmapfactory.TiffBitmapFactory.Options#outResolutionUnit} in the ImageHeight direction.
*/
public float outYResolution;
/**
* The unit of measurement for XResolution and YResolution.
* The specification defines these values:
*
* - RESUNIT_NONE
* - RESUNIT_INCH
* - RESUNIT_CENTIMETER
*
* This parameter is link to TIFFTAG_RESOLUTIONUNIT tag
*/
public ResolutionUnit outResolutionUnit;
/**
* The tile width in pixels. This is the number of columns in each tile.
*/
public int outTileWidth;
/**
* The tile height in pixels. This is the number of rows in each tile.
*/
public int outTileHeight;
/**
* The number of rows per strip.
* RowsPerStrip and ImageLength together tell us the number of strips in the entire image.
*/
public int outRowPerStrip;
/**
* Size for a strip of data in bytes.
*/
public int outStripSize;
/**
* Number of strips in the image.
*/
public int outNumberOfStrips;
/**
* The color space of the image data.
* This parameter is link to TIFFTAG_PHOTOMETRIC tag
*/
public Photometric outPhotometric;
/**
* The logical order of bits within a byte.
* The specification defines these values:
*
* - 1 = Pixels with lower column values are stored in the higher-order bits of the byte.
* - 2 = Pixels with lower column values are stored in the lower-order bits of the byte.
*
* This parameter is link to TIFFTAG_PLANARCONFIG tag
*/
public FillOrder outFillOrder;
/**
* Author of file.
* This parameter is link to TIFFTAG_ARTIST tag
*/
public String outAuthor = "";
/**
* Copyright of file
* This parameter is link to TIFFTAG_COPYRIGHT tag
*/
public String outCopyright = "";
/**
* A string that describes the subject of the image.
* This parameter is link to TIFFTAG_IMAGEDESCRIPTION tag
*/
public String outImageDescription = "";
/**
* Name and version number of the software package(s) used to create the image.
* This parameter is link to TIFFTAG_SOFTWARE tag
*/
public String outSoftware = "";
/**
* Date and time of image creation. The format is: "YYYY:MM:DD HH:MM:SS", with hours like those on a 24-hour clock.
* This parameter is link to TIFFTAG_DATETIME tag
*/
public String outDatetime = "";
/**
* The computer and/or operating system in use at the time of image creation.
* This parameter is link to TIFFTAG_HOSTCOMPUTER tag
*/
public String outHostComputer = "";
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/TiffConverter.java
================================================
package org.beyka.tiffbitmapfactory;
import org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException;
import org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException;
import org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException;
import java.io.File;
/**
* Created by beyka on 5/9/17.
*/
public class TiffConverter {
static {
System.loadLibrary("tiff");
System.loadLibrary("tiffconverter");
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertToTiff(int, int, ConverterOptions, IProgressListener)}.
*
* Convert any of supported formats from {@link ImageFormat} to tiff
* @param inFile path to income tiff file
* @param outFile path to outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
*
* @return true if convert process have been successful
*/
public static boolean convertToTiff(File inFile, File outFile, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
return convertToTiff(inFile.getAbsolutePath(), outFile.getAbsolutePath(), options, listener);
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertToTiff(int, int, ConverterOptions, IProgressListener)}.
*
* Convert any of supported formats from {@link ImageFormat} to tiff
* @param inPath path to income tiff file
* @param outPath path to outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
*
* @return true if convert process have been successful
*/
public static boolean convertToTiff(String inPath, String outPath, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
switch (getImageType(inPath)) {
case JPEG:
return convertJpgTiff(inPath, outPath, options, listener);
case PNG:
return convertPngTiff(inPath, outPath, options, listener);
case BMP:
return convertBmpTiff(inPath, outPath, options, listener);
case TIFF:
// TODO: 9/19/17 make convert tiff to tiff method
break;
}
return false;
}
/**
* Convert any of supported formats from {@link ImageFormat} to tiff
* This method don't close file descriptor
* @param inFd file descriptor that represent income file
* @param outFd file descriptor that represent outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
*
* @return true if convert process have been successful
*/
public static boolean convertToTiff(int inFd, int outFd, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException {
switch (getImageTypeFd(inFd)) {
case JPEG:
return convertJpgTiffFd(inFd, outFd, options, listener);
case PNG:
return convertPngTiffFd(inFd, outFd, options, listener);
case BMP:
return convertBmpTiffFd(inFd, outFd, options, listener);
case TIFF:
// TODO: 9/19/17 make convert tiff to tiff method
break;
}
return false;
}
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertTiffPngFd(int, int, ConverterOptions, IProgressListener)}.
*
* Convert tiff to png file. Uses direct data read method, that decrease memory usage
* @param tiff path to income tiff file
* @param png path to outcome png file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertTiffPng(String tiff, String png, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* Convert tiff to png file. Uses direct data read method, that decrease memory usage
* @param tiff file descriptor that represent income tiff file
* @param png file descriptor that represent outcome png file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertTiffPngFd(int tiff, int png, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertPngTiffFd(int, int, ConverterOptions, IProgressListener)}.
*
* Convert png to tiff file. Uses direct data read method, that decrease memory usage.
* @param png path to income png file
* @param tiff path to outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertPngTiff(String png, String tiff, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* Convert png to tiff file. Uses direct data read method, that decrease memory usage.
* This method don't close file descriptor
* @param png file descriptor that represent income png file
* @param tiff file descriptor that represent outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertPngTiffFd(int png, int tiff, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertTiffJpgFd(int, int, ConverterOptions, IProgressListener)}.
*
* Convert tiff to jpeg file. Uses direct data read method, that decrease memory usage
* @param tiff path to income tiff file
* @param jpg path to outcome jpeg file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertTiffJpg(String tiff, String jpg, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* Convert tiff to jpg file. Uses direct data read method, that decrease memory usage
* @param tiff file descriptor that represent income tiff file
* @param jpg file descriptor that represent outcome jpg file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertTiffJpgFd(int tiff, int jpg, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertJpgTiffFd(int, int, ConverterOptions, IProgressListener)}.
*
* Convert jpeg to tiff file. Uses direct data read method, that decrease memory usage.
* @param jpg path to income jpeg file
* @param tiff path to outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertJpgTiff(String jpg, String tiff, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* Convert jpeg to tiff file. Uses direct data read method, that decrease memory usage.
* This method don't close file descriptor
* @param jpg file descriptor that represent income jpeg file
* @param tiff file descriptor that represent outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertJpgTiffFd(int jpg, int tiff, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertTiffBmpFd(int, int, ConverterOptions, IProgressListener)}.
*
* Convert tiff to bmp file. Uses direct data read method, that decrease memory usage
* @param tiff path to income tiff file
* @param bmp path to outcome jpeg file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertTiffBmp(String tiff, String bmp, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* Convert tiff to bmp file. Uses direct data read method, that decrease memory usage
* @param tiff file descriptor that represent income tiff file
* @param bmp file descriptor that represent outcome bmp file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertTiffBmpFd(int tiff, int bmp, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#convertBmpTiffFd(int, int, ConverterOptions, IProgressListener)}.
*
* Convert bmp to tiff file. Uses direct data read method, that decrease memory usage.
* @param bmp path to income bmp file
* @param tiff path to outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertBmpTiff(String bmp, String tiff, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* Convert bmp to tiff file. Uses direct data read method, that decrease memory usage.
* This method don't close file descriptor
* @param bmp file descriptor that represent income bmp file
* @param tiff file descriptor that represent outcome tiff file
* @param options converter options
* @param listener listener which will receive converting progress
* @return true if convert process have been successful
*/
public static native boolean convertBmpTiffFd(int bmp, int tiff, ConverterOptions options, IProgressListener listener) throws CantOpenFileException, DecodeTiffException, NotEnoughtMemoryException;
/**
* @deprecated Since Android Q is released. You can use this method with scoped storage.
* Otherwise use {@link TiffConverter#getImageTypeFd(int)}.
*
* Return type of file.
* @param path - file path
* @return one of {@link ImageFormat} or {@link ImageFormat#UNKNOWN}
*/
public static native ImageFormat getImageType(String path);
/**
* Return type of file. This method don't close file descriptor
* @param fd - file descriptor for file
* @return one of {@link ImageFormat} or {@link ImageFormat#UNKNOWN}
*/
public static native ImageFormat getImageTypeFd(int fd);
/**
* Close detached file descriptor
* @param fd
*/
public static native void closeFd(int fd);
public static final class ConverterOptions {
public ConverterOptions() {
availableMemory = 8000*8000*4;
appendTiff = false;
resUnit = ResolutionUnit.NONE;
compressionScheme = CompressionScheme.NONE;
//orientation = Orientation.TOP_LEFT;
throwExceptions = false;
isStoped = false;
}
/**
* Uses for stoping of native thread
* @deprecated As of release 0.9.8.4, replaced by {@link Thread#interrupt()}
*/
private volatile boolean isStoped;
/**
* Stop native convert thread
* If converting is started in any thread except main, calling of this method will cause force stop of converting and returning of false.
* @deprecated As of release 0.9.8.4, replaced by {@link Thread#interrupt()}
*/
public void stop() {
isStoped = true;
}
/**
* Number of bytes that may be allocated during the file operations.
* -1 means memory is unlimited.
* Default value is 244Mb
*/
public long availableMemory;
/**
* If set to true, converter will throw exceptions if some errors appeared while converting.
* Otherwise converter will just return false.
* Default value is false
*/
public boolean throwExceptions;
/**
* For converting from TIFF to ANY cases
* Tiff directory that should be converted
*/
public int readTiffDirectory;
/**
* For converting from ANY to TIFF cases
* If this value set to true while converting any to tiff - new tiff directory will be created
* and added to existed tiff file.
* Otherwise file will be overwritten.
* Default value is false
*/
public boolean appendTiff;
/**
* For converting from ANY to TIFF cases
* Compression scheme used on the image data.
* Default value is {@link CompressionScheme#NONE COMPRESSION_NONE}
* This parameter is link to TIFFTAG_COMPRESSION tag
*/
public CompressionScheme compressionScheme;
/**
* For converting from ANY to TIFF cases
* {@link org.beyka.tiffbitmapfactory.Orientation Orientation} that will used for saving image
* By default uses {@link org.beyka.tiffbitmapfactory.Orientation#TOP_LEFT ORIENTATION_TOPLEFT}
* This parameter is link to TIFFTAG_ORIENTATION tag
*/
//public Orientation orientation;
/**
* If this field is non-null - Converter will use only area specified in {@link DecodeArea} object to convert.
* This field works only when convert from TIFF.
* For decoding not full bitmap, but only part of it - create new {@link DecodeArea} object and specify:
* {@link DecodeArea#x x}, {@link DecodeArea#y y} - left top corner of decoding area
* {@link DecodeArea#width width} - width of decoding area
* {@link DecodeArea#height height} - height of decoding area
*/
public DecodeArea inTiffDecodeArea;
/**
* For converting from ANY to TIFF cases
* The number of pixels per {@link org.beyka.tiffbitmapfactory.TiffConverter.ConverterOptions#resUnit} in the ImageWidth direction.
* It is not mandatory that the image be actually displayed or printed at the size implied by this parameter.
* It is up to the application to use this information as it wishes.
* Defualt value is 0
*/
public float xResolution;
/**
* For converting from ANY to TIFF cases
* The number of pixels per {@link org.beyka.tiffbitmapfactory.TiffConverter.ConverterOptions#resUnit} in the ImageHeight direction.
* It is not mandatory that the image be actually displayed or printed at the size implied by this parameter.
* It is up to the application to use this information as it wishes.
* Defualt value is 0
*/
public float yResolution;
/**
* For converting from ANY to TIFF cases
* The unit of measurement for XResolution and YResolution.
* To be used with xResolution and yResolution.
* The specification defines these values:
*
* - RESUNIT_NONE
* - RESUNIT_INCH
* - RESUNIT_CENTIMETER
*
* Default value is {@link org.beyka.tiffbitmapfactory.ResolutionUnit#NONE}
*/
public ResolutionUnit resUnit;
/**
* For converting from ANY to TIFF cases
* A string that describes the subject of the image.
* This parameter is link to TIFFTAG_IMAGEDESCRIPTION tag
*/
public String imageDescription;
/**
* For converting from ANY to TIFF cases
* Software that used for creating of image.
* This parameter is link to TIFFTAG_SOFTWARE tag
*/
public String software;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/TiffSaver.java
================================================
package org.beyka.tiffbitmapfactory;
import android.graphics.Bitmap;
import org.beyka.tiffbitmapfactory.exceptions.CantOpenFileException;
import org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException;
import java.io.File;
/**
* Created by beyka on 18.2.16.
*/
public class TiffSaver {
static {
System.loadLibrary("tiff");
System.loadLibrary("tiffsaver");
}
/**
* Save bitmap to file with default {@link TiffSaver.SaveOptions options}.
*
* @param destination - file to write bitmap
* @param bmp - Bitmap for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destination} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean saveBitmap(File destination, Bitmap bmp) throws CantOpenFileException, NotEnoughtMemoryException {
return saveBitmap(destination.getAbsolutePath(), bmp, new SaveOptions());
}
/**
* Save bitmap to file.
*
* @param destination - file to write bitmap
* @param bmp - Bitmap for saving
* @param options - options for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destinationPath} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean saveBitmap(File destination, Bitmap bmp, SaveOptions options) throws CantOpenFileException {
return saveBitmap(destination.getAbsolutePath(), bmp, options);
}
/**
* Save bitmap to file with default {@link TiffSaver.SaveOptions options}.
*
* @param destinationPath - file path to write bitmap
* @param bmp - Bitmap for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destinationPath} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean saveBitmap(String destinationPath, Bitmap bmp) throws CantOpenFileException {
return saveBitmap(destinationPath, bmp, new SaveOptions());
}
/**
* Save bitmap to file.
*
* @param destinationPath - file path to write bitmap
* @param bmp - Bitmap for saving
* @param options - options for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destinationPath} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean saveBitmap(String destinationPath, Bitmap bmp, SaveOptions options) throws CantOpenFileException {
// int pixels[] = new int[bmp.getWidth() * bmp.getHeight()];
// bmp.getPixels(pixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
return save(destinationPath, -1, bmp, options, false);
}
/**
* Append bitmap to the end of existing file or create new file with default {@link TiffSaver.SaveOptions options}.
*
* @param destination - file to write bitmap
* @param bmp - Bitmap for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destination} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean appendBitmap(File destination, Bitmap bmp) throws CantOpenFileException, NotEnoughtMemoryException {
return appendBitmap(destination.getAbsolutePath(), bmp, new SaveOptions());
}
/**
* append bitmap to the end of existing file or create new file.
*
* @param destination - file to write bitmap
* @param bmp - Bitmap for saving
* @param options - options for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destinationPath} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean appendBitmap(File destination, Bitmap bmp, SaveOptions options) throws CantOpenFileException {
return appendBitmap(destination.getAbsolutePath(), bmp, options);
}
/**
* append bitmap to the end of existing file or create new file with default {@link TiffSaver.SaveOptions options}.
*
* @param destinationPath - file path to write bitmap
* @param bmp - Bitmap for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destinationPath} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean appendBitmap(String destinationPath, int page, Bitmap bmp) throws CantOpenFileException {
return appendBitmap(destinationPath, bmp, new SaveOptions());
}
/**
* append bitmap to the end of existing file or create new file.
*
* @param destinationPath - file path to write bitmap
* @param bmp - Bitmap for saving
* @param options - options for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destinationPath} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean appendBitmap(String destinationPath, Bitmap bmp,SaveOptions options) throws CantOpenFileException {
// int pixels[] = new int[bmp.getWidth() * bmp.getHeight()];
// bmp.getPixels(pixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
return save(destinationPath, -1, bmp, options, true);
}
/**
* Save bitmap to file with default {@link TiffSaver.SaveOptions options}.
*
* @param fileDescriptor - file descriptor that represent file to write bitmap
* @param bmp - Bitmap for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destination} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean saveBitmap(int fileDescriptor, Bitmap bmp) throws CantOpenFileException, NotEnoughtMemoryException {
return saveBitmap(fileDescriptor, bmp, new SaveOptions());
}
/**
* Save bitmap to file with default {@link TiffSaver.SaveOptions options}.
*
* @param fileDescriptor - file descriptor that represent file to write bitmap
* @param bmp - Bitmap for saving
* @param options - options for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destination} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean saveBitmap(int fileDescriptor, Bitmap bmp, SaveOptions options) throws CantOpenFileException, NotEnoughtMemoryException {
return save(null, fileDescriptor, bmp, options, false);
}
/**
* Save bitmap to file with default {@link TiffSaver.SaveOptions options}.
*
* @param fileDescriptor - file descriptor that represent file to write bitmap
* @param bmp - Bitmap for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destination} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean appendBitmap(int fileDescriptor, Bitmap bmp) throws CantOpenFileException, NotEnoughtMemoryException {
return appendBitmap(fileDescriptor, bmp, new SaveOptions());
}
/**
* Save bitmap to file with default {@link TiffSaver.SaveOptions options}.
*
* @param fileDescriptor - file descriptor that represent file to write bitmap
* @param bmp - Bitmap for saving
* @param options - options for saving
* @return true if bitmap was saved successful or false otherwise
* @throws CantOpenFileException when {@code destination} not exist or can't be opened for writing
* @throws org.beyka.tiffbitmapfactory.exceptions.NotEnoughtMemoryException when there is no avalable memory for processing bitmap
* @throws org.beyka.tiffbitmapfactory.exceptions.DecodeTiffException when error occure while saving image
*/
public static boolean appendBitmap(int fileDescriptor, Bitmap bmp, SaveOptions options) throws CantOpenFileException, NotEnoughtMemoryException {
return save(null, fileDescriptor, bmp, options, true);
}
private static synchronized native boolean save(String filePath, int fileDescriptor, Bitmap bmp, SaveOptions options, boolean append);
/**
* Close detached file descriptor
* @param fd
*/
public static native void closeFd(int fd);
/**
* Options class to specify saving parameters
*/
public static final class SaveOptions {
public SaveOptions() {
inAvailableMemory = 8000*8000*4;
inThrowException = false;
compressionScheme = CompressionScheme.NONE;
orientation = Orientation.TOP_LEFT;
xResolution = 0;
yResolution = 0;
resUnit = ResolutionUnit.NONE;
}
/**
* Number of bytes that may be allocated during the Tiff file operations.
* -1 means memory is unlimited.
* Default value is 244Mb
*/
public long inAvailableMemory;
/**
* If set to true, saver will throw exceptions if some errors appeared while writing tiff.
* Otherwise saver will just return false.
* Default value is false
*/
public boolean inThrowException;
/**
* Compression scheme used on the image data.
* Default value is {@link CompressionScheme#NONE COMPRESSION_NONE}
* This parameter is link to TIFFTAG_COMPRESSION tag
*/
public CompressionScheme compressionScheme;
/**
* {@link org.beyka.tiffbitmapfactory.Orientation Orientation} that will used for saving image
* By default uses {@link org.beyka.tiffbitmapfactory.Orientation#TOP_LEFT ORIENTATION_TOPLEFT}
* This parameter is link to TIFFTAG_ORIENTATION tag
*/
public Orientation orientation;
/**
* The number of pixels per {@link org.beyka.tiffbitmapfactory.TiffSaver.SaveOptions#resUnit} in the ImageWidth direction.
* It is not mandatory that the image be actually displayed or printed at the size implied by this parameter.
* It is up to the application to use this information as it wishes.
* Defualt value is 0
*/
public float xResolution;
/**
* The number of pixels per {@link org.beyka.tiffbitmapfactory.TiffSaver.SaveOptions#resUnit} in the ImageHeight direction.
* It is not mandatory that the image be actually displayed or printed at the size implied by this parameter.
* It is up to the application to use this information as it wishes.
* Defualt value is 0
*/
public float yResolution;
/**
* The unit of measurement for XResolution and YResolution.
* To be used with xResolution and yResolution.
* The specification defines these values:
*
* - RESUNIT_NONE
* - RESUNIT_INCH
* - RESUNIT_CENTIMETER
*
* Default value is {@link org.beyka.tiffbitmapfactory.ResolutionUnit#NONE}
*/
public ResolutionUnit resUnit;
/**
* Author for writing to file.
* This parameter is link to TIFFTAG_ARTIST tag
*/
public String author;
/**
* Copyright for writing to file
* This parameter is link to TIFFTAG_COPYRIGHT tag
*/
public String copyright;
/**
* A string that describes the subject of the image.
* This parameter is link to TIFFTAG_IMAGEDESCRIPTION tag
*/
public String imageDescription;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/exceptions/CantOpenFileException.java
================================================
package org.beyka.tiffbitmapfactory.exceptions;
/**
* Created by alexeyba on 09.11.15.
*/
public class CantOpenFileException extends RuntimeException {
private String fileName;
private int fileDescriptor = -1;
public CantOpenFileException(String fileName){
super("Can\'t open file " + fileName);
this.fileName = fileName;
}
public CantOpenFileException(int fileDescriptor){
super("Can\'t open file with file descriptor " + fileDescriptor);
this.fileDescriptor = fileDescriptor;
}
public String getFileName(){
return fileName;
}
public int getFileDescriptor() {
return fileDescriptor;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/exceptions/DecodeTiffException.java
================================================
package org.beyka.tiffbitmapfactory.exceptions;
/**
* Created by alexeyba on 09.11.15.
*/
public class DecodeTiffException extends RuntimeException {
private String fileName;
private String aditionalInfo;
private int fileDescriptor = -1;
public DecodeTiffException(String fileName){
super("Could not decode tiff file " + fileName);
this.fileName = fileName;
}
public DecodeTiffException(int fileDescriptor) {
super("Could not decode tiff file with file descriptor " + fileDescriptor);
this.fileDescriptor = fileDescriptor;
}
public DecodeTiffException(String fileName, String aditionaInfo){
super("Could not decode tiff file " + fileName + "\n" + aditionaInfo);
this.fileName = fileName;
this.aditionalInfo = aditionaInfo;
}
public DecodeTiffException(int fileDescriptor, String aditionaInfo){
super("Could not decode tiff file with file descriptor" + fileDescriptor + "\n" + aditionaInfo);
this.fileDescriptor = fileDescriptor;
this.aditionalInfo = aditionaInfo;
}
public String getFileName(){
return fileName;
}
public String getAditionalInfo() {
return aditionalInfo;
}
public int getFileDescriptor() {
return fileDescriptor;
}
}
================================================
FILE: src/main/java/org/beyka/tiffbitmapfactory/exceptions/NotEnoughtMemoryException.java
================================================
package org.beyka.tiffbitmapfactory.exceptions;
/**
* Created by alexeyba on 09.11.15.
*/
public class NotEnoughtMemoryException extends RuntimeException {
private int availableMemory;
private int needMemory;
public NotEnoughtMemoryException(int availableMemory, int needMemory){
super("Available memory is not enought to decode image. Available " + availableMemory + " bytes. Need " + needMemory + " bytes.");
this.availableMemory = availableMemory;
this.needMemory = needMemory;
}
public int getAvailableMemory() {
return availableMemory;
}
public int getNeedMemory() {
return needMemory;
}
}
================================================
FILE: src/main/jni/Android.mk
================================================
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_TIFF_SRC_FILES := \
tiff/libtiff/tif_dirread.c \
tiff/libtiff/tif_zip.c \
tiff/libtiff/tif_flush.c \
tiff/libtiff/tif_next.c \
tiff/libtiff/tif_ojpeg.c \
tiff/libtiff/tif_dirwrite.c \
tiff/libtiff/tif_dirinfo.c \
tiff/libtiff/tif_dir.c \
tiff/libtiff/tif_compress.c \
tiff/libtiff/tif_close.c \
tiff/libtiff/tif_tile.c \
tiff/libtiff/tif_open.c \
tiff/libtiff/tif_getimage.c \
tiff/libtiff/tif_pixarlog.c \
tiff/libtiff/tif_warning.c \
tiff/libtiff/tif_dumpmode.c \
tiff/libtiff/tif_jpeg.c \
tiff/libtiff/tif_jbig.c \
tiff/libtiff/tif_predict.c \
tiff/libtiff/mkg3states.c \
tiff/libtiff/tif_write.c \
tiff/libtiff/tif_error.c \
tiff/libtiff/tif_version.c \
tiff/libtiff/tif_print.c \
tiff/libtiff/tif_color.c \
tiff/libtiff/tif_read.c \
tiff/libtiff/tif_extension.c \
tiff/libtiff/tif_thunder.c \
tiff/libtiff/tif_lzw.c \
tiff/libtiff/tif_fax3.c \
tiff/libtiff/tif_luv.c \
tiff/libtiff/tif_codec.c \
tiff/libtiff/tif_unix.c \
tiff/libtiff/tif_packbits.c \
tiff/libtiff/tif_aux.c \
tiff/libtiff/tif_fax3sm.c \
tiff/libtiff/tif_swab.c \
tiff/libtiff/tif_strip.c
LOCAL_TIFF_SRC_FILES += tiff/port/lfind.c
#######################LIBTIFF#################################
LOCAL_SRC_FILES:= $(LOCAL_TIFF_SRC_FILES)
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/tiff/libtiff \
$(LOCAL_PATH)/jpeg
LOCAL_CFLAGS += -DAVOID_TABLES
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
LOCAL_MODULE:= libtiff
LOCAL_LDLIBS := -lz
LOCAL_LDLIBS += $(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libjpeg.a
include $(BUILD_SHARED_LIBRARY)
###############################################################
include $(CLEAR_VARS)
LOCAL_MODULE := libpng
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libpng.a
include $(PREBUILT_STATIC_LIBRARY)
###############################################################
include $(CLEAR_VARS)
LOCAL_MODULE := libjpeg
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libjpeg.a
include $(PREBUILT_STATIC_LIBRARY)
###############################################################
include $(CLEAR_VARS)
LOCAL_MODULE := tifffactory
LOCAL_CFLAGS := -DANDROID_NDK
LOCAL_SRC_FILES := \
NativeExceptions.cpp \
NativeTiffBitmapFactory.cpp \
NativeDecoder.cpp
LOCAL_LDLIBS := -ldl -llog -ljnigraphics
LOCAL_LDFLAGS +=-ljnigraphics
LOCAL_SHARED_LIBRARIES := tiff
include $(BUILD_SHARED_LIBRARY)
###############################################################
include $(CLEAR_VARS)
LOCAL_MODULE := tiffsaver
LOCAL_CFLAGS := -DANDROID_NDK
LOCAL_SRC_FILES := \
NativeExceptions.cpp \
NativeTiffSaver.cpp
LOCAL_LDLIBS := -ldl -llog -ljnigraphics
LOCAL_LDFLAGS +=-ljnigraphics
LOCAL_SHARED_LIBRARIES := tiff
include $(BUILD_SHARED_LIBRARY)
###############################################################
include $(CLEAR_VARS)
LOCAL_MODULE := tiffconverter
LOCAL_CFLAGS := -DANDROID_NDK
LOCAL_SRC_FILES := \
NativeExceptions.cpp \
NativeTiffConverter.cpp \
TiffToPngConverter.cpp \
TiffToJpgConverter.cpp \
BaseTiffConverter.cpp \
PngToTiffConverter.cpp \
JpgToTiffConverter.cpp \
BmpToTiffConverter.cpp \
TiffToBmpConverter.cpp \
BitmapReader.cpp
#LOCAL_C_INCLUDES := libs/$(TARGET_ARCH_ABI)/libpng.a
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/png \
$(LOCAL_PATH)/jpeg
LOCAL_LDLIBS := -lz -ldl -llog -ljnigraphics
LOCAL_LDFLAGS +=-ljnigraphics
LOCAL_STATIC_LIBRARIES := png
LOCAL_STATIC_LIBRARIES += jpeg
LOCAL_SHARED_LIBRARIES := tiff
include $(BUILD_SHARED_LIBRARY)
================================================
FILE: src/main/jni/Application.mk
================================================
APP_STL := c++_static
APP_MODULES := tiff png jpeg tifffactory tiffsaver tiffconverter
APP_PLATFORM=android-16
APP_ABI := arm64-v8a, armeabi-v7a
#APP_OPTIM := debug
================================================
FILE: src/main/jni/BMP.h
================================================
//
// Created by beyka on 9/21/17.
//
#ifndef __BMP_H_INCLUDED__ // if x.h hasn't been included yet...
#define __BMP_H_INCLUDED__
#pragma pack(2)
typedef struct BITMAPFILEHEADER
{
BITMAPFILEHEADER() : bfReserved1(0), bfReserved2(0) {}
unsigned char bfType[2];
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} BITMAPFILEHEADER;
typedef struct /**** BMP file info structure ****/
{
unsigned int biSize; /* Size of info header */
int biWidth; /* Width of image */
int biHeight; /* Height of image */
unsigned short biPlanes; /* Number of color planes */
unsigned short biBitCount; /* Number of bits per pixel */
unsigned int biCompression; /* Type of compression to use 0 - none, 1 - rle 8 bit, 2 - rle 4 but, 3 - bi_bitfields*/
unsigned int biSizeImage; /* Size of image data */
int biXPelsPerMeter; /* X pixels per meter */
int biYPelsPerMeter; /* Y pixels per meter */
unsigned int biClrUsed; /* Number of colors used */
unsigned int biClrImportant; /* Number of important colors */
unsigned int biPalete[3] ;
unsigned char reserved[56];
/* Palete (masks for 16 bit bmps)*/
/*a 5-5-5 16-bit image, where the blue mask is 0x001f, the green mask is 0x03e0, and the red mask is 0x7c00; and a 5-6-5 16-bit image, where the blue mask is 0x001f, the green mask is 0x07e0, and the red mask is 0xf800*/
} BITMAPINFOHEADER;
#pragma pack()
#endif
================================================
FILE: src/main/jni/BaseTiffConverter.cpp
================================================
//
// Created by beyka on 5/11/17.
//
#include "BaseTiffConverter.h"
BaseTiffConverter::BaseTiffConverter(JNIEnv *e, jclass clazz, jstring in, jstring out, jobject opts, jobject listener)
{
boundX = boundY = boundWidth = boundHeight = -1;
hasBounds = 0;
availableMemory = 8000 * 8000 * 4;
env = e;
inPath = in;
outPath = out;
optionsObj = opts;
this->listener = listener;
throwException = JNI_FALSE;
appendTiff = JNI_FALSE;
tiffDirectory = 0;
jIProgressListenerClass = env->FindClass("org/beyka/tiffbitmapfactory/IProgressListener");
jConvertOptionsClass = env->FindClass("org/beyka/tiffbitmapfactory/TiffConverter$ConverterOptions");
jThreadClass = env->FindClass("java/lang/Thread");
compressionInt = 5;
inFd = -1;
outFd = -1;
}
BaseTiffConverter::BaseTiffConverter(JNIEnv *e, jclass clazz, jint in, jint out, jobject opts, jobject listener)
{
boundX = boundY = boundWidth = boundHeight = -1;
hasBounds = 0;
availableMemory = 8000 * 8000 * 4;
env = e;
inFd = in;
outFd = out;
optionsObj = opts;
this->listener = listener;
throwException = JNI_FALSE;
appendTiff = JNI_FALSE;
tiffDirectory = 0;
jIProgressListenerClass = env->FindClass("org/beyka/tiffbitmapfactory/IProgressListener");
jConvertOptionsClass = env->FindClass("org/beyka/tiffbitmapfactory/TiffConverter$ConverterOptions");
jThreadClass = env->FindClass("java/lang/Thread");
compressionInt = 5;
}
BaseTiffConverter::~BaseTiffConverter()
{
LOGI("base destructor");
if (cdescription) {
env->ReleaseStringUTFChars(description, cdescription);
}
if (csoftware) {
env->ReleaseStringUTFChars(software, csoftware);
}
if (jIProgressListenerClass) {
env->DeleteLocalRef(jIProgressListenerClass);
jIProgressListenerClass = NULL;
}
if (jThreadClass) {
env->DeleteLocalRef(jThreadClass);
jThreadClass = NULL;
}
}
void BaseTiffConverter::readOptions()
{
if (optionsObj == NULL) return;
jfieldID tiffdirfield = env->GetFieldID(jConvertOptionsClass, "readTiffDirectory", "I");
tiffDirectory = env->GetIntField(optionsObj, tiffdirfield);
jfieldID availablememfield = env->GetFieldID(jConvertOptionsClass, "availableMemory", "J");
jlong am = env->GetLongField(optionsObj, availablememfield);
if (am > 0 || am == -1) availableMemory = am;
jfieldID throwexceptionsfield = env->GetFieldID(jConvertOptionsClass, "throwExceptions", "Z");
throwException = env->GetBooleanField(optionsObj, throwexceptionsfield);
jfieldID appentifffield = env->GetFieldID(jConvertOptionsClass, "appendTiff", "Z");
appendTiff = env->GetBooleanField(optionsObj, appentifffield);
//read compression
jfieldID gOptions_CompressionModeFieldID = env->GetFieldID(jConvertOptionsClass,
"compressionScheme",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
jobject compressionMode = env->GetObjectField(optionsObj, gOptions_CompressionModeFieldID);
jclass compressionModeClass = env->FindClass("org/beyka/tiffbitmapfactory/CompressionScheme");
jfieldID ordinalFieldID = env->GetFieldID(compressionModeClass, "ordinal", "I");
jint ci = env->GetIntField(compressionMode, ordinalFieldID);
LOGII("ci", ci);
//check is compression scheme is right. if not - set default LZW
if (ci == 1 || ci == 2 || ci == 3 || ci == 4 || ci == 5 || ci == 7 || ci == 8 || ci == 32773 || ci == 32946)
compressionInt = ci;
else
compressionInt = 5;
LOGII("compressionInt ", compressionInt );
env->DeleteLocalRef(compressionModeClass);
//Get image orientation from options object
/*jfieldID orientationFieldID = env->GetFieldID(jConvertOptionsClass,
"orientation",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
jobject orientation = env->GetObjectField(optionsObj, orientationFieldID);
jclass orientationClass = env->FindClass("org/beyka/tiffbitmapfactory/Orientation");
jfieldID orientationOrdinalFieldID = env->GetFieldID(orientationClass, "ordinal", "I");
orientationInt = env->GetIntField(orientation, orientationOrdinalFieldID);
env->DeleteLocalRef(orientationClass);*/
orientationInt = ORIENTATION_TOPLEFT;
//Get image description field if exist
jfieldID imgDescrFieldID = env->GetFieldID(jConvertOptionsClass, "imageDescription", "Ljava/lang/String;");
description = (jstring)env->GetObjectField(optionsObj, imgDescrFieldID);
if (description) {
cdescription = env->GetStringUTFChars(description, 0);
LOGIS("Image Description: ", cdescription);
}
//Get software field if exist
jfieldID softwareFieldID = env->GetFieldID(jConvertOptionsClass, "software", "Ljava/lang/String;");
software = (jstring)env->GetObjectField(optionsObj, softwareFieldID);
if (software) {
csoftware = env->GetStringUTFChars(software, 0);
LOGIS("Software tag: ", csoftware);
}
// variables for resolution
jfieldID gOptions_xResolutionFieldID = env->GetFieldID(jConvertOptionsClass, "xResolution", "F");
xRes = env->GetFloatField(optionsObj, gOptions_xResolutionFieldID);
jfieldID gOptions_yResolutionFieldID = env->GetFieldID(jConvertOptionsClass, "yResolution", "F");
yRes = env->GetFloatField(optionsObj, gOptions_yResolutionFieldID);
jfieldID gOptions_resUnitFieldID = env->GetFieldID(jConvertOptionsClass,
"resUnit",
"Lorg/beyka/tiffbitmapfactory/ResolutionUnit;");
jobject resUnitObject = env->GetObjectField(optionsObj, gOptions_resUnitFieldID);
//Get res int from resUnitObject
jclass resolutionUnitClass = env->FindClass("org/beyka/tiffbitmapfactory/ResolutionUnit");
jfieldID resUnitOrdinalFieldID = env->GetFieldID(resolutionUnitClass, "ordinal", "I");
resUnit = env->GetIntField(resUnitObject, resUnitOrdinalFieldID);
env->DeleteLocalRef(resolutionUnitClass);
//Get decode are
jfieldID gOptions_decodeAreaFieldID = env->GetFieldID(jConvertOptionsClass,
"inTiffDecodeArea",
"Lorg/beyka/tiffbitmapfactory/DecodeArea;");
jobject decodeAreaObj = env->GetObjectField(optionsObj, gOptions_decodeAreaFieldID);
if (decodeAreaObj) {
LOGI("Decode bounds present");
jclass decodeAreaClass = env->FindClass("org/beyka/tiffbitmapfactory/DecodeArea");
jfieldID xFieldID = env->GetFieldID(decodeAreaClass, "x", "I");
jfieldID yFieldID = env->GetFieldID(decodeAreaClass, "y", "I");
jfieldID widthFieldID = env->GetFieldID(decodeAreaClass, "width", "I");
jfieldID heightFieldID = env->GetFieldID(decodeAreaClass, "height", "I");
boundX = env->GetIntField(decodeAreaObj, xFieldID);
boundY = env->GetIntField(decodeAreaObj, yFieldID);
boundWidth = env->GetIntField(decodeAreaObj, widthFieldID);
boundHeight = env->GetIntField(decodeAreaObj, heightFieldID);
LOGII("Decode X", boundX);
LOGII("Decode Y", boundY);
LOGII("Decode width", boundWidth);
LOGII("Decode height", boundHeight);
hasBounds = 1;
env->DeleteLocalRef(decodeAreaClass);
}
}
char BaseTiffConverter::normalizeDecodeArea() {
if (hasBounds) {
if (boundX >= width-1) {
const char *message = "X of left top corner of decode area should be less than image width";
LOGE(*message);
if (throwException) {
jstring adinf = env->NewStringUTF(message);
if (inPath) {
throw_decode_file_exception(env, inPath, adinf);
} else {
throw_decode_file_exception_fd(env, inFd, adinf);
}
env->DeleteLocalRef(adinf);
}
return 0;
}
if (boundY >= height-1) {
const char *message = "Y of left top corner of decode area should be less than image height";
LOGE(*message);
if (throwException) {
jstring adinf = env->NewStringUTF(message);
if (inPath) {
throw_decode_file_exception(env, inPath, adinf);
} else {
throw_decode_file_exception_fd(env, inFd, adinf);
}
env->DeleteLocalRef(adinf);
}
return 0;
}
if (boundX < 0) boundX = 0;
if (boundY < 0) boundY = 0;
if (boundX + boundWidth >= width) boundWidth = width - boundX -1;
if (boundY + boundHeight >= height) boundHeight = height - boundY -1;
if (boundWidth < 1) {
const char *message = "Width of decode area can\'t be less than 1";
LOGE(*message);
if (throwException) {
jstring adinf = env->NewStringUTF(message);
if (inPath) {
throw_decode_file_exception(env, inPath, adinf);
} else {
throw_decode_file_exception_fd(env, inFd, adinf);
}
env->DeleteLocalRef(adinf);
}
return 0;
}
if (boundHeight < 1) {
const char *message = "Height of decode area can\'t be less than 1";
LOGE(*message);
if (throwException) {
jstring adinf = env->NewStringUTF(message);
if (inPath) {
throw_decode_file_exception(env, inPath, adinf);
} else {
throw_decode_file_exception_fd(env, inFd, adinf);
}
env->DeleteLocalRef(adinf);
}
return 0;
}
outWidth = boundWidth;
outHeight = boundHeight;
outStartX = boundX;
outStartY = boundY;
return 1;
} else {
outWidth = width;
outHeight = height;
outStartX = 0;
outStartY = 0;
return 1;
}
}
char *BaseTiffConverter::getCreationDate() {
char * datestr = (char *) malloc(sizeof(char) * 20);
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
strftime (datestr,20,/*"Now it's %I:%M%p."*/"%Y:%m:%d %H:%M:%S",timeinfo);
return datestr;
}
void BaseTiffConverter::sendProgress(jlong current, jlong total) {
if (listener != NULL) {
jmethodID methodid = env->GetMethodID(jIProgressListenerClass, "reportProgress", "(JJ)V");
env->CallVoidMethod(listener, methodid, current, total);
}
}
jboolean BaseTiffConverter::checkStop() {
jmethodID methodID = env->GetStaticMethodID(jThreadClass, "interrupted", "()Z");
jboolean interupted = env->CallStaticBooleanMethod(jThreadClass, methodID);
jboolean stop;
if (optionsObj) {
jfieldID stopFieldId = env->GetFieldID(jConvertOptionsClass,
"isStoped",
"Z");
stop = env->GetBooleanField(optionsObj, stopFieldId);
} else {
stop = JNI_FALSE;
}
return interupted || stop;
}
void BaseTiffConverter::rotateTileLinesVertical(uint32 tileHeight, uint32 tileWidth, uint32* whatRotate, uint32 *bufferLine) {
for (int line = 0; line < tileHeight / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = whatRotate + tileWidth * line;
bottom_line = whatRotate + tileWidth * (tileHeight - line -1);
_TIFFmemcpy(bufferLine, top_line, sizeof(unsigned int) * tileWidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * tileWidth);
_TIFFmemcpy(bottom_line, bufferLine, sizeof(unsigned int) * tileWidth);
}
}
void BaseTiffConverter::rotateTileLinesHorizontal(uint32 tileHeight, uint32 tileWidth, uint32* whatRotate, uint32 *bufferLine) {
uint32 buf;
for (int y = 0; y < tileHeight; y++) {
for (int x = 0; x < tileWidth / 2; x++) {
buf = whatRotate[y * tileWidth + x];
whatRotate[y * tileWidth + x] = whatRotate[y * tileWidth + tileWidth - x - 1];
whatRotate[y * tileWidth + tileWidth - x - 1] = buf;
}
}
}
void BaseTiffConverter::normalizeTile(uint32 tileHeight, uint32 tileWidth, uint32* rasterTile) {
//normalize tile
//find start and end pixels
int sx = -1, ex= -1, sy= -1, ey= -1;
for (int y = 0; y < tileHeight; y++) {
for (int x = 0; x < tileWidth; x++) {
if (rasterTile[y * tileWidth + x] != 0) {
sx = x;
sy = y;
break;
}
}
if (sx != -1) break;
}
for (int y = tileHeight -1; y >= 0; y--) {
for (int x = tileWidth -1; x >= 0; x--) {
if (rasterTile[y * tileWidth + x] != 0) {
ex = x;
ey = y;
break;
}
}
if (ex != -1) break;
}
if (sy != 0) {
for (int y = 0; y < tileHeight - sy -1; y++) {
memcpy(rasterTile + (y * tileWidth), rasterTile + ((y+sy)*tileWidth), tileWidth * sizeof(uint32));
}
}
if (sx != 0) {
for (int y = 0; y < tileHeight; y++) {
for (int x = 0; x < tileWidth - sx -1; x++) {
rasterTile[y * tileWidth + x] = rasterTile[y * tileWidth + x + sx];
}
}
}
}
================================================
FILE: src/main/jni/BaseTiffConverter.h
================================================
//
// Created by beyka on 5/11/17.
//
#ifndef TIFFSAMPLE_BASETIFFCONVERTER_H
#define TIFFSAMPLE_BASETIFFCONVERTER_H
#include
#include
#include
#include "NativeExceptions.h"
#include
#include
#include "unistd.h"
#include
#include "string.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "BaseTiffConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BaseTiffConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BaseTiffConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BaseTiffConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "BaseTiffConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "BaseTiffConverter", "%s %s", x, y)
#endif
class BaseTiffConverter {
public:
explicit BaseTiffConverter(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
explicit BaseTiffConverter(JNIEnv *, jclass, jint, jint, jobject, jobject);
~BaseTiffConverter();
virtual jboolean convert() = 0;
protected:
static const int colorMask = 0xFF;
jboolean conversion_result = JNI_FALSE;
JNIEnv *env;
jstring inPath;
jstring outPath;
jint inFd;
jint outFd;
jobject optionsObj = NULL;
jobject listener = NULL;
jclass jConvertOptionsClass = NULL;
jclass jIProgressListenerClass = NULL;
jclass jThreadClass = NULL;
uint32 width;
uint32 height;
uint32 outWidth;
uint32 outHeight;
uint32 outStartX;
uint32 outStartY;
jlong availableMemory;
jboolean throwException;
jint tiffDirectory;
jboolean appendTiff;
jint compressionInt;
jint orientationInt;
uint16 resUnit;
float xRes;
float yRes;
jstring description;
const char *cdescription = NULL;
jstring software;
const char *csoftware = NULL;
int boundX;
int boundY;
int boundWidth;
int boundHeight;
char hasBounds;
void readOptions();
char normalizeDecodeArea();
char *getCreationDate();
void sendProgress(jlong, jlong);
jboolean checkStop();
void rotateTileLinesVertical(uint32, uint32, uint32*, uint32*);
void rotateTileLinesHorizontal(uint32, uint32, uint32*, uint32*);
void normalizeTile(uint32, uint32, uint32*);
};
#endif //TIFFSAMPLE_BASETOTIFFCONVERTER_H
================================================
FILE: src/main/jni/BitmapReader.cpp
================================================
//
// Created by beyka on 9/21/17.
//
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
#include "BitmapReader.h"
#include "BMP.h"
#include
jobject readBmp
(JNIEnv *env, jclass clazz, jstring tiffPath, jstring inPath, jobject options, jobject listener)
{
FILE *inFile;
//open bmp file fow reading
const char *inCPath = NULL;
inCPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", inCPath);
inFile = fopen(inCPath, "rb");
if (!inFile) {
//if (throwException) {
throw_cant_open_file_exception(env, inPath);
//}
LOGES("Can\'t open out file", inCPath);
env->ReleaseStringUTFChars(inPath, inCPath);
return JNI_FALSE;
} else {
env->ReleaseStringUTFChars(inPath, inCPath);
}
//read file header
size_t byte_count = 54;
unsigned char *header = (unsigned char *)malloc(sizeof(unsigned char) * byte_count);
fread(header, 1, byte_count, inFile);
rewind(inFile);
//Check is file is JPG image
bool is_bmp = !strncmp( (const char*)header, "BM", 2 );
//seek file to begin
//rewind(inFile);
if (!is_bmp) {
LOGE("Not bmp file");
// if (throwException) {
throw_cant_open_file_exception(env, inPath);
// }
return JNI_FALSE;
} else {
LOGI("IS BMP");
}
unsigned char *buf;
BITMAPFILEHEADER bmp;
BITMAPINFOHEADER inf;
int size;
int width, height;
fread(&bmp, sizeof(BITMAPFILEHEADER), 1, inFile);
//read(fd, &bmp, sizeof(BITMAPFILEHEADER));
//read(fd, &inf,sizeof(BITMAPINFOHEADER));
fread(&inf, sizeof(BITMAPINFOHEADER), 1, inFile);
width = inf.biWidth;
height = inf.biHeight;
LOGII("width = ", inf.biWidth);
LOGII("height = ", inf.biHeight);
LOGII("bfType",bmp.bfType);
LOGII("bfSize",bmp.bfSize);
LOGII("bfOffBits",bmp.bfOffBits);
LOGII("biSize",inf.biSize);
LOGII("biPlanes",inf.biPlanes);
LOGII("biBitCount",inf.biBitCount);
LOGII("biCompression",inf.biCompression);
LOGII("biSizeImage",inf.biSizeImage);
//check if bitnap not 24 bits - throw exception
/*if (inf.biBitCount != 24) {
LOGE("Not 24 bits file");
if (throwException) {
throw_cant_open_file_exception(env, inPath);
}
return NULL;
}*/
LOGII("biSizeImage", inf.biSizeImage);
if(inf.biSizeImage == 0) {
size = width * 3 + width % 4;
size = size * height;
} else {
size = inf.biSizeImage;
}
buf = (unsigned char *)malloc(size);
if (buf == NULL) {
LOGE("Cant allocate buffer");
return NULL;
}
fseek(inFile, bmp.bfOffBits, SEEK_SET);
//fread(pixels, sizeof(unsigned char), rowPerStrip * rowSize, inFile);
int n = fread(buf, sizeof(unsigned char), size, inFile);
//int n = read(inFile, buf, size);
LOGII("Read bytes", n);
int temp, line, i, j, numImgBytes, iw, ih, ind = 0, new_ind = 0;
uint32 *pixels;
temp = width * 3;
line = temp + width % 4;
numImgBytes = (4 * (width * height));
pixels = (uint32*)malloc(numImgBytes);
//memcpy(pixels, buf, numImgBytes);
numImgBytes = line * height;
for (i = 0; i < numImgBytes; i++) {
unsigned int r, g, b;
if (i > temp && (i % line) >= temp) continue;
b = buf[i];
i++;
g = buf[i];
i++;
r = buf[i];
/*iw = ind % width;
ih = ind / width;
new_ind = iw + (height - ih - 1) * width;*/
unsigned int alpha = 255;
pixels[ind] = (r| g << 8 | b << 16 | alpha << 24) ;
ind++;
}
for (i = 0; i < height/2 ;i++) {
uint32 *tmp = new uint32[width];
memcpy(tmp, pixels + i * width, width * sizeof(uint32));
memcpy(pixels + i * width, pixels + (height - 1- i) * width , width * sizeof(uint32));
memcpy(pixels + (height - 1- i) * width , tmp, width * sizeof(uint32));
free (tmp);
}
free(buf);
jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
jmethodID methodid = env->GetStaticMethodID(bitmapClass, "createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
jfieldID bitmapConfigField = env->GetStaticFieldID(bitmapConfigClass, "ARGB_8888",
"Landroid/graphics/Bitmap$Config;");
//BitmapConfig
jobject config = env->GetStaticObjectField(bitmapConfigClass, bitmapConfigField);
jobject java_bitmap = env->CallStaticObjectMethod(bitmapClass, methodid, width,
height, config);
int ret;
void *bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, java_bitmap, &bitmapPixels)) < 0) {
//error
LOGE("Lock pixels failed");
return NULL;
}
int pixelsCount = width * height;
memcpy(bitmapPixels, (jint *) pixels, sizeof(jint) * pixelsCount);
AndroidBitmap_unlockPixels(env, java_bitmap);
free(pixels);
return java_bitmap;
}
#ifdef __cplusplus
}
#endif
================================================
FILE: src/main/jni/BitmapReader.h
================================================
//
// Created by beyka on 9/21/17.
//
#ifndef TIFFSAMPLE_BITMAPREADER_H
#define TIFFSAMPLE_BITMAPREADER_H
#include
#include
#include
#include "string.h"
#include "NativeExceptions.h"
#include
#include
#include "unistd.h"
#include
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "BMPReader", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BMPReader", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BMPReader", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BMPReader", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "BMPReader", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "BMPReader", "%s %s", x, y)
#endif
#ifdef __cplusplus
extern "C" {
#endif
jobject readBmp
(JNIEnv *env, jclass clazz, jstring tiffPath, jstring pngPath, jobject options, jobject listener);
#ifdef __cplusplus
}
#endif
#endif //TIFFSAMPLE_BITMAPREADER_H
================================================
FILE: src/main/jni/BmpToTiffConverter.cpp
================================================
//
// Created by beyka on 9/20/17.
//
#include "BmpToTiffConverter.h"
BmpToTiffConverter::BmpToTiffConverter(JNIEnv *e, jclass clazz, jstring in, jstring out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
}
BmpToTiffConverter::BmpToTiffConverter(JNIEnv *e, jclass clazz, jint in, jint out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
}
BmpToTiffConverter::~BmpToTiffConverter()
{
LOGI("Destructor");
if (tiffImage) {
TIFFClose(tiffImage);
tiffImage = NULL;
}
LOGI("Tiff removed");
if (inf) {
delete inf;
}
LOGI("Inf deleted");
if (bmp) {
delete bmp;
}
LOGI("header deleted");
}
jboolean BmpToTiffConverter::convert()
{
LOGI("CONVERT");
readOptions();
if(outFd < 0) {
//open tiff file for writing or appending
const char *outCPath = NULL;
outCPath = env->GetStringUTFChars(outPath, 0);
LOGIS("OUT path", outCPath);
LOGIS("nativeTiffOpenForSave", outCPath);
int mode = O_RDWR | O_CREAT | O_TRUNC | 0;
if (appendTiff) {
mode = O_RDWR | O_CREAT;
}
outFd = open(outCPath, mode, 0666);
if (outFd < 0) {
throw_cant_open_file_exception(env, outPath);
env->ReleaseStringUTFChars(outPath, outCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(outPath, outCPath);
}
if (!appendTiff) {
if ((tiffImage = TIFFFdOpen(outFd, "", "w")) == NULL) {
LOGE("Unable to open tif file");
if (throwException) {
throw_cant_open_file_exception_fd(env, outFd);
}
return JNI_FALSE;
}
} else {
if ((tiffImage = TIFFFdOpen(outFd, "", "a")) == NULL) {
LOGE("Unable to open tif file");
if (throwException) {
throw_cant_open_file_exception_fd(env, outFd);
}
return JNI_FALSE;
}
}
//open bmp file fow reading
if(inFd < 0) {
const char *inCPath = NULL;
inCPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", inCPath);
int mode = O_RDONLY;
inFd = open(inCPath, mode, 0666);
if (inFd < 0) {
LOGES("Can\'t open in file", inCPath);
throw_cant_open_file_exception(env, inPath);
env->ReleaseStringUTFChars(inPath, inCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(inPath, inCPath);
}
//Read header of bitmap file
readHeaders();
//Check is file is BMP image
bool is_bmp = !strncmp( (const char*)&bmp->bfType, "BM", 2 );
if (!is_bmp) {
LOGE("Not bmp file");
if (throwException) {
throw_cant_open_file_exception_fd(env, inFd);
}
return JNI_FALSE;
}
//check is bitmap has 24 bit per pixel. other format not supported
if (inf->biBitCount != 16 && inf->biBitCount != 24 && inf->biBitCount != 32 && inf->biBitCount != 0) {
LOGE("Support only 24bpp bitmaps");
if (throwException) {
throw_cant_open_file_exception_fd(env, inFd);
}
return JNI_FALSE;
}
LOGII("Bits per pixel", inf->biBitCount);
int compression = inf->biCompression;
LOGII("compression", inf->biCompression);
for (int i = 0; i < 3; i++) {
LOGII("mask", inf->biPalete[i]);
}
//Component per pixel will be always 4. Alpha will be always 0xff
int componentsPerPixel = 4;//inf->biBitCount / 8;
int width = inf->biWidth;
int height = inf->biHeight;
LOGII("width", width);
LOGII("height", height);
//Create tiff structure
TIFFSetField(tiffImage, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tiffImage, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tiffImage, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tiffImage, TIFFTAG_COMPRESSION, compressionInt);
TIFFSetField(tiffImage, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tiffImage, TIFFTAG_XRESOLUTION, xRes);
TIFFSetField(tiffImage, TIFFTAG_YRESOLUTION, yRes);
TIFFSetField(tiffImage, TIFFTAG_RESOLUTIONUNIT, resUnit);
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
TIFFSetField(tiffImage, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(tiffImage, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tiffImage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tiffImage, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
} else {
TIFFSetField(tiffImage, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(tiffImage, TIFFTAG_SAMPLESPERPIXEL, componentsPerPixel);
TIFFSetField(tiffImage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
}
//creation date
char *date = getCreationDate();
TIFFSetField(tiffImage, TIFFTAG_DATETIME, date);
free(date);
//image description
if (cdescription) {
TIFFSetField(tiffImage, TIFFTAG_IMAGEDESCRIPTION, cdescription);
}
//software tag
if (csoftware) {
TIFFSetField(tiffImage, TIFFTAG_SOFTWARE, csoftware);
}
//progress reporter
jlong total = width * height;
sendProgress(0, total);
int rowSize = width * componentsPerPixel;
//Calculate row per strip
//maximum size for strip should be less than 2Mb if memory available
unsigned long MB2 = (availableMemory == -1 || availableMemory > 3 * 1024 * 1024) ? 2 * 1024 * 1024 : width * 4;
int rowPerStrip = MB2/rowSize;
if (rowPerStrip >= height) {
rowPerStrip = height / 4;
}
if (rowPerStrip < 1) rowPerStrip = 1;
LOGII("rowPerStrip", rowPerStrip);
unsigned long estimateMem = rowPerStrip * width * 4 * 2;//need 2 buffers for read data from bitmap. Check getPixelsFromBmp method
if (compressionInt == COMPRESSION_JPEG) {
estimateMem += width * sizeof(uint32);//temp array for writing JPEG lines
estimateMem += width * sizeof(uint32);//temp array for fliping bitmap data in getPixelsFromBmp method
} else if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
estimateMem += (width/8 + 0.5) * rowPerStrip; // bilevel array
} else {
estimateMem += 0;
}
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enough memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
if (checkStop()) {
conversion_result = JNI_FALSE;
return conversion_result;
}
int ret;
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
TIFFSetField(tiffImage, TIFFTAG_ROWSPERSTRIP, rowPerStrip);
int compressedWidth = (width/8 + 0.5);
for (int y = 0; y < height; y+=rowPerStrip) {
if (checkStop()) {
conversion_result = JNI_FALSE;
return conversion_result;
}
int rowToRead = rowPerStrip;
if (rowToRead + y >= height) {
rowToRead = height - y;
}
sendProgress(y * width, total);
uint32 *pixels = getPixelsFromBmp(y, rowToRead);
unsigned char *bilevel = convertArgbToBilevel(pixels, width, rowToRead);
free(pixels);
ret = TIFFWriteEncodedStrip(tiffImage, y/rowToRead, bilevel, compressedWidth * sizeof(unsigned char) * rowToRead);
free(bilevel);
}
} else if (compressionInt == COMPRESSION_JPEG) {
for (int ys = 0; ys < height; ys+=rowPerStrip) {
if (checkStop()) {
return JNI_FALSE;
}
int rowToRead = rowPerStrip;
if (rowToRead + ys >= height) {
rowToRead = height - ys;
}
sendProgress(ys * width, total);
uint32 *pixels = getPixelsFromBmp(ys, rowToRead);
uint32 *pixelsline = new uint32[width];
for (int k = 0; k < rowToRead; k++) {
memcpy(pixelsline, &pixels [k * width], width * sizeof(uint32));
ret = TIFFWriteScanline(tiffImage, pixelsline, ys + k, 0);
}
delete[] pixelsline;
free(pixels);
}
} else {
TIFFSetField(tiffImage, TIFFTAG_ROWSPERSTRIP, rowPerStrip);
for (int y = 0; y < height; y+=rowPerStrip) {
if (checkStop()) {
return JNI_FALSE;
}
int rowToRead = rowPerStrip;
if (rowToRead + y >= height) {
rowToRead = height - y;
}
//LOGII("rowToRead", rowToRead);
sendProgress(y * width, total);
uint32 *pixels = getPixelsFromBmp(y, rowToRead);
TIFFWriteEncodedStrip(tiffImage, y/rowPerStrip, pixels, width * sizeof(uint32) * rowToRead);
free(pixels);
}
}
ret = TIFFWriteDirectory(tiffImage);
LOGII("ret = ", ret);
sendProgress(total, total);
conversion_result = JNI_TRUE;
return conversion_result;
}
void BmpToTiffConverter::readHeaders()
{
bmp = new BITMAPFILEHEADER;
inf = new BITMAPINFOHEADER;
int br = read(inFd, bmp, sizeof(BITMAPFILEHEADER));
LOGII("Read bytes ", br);
LOGIS("bmp read ", bmp);
int bi = read(inFd, inf, sizeof(BITMAPINFOHEADER));
LOGII("Read bytes ", bi);
LOGIS("inf read ", (char*)inf);
}
uint32 *BmpToTiffConverter::getPixelsFromBmp(int offset, int limit)
{
int componentPerPixel = inf->biBitCount/8;
LOGII("componentPerPixel", inf->biBitCount);
LOGII("componentPerPixel", componentPerPixel);
if (componentPerPixel == 2) {
return getPixelsFrom16Bmp(offset, limit);
} else if (componentPerPixel == 3) {
return getPixelsFrom24Bmp(offset, limit);
} else if (componentPerPixel == 4) {
return getPixelsFrom32Bmp(offset, limit);
}
return NULL;
}
uint32 *BmpToTiffConverter::getPixelsFrom16Bmp(int offset, int limit)
{
unsigned char *buf;
int size;
int width = inf->biWidth;
int height = inf->biHeight;
LOGII("compr", inf->biCompression);
if (offset + limit >= height) {
limit = height - offset;
}
//width of bitmap should be multiple 4
size = width * 2 + (width * 2) % 4;
size = size * limit;
buf = (unsigned char *)malloc(size);
if (buf == NULL) {
LOGE("Can\'t allocate buffer");
return NULL;
}
//in bitmap picture stored fliped from up to down.
//when need read 0 row - should read height-1 row
//seek file to position from the end of file to read
lseek(inFd, bmp->bfOffBits + (height - offset - limit) * (width * 2 + (width * 2) % 4) , SEEK_SET);
int n = read(inFd, buf, size);
LOGII("Read bytes", n);
int temp, line, i, j, numImgBytes, ind = 0;
uint32 *pixels;
temp = width * 2;
line = temp + (width * 2) % 4;//width % 4;
numImgBytes = (4 * (width * limit));
pixels = (uint32*)malloc(numImgBytes);
int pixelss = 0;
numImgBytes = line * limit;
for (i = 0; i < numImgBytes; i+=2) {
if (i > temp && (i % line) >= temp) continue;
uint16_t r, g, b, a = 0b11111111;
uint16_t* pix = (uint16_t*) (buf + i);
r = inf->biPalete[0] & *pix;
g = inf->biPalete[1] & *pix;
b = inf->biPalete[2] & *pix;
//Use one of palete mask to determine which type of 1 bpp used 555 or 565
char greenShiftBits;
g = g >> 5;
if (inf->biPalete[1] == 0x03E0) {
greenShiftBits = 3;
r = r >> 10;
} else {
greenShiftBits = 2;
r = r >> 11;
}
pixels[ind] = (r<<3) | (g << greenShiftBits << 8) | (b << 3 << 16) | a << 24 ;//(r| g << 8 | b << 16 | a << 24) ;
ind++;
}
uint32 *tmp = new uint32[width];
for (i = 0; i < limit/2 ;i++) {
memcpy(tmp, pixels + i * width, width * sizeof(uint32));
memcpy(pixels + i * width, pixels + (limit - 1- i) * width , width * sizeof(uint32));
memcpy(pixels + (limit - 1- i) * width , tmp, width * sizeof(uint32));
}
free (tmp);
free(buf);
return pixels;
}
uint32 *BmpToTiffConverter::getPixelsFrom24Bmp(int offset, int limit)
{
unsigned char *buf;
int size;
int width = inf->biWidth;
int height = inf->biHeight;
if (offset + limit >= height) {
limit = height - offset;
}
//width of bitmap should be multiple 4
size = width * 3 + width % 4;
size = size * limit;
buf = (unsigned char *)malloc(size);
if (buf == NULL) {
LOGE("Can\'t allocate buffer");
return NULL;
}
//in bitmap picture stored fliped from up to down.
//when need read 0 row - should read height-1 row
//seek file to position from the end of file to read
lseek(inFd, bmp->bfOffBits + (height - offset - limit) * (width * 3 + width % 4) , SEEK_SET);
int n = read(inFd, buf, size);
LOGII("Read bytes", n);
int temp, line, i, j, numImgBytes, ind = 0;
uint32 *pixels;
temp = width * 3;
line = temp + width % 4;//width % 4;
numImgBytes = (4 * (width * limit));
pixels = (uint32*)malloc(numImgBytes);
numImgBytes = line * limit;
for (i = 0; i < numImgBytes; i++) {
unsigned char r, g, b, a = 0b11111111;
//width of bitmap should be multiple 4
//here skip pixels that haven't data
//but if bitmap is 32 bpp - it is laready multiple to 4
if (i > temp && (i % line) >= temp) continue;
//read colors. alpha always 255lf because 24bpp bitmap hasn't alpha chanel
b = buf[i];
i++;
g = buf[i];
i++;
r = buf[i];
pixels[ind] = (r| g << 8 | b << 16 | a << 24) ;
ind++;
}
uint32 *tmp = new uint32[width];
for (i = 0; i < limit/2 ;i++) {
memcpy(tmp, pixels + i * width, width * sizeof(uint32));
memcpy(pixels + i * width, pixels + (limit - 1- i) * width , width * sizeof(uint32));
memcpy(pixels + (limit - 1- i) * width , tmp, width * sizeof(uint32));
}
free (tmp);
free(buf);
return pixels;
}
uint32 *BmpToTiffConverter::getPixelsFrom32Bmp(int offset, int limit)
{
unsigned char *buf;
int size;
int width = inf->biWidth;
int height = inf->biHeight;
if (offset + limit >= height) {
limit = height - offset;
}
//width of bitmap should be multiple 4
size = width * 4;
size = size * limit;
buf = (unsigned char *)malloc(size);
if (buf == NULL) {
LOGE("Can\'t allocate buffer");
return NULL;
}
//in bitmap picture stored fliped from up to down.
//when need read 0 row - should read height-1 row
//seek file to position from the end of file to read
lseek(inFd, bmp->bfOffBits + (height - offset - limit) * width * 4, SEEK_SET);
int n = read(inFd, buf, size);
LOGII("Read bytes", n);
int temp, line, i, j, numImgBytes, ind = 0;
uint32 *pixels;
line = width * 4;//width % 4;
numImgBytes = (4 * (width * limit));
pixels = (uint32*)malloc(numImgBytes);
for (i = 0; i < numImgBytes; i++) {
unsigned char r, g, b, a = 0b11111111;
//read colors. alpha always 255lf because 24bpp bitmap hasn't alpha chanel
//a = buf[i];
i++;
b = buf[i];
i++;
g = buf[i];
i++;
r = buf[i];
pixels[ind] = (r| g << 8 | b << 16 | a << 24) ;
ind++;
}
uint32 *tmp = new uint32[width];
for (i = 0; i < limit/2 ;i++) {
memcpy(tmp, pixels + i * width, width * sizeof(uint32));
memcpy(pixels + i * width, pixels + (limit - 1- i) * width , width * sizeof(uint32));
memcpy(pixels + (limit - 1- i) * width , tmp, width * sizeof(uint32));
}
free (tmp);
free(buf);
return pixels;
}
unsigned char * BmpToTiffConverter::convertArgbToBilevel(uint32 *data, uint32 width, uint32 height)
{
unsigned char red;
unsigned char green;
unsigned char blue;
uint32 crPix;
uint32 grayPix;
int bilevelWidth = (width / 8 + 0.5);
unsigned char *dest = (unsigned char *) malloc(sizeof(unsigned char) * bilevelWidth * height);
uint32 maxGrey = 0.2125 * 255 + 0.7154 * 255 + 0.0721 * 255;
uint32 halfGrey = maxGrey/2;
uint32 shift = 0;
unsigned char charsum = 0;
int k = 7;
for (int y = 0; y < height; y++) {
shift = 0;
charsum = 0;
k = 7;
for (int i = 0; i < width; i++) {
uint32 *px = &data[y * width + i];
red = px[0];
green = px[1];
blue = px[2];
grayPix = (0.2125 * red + 0.7154 * green + 0.0721 * blue);
if (grayPix < halfGrey) charsum &= ~(1 << k);
else charsum |= 1 << k;
if (k == 0) {
dest[y * bilevelWidth + shift] = charsum;
shift++;
k = 7;
charsum = 0;
} else {
k--;
}
}
}
return dest;
}
================================================
FILE: src/main/jni/BmpToTiffConverter.h
================================================
//
// Created by beyka on 9/20/17.
//
#ifndef TIFFSAMPLE_BMPTOTIFFCONVERTER_H
#define TIFFSAMPLE_BMPTOTIFFCONVERTER_H
#include
#include
#include
#include "fcntl.h"
#include "unistd.h"
#include
#include
#include "BaseTiffConverter.h"
#include "BMP.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#define LOGEI(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "BmpToTiffConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BmpToTiffConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BmpToTiffConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "BmpToTiffConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "BmpToTiffConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "BmpToTiffConverter", "%s %s", x, y)
#define LOGEI(x, y) __android_log_print(ANDROID_LOG_ERROR, "BmpToTiffConverter", "%s %d", x, y)
#endif
class BmpToTiffConverter : public BaseTiffConverter
{
public:
explicit BmpToTiffConverter(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
explicit BmpToTiffConverter(JNIEnv *, jclass, jint, jint, jobject, jobject);
~BmpToTiffConverter();
virtual jboolean convert();
private:
TIFF *tiffImage;
BITMAPFILEHEADER *bmp;
BITMAPINFOHEADER *inf;
void readHeaders();
uint32 * getPixelsFromBmp(int offset, int limit);
uint32 * getPixelsFrom16Bmp(int offset, int limit);
uint32 * getPixelsFrom24Bmp(int offset, int limit);
uint32 * getPixelsFrom32Bmp(int offset, int limit);
unsigned char * convertArgbToBilevel(uint32 *, uint32, uint32);
};
#endif //TIFFSAMPLE_BMPTOTIFFCONVERTER_H
================================================
FILE: src/main/jni/JpgToTiffConverter.cpp
================================================
//
// Created by beyka on 5/15/17.
//
#include "JpgToTiffConverter.h"
JpgToTiffConverter::JpgToTiffConverter(JNIEnv *e, jclass clazz, jstring in, jstring out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
jpeg_struct_init = 0;
compressionInt = 5;
}
JpgToTiffConverter::JpgToTiffConverter(JNIEnv *e, jclass clazz, jint in, jint out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
jpeg_struct_init = 0;
compressionInt = 5;
}
JpgToTiffConverter::~JpgToTiffConverter()
{
LOGI("Destructor");
if (tiffImage) {
TIFFClose(tiffImage);
tiffImage = NULL;
}
LOGI("Tiff removed");
if (jpeg_struct_init) {
jpeg_destroy_decompress(&cinfo);
}
LOGI("JPEG destroyed");
if (inFile) {
fclose(inFile);
}
LOGI("IN file closed");
}
jboolean JpgToTiffConverter::convert()
{
readOptions();
if(outFd < 0) {
//open tiff file for writing or appending
const char *outCPath = NULL;
outCPath = env->GetStringUTFChars(outPath, 0);
LOGIS("OUT path", outCPath);
LOGIS("nativeTiffOpenForSave", outCPath);
int mode = O_RDWR | O_CREAT | O_TRUNC | 0;
if (appendTiff) {
mode = O_RDWR | O_CREAT;
}
outFd = open(outCPath, mode, 0666);
if (outFd < 0) {
throw_cant_open_file_exception(env, outPath);
env->ReleaseStringUTFChars(outPath, outCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(outPath, outCPath);
}
if (!appendTiff) {
if ((tiffImage = TIFFFdOpen(outFd, "", "w")) == NULL) {
LOGE("Unable to open tif file");
if (throwException) {
throw_cant_open_file_exception_fd(env, outFd);
}
return JNI_FALSE;
}
} else {
if ((tiffImage = TIFFFdOpen(outFd, "", "a")) == NULL) {
LOGE("Unable to open tif file");
if (throwException) {
throw_cant_open_file_exception_fd(env, outFd);
}
return JNI_FALSE;
}
}
//open jpg file fow reading
if (inFd < 0) {
const char *inCPath = NULL;
inCPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", inCPath);
inFile = fopen(inCPath, "rb");
if (!inFile) {
if (throwException) {
throw_cant_open_file_exception(env, inPath);
}
LOGES("Can\'t open out file", inCPath);
env->ReleaseStringUTFChars(inPath, inCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(inPath, inCPath);
} else {
inFile = fdopen(inFd, "rb");
if (!inFile) {
if (throwException) {
throw_cant_open_file_exception_fd(env, inFd);
}
LOGES("Can\'t open out file descriptor", inFd);
return JNI_FALSE;
}
}
//read file header
size_t byte_count = 8;
unsigned char *header = (unsigned char *)malloc(sizeof(unsigned char) * byte_count);
fread(header, 1, byte_count, inFile);
//Check is file is JPG image
bool is_jpg = !strncmp( (const char*)header, "\xFF\xD8\xFF", 3 );
//seek file to begin
rewind(inFile);
if (!is_jpg) {
LOGE("Not jpeg file");
if (throwException) {
if (inFd < 0) {
throw_cant_open_file_exception(env, inPath);
} else {
throw_cant_open_file_exception_fd(env, inFd);
}
}
return JNI_FALSE;
} else {
LOGI("IS JPEG");
}
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_struct_init = 1;
LOGI("decompress created");
jpeg_stdio_src(&cinfo, inFile);
LOGI("set file");
//read file parameters
int readHeader = jpeg_read_header(&cinfo, TRUE);
LOGII("read jpeg header", readHeader);
//start decompress
int startDecompress = jpeg_start_decompress(&cinfo);
LOGII("start decompress", startDecompress);
width = cinfo.image_width;
height = cinfo.image_height;
LOGII("width", width);
LOGII("height", height);
componentsPerPixel = cinfo.output_components;
//Create tiff structure
TIFFSetField(tiffImage, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tiffImage, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tiffImage, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tiffImage, TIFFTAG_COMPRESSION, compressionInt);
TIFFSetField(tiffImage, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tiffImage, TIFFTAG_XRESOLUTION, xRes);
TIFFSetField(tiffImage, TIFFTAG_YRESOLUTION, yRes);
TIFFSetField(tiffImage, TIFFTAG_RESOLUTIONUNIT, resUnit);
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
TIFFSetField(tiffImage, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(tiffImage, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tiffImage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tiffImage, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
} else {
TIFFSetField(tiffImage, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(tiffImage, TIFFTAG_SAMPLESPERPIXEL, componentsPerPixel);
if (componentsPerPixel == 1) {
TIFFSetField(tiffImage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
} else {
TIFFSetField(tiffImage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
}
}
//creation date
char *date = getCreationDate();
TIFFSetField(tiffImage, TIFFTAG_DATETIME, date);
free(date);
//image description
if (cdescription) {
TIFFSetField(tiffImage, TIFFTAG_IMAGEDESCRIPTION, cdescription);
}
//software tag
if (csoftware) {
TIFFSetField(tiffImage, TIFFTAG_SOFTWARE, csoftware);
}
//progress reporter
jlong total = width * height;
sendProgress(0, total);
int rowSize = width * componentsPerPixel;
LOGII("jpg samples", componentsPerPixel);
//Calculate row per strip
//maximum size for strip should be less than 2Mb if memory available
unsigned long MB2 = (availableMemory == -1 || availableMemory > 3 * 1024 * 1024) ? 2 * 1024 * 1024 : width * 4;
int rowPerStrip = MB2/rowSize;
//TODO This is workaround. Need to understand why FAX compression schemes have shift in strips.
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
rowPerStrip = 1;
}
if (rowPerStrip >= height) {
rowPerStrip = height / 4;
}
if (rowPerStrip < 1) rowPerStrip = 1;
LOGII("rowPerStrip", rowPerStrip);
unsigned long estimateMem = rowPerStrip * width * 4;
estimateMem += sizeof(JSAMPLE) * rowSize;//jpg buffer
if (compressionInt == COMPRESSION_JPEG) {
estimateMem += 0;
} else if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
estimateMem += (width/8 + 0.5) * rowPerStrip;
} else {
estimateMem += rowPerStrip * rowSize;
}
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enough memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
if (checkStop()) {
//jpeg_finish_decompress(&cinfo);
conversion_result = JNI_FALSE;
return conversion_result;
}
//Buffer for read jpeg image line by line
int buffer_height = 1;
JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW) * buffer_height);
buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * rowSize);
//buffer for format strips for tiff
int ret;
if (compressionInt == COMPRESSION_JPEG) {
int line = 0;
while (cinfo.output_scanline < height) {
if (checkStop()) {
free(buffer[0]);
free(buffer);
conversion_result = JNI_FALSE;
return conversion_result;
}
if (line % rowPerStrip == 0) {
sendProgress(line * width, total);
}
jpeg_read_scanlines(&cinfo, buffer, 1);
ret = TIFFWriteScanline(tiffImage, buffer[0], line, 0);
line++;
}
} else {
TIFFSetField(tiffImage, TIFFTAG_ROWSPERSTRIP, rowPerStrip);
unsigned char *data = new unsigned char[rowSize * rowPerStrip];
int totalRowCounter = 0;
int rowCounter = 0;
bool shouldWrite = false;
while (cinfo.output_scanline < height) {
shouldWrite = true;
jpeg_read_scanlines(&cinfo, buffer, 1);
memcpy(data + rowCounter * rowSize, buffer[0], rowSize);
rowCounter++;
totalRowCounter++;
if (rowCounter == rowPerStrip) {
if (checkStop()) {
//jpeg_finish_decompress(&cinfo);
delete[] data;
free(buffer[0]);
free(buffer);
conversion_result = JNI_FALSE;
return conversion_result;
}
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
int compressedWidth = (width/8 + 0.5);
unsigned char *bilevel = convertArgbToBilevel(data, componentsPerPixel, width, rowPerStrip);
ret = TIFFWriteEncodedStrip(tiffImage, totalRowCounter/rowPerStrip - 1, bilevel, compressedWidth * sizeof(unsigned char) * rowPerStrip);
free(bilevel);
} else {
ret = TIFFWriteEncodedStrip(tiffImage, totalRowCounter/rowPerStrip - 1, data, rowPerStrip * rowSize);
}
rowCounter = 0;
shouldWrite = false;
sendProgress(totalRowCounter * width, total);
}
}
if (shouldWrite) { LOGI("last stage");
if (checkStop()) {
//jpeg_finish_decompress(&cinfo);
delete[] data;
free(buffer[0]);
free(buffer);
conversion_result = JNI_FALSE;
return conversion_result;
}
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
int compressedWidth = (width/8 + 0.5);
unsigned char *bilevel = convertArgbToBilevel(data, componentsPerPixel, width, rowPerStrip);
ret = TIFFWriteEncodedStrip(tiffImage, totalRowCounter/rowPerStrip, bilevel, compressedWidth * sizeof(unsigned char) * rowPerStrip);
free(bilevel);
} else {
ret = TIFFWriteEncodedStrip(tiffImage, totalRowCounter/rowPerStrip, data, rowPerStrip * rowSize);
}
}
delete[] data;
}
ret = TIFFWriteDirectory(tiffImage);
LOGII("ret = ", ret);
jpeg_finish_decompress(&cinfo);
free(buffer[0]);
free(buffer);
sendProgress(total, total);
conversion_result = JNI_TRUE;
return conversion_result;
}
unsigned char * JpgToTiffConverter::convertArgbToBilevel(unsigned char *data, int components, uint32 width, uint32 height)
{
unsigned char red;
unsigned char green;
unsigned char blue;
uint32 crPix;
uint32 grayPix;
int bilevelWidth = (width / 8 + 0.5);
unsigned char *dest = (unsigned char *) malloc(sizeof(unsigned char) * bilevelWidth * height);
uint32 maxGrey = (components > 1) ? (0.2125 * 255 + 0.7154 * 255 + 0.0721 * 255) : 255;
uint32 halfGrey = maxGrey/2;
uint32 shift = 0;
unsigned char charsum = 0;
int k = 7;
for (int y = 0; y < height; y++) {
shift = 0;
charsum = 0;
k = 7;
for (int i = 0; i < width * components; i+=components) {
unsigned char *px = &data[y * width * components + i];
if (components == 1) {
grayPix = (*px);
} else {
red = px[0];
green = px[1];
blue = px[2];
grayPix = (0.2125 * red + 0.7154 * green + 0.0721 * blue);
}
if (grayPix < halfGrey) charsum &= ~(1 << k);
else charsum |= 1 << k;
if (k == 0) {
dest[y * bilevelWidth + shift] = charsum;
shift++;
k = 7;
charsum = 0;
} else {
k--;
}
}
}
return dest;
}
================================================
FILE: src/main/jni/JpgToTiffConverter.h
================================================
//
// Created by beyka on 5/15/17.
//
#ifndef TIFFSAMPLE_JPGTOTIFFCONVERTER_H
#define TIFFSAMPLE_JPGTOTIFFCONVERTER_H
#include
#include
#include
#include "fcntl.h"
#include "unistd.h"
#include
#include
#include "BaseTiffConverter.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#define LOGEI(x, y);
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "JpgToTiffConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "JpgToTiffConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "JpgToTiffConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "JpgToTiffConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "JpgToTiffConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "JpgToTiffConverter", "%s %s", x, y)
#define LOGEI(x, y) __android_log_print(ANDROID_LOG_ERROR, "JpgToTiffConverter", "%s %d", x, y)
#endif
class JpgToTiffConverter : public BaseTiffConverter
{
public:
explicit JpgToTiffConverter(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
explicit JpgToTiffConverter(JNIEnv *, jclass, jint, jint, jobject, jobject);
~JpgToTiffConverter();
virtual jboolean convert();
private:
TIFF *tiffImage;
FILE *inFile;
int componentsPerPixel;
char jpeg_struct_init;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
//METHODDEF(void) JpgToTiffConverter::my_error_exit (j_common_ptr)
unsigned char * convertArgbToBilevel(unsigned char *, int, uint32, uint32);
};
#endif //TIFFSAMPLE_JPGTOTIFFCONVERTER_H
================================================
FILE: src/main/jni/NativeDecoder.cpp
================================================
//
// Created by beyka on 3.2.17.
//
#include "NativeDecoder.h"
#include
jmp_buf NativeDecoder::tile_buf;
jmp_buf NativeDecoder::strip_buf;
jmp_buf NativeDecoder::image_buf;
jmp_buf NativeDecoder::general_buf;
//Constructor for decoding from file descriptor
NativeDecoder::NativeDecoder(JNIEnv *e, jclass c, jint fd, jobject opts, jobject listener)
{
decodingMode = DECODE_MODE_FILE_DESCRIPTOR;
availableMemory = 8000*8000*4; // use 244Mb restriction for decoding full image
env = e;
clazz = c;
optionsObject = opts;
listenerObject = listener;
jFd = fd;
origwidth = 0;
origheight = 0;
origorientation = 0;
origcompressionscheme = 0;
progressTotal = 0;
invertRedAndBlue = false;
boundX = boundY = boundWidth = boundHeight = -1;
hasBounds = 0;
preferedConfig = NULL;
image = NULL;
jBitmapOptionsClass = env->FindClass(
"org/beyka/tiffbitmapfactory/TiffBitmapFactory$Options");
jIProgressListenerClass = env->FindClass("org/beyka/tiffbitmapfactory/IProgressListener");
jThreadClass = env->FindClass("java/lang/Thread");
}
//Constructor for decoding from file path
NativeDecoder::NativeDecoder(JNIEnv *e, jclass c, jstring path, jobject opts, jobject listener)
{
decodingMode = DECODE_MODE_FILE_PATH;
availableMemory = 8000*8000*4; // use 244Mb restriction for decoding full image
env = e;
clazz = c;
optionsObject = opts;
listenerObject = listener;
jPath = path;
origwidth = 0;
origheight = 0;
origorientation = 0;
origcompressionscheme = 0;
progressTotal = 0;
invertRedAndBlue = false;
boundX = boundY = boundWidth = boundHeight = -1;
hasBounds = 0;
preferedConfig = NULL;
image = NULL;
jBitmapOptionsClass = env->FindClass(
"org/beyka/tiffbitmapfactory/TiffBitmapFactory$Options");
jIProgressListenerClass = env->FindClass("org/beyka/tiffbitmapfactory/IProgressListener");
jThreadClass = env->FindClass("java/lang/Thread");
}
NativeDecoder::~NativeDecoder()
{
LOGI("Destructor");
if (image) {
TIFFClose(image);
image = NULL;
}
//Release global reference for Bitmap.Config
if (preferedConfig) {
env->DeleteGlobalRef(preferedConfig);
preferedConfig = NULL;
}
if (jBitmapOptionsClass) {
env->DeleteLocalRef(jBitmapOptionsClass);
jBitmapOptionsClass = NULL;
}
if (jIProgressListenerClass) {
env->DeleteLocalRef(jIProgressListenerClass);
jIProgressListenerClass = NULL;
}
if (jThreadClass) {
env->DeleteLocalRef(jThreadClass);
jThreadClass = NULL;
}
}
jobject NativeDecoder::getBitmap()
{
//init signal handler for catch SIGSEGV error that could be raised in libtiff
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = generalErrorHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if(sigaction(SIGSEGV, &act, 0) < 0) {
LOGE("Can\'t setup signal handler. Working without errors catching mechanism");
}
//check for error
if (setjmp(NativeDecoder::general_buf)) {
const char * err = "Caught SIGSEGV signal(Segmentation fault or invalid memory reference)";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
//Get options from TiffBitmapFactory$Options
jfieldID gOptions_ThrowExceptionFieldID = env->GetFieldID(jBitmapOptionsClass,
"inThrowException",
"Z");
throwException = env->GetBooleanField(optionsObject, gOptions_ThrowExceptionFieldID);
jfieldID gOptions_UseOrientationTagFieldID = env->GetFieldID(jBitmapOptionsClass,
"inUseOrientationTag",
"Z");
useOrientationTag = env->GetBooleanField(optionsObject, gOptions_UseOrientationTagFieldID);
jfieldID gOptions_sampleSizeFieldID = env->GetFieldID(jBitmapOptionsClass, "inSampleSize", "I");
jint inSampleSize = env->GetIntField(optionsObject, gOptions_sampleSizeFieldID);
if (inSampleSize != 1 && inSampleSize % 2 != 0) {
const char *message = "inSampleSize should be power of 2\0";
LOGE(message);
if (throwException) {
throwDecodeFileException(message);
}
return NULL;
}
jfieldID gOptions_justDecodeBoundsFieldID = env->GetFieldID(jBitmapOptionsClass,
"inJustDecodeBounds", "Z");
jboolean inJustDecodeBounds = env->GetBooleanField(optionsObject, gOptions_justDecodeBoundsFieldID);
jfieldID gOptions_invertRedAndBlueFieldID = env->GetFieldID(jBitmapOptionsClass,
"inSwapRedBlueColors", "Z");
invertRedAndBlue = env->GetBooleanField(optionsObject, gOptions_invertRedAndBlueFieldID);
jfieldID gOptions_DirectoryCountFieldID = env->GetFieldID(jBitmapOptionsClass,
"inDirectoryNumber",
"I");
jint inDirectoryNumber = env->GetIntField(optionsObject, gOptions_DirectoryCountFieldID);
LOGII("param directoryCount", inDirectoryNumber);
jfieldID gOptions_AvailableMemoryFieldID = env->GetFieldID(jBitmapOptionsClass,
"inAvailableMemory",
"J");
unsigned long inAvailableMemory = env->GetLongField(optionsObject, gOptions_AvailableMemoryFieldID);
jfieldID gOptions_PreferedConfigFieldID = env->GetFieldID(jBitmapOptionsClass,
"inPreferredConfig",
"Lorg/beyka/tiffbitmapfactory/TiffBitmapFactory$ImageConfig;");
jobject config = env->GetObjectField(optionsObject, gOptions_PreferedConfigFieldID);
if (inAvailableMemory > 0) {
availableMemory = inAvailableMemory;
}
if (config == NULL) {
LOGI("config is NULL, creating default options");
jclass bitmapConfig = env->FindClass(
"org/beyka/tiffbitmapfactory/TiffBitmapFactory$ImageConfig");
jfieldID argb8888FieldID = env->GetStaticFieldID(bitmapConfig, "ARGB_8888",
"Lorg/beyka/tiffbitmapfactory/TiffBitmapFactory$ImageConfig;");
config = env->GetStaticObjectField(bitmapConfig, argb8888FieldID);
env->DeleteLocalRef(bitmapConfig);
}
preferedConfig = env->NewGlobalRef(config);
env->DeleteLocalRef(config);
jfieldID gOptions_DecodeAreaFieldId = env->GetFieldID(jBitmapOptionsClass, "inDecodeArea",
"Lorg/beyka/tiffbitmapfactory/DecodeArea;");
jobject decodeArea = env->GetObjectField(optionsObject, gOptions_DecodeAreaFieldId);
//if directory number < 0 set it to 0
if (inDirectoryNumber < 0) inDirectoryNumber = 0;
//Open tiff file
LOGIS("nativeTiffOpen", strPath);
const char *strPath = NULL;
if (decodingMode == DECODE_MODE_FILE_DESCRIPTOR) {
image = TIFFFdOpen(jFd, "", "r");
} else if (decodingMode == DECODE_MODE_FILE_PATH) {
strPath = env->GetStringUTFChars(jPath, 0);
image = TIFFOpen(strPath, "r");
}
if (image == NULL) {
if (throwException) {
throwCantOpenFileException();
}
if (decodingMode == DECODE_MODE_FILE_PATH) {
LOGES("Can\'t open bitmap", strPath);
env->ReleaseStringUTFChars(jPath, strPath);
} else {
LOGEI("Can\'t open file descriptor", jFd);
}
return NULL;
} else {
if (decodingMode == DECODE_MODE_FILE_PATH) {
env->ReleaseStringUTFChars(jPath, strPath);
}
}
LOGI("Tiff is open");
TIFFSetDirectory(image, inDirectoryNumber);
TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &origwidth);
TIFFGetField(image, TIFFTAG_IMAGELENGTH, &origheight);
//Read decode bounds if exists
if (decodeArea) {
LOGI("Decode bounds present");
jclass decodeAreaClass = env->FindClass("org/beyka/tiffbitmapfactory/DecodeArea");
jfieldID xFieldID = env->GetFieldID(decodeAreaClass, "x", "I");
jfieldID yFieldID = env->GetFieldID(decodeAreaClass, "y", "I");
jfieldID widthFieldID = env->GetFieldID(decodeAreaClass, "width", "I");
jfieldID heightFieldID = env->GetFieldID(decodeAreaClass, "height", "I");
boundX = env->GetIntField(decodeArea, xFieldID);
boundY = env->GetIntField(decodeArea, yFieldID);
boundWidth = env->GetIntField(decodeArea, widthFieldID);
boundHeight = env->GetIntField(decodeArea, heightFieldID);
if (boundX >= origwidth-1) {
const char *message = "X of left top corner of decode area should be less than image width";
LOGE(*message);
if (throwException) {
throwDecodeFileException(message);
}
env->DeleteLocalRef(decodeAreaClass);
return NULL;
}
if (boundY >= origheight-1) {
const char *message = "Y of left top corner of decode area should be less than image height";
LOGE(*message);
if (throwException) {
throwDecodeFileException(message);
}
env->DeleteLocalRef(decodeAreaClass);
return NULL;
}
if (boundX < 0) boundX = 0;
if (boundY < 0) boundY = 0;
if (boundX + boundWidth >= origwidth) boundWidth = origwidth - boundX -1;
if (boundY + boundHeight >= origheight) boundHeight = origheight - boundY -1;
if (boundWidth < 1) {
const char *message = "Width of decode area can\'t be less than 1";
LOGE(*message);
if (throwException) {
throwDecodeFileException(message);
}
env->DeleteLocalRef(decodeAreaClass);
return NULL;
}
if (boundHeight < 1) {
const char *message = "Height of decode area can\'t be less than 1";
LOGE(*message);
if (throwException) {
throwDecodeFileException(message);
}
env->DeleteLocalRef(decodeAreaClass);
return NULL;
}
LOGII("Decode X", boundX);
LOGII("Decode Y", boundY);
LOGII("Decode width", boundWidth);
LOGII("Decode height", boundHeight);
hasBounds = 1;
env->DeleteLocalRef(decodeAreaClass);
env->DeleteLocalRef(decodeArea);
}
jobject java_bitmap = NULL;
writeDataToOptions(inDirectoryNumber);
if (!inJustDecodeBounds) {
progressTotal = origwidth * origheight;
sendProgress(0, progressTotal);
java_bitmap = createBitmap(inSampleSize, inDirectoryNumber);
}
return java_bitmap;
}
jobject NativeDecoder::createBitmap(int inSampleSize, int directoryNumber)
{
//Read Config from options. Use ordinal field from ImageConfig class
jint configInt = ARGB_8888;
if(preferedConfig) {
jclass configClass = env->FindClass(
"org/beyka/tiffbitmapfactory/TiffBitmapFactory$ImageConfig");
jfieldID ordinalFieldID = env->GetFieldID(configClass, "ordinal", "I");
configInt = env->GetIntField(preferedConfig, ordinalFieldID);
env->DeleteLocalRef(configClass);
}
int bitdepth = 1;
TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitdepth);
if (bitdepth != 1 && bitdepth != 4 && bitdepth != 8 && bitdepth != 16) {
const char * err = "Only 1, 4, 8 and 16 bits per sample are supported";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
int newBitmapWidth = 0;
int newBitmapHeight = 0;
jint *raster = NULL;
if (!hasBounds) {
switch(getDecodeMethod()) {
case DECODE_METHOD_IMAGE:
raster = getSampledRasterFromImage(inSampleSize, &newBitmapWidth, &newBitmapHeight);
break;
case DECODE_METHOD_TILE:
raster = getSampledRasterFromTile(inSampleSize, &newBitmapWidth, &newBitmapHeight);
break;
case DECODE_METHOD_STRIP:
raster = getSampledRasterFromStrip(inSampleSize, &newBitmapWidth, &newBitmapHeight);
break;
}
} else {
switch(getDecodeMethod()) {
case DECODE_METHOD_IMAGE:
raster = getSampledRasterFromImageWithBounds(inSampleSize, &newBitmapWidth, &newBitmapHeight);
break;
case DECODE_METHOD_TILE:
raster = getSampledRasterFromTileWithBounds(inSampleSize, &newBitmapWidth, &newBitmapHeight);
break;
case DECODE_METHOD_STRIP:
raster = getSampledRasterFromStripWithBounds(inSampleSize, &newBitmapWidth, &newBitmapHeight);
break;
}
}
if (raster == NULL) {
return NULL;
}
// Convert ABGR to ARGB
if (invertRedAndBlue) {
int i = 0;
int j = 0;
int tmp = 0;
for (i = 0; i < newBitmapHeight; i++) {
for (j = 0; j < newBitmapWidth; j++) {
tmp = raster[j + newBitmapWidth * i];
raster[j + newBitmapWidth * i] =
(tmp & 0xff000000) | ((tmp & 0x00ff0000) >> 16) | (tmp & 0x0000ff00) |
((tmp & 0xff) << 16);
}
}
}
sendProgress(progressTotal, progressTotal);
if(checkStop()) {
if (raster) {
free(raster);
}
LOGI("Thread stopped");
return NULL;
}
//Class and field for Bitmap.Config
jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
jfieldID bitmapConfigField = NULL;
void *processedBuffer = NULL;
if (configInt == ARGB_8888) {
processedBuffer = raster;
bitmapConfigField = env->GetStaticFieldID(bitmapConfigClass, "ARGB_8888",
"Landroid/graphics/Bitmap$Config;");
} else if (configInt == ALPHA_8) {
processedBuffer = createBitmapAlpha8(raster, newBitmapWidth,
newBitmapHeight);
bitmapConfigField = env->GetStaticFieldID(bitmapConfigClass, "ALPHA_8",
"Landroid/graphics/Bitmap$Config;");
} else if (configInt == RGB_565) {
processedBuffer = createBitmapRGB565(raster, newBitmapWidth,
newBitmapHeight);
bitmapConfigField = env->GetStaticFieldID(bitmapConfigClass, "RGB_565",
"Landroid/graphics/Bitmap$Config;");
}
if (processedBuffer == NULL) {
LOGE("Error while decoding image");
return NULL;
}
//Create mutable bitmap
jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
jmethodID methodid = env->GetStaticMethodID(bitmapClass, "createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
//BitmapConfig
jobject config = env->GetStaticObjectField(bitmapConfigClass, bitmapConfigField);
env->DeleteLocalRef(bitmapConfigClass);
jobject java_bitmap = NULL;
if(checkStop()) {
env->DeleteLocalRef(config);
env->DeleteLocalRef(bitmapClass);
if (processedBuffer) {
free(processedBuffer);
}
LOGI("Thread stopped");
return NULL;
}
if (!useOrientationTag) {
java_bitmap = env->CallStaticObjectMethod(bitmapClass, methodid, newBitmapWidth,
newBitmapHeight, config);
} else if (origorientation > 4) {
java_bitmap = env->CallStaticObjectMethod(bitmapClass, methodid, newBitmapHeight,
newBitmapWidth, config);
} else {
java_bitmap = env->CallStaticObjectMethod(bitmapClass, methodid, newBitmapWidth,
newBitmapHeight, config);
}
//remove not used references
env->DeleteLocalRef(config);
env->DeleteLocalRef(bitmapClass);
//Copy data to bitmap
int ret;
void *bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, java_bitmap, &bitmapPixels)) < 0) {
//error
LOGE("Lock pixels failed");
return NULL;
}
int pixelsCount = newBitmapWidth * newBitmapHeight;
if (configInt == ARGB_8888) {
memcpy(bitmapPixels, (jint *) processedBuffer, sizeof(jint) * pixelsCount);
} else if (configInt == ALPHA_8) {
memcpy(bitmapPixels, (jbyte *) processedBuffer, sizeof(jbyte) * pixelsCount);
} else if (configInt == RGB_565) {
memcpy(bitmapPixels, (unsigned short *) processedBuffer,
sizeof(unsigned short) * pixelsCount);
}
AndroidBitmap_unlockPixels(env, java_bitmap);
//remove array
free(processedBuffer);
return java_bitmap;
}
jint * NativeDecoder::getSampledRasterFromStrip(int inSampleSize, int *bitmapwidth, int *bitmapheight) {
//init signal handler for catch SIGSEGV error that could be raised in libtiff
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = stripErrorHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if(sigaction(SIGSEGV, &act, 0) < 0) {
LOGE("Can\'t setup signal handler. Working without errors catching mechanism");
}
LOGII("width", origwidth);
LOGII("height", origheight);
jint *pixels = NULL;
*bitmapwidth = origwidth / inSampleSize;
*bitmapheight = origheight / inSampleSize;
uint32 pixelsBufferSize = *bitmapwidth * *bitmapheight;
int origImageBufferSize = origwidth * origheight;
LOGII("new width", *bitmapwidth);
LOGII("new height", *bitmapheight);
uint32 stripSize = TIFFStripSize (image);
uint32 stripMax = TIFFNumberOfStrips (image);
LOGII("strip size ", stripSize);
LOGII("stripMax ", stripMax);
int rowPerStrip = -1;
TIFFGetField(image, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
LOGII("rowsperstrip", rowPerStrip);
unsigned long estimateMem = 0;
estimateMem += (sizeof(jint) * pixelsBufferSize); //buffer for decoded pixels
estimateMem += (origwidth * sizeof(uint32)); //work line for rotate strip
estimateMem += (origwidth * rowPerStrip * sizeof (uint32) * 2); //current and next strips
estimateMem += (sizeof(jint) * origwidth * 2); //bottom and top lines for reading pixel(matrixBottomLine, matrixTopLine)
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
pixels = (jint *) malloc(sizeof(jint) * pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
}
uint32* work_line_buf = (uint32 *)_TIFFmalloc(origwidth * sizeof(uint32));
uint32* raster;
uint32* rasterForBottomLine; // in this raster copy next strip for getting bottom line in matrix color selection
if (rowPerStrip == -1 && stripMax == 1) {
raster = (uint32 *)_TIFFmalloc(origImageBufferSize * sizeof (uint32));
rasterForBottomLine = (uint32 *)_TIFFmalloc(origImageBufferSize * sizeof (uint32));
} else {
raster = (uint32 *)_TIFFmalloc(origwidth * rowPerStrip * sizeof (uint32));
rasterForBottomLine = (uint32 *)_TIFFmalloc(origwidth * rowPerStrip * sizeof (uint32));
}
if (rowPerStrip == -1) {
rowPerStrip = origheight;
}
int writedLines = 0;
int nextStripOffset = 0;
int globalLineCounter = 0;
unsigned int *matrixTopLine = (uint32 *) malloc(sizeof(jint) * origwidth);
unsigned int *matrixBottomLine = (uint32 *) malloc(sizeof(jint) * origwidth);
int isSecondRasterExist = 0;
int ok = 1;
uint32 rows_to_write = 0;
//check for error
if (setjmp(NativeDecoder::strip_buf)) {
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (rasterForBottomLine) {
_TIFFfree(rasterForBottomLine);
rasterForBottomLine = NULL;
}
if (matrixTopLine) {
_TIFFfree(matrixTopLine);
matrixTopLine = NULL;
}
if (matrixBottomLine) {
_TIFFfree(matrixBottomLine);
matrixBottomLine = NULL;
}
const char * err = "Caught SIGSEGV signal(Segmentation fault or invalid memory reference)";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
for (int i = 0; i < stripMax*rowPerStrip; i += rowPerStrip) {
sendProgress(i * origwidth, progressTotal);
//if second raster is exist - copy it to work raster end decode next strip
if (isSecondRasterExist) {
_TIFFmemcpy(raster, rasterForBottomLine, origwidth * rowPerStrip * sizeof (uint32));
//If next strip is exist - decode it, invert lines
if (i + rowPerStrip < stripMax*rowPerStrip) {
TIFFReadRGBAStrip(image, i+rowPerStrip, rasterForBottomLine);
isSecondRasterExist = 1;
rows_to_write = 0;
if ( i + rowPerStrip * 2 > origheight )
rows_to_write = origheight - i - rowPerStrip;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = rasterForBottomLine + origwidth * line;
bottom_line = rasterForBottomLine + origwidth * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * origwidth);
}
}
} else {
isSecondRasterExist = 0;
}
} else {
//if second raster is not exist - first processing - read first and second raster
TIFFReadRGBAStrip(image, i, raster);
//invert lines, because libtiff origin is bottom left instead of top left
rows_to_write = 0;
if( i + rowPerStrip > origheight )
rows_to_write = origheight - i;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = raster + origwidth * line;
bottom_line = raster + origwidth * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * origwidth);
}
}
//if next strip is exist - read it and invert lines
if (i + rowPerStrip < origheight) {
TIFFReadRGBAStrip(image, i+rowPerStrip, rasterForBottomLine);
isSecondRasterExist = 1;
//invert lines, because libtiff origin is bottom left instead of top left
rows_to_write = 0;
if ( i + rowPerStrip * 2 > origheight )
rows_to_write = origheight - i - rowPerStrip;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = rasterForBottomLine + origwidth * line;
bottom_line = rasterForBottomLine + origwidth * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * origwidth);
}
}
}
}
if (inSampleSize == 1) {
int byteToCopy = 0;
if (i + rowPerStrip < origheight) {
byteToCopy = sizeof(unsigned int) * rowPerStrip * origwidth;
} else {
byteToCopy = sizeof(unsigned int) * rows_to_write * origwidth;
}
int position = i * origwidth;
memcpy(&pixels[position], raster, byteToCopy);
//sendProgress(position, progressTotal);
} else {
if (isSecondRasterExist) {
_TIFFmemcpy(matrixBottomLine, rasterForBottomLine /*+ lineAddrToCopyBottomLine * origwidth*/, sizeof(unsigned int) * origwidth);
}
int workWritedLines = writedLines;
for (int resBmpY = workWritedLines, workY = 0; resBmpY < *bitmapheight && workY < rowPerStrip; /*wj++,*/ workY ++/*= inSampleSize*/) {
if (checkStop()) {
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (rasterForBottomLine) {
_TIFFfree(rasterForBottomLine);
rasterForBottomLine = NULL;
}
if (matrixTopLine) {
_TIFFfree(matrixTopLine);
matrixTopLine = NULL;
}
if (matrixBottomLine) {
_TIFFfree(matrixBottomLine);
matrixBottomLine = NULL;
}
LOGI("Thread stopped");
return NULL;
}
// if total line of source image is equal to inSampleSize*N then process this line
if (globalLineCounter % inSampleSize == 0) {
for (int resBmpX = 0, workX = 0; resBmpX < *bitmapwidth; resBmpX++, workX += inSampleSize) {
//Apply filter to pixel
jint crPix = raster[workY * origwidth + workX];
int sum = 1;
int alpha = colorMask & crPix >> 24;
int red = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int blue = colorMask & crPix;
//topleft
if (workX - 1 >= 0 && workY - 1 >= 0) {
crPix = raster[(workY - 1) * origwidth + workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX - 1 >= 0 && workY - 1 == -1 && globalLineCounter > 0) {
crPix = matrixTopLine[workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//top
if (workY - 1 >= 0) {
crPix = raster[(workY - 1) * origwidth + workX];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workY - 1 == -1 && globalLineCounter > 0) {
crPix = matrixTopLine[workX];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
// topright
if (workX + 1 < origwidth && workY - 1 >= 0) {
crPix = raster[(workY - 1) * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX + 1 < origwidth && workY - 1 == -1 && globalLineCounter > 0) {
crPix = matrixTopLine[workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//right
if (workX + 1 < origwidth) {
crPix = raster[workY * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomright
if (workX + 1 < origwidth && workY + 1 < rowPerStrip) {
crPix = raster[(workY + 1) * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX + 1 < origwidth && workY + 1 == rowPerStrip && isSecondRasterExist) {
crPix = matrixBottomLine[workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottom
if (workY + 1 < rowPerStrip) {
crPix = raster[(workY + 1) * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workY + 1 == rowPerStrip && isSecondRasterExist) {
crPix = matrixBottomLine[workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomleft
if (workX - 1 >= 0 && workY + 1 < rowPerStrip) {
crPix = raster[(workY + 1) * origwidth + workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX - 1 >= 0 && workY + 1 == rowPerStrip && isSecondRasterExist) {
crPix = matrixBottomLine[workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//left
if (workX - 1 >= 0) {
crPix = raster[workY * origwidth + workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
red /= sum;
if (red > 255) red = 255;
if (red < 0) red = 0;
green /= sum;
if (green > 255) green = 255;
if (green < 0) green = 0;
blue /= sum;
if (blue > 255) blue = 255;
if (blue < 0) blue = 0;
alpha /= sum;///= sum;
if (alpha > 255) alpha = 255;
if (alpha < 0) alpha = 0;
crPix = (alpha << 24) | (red << 16) | (green << 8) | (blue);
pixels[resBmpY * *bitmapwidth + resBmpX] = crPix;
}
//if line was processed - increment counter of lines that was writed to result image
writedLines++;
//and incremetncounter of current Y for writing
resBmpY++;
}
if (workY == rowPerStrip - 1 && i + rowPerStrip < origheight) {
_TIFFmemcpy(matrixTopLine, raster + workY * origwidth, sizeof(unsigned int) * origwidth);
}
//incremetn global source image line counter
globalLineCounter++;
}
}
}
LOGI("Decoding finished. Free memmory");
//Close Buffers
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (rasterForBottomLine) {
_TIFFfree(rasterForBottomLine);
rasterForBottomLine = NULL;
}
if (matrixTopLine) {
_TIFFfree(matrixTopLine);
matrixTopLine = NULL;
}
if (matrixBottomLine) {
_TIFFfree(matrixBottomLine);
matrixBottomLine = NULL;
}
if (useOrientationTag) {
uint32 buf;
//fixOrientation(pixels, pixelsBufferSize, *bitmapwidth, *bitmapheight);
switch(origorientation) {
case ORIENTATION_TOPLEFT:
case ORIENTATION_TOPRIGHT:
break;
case ORIENTATION_BOTRIGHT:
case ORIENTATION_BOTLEFT:
flipPixelsVertical(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_LEFTTOP:
rotateRaster(pixels, 90, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
case ORIENTATION_RIGHTTOP:
rotateRaster(pixels, 270, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
case ORIENTATION_RIGHTBOT:
rotateRaster(pixels, 90, bitmapwidth, bitmapheight);
buf= *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
case ORIENTATION_LEFTBOT:
rotateRaster(pixels, 270, bitmapwidth, bitmapheight);
buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
}
} else if (origorientation == 2 || origorientation == 3 || origorientation == 6 || origorientation == 7) {
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
}
return pixels;
}
jint * NativeDecoder::getSampledRasterFromStripWithBounds(int inSampleSize, int *bitmapwidth, int *bitmapheight) {
//init signal handler for catch SIGSEGV error that could be raised in libtiff
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = stripErrorHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if(sigaction(SIGSEGV, &act, 0) < 0) {
LOGE("Can\'t setup signal handler. Working without errors catching mechanism");
}
LOGII("width", origwidth);
LOGII("height", origheight);
jint *pixels = NULL;
*bitmapwidth = origwidth / inSampleSize;
*bitmapheight = boundHeight / inSampleSize;//origheight / inSampleSize;
uint32 pixelsBufferSize = *bitmapwidth * *bitmapheight;
int origImageBufferSize = origwidth * origheight;
LOGII("new width", *bitmapwidth);
LOGII("new height", *bitmapheight);
uint32 stripSize = TIFFStripSize (image);
uint32 stripMax = TIFFNumberOfStrips (image);
LOGII("strip size ", stripSize);
LOGII("stripMax ", stripMax);
int rowPerStrip = -1;
TIFFGetField(image, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
LOGII("rowsperstrip", rowPerStrip);
unsigned long estimateMem = 0;
estimateMem += (sizeof(jint) * pixelsBufferSize); //temp buffer for decoded pixels
estimateMem += (sizeof(jint) * (boundWidth / inSampleSize) * (boundHeight/inSampleSize)); //final buffer that will store original image
estimateMem += (origwidth * sizeof(uint32)); //work line for rotate strip
estimateMem += (origwidth * rowPerStrip * sizeof (uint32) * 2); //current and next strips
estimateMem += (sizeof(jint) * origwidth * 2); //bottom and top lines for reading pixel(matrixBottomLine, matrixTopLine)
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
progressTotal = pixelsBufferSize + (boundWidth/inSampleSize) * (boundHeight / inSampleSize);
sendProgress(0, progressTotal);
jlong processedProgress = 0;
pixels = (jint *) malloc(sizeof(jint) * pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
}
uint32* work_line_buf = (uint32 *)_TIFFmalloc(origwidth * sizeof(uint32));
uint32* raster;
uint32* rasterForBottomLine; // in this raster copy next strip for getting bottom line in matrix color selection
if (rowPerStrip == -1 && stripMax == 1) {
raster = (uint32 *)_TIFFmalloc(origImageBufferSize * sizeof (uint32));
rasterForBottomLine = (uint32 *)_TIFFmalloc(origImageBufferSize * sizeof (uint32));
} else {
raster = (uint32 *)_TIFFmalloc(origwidth * rowPerStrip * sizeof (uint32));
rasterForBottomLine = (uint32 *)_TIFFmalloc(origwidth * rowPerStrip * sizeof (uint32));
}
if (rowPerStrip == -1) {
rowPerStrip = origheight;
}
int writedLines = 0;
int nextStripOffset = 0;
int globalLineCounter = 0;
unsigned int *matrixTopLine = (uint32 *) malloc(sizeof(jint) * origwidth);
unsigned int *matrixBottomLine = (uint32 *) malloc(sizeof(jint) * origwidth);
int isSecondRasterExist = 0;
int ok = 1;
uint32 rows_to_write = 0;
//check for error
if (setjmp(NativeDecoder::strip_buf)) {
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (rasterForBottomLine) {
_TIFFfree(rasterForBottomLine);
rasterForBottomLine = NULL;
}
if (matrixTopLine) {
_TIFFfree(matrixTopLine);
matrixTopLine = NULL;
}
if (matrixBottomLine) {
_TIFFfree(matrixBottomLine);
matrixBottomLine = NULL;
}
const char * err = "Caught SIGSEGV signal(Segmentation fault or invalid memory reference)";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
for (int i = 0; (i < stripMax*rowPerStrip || i > boundY + boundHeight) ; i += rowPerStrip) {
if (i + rowPerStrip <= boundY) {
continue;
}
if (i > boundY + boundHeight) {
break;
}
sendProgress(processedProgress * *bitmapwidth, progressTotal);
processedProgress += rowPerStrip/inSampleSize;
//if second raster is exist - copy it to work raster end decode next strip
if (isSecondRasterExist) {
_TIFFmemcpy(raster, rasterForBottomLine, origwidth * rowPerStrip * sizeof (uint32));
//If next strip is exist - decode it, invert lines
if (i + rowPerStrip < stripMax*rowPerStrip) {
TIFFReadRGBAStrip(image, i+rowPerStrip, rasterForBottomLine);
isSecondRasterExist = 1;
rows_to_write = 0;
if ( i + rowPerStrip * 2 > origheight )
rows_to_write = origheight - i - rowPerStrip;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = rasterForBottomLine + origwidth * line;
bottom_line = rasterForBottomLine + origwidth * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * origwidth);
}
}
} else {
isSecondRasterExist = 0;
}
} else {
//if second raster is not exist - first processing - read first and second raster
TIFFReadRGBAStrip(image, i, raster);
//invert lines, because libtiff origin is bottom left instead of top left
rows_to_write = 0;
if( i + rowPerStrip > origheight )
rows_to_write = origheight - i;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = raster + origwidth * line;
bottom_line = raster + origwidth * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * origwidth);
}
}
//if next strip is exist - read it and invert lines
if (i + rowPerStrip < origheight) {
TIFFReadRGBAStrip(image, i+rowPerStrip, rasterForBottomLine);
isSecondRasterExist = 1;
//invert lines, because libtiff origin is bottom left instead of top left
rows_to_write = 0;
if ( i + rowPerStrip * 2 > origheight )
rows_to_write = origheight - i - rowPerStrip;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = rasterForBottomLine + origwidth * line;
bottom_line = rasterForBottomLine + origwidth * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * origwidth);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * origwidth);
}
}
}
}
/*if (inSampleSize == 1) {
int byteToCopy = 0;
if (i + rowPerStrip < origheight) {
byteToCopy = sizeof(unsigned int) * rowPerStrip * origwidth;
} else {
byteToCopy = sizeof(unsigned int) * rows_to_write * origwidth;
}
int position = i * origwidth;
memcpy(&pixels[position], raster, byteToCopy);
//sendProgress(position, progressTotal);
} else {*/
if (isSecondRasterExist) {
_TIFFmemcpy(matrixBottomLine, rasterForBottomLine /*+ lineAddrToCopyBottomLine * origwidth*/, sizeof(unsigned int) * origwidth);
}
int workWritedLines = writedLines;
for (int resBmpY = workWritedLines, workY = 0; resBmpY < *bitmapheight && workY < rowPerStrip; /*wj++,*/ workY ++/*= inSampleSize*/) {
if (checkStop()) {
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (rasterForBottomLine) {
_TIFFfree(rasterForBottomLine);
rasterForBottomLine = NULL;
}
if (matrixTopLine) {
_TIFFfree(matrixTopLine);
matrixTopLine = NULL;
}
if (matrixBottomLine) {
_TIFFfree(matrixBottomLine);
matrixBottomLine = NULL;
}
LOGI("Thread stopped");
return NULL;
}
// if total line of source image is equal to inSampleSize*N then process this line
if (globalLineCounter % inSampleSize == 0) {
for (int resBmpX = 0, workX = 0; resBmpX < *bitmapwidth; workX += inSampleSize) {
/*if (workX <= boundX) {
continue;
}
if (workX > boundX + boundWidth) {
break;
}
LOGII("J", workX);*/
//Apply filter to pixel
jint crPix = raster[workY * origwidth + workX];
int sum = 1;
int alpha = colorMask & crPix >> 24;
int red = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int blue = colorMask & crPix;
//topleft
if (workX - 1 >= 0 && workY - 1 >= 0) {
crPix = raster[(workY - 1) * origwidth + workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX - 1 >= 0 && workY - 1 == -1 && globalLineCounter > 0) {
crPix = matrixTopLine[workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//top
if (workY - 1 >= 0) {
crPix = raster[(workY - 1) * origwidth + workX];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workY - 1 == -1 && globalLineCounter > 0) {
crPix = matrixTopLine[workX];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
// topright
if (workX + 1 < origwidth && workY - 1 >= 0) {
crPix = raster[(workY - 1) * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX + 1 < origwidth && workY - 1 == -1 && globalLineCounter > 0) {
crPix = matrixTopLine[workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//right
if (workX + 1 < origwidth) {
crPix = raster[workY * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomright
if (workX + 1 < origwidth && workY + 1 < rowPerStrip) {
crPix = raster[(workY + 1) * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX + 1 < origwidth && workY + 1 == rowPerStrip && isSecondRasterExist) {
crPix = matrixBottomLine[workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottom
if (workY + 1 < rowPerStrip) {
crPix = raster[(workY + 1) * origwidth + workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workY + 1 == rowPerStrip && isSecondRasterExist) {
crPix = matrixBottomLine[workX + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomleft
if (workX - 1 >= 0 && workY + 1 < rowPerStrip) {
crPix = raster[(workY + 1) * origwidth + workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
} else if (workX - 1 >= 0 && workY + 1 == rowPerStrip && isSecondRasterExist) {
crPix = matrixBottomLine[workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//left
if (workX - 1 >= 0) {
crPix = raster[workY * origwidth + workX - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
red /= sum;
if (red > 255) red = 255;
if (red < 0) red = 0;
green /= sum;
if (green > 255) green = 255;
if (green < 0) green = 0;
blue /= sum;
if (blue > 255) blue = 255;
if (blue < 0) blue = 0;
alpha /= sum;///= sum;
if (alpha > 255) alpha = 255;
if (alpha < 0) alpha = 0;
crPix = (alpha << 24) | (red << 16) | (green << 8) | (blue);
pixels[resBmpY * *bitmapwidth + resBmpX] = crPix;
resBmpX++;
}
//if line was processed - increment counter of lines that was writed to result image
writedLines++;
//and incremetncounter of current Y for writing
resBmpY++;
}
if (workY == rowPerStrip - 1 && i + rowPerStrip < origheight) {
_TIFFmemcpy(matrixTopLine, raster + workY * origwidth, sizeof(unsigned int) * origwidth);
}
//incremetn global source image line counter
globalLineCounter++;
}
/*}*/
}
LOGI("Decoding finished. Free memmory");
//Close Buffers
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (rasterForBottomLine) {
_TIFFfree(rasterForBottomLine);
rasterForBottomLine = NULL;
}
if (matrixTopLine) {
_TIFFfree(matrixTopLine);
matrixTopLine = NULL;
}
if (matrixBottomLine) {
_TIFFfree(matrixBottomLine);
matrixBottomLine = NULL;
}
processedProgress *= *bitmapwidth;
if (useOrientationTag) {
uint32 buf;
switch(origorientation) {
case ORIENTATION_TOPLEFT:
case ORIENTATION_TOPRIGHT:
break;
case ORIENTATION_BOTRIGHT:
case ORIENTATION_BOTLEFT:
flipPixelsVertical(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_LEFTTOP:
rotateRaster(pixels, 90, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
case ORIENTATION_RIGHTTOP:
rotateRaster(pixels, 270, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
case ORIENTATION_RIGHTBOT:
rotateRaster(pixels, 90, bitmapwidth, bitmapheight);
buf= *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
case ORIENTATION_LEFTBOT:
rotateRaster(pixels, 270, bitmapwidth, bitmapheight);
buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
break;
}
} else if (origorientation == 2 || origorientation == 3 || origorientation == 6 || origorientation == 7) {
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
}
uint32 tmpPixelBufferSize = (boundWidth / inSampleSize) * (boundHeight / inSampleSize);
estimateMem = (sizeof(jint) * pixelsBufferSize); //temp buffer for decoded pixels
estimateMem += (sizeof(jint) * tmpPixelBufferSize); //final buffer that will store original image
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
jint* tmpPixels = (jint *) malloc(sizeof(jint) * tmpPixelBufferSize);
uint32 startPosX = 0;
if (useOrientationTag && (origorientation == ORIENTATION_TOPRIGHT || origorientation == ORIENTATION_BOTRIGHT
|| origorientation == ORIENTATION_LEFTBOT || origorientation == ORIENTATION_RIGHTBOT)) {
startPosX = *bitmapwidth - boundX/inSampleSize;
for (int ox = startPosX, nx = 0; nx < boundWidth/inSampleSize; ox--, nx++) {
sendProgress(processedProgress + nx * boundWidth/inSampleSize, progressTotal);
for (int oy = 0, ny = 0; ny < boundHeight/inSampleSize; oy++, ny++) {
if (useOrientationTag && (origorientation > 4)) {
tmpPixels[nx * (boundHeight/inSampleSize) + ny] = pixels[ox * *bitmapheight + oy];
} else {
tmpPixels[ny * (boundWidth/inSampleSize) + nx] = pixels[oy * *bitmapwidth + ox];
}
}
}
} else {
startPosX = boundX/inSampleSize;
for (int ox = startPosX, nx = 0; nx < boundWidth/inSampleSize; ox++, nx++) {
sendProgress(processedProgress + nx * boundWidth/inSampleSize, progressTotal);
for (int oy = 0, ny = 0; ny < boundHeight/inSampleSize; oy++, ny++) {
if (useOrientationTag && (origorientation > 4)) {
tmpPixels[nx * (boundHeight/inSampleSize) + ny] = pixels[ox * *bitmapheight + oy];
} else {
tmpPixels[ny * (boundWidth/inSampleSize) + nx] = pixels[oy * *bitmapwidth + ox];
}
}
}
}
free(pixels);
pixels = tmpPixels;
*bitmapwidth = boundWidth/inSampleSize;
*bitmapheight = boundHeight/inSampleSize;
return pixels;
}
void NativeDecoder::rotateTileLinesVertical(uint32 tileHeight, uint32 tileWidth, uint32* whatRotate, uint32 *bufferLine) {
for (int line = 0; line < tileHeight / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = whatRotate + tileWidth * line;
bottom_line = whatRotate + tileWidth * (tileHeight - line -1);
_TIFFmemcpy(bufferLine, top_line, sizeof(unsigned int) * tileWidth);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * tileWidth);
_TIFFmemcpy(bottom_line, bufferLine, sizeof(unsigned int) * tileWidth);
}
}
void NativeDecoder::rotateTileLinesHorizontal(uint32 tileHeight, uint32 tileWidth, uint32* whatRotate, uint32 *bufferLine) {
uint32 buf;
for (int y = 0; y < tileHeight; y++) {
for (int x = 0; x < tileWidth / 2; x++) {
buf = whatRotate[y * tileWidth + x];
whatRotate[y * tileWidth + x] = whatRotate[y * tileWidth + tileWidth - x - 1];
whatRotate[y * tileWidth + tileWidth - x - 1] = buf;
}
}
}
jint * NativeDecoder::getSampledRasterFromTile(int inSampleSize, int *bitmapwidth, int *bitmapheight) {
//init signal handler for catch SIGSEGV error that could be raised in libtiff
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = tileErrorHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if(sigaction(SIGSEGV, &act, 0) < 0) {
LOGE("Can\'t setup signal handler. Working without errors catching mechanism");
}
jint *pixels = NULL;
*bitmapwidth = origwidth / inSampleSize;
*bitmapheight = origheight / inSampleSize;
uint32 pixelsBufferSize = *bitmapwidth * *bitmapheight;
uint32 tileWidth = 0, tileHeight = 0;
TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileHeight);
unsigned long estimateMem = 0;
estimateMem += (sizeof(jint) * pixelsBufferSize); //buffer for decoded pixels
estimateMem += (tileWidth * tileHeight * sizeof(uint32)) * 3; //current, left and right tiles buffers
estimateMem += (tileWidth * sizeof(uint32)); //work line for rotate tile
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
pixels = (jint *) malloc(sizeof(jint) * pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
}
uint32 row, column;
//main worker tile
uint32 *rasterTile = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
//left tile
uint32 *rasterTileLeft = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
//right tile
uint32 *rasterTileRight = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
uint32 *work_line_buf = (uint32*)_TIFFmalloc(tileWidth * sizeof (uint32));
//this variable calculate processed pixels for x and y direction to make right offsets at the begining of next tile
//offset calculated from condition globalProcessed % inSampleSize should be 0
uint32 globalProcessedX = 0;
uint32 globalProcessedY = 0;
//check for error
if (setjmp(NativeDecoder::tile_buf)) {
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (rasterTileLeft) {
_TIFFfree(rasterTileLeft);
rasterTileLeft = NULL;
}
if (rasterTileRight) {
_TIFFfree(rasterTileRight);
rasterTileRight = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
const char * err = "Caught SIGSEGV signal(Segmentation fault or invalid memory reference)";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
for (row = 0; row < origheight; row += tileHeight) {
short leftTileExists = 0;
short rightTileExists = 0;
for (column = 0; column < origwidth; column += tileWidth) {
sendProgress(row * origwidth + column, progressTotal);
//If not first column - we should have previous tile - copy it to left tile buffer
if (column != 0) {
_TIFFmemcpy(rasterTileLeft, rasterTile, tileWidth * tileHeight * sizeof(uint32));
leftTileExists = 1;
} else {
leftTileExists = 0;
}
//if current column + tile width is less than origin width - we have right tile - copy it to current tile and read next tile to rasterTileRight buffer
if (column + tileWidth < origwidth && rightTileExists) {
_TIFFmemcpy(rasterTile, rasterTileRight, tileWidth * tileHeight * sizeof(uint32));
TIFFReadRGBATile(image, column + tileWidth, row, rasterTileRight);
rightTileExists = 1;
} else if (column + tileWidth < origwidth) {
//have right tile but this is first tile in row, so need to read raster and right raster
TIFFReadRGBATile(image, column + tileWidth, row, rasterTileRight);
TIFFReadRGBATile(image, column, row, rasterTile);
rightTileExists = 1;
//in that case we also need to invert lines in rasterTile
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
}
} else {
//otherwise we haven't right tile buffer, so we should read tile to current buffer
TIFFReadRGBATile(image, column, row, rasterTile);
rightTileExists = 0;
}
//if we have right tile - current tile already rotated and we need to rotate only right tile
if (rightTileExists) {
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTileRight, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTileRight, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTileRight, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTileRight, work_line_buf);
break;
}
} else {
//otherwise - current tile not rotated so rotate it
//tile orig is on bottom left - should change lines
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
}
}
if (inSampleSize > 1 )
{
//Tile could begin from not filled pixel(pixel[x,y] == 0). This variables allow to calculate begining of filled pixels
int tileStartDataX = -1;
int tileStartDataY = -1;
for (int origTileY = 0, pixY = row/inSampleSize; origTileY < tileHeight && pixY < *bitmapheight; origTileY++) {
if (checkStop()) {
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (rasterTileLeft) {
_TIFFfree(rasterTileLeft);
rasterTileLeft = NULL;
}
if (rasterTileRight) {
_TIFFfree(rasterTileRight);
rasterTileRight = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
LOGI("Thread stopped");
return NULL;
}
if (tileStartDataY != -1 && globalProcessedY % inSampleSize != 0) {
if (tileStartDataY != -1) {
globalProcessedY++;
}
}
else
{
for (int origTileX = 0, pixX = column/inSampleSize; origTileX < tileWidth && pixX < *bitmapwidth; origTileX++) {
if (tileStartDataX != -1 && globalProcessedX % inSampleSize != 0)
{
if (tileStartDataX != -1) {
globalProcessedX++;
}
}
else
{
uint32 srcPosition = origTileY * tileWidth + origTileX;
if (rasterTile[srcPosition] != 0) {
if (tileStartDataX == -1) {
tileStartDataX = origTileX;
}
if (tileStartDataY == -1) {
tileStartDataY = origTileY;
}
//Apply filter to pixel
jint crPix = rasterTile[srcPosition];//origBuffer[j1 * origwidth + i1];
int sum = 1;
int alpha = colorMask & crPix >> 24;
int red = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int blue = colorMask & crPix;
//using kernel 3x3
//topleft
if (origTileX - 1 >= 0 && origTileY - 1 >= 0) {
crPix = rasterTile[(origTileY - 1) * tileWidth + origTileX - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY - 1 >= 0 && leftTileExists) {
crPix = rasterTileLeft[(origTileY - 1) * tileWidth + tileWidth - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//top
if (origTileY - 1 >= 0) {
crPix = rasterTile[(origTileY - 1) * tileWidth + origTileX];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
// topright
if (origTileX + 1 < tileWidth && origTileY - 1 >= 0) {
crPix = rasterTile[(origTileY - 1) * tileWidth + origTileX + 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY - 1 >= 0 && rightTileExists) {
crPix = rasterTileRight[(origTileY - 1) * tileWidth];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//right
if (origTileX + 1 < tileWidth) {
crPix = rasterTile[origTileY * tileWidth + origTileX + 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (rightTileExists) {
crPix = rasterTileRight[origTileY * tileWidth];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//bottomright
if (origTileX + 1 < tileWidth && origTileY + 1 < tileHeight) {
crPix = rasterTile[(origTileY + 1) * tileWidth + origTileX + 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY + 1 < tileHeight && rightTileExists) {
crPix = rasterTileRight[(origTileY + 1) * tileWidth];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//bottom
if (origTileY + 1 < tileHeight) {
crPix = rasterTile[(origTileY + 1) * tileWidth + origTileX];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//bottomleft
if (origTileX - 1 >= 0 && origTileY + 1 < tileHeight) {
crPix = rasterTile[(origTileY + 1) * tileWidth + origTileX - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY + 1 < tileHeight && leftTileExists) {
crPix = rasterTileLeft[(origTileY + 1) * tileWidth + tileWidth - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//left
if (origTileX - 1 >= 0) {
crPix = rasterTile[origTileY * tileWidth + origTileX - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (leftTileExists) {
crPix = rasterTileLeft[origTileY * tileWidth + tileWidth - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
red /= sum;
if (red > 255) red = 255;
if (red < 0) red = 0;
green /= sum;
if (green > 255) green = 255;
if (green < 0) green = 0;
blue /= sum;
if (blue > 255) blue = 255;
if (blue < 0) blue = 0;
alpha /= sum;///= sum;
if (alpha > 255) alpha = 255;
if (alpha < 0) alpha = 0;
crPix = (alpha << 24) | (red << 16) | (green << 8) | (blue);
int position;
if (origorientation <= 4) {
position = pixY * *bitmapwidth + pixX;
} else {
position = pixX * *bitmapheight + pixY;
}
pixels[position] = crPix;
} else {
if (tileStartDataX != -1) tileStartDataX = -1;
if (tileStartDataY != -1) tileStartDataY = -1;
}
if (tileStartDataX != -1) {
pixX++;
globalProcessedX++;
}
}
}
if (tileStartDataY != -1) {
pixY++;
globalProcessedY++;
}
}
}
} else {
int rowHasPixels = 0;
for (int th = 0, bh = 0; th < tileHeight; th++) {
for (int tw = 0, bw = 0; tw < tileWidth; tw++) {
uint32 srcPosition = th * tileWidth + tw;
if (rasterTile[srcPosition] != 0) {
int position = 0;
if (origorientation <= 4) {
position = (row + bh) * *bitmapwidth + column + bw;
} else {
position = (column + bw) * *bitmapheight + row + bh;
}
pixels[position] = rasterTile[srcPosition];
rowHasPixels = 1;
bw++;
}
}
if (rowHasPixels) {
bh++;
rowHasPixels = 0;
}
}
}
}
}
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (rasterTileLeft) {
_TIFFfree(rasterTileLeft);
rasterTileLeft = NULL;
}
if (rasterTileRight) {
_TIFFfree(rasterTileRight);
rasterTileRight = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
if (useOrientationTag) {
switch (origorientation) {
case ORIENTATION_TOPLEFT:
case ORIENTATION_LEFTTOP:
break;
case ORIENTATION_TOPRIGHT:
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_RIGHTTOP:
flipPixelsHorizontal(*bitmapheight, *bitmapwidth, pixels);
break;
case ORIENTATION_BOTRIGHT:
case ORIENTATION_RIGHTBOT:
rotateRaster(pixels, 180, bitmapwidth, bitmapheight);
break;
case ORIENTATION_BOTLEFT:
flipPixelsVertical(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_LEFTBOT:
flipPixelsVertical(*bitmapheight, *bitmapwidth, pixels);
break;
}
} else {
if (origorientation > 4) {
uint32 buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
rotateRaster(pixels, 90, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
}
}
return pixels;
}
jint * NativeDecoder::getSampledRasterFromTileWithBounds(int inSampleSize, int *bitmapwidth, int *bitmapheight) {
//init signal handler for catch SIGSEGV error that could be raised in libtiff
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = tileErrorHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if(sigaction(SIGSEGV, &act, 0) < 0) {
LOGE("Can\'t setup signal handler. Working without errors catching mechanism");
}
//First read all tiles that are on necessary area
uint32 tileWidth = 0, tileHeight = 0;
TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileHeight);
//find first and last tile to process
uint32 firstTileX = (uint32)(boundX / tileWidth);
uint32 firstTileY = (uint32)(boundY / tileHeight);
uint32 lastTileX = (uint32)((boundX + boundWidth) / tileWidth) + 1;
uint32 lastTileY = (uint32)((boundY + boundHeight) / tileHeight) + 1;
jint *pixels = NULL;
*bitmapwidth = /*boundWidth*/ (lastTileX - firstTileX) * tileWidth / inSampleSize;//origwidth / inSampleSize;
*bitmapheight = /*boundHeight*/ (lastTileY - firstTileY) * tileHeight / inSampleSize;//origheight / inSampleSize;
uint32 pixelsBufferSize = *bitmapwidth * *bitmapheight;
unsigned long estimateMem = 0;
estimateMem += (sizeof(jint) * pixelsBufferSize); //buffer for decoded pixels
estimateMem += (tileWidth * tileHeight * sizeof(uint32)) * 3; //current, left and right tiles buffers
estimateMem += (tileWidth * sizeof(uint32)); //work line for rotate tile
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
pixels = (jint *) malloc(sizeof(jint) * pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
}
progressTotal = pixelsBufferSize + (boundWidth/inSampleSize) * (boundHeight/inSampleSize);
sendProgress(0, progressTotal);
jlong processedProgress = 0;
uint32 row, column, rowDest, columnDest;
//main worker tile
uint32 *rasterTile = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
//left tile
uint32 *rasterTileLeft = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
//right tile
uint32 *rasterTileRight = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
uint32 *work_line_buf = (uint32*)_TIFFmalloc(tileWidth * sizeof (uint32));
//check for error
if (setjmp(NativeDecoder::tile_buf)) {
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (rasterTileLeft) {
_TIFFfree(rasterTileLeft);
rasterTileLeft = NULL;
}
if (rasterTileRight) {
_TIFFfree(rasterTileRight);
rasterTileRight = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
const char * err = "Caught SIGSEGV signal(Segmentation fault or invalid memory reference)";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
//this variable calculate processed pixels for x and y direction to make right offsets at the begining of next tile
//offset calculated from condition globalProcessed % inSampleSize should be 0
uint32 globalProcessedX = 0;
uint32 globalProcessedY = 0;
uint32 progressRow = 0;
uint32 progressColumn = 0;
rowDest = columnDest = 0;
for (row = firstTileY * tileHeight; row < lastTileY * tileHeight; row += tileHeight, progressRow += tileHeight) {
columnDest = 0;
short leftTileExists = 0;
short rightTileExists = 0;
for (column = firstTileX * tileWidth; column < lastTileX * tileWidth; column += tileWidth, progressColumn += tileWidth) {
processedProgress = progressRow * *bitmapwidth + progressColumn;
sendProgress(processedProgress, progressTotal);
//If not first column - we should have previous tile - copy it to left tile buffer
if (column != firstTileY) {
_TIFFmemcpy(rasterTileLeft, rasterTile, tileWidth * tileHeight * sizeof(uint32));
leftTileExists = 1;
} else {
leftTileExists = 0;
}
//if current column + tile width is less than origin width - we have right tile - copy it to current tile and read next tile to rasterTileRight buffer
if (column + tileWidth < origwidth && rightTileExists) {
_TIFFmemcpy(rasterTile, rasterTileRight, tileWidth * tileHeight * sizeof(uint32));
TIFFReadRGBATile(image, column + tileWidth, row, rasterTileRight);
rightTileExists = 1;
} else if (column + tileWidth < origwidth) {
//have right tile but this is first tile in row, so need to read raster and right raster
TIFFReadRGBATile(image, column + tileWidth, row, rasterTileRight);
TIFFReadRGBATile(image, column, row, rasterTile);
rightTileExists = 1;
//in that case we also need to invert lines in rasterTile
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
}
} else {
//otherwise we haven't right tile buffer, so we should read tile to current buffer
TIFFReadRGBATile(image, column, row, rasterTile);
rightTileExists = 0;
}
//if we have right tile - current tile already rotated and we need to rotate only right tile
if (rightTileExists) {
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTileRight, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTileRight, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTileRight, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTileRight, work_line_buf);
break;
}
} else {
//otherwise - current tile not rotated so rotate it
//tile orig is on bottom left - should change lines
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
}
}
//Tile could begin from not filled pixel(pixel[x,y] == 0). This variables allow to calculate begining of filled pixels
int tileStartDataX = -1;
int tileStartDataY = -1;
for (int origTileY = 0, pixY = rowDest/inSampleSize; origTileY < tileHeight && pixY < *bitmapheight; origTileY++) {
if (checkStop()) {
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (rasterTileLeft) {
_TIFFfree(rasterTileLeft);
rasterTileLeft = NULL;
}
if (rasterTileRight) {
_TIFFfree(rasterTileRight);
rasterTileRight = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
LOGI("Thread stopped");
return NULL;
}
if (tileStartDataY != -1 && globalProcessedY % inSampleSize != 0) {
if (tileStartDataY != -1) {
globalProcessedY++;
}
}
else
{
for (int origTileX = 0, pixX = columnDest/inSampleSize; origTileX < tileWidth && pixX < *bitmapwidth; origTileX++) {
if (tileStartDataX != -1 && globalProcessedX % inSampleSize != 0)
{
if (tileStartDataX != -1) {
globalProcessedX++;
}
}
else
{
uint32 srcPosition = origTileY * tileWidth + origTileX;
if (rasterTile[srcPosition] != 0) {
if (tileStartDataX == -1) {
tileStartDataX = origTileX;
}
if (tileStartDataY == -1) {
tileStartDataY = origTileY;
}
//Apply filter to pixel
jint crPix = rasterTile[srcPosition];//origBuffer[j1 * origwidth + i1];
int sum = 1;
int alpha = colorMask & crPix >> 24;
int red = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int blue = colorMask & crPix;
//using kernel 3x3
//topleft
if (origTileX - 1 >= 0 && origTileY - 1 >= 0) {
crPix = rasterTile[(origTileY - 1) * tileWidth + origTileX - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY - 1 >= 0 && leftTileExists) {
crPix = rasterTileLeft[(origTileY - 1) * tileWidth + tileWidth - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//top
if (origTileY - 1 >= 0) {
crPix = rasterTile[(origTileY - 1) * tileWidth + origTileX];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
// topright
if (origTileX + 1 < tileWidth && origTileY - 1 >= 0) {
crPix = rasterTile[(origTileY - 1) * tileWidth + origTileX + 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY - 1 >= 0 && rightTileExists) {
crPix = rasterTileRight[(origTileY - 1) * tileWidth];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//right
if (origTileX + 1 < tileWidth) {
crPix = rasterTile[origTileY * tileWidth + origTileX + 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (rightTileExists) {
crPix = rasterTileRight[origTileY * tileWidth];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//bottomright
if (origTileX + 1 < tileWidth && origTileY + 1 < tileHeight) {
crPix = rasterTile[(origTileY + 1) * tileWidth + origTileX + 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY + 1 < tileHeight && rightTileExists) {
crPix = rasterTileRight[(origTileY + 1) * tileWidth];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//bottom
if (origTileY + 1 < tileHeight) {
crPix = rasterTile[(origTileY + 1) * tileWidth + origTileX];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//bottomleft
if (origTileX - 1 >= 0 && origTileY + 1 < tileHeight) {
crPix = rasterTile[(origTileY + 1) * tileWidth + origTileX - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (origTileY + 1 < tileHeight && leftTileExists) {
crPix = rasterTileLeft[(origTileY + 1) * tileWidth + tileWidth - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
//left
if (origTileX - 1 >= 0) {
crPix = rasterTile[origTileY * tileWidth + origTileX - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
} else if (leftTileExists) {
crPix = rasterTileLeft[origTileY * tileWidth + tileWidth - 1];
if (crPix != 0) {
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
}
red /= sum;
if (red > 255) red = 255;
if (red < 0) red = 0;
green /= sum;
if (green > 255) green = 255;
if (green < 0) green = 0;
blue /= sum;
if (blue > 255) blue = 255;
if (blue < 0) blue = 0;
alpha /= sum;///= sum;
if (alpha > 255) alpha = 255;
if (alpha < 0) alpha = 0;
crPix = (alpha << 24) | (red << 16) | (green << 8) | (blue);
int position;
if (origorientation <= 4) {
position = pixY * *bitmapwidth + pixX;
} else {
position = pixX * *bitmapheight + pixY;
}
pixels[position] = crPix;
} else {
if (tileStartDataX != -1) tileStartDataX = -1;
if (tileStartDataY != -1) tileStartDataY = -1;
}
if (tileStartDataX != -1) {
pixX++;
globalProcessedX++;
}
}
}
if (tileStartDataY != -1) {
pixY++;
globalProcessedY++;
}
}
}
columnDest += tileWidth;
}
rowDest += tileHeight;
}
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (rasterTileLeft) {
_TIFFfree(rasterTileLeft);
rasterTileLeft = NULL;
}
if (rasterTileRight) {
_TIFFfree(rasterTileRight);
rasterTileRight = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
//Copy necessary pixels to new array if orientation <=4
uint32 tmpPixelBufferSize = (boundWidth / inSampleSize) * (boundHeight / inSampleSize);
estimateMem = (sizeof(jint) * pixelsBufferSize); //buffer for decoded pixels
estimateMem += (sizeof(jint) * tmpPixelBufferSize); //finall buffer
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
if (origorientation <= 4) {
jint* tmpPixels = (jint *) malloc(sizeof(jint) * tmpPixelBufferSize);
uint32 startPosX = boundX%tileWidth /inSampleSize;//(firstTileX * tileWidth - tileWidth + boundX) / inSampleSize;
uint32 startPosY = boundY%tileHeight /inSampleSize;//(firstTileY * tileHeight - tileHeight + boundY) /inSampleSize;
for (int ox = startPosX, nx = 0; nx < boundWidth/inSampleSize; ox++, nx++) {
sendProgress(processedProgress + nx * (boundHeight/inSampleSize), progressTotal);
for (int oy = startPosY, ny = 0; ny < boundHeight/inSampleSize; oy++, ny++) {
tmpPixels[ny * (boundWidth/inSampleSize) + nx] = pixels[oy * *bitmapwidth + ox];
}
}
free(pixels);
pixels = tmpPixels;
*bitmapwidth = boundWidth/inSampleSize;
*bitmapheight = boundHeight/inSampleSize;
}
if (useOrientationTag) {
switch (origorientation) {
case ORIENTATION_TOPLEFT:
case ORIENTATION_LEFTTOP:
break;
case ORIENTATION_TOPRIGHT:
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_RIGHTTOP:
flipPixelsHorizontal(*bitmapheight, *bitmapwidth, pixels);
break;
case ORIENTATION_BOTRIGHT:
case ORIENTATION_RIGHTBOT:
rotateRaster(pixels, 180, bitmapwidth, bitmapheight);
break;
case ORIENTATION_BOTLEFT:
flipPixelsVertical(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_LEFTBOT:
flipPixelsVertical(*bitmapheight, *bitmapwidth, pixels);
break;
}
} else {
if (origorientation > 4) {
uint32 buf = *bitmapwidth;
*bitmapwidth = *bitmapheight;
*bitmapheight = buf;
rotateRaster(pixels, 90, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
}
}
//Copy necessary pixels to new array if orientation >4
if (origorientation > 4) {
jint* tmpPixels = (jint *) malloc(sizeof(jint) * tmpPixelBufferSize);
uint32 startPosX = boundX%tileWidth /inSampleSize;
uint32 startPosY = boundY%tileHeight /inSampleSize;
for (int ox = startPosX, nx = 0; nx < boundWidth/inSampleSize; ox++, nx++) {
sendProgress(processedProgress + nx * (boundHeight/inSampleSize), progressTotal);
for (int oy = startPosY, ny = 0; ny < boundHeight/inSampleSize; oy++, ny++) {
if (useOrientationTag) {
tmpPixels[nx * (boundHeight/inSampleSize) + ny] = pixels[ox * *bitmapheight + oy];
} else {
tmpPixels[ny * (boundWidth/inSampleSize) + nx] = pixels[oy * *bitmapwidth + ox];
}
}
}
free(pixels);
pixels = tmpPixels;
*bitmapwidth = boundWidth/inSampleSize;
*bitmapheight = boundHeight/inSampleSize;
}
return pixels;
}
jint * NativeDecoder::getSampledRasterFromImage(int inSampleSize, int *bitmapwidth, int *bitmapheight)
{
//init signal handler for catch SIGSEGV error that could be raised in libtiff
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = imageErrorHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if(sigaction(SIGSEGV, &act, 0) < 0) {
LOGE("Can\'t setup signal handler. Working without errors catching mechanism");
}
//buffer size for decoding tiff image in RGBA format
int origBufferSize = origwidth * origheight * sizeof(unsigned int);
*bitmapwidth = origwidth / inSampleSize;
*bitmapheight = origheight / inSampleSize;
//buffer size for creating scaled image;
uint32 pixelsBufferSize = *bitmapwidth * *bitmapheight * sizeof(jint);
/**Estimate usage of memory for decoding*/
unsigned long estimateMem = origBufferSize;//origBufferSize - size of decoded RGBA image
if (inSampleSize > 1) {
estimateMem += pixelsBufferSize; //if inSmapleSize greater than 1 we need aditional vevory for scaled image
}
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
unsigned int *origBuffer = NULL;
origBuffer = (unsigned int *) _TIFFmalloc(origBufferSize);
if (origBuffer == NULL) {
LOGE("Can\'t allocate memory for origBuffer");
return NULL;
}
jint *pixels = NULL;
//check for error
if (setjmp(NativeDecoder::image_buf)) {
if (origBuffer) {
_TIFFfree(origBuffer);
origBuffer = NULL;
}
if (pixels) {
free(pixels);
pixels = NULL;
}
const char * err = "Caught SIGSEGV signal(Segmentation fault or invalid memory reference)";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
if (0 ==
TIFFReadRGBAImageOriented(image, origwidth, origheight, origBuffer, ORIENTATION_TOPLEFT, 0)) {
free(origBuffer);
const char *message = "Error reading image";
LOGE(*message);
if (throwException) {
throwDecodeFileException(message);
}
return NULL;
}
if (inSampleSize == 1) {
// Use buffer as is.
pixels = (jint*) origBuffer;
}
else {
// Sample the buffer.
pixels = (jint *) malloc(pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
}
else {
for (int j = 0, j1 = 0; j < *bitmapheight; j++, j1 += inSampleSize) {
sendProgress(j1 * origwidth, progressTotal);
if (checkStop()) {
//TODO clear memory
if (origBuffer) {
_TIFFfree(origBuffer);
origBuffer = NULL;
}
if (pixels) {
free(pixels);
pixels = NULL;
}
LOGI("Thread stopped");
return NULL;
}
for (int i = 0, i1 = 0; i < *bitmapwidth; i++, i1 += inSampleSize) {
//Apply filter to pixel
jint crPix = origBuffer[j1 * origwidth + i1];
int sum = 1;
int alpha = colorMask & crPix >> 24;
int red = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int blue = colorMask & crPix;
//using kernel 3x3
//topleft
if (i1 - 1 >= 0 && j1 - 1 >= 0) {
crPix = origBuffer[(j1 - 1) * origwidth + i1 - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//top
if (j1 - 1 >= 0) {
crPix = origBuffer[(j1 - 1) * origwidth + i1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
// topright
if (i1 + 1 < origwidth && j1 - 1 >= 0) {
crPix = origBuffer[(j1 - 1) * origwidth + i1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//right
if (i1 + 1 < origwidth) {
crPix = origBuffer[j1 * origwidth + i1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomright
if (i1 + 1 < origwidth && j1 + 1 < origheight) {
crPix = origBuffer[(j1 + 1) * origwidth + i1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottom
if (j1 + 1 < origheight) {
crPix = origBuffer[(j1 + 1) * origwidth + i1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomleft
if (i1 - 1 >= 0 && j1 + 1 < origheight) {
crPix = origBuffer[(j1 + 1) * origwidth + i1 - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//left
if (i1 - 1 >= 0) {
crPix = origBuffer[j1 * origwidth + i1 - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
red /= sum;
if (red > 255) red = 255;
if (red < 0) red = 0;
green /= sum;
if (green > 255) green = 255;
if (green < 0) green = 0;
blue /= sum;
if (blue > 255) blue = 255;
if (blue < 0) blue = 0;
alpha /= sum;///= sum;
if (alpha > 255) alpha = 255;
if (alpha < 0) alpha = 0;
crPix = (alpha << 24) | (red << 16) | (green << 8) | (blue);
pixels[j * *bitmapwidth + i] = crPix;
}
}
}
//Close Buffer
if (origBuffer) {
_TIFFfree(origBuffer);
origBuffer = NULL;
}
}
if (useOrientationTag) {
fixOrientation(pixels, pixelsBufferSize, *bitmapwidth, *bitmapheight);
} else {
uint32 buf;
switch(origorientation) {
case ORIENTATION_TOPLEFT:
case ORIENTATION_LEFTTOP:
break;
case ORIENTATION_TOPRIGHT:
case ORIENTATION_RIGHTTOP:
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_BOTRIGHT:
case ORIENTATION_RIGHTBOT:
rotateRaster(pixels, 180, bitmapwidth, bitmapheight);
break;
case ORIENTATION_BOTLEFT:
case ORIENTATION_LEFTBOT:
rotateRaster(pixels, 180, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
break;
}
}
return pixels;
}
jint * NativeDecoder::getSampledRasterFromImageWithBounds(int inSampleSize, int *bitmapwidth, int *bitmapheight)
{
//init signal handler for catch SIGSEGV error that could be raised in libtiff
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = imageErrorHandler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
if(sigaction(SIGSEGV, &act, 0) < 0) {
LOGE("Can\'t setup signal handler. Working without errors catching mechanism");
}
//buffer size for decoding tiff image in RGBA format
int origBufferSize = origwidth * origheight * sizeof(unsigned int);
*bitmapwidth = boundWidth / inSampleSize;//origwidth / inSampleSize;
*bitmapheight = boundHeight / inSampleSize;//origheight / inSampleSize;
//buffer size for creating scaled image;
uint32 pixelsBufferSize = *bitmapwidth * *bitmapheight * sizeof(jint);
/**Estimate usage of memory for decoding*/
unsigned long estimateMem = origBufferSize;//origBufferSize - size of decoded RGBA image
//if (inSampleSize > 1) {
estimateMem += pixelsBufferSize; //if inSmapleSize greater than 1 we need aditional vevory for scaled image
//}
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory) {
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return NULL;
}
unsigned int *origBuffer = NULL;
jint *pixels = NULL;
//check for error
if (setjmp(NativeDecoder::image_buf)) {
if (origBuffer) {
_TIFFfree(origBuffer);
origBuffer = NULL;
}
if (pixels) {
free(pixels);
pixels = NULL;
}
const char * err = "Caught SIGSEGV signal(Segmentation fault or invalid memory reference)";
LOGE(err);
if (throwException) {
throwDecodeFileException(err);
}
return NULL;
}
origBuffer = (unsigned int *) _TIFFmalloc(origBufferSize);
if (origBuffer == NULL) {
LOGE("Can\'t allocate memory for origBuffer");
return NULL;
}
if (0 ==
TIFFReadRGBAImageOriented(image, origwidth, origheight, origBuffer, ORIENTATION_TOPLEFT, 0)) {
free(origBuffer);
const char *message = "Error reading image";
LOGE(*message);
if (throwException) {
throwDecodeFileException(message);
}
return NULL;
}
progressTotal = boundWidth/inSampleSize * boundHeight/inSampleSize;
// Sample the buffer.
pixels = (jint *) malloc(pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
} else {
for (int y = 0, y1 = boundY; y < *bitmapheight; y++, y1 += inSampleSize) {
sendProgress(y1 * boundWidth, progressTotal);
if (checkStop()) {
//TODO clear memory
if (origBuffer) {
_TIFFfree(origBuffer);
origBuffer = NULL;
}
if (pixels) {
free(pixels);
pixels = NULL;
}
LOGI("Thread stopped");
return NULL;
}
for (int x = 0, x1 = boundX; x < *bitmapwidth; x++, x1 += inSampleSize) {
//Apply filter to pixel
jint crPix = origBuffer[y1 * origwidth + x1];
int sum = 1;
int alpha = colorMask & crPix >> 24;
int red = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int blue = colorMask & crPix;
//using kernel 3x3
//topleft
if (x1 - 1 >= 0 && y1 - 1 >= 0) {
crPix = origBuffer[(y1 - 1) * origwidth + x1 - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//top
if (y1 - 1 >= 0) {
crPix = origBuffer[(y1 - 1) * origwidth + x1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
// topright
if (x1 + 1 < origwidth && y1 - 1 >= 0) {
crPix = origBuffer[(y1 - 1) * origwidth + x1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//right
if (x1 + 1 < origwidth) {
crPix = origBuffer[y1 * origwidth + x1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomright
if (x1 + 1 < origwidth && y1 + 1 < origheight) {
crPix = origBuffer[(y1 + 1) * origwidth + x1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottom
if (y1 + 1 < origheight) {
crPix = origBuffer[(y1 + 1) * origwidth + x1 + 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//bottomleft
if (x1 - 1 >= 0 && y1 + 1 < origheight) {
crPix = origBuffer[(y1 + 1) * origwidth + x1 - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
//left
if (x1 - 1 >= 0) {
crPix = origBuffer[y1 * origwidth + x1 - 1];
red += colorMask & crPix >> 16;
green += colorMask & crPix >> 8;
blue += colorMask & crPix;
alpha += colorMask & crPix >> 24;
sum++;
}
red /= sum;
if (red > 255) red = 255;
if (red < 0) red = 0;
green /= sum;
if (green > 255) green = 255;
if (green < 0) green = 0;
blue /= sum;
if (blue > 255) blue = 255;
if (blue < 0) blue = 0;
alpha /= sum;///= sum;
if (alpha > 255) alpha = 255;
if (alpha < 0) alpha = 0;
crPix = (alpha << 24) | (red << 16) | (green << 8) | (blue);
pixels[y * *bitmapwidth + x] = crPix;
}
}
}
//Close Buffer
if (origBuffer) {
_TIFFfree(origBuffer);
origBuffer = NULL;
}
if (useOrientationTag) {
fixOrientation(pixels, pixelsBufferSize, *bitmapwidth, *bitmapheight);
} else {
uint32 buf;
switch(origorientation) {
case ORIENTATION_TOPLEFT:
case ORIENTATION_LEFTTOP:
break;
case ORIENTATION_TOPRIGHT:
case ORIENTATION_RIGHTTOP:
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
break;
case ORIENTATION_BOTRIGHT:
case ORIENTATION_RIGHTBOT:
rotateRaster(pixels, 180, bitmapwidth, bitmapheight);
break;
case ORIENTATION_BOTLEFT:
case ORIENTATION_LEFTBOT:
rotateRaster(pixels, 180, bitmapwidth, bitmapheight);
flipPixelsHorizontal(*bitmapwidth, *bitmapheight, pixels);
break;
}
}
return pixels;
}
int NativeDecoder::getDecodeMethod()
{
int method = -1;
uint32 tileWidth, tileHeight;
int readTW = 0, readTH = 0;
readTW = TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
readTH = TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight);
if (tileWidth > 0 && tileHeight > 0 && readTH > 0 && readTW > 0) {
method = DECODE_METHOD_TILE;
} else {
int rowPerStrip = -1;
TIFFGetField(image, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
uint32 stripSize = TIFFStripSize (image);
uint32 stripMax = TIFFNumberOfStrips (image);
int estimate = origwidth * 3;
LOGII("RPS", rowPerStrip);
LOGII("stripSize", stripSize);
LOGII("stripMax", stripMax);
if (rowPerStrip != -1 && stripSize > 0 && stripMax > 1 && rowPerStrip < origheight) {
method = DECODE_METHOD_STRIP;
} else {
method = DECODE_METHOD_IMAGE;
}
}
LOGII("Decode method", method);
return method;
}
void NativeDecoder::flipPixelsVertical(uint32 width, uint32 height, jint* raster) {
jint *bufferLine = (jint *) malloc(sizeof(jint) * width);
for (int line = 0; line < height / 2; line++) {
jint *top_line, *bottom_line;
top_line = raster + width * line;
bottom_line = raster + width * (height - line -1);
_TIFFmemcpy(bufferLine, top_line, sizeof(jint) * width);
_TIFFmemcpy(top_line, bottom_line, sizeof(jint) * width);
_TIFFmemcpy(bottom_line, bufferLine, sizeof(jint) * width);
}
free(bufferLine);
}
void NativeDecoder::flipPixelsHorizontal(uint32 width, uint32 height, jint* raster) {
jint buf;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width / 2; x++) {
buf = raster[y * width + x];
raster[y * width + x] = raster[y * width + width - x - 1];
raster[y * width + width - x - 1] = buf;
}
}
}
void NativeDecoder::rotateRaster(jint *raster, int angle, int *width, int *height)
{
int rotatedWidth = *width;
int rotatedHeight = *height;
int numberOf90s = angle / 90;
if (numberOf90s % 2 != 0)
{
int tmp = rotatedWidth;
rotatedWidth = rotatedHeight;
rotatedHeight = tmp;
}
jint *rotated = (jint *) malloc(sizeof(jint) * rotatedWidth * rotatedHeight);//new int[rotatedWidth * rotatedHeight];
for (int h = 0; h < *height; ++h)
{
for (int w = 0; w < *width; ++w)
{
uint32 item = raster[h * *width + w];
int x = 0;
int y = 0;
switch (numberOf90s % 4)
{
case 0:
x = w;
y = h;
break;
case 1:
x = (*height - h - 1);
y = (rotatedHeight - 1) - (*width - w - 1);
break;
case 2:
x = (*width - w - 1);
y = (*height - h - 1);
break;
case 3:
x = (rotatedWidth - 1) - (*height - h - 1);
y = (*width - w - 1);
break;
}
rotated[y * rotatedWidth + x] = item;
}
}
*width = rotatedWidth;
*height = rotatedHeight;
memcpy(raster, rotated, sizeof(jint) * *width * *height);
free(rotated);
}
void NativeDecoder::fixOrientation(jint *pixels, uint32 pixelsBufferSize, int bitmapwidth, int bitmapheight)
{
if (origorientation > 4) {
unsigned int size = bitmapheight * bitmapwidth - 1;
jint t;
unsigned long long next;
unsigned long long cycleBegin;
bool *barray = (bool *) malloc(sizeof(bool) * pixelsBufferSize);
for (int x = 0; x < size; x++) { barray[x] = false; }
barray[0] = barray[size] = true;
unsigned long long k = 1;
switch (origorientation) {
case ORIENTATION_LEFTTOP:
case ORIENTATION_RIGHTBOT:
while (k < size) {
cycleBegin = k;
t = pixels[k];
do {
next = (k * bitmapheight) % size;
jint buf = pixels[next];
pixels[next] = t;
t = buf;
barray[k] = true;
k = next;
} while (k != cycleBegin);
for (k = 1; k < size && barray[k]; k++);
}
break;
case ORIENTATION_LEFTBOT:
case ORIENTATION_RIGHTTOP:
while (k < size) {
cycleBegin = k;
t = pixels[k];
do {
next = (k * bitmapheight) % size;
jint buf = pixels[next];
pixels[next] = t;
t = buf;
barray[k] = true;
k = next;
} while (k != cycleBegin);
for (k = 1; k < size && barray[k]; k++);
}
//flip horizontally
for (int j = 0, j1 = bitmapwidth - 1; j < bitmapwidth / 2; j++, j1--) {
for (int i = 0; i < bitmapheight; i++) {
jint tmp = pixels[j * bitmapheight + i];
pixels[j * bitmapheight + i] = pixels[j1 * bitmapheight + i];
pixels[j1 * bitmapheight + i] = tmp;
}
}
//flip vertically
for (int i = 0, i1 = bitmapheight - 1; i < bitmapheight / 2; i++, i1--) {
for (int j = 0; j < bitmapwidth; j++) {
jint tmp = pixels[j * bitmapheight + i];
pixels[j * bitmapheight + i] = pixels[j * bitmapheight + i1];
pixels[j * bitmapheight + i1] = tmp;
}
}
break;
}
free(barray);
}
}
jbyte * NativeDecoder::createBitmapAlpha8(jint *raster, int bitmapwidth, int bitmapheight)
{
jbyte *pixels = NULL;
int pixelsBufferSize = bitmapwidth * bitmapheight;
pixels = (jbyte *) malloc(sizeof(jbyte) * pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
}
for (int i = 0; i < bitmapwidth; i++) {
if (checkStop()) {
if (pixels) {
free(pixels);
pixels = NULL;
}
LOGI("Thread stopped");
return NULL;
}
for (int j = 0; j < bitmapheight; j++) {
uint32 crPix = raster[j * bitmapwidth + i];
int alpha = colorMask & crPix >> 24;
pixels[j * bitmapwidth + i] = alpha;
}
}
//Close Buffer
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
return pixels;
}
unsigned short * NativeDecoder::createBitmapRGB565(jint *buffer, int bitmapwidth, int bitmapheight)
{
unsigned short *pixels = NULL;
int pixelsBufferSize = bitmapwidth * bitmapheight;
pixels = (unsigned short *) malloc(sizeof(unsigned short) * pixelsBufferSize);
if (pixels == NULL) {
LOGE("Can\'t allocate memory for temp buffer");
return NULL;
}
for (int i = 0; i < bitmapwidth; i++) {
if (checkStop()) {
if (pixels) {
free(pixels);
pixels = NULL;
}
LOGI("Thread stopped");
return NULL;
}
for (int j = 0; j < bitmapheight; j++) {
jint crPix = buffer[j * bitmapwidth + i];
int blue = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int red = colorMask & crPix;
unsigned char B = (blue >> 3);
unsigned char G = (green >> 2);
unsigned char R = (red >> 3);
jint curPix = (R << 11) | (G << 5) | B;
pixels[j * bitmapwidth + i] = curPix;
}
}
//Close Buffer
if (buffer) {
_TIFFfree(buffer);
buffer = NULL;
}
return pixels;
}
int NativeDecoder::getDyrectoryCount()
{
int dircount = 0;
do {
dircount++;
} while (TIFFReadDirectory(image));
return dircount;
}
void NativeDecoder::writeDataToOptions(int directoryNumber)
{
TIFFSetDirectory(image, directoryNumber);
jfieldID gOptions_outDirectoryCountFieldId = env->GetFieldID(jBitmapOptionsClass,
"outDirectoryCount", "I");
int dircount = getDyrectoryCount();
env->SetIntField(optionsObject, gOptions_outDirectoryCountFieldId, dircount);
TIFFSetDirectory(image, directoryNumber);
TIFFGetField(image, TIFFTAG_IMAGEWIDTH, & origwidth);
TIFFGetField(image, TIFFTAG_IMAGELENGTH, & origheight);
//Getting image orientation and createing ImageOrientation enum
TIFFGetField(image, TIFFTAG_ORIENTATION, & origorientation);
//If orientation field is empty - use ORIENTATION_TOPLEFT
if (origorientation == 0) {
origorientation = ORIENTATION_TOPLEFT;
}
jclass gOptions_ImageOrientationClass = env->FindClass(
"org/beyka/tiffbitmapfactory/Orientation");
jfieldID gOptions_ImageOrientationFieldId = NULL;
bool flipHW = false;
LOGII("Orientation", origorientation);
switch (origorientation) {
case ORIENTATION_TOPLEFT:
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"TOP_LEFT",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
case ORIENTATION_TOPRIGHT:
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"TOP_RIGHT",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
case ORIENTATION_BOTRIGHT:
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"BOT_RIGHT",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
case ORIENTATION_BOTLEFT:
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"BOT_LEFT",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
case ORIENTATION_LEFTTOP:
flipHW = true;
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"LEFT_TOP",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
case ORIENTATION_RIGHTTOP:
flipHW = true;
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"RIGHT_TOP",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
case ORIENTATION_RIGHTBOT:
flipHW = true;
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"RIGHT_BOT",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
case ORIENTATION_LEFTBOT:
flipHW = true;
gOptions_ImageOrientationFieldId = env->GetStaticFieldID(gOptions_ImageOrientationClass,
"LEFT_BOT",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
break;
}
if (gOptions_ImageOrientationFieldId != NULL) {
jobject gOptions_ImageOrientationObj = env->GetStaticObjectField(
gOptions_ImageOrientationClass,
gOptions_ImageOrientationFieldId);
//Set outImageOrientation field to options object
jfieldID gOptions_outImageOrientationField = env->GetFieldID(jBitmapOptionsClass,
"outImageOrientation",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
env->SetObjectField(optionsObject, gOptions_outImageOrientationField,
gOptions_ImageOrientationObj);
}
//Get resolution variables
/*
jfieldID gOptions_outDirectoryCountFieldId = env->GetFieldID(jOptionsClass,
"outDirectoryCount", "I");
int dircount = getDyrectoryCount();
env->SetIntField(optionsObject, gOptions_outDirectoryCountFieldId, dircount);
*/
float xresolution, yresolution;
uint16 resunit;
TIFFGetField(image, TIFFTAG_XRESOLUTION, &xresolution);
LOGIF("xres", xresolution);
jfieldID gOptions_outXResolutionFieldID = env->GetFieldID(jBitmapOptionsClass, "outXResolution", "F");
env->SetFloatField(optionsObject, gOptions_outXResolutionFieldID, xresolution);
TIFFGetField(image, TIFFTAG_YRESOLUTION, &yresolution);
LOGIF("yres", yresolution);
jfieldID gOptions_outYResolutionFieldID = env->GetFieldID(jBitmapOptionsClass, "outYResolution", "F");
env->SetFloatField(optionsObject, gOptions_outYResolutionFieldID, yresolution);
TIFFGetField(image, TIFFTAG_RESOLUTIONUNIT, &resunit);
LOGII("resunit", resunit);
jclass gOptions_ResolutionUnitClass = env->FindClass("org/beyka/tiffbitmapfactory/ResolutionUnit");
jfieldID gOptions_ResolutionUnitFieldId = NULL;
switch(resunit) {
case RESUNIT_INCH:
gOptions_ResolutionUnitFieldId = env->GetStaticFieldID(gOptions_ResolutionUnitClass,
"INCH",
"Lorg/beyka/tiffbitmapfactory/ResolutionUnit;");
break;
case RESUNIT_CENTIMETER:
gOptions_ResolutionUnitFieldId = env->GetStaticFieldID(gOptions_ResolutionUnitClass,
"CENTIMETER",
"Lorg/beyka/tiffbitmapfactory/ResolutionUnit;");
break;
case RESUNIT_NONE:
default:
gOptions_ResolutionUnitFieldId = env->GetStaticFieldID(gOptions_ResolutionUnitClass,
"NONE",
"Lorg/beyka/tiffbitmapfactory/ResolutionUnit;");
break;
}
if (gOptions_ResolutionUnitFieldId != NULL) {
jobject gOptions_ResolutionUnitObj = env->GetStaticObjectField(
gOptions_ResolutionUnitClass,
gOptions_ResolutionUnitFieldId);
//Set resolution unit field to options object
jfieldID gOptions_outResUnitField = env->GetFieldID(jBitmapOptionsClass,
"outResolutionUnit",
"Lorg/beyka/tiffbitmapfactory/ResolutionUnit;");
env->SetObjectField(optionsObject, gOptions_outResUnitField,
gOptions_ResolutionUnitObj);
}
//Get image planar config
int planarConfig = 0;
TIFFGetField(image, TIFFTAG_PLANARCONFIG, &planarConfig);
LOGII("planar config", planarConfig);
jclass gOptions_PlanarConfigClass = env->FindClass("org/beyka/tiffbitmapfactory/PlanarConfig");
jfieldID gOptions_PlanarConfigFieldId = NULL;
switch(planarConfig) {
case PLANARCONFIG_CONTIG:
gOptions_PlanarConfigFieldId = env->GetStaticFieldID(gOptions_PlanarConfigClass,
"CONTIG",
"Lorg/beyka/tiffbitmapfactory/PlanarConfig;");
break;
case PLANARCONFIG_SEPARATE:
gOptions_PlanarConfigFieldId = env->GetStaticFieldID(gOptions_PlanarConfigClass,
"SEPARATE",
"Lorg/beyka/tiffbitmapfactory/PlanarConfig;");
break;
}
if (gOptions_PlanarConfigFieldId != NULL) {
jobject gOptions_PlanarConfigObj = env->GetStaticObjectField(
gOptions_PlanarConfigClass,
gOptions_PlanarConfigFieldId);
jfieldID gOptions_outPlanarConfigField = env->GetFieldID(jBitmapOptionsClass,
"outPlanarConfig",
"Lorg/beyka/tiffbitmapfactory/PlanarConfig;");
env->SetObjectField(optionsObject, gOptions_outPlanarConfigField,
gOptions_PlanarConfigObj);
}
//Getting image compression scheme and createing CompressionScheme enum
TIFFGetField(image, TIFFTAG_COMPRESSION, & origcompressionscheme);
LOGII("compression", origcompressionscheme);
jclass gOptions_ImageCompressionClass = env->FindClass(
"org/beyka/tiffbitmapfactory/CompressionScheme");
jfieldID gOptions_ImageCompressionFieldId = NULL;
switch (origcompressionscheme) {
case COMPRESSION_NONE:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"NONE",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_CCITTRLE:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"CCITTRLE",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_CCITTFAX3:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"CCITTFAX3",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_CCITTFAX4:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"CCITTFAX4",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_LZW:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"LZW",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_JPEG:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"JPEG",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_PACKBITS:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"PACKBITS",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_DEFLATE:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"DEFLATE",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
case COMPRESSION_ADOBE_DEFLATE:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"ADOBE_DEFLATE",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
break;
default:
gOptions_ImageCompressionFieldId = env->GetStaticFieldID(gOptions_ImageCompressionClass,
"OTHER",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
}
if (gOptions_ImageCompressionFieldId != NULL) {
jobject gOptions_ImageCompressionObj = env->GetStaticObjectField(
gOptions_ImageCompressionClass,
gOptions_ImageCompressionFieldId);
//Set outImageOrientation field to options object
jfieldID gOptions_outCompressionSchemeField = env->GetFieldID(jBitmapOptionsClass,
"outCompressionScheme",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
env->SetObjectField(optionsObject, gOptions_outCompressionSchemeField,
gOptions_ImageCompressionObj);
}
jfieldID gOptions_OutCurDirNumberFieldID = env->GetFieldID(jBitmapOptionsClass,
"outCurDirectoryNumber",
"I");
env->SetIntField(optionsObject, gOptions_OutCurDirNumberFieldID, directoryNumber);
if (!flipHW) {
jfieldID gOptions_outWidthFieldId = env->GetFieldID(jBitmapOptionsClass, "outWidth", "I");
env->SetIntField(optionsObject, gOptions_outWidthFieldId, origwidth);
jfieldID gOptions_outHeightFieldId = env->GetFieldID(jBitmapOptionsClass, "outHeight", "I");
env->SetIntField(optionsObject, gOptions_outHeightFieldId, origheight);
} else {
jfieldID gOptions_outWidthFieldId = env->GetFieldID(jBitmapOptionsClass, "outWidth", "I");
env->SetIntField(optionsObject, gOptions_outWidthFieldId, origheight);
jfieldID gOptions_outHeightFieldId = env->GetFieldID(jBitmapOptionsClass, "outHeight", "I");
env->SetIntField(optionsObject, gOptions_outHeightFieldId, origwidth);
}
int tagRead = 0;
int bitPerSample = 0;
tagRead = TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitPerSample);
if (tagRead == 1) {
LOGII("bit per sample", bitPerSample);
jfieldID gOptions_outBitPerSampleFieldID = env->GetFieldID(jBitmapOptionsClass, "outBitsPerSample", "I");
env->SetIntField(optionsObject, gOptions_outBitPerSampleFieldID, bitPerSample);
}
int samplePerPixel = 0;
tagRead = TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &samplePerPixel);
if (tagRead == 1) {
LOGII("sample per pixel", samplePerPixel);
jfieldID gOptions_outSamplePerPixelFieldID = env->GetFieldID(jBitmapOptionsClass, "outSamplePerPixel", "I");
env->SetIntField(optionsObject, gOptions_outSamplePerPixelFieldID, samplePerPixel);
}
//Tile size
int tileWidth = 0;
tagRead = TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
if (tagRead == 1) {
LOGII("tile width", tileWidth);
jfieldID gOptions_outTileWidthFieldID = env->GetFieldID(jBitmapOptionsClass, "outTileWidth", "I");
env->SetIntField(optionsObject, gOptions_outTileWidthFieldID, tileWidth);
}
int tileHeight = 0;
tagRead = TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight);
if (tagRead == 1) {
LOGII("tile height", tileHeight);
jfieldID gOptions_outTileHeightFieldID = env->GetFieldID(jBitmapOptionsClass, "outTileHeight", "I");
env->SetIntField(optionsObject, gOptions_outTileHeightFieldID, tileHeight);
}
//row per strip
int rowPerStrip = 0;
tagRead = TIFFGetField(image, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
if (tagRead == 1) {
LOGII("row per strip", rowPerStrip);
jfieldID gOptions_outRowPerStripFieldID = env->GetFieldID(jBitmapOptionsClass, "outRowPerStrip", "I");
env->SetIntField(optionsObject, gOptions_outRowPerStripFieldID, rowPerStrip);
}
//strip size
uint32 stripSize = TIFFStripSize (image);
LOGII("strip size", stripSize);
jfieldID gOptions_outStripSizeFieldID = env->GetFieldID(jBitmapOptionsClass, "outStripSize", "I");
env->SetIntField(optionsObject, gOptions_outStripSizeFieldID, stripSize);
//strip max
uint32 stripMax = TIFFNumberOfStrips (image);
LOGII("number of strips", stripMax);
jfieldID gOptions_outStripMaxFieldID = env->GetFieldID(jBitmapOptionsClass, "outNumberOfStrips", "I");
env->SetIntField(optionsObject, gOptions_outStripMaxFieldID, stripMax);
//photometric
int photometric = 0;
TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &photometric);
LOGII("photometric", photometric);
jclass gOptions_PhotometricClass = env->FindClass("org/beyka/tiffbitmapfactory/Photometric");
jfieldID gOptions_PhotometricFieldId = NULL;
switch(photometric) {
case PHOTOMETRIC_MINISWHITE:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"MINISWHITE",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
break;
case PHOTOMETRIC_MINISBLACK:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"MINISBLACK",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_RGB:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"RGB",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_PALETTE:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"PALETTE",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_MASK:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"MASK",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_SEPARATED:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"SEPARATED",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_YCBCR:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"YCBCR",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_CIELAB:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"CIELAB",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_ICCLAB:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"ICCLAB",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_ITULAB:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"ITULAB",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_LOGL:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"LOGL",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
case PHOTOMETRIC_LOGLUV:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"LOGLUV",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
default:
gOptions_PhotometricFieldId = env->GetStaticFieldID(gOptions_PhotometricClass,
"OTHER",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
}
if (gOptions_PhotometricFieldId != NULL) {
jobject gOptions_PhotometricObj = env->GetStaticObjectField(
gOptions_PhotometricClass,
gOptions_PhotometricFieldId);
jfieldID gOptions_outPhotometricField = env->GetFieldID(jBitmapOptionsClass,
"outPhotometric",
"Lorg/beyka/tiffbitmapfactory/Photometric;");
env->SetObjectField(optionsObject, gOptions_outPhotometricField,
gOptions_PhotometricObj);
}
//FillOrder
int fillOrder = 0;
TIFFGetField(image, TIFFTAG_FILLORDER, &fillOrder);
LOGII("fill Order", fillOrder);
jclass gOptions_FillOrderClass = env->FindClass("org/beyka/tiffbitmapfactory/FillOrder");
jfieldID gOptions_FillOrderFieldId = NULL;
switch(fillOrder) {
case FILLORDER_MSB2LSB:
gOptions_FillOrderFieldId = env->GetStaticFieldID(gOptions_FillOrderClass,
"MSB2LSB",
"Lorg/beyka/tiffbitmapfactory/FillOrder;");
break;
case PLANARCONFIG_SEPARATE:
gOptions_FillOrderFieldId = env->GetStaticFieldID(gOptions_FillOrderClass,
"LSB2MSB",
"Lorg/beyka/tiffbitmapfactory/FillOrder;");
break;
}
if (gOptions_FillOrderFieldId != NULL) {
jobject gOptions_FillOrderObj = env->GetStaticObjectField(
gOptions_FillOrderClass,
gOptions_FillOrderFieldId);
jfieldID gOptions_outFillOrderField = env->GetFieldID(jBitmapOptionsClass,
"outFillOrder",
"Lorg/beyka/tiffbitmapfactory/FillOrder;");
env->SetObjectField(optionsObject, gOptions_outFillOrderField,
gOptions_FillOrderObj);
}
//Author
const char * artist;
tagRead = TIFFGetField(image, TIFFTAG_ARTIST, & artist);
if (tagRead == 1) {
LOGI(artist);
jstring jauthor = charsToJString(artist);//env->NewStringUTF(artist);
jfieldID gOptions_outAuthorFieldId = env->GetFieldID(jBitmapOptionsClass, "outAuthor", "Ljava/lang/String;");
env->SetObjectField(optionsObject, gOptions_outAuthorFieldId, jauthor);
env->DeleteLocalRef(jauthor);
//free(artist);
}
//Copyright
const char * copyright;
tagRead = TIFFGetField(image, TIFFTAG_COPYRIGHT, & copyright);
if (tagRead == 1) {
LOGI(copyright);
jstring jcopyright = charsToJString(copyright);//env->NewStringUTF(copyright);
jfieldID gOptions_outCopyrightFieldId = env->GetFieldID(jBitmapOptionsClass, "outCopyright", "Ljava/lang/String;");
env->SetObjectField(optionsObject, gOptions_outCopyrightFieldId, jcopyright);
env->DeleteLocalRef(jcopyright);
//free(copyright);
}
//ImageDescription
const char * imgDescr;
tagRead = TIFFGetField(image, TIFFTAG_IMAGEDESCRIPTION, & imgDescr);
if (tagRead == 1) {
LOGI(imgDescr);
jstring jimgDescr = charsToJString(imgDescr);//env->NewStringUTF(imgDescr);
jfieldID gOptions_outimgDescrFieldId = env->GetFieldID(jBitmapOptionsClass, "outImageDescription", "Ljava/lang/String;");
env->SetObjectField(optionsObject, gOptions_outimgDescrFieldId, jimgDescr);
env->DeleteLocalRef(jimgDescr);
//free(imgDescr);
}
//Software
const char * software;
tagRead = TIFFGetField(image, TIFFTAG_SOFTWARE, & software);
if (tagRead == 1) {
LOGI(software);
jstring jsoftware = charsToJString(software);//env->NewStringUTF(software);
jfieldID gOptions_outsoftwareFieldId = env->GetFieldID(jBitmapOptionsClass, "outSoftware", "Ljava/lang/String;");
env->SetObjectField(optionsObject, gOptions_outsoftwareFieldId, jsoftware);
env->DeleteLocalRef(jsoftware);
//free(software);
}
//DateTime
const char * datetime;
tagRead = TIFFGetField(image, TIFFTAG_DATETIME, & datetime);
if (tagRead == 1) {
LOGI(datetime);
jstring jdatetime = charsToJString(datetime);//env->NewStringUTF(datetime);
jfieldID gOptions_outdatetimeFieldId = env->GetFieldID(jBitmapOptionsClass, "outDatetime", "Ljava/lang/String;");
env->SetObjectField(optionsObject, gOptions_outdatetimeFieldId, jdatetime);
env->DeleteLocalRef(jdatetime);
//free(datetime);
}
//Host Computer
const char * host;
tagRead = TIFFGetField(image, TIFFTAG_HOSTCOMPUTER, & host);
if (tagRead == 1) {
LOGI(host);
jstring jhost = charsToJString(host);//env->NewStringUTF(host);
jfieldID gOptions_outhostFieldId = env->GetFieldID(jBitmapOptionsClass, "outHostComputer", "Ljava/lang/String;");
env->SetObjectField(optionsObject, gOptions_outhostFieldId, jhost);
env->DeleteLocalRef(jhost);
//free(host);
}
}
jstring NativeDecoder::charsToJString(const char *chars) {
std::string str(chars);
jbyteArray array = env->NewByteArray(str.size());
env->SetByteArrayRegion(array, 0, str.size(), (const jbyte*)str.c_str());
jstring strEncode = env->NewStringUTF("UTF-8");
jclass cls = env->FindClass("java/lang/String");
jmethodID ctor = env->GetMethodID(cls, "", "([BLjava/lang/String;)V");
jstring object = (jstring) env->NewObject(cls, ctor, array, strEncode);
return object;
//return NULL;
}
jboolean NativeDecoder::checkStop() {
jmethodID methodID = env->GetStaticMethodID(jThreadClass, "interrupted", "()Z");
jboolean interupted = env->CallStaticBooleanMethod(jThreadClass, methodID);
jboolean stop;
if (optionsObject) {
jfieldID stopFieldId = env->GetFieldID(jBitmapOptionsClass,
"isStoped",
"Z");
stop = env->GetBooleanField(optionsObject, stopFieldId);
} else {
stop = JNI_FALSE;
}
return interupted || stop;
}
void NativeDecoder::sendProgress(jlong current, jlong total) {
if (listenerObject != NULL) {
jmethodID methodid = env->GetMethodID(jIProgressListenerClass, "reportProgress", "(JJ)V");
env->CallVoidMethod(listenerObject, methodid, current, total);
}
}
void NativeDecoder::tileErrorHandler(int code, siginfo_t *siginfo, void *sc) {
LOGE("tileErrorHandler");
longjmp(tile_buf, 1);
}
void NativeDecoder::stripErrorHandler(int code, siginfo_t *siginfo, void *sc) {
LOGE("stripErrorHandler");
longjmp(strip_buf, 1);
}
void NativeDecoder::imageErrorHandler(int code, siginfo_t *siginfo, void *sc) {
LOGE("imageErrorHandler");
longjmp(image_buf, 1);
}
void NativeDecoder::generalErrorHandler(int code, siginfo_t *siginfo, void *sc) {
LOGE("generalErrorHandler");
longjmp(general_buf, 1);
}
void NativeDecoder::throwDecodeFileException(const char *message) {
jstring adinf = env->NewStringUTF(message);
if (decodingMode == DECODE_MODE_FILE_PATH) {
throw_decode_file_exception(env, jPath, adinf);
} else if (decodingMode == DECODE_MODE_FILE_DESCRIPTOR) {
throw_decode_file_exception_fd(env, jFd, adinf);
}
env->DeleteLocalRef(adinf);
}
void NativeDecoder::throwCantOpenFileException() {
if (decodingMode == DECODE_MODE_FILE_PATH) {
throw_cant_open_file_exception(env, jPath);
} else if (decodingMode == DECODE_MODE_FILE_DESCRIPTOR) {
throw_cant_open_file_exception_fd(env, jFd);
}
}
================================================
FILE: src/main/jni/NativeDecoder.h
================================================
//
// Created by beyka on 3.2.17.
//
#ifndef TIFFSAMPLE_NATIVEDECODER_H
#define TIFFSAMPLE_NATIVEDECODER_H
#include
#include
#include
#include
#include
#include
#include
#include
#include "NativeExceptions.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#define LOGEI(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "NativeDecoder", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeDecoder", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeDecoder", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeDecoder", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "NativeDecoder", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "NativeDecoder", "%s %s", x, y)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "NativeDecoder", "%s %d", x, y)
#endif
class NativeDecoder
{
public:
explicit NativeDecoder(JNIEnv *, jclass, jint, jobject, jobject);
explicit NativeDecoder(JNIEnv *, jclass, jstring, jobject, jobject);
~NativeDecoder();
jobject getBitmap();
private:
//constants
static int const colorMask = 0xFF;
static int const ARGB_8888 = 2;
static int const RGB_565 = 4;
static int const ALPHA_8 = 8;
static int const DECODE_METHOD_IMAGE = 1;
static int const DECODE_METHOD_TILE = 2;
static int const DECODE_METHOD_STRIP = 3;
static int const DECODE_MODE_FILE_PATH = 1;
static int const DECODE_MODE_FILE_DESCRIPTOR = 2;
//decoding mode
int decodingMode;
//fields
JNIEnv *env;
jclass clazz;
static jmp_buf tile_buf;
static jmp_buf strip_buf;
static jmp_buf image_buf;
static jmp_buf general_buf;
jobject optionsObject;
jobject listenerObject;
jclass jIProgressListenerClass;
jclass jBitmapOptionsClass;
jclass jThreadClass = NULL;
jint jFd;
jstring jPath;
jboolean throwException;
jboolean useOrientationTag;
TIFF *image;
jlong progressTotal;
int origwidth;
int origheight;
short origorientation;
int origcompressionscheme;
jobject preferedConfig;
jboolean invertRedAndBlue;
jint boundX;
jint boundY;
jint boundWidth;
jint boundHeight;
char hasBounds;
unsigned long availableMemory;
//methods
int getDyrectoryCount();
void writeDataToOptions(int);
jobject createBitmap(int, int);
jint *getSampledRasterFromImage(int, int *, int *);
jint *getSampledRasterFromImageWithBounds(int , int *, int *);
jint *getSampledRasterFromStrip(int, int *, int *);
jint *getSampledRasterFromStripWithBounds(int, int *, int *);
void rotateTileLinesVertical(uint32, uint32, uint32 *, uint32 *);
void rotateTileLinesHorizontal(uint32, uint32, uint32 *, uint32 *);
void flipPixelsVertical(uint32, uint32, jint *);
void flipPixelsHorizontal(uint32, uint32, jint *);
jint *getSampledRasterFromTile(int, int *, int *);
jint *getSampledRasterFromTileWithBounds(int, int *, int *);
int getDecodeMethod();
void fixOrientation(jint *, uint32, int, int);
void rotateRaster(jint *, int, int *, int *);
jbyte * createBitmapAlpha8(jint *, int, int);
unsigned short *createBitmapRGB565(jint *, int, int);
jstring charsToJString(const char *);
jboolean checkStop();
void sendProgress(jlong, jlong);
//functions for catching SIGSEGV from libtiff methods
void signalFromTileHandler(int code, siginfo_t *siginfo, void *sc);
void signalFromStripHandler(int code, siginfo_t *siginfo, void *sc);
//throwing exceptions
void throwDecodeFileException(const char *);
void throwCantOpenFileException();
static void tileErrorHandler(int code, siginfo_t *siginfo, void *sc);
static void stripErrorHandler(int code, siginfo_t *siginfo, void *sc);
static void imageErrorHandler(int code, siginfo_t *siginfo, void *sc);
static void generalErrorHandler(int code, siginfo_t *siginfo, void *sc);
};
#endif //TIFFSAMPLE_NATIVEDECODER_H
================================================
FILE: src/main/jni/NativeExceptions.cpp
================================================
//
// Created by alexeyba on 09.11.15.
//
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
#include "NativeExceptions.h"
void throw_not_enought_memory_exception(JNIEnv *env, int available, int need)
{
jclass exClass;
jmethodID exConstructorID;
jobject exObj;
const char *className = "org/beyka/tiffbitmapfactory/exceptions/NotEnoughtMemoryException" ;
exClass = env->FindClass(className);
exConstructorID = env->GetMethodID(exClass, "", "(II)V");
exObj = env->NewObject(exClass, exConstructorID, available, need);
env->Throw((jthrowable)exObj);
}
void throw_decode_file_exception(JNIEnv *env, jstring str, jstring additionalInfo)
{
jclass exClass;
jmethodID exConstructorID;
jobject exObj;
const char *className = "org/beyka/tiffbitmapfactory/exceptions/DecodeTiffException" ;
exClass = env->FindClass(className);
exConstructorID = env->GetMethodID(exClass, "", "(Ljava/lang/String;Ljava/lang/String;)V");
exObj = env->NewObject(exClass, exConstructorID, str, additionalInfo);
env->Throw((jthrowable)exObj);
}
void throw_decode_file_exception_fd(JNIEnv *env, jint fd, jstring additionalInfo)
{
jclass exClass;
jmethodID exConstructorID;
jobject exObj;
const char *className = "org/beyka/tiffbitmapfactory/exceptions/DecodeTiffException" ;
exClass = env->FindClass(className);
exConstructorID = env->GetMethodID(exClass, "", "(ILjava/lang/String;)V");
exObj = env->NewObject(exClass, exConstructorID, fd, additionalInfo);
env->Throw((jthrowable)exObj);
}
void throw_cant_open_file_exception(JNIEnv *env, jstring str)
{
jclass exClass;
jmethodID exConstructorID;
jobject exObj;
const char *className = "org/beyka/tiffbitmapfactory/exceptions/CantOpenFileException" ;
exClass = env->FindClass(className);
exConstructorID = env->GetMethodID(exClass, "", "(Ljava/lang/String;)V");
exObj = env->NewObject(exClass, exConstructorID, str);
env->Throw((jthrowable)exObj);
}
void throw_cant_open_file_exception_fd(JNIEnv *env, jint fd)
{
jclass exClass;
jmethodID exConstructorID;
jobject exObj;
const char *className = "org/beyka/tiffbitmapfactory/exceptions/CantOpenFileException" ;
exClass = env->FindClass(className);
exConstructorID = env->GetMethodID(exClass, "", "(I)V");
exObj = env->NewObject(exClass, exConstructorID, fd);
env->Throw((jthrowable)exObj);
}
#ifdef __cplusplus
}
#endif
================================================
FILE: src/main/jni/NativeExceptions.h
================================================
//
// Created by alexeyba on 09.11.15.
//
#ifdef __cplusplus
extern "C" {
#endif
#ifndef TIFFEXAMPLE_NATIVEEXCEPTIONS_H
#define TIFFEXAMPLE_NATIVEEXCEPTIONS_H
#include
#include
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIS(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "NativeDecoder", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeDecoder", "%s %d", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeDecoder", "%s %s", x, y)
#endif
void throw_not_enought_memory_exception(JNIEnv *, int, int);
void throw_decode_file_exception(JNIEnv *, jstring, jstring);
void throw_decode_file_exception_fd(JNIEnv *, jint, jstring);
void throw_cant_open_file_exception(JNIEnv *, jstring);
void throw_cant_open_file_exception_fd(JNIEnv *, jint);
#endif //TIFFEXAMPLE_NATIVEEXCEPTIONS_H
#ifdef __cplusplus
}
#endif
================================================
FILE: src/main/jni/NativeTiffBitmapFactory.cpp
================================================
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
#include "NativeTiffBitmapFactory.h"
JNIEXPORT jobject
JNICALL Java_org_beyka_tiffbitmapfactory_TiffBitmapFactory_nativeDecodePath
(JNIEnv *env, jclass clazz, jstring path, jobject options, jobject listener) {
NativeDecoder *decoder = new NativeDecoder(env, clazz, path, options, listener);
jobject java_bitmap = decoder->getBitmap();
delete(decoder);
return java_bitmap;
}
JNIEXPORT jobject
JNICALL Java_org_beyka_tiffbitmapfactory_TiffBitmapFactory_nativeDecodeFD
(JNIEnv *env, jclass clazz, jint fd, jobject options, jobject listener) {
NativeDecoder *decoder = new NativeDecoder(env, clazz, fd, options, listener);
jobject java_bitmap = decoder->getBitmap();
delete(decoder);
return java_bitmap;
}
JNIEXPORT jobject
JNICALL Java_org_beyka_tiffbitmapfactory_TiffBitmapFactory_nativeCloseFd
(JNIEnv *env, jclass clazz, jint fd) {
close(fd);
}
#ifdef __cplusplus
}
#endif
================================================
FILE: src/main/jni/NativeTiffBitmapFactory.h
================================================
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
#include
#include
#include
#include
#include
#include
#include "NativeExceptions.h"
#include "NativeDecoder.h"
/* Header for class NativeTiffBitmapFactory */
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffBitmapFactory", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffBitmapFactory", "%s %d", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffBitmapFactory", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "NativeTiffBitmapFactory", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "NativeTiffBitmapFactory", "%s %s", x, y)
#endif
#ifndef _Included_org_beyka_tiffbitmapfactory_TiffBitmapFactory
#define _Included_org_beyka_tiffbitmapfactory_TiffBitmapFactory
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_beyka_tiffexample_TiffBitmapFactory
* Method: nativeDecodePath
* Signature: (Ljava/lang/String;I)Landroid/graphics/Bitmap;
*/
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffBitmapFactory_nativeDecodePath
(JNIEnv *, jclass, jstring, jobject, jobject);
/*
* Class: com_example_beyka_tiffexample_TiffBitmapFactory
* Method: nativeDecodePath
* Signature: (Ljava/lang/String;I)Landroid/graphics/Bitmap;
*/
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffBitmapFactory_nativeDecodeFD
(JNIEnv *, jclass, jint, jobject, jobject);
/*
* Class: com_example_beyka_tiffexample_TiffBitmapFactory
* Method: nativeCloseFd
* Signature: (Ljava/lang/String;I)Landroid/graphics/Bitmap;
*/
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffBitmapFactory_nativeCloseFd
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: src/main/jni/NativeTiffConverter.cpp
================================================
//
// Created by beyka on 5/9/17.
//
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
#include "NativeTiffConverter.h"
#include "png.h"
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffPng
(JNIEnv *env, jclass clazz, jstring tiffPath, jstring pngPath, jobject options, jobject listener)
{
TiffToPngConverter *converter = new TiffToPngConverter(env, clazz, tiffPath, pngPath, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffPngFd
(JNIEnv *env, jclass clazz, jint tiffFd, jint pngFd, jobject options, jobject listener)
{
TiffToPngConverter *converter = new TiffToPngConverter(env, clazz, tiffFd, pngFd, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffJpg
(JNIEnv *env, jclass clazz, jstring tiffPath, jstring jpgPath, jobject options, jobject listener)
{
TiffToJpgConverter *converter = new TiffToJpgConverter(env, clazz, tiffPath, jpgPath, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffJpgFd
(JNIEnv *env, jclass clazz, jint tiffFd, jint jpgFd, jobject options, jobject listener)
{
TiffToJpgConverter *converter = new TiffToJpgConverter(env, clazz, tiffFd, jpgFd, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffBmp
(JNIEnv *env, jclass clazz, jstring tiffPath, jstring outPath, jobject options, jobject listener)
{
TiffToBmpConverter *converter = new TiffToBmpConverter(env, clazz, tiffPath, outPath, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffBmpFd
(JNIEnv *env, jclass clazz, jint tiffFd, jint bmpFd, jobject options, jobject listener)
{
TiffToBmpConverter *converter = new TiffToBmpConverter(env, clazz, tiffFd, bmpFd, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertPngTiff
(JNIEnv *env, jclass clazz, jstring pngPath, jstring tiffPath, jobject options, jobject listener)
{
PngToTiffConverter *converter = new PngToTiffConverter(env, clazz, pngPath, tiffPath, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertPngTiffFd
(JNIEnv *env, jclass clazz, jint pngFd, jint tiffFd, jobject options, jobject listener)
{
PngToTiffConverter *converter = new PngToTiffConverter(env, clazz, pngFd, tiffFd, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertJpgTiff
(JNIEnv *env, jclass clazz, jstring pngPath, jstring tiffPath, jobject options, jobject listener)
{
JpgToTiffConverter *converter = new JpgToTiffConverter(env, clazz, pngPath, tiffPath, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertJpgTiffFd
(JNIEnv *env, jclass clazz, jint jpgFd, jint tiffFd, jobject options, jobject listener)
{
JpgToTiffConverter *converter = new JpgToTiffConverter(env, clazz, jpgFd, tiffFd, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertBmpTiff
(JNIEnv *env, jclass clazz, jstring bmpPath, jstring tiffPath, jobject options, jobject listener)
{
BmpToTiffConverter *converter = new BmpToTiffConverter(env, clazz, bmpPath, tiffPath, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertBmpTiffFd
(JNIEnv *env, jclass clazz, jint bmpFd, jint tiffFd, jobject options, jobject listener)
{
BmpToTiffConverter *converter = new BmpToTiffConverter(env, clazz, bmpFd, tiffFd, options, listener);
jboolean result = converter->convert();
delete(converter);
return result;
}
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_readBmp
(JNIEnv *env, jclass clazz, jstring tiffPath, jstring bmpPath, jobject options, jobject listener)
{
return readBmp(env, clazz, tiffPath, bmpPath, options, listener);
}
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_getImageType
(JNIEnv *env, jclass clazz, jstring path)
{
const char *strPath = NULL;
strPath = env->GetStringUTFChars(path, 0);
LOGIS("path", strPath);
int imageformat;
FILE *inFile = fopen(strPath, "rb");
if (inFile) {
//read file header
size_t byte_count = 8;
unsigned char *data = (unsigned char *)malloc(sizeof(unsigned char) * byte_count);
fread(data, 1, byte_count, inFile);
LOGIS("header", data);
switch(data[0]) {
case (unsigned char)'\xFF':
imageformat = ( !strncmp( (const char*)data, "\xFF\xD8\xFF", 3 )) ?
IMAGE_FILE_JPG : IMAGE_FILE_INVALID;
break;
case (unsigned char)'\x89':
imageformat = ( !strncmp( (const char*)data,
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8 )) ?
IMAGE_FILE_PNG : IMAGE_FILE_INVALID;
break;
case 'G':
imageformat = ( !strncmp( (const char*)data, "GIF87a", 6 ) ||
!strncmp( (const char*)data, "GIF89a", 6 ) ) ?
IMAGE_FILE_GIF : IMAGE_FILE_INVALID;
break;
case 'I':
imageformat = ( !strncmp( (const char*)data, "\x49\x49\x2A\x00", 4 )) ?
IMAGE_FILE_TIFF : IMAGE_FILE_INVALID;
break;
case 'M':
imageformat = ( !strncmp( (const char*)data, "\x4D\x4D\x00\x2A", 4 )) ?
IMAGE_FILE_TIFF : IMAGE_FILE_INVALID;
break;
case 'B':
imageformat = (( data[1] == 'M' )) ?
IMAGE_FILE_BMP : IMAGE_FILE_INVALID;
break;
case 'R':
if ( strncmp( (const char*)data, "RIFF", 4 )) {
imageformat = IMAGE_FILE_INVALID;
break;
}
if ( strncmp( (const char*)(data+8), "WEBP", 4 )) {
imageformat = IMAGE_FILE_INVALID;
break;
}
imageformat = IMAGE_FILE_WEBP;
break;
case '\0':
if ( !strncmp( (const char*)data, "\x00\x00\x01\x00", 4 )) {
imageformat = IMAGE_FILE_ICO;
break;
}
if ( !strncmp( (const char*)data, "\x00\x00\x02\x00", 4 )) {
imageformat = IMAGE_FILE_ICO;
break;
}
imageformat = IMAGE_FILE_INVALID;
break;
default:
imageformat = IMAGE_FILE_INVALID;
}
fclose(inFile);
} else {
imageformat = IMAGE_FILE_INVALID;
}
jclass imageFormatClass = env->FindClass(
"org/beyka/tiffbitmapfactory/ImageFormat");
jfieldID imageFormatFieldId = NULL;
switch (imageformat) {
case IMAGE_FILE_JPG:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"JPEG",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
case IMAGE_FILE_PNG:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"PNG",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
case IMAGE_FILE_TIFF:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"TIFF",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
case IMAGE_FILE_BMP:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"BMP",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
default:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"UNKNOWN",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
}
jobject imageFormatObj = env->GetStaticObjectField(
imageFormatClass,
imageFormatFieldId);
return imageFormatObj;
}
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_getImageTypeFd
(JNIEnv *env, jclass clazz, jint fd)
{
int imageformat;
LOGII("fd ", fd);
if (fd != -1) {
LOGI("Start check");
//read file header
int i= 0;
size_t byte_count = 8;
/*while( i < byte_count) {
char c;
read(fd, &c, 1);
LOGII("Read ", c);
i++;
}*/
unsigned char *data = (unsigned char *)malloc(sizeof(unsigned char) * byte_count);
int b = read(fd, data, byte_count);
LOGII("Read bytes: ", b);
LOGIS("header", data);
lseek(fd, 0, SEEK_SET);
switch(data[0]) {
case (unsigned char)'\xFF':
imageformat = ( !strncmp( (const char*)data, "\xFF\xD8\xFF", 3 )) ?
IMAGE_FILE_JPG : IMAGE_FILE_INVALID;
break;
case (unsigned char)'\x89':
imageformat = ( !strncmp( (const char*)data,
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8 )) ?
IMAGE_FILE_PNG : IMAGE_FILE_INVALID;
break;
case 'G':
imageformat = ( !strncmp( (const char*)data, "GIF87a", 6 ) ||
!strncmp( (const char*)data, "GIF89a", 6 ) ) ?
IMAGE_FILE_GIF : IMAGE_FILE_INVALID;
break;
case 'I':
imageformat = ( !strncmp( (const char*)data, "\x49\x49\x2A\x00", 4 )) ?
IMAGE_FILE_TIFF : IMAGE_FILE_INVALID;
break;
case 'M':
imageformat = ( !strncmp( (const char*)data, "\x4D\x4D\x00\x2A", 4 )) ?
IMAGE_FILE_TIFF : IMAGE_FILE_INVALID;
break;
case 'B':
imageformat = (( data[1] == 'M' )) ?
IMAGE_FILE_BMP : IMAGE_FILE_INVALID;
break;
case 'R':
if ( strncmp( (const char*)data, "RIFF", 4 )) {
imageformat = IMAGE_FILE_INVALID;
break;
}
if ( strncmp( (const char*)(data+8), "WEBP", 4 )) {
imageformat = IMAGE_FILE_INVALID;
break;
}
imageformat = IMAGE_FILE_WEBP;
break;
case '\0':
if ( !strncmp( (const char*)data, "\x00\x00\x01\x00", 4 )) {
imageformat = IMAGE_FILE_ICO;
break;
}
if ( !strncmp( (const char*)data, "\x00\x00\x02\x00", 4 )) {
imageformat = IMAGE_FILE_ICO;
break;
}
imageformat = IMAGE_FILE_INVALID;
break;
default:
imageformat = IMAGE_FILE_INVALID;
}
} else {
imageformat = IMAGE_FILE_INVALID;
}
jclass imageFormatClass = env->FindClass(
"org/beyka/tiffbitmapfactory/ImageFormat");
jfieldID imageFormatFieldId = NULL;
switch (imageformat) {
case IMAGE_FILE_JPG:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"JPEG",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
case IMAGE_FILE_PNG:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"PNG",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
case IMAGE_FILE_TIFF:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"TIFF",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
case IMAGE_FILE_BMP:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"BMP",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
break;
default:
imageFormatFieldId = env->GetStaticFieldID(imageFormatClass,
"UNKNOWN",
"Lorg/beyka/tiffbitmapfactory/ImageFormat;");
}
jobject imageFormatObj = env->GetStaticObjectField(
imageFormatClass,
imageFormatFieldId);
return imageFormatObj;
}
JNIEXPORT jobject
JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_nativeCloseFd
(JNIEnv *env, jclass clazz, jint fd) {
close(fd);
}
#ifdef __cplusplus
}
#endif
================================================
FILE: src/main/jni/NativeTiffConverter.h
================================================
//
// Created by beyka on 5/9/17.
//
#include
#include
#include
#include
#include "jpeglib.h"
#include
#include
#include "TiffToPngConverter.h"
#include "TiffToJpgConverter.h"
#include "TiffToBmpConverter.h"
#include "PngToTiffConverter.h"
#include "JpgToTiffConverter.h"
#include "BmpToTiffConverter.h"
#include "BitmapReader.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "NativeTiffConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "NativeTiffConverter", "%s %s", x, y)
#endif
#ifndef TIFFSAMPLE_NATIVETIFFCONVERTER_H
#define TIFFSAMPLE_NATIVETIFFCONVERTER_H
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffPng
(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffPngFd
(JNIEnv *, jclass, jint, jint, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffJpg
(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffJpgFd
(JNIEnv *, jclass, jint, jint, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffbmp
(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertTiffbmpFd
(JNIEnv *, jclass, jint, jint, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertPngTiff
(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertPngTiffFd
(JNIEnv *, jclass, jint, jint, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertJpgTiff
(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertJpgTiffFd
(JNIEnv *, jclass, jint, jint, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertBmpTiff
(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_convertBmpTiffFd
(JNIEnv *, jclass, jint, jint, jobject, jobject);
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_readBmp
(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
// .jpg: FF D8 FF
// .png: 89 50 4E 47 0D 0A 1A 0A
// .gif: GIF87a
// GIF89a
// .tiff: 49 49 2A 00
// 4D 4D 00 2A
// .bmp: BM
// .webp: RIFF ???? WEBP
// .ico 00 00 01 00
// 00 00 02 00 ( cursor files )
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_getImageType
(JNIEnv *, jclass, jstring);
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_getImageTypeFd
(JNIEnv *, jclass, jint);
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffConverter_nativeCloseFd
(JNIEnv *, jclass, jint);
//constants for check files
const jint IMAGE_FILE_INVALID = 0;
const jint IMAGE_FILE_JPG = 1;
const jint IMAGE_FILE_PNG = 2;
const jint IMAGE_FILE_GIF = 3;
const jint IMAGE_FILE_TIFF = 4;
const jint IMAGE_FILE_BMP = 5;
const jint IMAGE_FILE_WEBP = 6;
const jint IMAGE_FILE_ICO = 7;
#ifdef __cplusplus
}
#endif
#endif //TIFFSAMPLE_NATIVETIFFCONVERTER_H
================================================
FILE: src/main/jni/NativeTiffSaver.cpp
================================================
//
// Created by beyka on 18.2.16.
//
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
#include "NativeTiffSaver.h"
int const colorMask = 0xFF;
int const paramCompression = 0;
int const paramOrientation = 1;
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffSaver_save
(JNIEnv *env, jclass clazz, jstring filePath, jint fileDescriptor, jobject bitmap, jobject options, jboolean append) {
__android_log_write(ANDROID_LOG_ERROR, "NativeTiffSaver", "Test Error here");
//Options class
jclass jSaveOptionsClass = env->FindClass("org/beyka/tiffbitmapfactory/TiffSaver$SaveOptions");
//How much memory can we use?
jfieldID availableMemoryFieldID = env->GetFieldID(jSaveOptionsClass,
"inAvailableMemory",
"J");
unsigned long inAvailableMemory = env->GetLongField(options, availableMemoryFieldID);
//If we need to throw exceptions
jfieldID throwExceptionFieldID = env->GetFieldID(jSaveOptionsClass,
"inThrowException",
"Z");
jboolean throwException = env->GetBooleanField(options, throwExceptionFieldID);
// check is bitmap null
if (bitmap == NULL) {
const char *message = "Bitmap is null\0";
LOGE(message);
if (throwException) {
jstring jmessage = env->NewStringUTF(message);
throw_decode_file_exception(env, filePath, jmessage);
env->DeleteLocalRef(jmessage);
}
return JNI_FALSE;
}
jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
//check is bitmap recycled
jmethodID isRecycledMethodid = env->GetMethodID(bitmapClass, "isRecycled", "()Z");
jboolean isRecycled = env->CallBooleanMethod(bitmap, isRecycledMethodid);
if (isRecycled) {
const char *message = "Bitmap is recycled\0";
LOGE(message);
if (throwException) {
jstring jmessage = env->NewStringUTF(message);
throw_decode_file_exception(env, filePath, jmessage);
env->DeleteLocalRef(jmessage);
}
return JNI_FALSE;
}
//Read pixels from bitmap
AndroidBitmapInfo info;
void* pixels;
int ret;
if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=");
return JNI_FALSE;
}
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=");
return JNI_FALSE;
}
uint32 img_width = info.width;
uint32 img_height= info.height;
/*
//Get array of jint from jintArray
jint *c_array;
c_array = env->GetIntArrayElements(img, NULL);
if (c_array == NULL) {
//if array is null - nothing to save
LOGE("array is null");
return JNI_FALSE;
}
*/
//Get options
//Get compression mode from options object
jfieldID gOptions_CompressionModeFieldID = env->GetFieldID(jSaveOptionsClass,
"compressionScheme",
"Lorg/beyka/tiffbitmapfactory/CompressionScheme;");
jobject compressionMode = env->GetObjectField(options, gOptions_CompressionModeFieldID);
jclass compressionModeClass = env->FindClass(
"org/beyka/tiffbitmapfactory/CompressionScheme");
jfieldID ordinalFieldID = env->GetFieldID(compressionModeClass, "ordinal", "I");
jint compressionInt = env->GetIntField(compressionMode, ordinalFieldID);
//Get image orientation from options object
jfieldID gOptions_OrientationFieldID = env->GetFieldID(jSaveOptionsClass,
"orientation",
"Lorg/beyka/tiffbitmapfactory/Orientation;");
jobject orientation = env->GetObjectField(options, gOptions_OrientationFieldID);
jclass orientationClass = env->FindClass(
"org/beyka/tiffbitmapfactory/Orientation");
jfieldID orientationOrdinalFieldID = env->GetFieldID(orientationClass, "ordinal", "I");
jint orientationInt = env->GetIntField(orientation, orientationOrdinalFieldID);
env->DeleteLocalRef(orientationClass);
// variables for resolution
jfieldID gOptions_xResolutionFieldID = env->GetFieldID(jSaveOptionsClass, "xResolution", "F");
float xRes = env->GetFloatField(options, gOptions_xResolutionFieldID);
jfieldID gOptions_yResolutionFieldID = env->GetFieldID(jSaveOptionsClass, "yResolution", "F");
float yRes = env->GetFloatField(options, gOptions_yResolutionFieldID);
jfieldID gOptions_resUnitFieldID = env->GetFieldID(jSaveOptionsClass,
"resUnit",
"Lorg/beyka/tiffbitmapfactory/ResolutionUnit;");
jobject resUnitObject = env->GetObjectField(options, gOptions_resUnitFieldID);
//Get res int from resUnitObject
jclass resolutionUnitClass = env->FindClass("org/beyka/tiffbitmapfactory/ResolutionUnit");
jfieldID resUnitOrdinalFieldID = env->GetFieldID(resolutionUnitClass, "ordinal", "I");
uint16 resUnit = env->GetIntField(resUnitObject, resUnitOrdinalFieldID);
env->DeleteLocalRef(resolutionUnitClass);
//Get author field if exist
jfieldID gOptions_authorFieldID = env->GetFieldID(jSaveOptionsClass, "author", "Ljava/lang/String;");
jstring jAuthor = (jstring)env->GetObjectField(options, gOptions_authorFieldID);
const char *authorString = NULL;
if (jAuthor) {
authorString = env->GetStringUTFChars(jAuthor, 0);
LOGIS("Author: ", authorString);
}
//Get copyright field if exist
jfieldID gOptions_copyrightFieldID = env->GetFieldID(jSaveOptionsClass, "copyright", "Ljava/lang/String;");
jstring jCopyright = (jstring)env->GetObjectField(options, gOptions_copyrightFieldID);
const char *copyrightString = NULL;
if (jCopyright) {
copyrightString = env->GetStringUTFChars(jCopyright, 0);
LOGIS("Copyright: ", copyrightString);
}
//Get image description field if exist
jfieldID gOptions_imgDescrFieldID = env->GetFieldID(jSaveOptionsClass, "imageDescription", "Ljava/lang/String;");
jstring jImgDescr = (jstring)env->GetObjectField(options, gOptions_imgDescrFieldID);
const char *imgDescrString = NULL;
if (jImgDescr) {
imgDescrString = env->GetStringUTFChars(jImgDescr, 0);
LOGIS("Image Description: ", imgDescrString);
}
//Get software name and number from buildconfig
jclass jBuildConfigClass = env->FindClass(
"org/beyka/tiffbitmapfactory/BuildConfig");
jfieldID softwareNameFieldID = env->GetStaticFieldID(jBuildConfigClass, "softwarename", "Ljava/lang/String;");
jstring jsoftwarename = (jstring)env->GetStaticObjectField(jBuildConfigClass, softwareNameFieldID);
const char *softwareNameString = NULL;
if (jsoftwarename) {
softwareNameString = env->GetStringUTFChars(jsoftwarename, 0);
LOGIS("Software Name: ", softwareNameString);
}
//Get android version
jclass build_class = env->FindClass("android/os/Build$VERSION");
jfieldID releaseFieldID = env->GetStaticFieldID(build_class, "RELEASE", "Ljava/lang/String;");
jstring jrelease = (jstring)env->GetStaticObjectField(build_class, releaseFieldID);
const char *releaseString = NULL;
if (jrelease) {
releaseString = env->GetStringUTFChars(jrelease, 0);
LOGIS("Release: ", releaseString);
}
char *fullReleaseName = concat("Android ", releaseString);
LOGIS("Full Release: ", fullReleaseName);
uint32 pixelsBufferSize = img_width * img_height;
uint32* img = NULL;
int tmpImgArrayCreated = 0;
switch (info.format) {
case ANDROID_BITMAP_FORMAT_RGBA_8888:
{
LOGI("ANDROID_BITMAP_FORMAT_RGBA_8888");
img = (uint32*)pixels;
break;
}
case ANDROID_BITMAP_FORMAT_RGBA_4444:
{
LOGI("ANDROID_BITMAP_FORMAT_RGBA_4444");
uint16_t* tmp4444 = (uint16_t*)pixels;
img = (uint32*) malloc(sizeof(uint32) * pixelsBufferSize);
for (int x = 0; x < img_width; x++) {
for (int y = 0; y < img_height; y++) {
uint16_t pix = tmp4444[y * img_width + x];
int alpha = colorMask & pix >> 16;
int red = colorMask & pix >> 8;
int green = colorMask & pix >> 4;
int blue = colorMask & pix;
uint32 crPix = (alpha << 24) | (blue << 16) | (green << 8) | (red);
img[y * img_width + x] = crPix;
}
}
tmpImgArrayCreated = 1;
break;
}
case ANDROID_BITMAP_FORMAT_RGB_565:
{
LOGI("ANDROID_BITMAP_FORMAT_RGB_565");
uint16_t* tmp565 = (uint16_t*)pixels;
img = (uint32*) malloc(sizeof(uint32) * pixelsBufferSize);
for (int x = 0; x < img_width; x++) {
for (int y = 0; y < img_height; y++) {
uint16_t pix = tmp565[y * img_width + x];
unsigned char red = 0b11111 & pix >> 11;
unsigned char green = 0b111111 & pix >> 5;
unsigned char blue = 0b11111 & pix;
uint32 crPix = (blue << 3 << 16) | (green << 2 << 8) | (red<<3);
img[y * img_width + x] = crPix;
}
}
tmpImgArrayCreated = 1;
break;
}
case ANDROID_BITMAP_FORMAT_A_8:
{
LOGI("ANDROID_BITMAP_FORMAT_A_8");
uint8_t* tmp8 = (uint8_t*)pixels;
img = (uint32*) malloc(sizeof(uint32) * pixelsBufferSize);
for (int x = 0; x < img_width; x++) {
for (int y = 0; y < img_height; y++) {
uint8_t pix = tmp8[y * img_width + x];
img[y * img_width + x] = pix << 24;
}
}
tmpImgArrayCreated = 1;
break;
}
}
/*
int pixelsBufferSize = img_width * img_height;
uint32 *array = (uint32 *) malloc(sizeof(uint32) * pixelsBufferSize);
if (!array) {
throw_not_enought_memory_exception(env, sizeof(uint32) * pixelsBufferSize, 0);//todo change for estimating memory
return JNI_FALSE;
}
uint32_t* img = (uint32_t*)pixels;
for (int y = 0; y < img_height; y++) {
for (int x = 0; x < img_width; x++) {
uint32_t pix = img[y * img_width + x];
int alpha = colorMask & pix >> 24;
int red = colorMask & pix >> 16;
int green = colorMask & pix >> 8;
int blue = colorMask & pix;
uint32 crPix = (alpha << 24) | (blue << 16) | (green << 8) | (red);
array[y * img_width + x] = crPix;
}
}
*/
/*
for (int i = 0; i < img_width; i++) {
for (int j = 0; j < img_height; j++) {
uint32 crPix = getPixel(pixels,info,i,j);
//jint crPix = c_array[j * img_width + i];
int alpha = colorMask & crPix >> 24;
int red = colorMask & crPix >> 16;
int green = colorMask & crPix >> 8;
int blue = colorMask & crPix;
crPix = (alpha << 24) | (blue << 16) | (green << 8) | (red);
array[j * img_width + i] = crPix;
}
}
*/
TIFF *output_image;
LOGII("Check file descripor", fileDescriptor);
const char *strPath = NULL;
if (fileDescriptor == -1) {
strPath = env->GetStringUTFChars(filePath, 0);
LOGIS("nativeTiffOpenForSave", strPath);
int mode = O_RDWR | O_CREAT | O_TRUNC | 0;
if (append) {
mode = O_RDWR | O_CREAT;
}
fileDescriptor = open(strPath, mode, 0666);
if (fileDescriptor < 0) {
throw_cant_open_file_exception(env, filePath);
return JNI_FALSE;
}
}
// Open the TIFF file
if (!append) {
if ((output_image = TIFFFdOpen(fileDescriptor, "", "w")) == NULL) {
LOGE("Unable to write tif file");
if (strPath) {
throw_cant_open_file_exception(env, filePath);
} else {
throw_cant_open_file_exception_fd(env, fileDescriptor);
}
return JNI_FALSE;
}
} else {
if ((output_image = TIFFFdOpen(fileDescriptor, "", "a")) == NULL) {
LOGE("Unable to write tif file");
if (strPath) {
throw_cant_open_file_exception(env, filePath);
} else {
throw_cant_open_file_exception_fd(env, fileDescriptor);
return JNI_FALSE;
}
}
}
TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, img_width);
TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, img_height);
TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(output_image, TIFFTAG_COMPRESSION, compressionInt);
TIFFSetField(output_image, TIFFTAG_ORIENTATION, orientationInt);
TIFFSetField(output_image, TIFFTAG_XRESOLUTION, xRes);
TIFFSetField(output_image, TIFFTAG_YRESOLUTION, yRes);
TIFFSetField(output_image, TIFFTAG_RESOLUTIONUNIT, resUnit);
if (compressionInt == COMPRESSION_CCITTRLE ||compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(output_image, TIFFTAG_ROWSPERSTRIP, 1);
TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(output_image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
} else {
TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 4);
TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
}
//Write additiona tags
//CreationDate tag
char *date = getCreationDate();
TIFFSetField(output_image, TIFFTAG_DATETIME, date);
free(date);
//Host system
TIFFSetField(output_image, TIFFTAG_HOSTCOMPUTER, fullReleaseName);
//software
if (softwareNameString) {
TIFFSetField(output_image, TIFFTAG_SOFTWARE, softwareNameString);
}
//image description
if (imgDescrString) {
TIFFSetField(output_image, TIFFTAG_IMAGEDESCRIPTION, imgDescrString);
}
//author
if (authorString) {
TIFFSetField(output_image, TIFFTAG_ARTIST, authorString);
}
//copyright
if (copyrightString) {
TIFFSetField(output_image, TIFFTAG_COPYRIGHT, copyrightString);
}
// Write the information to the file
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
unsigned char *bilevel = convertArgbToBilevel(img, img_width, img_height);
int compressedWidth = (img_width/8 + 0.5);
for (int i = 0; i < img_height; i++) {
TIFFWriteEncodedStrip(output_image, i, &bilevel[i * compressedWidth], (compressedWidth));
}
free(bilevel);
} else if (compressionInt == COMPRESSION_JPEG) {
for (int row = 0; row < img_height; row++) {
TIFFWriteScanline(output_image, &img[row * img_width], row, 0);
}
} else {
TIFFSetField(output_image, TIFFTAG_ROWSPERSTRIP, 1);
for (int row = 0; row < img_height; row++) {
TIFFWriteEncodedStrip(output_image, row, &img[row * img_width], img_width * sizeof(uint32));
//TIFFWriteScanline(output_image, &img[row * img_width], row, 0);
}
}
ret = TIFFWriteDirectory(output_image);
LOGII("ret = ", ret);
// Close the file
TIFFClose(output_image);
/*
//free temp array
free (array);
*/
if (tmpImgArrayCreated) {
free(img);
}
//Now we don't need android pixels, so unlock
AndroidBitmap_unlockPixels(env, bitmap);
//Remove variables
if (releaseString) {
env->ReleaseStringUTFChars(jrelease, releaseString);
}
free(fullReleaseName);
if (softwareNameString) {
env->ReleaseStringUTFChars(jsoftwarename, softwareNameString);
}
if (imgDescrString) {
env->ReleaseStringUTFChars(jImgDescr, imgDescrString);
}
if (authorString) {
env->ReleaseStringUTFChars(jAuthor, authorString);
}
if (copyrightString) {
env->ReleaseStringUTFChars(jCopyright, copyrightString);
}
if (strPath) {
env->ReleaseStringUTFChars(filePath, strPath);
}
// env->ReleaseIntArrayElements(img, c_array, 0);
if (ret == -1) return JNI_FALSE;
return JNI_TRUE;
}
unsigned char *convertArgbToBilevel(uint32 *source, jint width, jint height) {
long long threshold = 0;
uint32 crPix;
uint32 grayPix;
int bilevelWidth = (width / 8 + 0.5);
unsigned char *dest = (unsigned char *) malloc(sizeof(unsigned char) * bilevelWidth * height);
uint32 maxGrey = (0.2125 * 255 + 0.7154 * 255 + 0.0721 * 255);
uint32 halfGrey = maxGrey/2;
uint32 shift = 0;
unsigned char charsum = 0;
int k = 7;
for (int j = 0; j < height; j++) {
shift = 0;
charsum = 0;
k = 7;
for (int i = 0; i < width; i++) {
crPix = source[j * width + i];
grayPix = (0.2125 * (colorMask & crPix >> 16) + 0.7154 * (colorMask & crPix >> 8) + 0.0721 * (colorMask & crPix));
if (grayPix < halfGrey) charsum &= ~(1 << k);
else charsum |= 1 << k;
if (k == 0) {
dest[j * bilevelWidth + shift] = charsum;
shift++;
k = 7;
charsum = 0;
} else {
k--;
}
}
}
return dest;
}
char *getCreationDate() {
char * datestr = (char *) malloc(sizeof(char) * 20);
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
strftime (datestr,20,/*"Now it's %I:%M%p."*/"%Y:%m:%d %H:%M:%S",timeinfo);
return datestr;
}
char* concat(const char *s1, const char *s2)
{
char *result = (char *)malloc(strlen(s1)+strlen(s2)+1);//+1 for the zero-terminator
//in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
JNIEXPORT jobject
JNICALL Java_org_beyka_tiffbitmapfactory_TiffSaver_nativeCloseFd
(JNIEnv *env, jclass clazz, jint fd) {
close(fd);
}
#ifdef __cplusplus
}
#endif
================================================
FILE: src/main/jni/NativeTiffSaver.h
================================================
#include
#include
#include
#include
#include
#include
#include "fcntl.h"
#include "unistd.h"
#include
#include "string.h"
#include "NativeExceptions.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffSaver", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffSaver", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffSaver", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "NativeTiffSaver", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "NativeTiffSaver", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "NativeTiffSaver", "%s %s", x, y)
#endif
#ifndef _Included_org_beyka_tiffbitmapfactory_TiffSaver
#define _Included_org_beyka_tiffbitmapfactory_TiffSaver
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_beyka_tiffbitmapfactory_TiffSaver
* Method: save
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT jboolean JNICALL Java_org_beyka_tiffbitmapfactory_TiffSaver_save
(JNIEnv *, jclass, jstring, jint, jobject, jobject, jboolean);
JNIEXPORT jobject JNICALL Java_org_beyka_tiffbitmapfactory_TiffSaver_nativeCloseFd
(JNIEnv *, jclass, jint);
unsigned char *convertArgbToBilevel(uint32 *, jint, jint);
char *getCreationDate();
char *concat(const char *, const char *);
#ifdef __cplusplus
}
#endif
#endif
================================================
FILE: src/main/jni/PngToTiffConverter.cpp
================================================
//
// Created by beyka on 5/12/17.
//
#include "PngToTiffConverter.h"
PngToTiffConverter::PngToTiffConverter(JNIEnv *e, jclass clazz, jstring in, jstring out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
png_ptr_init = 0;
png_info_init = 0;
compressionInt = 5;
}
PngToTiffConverter::PngToTiffConverter(JNIEnv *e, jclass clazz, jint in, jint out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
png_ptr_init = 0;
png_info_init = 0;
compressionInt = 5;
}
PngToTiffConverter::~PngToTiffConverter() {
if (tiffImage) {
TIFFClose(tiffImage);
tiffImage = NULL;
}
if (png_info_init) {
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
}
if (png_ptr_init) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
}
if (inFile) {
fclose(inFile);
}
}
jboolean PngToTiffConverter::convert()
{
readOptions();
//open tiff file for writing or appending
if(outFd < 0) {
//open tiff file for writing or appending
const char *outCPath = NULL;
outCPath = env->GetStringUTFChars(outPath, 0);
LOGIS("OUT path", outCPath);
LOGIS("nativeTiffOpenForSave", outCPath);
int mode = O_RDWR | O_CREAT | O_TRUNC | 0;
if (appendTiff) {
mode = O_RDWR | O_CREAT;
}
outFd = open(outCPath, mode, 0666);
if (outFd < 0) {
throw_cant_open_file_exception(env, outPath);
env->ReleaseStringUTFChars(outPath, outCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(outPath, outCPath);
}
if (!appendTiff) {
if ((tiffImage = TIFFFdOpen(outFd, "", "w")) == NULL) {
LOGE("Unable to open tif file");
if (throwException) {
throw_cant_open_file_exception_fd(env, outFd);
}
return JNI_FALSE;
}
} else {
if ((tiffImage = TIFFFdOpen(outFd, "", "a")) == NULL) {
LOGE("Unable to open tif file");
if (throwException) {
throw_cant_open_file_exception_fd(env, outFd);
}
return JNI_FALSE;
}
}
//open png file fow reading
if (inFd == -1) {
const char *inCPath = NULL;
inCPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", inCPath);
inFile = fopen(inCPath, "rb");
if (!inFile) {
if (throwException) {
throw_cant_open_file_exception(env, inPath);
}
LOGES("Can\'t open in file", inCPath);
env->ReleaseStringUTFChars(inPath, inCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(inPath, inCPath);
} else {
inFile = fdopen(inFd, "rb");
if (!inFile) {
if (throwException) {
throw_cant_open_file_exception_fd(env, inFd);
}
LOGES("Can\'t open out file descriptor", inFd);
return JNI_FALSE;
}
}
//read file header
size_t byte_count = 8;
unsigned char *header = (unsigned char *)malloc(sizeof(unsigned char) * byte_count);
fread(header, 1, byte_count, inFile);
//check is file is PNG or not
bool is_png = !png_sig_cmp(header, 0, byte_count);
if (!is_png) {
LOGE("Not png file");
if (throwException) {
if (inFd == -1) {
throw_cant_open_file_exception(env, inPath);
} else {
throw_cant_open_file_exception_fd(env, inFd);
}
}
return JNI_FALSE;
} else {
LOGI("Is png");
}
//init png struct
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
const char *message = "Can\'t create PNG structure";
LOGE(*message);
if (throwException) {
jstring er = env->NewStringUTF(message);
if (inFd < 0) {
throw_decode_file_exception(env, inPath, er);
} else {
throw_decode_file_exception_fd(env, inFd, er);
}
env->DeleteLocalRef(er);
}
return JNI_FALSE;
}
png_ptr_init = 1;
png_set_sig_bytes(png_ptr, byte_count);
//create png info pointer
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
const char *message = "Can\'t create PNG info structure";
LOGE(*message);
if (throwException) {
jstring er = env->NewStringUTF(message);
if (inFd < 0) {
throw_decode_file_exception(env, inPath, er);
} else {
throw_decode_file_exception_fd(env, inFd, er);
}
env->DeleteLocalRef(er);
}
return JNI_FALSE;
}
png_info_init = 1;
//png error handler
if (setjmp(png_jmpbuf(png_ptr))) {
const char *message = "Error reading PNG";
LOGE(message);
if (throwException) {
jstring er = env->NewStringUTF(message);
if (inFd < 0) {
throw_decode_file_exception(env, inPath, er);
} else {
throw_decode_file_exception_fd(env, inFd, er);
}
env->DeleteLocalRef(er);
}
return JNI_FALSE;
}
//Init PNG IO
png_init_io(png_ptr, inFile);
//seek file header
png_set_sig_bytes(png_ptr, byte_count);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
LOGII("width", width);
LOGII("height", height);
LOGII("bit_depth", bit_depth);
LOGII("color_type", color_type);
// cast any pixel data to RGBA data for simplest reading
if(bit_depth == 16)
png_set_strip_16(png_ptr);
if(color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand_gray_1_2_4_to_8(png_ptr);
if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
// These color_type don't have an alpha channel then fill it with 0xff.
if(color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_PALETTE)
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
if(color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
int number_passes = png_set_interlace_handling(png_ptr);
LOGII("number_passes", number_passes);
png_read_update_info(png_ptr, info_ptr);
LOGII("compression", compressionInt);
//Set tiff parameters
//Set various text parameters
//Set image parameters
TIFFSetField(tiffImage, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tiffImage, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tiffImage, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tiffImage, TIFFTAG_COMPRESSION, compressionInt);
TIFFSetField(tiffImage, TIFFTAG_ORIENTATION, orientationInt);
TIFFSetField(tiffImage, TIFFTAG_XRESOLUTION, xRes);
TIFFSetField(tiffImage, TIFFTAG_YRESOLUTION, yRes);
TIFFSetField(tiffImage, TIFFTAG_RESOLUTIONUNIT, resUnit);
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
TIFFSetField(tiffImage, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(tiffImage, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tiffImage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tiffImage, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
} else {
TIFFSetField(tiffImage, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(tiffImage, TIFFTAG_SAMPLESPERPIXEL, 4);
TIFFSetField(tiffImage, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
}
//creation date
char *date = getCreationDate();
TIFFSetField(tiffImage, TIFFTAG_DATETIME, date);
free(date);
//image description
if (cdescription) {
TIFFSetField(tiffImage, TIFFTAG_IMAGEDESCRIPTION, cdescription);
}
//software tag
if (csoftware) {
TIFFSetField(tiffImage, TIFFTAG_SOFTWARE, csoftware);
}
//Calculate row per strip
//maximum size for strip should be less than 2Mb if memory available
unsigned long MB2 = (availableMemory == -1 || availableMemory > 3 * 1024 * 1024) ? 2 * 1024 * 1024 : width * 4;
unsigned long rowSizeBytes = width * 4;
int rowPerStrip = MB2/rowSizeBytes;
if (rowPerStrip >= height) {
rowPerStrip = height / 4;
}
if (rowPerStrip < 1) rowPerStrip = 1;
LOGII("rowPerStrip", rowPerStrip);
//check available memory and estimate memory
unsigned long estimateMem = rowPerStrip * width * 4;
estimateMem += (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) ? (width/8 + 0.5) * rowPerStrip : 0;
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enough memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
if (checkStop()) {
conversion_result = JNI_FALSE;
return conversion_result;
}
//progress reporter
jlong total = width * height;
sendProgress(0, total);
int rowbytes = png_get_rowbytes(png_ptr,info_ptr);
png_bytep row_pointers[rowPerStrip];
for (int sy = 0; sy < rowPerStrip; sy++) {
row_pointers[sy] = (png_byte*)malloc(rowbytes);
}
int ret;
// Write the information to the file
if (compressionInt == COMPRESSION_CCITTRLE || compressionInt == COMPRESSION_CCITTFAX3 || compressionInt == COMPRESSION_CCITTFAX4) {
TIFFSetField(tiffImage, TIFFTAG_ROWSPERSTRIP, rowPerStrip);
int compressedWidth = (width/8 + 0.5);
for (int y = 0; y < height; y+=rowPerStrip) {
if (checkStop()) {
for (int sy = 0; sy < rowPerStrip; sy++) {
free(row_pointers[sy]);
}
conversion_result = JNI_FALSE;
return conversion_result;
}
int rowToRead = rowPerStrip;
if (rowToRead + y >= height) {
rowToRead = height - y;
}
sendProgress(y * width, total);
png_read_rows(png_ptr, &row_pointers[0], NULL, rowToRead);
unsigned char *bilevel = convertArgbToBilevel(&row_pointers[0], 4, width, rowToRead);
TIFFWriteEncodedStrip(tiffImage, y/rowPerStrip, bilevel, compressedWidth * sizeof(unsigned char) * rowToRead);
free(bilevel);
}
} else if (compressionInt == COMPRESSION_JPEG) {
for (int ys = 0; ys < height; ys+=rowPerStrip) {
if (checkStop()) {
for (int sy = 0; sy < rowPerStrip; sy++) {
free(row_pointers[sy]);
}
conversion_result = JNI_FALSE;
return conversion_result;
}
int rowToRead = rowPerStrip;
if (rowToRead + ys >= height) {
rowToRead = height - ys;
}
LOGII("rowToRead", rowToRead);
sendProgress(ys * width, total);
png_read_rows(png_ptr, &row_pointers[0], NULL, rowToRead);
uint32 *pixels = new uint32[width];
for (int k = 0; k < rowToRead; k++) {
memcpy(pixels, row_pointers[k], width * sizeof(uint32));
ret = TIFFWriteScanline(tiffImage, pixels, ys + k, 0);
}
//TIFFWriteEncodedStrip(tiffImage, y/rowPerStrip, pixels, width * sizeof(uint32) * rowToRead);
delete[] pixels;
}
} else {
TIFFSetField(tiffImage, TIFFTAG_ROWSPERSTRIP, rowPerStrip);
for (int y = 0; y < height; y+=rowPerStrip) {
if (checkStop()) {
for (int sy = 0; sy < rowPerStrip; sy++) {
free(row_pointers[sy]);
}
conversion_result = JNI_FALSE;
return conversion_result;
}
int rowToRead = rowPerStrip;
if (rowToRead + y >= height) {
rowToRead = height - y;
}
LOGII("rowToRead", rowToRead);
sendProgress(y * width, total);
png_read_rows(png_ptr, &row_pointers[0], NULL, rowToRead);
uint32 *pixels = new uint32[width * rowPerStrip];
for (int k = 0; k < rowToRead; k++) {
memcpy(pixels+k*width, row_pointers[k], width * sizeof(uint32));
}
TIFFWriteEncodedStrip(tiffImage, y/rowPerStrip, pixels, width * sizeof(uint32) * rowToRead);
delete[] pixels;
}
}
//free memory allocated for png rows
for (int sy = 0; sy < rowPerStrip; sy++) {
free(row_pointers[sy]);
}
ret = TIFFWriteDirectory(tiffImage);
LOGII("ret = ", ret);
sendProgress(total, total);
conversion_result = JNI_TRUE;
return conversion_result;
}
unsigned char * PngToTiffConverter::convertArgbToBilevel(png_bytep *data, int samplePerPixel, uint32 width, uint32 height) {
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;
uint32 crPix;
uint32 grayPix;
int bilevelWidth = (width / 8 + 0.5);
unsigned char *dest = (unsigned char *) malloc(sizeof(unsigned char) * bilevelWidth * height);
uint32 maxGrey = (0.2125 * 255 + 0.7154 * 255 + 0.0721 * 255);
uint32 halfGrey = maxGrey/2;
uint32 shift = 0;
unsigned char charsum = 0;
int k = 7;
for (int y = 0; y < height; y++) {
shift = 0;
charsum = 0;
k = 7;
png_bytep row = data[y];
for (int i = 0; i < width; i++) {
png_bytep px = &(row[i * samplePerPixel]);
red = px[0];
green = px[1];
blue = px[2];
grayPix = (0.2125 * red + 0.7154 * green + 0.0721 * blue);
if (grayPix < halfGrey) charsum &= ~(1 << k);
else charsum |= 1 << k;
if (k == 0) {
dest[y * bilevelWidth + shift] = charsum;
shift++;
k = 7;
charsum = 0;
} else {
k--;
}
}
}
return dest;
}
================================================
FILE: src/main/jni/PngToTiffConverter.h
================================================
//
// Created by beyka on 5/12/17.
//
#ifndef TIFFSAMPLE_PNGTOTIFFCONVERTER_H
#define TIFFSAMPLE_PNGTOTIFFCONVERTER_H
#include
#include
#include
#include "fcntl.h"
#include "unistd.h"
#include
#include
#include "BaseTiffConverter.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#define LOGEI(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "PngToTiffConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "PngToTiffConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "PngToTiffConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "PngToTiffConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "PngToTiffConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "PngToTiffConverter", "%s %s", x, y)
#define LOGEI(x, y) __android_log_print(ANDROID_LOG_ERROR, "PngToTiffConverter", "%s %d", x, y)
#endif
class PngToTiffConverter : public BaseTiffConverter
{
public:
explicit PngToTiffConverter(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
explicit PngToTiffConverter(JNIEnv *, jclass, jint, jint, jobject, jobject);
~PngToTiffConverter();
virtual jboolean convert();
private:
TIFF *tiffImage;
FILE *inFile;
char png_ptr_init;
png_structp png_ptr;
char png_info_init;
png_infop info_ptr;
int bit_depth;
int color_type;
//unsigned char * convertArgbToBilevel(png_byte *, int, uint32, uint32);
unsigned char * convertArgbToBilevel(png_bytep *, int, uint32, uint32);
};
#endif //TIFFSAMPLE_PNGTOTIFFCONVERTER_H
================================================
FILE: src/main/jni/TiffToBmpConverter.cpp
================================================
//
// Created by beyka on 9/22/17.
//
#include "TiffToBmpConverter.h"
#include "BMP.h"
TiffToBmpConverter::TiffToBmpConverter(JNIEnv *e, jclass clazz, jstring in, jstring out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
bmpHeader = new BITMAPFILEHEADER;
bmpInfo = new BITMAPINFOHEADER;
}
TiffToBmpConverter::TiffToBmpConverter(JNIEnv *e, jclass clazz, jint in, jint out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
bmpHeader = new BITMAPFILEHEADER;
bmpInfo = new BITMAPINFOHEADER;
}
TiffToBmpConverter::~TiffToBmpConverter()
{
if (bmpHeader)
free(bmpHeader);
if (bmpInfo)
free(bmpInfo);
}
jboolean TiffToBmpConverter::convert()
{
readOptions();
LOGI("Optioons read done");
LOGII("inFd=", inFd);
if (inFd == -1) {
const char *inCPath = NULL;
inCPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", inCPath);
inFd = open(inCPath, O_RDWR, 0666);
if (inFd == -1) {
if (throwException) {
throw_cant_open_file_exception(env, inPath);
}
LOGES("Can\'t open in file", inCPath);
env->ReleaseStringUTFChars(inPath, inCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(inPath, inCPath);
}
//open tiff image for reading
tiffImage = TIFFFdOpen(inFd, "", "r");
if (tiffImage == NULL) {
if (throwException) {
if (inFd < 0) {
throw_cant_open_file_exception(env, inPath);
} else {
throw_cant_open_file_exception_fd(env, inFd);
}
}
return JNI_FALSE;
}
LOGI("Tiff file opened for reading");
//open bmp file for writing
LOGII("outFd=", outFd);
if(outFd == -1) {
LOGI("Opening bmp as File");
//open tiff file for writing or appending
const char *outCPath = NULL;
outCPath = env->GetStringUTFChars(outPath, 0);
LOGIS("OUT path", outCPath);
outFIle = fopen(outCPath, "w");
if (!outFIle) {
throw_cant_open_file_exception(env, outPath);
env->ReleaseStringUTFChars(outPath, outCPath);
return JNI_FALSE;
}
} else {
LOGI("Opening bmp as FD");
outFIle = fdopen(outFd, "w");
if (!outFIle) {
LOGI("BMP file is null");
if (throwException) {
throw_cant_open_file_exception_fd(env, inFd);
}
LOGES("Can\'t open out file descriptor", inFd);
return JNI_FALSE;
}
}
LOGI("BMP file opened");
//set tiff directory and read image dimensions
TIFFSetDirectory(tiffImage, tiffDirectory);
TIFFGetField(tiffImage, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tiffImage, TIFFTAG_IMAGELENGTH, &height);
//Getting image orientation and createing ImageOrientation enum
TIFFGetField(tiffImage, TIFFTAG_ORIENTATION, &origorientation);
//If orientation field is empty - use ORIENTATION_TOPLEFT
if (origorientation == 0) {
origorientation = ORIENTATION_TOPLEFT;
}
if (!normalizeDecodeArea()) {
fclose(outFIle);
return JNI_FALSE;
}
LOGII("image width", width);
LOGII("image height", height);
LOGII("image bound width", boundWidth);
LOGII("image bound height", boundHeight);
unsigned long long imageDataSize = (outWidth * 3 + outWidth % 4) * outHeight;
LOGII("image out width", outWidth);
LOGII("image out height", outHeight);
LOGII("image data size", imageDataSize);
LOGII("size", sizeof(BITMAPINFOHEADER));
//char *bm = "BM";
//memcpy(&bmpHeader->bfType, bm, sizeof(short));
bmpHeader->bfType[0] = 0x42;
bmpHeader->bfType[1] = 0x4d;
bmpHeader->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + imageDataSize;//sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * width * height;
bmpHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//sizeof(BITMAPFILEHEADER) + 108;
bmpInfo->biSize = 108;
bmpInfo->biWidth = outWidth;
bmpInfo->biHeight = outHeight;
bmpInfo->biBitCount = 24;
bmpInfo->biPlanes = 1;
bmpInfo->biCompression = 0;
bmpInfo->biSizeImage = 0;//imageDataSize;
bmpInfo->biClrUsed = 0;
bmpInfo->biClrImportant = 0;
bmpInfo->biPalete[0] = 0;
bmpInfo->biPalete[1] = 0;
bmpInfo->biPalete[2] = 0;
for (int i = 0; i < 55; i++) {
bmpInfo->reserved[i] = 0;
}
fwrite(bmpHeader,sizeof(BITMAPFILEHEADER),1,outFIle);
fseek(outFIle, sizeof(BITMAPFILEHEADER) , SEEK_SET);
fwrite(bmpInfo,sizeof(BITMAPINFOHEADER),1,outFIle);
fseek(outFIle, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) , SEEK_SET);
jboolean result = JNI_FALSE;
switch(getDecodeMethod()) {
case DECODE_METHOD_IMAGE:
result = convertFromImage();
break;
case DECODE_METHOD_TILE:
result = convertFromTile();
break;
case DECODE_METHOD_STRIP:
result = convertFromStrip();
break;
}
fclose(outFIle);
if (!result) {
//maybe shold delete file?
}
LOGI("fille closed");
conversion_result = result;
return conversion_result;
//return JNI_FALSE;
}
jboolean TiffToBmpConverter::convertFromImage() {
int origBufferSize = width * height * sizeof(uint32);
unsigned long estimateMem = origBufferSize;
estimateMem += outWidth * 3 + outWidth % 4; //working buf to write to file
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enough memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
uint32 *origBuffer = NULL;
origBuffer = (uint32 *) _TIFFmalloc(origBufferSize);
if (origBuffer == NULL) {
const char *message = "Can\'t allocate buffer";
LOGE(*message);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, origBufferSize);
}
return JNI_FALSE;
}
if (0 == TIFFReadRGBAImageOriented(tiffImage, width, height, origBuffer, ORIENTATION_TOPLEFT, 0)) {
free(origBuffer);
const char *message = "Can\'t read tiff";
if (throwException) {
jstring er = env->NewStringUTF(message);
if (outFd == -1) {
throw_decode_file_exception(env, outPath, er);
} else {
throw_decode_file_exception_fd(env, outFd, er);
}
env->DeleteLocalRef(er);
}
LOGE(message);
return JNI_FALSE;
}
LOGI("tiff read");
jlong total = outWidth * outHeight;
int outY, outX;
sendProgress(0, total);
//24 bpp bmp should has with multiple 4
int rowSize = outWidth * 3 + outWidth % 4;
unsigned char *row = new unsigned char[rowSize];
for (int y = 0; y < height ; y++) {
if (y < outStartY || y >= outStartY + outHeight) continue;
if (checkStop()) {
free(origBuffer);
return JNI_FALSE;
}
outY = y - outStartY;
sendProgress(outY * outWidth, total);
for (int x = 0; x < width * 3; x += 3) {
if (x < outStartX * 3 || x >= (outStartX + outWidth) * 3) continue;
outX = x - (outStartX*3);
uint32 pix = origBuffer[y * width + x/3];
unsigned char *vp = (unsigned char *)&pix;
//in bmp colors stores as bgr
row[outX] = vp[2]; //red
row[outX+1] = vp[1]; //green
row[outX+2] = vp[0]; //blue
}
//in bmp lines stored fliped verticaly. Write lines from bottom to top
fseek(outFIle, 122 + (outHeight - outY - 1) * rowSize , SEEK_SET);
fwrite(row,rowSize,1,outFIle);
}
free(row);
LOGI("exit for");
if (origBuffer) {
_TIFFfree(origBuffer);
}
LOGI("free orig");
sendProgress(total, total);
LOGI("dend progress");
return JNI_TRUE;
}
jboolean TiffToBmpConverter::convertFromTile() {
uint32 tileWidth = 0, tileHeight = 0;
TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileHeight);
LOGII("Tile width", tileWidth);
LOGII("Tile height", tileHeight);
uint32 workingWidth = (width/tileWidth + (width%tileWidth == 0 ? 0 : 1)) * tileWidth;
LOGII("workingWidth ", workingWidth );
uint32 rasterSize = workingWidth * tileHeight ;
LOGII("rasterSize ", rasterSize );
unsigned long estimateMem = rasterSize * sizeof(uint32); //raster
estimateMem += tileWidth * tileHeight * sizeof(uint32); //tile raster
estimateMem += tileWidth * sizeof (uint32); //working buf
estimateMem += width * 3 + width % 4; //bufer for writing scanline to bmp
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enought memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
uint32 *rasterTile = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
uint32 *work_line_buf = (uint32*)_TIFFmalloc(tileWidth * sizeof (uint32));
jlong total = ((width/tileWidth + (width%tileWidth == 0 ? 0 : 1)) * tileWidth)
* ((height/tileHeight + (height%tileHeight == 0 ? 0 : 1)) * tileHeight);
sendProgress(0, total);
uint32 row, column;
int startx = -1, starty = -1, endx = -1, endy = -1;
uint32 imageWritedLines = 0;
//24 bpp bmp should has with multiple 4
int scanlineSize = outWidth * 3 + outWidth % 4;
unsigned char *scanline = new unsigned char[scanlineSize];
for (row = 0; row < height; row += tileHeight) {
sendProgress(row * width, total);
endy = -1;
starty = -1;
uint32 *raster = (uint32 *)_TIFFmalloc(rasterSize * sizeof(uint32));
for (column = 0; column < width; column += tileWidth) {
if (checkStop()) {
free(raster);
raster = NULL;
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (work_line_buf) {
_TIFFfree(rasterTile);
work_line_buf = NULL;
}
return JNI_FALSE;
}
endx = -1;
startx = -1;
TIFFReadRGBATile(tiffImage, column , row, rasterTile);
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
}
normalizeTile(tileHeight, tileWidth, rasterTile);
//find start and end position
for (int ty = 0; ty < tileHeight; ty++) {
for (int tx = 0; tx < tileWidth; tx++) {
if (rasterTile[ty * tileWidth + tx] != 0) {
if (startx == -1) {
startx = tx;
}
if (starty == -1) {
starty = ty;
}
if (tx > endx)
endx = tx;
if (ty > endy)
endy = ty;
uint32 rasterPos = (ty ) * workingWidth + (tx + column);
//LOGII("rp", rasterPos);
raster[rasterPos] = rasterTile[ty * tileWidth + tx];
}
}
}
}
int outY, outX;
int tileShift = 0;
for (int y = starty; y < tileHeight; y++) {
if (imageWritedLines == height) break;
if (y + row < outStartY || y + row >= outStartY + outHeight) continue;
outY = y + row - outStartY;
for (int x = 0; x < width * 3; x += 3) {
if (x < outStartX * 3 || x >= (outStartX + outWidth) * 3) continue;
outX = x - (outStartX*3);
uint32 pix = raster[y * workingWidth + x/3];
unsigned char *vp = (unsigned char *)&pix;
scanline[outX] = vp[2];
scanline[outX+1] = vp[1];
scanline[outX+2] = vp[0];
}
//in bmp lines stored fliped verticaly. Write lines from bottom to top
fseek(outFIle, 122 + (/*height - tileShift - row*/outHeight - outY - 1) * scanlineSize , SEEK_SET);
fwrite(scanline,scanlineSize,1,outFIle);
tileShift++;
imageWritedLines++;
}
//LOGII("imageWritedLines", imageWritedLines);
free(raster);
}
free(scanline);
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (work_line_buf) {
_TIFFfree(rasterTile);
work_line_buf = NULL;
}
sendProgress(total, total);
return JNI_TRUE;
}
jboolean TiffToBmpConverter::convertFromStrip() {
uint32 stripSize = TIFFStripSize (tiffImage);
uint32 stripMax = TIFFNumberOfStrips (tiffImage);
int rowPerStrip = -1;
TIFFGetField(tiffImage, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
unsigned long estimateMem = width * sizeof(uint32);//working buf
estimateMem += width * rowPerStrip * sizeof (uint32);//raster
estimateMem += outWidth * 3 + outWidth % 4;
//estimateMem += 4 * width * sizeof(png_bytep); //buf for writing to png
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enought memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
LOGII("rps", rowPerStrip);
LOGII("sm", stripMax);
jlong total = stripMax * rowPerStrip * width;
sendProgress(0, total);
uint32* work_line_buf = (uint32 *)_TIFFmalloc(width * sizeof(uint32));
uint32* raster = (uint32 *)_TIFFmalloc(width * rowPerStrip * sizeof (uint32));
uint32 rows_to_write = 0;
//24 bpp bmp should has with multiple 4
int rowSize = outWidth * 3 + outWidth % 4;
unsigned char *row = new unsigned char[rowSize];
for (int i = 0; i < stripMax*rowPerStrip; i += rowPerStrip) {
if (checkStop()) {
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
return JNI_FALSE;
}
if ((i < outStartY && i + rowPerStrip < outStartY) || (i >= outStartY + outHeight && i + rowPerStrip >= outStartY + outHeight)) continue;
LOGII("i", i);
sendProgress(i * width, total);
TIFFReadRGBAStrip(tiffImage, i, raster);
rows_to_write = 0;
if( i + rowPerStrip > height )
rows_to_write = height - i;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = raster + width * line;
bottom_line = raster + width * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * width);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * width);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * width);
}
}
if (origorientation == ORIENTATION_TOPRIGHT || origorientation == ORIENTATION_BOTRIGHT
|| origorientation == ORIENTATION_RIGHTTOP || origorientation == ORIENTATION_RIGHTBOT) {
for (int y = 0; y < rows_to_write; y++) {
for (int x = 0; x < width/2; x++) {
uint32 buf = raster[y * width + x];
raster[y * width + x] = raster[y * width + width - 1 - x];
raster[y * width + width - 1 - x] = buf;
}
}
}
int outY, outX;
for (int y = 0; y < rows_to_write; y++) {
if (i + y < outStartY || i + y >= outStartY + outHeight) continue;
outY = i + y - outStartY;
for (int x = 0; x < width * 3; x += 3) {
if (x < outStartX * 3 || x >= (outStartX + outWidth) * 3) continue;
outX = x - (outStartX*3);
uint32 pix = raster[y * width + x/3];
unsigned char *vp = (unsigned char *)&pix;
//in bmp colors stores as bgr
row[outX] = vp[2]; //red
row[outX+1] = vp[1]; //green
row[outX+2] = vp[0]; //blue
}
//in bmp lines stored fliped verticaly. Write lines from bottom to top
fseek(outFIle, 122 + (outHeight - outY - 1) * rowSize , SEEK_SET);
fwrite(row,rowSize,1,outFIle);
}
}
free(row);
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
sendProgress(total, total);
return JNI_TRUE;
}
int TiffToBmpConverter::getDecodeMethod() {
int method = -1;
uint32 tileWidth, tileHeight;
int readTW = 0, readTH = 0;
readTW = TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileWidth);
readTH = TIFFGetField(tiffImage, TIFFTAG_TILELENGTH, &tileHeight);
if (tileWidth > 0 && tileHeight > 0 && readTH > 0 && readTW > 0) {
method = DECODE_METHOD_TILE;
} else {
int rowPerStrip = -1;
TIFFGetField(tiffImage, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
uint32 stripSize = TIFFStripSize (tiffImage);
uint32 stripMax = TIFFNumberOfStrips (tiffImage);
int estimate = width * 3;
LOGII("RPS", rowPerStrip);
LOGII("stripSize", stripSize);
LOGII("stripMax", stripMax);
if (rowPerStrip != -1 && stripSize > 0 && stripMax > 1 && rowPerStrip < height) {
method = DECODE_METHOD_STRIP;
} else {
method = DECODE_METHOD_IMAGE;
}
}
LOGII("Decode method", method);
return method;
}
================================================
FILE: src/main/jni/TiffToBmpConverter.h
================================================
//
// Created by beyka on 9/22/17.
//
#ifndef TIFFSAMPLE_TIFFTOBMPCONVERTER_H
#define TIFFSAMPLE_TIFFTOBMPCONVERTER_H
#include
#include
#include
#include "fcntl.h"
#include "unistd.h"
#include "jpeglib.h"
#include
#include "BaseTiffConverter.h"
#include "BMP.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#define LOGEI(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "TiffToBmpConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToBmpConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToBmpConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToBmpConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "TiffToBmpConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "TiffToBmpConverter", "%s %s", x, y)
#define LOGEI(x, y) __android_log_print(ANDROID_LOG_ERROR, "TiffToBmpConverter", "%s %d", x, y)
#endif
class TiffToBmpConverter : public BaseTiffConverter
{
public:
explicit TiffToBmpConverter(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
explicit TiffToBmpConverter(JNIEnv *, jclass, jint, jint, jobject, jobject);
~TiffToBmpConverter();
virtual jboolean convert();
private:
static int const DECODE_METHOD_IMAGE = 1;
static int const DECODE_METHOD_TILE = 2;
static int const DECODE_METHOD_STRIP = 3;
int getDecodeMethod();
jboolean convertFromImage();
jboolean convertFromTile();
jboolean convertFromStrip();
//jboolean convertFromImageWithBounds();
//jboolean convertFromTileWithBounds();
//jboolean convertFromStripWithBounds();
TIFF *tiffImage;
short origorientation;
FILE *outFIle = NULL;
BITMAPFILEHEADER *bmpHeader;
BITMAPINFOHEADER *bmpInfo;
};
#endif //TIFFSAMPLE_TIFFTOBMPCONVERTER_H
================================================
FILE: src/main/jni/TiffToJpgConverter.cpp
================================================
//
// Created by beyka on 5/10/17.
//
#include "TiffToJpgConverter.h"
TiffToJpgConverter::TiffToJpgConverter(JNIEnv *e, jclass clazz, jstring in, jstring out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
jpeg_struct_init = 0;
}
TiffToJpgConverter::TiffToJpgConverter(JNIEnv *e, jclass clazz, jint in, jint out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
jpeg_struct_init = 0;
}
TiffToJpgConverter::~TiffToJpgConverter()
{
LOGI("destructor");
if (tiffImage) {
TIFFClose(tiffImage);
tiffImage = NULL;
}
LOGI("tiff");
if (jpegFile) {
/*if (!conversion_result) {
const char *strPngPath = NULL;
strPngPath = env->GetStringUTFChars(outPath, 0);
remove(strPngPath);
env->ReleaseStringUTFChars(outPath, strPngPath);
}*/
fclose(jpegFile);
}
LOGI("file");
if (jpeg_struct_init) {
jpeg_destroy_compress(&cinfo);
}
LOGI("destructor finish");
}
jboolean TiffToJpgConverter::convert()
{
readOptions();
LOGI("Optioons read done");
LOGII("inFd=", inFd);
if (inFd == -1) {
const char *inCPath = NULL;
inCPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", inCPath);
inFd = open(inCPath, O_RDWR, 0666);
if (inFd == -1) {
if (throwException) {
throw_cant_open_file_exception(env, inPath);
}
LOGES("Can\'t open in file", inCPath);
env->ReleaseStringUTFChars(inPath, inCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(inPath, inCPath);
}
//open tiff image for reading
tiffImage = TIFFFdOpen(inFd, "", "r");
if (tiffImage == NULL) {
if (throwException) {
if (inFd < 0) {
throw_cant_open_file_exception(env, inPath);
} else {
throw_cant_open_file_exception_fd(env, inFd);
}
}
return JNI_FALSE;
}
LOGI("Tiff file opened for reading");
//in c++ path
/*const char *strTiffPath = NULL;
strTiffPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", strTiffPath);
//open tiff image for reading
tiffImage = TIFFOpen(strTiffPath, "r");
if (tiffImage == NULL) {
if (throwException) {
throw_cant_open_file_exception(env, inPath);
}
LOGES("Can\'t open in file", strTiffPath);
env->ReleaseStringUTFChars(inPath, strTiffPath);
return JNI_FALSE;
} else {
env->ReleaseStringUTFChars(inPath, strTiffPath);
}
LOGI("Tiff file opened for reading");*/
//open jpg file for writing
LOGII("outFd=", outFd);
if(outFd == -1) {
LOGI("Opening jpg as File");
//open tiff file for writing or appending
const char *outCPath = NULL;
outCPath = env->GetStringUTFChars(outPath, 0);
LOGIS("OUT path", outCPath);
jpegFile = fopen(outCPath, "w");
if (!jpegFile) {
throw_cant_open_file_exception(env, outPath);
env->ReleaseStringUTFChars(outPath, outCPath);
return JNI_FALSE;
}
} else {
LOGI("Opening jpg as FD");
jpegFile = fdopen(outFd, "w");
if (!jpegFile) {
LOGI("JPG file is null");
if (throwException) {
throw_cant_open_file_exception_fd(env, inFd);
}
LOGES("Can\'t open out file descriptor", inFd);
return JNI_FALSE;
}
}
LOGI("JPG file opened");
/*const char *strPngPath = NULL;
strPngPath = env->GetStringUTFChars(outPath, 0);
LOGIS("OUT path", strPngPath);
jpegFile = fopen(strPngPath, "wb");
if (!jpegFile) {
if (throwException) {
throw_cant_open_file_exception(env, outPath);
}
LOGES("Can\'t open out file", strPngPath);
env->ReleaseStringUTFChars(outPath, strPngPath);
return JNI_FALSE;
} else {
env->ReleaseStringUTFChars(outPath, strPngPath);
}*/
LOGI("initialize jpeg structure");
//set error handling
cinfo.err = jpeg_std_error(&jerr);
LOGI("initialize error handling done");
//initialize jpeg compression object
jpeg_create_compress(&cinfo);
jpeg_struct_init = 1;
LOGI("initialize compress done");
//set phisical file for jpeg
jpeg_stdio_dest(&cinfo, jpegFile);
LOGI("initialize dest file done");
//set tiff directory and read image dimensions
TIFFSetDirectory(tiffImage, tiffDirectory);
TIFFGetField(tiffImage, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tiffImage, TIFFTAG_IMAGELENGTH, &height);
//Getting image orientation and createing ImageOrientation enum
TIFFGetField(tiffImage, TIFFTAG_ORIENTATION, &origorientation);
//If orientation field is empty - use ORIENTATION_TOPLEFT
if (origorientation == 0) {
origorientation = ORIENTATION_TOPLEFT;
}
if (!normalizeDecodeArea()) {
return JNI_FALSE;
}
LOGII("image width", width);
LOGII("image height", height);
LOGII("image bound width", boundWidth);
LOGII("image bound height", boundHeight);
LOGII("image out width", outWidth);
LOGII("image out height", outHeight);
cinfo.image_width = outWidth;
cinfo.image_height = outHeight;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
LOGI("writing img parameters done");
jpeg_set_defaults(&cinfo);
LOGI("set defaults done");
jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE /* limit to baseline-JPEG values */);
LOGI("set quality done");
//write file header
jpeg_start_compress(&cinfo, TRUE);
LOGI("start compressing");
jboolean result = JNI_FALSE;
switch(getDecodeMethod()) {
case DECODE_METHOD_IMAGE:
result = convertFromImage();
break;
case DECODE_METHOD_TILE:
result = convertFromTile();
break;
case DECODE_METHOD_STRIP:
result = convertFromStrip();
break;
}
if (result) {
jpeg_finish_compress(&cinfo);
}
conversion_result = result;
return conversion_result;
}
jboolean TiffToJpgConverter::convertFromImage() {
int origBufferSize = width * height * sizeof(uint32);
unsigned long estimateMem = origBufferSize;
estimateMem += outWidth * sizeof(unsigned char) * 3;//working buf
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enough memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
uint32 *origBuffer = NULL;
origBuffer = (uint32 *) _TIFFmalloc(origBufferSize);
if (origBuffer == NULL) {
const char *message = "Can\'t allocate buffer";
LOGE(*message);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, origBufferSize);
}
return JNI_FALSE;
}
if (0 == TIFFReadRGBAImageOriented(tiffImage, width, height, origBuffer, ORIENTATION_TOPLEFT, 0)) {
free(origBuffer);
const char *message = "Can\'t read tiff";
if (throwException) {
jstring er = env->NewStringUTF(message);
if (outFd == -1) {
throw_decode_file_exception(env, outPath, er);
} else {
throw_decode_file_exception_fd(env, outFd, er);
}
env->DeleteLocalRef(er);
}
LOGE(message);
return JNI_FALSE;
}
jlong total = width * height;
sendProgress(0, total);
int outY, outX;
JSAMPROW row_pointer[1];
for (int y = 0; y < height; y++) {
if (checkStop()) {
free(origBuffer);
return JNI_FALSE;
}
sendProgress(y * width, total);
if (y < outStartY || y >= outStartY + outHeight) continue;
outY = y - outStartY;
unsigned char *row = (unsigned char*)malloc(outWidth * sizeof(unsigned char) * 3);
for (int x = 0; x < width * 3; x += 3) {
if (x < outStartX * 3 || x >= (outStartX + outWidth) * 3) continue;
outX = x - (outStartX*3);
uint32 pix = origBuffer[y * width + x/3];
unsigned char *vp = (unsigned char *)&pix;
row[outX] = vp[0];
row[outX+1] = vp[1];
row[outX+2] = vp[2];
}
row_pointer[0] = row;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
delete(row);
}
free(origBuffer);
sendProgress(total, total);
return JNI_TRUE;
}
jboolean TiffToJpgConverter::convertFromTile() {
uint32 tileWidth = 0, tileHeight = 0;
TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileHeight);
LOGII("Tile width", tileWidth);
LOGII("Tile height", tileHeight);
//uint32 *raster = (uint32 *)_TIFFmalloc(width * tileHeight * sizeof(uint32));
uint32 workingWidth = (width/tileWidth + (width%tileWidth == 0 ? 0 : 1)) * tileWidth;
LOGII("workingWidth ", workingWidth );
uint32 rasterSize = workingWidth * tileHeight ;
LOGII("rasterSize ", rasterSize );
//uint32 *raster = (uint32 *)_TIFFmalloc(rasterSize * sizeof(uint32));
unsigned long estimateMem = rasterSize * sizeof(uint32); //raster
estimateMem += tileWidth * tileHeight * sizeof(uint32); //tile raster
estimateMem += tileWidth * sizeof (uint32); //working buf
estimateMem += outWidth * sizeof(unsigned char) * 3; //bufer for writing to jpg
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enought memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
uint32 *rasterTile = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
uint32 *work_line_buf = (uint32*)_TIFFmalloc(tileWidth * sizeof (uint32));
jlong total = ((width/tileWidth + (width%tileWidth == 0 ? 0 : 1)) * tileWidth)
* ((height/tileHeight + (height%tileHeight == 0 ? 0 : 1)) * tileHeight);
sendProgress(0, total);
uint32 row, column;
int startx = -1, starty = -1, endx = -1, endy = -1;
uint32 imageWritedLines = 0;
for (row = 0; row < height; row += tileHeight) {
sendProgress(row * width, total);
endy = -1;
starty = -1;
uint32 *raster = (uint32 *)_TIFFmalloc(rasterSize * sizeof(uint32));
for (column = 0; column < width; column += tileWidth) {
if (checkStop()) {
free(raster);
raster = NULL;
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (work_line_buf) {
_TIFFfree(rasterTile);
work_line_buf = NULL;
}
return JNI_FALSE;
}
endx = -1;
startx = -1;
TIFFReadRGBATile(tiffImage, column , row, rasterTile);
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 3:
case 7:
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
}
normalizeTile(tileHeight, tileWidth, rasterTile);
//find start and end position
for (int ty = 0; ty < tileHeight; ty++) {
for (int tx = 0; tx < tileWidth; tx++) {
if (rasterTile[ty * tileWidth + tx] != 0) {
if (startx == -1) {
startx = tx;
}
if (starty == -1) {
starty = ty;
}
if (tx > endx)
endx = tx;
if (ty > endy)
endy = ty;
uint32 rasterPos = (ty ) * workingWidth + (tx + column);
//LOGII("rp", rasterPos);
raster[rasterPos] = rasterTile[ty * tileWidth + tx];
}
}
}
}
int outY, outX;
JSAMPROW row_pointer[1];
for (int y = starty; y < tileHeight; y++) {
if (imageWritedLines == height) break;
if (y + row < outStartY || y + row >= outStartY + outHeight) continue;
outY = y + row - outStartY;
unsigned char *jpgrow = (unsigned char*)malloc(outWidth * sizeof(unsigned char) * 3);
// uint32 *rasterLine = (uint32 *)malloc(width * sizeof(uint32));
//for (int x = startx, x2 = 0; x2 < width; x++, x2++) {
// rasterLine[x2] = raster[y * workingWidth + x];
//}
for (int x = 0; x < width * 3; x += 3) {
if (x < outStartX * 3 || x >= (outStartX + outWidth) * 3) continue;
outX = x - (outStartX*3);
uint32 pix = raster[y * workingWidth + x/3];
unsigned char *vp = (unsigned char *)&pix;
jpgrow[outX] = vp[0];
jpgrow[outX+1] = vp[1];
jpgrow[outX+2] = vp[2];
}
row_pointer[0] = jpgrow;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
delete(jpgrow);
//delete(rasterLine);
imageWritedLines++;
}
//LOGII("imageWritedLines", imageWritedLines);
free(raster);
}
/*if (raster) {
_TIFFfree(raster);
raster = NULL;
}*/
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (work_line_buf) {
_TIFFfree(rasterTile);
work_line_buf = NULL;
}
sendProgress(total, total);
return JNI_TRUE;
}
jboolean TiffToJpgConverter::convertFromStrip() {
uint32 stripSize = TIFFStripSize (tiffImage);
uint32 stripMax = TIFFNumberOfStrips (tiffImage);
int rowPerStrip = -1;
TIFFGetField(tiffImage, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
unsigned long estimateMem = width * sizeof(uint32);//working buf
estimateMem += width * rowPerStrip * sizeof (uint32);//raster
estimateMem += outWidth * sizeof(unsigned char) * 3; //buf for writing to jpg
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enought memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
jlong total = stripMax * rowPerStrip * width;
sendProgress(0, total);
uint32* work_line_buf = (uint32 *)_TIFFmalloc(width * sizeof(uint32));
uint32* raster = (uint32 *)_TIFFmalloc(width * rowPerStrip * sizeof (uint32));
uint32 rows_to_write = 0;
for (int i = 0; i < stripMax*rowPerStrip; i += rowPerStrip) {
if (checkStop()) {
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
return JNI_FALSE;
}
sendProgress(i * width, total);
TIFFReadRGBAStrip(tiffImage, i, raster);
rows_to_write = 0;
if( i + rowPerStrip > height )
rows_to_write = height - i;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = raster + width * line;
bottom_line = raster + width * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * width);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * width);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * width);
}
}
if (origorientation == ORIENTATION_TOPRIGHT || origorientation == ORIENTATION_BOTRIGHT
|| origorientation == ORIENTATION_RIGHTTOP || origorientation == ORIENTATION_RIGHTBOT) {
for (int y = 0; y < rows_to_write; y++) {
for (int x = 0; x < width/2; x++) {
uint32 buf = raster[y * width + x];
raster[y * width + x] = raster[y * width + width - 1 - x];
raster[y * width + width - 1 - x] = buf;
}
}
}
int outY, outX;
JSAMPROW row_pointer[1];
for (int y = 0; y < rows_to_write; y++) {
if (i + y < outStartY || i + y >= outStartY + outHeight) continue;
outY = i + y - outStartY;
unsigned char *jpgrow = (unsigned char*)malloc(outWidth * sizeof(unsigned char) * 3);
for (int x = 0; x < width * 3; x += 3) {
if (x < outStartX * 3 || x >= (outStartX + outWidth) * 3) continue;
outX = x - (outStartX*3);
uint32 pix = raster[y * width + x/3];
unsigned char *vp = (unsigned char *)&pix;
jpgrow[outX] = vp[0];
jpgrow[outX+1] = vp[1];
jpgrow[outX+2] = vp[2];
}
row_pointer[0] = jpgrow;
jpeg_write_scanlines(&cinfo, row_pointer, 1);
delete(jpgrow);
/*png_bytep row = (png_bytep)malloc(4 * width * sizeof(png_bytep));
memcpy(row, raster + (y * width), width * 4);
png_write_row(png_ptr, row);
delete(row);*/
}
}
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
sendProgress(total, total);
return JNI_TRUE;
}
int TiffToJpgConverter::getDecodeMethod() {
int method = -1;
uint32 tileWidth, tileHeight;
int readTW = 0, readTH = 0;
readTW = TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileWidth);
readTH = TIFFGetField(tiffImage, TIFFTAG_TILELENGTH, &tileHeight);
if (tileWidth > 0 && tileHeight > 0 && readTH > 0 && readTW > 0) {
method = DECODE_METHOD_TILE;
} else {
int rowPerStrip = -1;
TIFFGetField(tiffImage, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
uint32 stripSize = TIFFStripSize (tiffImage);
uint32 stripMax = TIFFNumberOfStrips (tiffImage);
int estimate = width * 3;
LOGII("RPS", rowPerStrip);
LOGII("stripSize", stripSize);
LOGII("stripMax", stripMax);
if (rowPerStrip != -1 && stripSize > 0 && stripMax > 1 && rowPerStrip < height) {
method = DECODE_METHOD_STRIP;
} else {
method = DECODE_METHOD_IMAGE;
}
}
LOGII("Decode method", method);
return method;
/*int method = -1;
uint32 tileWidth, tileHeight;
int readTW = 0, readTH = 0;
readTW = TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileWidth);
readTH = TIFFGetField(tiffImage, TIFFTAG_TILELENGTH, &tileHeight);
int rowPerStrip = -1;
TIFFGetField(tiffImage, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
uint32 stripSize = TIFFStripSize (tiffImage);
uint32 stripMax = TIFFNumberOfStrips (tiffImage);
int estimate = width * 3;
LOGII("RPS", rowPerStrip);
LOGII("stripSize", stripSize);
LOGII("stripMax", stripMax);
if (rowPerStrip != -1 && stripSize > 0 && stripMax > 1 && rowPerStrip < height) {
method = DECODE_METHOD_STRIP;
} else if (tileWidth > 0 && tileHeight > 0 && readTH > 0 && readTW > 0) {
method = DECODE_METHOD_TILE;
} else {
method = DECODE_METHOD_IMAGE;
}
LOGII("Decode method", method);
return method;*/
}
================================================
FILE: src/main/jni/TiffToJpgConverter.h
================================================
//
// Created by beyka on 5/10/17.
//
#ifndef TIFFSAMPLE_TIFFTOJPGCONVERTER_H
#define TIFFSAMPLE_TIFFTOJPGCONVERTER_H
#include
#include
#include
#include "fcntl.h"
#include "unistd.h"
#include "jpeglib.h"
#include
#include "BaseTiffConverter.h"
//extern "C" {
//#include "jpeglib.h"
//}
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#define LOGEI(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "TiffToJpgConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToJpgConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToJpgConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToJpgConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "TiffToJpgConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "TiffToJpgConverter", "%s %s", x, y)
#define LOGEI(x, y) __android_log_print(ANDROID_LOG_ERROR, "TiffToJpgConverter", "%s %d", x, y)
#endif
class TiffToJpgConverter : public BaseTiffConverter
{
public:
explicit TiffToJpgConverter(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
explicit TiffToJpgConverter(JNIEnv *, jclass, jint, jint, jobject, jobject);
~TiffToJpgConverter();
virtual jboolean convert();
private:
static int const DECODE_METHOD_IMAGE = 1;
static int const DECODE_METHOD_TILE = 2;
static int const DECODE_METHOD_STRIP = 3;
static int const JPEG_QUALITY = 90;
int getDecodeMethod();
jboolean convertFromImage();
jboolean convertFromTile();
jboolean convertFromStrip();
TIFF *tiffImage;
short origorientation;
FILE *jpegFile = NULL;
char jpeg_struct_init;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
};
#endif //TIFFSAMPLE_TIFFTOJPGCONVERTER_H
================================================
FILE: src/main/jni/TiffToPngConverter.cpp
================================================
//
// Created by beyka on 5/10/17.
//
#include "TiffToPngConverter.h"
TiffToPngConverter::TiffToPngConverter(JNIEnv *e, jclass clazz, jstring in, jstring out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
png_ptr_init = 0;
png_info_init = 0;
}
TiffToPngConverter::TiffToPngConverter(JNIEnv *e, jclass clazz, jint in, jint out, jobject opts, jobject listener)
: BaseTiffConverter(e, clazz, in, out, opts, listener)
{
png_ptr_init = 0;
png_info_init = 0;
}
TiffToPngConverter::~TiffToPngConverter()
{
LOGI("destructor start");
if (tiffImage) {
TIFFClose(tiffImage);
tiffImage = NULL;
}
LOGI("tiff free");
if (png_info_init) {
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
}
LOGI("info_ptr free");
if (png_ptr_init) {
png_destroy_write_struct(&png_ptr, NULL);
}
LOGI("png_ptr free");
if (pngFile) {
LOGI("pngFile != NULL");
fclose(pngFile);
}
LOGI("png file free");
}
jboolean TiffToPngConverter::convert()
{
readOptions();
LOGI("Optioons read done");
LOGII("inFd=", inFd);
if (inFd == -1) {
const char *inCPath = NULL;
inCPath = env->GetStringUTFChars(inPath, 0);
LOGIS("IN path", inCPath);
inFd = open(inCPath, O_RDWR, 0666);
if (inFd < 0) {
if (throwException) {
throw_cant_open_file_exception(env, inPath);
}
LOGES("Can\'t open in file", inCPath);
env->ReleaseStringUTFChars(inPath, inCPath);
return JNI_FALSE;
}
env->ReleaseStringUTFChars(inPath, inCPath);
}
//open tiff image for reading
tiffImage = TIFFFdOpen(inFd, "", "r");
if (tiffImage == NULL) {
if (throwException) {
if (inFd < 0) {
throw_cant_open_file_exception(env, inPath);
} else {
throw_cant_open_file_exception_fd(env, inFd);
}
}
return JNI_FALSE;
}
LOGI("Tiff file opened for reading");
//open png file fow writing
LOGII("outFd=", outFd);
if(outFd == -1) {
LOGI("Opening png as File");
//open tiff file for writing or appending
const char *outCPath = NULL;
outCPath = env->GetStringUTFChars(outPath, 0);
LOGIS("OUT path", outCPath);
LOGIS("nativeTiffOpenForSave", outCPath);
pngFile = fopen(outCPath, "w");
if (!pngFile) {
throw_cant_open_file_exception(env, outPath);
env->ReleaseStringUTFChars(outPath, outCPath);
return JNI_FALSE;
}
} else {
LOGI("Opening png as FD");
pngFile = fdopen(outFd, "w");
if (!pngFile) {
LOGI("PNG file is null");
if (throwException) {
throw_cant_open_file_exception_fd(env, inFd);
}
LOGES("Can\'t open out file descriptor", inFd);
return JNI_FALSE;
}
}
LOGI("PNG file opened");
//create png structure pointer
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
const char *message = "Can\'t create PNG structure";
LOGE(*message);
if (throwException) {
jstring er = env->NewStringUTF(message);
if (outFd == -1) {
throw_decode_file_exception(env, outPath, er);
} else {
throw_decode_file_exception_fd(env, outFd, er);
}
env->DeleteLocalRef(er);
}
return JNI_FALSE;
}
png_ptr_init = 1;
//create png info pointer
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
const char *message = "Can\'t create PNG info structure";
LOGE(*message);
if (throwException) {
jstring er = env->NewStringUTF(message);
if (outFd == -1) {
throw_decode_file_exception(env, outPath, er);
} else {
throw_decode_file_exception_fd(env, outFd, er);
}
env->DeleteLocalRef(er);
}
return JNI_FALSE;
}
png_info_init = 1;
//png error handler
if (setjmp(png_jmpbuf(png_ptr))) {
const char *message = "Error creating PNG";
LOGE(message);
if (throwException) {
jstring er = env->NewStringUTF(message);
if (outFd == -1) {
throw_decode_file_exception(env, outPath, er);
} else {
throw_decode_file_exception_fd(env, outFd, er);
}
env->DeleteLocalRef(er);
}
return JNI_FALSE;
}
//Init PNG IO
png_init_io(png_ptr, pngFile);
//set tiff directory and read image dimensions
TIFFSetDirectory(tiffImage, tiffDirectory);
TIFFGetField(tiffImage, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tiffImage, TIFFTAG_IMAGELENGTH, &height);
//Getting image orientation and createing ImageOrientation enum
TIFFGetField(tiffImage, TIFFTAG_ORIENTATION, &origorientation);
//If orientation field is empty - use ORIENTATION_TOPLEFT
if (origorientation == 0) {
origorientation = ORIENTATION_TOPLEFT;
}
LOGII("image width", width);
LOGII("image height", height);
if (!normalizeDecodeArea()) {
return JNI_FALSE;
}
//set png data
png_set_IHDR(png_ptr, info_ptr, outWidth, outHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
LOGI("png_set_IHDR done");
//write file header
png_write_info(png_ptr, info_ptr);
LOGI("png_write_info done");
png_set_flush(png_ptr, 32);
jboolean result = JNI_FALSE;
switch(getDecodeMethod()) {
case DECODE_METHOD_IMAGE:
result = convertFromImage();
break;
case DECODE_METHOD_TILE:
result = convertFromTile();
break;
case DECODE_METHOD_STRIP:
result = convertFromStrip();
break;
}
if (result) {
png_write_end(png_ptr, info_ptr);
}
conversion_result = result;
return conversion_result;
}
jboolean TiffToPngConverter::convertFromImage() {
int origBufferSize = width * height * sizeof(uint32);
unsigned long estimateMem = origBufferSize;
estimateMem += 4 * outWidth * sizeof(png_bytep);//working buf
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enough memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
uint32 *origBuffer = NULL;
origBuffer = (uint32 *) _TIFFmalloc(origBufferSize);
if (origBuffer == NULL) {
const char *message = "Can\'t allocate buffer";
LOGE(*message);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, origBufferSize);
}
return JNI_FALSE;
}
if (0 == TIFFReadRGBAImageOriented(tiffImage, width, height, origBuffer, ORIENTATION_TOPLEFT, 0)) {
free(origBuffer);
const char *message = "Can\'t read tiff";
if (throwException) {
jstring er = env->NewStringUTF(message);
if (outFd == -1) {
throw_decode_file_exception(env, outPath, er);
} else {
throw_decode_file_exception_fd(env, outFd, er);
}
env->DeleteLocalRef(er);
}
LOGE(message);
return JNI_FALSE;
}
jlong total = width * height;
sendProgress(0, total);
int outY, outX;
for (int y = 0; y < height; y++) {
if (y < outStartY || y >= outStartY + outHeight) continue;
if (checkStop()) {
free(origBuffer);
return JNI_FALSE;
}
outY = y - outStartY;
sendProgress(y * width, total);
png_bytep row = (png_bytep)malloc(4 * outWidth * sizeof(png_bytep));
memcpy(row, origBuffer + (y * width + outStartX), outWidth * 4);
png_write_row(png_ptr, row);
delete(row);
}
free(origBuffer);
sendProgress(total, total);
return JNI_TRUE;
}
jboolean TiffToPngConverter::convertFromTile() {
uint32 tileWidth = 0, tileHeight = 0;
TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileHeight);
LOGII("Tile width", tileWidth);
LOGII("Tile height", tileHeight);
//uint32 *raster = (uint32 *)_TIFFmalloc(width * tileHeight * sizeof(uint32));
uint32 workingWidth = (width/tileWidth + (width%tileWidth == 0 ? 0 : 1)) * tileWidth;
LOGII("workingWidth ", workingWidth );
uint32 rasterSize = workingWidth * tileHeight ;
LOGII("rasterSize ", rasterSize );
//uint32 *raster = (uint32 *)_TIFFmalloc(rasterSize * sizeof(uint32));
unsigned long estimateMem = rasterSize * sizeof(uint32); //raster
estimateMem += tileWidth * tileHeight * sizeof(uint32); //tile raster
estimateMem += tileWidth * sizeof (uint32); //working buf
estimateMem += 4 * outWidth * sizeof(png_bytep); //bufer for writing to png
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enought memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
uint32 *rasterTile = (uint32 *)_TIFFmalloc(tileWidth * tileHeight * sizeof(uint32));
uint32 *work_line_buf = (uint32*)_TIFFmalloc(tileWidth * sizeof (uint32));
jlong total = ((width/tileWidth + (width%tileWidth == 0 ? 0 : 1)) * tileWidth)
* ((height/tileHeight + (height%tileHeight == 0 ? 0 : 1)) * tileHeight);
sendProgress(0, total);
uint32 row, column;
int startx = -1, starty = -1, endx = -1, endy = -1;
uint32 imageWritedLines = 0;
for (row = 0; row < height; row += tileHeight) {
sendProgress(row * width, total);
endy = -1;
starty = -1;
uint32 *raster = (uint32 *)_TIFFmalloc(rasterSize * sizeof(uint32));
for (column = 0; column < width; column += tileWidth) {
if (checkStop()) {
free(raster);
raster = NULL;
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (work_line_buf) {
_TIFFfree(rasterTile);
work_line_buf = NULL;
}
return JNI_FALSE;
}
endx = -1;
startx = -1;
TIFFReadRGBATile(tiffImage, column , row, rasterTile);
switch(origorientation) {
case 1:
case 5:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 2:
case 6:
rotateTileLinesVertical(tileHeight, tileWidth, rasterTile, work_line_buf);
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
case 3:
case 7:
{
rotateTileLinesHorizontal(tileHeight, tileWidth, rasterTile, work_line_buf);
break;
}
}
normalizeTile(tileHeight, tileWidth, rasterTile);
//find start and end position
for (int ty = 0; ty < tileHeight; ty++) {
for (int tx = 0; tx < tileWidth; tx++) {
if (rasterTile[ty * tileWidth + tx] != 0) {
if (startx == -1) {
startx = tx;
}
if (starty == -1) {
starty = ty;
}
if (tx > endx)
endx = tx;
if (ty > endy)
endy = ty;
uint32 rasterPos = (ty ) * workingWidth + (tx + column);
//LOGII("rp", rasterPos);
raster[rasterPos] = rasterTile[ty * tileWidth + tx];
}
}
}
}
int outY, outX;
for (int y = starty; y < tileHeight; y++) {
if (imageWritedLines == height) break;
if (y + row < outStartY || y + row >= outStartY + outHeight) continue;
outY = y + row - outStartY;
//create temp raster and write there pixels than not null
png_bytep pngrow = (png_bytep)malloc(4 * outWidth * sizeof(png_bytep));
memcpy(pngrow, raster + y * workingWidth + outStartX, outWidth * 4);
//memcpy(pngrow, rasterLine, width * 4);
png_write_row(png_ptr, pngrow);
free(pngrow);
//delete(rasterLine);
imageWritedLines++;
}
//LOGII("imageWritedLines", imageWritedLines);
free(raster);
}
/*if (raster) {
_TIFFfree(raster);
raster = NULL;
}*/
if (rasterTile) {
_TIFFfree(rasterTile);
rasterTile = NULL;
}
if (work_line_buf) {
_TIFFfree(rasterTile);
work_line_buf = NULL;
}
sendProgress(total, total);
return JNI_TRUE;
}
jboolean TiffToPngConverter::convertFromStrip() {
uint32 stripSize = TIFFStripSize (tiffImage);
uint32 stripMax = TIFFNumberOfStrips (tiffImage);
int rowPerStrip = -1;
TIFFGetField(tiffImage, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
LOGII("RPS", rowPerStrip);
unsigned long estimateMem = width * sizeof(uint32);//working buf
estimateMem += width * rowPerStrip * sizeof (uint32);//raster
estimateMem += 4 * outWidth * sizeof(png_bytep); //buf for writing to png
LOGII("estimateMem", estimateMem);
if (estimateMem > availableMemory && availableMemory != -1) {
LOGEI("Not enought memory", availableMemory);
if (throwException) {
throw_not_enought_memory_exception(env, availableMemory, estimateMem);
}
return JNI_FALSE;
}
jlong total = stripMax * rowPerStrip * width;
sendProgress(0, total);
uint32* work_line_buf = (uint32 *)_TIFFmalloc(width * sizeof(uint32));
uint32* raster = (uint32 *)_TIFFmalloc(width * rowPerStrip * sizeof (uint32));
uint32 rows_to_write = 0;
for (int i = 0; i < stripMax*rowPerStrip; i += rowPerStrip) {
if (checkStop()) {
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
return JNI_FALSE;
}
sendProgress(i * width, total);
TIFFReadRGBAStrip(tiffImage, i, raster);
rows_to_write = 0;
if( i + rowPerStrip > height )
rows_to_write = height - i;
else
rows_to_write = rowPerStrip;
if (origorientation <= 4) {
for (int line = 0; line < rows_to_write / 2; line++) {
unsigned int *top_line, *bottom_line;
top_line = raster + width * line;
bottom_line = raster + width * (rows_to_write - line - 1);
_TIFFmemcpy(work_line_buf, top_line, sizeof(unsigned int) * width);
_TIFFmemcpy(top_line, bottom_line, sizeof(unsigned int) * width);
_TIFFmemcpy(bottom_line, work_line_buf, sizeof(unsigned int) * width);
}
}
if (origorientation == ORIENTATION_TOPRIGHT || origorientation == ORIENTATION_BOTRIGHT
|| origorientation == ORIENTATION_RIGHTTOP || origorientation == ORIENTATION_RIGHTBOT) {
for (int y = 0; y < rows_to_write; y++) {
for (int x = 0; x < width/2; x++) {
uint32 buf = raster[y * width + x];
raster[y * width + x] = raster[y * width + width - 1 - x];
raster[y * width + width - 1 - x] = buf;
}
}
}
int outY, outX;
for (int y = 0; y < rows_to_write; y++) {
if (i + y < outStartY || i + y >= outStartY + outHeight) continue;
outY = i + y - outStartY;
LOGII("out Y", outY);
png_bytep pngrow = (png_bytep)malloc(4 * outWidth * sizeof(png_bytep));
memcpy(pngrow, raster + y * width + outStartX, outWidth * 4);
png_write_row(png_ptr, pngrow);
free(pngrow);
}
}
if (raster) {
_TIFFfree(raster);
raster = NULL;
}
if (work_line_buf) {
_TIFFfree(work_line_buf);
work_line_buf = NULL;
}
sendProgress(total, total);
return JNI_TRUE;
}
int TiffToPngConverter::getDecodeMethod() {
int method = -1;
uint32 tileWidth, tileHeight;
int readTW = 0, readTH = 0;
readTW = TIFFGetField(tiffImage, TIFFTAG_TILEWIDTH, &tileWidth);
readTH = TIFFGetField(tiffImage, TIFFTAG_TILELENGTH, &tileHeight);
if (tileWidth > 0 && tileHeight > 0 && readTH > 0 && readTW > 0) {
method = DECODE_METHOD_TILE;
} else {
int rowPerStrip = -1;
TIFFGetField(tiffImage, TIFFTAG_ROWSPERSTRIP, &rowPerStrip);
uint32 stripSize = TIFFStripSize (tiffImage);
uint32 stripMax = TIFFNumberOfStrips (tiffImage);
int estimate = width * 3;
LOGII("RPS", rowPerStrip);
LOGII("stripSize", stripSize);
LOGII("stripMax", stripMax);
if (rowPerStrip != -1 && stripSize > 0 && stripMax > 1 && rowPerStrip < height) {
method = DECODE_METHOD_STRIP;
} else {
method = DECODE_METHOD_IMAGE;
}
}
LOGII("Decode method", method);
return method;
}
================================================
FILE: src/main/jni/TiffToPngConverter.h
================================================
//
// Created by beyka on 5/10/17.
//
#ifndef TIFFSAMPLE_TIFFTOPNGCONVERTER_H
#define TIFFSAMPLE_TIFFTOPNGCONVERTER_H
#include
#include
#include
#include "fcntl.h"
#include "unistd.h"
#include
#include
#include "BaseTiffConverter.h"
#ifdef NDEBUG
#define LOGI(x)
#define LOGII(x, y)
#define LOGIF(x, y)
#define LOGIS(x, y)
#define LOGE(x)
#define LOGES(x, y)
#define LOGEI(x, y)
#else
#define LOGI(x) __android_log_print(ANDROID_LOG_DEBUG, "TiffToPngConverter", "%s", x)
#define LOGII(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToPngConverter", "%s %d", x, y)
#define LOGIF(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToPngConverter", "%s %f", x, y)
#define LOGIS(x, y) __android_log_print(ANDROID_LOG_DEBUG, "TiffToPngConverter", "%s %s", x, y)
#define LOGE(x) __android_log_print(ANDROID_LOG_ERROR, "TiffToPngConverter", "%s", x)
#define LOGES(x, y) __android_log_print(ANDROID_LOG_ERROR, "TiffToPngConverter", "%s %s", x, y)
#define LOGEI(x, y) __android_log_print(ANDROID_LOG_ERROR, "TiffToPngConverter", "%s %d", x, y)
#endif
class TiffToPngConverter : public BaseTiffConverter
{
public:
explicit TiffToPngConverter(JNIEnv *, jclass, jstring, jstring, jobject, jobject);
explicit TiffToPngConverter(JNIEnv *, jclass, jint, jint, jobject, jobject);
~TiffToPngConverter();
virtual jboolean convert();
private:
static int const DECODE_METHOD_IMAGE = 1;
static int const DECODE_METHOD_TILE = 2;
static int const DECODE_METHOD_STRIP = 3;
int getDecodeMethod();
jboolean convertFromImage();
jboolean convertFromTile();
jboolean convertFromStrip();
TIFF *tiffImage;
short origorientation;
FILE *pngFile = NULL;;
char png_ptr_init;
png_structp png_ptr;
char png_info_init;
png_infop info_ptr;
};
#endif //TIFFSAMPLE_TIFFTOPNGCONVERTER_H
================================================
FILE: src/main/jni/jpeg/jconfig.h
================================================
/* android jconfig.h */
/*
* jconfig.doc
*
* Copyright (C) 1991-1994, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file documents the configuration options that are required to
* customize the JPEG software for a particular system.
*
* The actual configuration options for a particular installation are stored
* in jconfig.h. On many machines, jconfig.h can be generated automatically
* or copied from one of the "canned" jconfig files that we supply. But if
* you need to generate a jconfig.h file by hand, this file tells you how.
*
* DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
* EDIT A COPY NAMED JCONFIG.H.
*/
/*
* These symbols indicate the properties of your machine or compiler.
* #define the symbol if yes, #undef it if no.
*/
/* Does your compiler support function prototypes?
* (If not, you also need to use ansi2knr, see install.doc)
*/
#define HAVE_PROTOTYPES
/* Does your compiler support the declaration "unsigned char" ?
* How about "unsigned short" ?
*/
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* Define "void" as "char" if your compiler doesn't know about type void.
* NOTE: be sure to define void such that "void *" represents the most general
* pointer type, e.g., that returned by malloc().
*/
/* #define void char */
/* Define "const" as empty if your compiler doesn't know the "const" keyword.
*/
/* #define const */
/* Define this if an ordinary "char" type is unsigned.
* If you're not sure, leaving it undefined will work at some cost in speed.
* If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
*/
#undef CHAR_IS_UNSIGNED
/* Define this if your system has an ANSI-conforming file.
*/
#define HAVE_STDDEF_H
/* Define this if your system has an ANSI-conforming file.
*/
#define HAVE_STDLIB_H
/* Define this if your system does not have an ANSI/SysV ,
* but does have a BSD-style .
*/
#undef NEED_BSD_STRINGS
/* Define this if your system does not provide typedef size_t in any of the
* ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
* instead.
*/
#undef NEED_SYS_TYPES_H
/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
* unless you are using a large-data memory model or 80386 flat-memory mode.
* On less brain-damaged CPUs this symbol must not be defined.
* (Defining this symbol causes large data structures to be referenced through
* "far" pointers and to be allocated with a special version of malloc.)
*/
#undef NEED_FAR_POINTERS
/* Define this if your linker needs global names to be unique in less
* than the first 15 characters.
*/
#undef NEED_SHORT_EXTERNAL_NAMES
/* Although a real ANSI C compiler can deal perfectly well with pointers to
* unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
* and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
* define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
* actually get "missing structure definition" warnings or errors while
* compiling the JPEG code.
*/
#undef INCOMPLETE_TYPES_BROKEN
/*
* The following options affect code selection within the JPEG library,
* but they don't need to be visible to applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS has been defined.
*/
#ifdef JPEG_INTERNALS
/* Define this if your compiler implements ">>" on signed values as a logical
* (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
* which is the normal and rational definition.
*/
#undef RIGHT_SHIFT_IS_UNSIGNED
#endif /* JPEG_INTERNALS */
/*
* The remaining options do not affect the JPEG library proper,
* but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
* Other applications can ignore these.
*/
#ifdef JPEG_CJPEG_DJPEG
/* These defines indicate which image (non-JPEG) file formats are allowed. */
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
/* Define this if you want to name both input and output files on the command
* line, rather than using stdout and optionally stdin. You MUST do this if
* your system can't cope with binary I/O to stdin/stdout. See comments at
* head of cjpeg.c or djpeg.c.
*/
#undef TWO_FILE_COMMANDLINE
/* Define this if your system needs explicit cleanup of temporary files.
* This is crucial under MS-DOS, where the temporary "files" may be areas
* of extended memory; on most other systems it's not as important.
*/
#undef NEED_SIGNAL_CATCHER
/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
* This is necessary on systems that distinguish text files from binary files,
* and is harmless on most systems that don't. If you have one of the rare
* systems that complains about the "b" spec, define this symbol.
*/
#undef DONT_USE_B_MODE
/* Define this if you want percent-done progress reports from cjpeg/djpeg.
*/
#undef PROGRESS_REPORT
#endif /* JPEG_CJPEG_DJPEG */
================================================
FILE: src/main/jni/jpeg/jerror.h
================================================
/*
* jerror.h
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* Modified 1997-2012 by Guido Vollbeding.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the error and message codes for the JPEG library.
* Edit this file to add new codes, or to translate the message strings to
* some other language.
* A set of error-reporting macros are defined too. Some applications using
* the JPEG library may wish to include this file to get the error codes
* and/or the macros.
*/
/*
* To define the enum list of message codes, include this file without
* defining macro JMESSAGE. To create a message string table, include it
* again with a suitable JMESSAGE definition (see jerror.c for an example).
*/
#ifndef JMESSAGE
#ifndef JERROR_H
/* First time through, define the enum list */
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
#define JMESSAGE(code,string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
#ifdef JMAKE_ENUM_LIST
typedef enum {
#define JMESSAGE(code,string) code ,
#endif /* JMAKE_ENUM_LIST */
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
/* For maintenance convenience, list is alphabetical by message code name */
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported")
JMESSAGE(JERR_BAD_DROP_SAMPLING,
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
JMESSAGE(JERR_BAD_LIB_VERSION,
"Wrong JPEG library version: library is %d, caller expects %d")
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
JMESSAGE(JERR_BAD_PROGRESSION,
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
JMESSAGE(JERR_BAD_PROG_SCRIPT,
"Invalid progressive parameters at scan script entry %d")
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
JMESSAGE(JERR_BAD_STRUCT_SIZE,
"JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
JMESSAGE(JERR_FILE_READ, "Input file read error")
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
"Cannot transcode due to multiple use of quantization table %d")
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
JMESSAGE(JERR_QUANT_COMPONENTS,
"Cannot quantize more than %d color components")
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF")
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
JMESSAGE(JERR_TFILE_WRITE,
"Write failed on temporary file --- out of disk space?")
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
JMESSAGE(JMSG_VERSION, JVERSION)
JMESSAGE(JTRC_16BIT_TABLES,
"Caution: quantization tables are too coarse for baseline JPEG")
JMESSAGE(JTRC_ADOBE,
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
JMESSAGE(JTRC_EOI, "End Of Image")
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
JMESSAGE(JTRC_JFIF_EXTENSION,
"JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
JMESSAGE(JTRC_RST, "RST%d")
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
"Smoothing not supported with nonstandard sampling ratios")
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
JMESSAGE(JTRC_SOI, "Start of Image")
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
JMESSAGE(JTRC_THUMB_JPEG,
"JFIF extension marker: JPEG-compressed thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_PALETTE,
"JFIF extension marker: palette thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_RGB,
"JFIF extension marker: RGB thumbnail image, length %u")
JMESSAGE(JTRC_UNKNOWN_IDS,
"Unrecognized component IDs %d %d %d, assuming YCbCr")
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
JMESSAGE(JWRN_BOGUS_PROGRESSION,
"Inconsistent progression sequence for component %d coefficient %d")
JMESSAGE(JWRN_EXTRANEOUS_DATA,
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
JMESSAGE(JWRN_MUST_RESYNC,
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
#ifdef JMAKE_ENUM_LIST
JMSG_LASTMSGCODE
} J_MESSAGE_CODE;
#undef JMAKE_ENUM_LIST
#endif /* JMAKE_ENUM_LIST */
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
#undef JMESSAGE
#ifndef JERROR_H
#define JERROR_H
/* Macros to simplify using the error and trace message stuff */
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
#define ERREXIT(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT3(cinfo,code,p1,p2,p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(cinfo)->err->msg_parm.i[4] = (p5), \
(cinfo)->err->msg_parm.i[5] = (p6), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXITS(cinfo,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
#define WARNMS(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
/* Informational/debugging messages */
#define TRACEMS(cinfo,lvl,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS1(cinfo,lvl,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMSS(cinfo,lvl,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#endif /* JERROR_H */
================================================
FILE: src/main/jni/jpeg/jmorecfg.h
================================================
/*
* jmorecfg.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2012 by Guido Vollbeding.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains additional configuration options that customize the
* JPEG software for special applications or support machine-dependent
* optimizations. Most users will not need to touch this file.
*/
/*
* Define BITS_IN_JSAMPLE as either
* 8 for 8-bit sample values (the usual setting)
* 12 for 12-bit sample values
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
* JPEG standard, and the IJG code does not support anything else!
* We do not support run-time selection of data precision, sorry.
*/
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
/*
* Maximum number of components (color channels) allowed in JPEG image.
* To meet the letter of the JPEG spec, set this to 255. However, darn
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
* really short on memory. (Each allowed component costs a hundred or so
* bytes of storage, whether actually used in an image or not.)
*/
#define MAX_COMPONENTS 10 /* maximum number of image components */
/*
* Basic data types.
* You may need to change these if you have a machine with unusual data
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
* but it had better be at least 16.
*/
/* Representation of a single sample (pixel element value).
* We frequently allocate large arrays of these, so it's important to keep
* them small. But if you have memory to burn and access to char or short
* arrays is very slow on your hardware, you might want to change these.
*/
#if BITS_IN_JSAMPLE == 8
/* JSAMPLE should be the smallest type that will hold the values 0..255.
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef CHAR_IS_UNSIGNED
#define GETJSAMPLE(value) ((int) (value))
#else
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
#endif /* BITS_IN_JSAMPLE == 8 */
#if BITS_IN_JSAMPLE == 12
/* JSAMPLE should be the smallest type that will hold the values 0..4095.
* On nearly all machines "short" will do nicely.
*/
typedef short JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
#endif /* BITS_IN_JSAMPLE == 12 */
/* Representation of a DCT frequency coefficient.
* This should be a signed value of at least 16 bits; "short" is usually OK.
* Again, we allocate large arrays of these, but you can change to int
* if you have memory to burn and "short" is really slow.
*/
typedef short JCOEF;
/* Compressed datastreams are represented as arrays of JOCTET.
* These must be EXACTLY 8 bits wide, at least once they are written to
* external storage. Note that when using the stdio data source/destination
* managers, this is also the data type passed to fread/fwrite.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JOCTET;
#define GETJOCTET(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JOCTET;
#ifdef CHAR_IS_UNSIGNED
#define GETJOCTET(value) (value)
#else
#define GETJOCTET(value) ((value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* These typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
* won't cost a huge amount of memory, so we don't provide special
* extraction code like we did for JSAMPLE. (In other words, these
* typedefs live at a different point on the speed/space tradeoff curve.)
*/
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char UINT8;
#else /* not CHAR_IS_UNSIGNED */
typedef short UINT8;
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short UINT16;
#else /* not HAVE_UNSIGNED_SHORT */
typedef unsigned int UINT16;
#endif /* HAVE_UNSIGNED_SHORT */
/* INT16 must hold at least the values -32768..32767. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
typedef short INT16;
#endif
/* INT32 must hold at least signed 32-bit values. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
#ifndef _BASETSD_H /* MinGW is slightly different */
#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
typedef long INT32;
#endif
#endif
#endif
#endif
/* Datatype used for image dimensions. The JPEG standard only supports
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
* "unsigned int" is sufficient on all machines. However, if you need to
* handle larger images and you don't mind deviating from the spec, you
* can change this datatype.
*/
typedef unsigned int JDIMENSION;
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
/* These macros are used in all function definitions and extern declarations.
* You could modify them if you need to change function linkage conventions;
* in particular, you'll need to do that to make the library a Windows DLL.
* Another application is to make all functions global for use with debuggers
* or code profilers that require it.
*/
/* a function called through method pointers: */
#define METHODDEF(type) static type
/* a function used only in its module: */
#define LOCAL(type) static type
/* a function referenced thru EXTERNs: */
#define GLOBAL(type) type
/* a reference to a GLOBAL function: */
#define EXTERN(type) extern type
/* This macro is used to declare a "method", that is, a function pointer.
* We want to supply prototype parameters if the compiler can cope.
* Note that the arglist parameter must be parenthesized!
* Again, you can customize this if you need special linkage keywords.
*/
#ifdef HAVE_PROTOTYPES
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
#endif
/* The noreturn type identifier is used to declare functions
* which cannot return.
* Compilers can thus create more optimized code and perform
* better checks for warnings and errors.
* Static analyzer tools can make improved inferences about
* execution paths and are prevented from giving false alerts.
*
* Unfortunately, the proposed specifications of corresponding
* extensions in the Dec 2011 ISO C standard revision (C11),
* GCC, MSVC, etc. are not viable.
* Thus we introduce a user defined type to declare noreturn
* functions at least for clarity. A proper compiler would
* have a suitable noreturn type to match in place of void.
*/
#ifndef HAVE_NORETURN_T
typedef void noreturn_t;
#endif
/* Here is the pseudo-keyword for declaring pointers that must be "far"
* on 80x86 machines. Most of the specialized coding for 80x86 is handled
* by just saying "FAR *" where such a pointer is needed. In a few places
* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
*/
#ifndef FAR
#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif
#endif
/*
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
* in standard header files. Or you may have conflicts with application-
* specific header files that you want to include together with these files.
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
*/
#ifndef HAVE_BOOLEAN
typedef int boolean;
#endif
#ifndef FALSE /* in case these macros already exist */
#define FALSE 0 /* values of boolean */
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
* The remaining options affect code selection within the JPEG library,
* but they don't need to be visible to most applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
*/
#ifdef JPEG_INTERNALS
#define JPEG_INTERNAL_OPTIONS
#endif
#ifdef JPEG_INTERNAL_OPTIONS
/*
* These defines indicate whether to include various optional functions.
* Undefining some of these symbols will produce a smaller but less capable
* library. Note that you can leave certain source files out of the
* compilation/linking process if you've #undef'd the corresponding symbols.
* (You may HAVE to do that if your compiler doesn't like null source files.)
*/
/* Capability options common to encoder and decoder: */
#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
/* Encoder capability options: */
#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
* precision, so jchuff.c normally uses entropy optimization to compute
* usable tables for higher precision. If you don't want to do optimization,
* you'll have to supply different default Huffman tables.
* The exact same statements apply for progressive JPEG: the default tables
* don't work for progressive mode. (This may get fixed, however.)
*/
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
/* Decoder capability options: */
#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
/* more capability options later, no doubt */
/*
* Ordering of RGB data in scanlines passed to or from the application.
* If your application wants to deal with data in the order B,G,R, just
* change these macros. You can also deal with formats such as R,G,B,X
* (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
* the offsets will also change the order in which colormap data is organized.
* RESTRICTIONS:
* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
* 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
* is not 3 (they don't understand about dummy color components!). So you
* can't use color quantization if you change that value.
*/
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
#define RGB_GREEN 1 /* Offset of Green */
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
/* Definitions for speed-related optimizations. */
/* If your compiler supports inline functions, define INLINE
* as the inline keyword; otherwise define it as empty.
*/
#ifndef INLINE
#ifdef __GNUC__ /* for instance, GNU C knows about inline */
#define INLINE __inline__
#endif
#ifndef INLINE
#define INLINE /* default is to define it as empty */
#endif
#endif
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
*/
#ifndef MULTIPLIER
#define MULTIPLIER int /* type for fastest integer multiply */
#endif
/* FAST_FLOAT should be either float or double, whichever is done faster
* by your compiler. (Note that this type is only used in the floating point
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
* Typically, float is faster in ANSI C compilers, while double is faster in
* pre-ANSI compilers (because they insist on converting to double anyway).
* The code below therefore chooses float if we have ANSI-style prototypes.
*/
#ifndef FAST_FLOAT
#ifdef HAVE_PROTOTYPES
#define FAST_FLOAT float
#else
#define FAST_FLOAT double
#endif
#endif
#endif /* JPEG_INTERNAL_OPTIONS */
================================================
FILE: src/main/jni/jpeg/jpeglib.h
================================================
/*
* jpeglib.h
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modified 2002-2012 by Guido Vollbeding.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the application interface for the JPEG library.
* Most applications using the library need only include this file,
* and perhaps jerror.h if they want to know the exact error codes.
*/
#ifndef JPEGLIB_H
#define JPEGLIB_H
/*
* First we include the configuration files that record how this
* installation of the JPEG library is set up. jconfig.h can be
* generated automatically for many systems. jmorecfg.h contains
* manual configuration options that most people need not worry about.
*/
#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
#include "jconfig.h" /* widely used configuration options */
#endif
#include "jmorecfg.h" /* seldom changed options */
#ifdef __cplusplus
#ifndef DONT_USE_EXTERN_C
extern "C" {
#endif
#endif
/* Version IDs for the JPEG library.
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 90".
*/
#define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */
#define JPEG_LIB_VERSION_MAJOR 9
#define JPEG_LIB_VERSION_MINOR 0
/* Various constants determining the sizes of things.
* All of these are specified by the JPEG standard, so don't change them
* if you want to be compatible.
*/
#define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */
#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
* the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
* If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
* to handle it. We even let you do this from the jconfig.h file. However,
* we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
* sometimes emits noncompliant files doesn't mean you should too.
*/
#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */
#ifndef D_MAX_BLOCKS_IN_MCU
#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */
#endif
/* Data structures for images (arrays of samples and of DCT coefficients).
* On 80x86 machines, the image arrays are too big for near pointers,
* but the pointer arrays can fit in near memory.
*/
typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */
typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
/* Types for JPEG compression parameters and working tables. */
/* DCT coefficient quantization tables. */
typedef struct {
/* This array gives the coefficient quantizers in natural array order
* (not the zigzag order in which they are stored in a JPEG DQT marker).
* CAUTION: IJG versions prior to v6a kept this array in zigzag order.
*/
UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */
/* This field is used only during compression. It's initialized FALSE when
* the table is created, and set TRUE when it's been output to the file.
* You could suppress output of a table by setting this to TRUE.
* (See jpeg_suppress_tables for an example.)
*/
boolean sent_table; /* TRUE when table has been output */
} JQUANT_TBL;
/* Huffman coding tables. */
typedef struct {
/* These two fields directly represent the contents of a JPEG DHT marker */
UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
/* length k bits; bits[0] is unused */
UINT8 huffval[256]; /* The symbols, in order of incr code length */
/* This field is used only during compression. It's initialized FALSE when
* the table is created, and set TRUE when it's been output to the file.
* You could suppress output of a table by setting this to TRUE.
* (See jpeg_suppress_tables for an example.)
*/
boolean sent_table; /* TRUE when table has been output */
} JHUFF_TBL;
/* Basic info about one component (color channel). */
typedef struct {
/* These values are fixed over the whole image. */
/* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOF marker. */
int component_id; /* identifier for this component (0..255) */
int component_index; /* its index in SOF or cinfo->comp_info[] */
int h_samp_factor; /* horizontal sampling factor (1..4) */
int v_samp_factor; /* vertical sampling factor (1..4) */
int quant_tbl_no; /* quantization table selector (0..3) */
/* These values may vary between scans. */
/* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOS marker. */
/* The decompressor output side may not use these variables. */
int dc_tbl_no; /* DC entropy table selector (0..3) */
int ac_tbl_no; /* AC entropy table selector (0..3) */
/* Remaining fields should be treated as private by applications. */
/* These values are computed during compression or decompression startup: */
/* Component's size in DCT blocks.
* Any dummy blocks added to complete an MCU are not counted; therefore
* these values do not depend on whether a scan is interleaved or not.
*/
JDIMENSION width_in_blocks;
JDIMENSION height_in_blocks;
/* Size of a DCT block in samples,
* reflecting any scaling we choose to apply during the DCT step.
* Values from 1 to 16 are supported.
* Note that different components may receive different DCT scalings.
*/
int DCT_h_scaled_size;
int DCT_v_scaled_size;
/* The downsampled dimensions are the component's actual, unpadded number
* of samples at the main buffer (preprocessing/compression interface);
* DCT scaling is included, so
* downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE)
* and similarly for height.
*/
JDIMENSION downsampled_width; /* actual width in samples */
JDIMENSION downsampled_height; /* actual height in samples */
/* This flag is used only for decompression. In cases where some of the
* components will be ignored (eg grayscale output from YCbCr image),
* we can skip most computations for the unused components.
*/
boolean component_needed; /* do we need the value of this component? */
/* These values are computed before starting a scan of the component. */
/* The decompressor output side may not use these variables. */
int MCU_width; /* number of blocks per MCU, horizontally */
int MCU_height; /* number of blocks per MCU, vertically */
int MCU_blocks; /* MCU_width * MCU_height */
int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */
int last_col_width; /* # of non-dummy blocks across in last MCU */
int last_row_height; /* # of non-dummy blocks down in last MCU */
/* Saved quantization table for component; NULL if none yet saved.
* See jdinput.c comments about the need for this information.
* This field is currently used only for decompression.
*/
JQUANT_TBL * quant_table;
/* Private per-component storage for DCT or IDCT subsystem. */
void * dct_table;
} jpeg_component_info;
/* The script for encoding a multiple-scan file is an array of these: */
typedef struct {
int comps_in_scan; /* number of components encoded in this scan */
int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
int Ss, Se; /* progressive JPEG spectral selection parms */
int Ah, Al; /* progressive JPEG successive approx. parms */
} jpeg_scan_info;
/* The decompressor can save APPn and COM markers in a list of these: */
typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr;
struct jpeg_marker_struct {
jpeg_saved_marker_ptr next; /* next in list, or NULL */
UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */
unsigned int original_length; /* # bytes of data in the file */
unsigned int data_length; /* # bytes of data saved at data[] */
JOCTET FAR * data; /* the data contained in the marker */
/* the marker length word is not counted in data_length or original_length */
};
/* Known color spaces. */
typedef enum {
JCS_UNKNOWN, /* error/unspecified */
JCS_GRAYSCALE, /* monochrome */
JCS_RGB, /* red/green/blue */
JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
JCS_CMYK, /* C/M/Y/K */
JCS_YCCK /* Y/Cb/Cr/K */
} J_COLOR_SPACE;
/* Supported color transforms. */
typedef enum {
JCT_NONE = 0,
JCT_SUBTRACT_GREEN = 1
} J_COLOR_TRANSFORM;
/* DCT/IDCT algorithm options. */
typedef enum {
JDCT_ISLOW, /* slow but accurate integer algorithm */
JDCT_IFAST, /* faster, less accurate integer method */
JDCT_FLOAT /* floating-point: accurate, fast on fast HW */
} J_DCT_METHOD;
#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */
#define JDCT_DEFAULT JDCT_ISLOW
#endif
#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */
#define JDCT_FASTEST JDCT_IFAST
#endif
/* Dithering options for decompression. */
typedef enum {
JDITHER_NONE, /* no dithering */
JDITHER_ORDERED, /* simple ordered dither */
JDITHER_FS /* Floyd-Steinberg error diffusion dither */
} J_DITHER_MODE;
/* Common fields between JPEG compression and decompression master structs. */
#define jpeg_common_fields \
struct jpeg_error_mgr * err; /* Error handler module */\
struct jpeg_memory_mgr * mem; /* Memory manager module */\
struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
void * client_data; /* Available for use by application */\
boolean is_decompressor; /* So common code can tell which is which */\
int global_state /* For checking call sequence validity */
/* Routines that are to be used by both halves of the library are declared
* to receive a pointer to this structure. There are no actual instances of
* jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
*/
struct jpeg_common_struct {
jpeg_common_fields; /* Fields common to both master struct types */
/* Additional fields follow in an actual jpeg_compress_struct or
* jpeg_decompress_struct. All three structs must agree on these
* initial fields! (This would be a lot cleaner in C++.)
*/
};
typedef struct jpeg_common_struct * j_common_ptr;
typedef struct jpeg_compress_struct * j_compress_ptr;
typedef struct jpeg_decompress_struct * j_decompress_ptr;
/* Master record for a compression instance */
struct jpeg_compress_struct {
jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */
/* Destination for compressed data */
struct jpeg_destination_mgr * dest;
/* Description of source image --- these fields must be filled in by
* outer application before starting compression. in_color_space must
* be correct before you can even call jpeg_set_defaults().
*/
JDIMENSION image_width; /* input image width */
JDIMENSION image_height; /* input image height */
int input_components; /* # of color components in input image */
J_COLOR_SPACE in_color_space; /* colorspace of input image */
double input_gamma; /* image gamma of input image */
/* Compression parameters --- these fields must be set before calling
* jpeg_start_compress(). We recommend calling jpeg_set_defaults() to
* initialize everything to reasonable defaults, then changing anything
* the application specifically wants to change. That way you won't get
* burnt when new parameters are added. Also note that there are several
* helper routines to simplify changing parameters.
*/
unsigned int scale_num, scale_denom; /* fraction by which to scale image */
JDIMENSION jpeg_width; /* scaled JPEG image width */
JDIMENSION jpeg_height; /* scaled JPEG image height */
/* Dimensions of actual JPEG image that will be written to file,
* derived from input dimensions by scaling factors above.
* These fields are computed by jpeg_start_compress().
* You can also use jpeg_calc_jpeg_dimensions() to determine these values
* in advance of calling jpeg_start_compress().
*/
int data_precision; /* bits of precision in image data */
int num_components; /* # of color components in JPEG image */
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
jpeg_component_info * comp_info;
/* comp_info[i] describes component that appears i'th in SOF */
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
int q_scale_factor[NUM_QUANT_TBLS];
/* ptrs to coefficient quantization tables, or NULL if not defined,
* and corresponding scale factors (percentage, initialized 100).
*/
JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
/* ptrs to Huffman coding tables, or NULL if not defined */
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
int num_scans; /* # of entries in scan_info array */
const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
/* The default value of scan_info is NULL, which causes a single-scan
* sequential JPEG file to be emitted. To create a multi-scan file,
* set num_scans and scan_info to point to an array of scan definitions.
*/
boolean raw_data_in; /* TRUE=caller supplies downsampled data */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */
int smoothing_factor; /* 1..100, or 0 for no input smoothing */
J_DCT_METHOD dct_method; /* DCT algorithm selector */
/* The restart interval can be specified in absolute MCUs by setting
* restart_interval, or in MCU rows by setting restart_in_rows
* (in which case the correct restart_interval will be figured
* for each scan).
*/
unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
int restart_in_rows; /* if > 0, MCU rows per restart interval */
/* Parameters controlling emission of special markers. */
boolean write_JFIF_header; /* should a JFIF marker be written? */
UINT8 JFIF_major_version; /* What to write for the JFIF version number */
UINT8 JFIF_minor_version;
/* These three values are not used by the JPEG code, merely copied */
/* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
/* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
/* ratio is defined by X_density/Y_density even when density_unit=0. */
UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */
boolean write_Adobe_marker; /* should an Adobe marker be written? */
J_COLOR_TRANSFORM color_transform;
/* Color transform identifier, writes LSE marker if nonzero */
/* State variable: index of next scanline to be written to
* jpeg_write_scanlines(). Application may use this to control its
* processing loop, e.g., "while (next_scanline < image_height)".
*/
JDIMENSION next_scanline; /* 0 .. image_height-1 */
/* Remaining fields are known throughout compressor, but generally
* should not be touched by a surrounding application.
*/
/*
* These fields are computed during compression startup
*/
boolean progressive_mode; /* TRUE if scan script uses progressive mode */
int max_h_samp_factor; /* largest h_samp_factor */
int max_v_samp_factor; /* largest v_samp_factor */
int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */
int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
/* The coefficient controller receives data in units of MCU rows as defined
* for fully interleaved scans (whether the JPEG file is interleaved or not).
* There are v_samp_factor * DCTSIZE sample rows of each component in an
* "iMCU" (interleaved MCU) row.
*/
/*
* These fields are valid during any one scan.
* They describe the components and MCUs actually appearing in the scan.
*/
int comps_in_scan; /* # of JPEG components in this scan */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
int blocks_in_MCU; /* # of DCT blocks per MCU */
int MCU_membership[C_MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
int block_size; /* the basic DCT block size: 1..16 */
const int * natural_order; /* natural-order position array */
int lim_Se; /* min( Se, DCTSIZE2-1 ) */
/*
* Links to compression subobjects (methods and private variables of modules)
*/
struct jpeg_comp_master * master;
struct jpeg_c_main_controller * main;
struct jpeg_c_prep_controller * prep;
struct jpeg_c_coef_controller * coef;
struct jpeg_marker_writer * marker;
struct jpeg_color_converter * cconvert;
struct jpeg_downsampler * downsample;
struct jpeg_forward_dct * fdct;
struct jpeg_entropy_encoder * entropy;
jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
int script_space_size;
};
/* Master record for a decompression instance */
struct jpeg_decompress_struct {
jpeg_common_fields; /* Fields shared with jpeg_compress_struct */
/* Source of compressed data */
struct jpeg_source_mgr * src;
/* Basic description of image --- filled in by jpeg_read_header(). */
/* Application may inspect these values to decide how to process image. */
JDIMENSION image_width; /* nominal image width (from SOF marker) */
JDIMENSION image_height; /* nominal image height */
int num_components; /* # of color components in JPEG image */
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
/* Decompression processing parameters --- these fields must be set before
* calling jpeg_start_decompress(). Note that jpeg_read_header() initializes
* them to default values.
*/
J_COLOR_SPACE out_color_space; /* colorspace for output */
unsigned int scale_num, scale_denom; /* fraction by which to scale image */
double output_gamma; /* image gamma wanted in output */
boolean buffered_image; /* TRUE=multiple output passes */
boolean raw_data_out; /* TRUE=downsampled data wanted */
J_DCT_METHOD dct_method; /* IDCT algorithm selector */
boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */
boolean do_block_smoothing; /* TRUE=apply interblock smoothing */
boolean quantize_colors; /* TRUE=colormapped output wanted */
/* the following are ignored if not quantize_colors: */
J_DITHER_MODE dither_mode; /* type of color dithering to use */
boolean two_pass_quantize; /* TRUE=use two-pass color quantization */
int desired_number_of_colors; /* max # colors to use in created colormap */
/* these are significant only in buffered-image mode: */
boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */
boolean enable_external_quant;/* enable future use of external colormap */
boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */
/* Description of actual output image that will be returned to application.
* These fields are computed by jpeg_start_decompress().
* You can also use jpeg_calc_output_dimensions() to determine these values
* in advance of calling jpeg_start_decompress().
*/
JDIMENSION output_width; /* scaled image width */
JDIMENSION output_height; /* scaled image height */
int out_color_components; /* # of color components in out_color_space */
int output_components; /* # of color components returned */
/* output_components is 1 (a colormap index) when quantizing colors;
* otherwise it equals out_color_components.
*/
int rec_outbuf_height; /* min recommended height of scanline buffer */
/* If the buffer passed to jpeg_read_scanlines() is less than this many rows
* high, space and time will be wasted due to unnecessary data copying.
* Usually rec_outbuf_height will be 1 or 2, at most 4.
*/
/* When quantizing colors, the output colormap is described by these fields.
* The application can supply a colormap by setting colormap non-NULL before
* calling jpeg_start_decompress; otherwise a colormap is created during
* jpeg_start_decompress or jpeg_start_output.
* The map has out_color_components rows and actual_number_of_colors columns.
*/
int actual_number_of_colors; /* number of entries in use */
JSAMPARRAY colormap; /* The color map as a 2-D pixel array */
/* State variables: these variables indicate the progress of decompression.
* The application may examine these but must not modify them.
*/
/* Row index of next scanline to be read from jpeg_read_scanlines().
* Application may use this to control its processing loop, e.g.,
* "while (output_scanline < output_height)".
*/
JDIMENSION output_scanline; /* 0 .. output_height-1 */
/* Current input scan number and number of iMCU rows completed in scan.
* These indicate the progress of the decompressor input side.
*/
int input_scan_number; /* Number of SOS markers seen so far */
JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */
/* The "output scan number" is the notional scan being displayed by the
* output side. The decompressor will not allow output scan/row number
* to get ahead of input scan/row, but it can fall arbitrarily far behind.
*/
int output_scan_number; /* Nominal scan number being displayed */
JDIMENSION output_iMCU_row; /* Number of iMCU rows read */
/* Current progression status. coef_bits[c][i] indicates the precision
* with which component c's DCT coefficient i (in zigzag order) is known.
* It is -1 when no data has yet been received, otherwise it is the point
* transform (shift) value for the most recent scan of the coefficient
* (thus, 0 at completion of the progression).
* This pointer is NULL when reading a non-progressive file.
*/
int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */
/* Internal JPEG parameters --- the application usually need not look at
* these fields. Note that the decompressor output side may not use
* any parameters that can change between scans.
*/
/* Quantization and Huffman tables are carried forward across input
* datastreams when processing abbreviated JPEG datastreams.
*/
JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
/* ptrs to coefficient quantization tables, or NULL if not defined */
JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
/* ptrs to Huffman coding tables, or NULL if not defined */
/* These parameters are never carried across datastreams, since they
* are given in SOF/SOS markers or defined to be reset by SOI.
*/
int data_precision; /* bits of precision in image data */
jpeg_component_info * comp_info;
/* comp_info[i] describes component that appears i'th in SOF */
boolean is_baseline; /* TRUE if Baseline SOF0 encountered */
boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
/* These fields record data obtained from optional markers recognized by
* the JPEG library.
*/
boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */
/* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
UINT8 JFIF_major_version; /* JFIF version number */
UINT8 JFIF_minor_version;
UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */
boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */
UINT8 Adobe_transform; /* Color transform code from Adobe marker */
J_COLOR_TRANSFORM color_transform;
/* Color transform identifier derived from LSE marker, otherwise zero */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */
/* Aside from the specific data retained from APPn markers known to the
* library, the uninterpreted contents of any or all APPn and COM markers
* can be saved in a list for examination by the application.
*/
jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */
/* Remaining fields are known throughout decompressor, but generally
* should not be touched by a surrounding application.
*/
/*
* These fields are computed during decompression startup
*/
int max_h_samp_factor; /* largest h_samp_factor */
int max_v_samp_factor; /* largest v_samp_factor */
int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */
int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
/* The coefficient controller's input and output progress is measured in
* units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows
* in fully interleaved JPEG scans, but are used whether the scan is
* interleaved or not. We define an iMCU row as v_samp_factor DCT block
* rows of each component. Therefore, the IDCT output contains
* v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row.
*/
JSAMPLE * sample_range_limit; /* table for fast range-limiting */
/*
* These fields are valid during any one scan.
* They describe the components and MCUs actually appearing in the scan.
* Note that the decompressor output side must not use these fields.
*/
int comps_in_scan; /* # of JPEG components in this scan */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */
JDIMENSION MCUs_per_row; /* # of MCUs across the image */
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
int blocks_in_MCU; /* # of DCT blocks per MCU */
int MCU_membership[D_MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
/* These fields are derived from Se of first SOS marker.
*/
int block_size; /* the basic DCT block size: 1..16 */
const int * natural_order; /* natural-order position array for entropy decode */
int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */
/* This field is shared between entropy decoder and marker parser.
* It is either zero or the code of a JPEG marker that has been
* read from the data source, but has not yet been processed.
*/
int unread_marker;
/*
* Links to decompression subobjects (methods, private variables of modules)
*/
struct jpeg_decomp_master * master;
struct jpeg_d_main_controller * main;
struct jpeg_d_coef_controller * coef;
struct jpeg_d_post_controller * post;
struct jpeg_input_controller * inputctl;
struct jpeg_marker_reader * marker;
struct jpeg_entropy_decoder * entropy;
struct jpeg_inverse_dct * idct;
struct jpeg_upsampler * upsample;
struct jpeg_color_deconverter * cconvert;
struct jpeg_color_quantizer * cquantize;
};
/* "Object" declarations for JPEG modules that may be supplied or called
* directly by the surrounding application.
* As with all objects in the JPEG library, these structs only define the
* publicly visible methods and state variables of a module. Additional
* private fields may exist after the public ones.
*/
/* Error handler object */
struct jpeg_error_mgr {
/* Error exit handler: does not return to caller */
JMETHOD(noreturn_t, error_exit, (j_common_ptr cinfo));
/* Conditionally emit a trace or warning message */
JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
/* Routine that actually outputs a trace or error message */
JMETHOD(void, output_message, (j_common_ptr cinfo));
/* Format a message string for the most recent JPEG error or message */
JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */
/* Reset error state variables at start of a new image */
JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
/* The message ID code and any parameters are saved here.
* A message can have one string parameter or up to 8 int parameters.
*/
int msg_code;
#define JMSG_STR_PARM_MAX 80
union {
int i[8];
char s[JMSG_STR_PARM_MAX];
} msg_parm;
/* Standard state variables for error facility */
int trace_level; /* max msg_level that will be displayed */
/* For recoverable corrupt-data errors, we emit a warning message,
* but keep going unless emit_message chooses to abort. emit_message
* should count warnings in num_warnings. The surrounding application
* can check for bad data by seeing if num_warnings is nonzero at the
* end of processing.
*/
long num_warnings; /* number of corrupt-data warnings */
/* These fields point to the table(s) of error message strings.
* An application can change the table pointer to switch to a different
* message list (typically, to change the language in which errors are
* reported). Some applications may wish to add additional error codes
* that will be handled by the JPEG library error mechanism; the second
* table pointer is used for this purpose.
*
* First table includes all errors generated by JPEG library itself.
* Error code 0 is reserved for a "no such error string" message.
*/
const char * const * jpeg_message_table; /* Library errors */
int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */
/* Second table can be added by application (see cjpeg/djpeg for example).
* It contains strings numbered first_addon_message..last_addon_message.
*/
const char * const * addon_message_table; /* Non-library errors */
int first_addon_message; /* code for first string in addon table */
int last_addon_message; /* code for last string in addon table */
};
/* Progress monitor object */
struct jpeg_progress_mgr {
JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
long pass_counter; /* work units completed in this pass */
long pass_limit; /* total number of work units in this pass */
int completed_passes; /* passes completed so far */
int total_passes; /* total number of passes expected */
};
/* Data destination object for compression */
struct jpeg_destination_mgr {
JOCTET * next_output_byte; /* => next byte to write in buffer */
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
JMETHOD(void, init_destination, (j_compress_ptr cinfo));
JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
JMETHOD(void, term_destination, (j_compress_ptr cinfo));
};
/* Data source object for decompression */
struct jpeg_source_mgr {
const JOCTET * next_input_byte; /* => next byte to read from buffer */
size_t bytes_in_buffer; /* # of bytes remaining in buffer */
JMETHOD(void, init_source, (j_decompress_ptr cinfo));
JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
JMETHOD(void, term_source, (j_decompress_ptr cinfo));
};
/* Memory manager object.
* Allocates "small" objects (a few K total), "large" objects (tens of K),
* and "really big" objects (virtual arrays with backing store if needed).
* The memory manager does not allow individual objects to be freed; rather,
* each created object is assigned to a pool, and whole pools can be freed
* at once. This is faster and more convenient than remembering exactly what
* to free, especially where malloc()/free() are not too speedy.
* NB: alloc routines never return NULL. They exit to error_exit if not
* successful.
*/
#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
#define JPOOL_NUMPOOLS 2
typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
typedef struct jvirt_barray_control * jvirt_barray_ptr;
struct jpeg_memory_mgr {
/* Method pointers */
JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
size_t sizeofobject));
JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
size_t sizeofobject));
JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
JDIMENSION samplesperrow,
JDIMENSION numrows));
JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
JDIMENSION blocksperrow,
JDIMENSION numrows));
JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
int pool_id,
boolean pre_zero,
JDIMENSION samplesperrow,
JDIMENSION numrows,
JDIMENSION maxaccess));
JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
int pool_id,
boolean pre_zero,
JDIMENSION blocksperrow,
JDIMENSION numrows,
JDIMENSION maxaccess));
JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
jvirt_sarray_ptr ptr,
JDIMENSION start_row,
JDIMENSION num_rows,
boolean writable));
JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
jvirt_barray_ptr ptr,
JDIMENSION start_row,
JDIMENSION num_rows,
boolean writable));
JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
JMETHOD(void, self_destruct, (j_common_ptr cinfo));
/* Limit on memory allocation for this JPEG object. (Note that this is
* merely advisory, not a guaranteed maximum; it only affects the space
* used for virtual-array buffers.) May be changed by outer application
* after creating the JPEG object.
*/
long max_memory_to_use;
/* Maximum allocation request accepted by alloc_large. */
long max_alloc_chunk;
};
/* Routine signature for application-supplied marker processing methods.
* Need not pass marker code since it is stored in cinfo->unread_marker.
*/
typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
/* Declarations for routines called by application.
* The JPP macro hides prototype parameters from compilers that can't cope.
* Note JPP requires double parentheses.
*/
#ifdef HAVE_PROTOTYPES
#define JPP(arglist) arglist
#else
#define JPP(arglist) ()
#endif
/* Short forms of external names for systems with brain-damaged linkers.
* We shorten external names to be unique in the first six letters, which
* is good enough for all known systems.
* (If your compiler itself needs names to be unique in less than 15
* characters, you are out of luck. Get a better compiler.)
*/
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jpeg_std_error jStdError
#define jpeg_CreateCompress jCreaCompress
#define jpeg_CreateDecompress jCreaDecompress
#define jpeg_destroy_compress jDestCompress
#define jpeg_destroy_decompress jDestDecompress
#define jpeg_stdio_dest jStdDest
#define jpeg_stdio_src jStdSrc
#define jpeg_mem_dest jMemDest
#define jpeg_mem_src jMemSrc
#define jpeg_set_defaults jSetDefaults
#define jpeg_set_colorspace jSetColorspace
#define jpeg_default_colorspace jDefColorspace
#define jpeg_set_quality jSetQuality
#define jpeg_set_linear_quality jSetLQuality
#define jpeg_default_qtables jDefQTables
#define jpeg_add_quant_table jAddQuantTable
#define jpeg_quality_scaling jQualityScaling
#define jpeg_simple_progression jSimProgress
#define jpeg_suppress_tables jSuppressTables
#define jpeg_alloc_quant_table jAlcQTable
#define jpeg_alloc_huff_table jAlcHTable
#define jpeg_start_compress jStrtCompress
#define jpeg_write_scanlines jWrtScanlines
#define jpeg_finish_compress jFinCompress
#define jpeg_calc_jpeg_dimensions jCjpegDimensions
#define jpeg_write_raw_data jWrtRawData
#define jpeg_write_marker jWrtMarker
#define jpeg_write_m_header jWrtMHeader
#define jpeg_write_m_byte jWrtMByte
#define jpeg_write_tables jWrtTables
#define jpeg_read_header jReadHeader
#define jpeg_start_decompress jStrtDecompress
#define jpeg_read_scanlines jReadScanlines
#define jpeg_finish_decompress jFinDecompress
#define jpeg_read_raw_data jReadRawData
#define jpeg_has_multiple_scans jHasMultScn
#define jpeg_start_output jStrtOutput
#define jpeg_finish_output jFinOutput
#define jpeg_input_complete jInComplete
#define jpeg_new_colormap jNewCMap
#define jpeg_consume_input jConsumeInput
#define jpeg_core_output_dimensions jCoreDimensions
#define jpeg_calc_output_dimensions jCalcDimensions
#define jpeg_save_markers jSaveMarkers
#define jpeg_set_marker_processor jSetMarker
#define jpeg_read_coefficients jReadCoefs
#define jpeg_write_coefficients jWrtCoefs
#define jpeg_copy_critical_parameters jCopyCrit
#define jpeg_abort_compress jAbrtCompress
#define jpeg_abort_decompress jAbrtDecompress
#define jpeg_abort jAbort
#define jpeg_destroy jDestroy
#define jpeg_resync_to_restart jResyncRestart
#endif /* NEED_SHORT_EXTERNAL_NAMES */
/* Default error-management setup */
EXTERN(struct jpeg_error_mgr *) jpeg_std_error
JPP((struct jpeg_error_mgr * err));
/* Initialization of JPEG compression objects.
* jpeg_create_compress() and jpeg_create_decompress() are the exported
* names that applications should call. These expand to calls on
* jpeg_CreateCompress and jpeg_CreateDecompress with additional information
* passed for version mismatch checking.
* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
*/
#define jpeg_create_compress(cinfo) \
jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_compress_struct))
#define jpeg_create_decompress(cinfo) \
jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_decompress_struct))
EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
int version, size_t structsize));
EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
int version, size_t structsize));
/* Destruction of JPEG compression objects */
EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
/* Standard data source and destination managers: stdio streams. */
/* Caller is responsible for opening the file before and closing after. */
EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
/* Data source and destination managers: memory buffers. */
EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo,
unsigned char ** outbuffer,
unsigned long * outsize));
EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo,
unsigned char * inbuffer,
unsigned long insize));
/* Default parameter setup for compression */
EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
/* Compression parameter setup aids */
EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
J_COLOR_SPACE colorspace));
EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
boolean force_baseline));
EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
int scale_factor,
boolean force_baseline));
EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo,
boolean force_baseline));
EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
const unsigned int *basic_table,
int scale_factor,
boolean force_baseline));
EXTERN(int) jpeg_quality_scaling JPP((int quality));
EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
boolean suppress));
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
/* Main entry points for compression */
EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
boolean write_all_tables));
EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION num_lines));
EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
/* Precalculate JPEG dimensions for current compression parameters. */
EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo));
/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
JSAMPIMAGE data,
JDIMENSION num_lines));
/* Write a special marker. See libjpeg.txt concerning safe usage. */
EXTERN(void) jpeg_write_marker
JPP((j_compress_ptr cinfo, int marker,
const JOCTET * dataptr, unsigned int datalen));
/* Same, but piecemeal. */
EXTERN(void) jpeg_write_m_header
JPP((j_compress_ptr cinfo, int marker, unsigned int datalen));
EXTERN(void) jpeg_write_m_byte
JPP((j_compress_ptr cinfo, int val));
/* Alternate compression function: just write an abbreviated table file */
EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
/* Decompression startup: read start of JPEG datastream to see what's there */
EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
boolean require_image));
/* Return value is one of: */
#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
#define JPEG_HEADER_OK 1 /* Found valid image datastream */
#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
/* If you pass require_image = TRUE (normal case), you need not check for
* a TABLES_ONLY return code; an abbreviated file will cause an error exit.
* JPEG_SUSPENDED is only possible if you use a data source module that can
* give a suspension return (the stdio source module doesn't).
*/
/* Main entry points for decompression */
EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION max_lines));
EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
JSAMPIMAGE data,
JDIMENSION max_lines));
/* Additional entry points for buffered-image mode. */
EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo));
EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo,
int scan_number));
EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo));
EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo));
EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo));
EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
/* Return value is one of: */
/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
#define JPEG_REACHED_EOI 2 /* Reached end of image */
#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */
#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */
/* Precalculate output dimensions for current decompression parameters. */
EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo));
EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
/* Control saving of COM and APPn markers into marker_list. */
EXTERN(void) jpeg_save_markers
JPP((j_decompress_ptr cinfo, int marker_code,
unsigned int length_limit));
/* Install a special processing method for COM or APPn markers. */
EXTERN(void) jpeg_set_marker_processor
JPP((j_decompress_ptr cinfo, int marker_code,
jpeg_marker_parser_method routine));
/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo));
EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo,
jvirt_barray_ptr * coef_arrays));
EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo,
j_compress_ptr dstinfo));
/* If you choose to abort compression or decompression before completing
* jpeg_finish_(de)compress, then you need to clean up to release memory,
* temporary files, etc. You can just call jpeg_destroy_(de)compress
* if you're done with the JPEG object, but if you want to clean it up and
* reuse it, call this:
*/
EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
/* Generic versions of jpeg_abort and jpeg_destroy that work on either
* flavor of JPEG object. These may be more convenient in some places.
*/
EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
/* Default restart-marker-resync procedure for use by data source modules */
EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
int desired));
/* These marker codes are exported since applications and data source modules
* are likely to want to use them.
*/
#define JPEG_RST0 0xD0 /* RST0 marker code */
#define JPEG_EOI 0xD9 /* EOI marker code */
#define JPEG_APP0 0xE0 /* APP0 marker code */
#define JPEG_COM 0xFE /* COM marker code */
/* If we have a brain-damaged compiler that emits warnings (or worse, errors)
* for structure definitions that are never filled in, keep it quiet by
* supplying dummy definitions for the various substructures.
*/
#ifdef INCOMPLETE_TYPES_BROKEN
#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */
struct jvirt_sarray_control { long dummy; };
struct jvirt_barray_control { long dummy; };
struct jpeg_comp_master { long dummy; };
struct jpeg_c_main_controller { long dummy; };
struct jpeg_c_prep_controller { long dummy; };
struct jpeg_c_coef_controller { long dummy; };
struct jpeg_marker_writer { long dummy; };
struct jpeg_color_converter { long dummy; };
struct jpeg_downsampler { long dummy; };
struct jpeg_forward_dct { long dummy; };
struct jpeg_entropy_encoder { long dummy; };
struct jpeg_decomp_master { long dummy; };
struct jpeg_d_main_controller { long dummy; };
struct jpeg_d_coef_controller { long dummy; };
struct jpeg_d_post_controller { long dummy; };
struct jpeg_input_controller { long dummy; };
struct jpeg_marker_reader { long dummy; };
struct jpeg_entropy_decoder { long dummy; };
struct jpeg_inverse_dct { long dummy; };
struct jpeg_upsampler { long dummy; };
struct jpeg_color_deconverter { long dummy; };
struct jpeg_color_quantizer { long dummy; };
#endif /* JPEG_INTERNALS */
#endif /* INCOMPLETE_TYPES_BROKEN */
/*
* The JPEG library modules define JPEG_INTERNALS before including this file.
* The internal structure declarations are read only when that is true.
* Applications using the library should not include jpegint.h, but may wish
* to include jerror.h.
*/
#ifdef JPEG_INTERNALS
#include "jpegint.h" /* fetch private declarations */
#include "jerror.h" /* fetch error codes too */
#endif
#ifdef __cplusplus
#ifndef DONT_USE_EXTERN_C
}
#endif
#endif
#endif /* JPEGLIB_H */
================================================
FILE: src/main/jni/png/config.h
================================================
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the header file. */
#define HAVE_DLFCN_H 0
/* Define to 1 if you have the header file. */
#define HAVE_INTTYPES_H 0
/* Define to 1 if you have the `m' library (-lm). */
#define HAVE_LIBM 1
/* Define to 1 if you have the `z' library (-lz). */
#define HAVE_LIBZ 1
/* Define to 1 if you have the header file. */
#define HAVE_MALLOC_H 1
/* Define to 1 if you have the header file. */
#define HAVE_MEMORY_H 0
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the `pow' function. */
/* #undef HAVE_POW */
/* Define to 1 if you have the header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the header file. */
#define HAVE_UNISTD_H 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libpng"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "png-mng-implement@lists.sourceforge.net"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libpng"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libpng 1.4.19"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libpng"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.4.19"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if your declares `struct tm'. */
/* #undef TM_IN_SYS_TIME */
/* Version number of package */
#define VERSION "1.4.19"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if does not define. */
/* #undef size_t */
================================================
FILE: src/main/jni/png/png.h
================================================
/* png.h - header file for PNG reference library
*
* libpng version 1.4.19, December 17, 2015
*
* Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license (See LICENSE, below)
*
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.4.19, December 17, 2015: Glenn
* See also "Contributing Authors", below.
*/
/*
* COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
*
* If you modify libpng you may insert additional notices immediately following
* this sentence.
*
* This code is released under the libpng license.
*
* libpng versions 1.0.7, July 1, 2000, through 1.4.19, December 17, 2015, are
* Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
* derived from libpng-1.0.6, and are distributed according to the same
* disclaimer and license as libpng-1.0.6 with the following individuals
* added to the list of Contributing Authors:
*
* Simon-Pierre Cadieux
* Eric S. Raymond
* Cosmin Truta
* Gilles Vollant
*
* and with the following additions to the disclaimer:
*
* There is no warranty against interference with your enjoyment of the
* library or against infringement. There is no warranty that our
* efforts or the library will fulfill any of your particular purposes
* or needs. This library is provided with all faults, and the entire
* risk of satisfactory quality, performance, accuracy, and effort is with
* the user.
*
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
* Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
* libpng-0.96, and are distributed according to the same disclaimer and
* license as libpng-0.96, with the following individuals added to the list
* of Contributing Authors:
*
* Tom Lane
* Glenn Randers-Pehrson
* Willem van Schaik
*
* libpng versions 0.89, June 1996, through 0.96, May 1997, are
* Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
* and are distributed according to the same disclaimer and license as
* libpng-0.88, with the following individuals added to the list of
* Contributing Authors:
*
* John Bowler
* Kevin Bracey
* Sam Bushell
* Magnus Holmgren
* Greg Roelofs
* Tom Tanner
*
* libpng versions 0.5, May 1995, through 0.88, January 1996, are
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* For the purposes of this copyright and license, "Contributing Authors"
* is defined as the following set of individuals:
*
* Andreas Dilger
* Dave Martindale
* Guy Eric Schalnat
* Paul Schmidt
* Tim Wegner
*
* The PNG Reference Library is supplied "AS IS". The Contributing Authors
* and Group 42, Inc. disclaim all warranties, expressed or implied,
* including, without limitation, the warranties of merchantability and of
* fitness for any purpose. The Contributing Authors and Group 42, Inc.
* assume no liability for direct, indirect, incidental, special, exemplary,
* or consequential damages, which may result from the use of the PNG
* Reference Library, even if advised of the possibility of such damage.
*
* Permission is hereby granted to use, copy, modify, and distribute this
* source code, or portions hereof, for any purpose, without fee, subject
* to the following restrictions:
*
* 1. The origin of this source code must not be misrepresented.
*
* 2. Altered versions must be plainly marked as such and must not
* be misrepresented as being the original source.
*
* 3. This Copyright notice may not be removed or altered from any
* source or altered source distribution.
*
* The Contributing Authors and Group 42, Inc. specifically permit, without
* fee, and encourage the use of this source code as a component to
* supporting the PNG file format in commercial products. If you use this
* source code in a product, acknowledgment is not required but would be
* appreciated.
*
* END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
*/
/*
* A "png_get_copyright" function is available, for convenient use in "about"
* boxes and the like:
*
* printf("%s", png_get_copyright(NULL));
*
* Also, the PNG logo (in PNG format, of course) is supplied in the
* files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
*/
/*
* Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
* a certification mark of the Open Source Initiative. OSI has not addressed
* the additional disclaimers inserted at version 1.0.7.
*/
/*
* The contributing authors would like to thank all those who helped
* with testing, bug fixes, and patience. This wouldn't have been
* possible without all of you.
*
* Thanks to Frank J. T. Wojcik for helping with the documentation.
*/
/* Note about libpng version numbers:
*
* Due to various miscommunications, unforeseen code incompatibilities
* and occasional factors outside the authors' control, version numbering
* on the library has not always been consistent and straightforward.
* The following table summarizes matters since version 0.89c, which was
* the first widely used release:
*
* source png.h png.h shared-lib
* version string int version
* ------- ------ ----- ----------
* 0.89c "1.0 beta 3" 0.89 89 1.0.89
* 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90]
* 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95]
* 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96]
* 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97]
* 0.97c 0.97 97 2.0.97
* 0.98 0.98 98 2.0.98
* 0.99 0.99 98 2.0.99
* 0.99a-m 0.99 99 2.0.99
* 1.00 1.00 100 2.1.0 [100 should be 10000]
* 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000]
* 1.0.1 png.h string is 10001 2.1.0
* 1.0.1a-e identical to the 10002 from here on, the shared library
* 1.0.2 source version) 10002 is 2.V where V is the source code
* 1.0.2a-b 10003 version, except as noted.
* 1.0.3 10003
* 1.0.3a-d 10004
* 1.0.4 10004
* 1.0.4a-f 10005
* 1.0.5 (+ 2 patches) 10005
* 1.0.5a-d 10006
* 1.0.5e-r 10100 (not source compatible)
* 1.0.5s-v 10006 (not binary compatible)
* 1.0.6 (+ 3 patches) 10006 (still binary incompatible)
* 1.0.6d-f 10007 (still binary incompatible)
* 1.0.6g 10007
* 1.0.6h 10007 10.6h (testing xy.z so-numbering)
* 1.0.6i 10007 10.6i
* 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0)
* 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible)
* 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible)
* 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
* 1.0.7 1 10007 (still compatible)
* ...
* 1.0.19 10 10019 10.so.0.19[.0]
* ...
* 1.4.19 14 10419 14.so.14.19[.0]
*
* Henceforth the source version will match the shared-library major
* and minor numbers; the shared-library major version number will be
* used for changes in backward compatibility, as it is intended. The
* PNG_LIBPNG_VER macro, which is not used within libpng but is available
* for applications, is an unsigned integer of the form xyyzz corresponding
* to the source version x.y.z (leading zeros in y and z). Beta versions
* were given the previous public release number plus a letter, until
* version 1.0.6j; from then on they were given the upcoming public
* release number plus "betaNN" or "rcNN".
*
* Binary incompatibility exists only when applications make direct access
* to the info_ptr or png_ptr members through png.h, and the compiled
* application is loaded with a different version of the library.
*
* DLLNUM will change each time there are forward or backward changes
* in binary compatibility (e.g., when a new feature is added).
*
* See libpng.txt or libpng.3 for more information. The PNG specification
* is available as a W3C Recommendation and as an ISO Specification,
* defines should NOT be changed.
*/
#define PNG_INFO_gAMA 0x0001
#define PNG_INFO_sBIT 0x0002
#define PNG_INFO_cHRM 0x0004
#define PNG_INFO_PLTE 0x0008
#define PNG_INFO_tRNS 0x0010
#define PNG_INFO_bKGD 0x0020
#define PNG_INFO_hIST 0x0040
#define PNG_INFO_pHYs 0x0080
#define PNG_INFO_oFFs 0x0100
#define PNG_INFO_tIME 0x0200
#define PNG_INFO_pCAL 0x0400
#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */
#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */
#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */
#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */
#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */
/* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using
* the routines for other purposes.
*/
typedef struct png_row_info_struct
{
png_uint_32 width; /* width of row */
png_size_t rowbytes; /* number of bytes in row */
png_byte color_type; /* color type of row */
png_byte bit_depth; /* bit depth of row */
png_byte channels; /* number of channels (1, 2, 3, or 4) */
png_byte pixel_depth; /* bits per pixel (depth * channels) */
} png_row_info;
typedef png_row_info FAR * png_row_infop;
typedef png_row_info FAR * FAR * png_row_infopp;
/* These are the function types for the I/O functions and for the functions
* that allow the user to override the default I/O functions with his or her
* own. The png_error_ptr type should match that of user-supplied warning
* and error functions, while the png_rw_ptr type should match that of the
* user read/write data functions.
*/
typedef struct png_struct_def png_struct;
typedef png_struct FAR * png_structp;
typedef PNG_CONST png_struct FAR * png_const_structp;
typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp));
typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t));
typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp));
typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32,
int));
typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32,
int));
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp,
png_infop));
typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop));
typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep,
png_uint_32, int));
#endif
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp,
png_row_infop, png_bytep));
#endif
#ifdef PNG_USER_CHUNKS_SUPPORTED
typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp,
png_unknown_chunkp));
#endif
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp));
#endif
#ifdef PNG_SETJMP_SUPPORTED
/* This must match the function definition in , and the
* application must include this before png.h to obtain the definition
* of jmp_buf.
*/
typedef void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int));
#endif
/* Transform masks for the high-level interface */
#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */
#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */
#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */
#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */
#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */
#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */
#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */
#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */
#define PNG_TRANSFORM_BGR 0x0080 /* read and write */
#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */
#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */
#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */
#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */
/* Added to libpng-1.2.34 */
#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER
#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */
/* Added to libpng-1.4.0 */
#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */
/* Flags for MNG supported features */
#define PNG_FLAG_MNG_EMPTY_PLTE 0x01
#define PNG_FLAG_MNG_FILTER_64 0x04
#define PNG_ALL_MNG_FEATURES 0x05
typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_alloc_size_t));
typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp));
/* The structure that holds the information to read and write PNG files.
* The only people who need to care about what is inside of this are the
* people who will be modifying the library for their own special needs.
* It should NOT be accessed directly by an application, except to store
* the jmp_buf.
*/
struct png_struct_def
{
#ifdef PNG_SETJMP_SUPPORTED
jmp_buf jmpbuf PNG_DEPSTRUCT; /* used in png_error */
png_longjmp_ptr longjmp_fn PNG_DEPSTRUCT;/* setjmp non-local goto
function. */
#endif
png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing
errors and aborting */
png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing
warnings */
png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for
error functions */
png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing
output data */
png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading
input data */
png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct
for I/O functions */
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read
transform */
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write
transform */
#endif
/* These were added in libpng-1.0.2 */
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct
for user transform */
png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user
transformed pixels */
png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user
transformed pixels */
#endif
#endif
png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in
the PNG file */
png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various
things to libpng */
png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations
to perform */
z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression
structure (below) */
png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */
png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */
int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */
int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */
int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window
bits */
int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory
level */
int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression
strategy */
png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */
png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */
png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */
png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */
png_size_t rowbytes PNG_DEPSTRUCT; /* size of row in bytes */
#if 0 /* Replaced with the following in libpng-1.4.1 */
png_size_t irowbytes PNG_DEPSTRUCT;
#endif
/* Added in libpng-1.4.1 */
#ifdef PNG_USER_LIMITS_SUPPORTED
/* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk
* can occupy when decompressed. 0 means unlimited.
* We will change the typedef from png_size_t to png_alloc_size_t
* in libpng-1.6.0
*/
png_alloc_size_t user_chunk_malloc_max PNG_DEPSTRUCT;
#endif
png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced
row in pixels */
png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */
png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous
(unfiltered) row */
png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current
(unfiltered) row */
png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row
when filtering */
png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row
when filtering */
png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row
when filtering */
png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row
when filtering */
png_row_info row_info PNG_DEPSTRUCT; /* used for transformation
routines */
png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */
png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */
png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */
png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in
palette */
png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */
png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current
chunk */
png_byte compression PNG_DEPSTRUCT; /* file compression type
(always 0) */
png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */
png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE,
PNG_INTERLACE_ADAM7 */
png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */
png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see
PNG_FILTER_ below ) */
png_byte color_type PNG_DEPSTRUCT; /* color type of file */
png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */
png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */
png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */
png_byte channels PNG_DEPSTRUCT; /* number of channels in file */
png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */
png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from
start of file */
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel
expansion */
#endif
#ifdef PNG_bKGD_SUPPORTED
png_byte background_gamma_type PNG_DEPSTRUCT;
# ifdef PNG_FLOATING_POINT_SUPPORTED
float background_gamma PNG_DEPSTRUCT;
# endif
png_color_16 background PNG_DEPSTRUCT; /* background color in
screen gamma space */
#ifdef PNG_READ_GAMMA_SUPPORTED
png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized
to gamma 1.0 */
#endif
#endif /* PNG_bKGD_SUPPORTED */
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing
output */
png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush,
0 - no flush */
png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since
last flush */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits
16-bit gamma */
#ifdef PNG_FLOATING_POINT_SUPPORTED
float gamma PNG_DEPSTRUCT; /* file gamma value */
float screen_gamma PNG_DEPSTRUCT; /* screen gamma value
(display_exponent) */
#endif
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit
depth files */
png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */
png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */
png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit
depth files */
png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to
screen */
png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each
available channel */
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit
tranformation */
#endif
#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
|| defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep trans_alpha PNG_DEPSTRUCT; /* alpha values for
paletted files */
png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for
non-paletted files */
#endif
png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each
row is decoded */
png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each
row is encoded */
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header
data fully read */
png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each
prog. row is decoded */
png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image
is complete */
png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in
save_buffer */
png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously
read data */
png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in
current_buffer */
png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently
used data */
png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input
chunk */
png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in
input data */
png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now
in save_buffer */
png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of
save_buffer */
png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of
available input data */
png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now
in current_buffer */
int process_mode PNG_DEPSTRUCT; /* what push library
is currently doing */
int cur_palette PNG_DEPSTRUCT; /* current push library
palette index */
# ifdef PNG_TEXT_SUPPORTED
png_size_t current_text_size PNG_DEPSTRUCT; /* current size of
text input data */
png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left
to read in input */
png_charp current_text PNG_DEPSTRUCT; /* current text chunk
buffer */
png_charp current_text_ptr PNG_DEPSTRUCT; /* current location
in current_text */
# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* For the Borland special 64K segment handler */
png_bytepp offset_table_ptr PNG_DEPSTRUCT;
png_bytep offset_table PNG_DEPSTRUCT;
png_uint_16 offset_table_number PNG_DEPSTRUCT;
png_uint_16 offset_table_count PNG_DEPSTRUCT;
png_uint_16 offset_table_count_free PNG_DEPSTRUCT;
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for quantizing */
png_bytep quantize_index PNG_DEPSTRUCT; /* index translation for palette
files */
#endif
#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED)
png_uint_16p hist PNG_DEPSTRUCT; /* histogram */
#endif
#ifdef PNG_TIME_RFC1123_SUPPORTED
png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */
#endif
/* New members added in libpng-1.0.6 */
png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is
responsible for freeing */
#ifdef PNG_USER_CHUNKS_SUPPORTED
png_voidp user_chunk_ptr PNG_DEPSTRUCT;
png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read
chunk handler */
#endif
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
int num_chunk_list PNG_DEPSTRUCT;
png_bytep chunk_list PNG_DEPSTRUCT;
#endif
/* New members added in libpng-1.0.3 */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte rgb_to_gray_status PNG_DEPSTRUCT;
/* These were changed from png_byte in libpng-1.0.6 */
png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT;
png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT;
png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT;
#endif
/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
#if defined(PNG_MNG_FEATURES_SUPPORTED) || \
defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
/* Changed from png_byte to png_uint_32 at version 1.2.0 */
png_uint_32 mng_features_permitted PNG_DEPSTRUCT;
#endif
/* New member added in libpng-1.0.7 */
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_fixed_point int_gamma PNG_DEPSTRUCT;
#endif
/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_byte filter_type PNG_DEPSTRUCT;
#endif
/* New members added in libpng-1.2.0 */
/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
#ifdef PNG_USER_MEM_SUPPORTED
png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for
mem functions */
png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for
allocating memory */
png_free_ptr free_fn PNG_DEPSTRUCT; /* function for
freeing memory */
#endif
/* New member added in libpng-1.0.13 and 1.2.0 */
png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current
(unfiltered) row */
#ifdef PNG_READ_QUANTIZE_SUPPORTED
/* The following three members were added at version 1.0.14 and 1.2.4 */
png_bytep quantize_sort PNG_DEPSTRUCT; /* working sort array */
png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original
index currently is
in the palette */
png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index
points to this
palette color */
#endif
/* New members added in libpng-1.0.16 and 1.2.6 */
png_byte compression_type PNG_DEPSTRUCT;
#ifdef PNG_USER_LIMITS_SUPPORTED
png_uint_32 user_width_max PNG_DEPSTRUCT;
png_uint_32 user_height_max PNG_DEPSTRUCT;
/* Added in libpng-1.4.0: Total number of sPLT, text, and unknown
* chunks that can be stored (0 means unlimited).
*/
png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT;
#endif
/* New member added in libpng-1.0.25 and 1.2.17 */
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
/* Storage for unknown chunk that the library doesn't recognize. */
png_unknown_chunk unknown_chunk PNG_DEPSTRUCT;
#endif
/* New members added in libpng-1.2.26 */
png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT;
png_uint_32 old_prev_row_size PNG_DEPSTRUCT;
/* New member added in libpng-1.2.30 */
png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */
#ifdef PNG_IO_STATE_SUPPORTED
/* New member added in libpng-1.4.0 */
png_uint_32 io_state PNG_DEPSTRUCT;
#endif
};
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
typedef png_structp version_1_4_19;
typedef png_struct FAR * FAR * png_structpp;
/* Here are the function definitions most commonly used. This is not
* the place to find out how to use libpng. See libpng.txt for the
* full explanation, see example.c for the summary. This just provides
* a simple one line description of the use of each function.
*/
/* Returns the version number of the library */
PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void));
/* Tell lib we have already handled the first magic bytes.
* Handling more than 8 bytes from the beginning of the file is an error.
*/
PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr,
int num_bytes));
/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
* PNG file. Returns zero if the supplied bytes match the 8-byte PNG
* signature, and non-zero otherwise. Having num_to_check == 0 or
* start > 7 will always fail (ie return non-zero).
*/
PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start,
png_size_t num_to_check));
/* Simple signature checking function. This is the same as calling
* png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
*/
#define png_check_sig(sig,n) !png_sig_cmp((sig), 0, (n))
/* Allocate and initialize png_ptr struct for reading, and any other memory. */
PNG_EXPORT(png_structp,png_create_read_struct)
PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED;
/* Allocate and initialize png_ptr struct for writing, and any other memory */
PNG_EXPORT(png_structp,png_create_write_struct)
PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED;
PNG_EXPORT(png_size_t,png_get_compression_buffer_size)
PNGARG((png_const_structp png_ptr));
PNG_EXPORT(void,png_set_compression_buffer_size)
PNGARG((png_structp png_ptr, png_size_t size));
/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp
* match up.
*/
#ifdef PNG_SETJMP_SUPPORTED
/* This function returns the jmp_buf built in to *png_ptr. It must be
* supplied with an appropriate 'longjmp' function to use on that jmp_buf
* unless the default error function is overridden in which case NULL is
* acceptable. The size of the jmp_buf is checked against the actual size
* allocated by the library - the call will return NULL on a mismatch
* indicating an ABI mismatch.
*/
PNG_EXPORT(jmp_buf*, png_set_longjmp_fn)
PNGARG((png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t
jmp_buf_size));
# define png_jmpbuf(png_ptr) \
(*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf)))
#else
# define png_jmpbuf(png_ptr) \
(LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP)
#endif
#ifdef PNG_READ_SUPPORTED
/* Reset the compression stream */
PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr));
#endif
/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
#ifdef PNG_USER_MEM_SUPPORTED
PNG_EXPORT(png_structp,png_create_read_struct_2)
PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED;
PNG_EXPORT(png_structp,png_create_write_struct_2)
PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED;
#endif
/* Write the PNG file signature. */
PNG_EXPORT(void,png_write_sig) PNGARG((png_structp png_ptr));
/* Write a PNG chunk - size, type, (optional) data, CRC. */
PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr,
png_bytep chunk_name, png_bytep data, png_size_t length));
/* Write the start of a PNG chunk - length and chunk name. */
PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr,
png_bytep chunk_name, png_uint_32 length));
/* Write the data of a PNG chunk started with png_write_chunk_start(). */
PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr,
png_bytep data, png_size_t length));
/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr));
/* Allocate and initialize the info structure */
PNG_EXPORT(png_infop,png_create_info_struct)
PNGARG((png_structp png_ptr)) PNG_ALLOCATED;
PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr,
png_size_t png_info_struct_size));
/* Writes all the PNG information before the image. */
PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr,
png_infop info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the information before the actual image data. */
PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr,
png_infop info_ptr));
#endif
#ifdef PNG_TIME_RFC1123_SUPPORTED
PNG_EXPORT(png_charp,png_convert_to_rfc1123)
PNGARG((png_structp png_ptr, png_timep ptime));
#endif
#ifdef PNG_CONVERT_tIME_SUPPORTED
/* Convert from a struct tm to png_time */
PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime,
struct tm FAR * ttime));
/* Convert from time_t to png_time. Uses gmtime() */
PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime,
time_t ttime));
#endif /* PNG_CONVERT_tIME_SUPPORTED */
#ifdef PNG_READ_EXPAND_SUPPORTED
/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr));
PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp
png_ptr));
PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr));
PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* Use blue, green, red order for pixels. */
PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr));
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand the grayscale to 24-bit RGB if necessary. */
PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr));
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
/* Reduce RGB to grayscale. */
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr,
int error_action, double red, double green ));
#endif
PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr,
int error_action, png_fixed_point red, png_fixed_point green ));
PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_const_structp
png_ptr));
#endif
PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth,
png_colorp palette));
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */
PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr,
png_uint_32 filler, int flags));
/* The values of the PNG_FILLER_ defines should NOT be changed */
#define PNG_FILLER_BEFORE 0
#define PNG_FILLER_AFTER 1
/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */
PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr,
png_uint_32 filler, int flags));
#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* Swap bytes in 16-bit depth files. */
PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* Swap packing order of pixels in bytes. */
PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
/* Converts files to legal bit depths. */
PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr,
png_color_8p true_bits));
#endif
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* Have the code handle the interlacing. Returns the number of passes. */
PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr));
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
/* Invert monochrome files */
PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr));
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
/* Handle alpha and tRNS by replacing with a background color. */
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr,
png_color_16p background_color, int background_gamma_code,
int need_expand, double background_gamma));
#endif
#define PNG_BACKGROUND_GAMMA_UNKNOWN 0
#define PNG_BACKGROUND_GAMMA_SCREEN 1
#define PNG_BACKGROUND_GAMMA_FILE 2
#define PNG_BACKGROUND_GAMMA_UNIQUE 3
#endif
#ifdef PNG_READ_16_TO_8_SUPPORTED
/* Strip the second byte of information from a 16-bit depth file. */
PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr));
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
/* Turn on quantizing, and reduce the palette to the number of colors
* available. Prior to libpng-1.4.2, this was png_set_dither().
*/
PNG_EXPORT(void,png_set_quantize) PNGARG((png_structp png_ptr,
png_colorp palette, int num_palette, int maximum_colors,
png_uint_16p histogram, int full_quantize));
#endif
/* This migration aid will be removed from libpng-1.5.0 */
#define png_set_dither png_set_quantize
#ifdef PNG_READ_GAMMA_SUPPORTED
/* Handle gamma correction. Screen_gamma=(display_exponent) */
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr,
double screen_gamma, double default_file_gamma));
#endif
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
/* Set how many lines between output flushes - 0 for no flushing */
PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows));
/* Flush the current PNG output buffer */
PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr));
#endif
/* Optional update palette with requested transformations */
PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr));
/* Optional call to update the users info structure */
PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr,
png_infop info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read one or more rows of image data. */
PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr,
png_bytepp row, png_bytepp display_row, png_uint_32 num_rows));
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read a row of data. */
PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr,
png_bytep row,
png_bytep display_row));
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the whole image into memory at once. */
PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr,
png_bytepp image));
#endif
/* Write a row of image data */
PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr,
png_bytep row));
/* Write a few rows of image data */
PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr,
png_bytepp row, png_uint_32 num_rows));
/* Write the image data */
PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr,
png_bytepp image));
/* Write the end of the PNG file. */
PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr,
png_infop info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the end of the PNG file. */
PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr,
png_infop info_ptr));
#endif
/* Free any memory associated with the png_info_struct */
PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr,
png_infopp info_ptr_ptr));
/* Free any memory associated with the png_struct and the png_info_structs */
PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp
png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr));
/* Free any memory associated with the png_struct and the png_info_structs */
PNG_EXPORT(void,png_destroy_write_struct)
PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr));
/* Set the libpng method of handling chunk CRC errors */
PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr,
int crit_action, int ancil_action));
/* Values for png_set_crc_action() to say how to handle CRC errors in
* ancillary and critical chunks, and whether to use the data contained
* therein. Note that it is impossible to "discard" data in a critical
* chunk. For versions prior to 0.90, the action was always error/quit,
* whereas in version 0.90 and later, the action for CRC errors in ancillary
* chunks is warn/discard. These values should NOT be changed.
*
* value action:critical action:ancillary
*/
#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */
#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */
#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */
#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */
#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */
#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */
/* These functions give the user control over the scan-line filtering in
* libpng and the compression methods used by zlib. These functions are
* mainly useful for testing, as the defaults should work with most users.
* Those users who are tight on memory or want faster performance at the
* expense of compression can modify them. See the compression library
* header file (zlib.h) for an explination of the compression functions.
*/
/* Set the filtering method(s) used by libpng. Currently, the only valid
* value for "method" is 0.
*/
PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method,
int filters));
/* Flags for png_set_filter() to say which filters to use. The flags
* are chosen so that they don't conflict with real filter types
* below, in case they are supplied instead of the #defined constants.
* These values should NOT be changed.
*/
#define PNG_NO_FILTERS 0x00
#define PNG_FILTER_NONE 0x08
#define PNG_FILTER_SUB 0x10
#define PNG_FILTER_UP 0x20
#define PNG_FILTER_AVG 0x40
#define PNG_FILTER_PAETH 0x80
#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
PNG_FILTER_AVG | PNG_FILTER_PAETH)
/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
* These defines should NOT be changed.
*/
#define PNG_FILTER_VALUE_NONE 0
#define PNG_FILTER_VALUE_SUB 1
#define PNG_FILTER_VALUE_UP 2
#define PNG_FILTER_VALUE_AVG 3
#define PNG_FILTER_VALUE_PAETH 4
#define PNG_FILTER_VALUE_LAST 5
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr,
int heuristic_method, int num_weights, png_doublep filter_weights,
png_doublep filter_costs));
#endif
#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
/* The following are no longer used and will be removed from libpng-1.7: */
#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */
#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */
#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */
#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */
/* Set the library compression level. Currently, valid values range from
* 0 - 9, corresponding directly to the zlib compression levels 0 - 9
* (0 - no compression, 9 - "maximal" compression). Note that tests have
* shown that zlib compression levels 3-6 usually perform as well as level 9
* for PNG images, and do considerably fewer caclulations. In the future,
* these values may not correspond directly to the zlib compression levels.
*/
PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr,
int level));
PNG_EXPORT(void,png_set_compression_mem_level)
PNGARG((png_structp png_ptr, int mem_level));
PNG_EXPORT(void,png_set_compression_strategy)
PNGARG((png_structp png_ptr, int strategy));
PNG_EXPORT(void,png_set_compression_window_bits)
PNGARG((png_structp png_ptr, int window_bits));
PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr,
int method));
/* These next functions are called for input/output, memory, and error
* handling. They are in the file pngrio.c, pngwio.c, and pngerror.c,
* and call standard C I/O routines such as fread(), fwrite(), and
* fprintf(). These functions can be made to use other I/O routines
* at run time for those applications that need to handle I/O in a
* different manner by calling png_set_???_fn(). See libpng.txt for
* more information.
*/
#ifdef PNG_STDIO_SUPPORTED
/* Initialize the input/output for the PNG file to the default functions. */
PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr,
png_FILE_p fp));
#endif
/* Replace the (error and abort), and warning functions with user
* supplied functions. If no messages are to be printed you must still
* write and use replacement functions. The replacement error_fn should
* still do a longjmp to the last setjmp location if you are using this
* method of error handling. If error_fn or warning_fn is NULL, the
* default function will be used.
*/
PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr,
png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
/* Return the user pointer associated with the error functions */
PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_const_structp png_ptr));
/* Replace the default data output functions with a user supplied one(s).
* If buffered output is not used, then output_flush_fn can be set to NULL.
* If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
* output_flush_fn will be ignored (and thus can be NULL).
* It is probably a mistake to use NULL for output_flush_fn if
* write_data_fn is not also NULL unless you have built libpng with
* PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's
* default flush function, which uses the standard *FILE structure, will
* be used.
*/
PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr,
png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
/* Replace the default data input function with a user supplied one. */
PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr,
png_voidp io_ptr, png_rw_ptr read_data_fn));
/* Return the user pointer associated with the I/O functions */
PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr));
PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr,
png_read_status_ptr read_row_fn));
PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr,
png_write_status_ptr write_row_fn));
#ifdef PNG_USER_MEM_SUPPORTED
/* Replace the default memory allocation functions with user supplied one(s). */
PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr,
png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn));
/* Return the user pointer associated with the memory functions */
PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_const_structp png_ptr));
#endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp
png_ptr, png_user_transform_ptr read_user_transform_fn));
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp
png_ptr, png_user_transform_ptr write_user_transform_fn));
#endif
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp
png_ptr, png_voidp user_transform_ptr, int user_transform_depth,
int user_transform_channels));
/* Return the user pointer associated with the user transform functions */
PNG_EXPORT(png_voidp,png_get_user_transform_ptr)
PNGARG((png_const_structp png_ptr));
#endif
#ifdef PNG_USER_CHUNKS_SUPPORTED
PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr,
png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_const_structp
png_ptr));
#endif
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
/* Sets the function callbacks for the push reader, and a pointer to a
* user-defined structure available to the callback functions.
*/
PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr,
png_voidp progressive_ptr,
png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
png_progressive_end_ptr end_fn));
/* Returns the user pointer associated with the push read functions */
PNG_EXPORT(png_voidp,png_get_progressive_ptr)
PNGARG((png_const_structp png_ptr));
/* Function to be called when data becomes available */
PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_bytep buffer, png_size_t buffer_size));
/* Function that combines rows. Not very much different than the
* png_combine_row() call. Is this even used?????
*/
PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr,
png_bytep old_row, png_bytep new_row));
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr,
png_alloc_size_t size)) PNG_ALLOCATED;
/* Added at libpng version 1.4.0 */
PNG_EXPORT(png_voidp,png_calloc) PNGARG((png_structp png_ptr,
png_alloc_size_t size)) PNG_ALLOCATED;
/* Added at libpng version 1.2.4 */
PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr,
png_alloc_size_t size)) PNG_ALLOCATED;
/* Frees a pointer allocated by png_malloc() */
PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr));
/* Free data that was allocated internally */
PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 free_me, int num));
/* Reassign responsibility for freeing existing data, whether allocated
* by libpng or by the application */
PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr,
png_infop info_ptr, int freer, png_uint_32 mask));
/* Assignments for png_data_freer */
#define PNG_DESTROY_WILL_FREE_DATA 1
#define PNG_SET_WILL_FREE_DATA 1
#define PNG_USER_WILL_FREE_DATA 2
/* Flags for png_ptr->free_me and info_ptr->free_me */
#define PNG_FREE_HIST 0x0008
#define PNG_FREE_ICCP 0x0010
#define PNG_FREE_SPLT 0x0020
#define PNG_FREE_ROWS 0x0040
#define PNG_FREE_PCAL 0x0080
#define PNG_FREE_SCAL 0x0100
#define PNG_FREE_UNKN 0x0200
#define PNG_FREE_LIST 0x0400
#define PNG_FREE_PLTE 0x1000
#define PNG_FREE_TRNS 0x2000
#define PNG_FREE_TEXT 0x4000
#define PNG_FREE_ALL 0x7fff
#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
#ifdef PNG_USER_MEM_SUPPORTED
PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr,
png_alloc_size_t size)) PNG_ALLOCATED;
PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr,
png_voidp ptr));
#endif
#ifndef PNG_NO_ERROR_TEXT
/* Fatal error in PNG image of libpng - can't continue */
PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr,
png_const_charp error_message)) PNG_NORETURN;
/* The same, but the chunk name is prepended to the error string. */
PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr,
png_const_charp error_message)) PNG_NORETURN;
#else
/* Fatal error in PNG image of libpng - can't continue */
PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN;
#endif
/* Non-fatal error in libpng. Can continue, but may have a problem. */
PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr,
png_const_charp warning_message));
/* Non-fatal error in libpng, chunk name is prepended to message. */
PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr,
png_const_charp warning_message));
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
/* Benign error in libpng. Can continue, but may have a problem.
* User can choose whether to handle as a fatal error or as a warning. */
PNG_EXPORT(void,png_benign_error) PNGARG((png_structp png_ptr,
png_const_charp warning_message));
/* Same, chunk name is prepended to message. */
PNG_EXPORT(void,png_chunk_benign_error) PNGARG((png_structp png_ptr,
png_const_charp warning_message));
PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp
png_ptr, int allowed));
#endif
/* The png_set_ functions are for storing values in the png_info_struct.
* Similarly, the png_get_ calls are used to read values from the
* png_info_struct, either storing the parameters in the passed variables, or
* setting pointers into the png_info_struct where the data is stored. The
* png_get_ functions return a non-zero value if the data was available
* in info_ptr, or return zero and do not change any of the parameters if the
* data was not available.
*
* These functions should be used instead of directly accessing png_info
* to avoid problems with future changes in the size and internal layout of
* png_info_struct.
*/
/* Returns "flag" if chunk data is valid in info_ptr. */
PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_uint_32 flag));
/* Returns number of bytes needed to hold a transformed row. */
PNG_EXPORT(png_size_t,png_get_rowbytes) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr));
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* Returns row_pointers, which is an array of pointers to scanlines that was
* returned from png_read_png().
*/
PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr));
/* Set row_pointers, which is an array of pointers to scanlines for use
* by png_write_png().
*/
PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_bytepp row_pointers));
#endif
/* Returns number of color channels in image. */
PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr));
#ifdef PNG_EASY_ACCESS_SUPPORTED
/* Returns image width in pixels. */
PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns image height in pixels. */
PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns image bit_depth. */
PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns image color_type. */
PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns image filter_type. */
PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns image interlace_type. */
PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns image compression_type. */
PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns image resolution in pixels per meter, from pHYs chunk data. */
PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
/* Returns pixel aspect ratio, computed from pHYs chunk data. */
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
#endif
/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr));
#endif /* PNG_EASY_ACCESS_SUPPORTED */
/* Returns pointer to signature string read from PNG header */
PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_const_structp png_ptr,
png_infop info_ptr));
#ifdef PNG_bKGD_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_const_structp png_ptr,
png_infop info_ptr, png_color_16p *background));
#endif
#ifdef PNG_bKGD_SUPPORTED
PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_color_16p background));
#endif
#ifdef PNG_cHRM_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, double *white_x, double *white_y, double *red_x,
double *red_y, double *green_x, double *green_y, double *blue_x,
double *blue_y));
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point
*int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y,
png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point
*int_blue_x, png_fixed_point *int_blue_y));
#endif
#endif
#ifdef PNG_cHRM_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr,
png_infop info_ptr, double white_x, double white_y, double red_x,
double red_y, double green_x, double green_y, double blue_x, double blue_y));
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y,
png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
png_fixed_point int_blue_y));
#endif
#endif
#ifdef PNG_gAMA_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, double *file_gamma));
#endif
PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_fixed_point *int_file_gamma));
#endif
#ifdef PNG_gAMA_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr,
png_infop info_ptr, double file_gamma));
#endif
PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_fixed_point int_file_gamma));
#endif
#ifdef PNG_hIST_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_uint_16p *hist));
#endif
#ifdef PNG_hIST_SUPPORTED
PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_16p hist));
#endif
PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 *width, png_uint_32 *height,
int *bit_depth, int *color_type, int *interlace_method,
int *compression_method, int *filter_method));
PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_method, int compression_method,
int filter_method));
#ifdef PNG_oFFs_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
int *unit_type));
#endif
#ifdef PNG_oFFs_SUPPORTED
PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y,
int unit_type));
#endif
#ifdef PNG_pCAL_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1,
int *type, int *nparams, png_charp *units, png_charpp *params));
#endif
#ifdef PNG_pCAL_SUPPORTED
PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1,
int type, int nparams, png_charp units, png_charpp params));
#endif
#ifdef PNG_pHYs_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
#endif
#ifdef PNG_pHYs_SUPPORTED
PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
#endif
PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_colorp *palette, int *num_palette));
PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_colorp palette, int num_palette));
#ifdef PNG_sBIT_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_const_structp png_ptr,
png_infop info_ptr, png_color_8p *sig_bit));
#endif
#ifdef PNG_sBIT_SUPPORTED
PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_color_8p sig_bit));
#endif
#ifdef PNG_sRGB_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, int *intent));
#endif
#ifdef PNG_sRGB_SUPPORTED
PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr,
png_infop info_ptr, int intent));
PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr,
png_infop info_ptr, int intent));
#endif
#ifdef PNG_iCCP_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_charpp name, int *compression_type,
png_charpp profile, png_uint_32 *proflen));
/* Note to maintainer: profile should be png_bytepp */
#endif
#ifdef PNG_iCCP_SUPPORTED
PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_charp name, int compression_type,
png_charp profile, png_uint_32 proflen));
/* Note to maintainer: profile should be png_bytep */
#endif
#ifdef PNG_sPLT_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_sPLT_tpp entries));
#endif
#ifdef PNG_sPLT_SUPPORTED
PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_sPLT_tp entries, int nentries));
#endif
#ifdef PNG_TEXT_SUPPORTED
/* png_get_text also returns the number of text chunks in *num_text */
PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_textp *text_ptr, int *num_text));
#endif
/* Note while png_set_text() will accept a structure whose text,
* language, and translated keywords are NULL pointers, the structure
* returned by png_get_text will always contain regular
* zero-terminated C strings. They might be empty strings but
* they will never be NULL pointers.
*/
#ifdef PNG_TEXT_SUPPORTED
PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_textp text_ptr, int num_text));
#endif
#ifdef PNG_tIME_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_const_structp png_ptr,
png_infop info_ptr, png_timep *mod_time));
#endif
#ifdef PNG_tIME_SUPPORTED
PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_timep mod_time));
#endif
#ifdef PNG_tRNS_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_const_structp png_ptr,
png_infop info_ptr, png_bytep *trans_alpha, int *num_trans,
png_color_16p *trans_color));
#endif
#ifdef PNG_tRNS_SUPPORTED
PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_bytep trans_alpha, int num_trans,
png_color_16p trans_color));
#endif
#ifdef PNG_tRNS_SUPPORTED
#endif
#ifdef PNG_sCAL_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, int *unit, double *width, double *height));
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight));
#endif
#endif
#endif /* PNG_sCAL_SUPPORTED */
#ifdef PNG_sCAL_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr,
png_infop info_ptr, int unit, double width, double height));
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr,
png_infop info_ptr, int unit, png_charp swidth, png_charp sheight));
#endif
#endif
#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
/* Provide a list of chunks and how they are to be handled, if the built-in
handling or default unknown chunk handling is not desired. Any chunks not
listed will be handled in the default manner. The IHDR and IEND chunks
must not be listed.
keep = 0: follow default behaviour
= 1: do not keep
= 2: keep only if safe-to-copy
= 3: keep even if unsafe-to-copy
*/
PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp
png_ptr, int keep, png_bytep chunk_list, int num_chunks));
PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep
chunk_name));
#endif
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr,
png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns));
PNG_EXPORT(void, png_set_unknown_chunk_location)
PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location));
PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_const_structp
png_ptr, png_const_infop info_ptr, png_unknown_chunkpp entries));
#endif
/* Png_free_data() will turn off the "valid" flag for anything it frees.
* If you need to turn it off for a chunk that your application has freed,
* you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
*/
PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr,
png_infop info_ptr, int mask));
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* The "params" pointer is currently not used and is for future expansion. */
PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr,
png_infop info_ptr,
int transforms,
png_voidp params));
PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr,
png_infop info_ptr,
int transforms,
png_voidp params));
#endif
PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_const_structp png_ptr));
PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_const_structp png_ptr));
PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_const_structp
png_ptr));
PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_const_structp png_ptr));
#ifdef PNG_MNG_FEATURES_SUPPORTED
PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp
png_ptr, png_uint_32 mng_features_permitted));
#endif
/* For use in png_set_keep_unknown, added to version 1.2.6 */
#define PNG_HANDLE_CHUNK_AS_DEFAULT 0
#define PNG_HANDLE_CHUNK_NEVER 1
#define PNG_HANDLE_CHUNK_IF_SAFE 2
#define PNG_HANDLE_CHUNK_ALWAYS 3
/* Strip the prepended error numbers ("#nnn ") from error and warning
* messages before passing them to the error or warning handler.
*/
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp
png_ptr, png_uint_32 strip_mode));
#endif
/* Added in libpng-1.2.6 */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp
png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max));
PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_const_structp
png_ptr));
PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_const_structp
png_ptr));
/* Added in libpng-1.4.0 */
PNG_EXPORT(void,png_set_chunk_cache_max) PNGARG((png_structp
png_ptr, png_uint_32 user_chunk_cache_max));
PNG_EXPORT(png_uint_32,png_get_chunk_cache_max)
PNGARG((png_const_structp png_ptr));
/* Added in libpng-1.4.1 */
PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp
png_ptr, png_alloc_size_t user_chunk_cache_max));
PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max)
PNGARG((png_const_structp png_ptr));
#endif
#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
PNG_EXPORT(png_uint_32,png_get_pixels_per_inch)
PNGARG((png_const_structp png_ptr, png_const_infop info_ptr));
PNG_EXPORT(png_uint_32,png_get_x_pixels_per_inch)
PNGARG((png_const_structp png_ptr, png_const_infop info_ptr));
PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch)
PNGARG((png_const_structp png_ptr, png_const_infop info_ptr));
PNG_EXPORT(float,png_get_x_offset_inches) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr));
PNG_EXPORT(float,png_get_y_offset_inches) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr));
#ifdef PNG_pHYs_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_pHYs_dpi) PNGARG((png_const_structp png_ptr,
png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
int *unit_type));
#endif /* PNG_pHYs_SUPPORTED */
#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
/* Added in libpng-1.4.0 */
#ifdef PNG_IO_STATE_SUPPORTED
PNG_EXPORT(png_uint_32,png_get_io_state) PNGARG((png_const_structp png_ptr));
PNG_EXPORT(png_bytep,png_get_io_chunk_name)
PNGARG((png_structp png_ptr));
/* The flags returned by png_get_io_state() are the following: */
#define PNG_IO_NONE 0x0000 /* no I/O at this moment */
#define PNG_IO_READING 0x0001 /* currently reading */
#define PNG_IO_WRITING 0x0002 /* currently writing */
#define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */
#define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */
#define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */
#define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */
#define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */
#define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */
#endif /* ?PNG_IO_STATE_SUPPORTED */
/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
* defs
*/
#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
/* With these routines we avoid an integer divide, which will be slower on
* most machines. However, it does take more operations than the corresponding
* divide method, so it may be slower on a few RISC systems. There are two
* shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
*
* Note that the rounding factors are NOT supposed to be the same! 128 and
* 32768 are correct for the NODIV code; 127 and 32767 are correct for the
* standard method.
*
* [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
*/
/* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
# define png_composite(composite, fg, alpha, bg) \
{ png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \
* (png_uint_16)(alpha) \
+ (png_uint_16)(bg)*(png_uint_16)(255 \
- (png_uint_16)(alpha)) + (png_uint_16)128); \
(composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
# define png_composite_16(composite, fg, alpha, bg) \
{ png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \
* (png_uint_32)(alpha) \
+ (png_uint_32)(bg)*(png_uint_32)(65535L \
- (png_uint_32)(alpha)) + (png_uint_32)32768L); \
(composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
#else /* Standard method using integer division */
# define png_composite(composite, fg, alpha, bg) \
(composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \
(png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
(png_uint_16)127) / 255)
# define png_composite_16(composite, fg, alpha, bg) \
(composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
(png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \
(png_uint_32)32767) / (png_uint_32)65535L)
#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */
#ifdef PNG_USE_READ_MACROS
/* Inline macros to do direct reads of bytes from the input buffer.
* The png_get_int_32() routine assumes we are using two's complement
* format for negative values, which is almost certainly true.
*/
# define png_get_uint_32(buf) \
(((png_uint_32)((*(buf)) & 0xff) << 24) + \
((png_uint_32)((*((buf) + 1)) & 0xff) << 16) + \
((png_uint_32)((*((buf) + 2)) & 0xff) << 8) + \
((png_uint_32)((*((buf) + 3)) & 0xff)))
/* The following definition introduces an API incompatibility (but not
* an ABI incompatibility) with libpng-1.4.0 through 1.4.4. Prior to
* libpng-1.4.5 the macro, which is used by default, returned (incorrectly)
* a (png_uint_32), while the function, if used instead, correctly returned
* a (png_uint_16).
*
* Libpng versions 1.0.x and 1.2.x only used a function so are not affected
* by this potential API incompatibility between macros.
*/
# define png_get_uint_16(buf) \
((png_uint_16) \
(((unsigned int)(*(buf)) << 8) + \
((unsigned int)(*((buf) + 1)))))
# define png_get_int_32(buf) \
((png_int_32)((*(buf) & 0x80) \
? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
: (png_int_32)png_get_uint_32(buf)))
#else
PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf));
PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf));
#ifdef PNG_GET_INT_32_SUPPORTED
PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf));
#endif
#endif
PNG_EXPORT(png_uint_32,png_get_uint_31)
PNGARG((png_structp png_ptr, png_bytep buf));
/* No png_get_int_16 -- may be added if there's a real need for it. */
/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */
PNG_EXPORT(void,png_save_uint_32)
PNGARG((png_bytep buf, png_uint_32 i));
PNG_EXPORT(void,png_save_int_32)
PNGARG((png_bytep buf, png_int_32 i));
/* Place a 16-bit number into a buffer in PNG byte order.
* The parameter is declared unsigned int, not png_uint_16,
* just to avoid potential problems on pre-ANSI C compilers.
*/
PNG_EXPORT(void,png_save_uint_16)
PNGARG((png_bytep buf, unsigned int i));
/* No png_save_int_16 -- may be added if there's a real need for it. */
/* ************************************************************************* */
/* Various modes of operation. Note that after an init, mode is set to
* zero automatically when the structure is created.
*/
#define PNG_HAVE_IHDR 0x01
#define PNG_HAVE_PLTE 0x02
#define PNG_HAVE_IDAT 0x04
#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */
#define PNG_HAVE_IEND 0x10
#define PNG_HAVE_gAMA 0x20
#define PNG_HAVE_cHRM 0x40
#ifdef __cplusplus
}
#endif
#endif /* PNG_VERSION_INFO_ONLY */
/* Do not put anything past this line */
#endif /* PNG_H */
================================================
FILE: src/main/jni/png/pngconf.h
================================================
/* pngconf.h - machine configurable file for libpng
*
* libpng version 1.4.19, December 17, 2015
*
* Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
* Any machine specific code is near the front of this file, so if you
* are configuring libpng for a machine, you may want to read the section
* starting here down to where it starts to typedef png_color, png_text,
* and png_info.
*/
#ifndef PNGCONF_H
#define PNGCONF_H
#ifndef PNG_NO_LIMITS_H
# include
#endif
/* Added at libpng-1.2.9 */
/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure"
* script.
*/
#ifdef PNG_CONFIGURE_LIBPNG
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
#endif
/*
* Added at libpng-1.2.8
*
* PNG_USER_CONFIG has to be defined on the compiler command line. This
* includes the resource compiler for Windows DLL configurations.
*/
#ifdef PNG_USER_CONFIG
# include "pngusr.h"
# ifndef PNG_USER_PRIVATEBUILD
# define PNG_USER_PRIVATEBUILD
# endif
#endif
/*
* If you create a private DLL you should define in "pngusr.h" the following:
* #define PNG_USER_PRIVATEBUILD
* e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons."
* #define PNG_USER_DLLFNAME_POSTFIX
* e.g. // private DLL "libpng14gx.dll"
* #define PNG_USER_DLLFNAME_POSTFIX "gx"
*
* The following macros are also at your disposal if you want to complete the
* DLL VERSIONINFO structure.
* - PNG_USER_VERSIONINFO_COMMENTS
* - PNG_USER_VERSIONINFO_COMPANYNAME
* - PNG_USER_VERSIONINFO_LEGALTRADEMARKS
*/
#ifdef __STDC__
# ifdef SPECIALBUILD
# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\
are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.")
# endif
# ifdef PRIVATEBUILD
# pragma message("PRIVATEBUILD is deprecated.\
Use PNG_USER_PRIVATEBUILD instead.")
# define PNG_USER_PRIVATEBUILD PRIVATEBUILD
# endif
#endif /* __STDC__ */
/* End of material added to libpng-1.2.8 */
/* Added at libpng-1.4.6 */
#ifndef PNG_UNUSED
/* Unused formal parameter warnings are silenced using the following macro
* which is expected to have no bad effects on performance (optimizing
* compilers will probably remove it entirely). Note that if you replace
* it with something other than whitespace, you must include the terminating
* semicolon.
*/
# define PNG_UNUSED(param) (void)param;
#endif
/* End of material added to libpng-1.4.6 */
#ifndef PNG_VERSION_INFO_ONLY
/* This is the size of the compression buffer, and thus the size of
* an IDAT chunk. Make this whatever size you feel is best for your
* machine. One of these will be allocated per png_struct. When this
* is full, it writes the data to the disk, and does some other
* calculations. Making this an extremely small size will slow
* the library down, but you may want to experiment to determine
* where it becomes significant, if you are concerned with memory
* usage. Note that zlib allocates at least 32Kb also. For readers,
* this describes the size of the buffer available to read the data in.
* Unless this gets smaller than the size of a row (compressed),
* it should not make much difference how big this is.
*/
#ifndef PNG_ZBUF_SIZE
# define PNG_ZBUF_SIZE 8192
#endif
/* Enable if you want a write-only libpng */
#ifndef PNG_NO_READ_SUPPORTED
# define PNG_READ_SUPPORTED
#endif
/* Enable if you want a read-only libpng */
#ifndef PNG_NO_WRITE_SUPPORTED
# define PNG_WRITE_SUPPORTED
#endif
/* Enabled in 1.4.0. */
#ifdef PNG_ALLOW_BENIGN_ERRORS
# define png_benign_error png_warning
# define png_chunk_benign_error png_chunk_warning
#else
# ifndef PNG_BENIGN_ERRORS_SUPPORTED
# define png_benign_error png_error
# define png_chunk_benign_error png_chunk_error
# endif
#endif
/* Added at libpng version 1.4.0 */
#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED)
# define PNG_WARNINGS_SUPPORTED
#endif
/* Added at libpng version 1.4.0 */
#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED)
# define PNG_ERROR_TEXT_SUPPORTED
#endif
/* Added at libpng version 1.4.0 */
#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED)
# define PNG_CHECK_cHRM_SUPPORTED
#endif
/* Added at libpng version 1.4.0 */
#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED)
# define PNG_ALIGNED_MEMORY_SUPPORTED
#endif
/* Enabled by default in 1.2.0. You can disable this if you don't need to
support PNGs that are embedded in MNG datastreams */
#ifndef PNG_NO_MNG_FEATURES
# ifndef PNG_MNG_FEATURES_SUPPORTED
# define PNG_MNG_FEATURES_SUPPORTED
# endif
#endif
/* Added at libpng version 1.4.0 */
#ifndef PNG_NO_FLOATING_POINT_SUPPORTED
# ifndef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FLOATING_POINT_SUPPORTED
# endif
#endif
/* Added at libpng-1.4.0beta49 for testing (this test is no longer used
in libpng and png_calloc() is always present)
*/
#define PNG_CALLOC_SUPPORTED
/* If you are running on a machine where you cannot allocate more
* than 64K of memory at once, uncomment this. While libpng will not
* normally need that much memory in a chunk (unless you load up a very
* large file), zlib needs to know how big of a chunk it can use, and
* libpng thus makes sure to check any memory allocation to verify it
* will fit into memory.
#define PNG_MAX_MALLOC_64K
*/
#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
# define PNG_MAX_MALLOC_64K
#endif
/* Special munging to support doing things the 'cygwin' way:
* 'Normal' png-on-win32 defines/defaults:
* PNG_BUILD_DLL -- building dll
* PNG_USE_DLL -- building an application, linking to dll
* (no define) -- building static library, or building an
* application and linking to the static lib
* 'Cygwin' defines/defaults:
* PNG_BUILD_DLL -- (ignored) building the dll
* (no define) -- (ignored) building an application, linking to the dll
* PNG_STATIC -- (ignored) building the static lib, or building an
* application that links to the static lib.
* ALL_STATIC -- (ignored) building various static libs, or building an
* application that links to the static libs.
* Thus,
* a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and
* this bit of #ifdefs will define the 'correct' config variables based on
* that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but
* unnecessary.
*
* Also, the precedence order is:
* ALL_STATIC (since we can't #undef something outside our namespace)
* PNG_BUILD_DLL
* PNG_STATIC
* (nothing) == PNG_USE_DLL
*
* CYGWIN (2002-01-20): The preceding is now obsolete. With the advent
* of auto-import in binutils, we no longer need to worry about
* __declspec(dllexport) / __declspec(dllimport) and friends. Therefore,
* we don't need to worry about PNG_STATIC or ALL_STATIC when it comes
* to __declspec() stuff. However, we DO need to worry about
* PNG_BUILD_DLL and PNG_STATIC because those change some defaults
* such as CONSOLE_IO.
*/
#ifdef __CYGWIN__
# ifdef ALL_STATIC
# ifdef PNG_BUILD_DLL
# undef PNG_BUILD_DLL
# endif
# ifdef PNG_USE_DLL
# undef PNG_USE_DLL
# endif
# ifdef PNG_DLL
# undef PNG_DLL
# endif
# ifndef PNG_STATIC
# define PNG_STATIC
# endif
# else
# ifdef PNG_BUILD_DLL
# ifdef PNG_STATIC
# undef PNG_STATIC
# endif
# ifdef PNG_USE_DLL
# undef PNG_USE_DLL
# endif
# ifndef PNG_DLL
# define PNG_DLL
# endif
# else
# ifdef PNG_STATIC
# ifdef PNG_USE_DLL
# undef PNG_USE_DLL
# endif
# ifdef PNG_DLL
# undef PNG_DLL
# endif
# else
# ifndef PNG_USE_DLL
# define PNG_USE_DLL
# endif
# ifndef PNG_DLL
# define PNG_DLL
# endif
# endif
# endif
# endif
#endif
/* This protects us against compilers that run on a windowing system
* and thus don't have or would rather us not use the stdio types:
* stdin, stdout, and stderr. The only one currently used is stderr
* in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will
* prevent these from being compiled and used. #defining PNG_NO_STDIO
* will also prevent these, plus will prevent the entire set of stdio
* macros and functions (FILE *, printf, etc.) from being compiled and used,
* unless (PNG_DEBUG > 0) has been #defined.
*
* #define PNG_NO_CONSOLE_IO
* #define PNG_NO_STDIO
*/
#ifdef _WIN32_WCE
# define PNG_NO_CONSOLE_IO
# define PNG_NO_STDIO
# define PNG_NO_TIME_RFC1123
# ifdef PNG_DEBUG
# undef PNG_DEBUG
# endif
#endif
#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED)
# define PNG_STDIO_SUPPORTED
#endif
#ifdef PNG_BUILD_DLL
# if !defined(PNG_CONSOLE_IO_SUPPORTED) && !defined(PNG_NO_CONSOLE_IO)
# define PNG_NO_CONSOLE_IO
# endif
#endif
# ifdef PNG_NO_STDIO
# ifndef PNG_NO_CONSOLE_IO
# define PNG_NO_CONSOLE_IO
# endif
# ifdef PNG_DEBUG
# if (PNG_DEBUG > 0)
# include
# endif
# endif
# else
# include
# endif
#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED)
# define PNG_CONSOLE_IO_SUPPORTED
#endif
/* This macro protects us against machines that don't have function
* prototypes (ie K&R style headers). If your compiler does not handle
* function prototypes, define this macro and use the included ansi2knr.
* I've always been able to use _NO_PROTO as the indicator, but you may
* need to drag the empty declaration out in front of here, or change the
* ifdef to suit your own needs.
*/
#ifndef PNGARG
#ifdef OF /* zlib prototype munger */
# define PNGARG(arglist) OF(arglist)
#else
#ifdef _NO_PROTO
# define PNGARG(arglist) ()
#else
# define PNGARG(arglist) arglist
#endif /* _NO_PROTO */
#endif /* OF */
#endif /* PNGARG */
/* Try to determine if we are compiling on a Mac. Note that testing for
* just __MWERKS__ is not good enough, because the Codewarrior is now used
* on non-Mac platforms.
*/
#ifndef MACOS
# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
# define MACOS
# endif
#endif
/* Enough people need this for various reasons to include it here */
#if !defined(MACOS) && !defined(RISCOS)
# include
#endif
/* PNG_SETJMP_NOT_SUPPORTED and PNG_NO_SETJMP_SUPPORTED are deprecated. */
#if !defined(PNG_NO_SETJMP) && \
!defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED)
# define PNG_SETJMP_SUPPORTED
#endif
#ifdef PNG_SETJMP_SUPPORTED
/* This is an attempt to force a single setjmp behaviour on Linux. If
* the X config stuff didn't define _BSD_SOURCE we wouldn't need this.
*
* You can bypass this test if you know that your application uses exactly
* the same setjmp.h that was included when libpng was built. Only define
* PNG_SKIP_SETJMP_CHECK while building your application, prior to the
* application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK
* while building a separate libpng library for general use.
*/
# ifndef PNG_SKIP_SETJMP_CHECK
# ifdef __linux__
# ifdef _BSD_SOURCE
# define PNG_SAVE_BSD_SOURCE
# undef _BSD_SOURCE
# endif
# ifdef _SETJMP_H
/* If you encounter a compiler error here, see the explanation
* near the end of INSTALL.
*/
__pngconf.h__ in libpng already includes setjmp.h;
__dont__ include it again.;
# endif
# endif /* __linux__ */
# endif /* PNG_SKIP_SETJMP_CHECK */
/* Include setjmp.h for error handling */
# include
# ifdef __linux__
# ifdef PNG_SAVE_BSD_SOURCE
# ifdef _BSD_SOURCE
# undef _BSD_SOURCE
# endif
# define _BSD_SOURCE
# undef PNG_SAVE_BSD_SOURCE
# endif
# endif /* __linux__ */
#endif /* PNG_SETJMP_SUPPORTED */
#ifdef BSD
# include
#else
# include
#endif
/* Other defines for things like memory and the like can go here. */
/* This controls how fine the quantizing gets. As this allocates
* a largish chunk of memory (32K), those who are not as concerned
* with quantizing quality can decrease some or all of these.
*/
/* Prior to libpng-1.4.2, these were PNG_DITHER_*_BITS
* These migration aids will be removed from libpng-1.5.0.
*/
#ifdef PNG_DITHER_RED_BITS
# define PNG_QUANTIZE_RED_BITS PNG_DITHER_RED_BITS
#endif
#ifdef PNG_DITHER_GREEN_BITS
# define PNG_QUANTIZE_GREEN_BITS PNG_DITHER_GREEN_BITS
#endif
#ifdef PNG_DITHER_BLUE_BITS
# define PNG_QUANTIZE_BLUE_BITS PNG_DITHER_BLUE_BITS
#endif
#ifndef PNG_QUANTIZE_RED_BITS
# define PNG_QUANTIZE_RED_BITS 5
#endif
#ifndef PNG_QUANTIZE_GREEN_BITS
# define PNG_QUANTIZE_GREEN_BITS 5
#endif
#ifndef PNG_QUANTIZE_BLUE_BITS
# define PNG_QUANTIZE_BLUE_BITS 5
#endif
/* This controls how fine the gamma correction becomes when you
* are only interested in 8 bits anyway. Increasing this value
* results in more memory being used, and more pow() functions
* being called to fill in the gamma tables. Don't set this value
* less then 8, and even that may not work (I haven't tested it).
*/
#ifndef PNG_MAX_GAMMA_8
# define PNG_MAX_GAMMA_8 11
#endif
/* This controls how much a difference in gamma we can tolerate before
* we actually start doing gamma conversion.
*/
#ifndef PNG_GAMMA_THRESHOLD
# define PNG_GAMMA_THRESHOLD 0.05
#endif
/* The following uses const char * instead of char * for error
* and warning message functions, so some compilers won't complain.
* If you do not want to use const, define PNG_NO_CONST.
*/
#ifndef PNG_CONST
# ifndef PNG_NO_CONST
# define PNG_CONST const
# else
# define PNG_CONST
# endif
#endif
/* The following defines give you the ability to remove code from the
* library that you will not be using. I wish I could figure out how to
* automate this, but I can't do that without making it seriously hard
* on the users. So if you are not using an ability, change the #define
* to an #undef, or pass in PNG_NO_feature and that part of the library
* will not be compiled.
* If your linker can't find a function, you may want to make sure the
* ability is defined here. Some of these depend upon some others being
* defined. I haven't figured out all the interactions here, so you may
* have to experiment awhile to get everything to compile. If you are
* creating or using a shared library, you probably shouldn't touch this,
* as it will affect the size of the structures, and this will cause bad
* things to happen if the library and/or application ever change.
*/
/* Any features you will not be using can be undef'ed here */
/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user
* to turn it off with PNG_NO_READ|WRITE_TRANSFORMS on the compile line,
* then pick and choose which ones to define without having to edit this
* file. It is safe to use the PNG_NO_READ|WRITE_TRANSFORMS
* if you only want to have a png-compliant reader/writer but don't need
* any of the extra transformations. This saves about 80 kbytes in a
* typical installation of the library. (PNG_NO_* form added in version
* 1.0.1c, for consistency; PNG_*_TRANSFORMS_NOT_SUPPORTED deprecated in
* 1.4.0)
*/
/* Ignore attempt to turn off both floating and fixed point support */
#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \
!defined(PNG_NO_FIXED_POINT_SUPPORTED)
# define PNG_FIXED_POINT_SUPPORTED
#endif
#ifdef PNG_READ_SUPPORTED
/* PNG_READ_TRANSFORMS_NOT_SUPPORTED is deprecated. */
#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \
!defined(PNG_NO_READ_TRANSFORMS)
# define PNG_READ_TRANSFORMS_SUPPORTED
#endif
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
# ifndef PNG_NO_READ_EXPAND
# define PNG_READ_EXPAND_SUPPORTED
# endif
# ifndef PNG_NO_READ_SHIFT
# define PNG_READ_SHIFT_SUPPORTED
# endif
# ifndef PNG_NO_READ_PACK
# define PNG_READ_PACK_SUPPORTED
# endif
# ifndef PNG_NO_READ_BGR
# define PNG_READ_BGR_SUPPORTED
# endif
# ifndef PNG_NO_READ_SWAP
# define PNG_READ_SWAP_SUPPORTED
# endif
# ifndef PNG_NO_READ_PACKSWAP
# define PNG_READ_PACKSWAP_SUPPORTED
# endif
# ifndef PNG_NO_READ_INVERT
# define PNG_READ_INVERT_SUPPORTED
# endif
# ifndef PNG_NO_READ_QUANTIZE
/* Prior to libpng-1.4.0 this was PNG_READ_DITHER_SUPPORTED */
# ifndef PNG_NO_READ_DITHER /* This migration aid will be removed */
# define PNG_READ_QUANTIZE_SUPPORTED
# endif
# endif
# ifndef PNG_NO_READ_BACKGROUND
# define PNG_READ_BACKGROUND_SUPPORTED
# endif
# ifndef PNG_NO_READ_16_TO_8
# define PNG_READ_16_TO_8_SUPPORTED
# endif
# ifndef PNG_NO_READ_FILLER
# define PNG_READ_FILLER_SUPPORTED
# endif
# ifndef PNG_NO_READ_GAMMA
# define PNG_READ_GAMMA_SUPPORTED
# endif
# ifndef PNG_NO_READ_GRAY_TO_RGB
# define PNG_READ_GRAY_TO_RGB_SUPPORTED
# endif
# ifndef PNG_NO_READ_SWAP_ALPHA
# define PNG_READ_SWAP_ALPHA_SUPPORTED
# endif
# ifndef PNG_NO_READ_INVERT_ALPHA
# define PNG_READ_INVERT_ALPHA_SUPPORTED
# endif
# ifndef PNG_NO_READ_STRIP_ALPHA
# define PNG_READ_STRIP_ALPHA_SUPPORTED
# endif
# ifndef PNG_NO_READ_USER_TRANSFORM
# define PNG_READ_USER_TRANSFORM_SUPPORTED
# endif
# ifndef PNG_NO_READ_RGB_TO_GRAY
# define PNG_READ_RGB_TO_GRAY_SUPPORTED
# endif
#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */
#if !defined(PNG_NO_PROGRESSIVE_READ) && \
!defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */
# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */
#endif /* about interlacing capability! You'll */
/* still have interlacing unless you change the following define: */
#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */
/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */
#if !defined(PNG_NO_SEQUENTIAL_READ) && \
!defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \
!defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED)
# define PNG_SEQUENTIAL_READ_SUPPORTED
#endif
#ifndef PNG_NO_READ_COMPOSITE_NODIV
# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */
# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */
# endif
#endif
#if !defined(PNG_NO_GET_INT_32) || defined(PNG_READ_oFFS_SUPPORTED) || \
defined(PNG_READ_pCAL_SUPPORTED)
# ifndef PNG_GET_INT_32_SUPPORTED
# define PNG_GET_INT_32_SUPPORTED
# endif
#endif
#endif /* PNG_READ_SUPPORTED */
#ifdef PNG_WRITE_SUPPORTED
/* PNG_WRITE_TRANSFORMS_NOT_SUPPORTED is deprecated. */
#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \
!defined(PNG_NO_WRITE_TRANSFORMS)
# define PNG_WRITE_TRANSFORMS_SUPPORTED
#endif
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
# ifndef PNG_NO_WRITE_SHIFT
# define PNG_WRITE_SHIFT_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_PACK
# define PNG_WRITE_PACK_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_BGR
# define PNG_WRITE_BGR_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_SWAP
# define PNG_WRITE_SWAP_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_PACKSWAP
# define PNG_WRITE_PACKSWAP_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_INVERT
# define PNG_WRITE_INVERT_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_FILLER
# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */
# endif
# ifndef PNG_NO_WRITE_SWAP_ALPHA
# define PNG_WRITE_SWAP_ALPHA_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_INVERT_ALPHA
# define PNG_WRITE_INVERT_ALPHA_SUPPORTED
# endif
# ifndef PNG_NO_WRITE_USER_TRANSFORM
# define PNG_WRITE_USER_TRANSFORM_SUPPORTED
# endif
#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \
!defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* This is not required for PNG-compliant encoders, but can cause
* trouble if left undefined
*/
# define PNG_WRITE_INTERLACING_SUPPORTED
#endif
#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \
!defined(PNG_WRITE_WEIGHTED_FILTER) && \
defined(PNG_FLOATING_POINT_SUPPORTED)
# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
#endif
#ifndef PNG_NO_WRITE_FLUSH
# define PNG_WRITE_FLUSH_SUPPORTED
#endif
#if !defined(PNG_NO_SAVE_INT_32) || defined(PNG_WRITE_oFFS_SUPPORTED) || \
defined(PNG_WRITE_pCAL_SUPPORTED)
# ifndef PNG_SAVE_INT_32_SUPPORTED
# define PNG_SAVE_INT_32_SUPPORTED
# endif
#endif
#endif /* PNG_WRITE_SUPPORTED */
#define PNG_NO_ERROR_NUMBERS
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
# ifndef PNG_NO_USER_TRANSFORM_PTR
# define PNG_USER_TRANSFORM_PTR_SUPPORTED
# endif
#endif
#if defined(PNG_STDIO_SUPPORTED) && !defined(PNG_TIME_RFC1123_SUPPORTED)
# define PNG_TIME_RFC1123_SUPPORTED
#endif
/* This adds extra functions in pngget.c for accessing data from the
* info pointer (added in version 0.99)
* png_get_image_width()
* png_get_image_height()
* png_get_bit_depth()
* png_get_color_type()
* png_get_compression_type()
* png_get_filter_type()
* png_get_interlace_type()
* png_get_pixel_aspect_ratio()
* png_get_pixels_per_meter()
* png_get_x_offset_pixels()
* png_get_y_offset_pixels()
* png_get_x_offset_microns()
* png_get_y_offset_microns()
*/
#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED)
# define PNG_EASY_ACCESS_SUPPORTED
#endif
/* Added at libpng-1.2.0 */
#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED)
# define PNG_USER_MEM_SUPPORTED
#endif
/* Added at libpng-1.2.6 */
#ifndef PNG_NO_SET_USER_LIMITS
# ifndef PNG_SET_USER_LIMITS_SUPPORTED
# define PNG_SET_USER_LIMITS_SUPPORTED
# endif
/* Feature added at libpng-1.4.0, this flag added at 1.4.1 */
# ifndef PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
# define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
# endif
/* Feature added at libpng-1.4.1, this flag added at 1.4.1 */
# ifndef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
# define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
# endif
#endif
/* Added at libpng-1.2.43 */
#ifndef PNG_USER_LIMITS_SUPPORTED
# ifndef PNG_NO_USER_LIMITS
# define PNG_USER_LIMITS_SUPPORTED
# endif
#endif
/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGs no matter
* how large, set these two limits to 0x7fffffffL
*/
#ifndef PNG_USER_WIDTH_MAX
# define PNG_USER_WIDTH_MAX 1000000L
#endif
#ifndef PNG_USER_HEIGHT_MAX
# define PNG_USER_HEIGHT_MAX 1000000L
#endif
/* Added at libpng-1.2.43. To accept all valid PNGs no matter
* how large, set these two limits to 0.
*/
#ifndef PNG_USER_CHUNK_CACHE_MAX
# define PNG_USER_CHUNK_CACHE_MAX 32767
#endif
/* Added at libpng-1.2.43 */
#ifndef PNG_USER_CHUNK_MALLOC_MAX
# define PNG_USER_CHUNK_MALLOC_MAX 8000000
#endif
/* Added at libpng-1.4.0 */
#if !defined(PNG_NO_IO_STATE) && !defined(PNG_IO_STATE_SUPPORTED)
# define PNG_IO_STATE_SUPPORTED
#endif
#ifndef PNG_LITERAL_SHARP
# define PNG_LITERAL_SHARP 0x23
#endif
#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
#endif
#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET
# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d
#endif
#ifndef PNG_STRING_NEWLINE
#define PNG_STRING_NEWLINE "\n"
#endif
/* These are currently experimental features, define them if you want */
/* Very little testing */
/*
#ifdef PNG_READ_SUPPORTED
# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
# endif
#endif
*/
/* This is only for PowerPC big-endian and 680x0 systems */
/* some testing */
/*
#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
# define PNG_READ_BIG_ENDIAN_SUPPORTED
#endif
*/
#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS)
# define PNG_USE_READ_MACROS
#endif
/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING */
#if !defined(PNG_NO_POINTER_INDEXING) && \
!defined(PNG_POINTER_INDEXING_SUPPORTED)
# define PNG_POINTER_INDEXING_SUPPORTED
#endif
/* Any chunks you are not interested in, you can undef here. The
* ones that allocate memory may be expecially important (hIST,
* tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info
* a bit smaller.
*/
/* The size of the png_text structure changed in libpng-1.0.6 when
* iTXt support was added. iTXt support was turned off by default through
* libpng-1.2.x, to support old apps that malloc the png_text structure
* instead of calling png_set_text() and letting libpng malloc it. It
* was turned on by default in libpng-1.4.0.
*/
/* PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */
#if defined(PNG_READ_SUPPORTED) && \
!defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
!defined(PNG_NO_READ_ANCILLARY_CHUNKS)
# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#endif
/* PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */
#if defined(PNG_WRITE_SUPPORTED) && \
!defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
!defined(PNG_NO_WRITE_ANCILLARY_CHUNKS)
# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#endif
#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#ifdef PNG_NO_READ_TEXT
# define PNG_NO_READ_iTXt
# define PNG_NO_READ_tEXt
# define PNG_NO_READ_zTXt
#endif
#ifndef PNG_NO_READ_bKGD
# define PNG_READ_bKGD_SUPPORTED
# define PNG_bKGD_SUPPORTED
#endif
#ifndef PNG_NO_READ_cHRM
# define PNG_READ_cHRM_SUPPORTED
# define PNG_cHRM_SUPPORTED
#endif
#ifndef PNG_NO_READ_gAMA
# define PNG_READ_gAMA_SUPPORTED
# define PNG_gAMA_SUPPORTED
#endif
#ifndef PNG_NO_READ_hIST
# define PNG_READ_hIST_SUPPORTED
# define PNG_hIST_SUPPORTED
#endif
#ifndef PNG_NO_READ_iCCP
# define PNG_READ_iCCP_SUPPORTED
# define PNG_iCCP_SUPPORTED
#endif
#ifndef PNG_NO_READ_iTXt
# ifndef PNG_READ_iTXt_SUPPORTED
# define PNG_READ_iTXt_SUPPORTED
# endif
# ifndef PNG_iTXt_SUPPORTED
# define PNG_iTXt_SUPPORTED
# endif
#endif
#ifndef PNG_NO_READ_oFFs
# define PNG_READ_oFFs_SUPPORTED
# define PNG_oFFs_SUPPORTED
#endif
#ifndef PNG_NO_READ_pCAL
# define PNG_READ_pCAL_SUPPORTED
# define PNG_pCAL_SUPPORTED
#endif
#ifndef PNG_NO_READ_sCAL
# define PNG_READ_sCAL_SUPPORTED
# define PNG_sCAL_SUPPORTED
#endif
#ifndef PNG_NO_READ_pHYs
# define PNG_READ_pHYs_SUPPORTED
# define PNG_pHYs_SUPPORTED
#endif
#ifndef PNG_NO_READ_sBIT
# define PNG_READ_sBIT_SUPPORTED
# define PNG_sBIT_SUPPORTED
#endif
#ifndef PNG_NO_READ_sPLT
# define PNG_READ_sPLT_SUPPORTED
# define PNG_sPLT_SUPPORTED
#endif
#ifndef PNG_NO_READ_sRGB
# define PNG_READ_sRGB_SUPPORTED
# define PNG_sRGB_SUPPORTED
#endif
#ifndef PNG_NO_READ_tEXt
# define PNG_READ_tEXt_SUPPORTED
# define PNG_tEXt_SUPPORTED
#endif
#ifndef PNG_NO_READ_tIME
# define PNG_READ_tIME_SUPPORTED
# define PNG_tIME_SUPPORTED
#endif
#ifndef PNG_NO_READ_tRNS
# define PNG_READ_tRNS_SUPPORTED
# define PNG_tRNS_SUPPORTED
#endif
#ifndef PNG_NO_READ_zTXt
# define PNG_READ_zTXt_SUPPORTED
# define PNG_zTXt_SUPPORTED
#endif
#ifndef PNG_NO_READ_OPT_PLTE
# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */
#endif /* optional PLTE chunk in RGB and RGBA images */
#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \
defined(PNG_READ_zTXt_SUPPORTED)
# define PNG_READ_TEXT_SUPPORTED
# define PNG_TEXT_SUPPORTED
#endif
#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
#ifndef PNG_NO_READ_UNKNOWN_CHUNKS
# ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
# endif
# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
# define PNG_UNKNOWN_CHUNKS_SUPPORTED
# endif
# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
# define PNG_READ_USER_CHUNKS_SUPPORTED
# endif
#endif
#ifndef PNG_NO_READ_USER_CHUNKS
# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
# define PNG_READ_USER_CHUNKS_SUPPORTED
# endif
# ifndef PNG_USER_CHUNKS_SUPPORTED
# define PNG_USER_CHUNKS_SUPPORTED
# endif
#endif
#ifndef PNG_NO_HANDLE_AS_UNKNOWN
# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
# endif
#endif
#ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#ifdef PNG_NO_WRITE_TEXT
# define PNG_NO_WRITE_iTXt
# define PNG_NO_WRITE_tEXt
# define PNG_NO_WRITE_zTXt
#endif
#ifndef PNG_NO_WRITE_bKGD
# define PNG_WRITE_bKGD_SUPPORTED
# ifndef PNG_bKGD_SUPPORTED
# define PNG_bKGD_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_cHRM
# define PNG_WRITE_cHRM_SUPPORTED
# ifndef PNG_cHRM_SUPPORTED
# define PNG_cHRM_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_gAMA
# define PNG_WRITE_gAMA_SUPPORTED
# ifndef PNG_gAMA_SUPPORTED
# define PNG_gAMA_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_hIST
# define PNG_WRITE_hIST_SUPPORTED
# ifndef PNG_hIST_SUPPORTED
# define PNG_hIST_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_iCCP
# define PNG_WRITE_iCCP_SUPPORTED
# ifndef PNG_iCCP_SUPPORTED
# define PNG_iCCP_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_iTXt
# ifndef PNG_WRITE_iTXt_SUPPORTED
# define PNG_WRITE_iTXt_SUPPORTED
# endif
# ifndef PNG_iTXt_SUPPORTED
# define PNG_iTXt_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_oFFs
# define PNG_WRITE_oFFs_SUPPORTED
# ifndef PNG_oFFs_SUPPORTED
# define PNG_oFFs_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_pCAL
# define PNG_WRITE_pCAL_SUPPORTED
# ifndef PNG_pCAL_SUPPORTED
# define PNG_pCAL_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_sCAL
# define PNG_WRITE_sCAL_SUPPORTED
# ifndef PNG_sCAL_SUPPORTED
# define PNG_sCAL_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_pHYs
# define PNG_WRITE_pHYs_SUPPORTED
# ifndef PNG_pHYs_SUPPORTED
# define PNG_pHYs_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_sBIT
# define PNG_WRITE_sBIT_SUPPORTED
# ifndef PNG_sBIT_SUPPORTED
# define PNG_sBIT_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_sPLT
# define PNG_WRITE_sPLT_SUPPORTED
# ifndef PNG_sPLT_SUPPORTED
# define PNG_sPLT_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_sRGB
# define PNG_WRITE_sRGB_SUPPORTED
# ifndef PNG_sRGB_SUPPORTED
# define PNG_sRGB_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_tEXt
# define PNG_WRITE_tEXt_SUPPORTED
# ifndef PNG_tEXt_SUPPORTED
# define PNG_tEXt_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_tIME
# define PNG_WRITE_tIME_SUPPORTED
# ifndef PNG_tIME_SUPPORTED
# define PNG_tIME_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_tRNS
# define PNG_WRITE_tRNS_SUPPORTED
# ifndef PNG_tRNS_SUPPORTED
# define PNG_tRNS_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_zTXt
# define PNG_WRITE_zTXt_SUPPORTED
# ifndef PNG_zTXt_SUPPORTED
# define PNG_zTXt_SUPPORTED
# endif
#endif
#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \
defined(PNG_WRITE_zTXt_SUPPORTED)
# define PNG_WRITE_TEXT_SUPPORTED
# ifndef PNG_TEXT_SUPPORTED
# define PNG_TEXT_SUPPORTED
# endif
#endif
#ifdef PNG_WRITE_tIME_SUPPORTED
# ifndef PNG_NO_CONVERT_tIME
# ifndef _WIN32_WCE
/* The "tm" structure is not supported on WindowsCE */
# ifndef PNG_CONVERT_tIME_SUPPORTED
# define PNG_CONVERT_tIME_SUPPORTED
# endif
# endif
# endif
#endif
#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */
#ifndef PNG_NO_WRITE_FILTER
# ifndef PNG_WRITE_FILTER_SUPPORTED
# define PNG_WRITE_FILTER_SUPPORTED
# endif
#endif
#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS
# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
# define PNG_UNKNOWN_CHUNKS_SUPPORTED
# endif
#endif
#ifndef PNG_NO_HANDLE_AS_UNKNOWN
# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
# endif
#endif
#endif /* PNG_WRITE_SUPPORTED */
/* Turn this off to disable png_read_png() and
* png_write_png() and leave the row_pointers member
* out of the info structure.
*/
#ifndef PNG_NO_INFO_IMAGE
# define PNG_INFO_IMAGE_SUPPORTED
#endif
/* Need the time information for converting tIME chunks */
#ifdef PNG_CONVERT_tIME_SUPPORTED
/* "time.h" functions are not supported on WindowsCE */
# include
#endif
/* Some typedefs to get us started. These should be safe on most of the
* common platforms. The typedefs should be at least as large as the
* numbers suggest (a png_uint_32 must be at least 32 bits long), but they
* don't have to be exactly that size. Some compilers dislike passing
* unsigned shorts as function parameters, so you may be better off using
* unsigned int for png_uint_16.
*/
#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL)
typedef unsigned int png_uint_32;
typedef int png_int_32;
#else
typedef unsigned long png_uint_32;
typedef long png_int_32;
#endif
typedef unsigned short png_uint_16;
typedef short png_int_16;
typedef unsigned char png_byte;
#ifdef PNG_NO_SIZE_T
typedef unsigned int png_size_t;
#else
typedef size_t png_size_t;
#endif
#define png_sizeof(x) (sizeof (x))
/* The following is needed for medium model support. It cannot be in the
* pngpriv.h header. Needs modification for other compilers besides
* MSC. Model independent support declares all arrays and pointers to be
* large using the far keyword. The zlib version used must also support
* model independent data. As of version zlib 1.0.4, the necessary changes
* have been made in zlib. The USE_FAR_KEYWORD define triggers other
* changes that are needed. (Tim Wegner)
*/
/* Separate compiler dependencies (problem here is that zlib.h always
* defines FAR. (SJT)
*/
#ifdef __BORLANDC__
# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
# define LDATA 1
# else
# define LDATA 0
# endif
/* GRR: why is Cygwin in here? Cygwin is not Borland C... */
# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
# define PNG_MAX_MALLOC_64K
# if (LDATA != 1)
# ifndef FAR
# define FAR __far
# endif
# define USE_FAR_KEYWORD
# endif /* LDATA != 1 */
/* Possibly useful for moving data out of default segment.
* Uncomment it if you want. Could also define FARDATA as
* const if your compiler supports it. (SJT)
# define FARDATA FAR
*/
# endif /* __WIN32__, __FLAT__, __CYGWIN__ */
#endif /* __BORLANDC__ */
/* Suggest testing for specific compiler first before testing for
* FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM,
* making reliance oncertain keywords suspect. (SJT)
*/
/* MSC Medium model */
#ifdef FAR
# ifdef M_I86MM
# define USE_FAR_KEYWORD
# define FARDATA FAR
# include
# endif
#endif
/* SJT: default case */
#ifndef FAR
# define FAR
#endif
/* At this point FAR is always defined */
#ifndef FARDATA
# define FARDATA
#endif
/* Typedef for floating-point numbers that are converted
to fixed-point with a multiple of 100,000, e.g., int_gamma */
typedef png_int_32 png_fixed_point;
/* Add typedefs for pointers */
typedef void FAR * png_voidp;
typedef png_byte FAR * png_bytep;
typedef png_uint_32 FAR * png_uint_32p;
typedef png_int_32 FAR * png_int_32p;
typedef png_uint_16 FAR * png_uint_16p;
typedef png_int_16 FAR * png_int_16p;
typedef PNG_CONST char FAR * png_const_charp;
typedef char FAR * png_charp;
typedef png_fixed_point FAR * png_fixed_point_p;
#ifndef PNG_NO_STDIO
typedef FILE * png_FILE_p;
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
typedef double FAR * png_doublep;
#endif
/* Pointers to pointers; i.e. arrays */
typedef png_byte FAR * FAR * png_bytepp;
typedef png_uint_32 FAR * FAR * png_uint_32pp;
typedef png_int_32 FAR * FAR * png_int_32pp;
typedef png_uint_16 FAR * FAR * png_uint_16pp;
typedef png_int_16 FAR * FAR * png_int_16pp;
typedef PNG_CONST char FAR * FAR * png_const_charpp;
typedef char FAR * FAR * png_charpp;
typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
#ifdef PNG_FLOATING_POINT_SUPPORTED
typedef double FAR * FAR * png_doublepp;
#endif
/* Pointers to pointers to pointers; i.e., pointer to array */
typedef char FAR * FAR * FAR * png_charppp;
/* Define PNG_BUILD_DLL if the module being built is a Windows
* LIBPNG DLL.
*
* Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL.
* It is equivalent to Microsoft predefined macro _DLL that is
* automatically defined when you compile using the share
* version of the CRT (C Run-Time library)
*
* The cygwin mods make this behavior a little different:
* Define PNG_BUILD_DLL if you are building a dll for use with cygwin
* Define PNG_STATIC if you are building a static library for use with cygwin,
* -or- if you are building an application that you want to link to the
* static library.
* PNG_USE_DLL is defined by default (no user action needed) unless one of
* the other flags is defined.
*/
#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL))
# define PNG_DLL
#endif
/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall",
* you may get warnings regarding the linkage of png_zalloc and png_zfree.
* Don't ignore those warnings; you must also reset the default calling
* convention in your compiler to match your PNGAPI, and you must build
* zlib and your applications the same way you build libpng.
*/
#ifdef __CYGWIN__
# undef PNGAPI
# define PNGAPI __cdecl
# undef PNG_IMPEXP
# define PNG_IMPEXP
#endif
#ifdef __WATCOMC__
# ifndef PNGAPI
# define PNGAPI
# endif
#endif
#if defined(__MINGW32__) && !defined(PNG_MODULEDEF)
# ifndef PNG_NO_MODULEDEF
# define PNG_NO_MODULEDEF
# endif
#endif
#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF)
# define PNG_IMPEXP
#endif
#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \
(( defined(_Windows) || defined(_WINDOWS) || \
defined(WIN32) || defined(_WIN32) || defined(__WIN32__) ))
# ifndef PNGAPI
# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
# define PNGAPI __cdecl
# else
# define PNGAPI _cdecl
# endif
# endif
# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \
0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */)
# define PNG_IMPEXP
# endif
# ifndef PNG_IMPEXP
# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol
# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol
/* Borland/Microsoft */
# if defined(_MSC_VER) || defined(__BORLANDC__)
# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500)
# define PNG_EXPORT PNG_EXPORT_TYPE1
# else
# define PNG_EXPORT PNG_EXPORT_TYPE2
# ifdef PNG_BUILD_DLL
# define PNG_IMPEXP __export
# else
# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in VC++ */
# endif /* Exists in Borland C++ for
C++ classes (== huge) */
# endif
# endif
# ifndef PNG_IMPEXP
# ifdef PNG_BUILD_DLL
# define PNG_IMPEXP __declspec(dllexport)
# else
# define PNG_IMPEXP __declspec(dllimport)
# endif
# endif
# endif /* PNG_IMPEXP */
#else /* !(DLL || non-cygwin WINDOWS) */
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
# ifndef PNGAPI
# define PNGAPI _System
# endif
# else
# if 0 /* ... other platforms, with other meanings */
# endif
# endif
#endif
#ifndef PNGAPI
# define PNGAPI
#endif
#ifndef PNG_IMPEXP
# define PNG_IMPEXP
#endif
#ifdef PNG_BUILDSYMS
# ifndef PNG_EXPORT
# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END
# endif
#endif
#ifndef PNG_EXPORT
# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol
#endif
#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */
/* Support for compiler specific function attributes. These are used
* so that where compiler support is available incorrect use of API
* functions in png.h will generate compiler warnings.
*
* Added at libpng-1.2.41.
*/
#ifndef PNG_NO_PEDANTIC_WARNINGS
# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
# define PNG_PEDANTIC_WARNINGS_SUPPORTED
# endif
#endif
#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
/* Support for compiler specific function attributes. These are used
* so that where compiler support is available incorrect use of API
* functions in png.h will generate compiler warnings. Added at libpng
* version 1.2.41.
*/
# ifdef __GNUC__
# ifndef PNG_USE_RESULT
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
# endif
# ifndef PNG_NORETURN
# define PNG_NORETURN __attribute__((__noreturn__))
# endif
# if __GNUC__ >= 3
# ifndef PNG_ALLOCATED
# define PNG_ALLOCATED __attribute__((__malloc__))
# endif
# ifndef PNG_DEPRECATED
# define PNG_DEPRECATED __attribute__((__deprecated__))
# endif
# ifndef PNG_PRIVATE
# if 0 /* Doesn't work so we use deprecated instead*/
# define PNG_PRIVATE \
__attribute__((warning("This function is not exported by libpng.")))
# else
# define PNG_PRIVATE \
__attribute__((__deprecated__))
# endif
# endif
# endif /* __GNUC__ >= 3 */
# endif /* __GNUC__ */
#endif /* PNG_PEDANTIC_WARNINGS */
#ifndef PNG_DEPRECATED
# define PNG_DEPRECATED /* Use of this function is deprecated */
#endif
#ifndef PNG_USE_RESULT
# define PNG_USE_RESULT /* The result of this function must be checked */
#endif
#ifndef PNG_NORETURN
# define PNG_NORETURN /* This function does not return */
#endif
#ifndef PNG_ALLOCATED
# define PNG_ALLOCATED /* The result of the function is new memory */
#endif
#ifndef PNG_DEPSTRUCT
# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */
#endif
#ifndef PNG_PRIVATE
# define PNG_PRIVATE /* This is a private libpng function */
#endif
/* Users may want to use these so they are not private. Any library
* functions that are passed far data must be model-independent.
*/
/* memory model/platform independent fns */
#ifndef PNG_ABORT
# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_))
# define PNG_ABORT() ExitProcess(0)
# else
# define PNG_ABORT() abort()
# endif
#endif
#ifdef USE_FAR_KEYWORD
/* Use this to make far-to-near assignments */
# define CHECK 1
# define NOCHECK 0
# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK))
# define png_strcpy _fstrcpy
# define png_strncpy _fstrncpy /* Added to v 1.2.6 */
# define png_strlen _fstrlen
# define png_memcmp _fmemcmp /* SJT: added */
# define png_memcpy _fmemcpy
# define png_memset _fmemset
# define png_sprintf sprintf
#else
# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_))
# /* Favor Windows over C runtime fns */
# define CVT_PTR(ptr) (ptr)
# define CVT_PTR_NOCHECK(ptr) (ptr)
# define png_strcpy lstrcpyA
# define png_strncpy lstrcpynA
# define png_strlen lstrlenA
# define png_memcmp memcmp
# define png_memcpy memcpy
# define png_memset memset
# define png_sprintf wsprintfA
# else
# define CVT_PTR(ptr) (ptr)
# define CVT_PTR_NOCHECK(ptr) (ptr)
# define png_strcpy strcpy
# define png_strncpy strncpy /* Added to v 1.2.6 */
# define png_strlen strlen
# define png_memcmp memcmp /* SJT: added */
# define png_memcpy memcpy
# define png_memset memset
# define png_sprintf sprintf
# endif
#endif
#ifndef PNG_NO_SNPRINTF
# ifdef _MSC_VER
# define png_snprintf _snprintf /* Added to v 1.2.19 */
# define png_snprintf2 _snprintf
# define png_snprintf6 _snprintf
# else
# define png_snprintf snprintf /* Added to v 1.2.19 */
# define png_snprintf2 snprintf
# define png_snprintf6 snprintf
# endif
#else
/* You don't have or don't want to use snprintf(). Caution: Using
* sprintf instead of snprintf exposes your application to accidental
* or malevolent buffer overflows. If you don't have snprintf()
* as a general rule you should provide one (you can get one from
* Portable OpenSSH).
*/
# define png_snprintf(s1,n,fmt,x1) png_sprintf(s1,fmt,x1)
# define png_snprintf2(s1,n,fmt,x1,x2) png_sprintf(s1,fmt,x1,x2)
# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \
png_sprintf(s1,fmt,x1,x2,x3,x4,x5,x6)
#endif
/* png_alloc_size_t is guaranteed to be no smaller than png_size_t,
* and no smaller than png_uint_32. Casts from png_size_t or png_uint_32
* to png_alloc_size_t are not necessary; in fact, it is recommended
* not to use them at all so that the compiler can complain when something
* turns out to be problematic.
* Casts in the other direction (from png_alloc_size_t to png_size_t or
* png_uint_32) should be explicitly applied; however, we do not expect
* to encounter practical situations that require such conversions.
*/
#if defined(__TURBOC__) && !defined(__FLAT__)
typedef unsigned long png_alloc_size_t;
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
typedef unsigned long png_alloc_size_t;
# else
/* This is an attempt to detect an old Windows system where (int) is
* actually 16 bits, in that case png_malloc must have an argument with a
* bigger size to accomodate the requirements of the library.
*/
# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \
(!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL)
typedef DWORD png_alloc_size_t;
# else
typedef png_size_t png_alloc_size_t;
# endif
# endif
#endif
/* End of memory model/platform independent support */
/* Just a little check that someone hasn't tried to define something
* contradictory.
*/
#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K)
# undef PNG_ZBUF_SIZE
# define PNG_ZBUF_SIZE 65536L
#endif
/* Added at libpng-1.2.8 */
#endif /* PNG_VERSION_INFO_ONLY */
#endif /* PNGCONF_H */
================================================
FILE: src/main/jni/png/pngpriv.h
================================================
/* pngpriv.h - private declarations for use inside libpng
*
* libpng version 1.4.19 - December 17, 2015
* For conditions of distribution and use, see copyright notice in png.h
* Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* The symbols declared in this file (including the functions declared
* as PNG_EXTERN) are PRIVATE. They are not part of the libpng public
* interface, and are not recommended for use by regular applications.
* Some of them may become public in the future; others may stay private,
* change in an incompatible way, or even disappear.
* Although the libpng users are not forbidden to include this header,
* they should be well aware of the issues that may arise from doing so.
*/
#ifndef PNGPRIV_H
#define PNGPRIV_H
#ifndef PNG_VERSION_INFO_ONLY
#if defined(_AIX) && defined(_ALL_SOURCE)
/* On AIX if _ALL_SOURCE is defined standard header files (including
* stdlib.h) define identifiers that are not permitted by the ANSI and
* POSIX standards. In particular 'jmpbuf' is #defined and this will
* prevent compilation of libpng. The following prevents this:
*/
# undef _ALL_SOURCE
#endif
#include
#ifndef PNG_EXTERN
/* The functions exported by PNG_EXTERN are internal functions, which
* aren't usually used outside the library (as far as I know), so it is
* debatable if they should be exported at all. In the future, when it
* is possible to have run-time registry of chunk-handling functions,
* some of these will be made available again.
# define PNG_EXTERN extern
*/
# define PNG_EXTERN
#endif
/* Other defines specific to compilers can go here. Try to keep
* them inside an appropriate ifdef/endif pair for portability.
*/
#ifdef PNG_FLOATING_POINT_SUPPORTED
# ifdef MACOS
/* We need to check that hasn't already been included earlier
* as it seems it doesn't agree with , yet we should really use
* if possible.
*/
# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
# include
# endif
# else
# include
# endif
# if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
/* Amiga SAS/C: We must include builtin FPU functions when compiling using
* MATH=68881
*/
# include
# endif
#endif
/* Codewarrior on NT has linking problems without this. */
#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__)
# define PNG_ALWAYS_EXTERN
#endif
/* This provides the non-ANSI (far) memory allocation routines. */
#if defined(__TURBOC__) && defined(__MSDOS__)
# include
# include
#endif
#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \
defined(_WIN32) || defined(__WIN32__)
# include /* defines _WINDOWS_ macro */
#endif
/* Various modes of operation. Note that after an init, mode is set to
* zero automatically when the structure is created.
*/
#define PNG_HAVE_IHDR 0x01
#define PNG_HAVE_PLTE 0x02
#define PNG_HAVE_IDAT 0x04
#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */
#define PNG_HAVE_IEND 0x10
#define PNG_HAVE_gAMA 0x20
#define PNG_HAVE_cHRM 0x40
#define PNG_HAVE_sRGB 0x80
#define PNG_HAVE_CHUNK_HEADER 0x100
#define PNG_WROTE_tIME 0x200
#define PNG_WROTE_INFO_BEFORE_PLTE 0x400
#define PNG_BACKGROUND_IS_GRAY 0x800
#define PNG_HAVE_PNG_SIGNATURE 0x1000
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001
#define PNG_INTERLACE 0x0002
#define PNG_PACK 0x0004
#define PNG_SHIFT 0x0008
#define PNG_SWAP_BYTES 0x0010
#define PNG_INVERT_MONO 0x0020
#define PNG_QUANTIZE 0x0040 /* formerly PNG_DITHER */
#define PNG_BACKGROUND 0x0080
#define PNG_BACKGROUND_EXPAND 0x0100
/* 0x0200 unused */
#define PNG_16_TO_8 0x0400
#define PNG_RGBA 0x0800
#define PNG_EXPAND 0x1000
#define PNG_GAMMA 0x2000
#define PNG_GRAY_TO_RGB 0x4000
#define PNG_FILLER 0x8000L
#define PNG_PACKSWAP 0x10000L
#define PNG_SWAP_ALPHA 0x20000L
#define PNG_STRIP_ALPHA 0x40000L
#define PNG_INVERT_ALPHA 0x80000L
#define PNG_USER_TRANSFORM 0x100000L
#define PNG_RGB_TO_GRAY_ERR 0x200000L
#define PNG_RGB_TO_GRAY_WARN 0x400000L
#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */
/* 0x800000L Unused */
#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */
#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */
/* 0x4000000L unused */
/* 0x8000000L unused */
/* 0x10000000L unused */
/* 0x20000000L unused */
/* 0x40000000L unused */
/* Flags for png_create_struct */
#define PNG_STRUCT_PNG 0x0001
#define PNG_STRUCT_INFO 0x0002
/* Scaling factor for filter heuristic weighting calculations */
#define PNG_WEIGHT_SHIFT 8
#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT))
#define PNG_COST_SHIFT 3
#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
/* Flags for the png_ptr->flags rather than declaring a byte for each one */
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001
#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002
#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004
#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008
#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010
#define PNG_FLAG_ZLIB_FINISHED 0x0020
#define PNG_FLAG_ROW_INIT 0x0040
#define PNG_FLAG_FILLER_AFTER 0x0080
#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100
#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200
#define PNG_FLAG_CRC_CRITICAL_USE 0x0400
#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800
/* 0x1000 unused */
/* 0x2000 unused */
/* 0x4000 unused */
#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L
#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L
#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L
#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L
#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L
#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L
#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */
#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */
#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */
/* 0x1000000L unused */
/* 0x2000000L unused */
/* 0x4000000L unused */
/* 0x8000000L unused */
/* 0x10000000L unused */
/* 0x20000000L unused */
/* 0x40000000L unused */
#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
PNG_FLAG_CRC_ANCILLARY_NOWARN)
#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \
PNG_FLAG_CRC_CRITICAL_IGNORE)
#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \
PNG_FLAG_CRC_CRITICAL_MASK)
/* Save typing and make code easier to understand */
#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
abs((int)((c1).green) - (int)((c2).green)) + \
abs((int)((c1).blue) - (int)((c2).blue)))
/* Added to libpng-1.2.6 JB */
#define PNG_ROWBYTES(pixel_bits, width) \
((pixel_bits) >= 8 ? \
((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \
(( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) )
/* PNG_OUT_OF_RANGE returns true if value is outside the range
* ideal-delta..ideal+delta. Each argument is evaluated twice.
* "ideal" and "delta" should be constants, normally simple
* integers, "value" a variable. Added to libpng-1.2.6 JB
*/
#define PNG_OUT_OF_RANGE(value, ideal, delta) \
( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) )
/* Constant strings for known chunk types. If you need to add a chunk,
* define the name here, and add an invocation of the macro wherever it's
* needed.
*/
#define PNG_IHDR PNG_CONST png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'}
#define PNG_IDAT PNG_CONST png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'}
#define PNG_IEND PNG_CONST png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'}
#define PNG_PLTE PNG_CONST png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'}
#define PNG_bKGD PNG_CONST png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'}
#define PNG_cHRM PNG_CONST png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'}
#define PNG_gAMA PNG_CONST png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'}
#define PNG_hIST PNG_CONST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'}
#define PNG_iCCP PNG_CONST png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'}
#define PNG_iTXt PNG_CONST png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'}
#define PNG_oFFs PNG_CONST png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'}
#define PNG_pCAL PNG_CONST png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'}
#define PNG_sCAL PNG_CONST png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'}
#define PNG_pHYs PNG_CONST png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'}
#define PNG_sBIT PNG_CONST png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'}
#define PNG_sPLT PNG_CONST png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'}
#define PNG_sRGB PNG_CONST png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'}
#define PNG_sTER PNG_CONST png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}
#define PNG_tEXt PNG_CONST png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'}
#define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'}
#define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'}
#define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'}
/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* These functions are used internally in the code. They generally
* shouldn't be used unless you are writing code to add or replace some
* functionality in libpng. More information about most functions can
* be found in the files where the functions are located.
*/
/* Allocate memory for an internal libpng struct */
PNG_EXTERN png_voidp png_create_struct PNGARG((int type));
/* Free memory from internal libpng struct */
PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr
malloc_fn, png_voidp mem_ptr));
PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
png_free_ptr free_fn, png_voidp mem_ptr));
/* Free any memory that info_ptr points to and reset struct. */
PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
png_infop info_ptr));
/* Function to allocate memory for zlib. PNGAPI is disallowed. */
PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size));
/* Function to free memory for zlib. PNGAPI is disallowed. */
PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr));
/* Next four functions are used internally as callbacks. PNGAPI is required
* but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */
PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr,
png_bytep data, png_size_t length));
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr,
png_bytep buffer, png_size_t length));
#endif
PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr,
png_bytep data, png_size_t length));
#ifdef PNG_WRITE_FLUSH_SUPPORTED
#ifdef PNG_STDIO_SUPPORTED
PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr));
#endif
#endif
/* Reset the CRC variable */
PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr));
/* Write the "data" buffer to whatever output you are using */
PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data,
png_size_t length));
/* Read and check the PNG file signature */
PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr));
/* Read the chunk header (length + type name) */
PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr));
/* Read data from whatever input you are using into the "data" buffer */
PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data,
png_size_t length));
/* Read bytes into buf, and update png_ptr->crc */
PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf,
png_size_t length));
/* Decompress data in a chunk that uses compression */
#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \
defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr,
int comp_type, png_size_t chunklength, png_size_t prefix_length,
png_size_t *data_length));
#endif
/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip));
/* Read the CRC from the file and compare it to the libpng calculated CRC */
PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr));
/* Calculate the CRC over a section of data. Note that we are only
* passing a maximum of 64K on systems that have this as a memory limit,
* since this is the maximum buffer size we can specify.
*/
PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr,
png_size_t length));
#ifdef PNG_WRITE_FLUSH_SUPPORTED
PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
#endif
/* Write various chunks */
/* Write the IHDR chunk, and update the png_struct with the necessary
* information.
*/
PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width,
png_uint_32 height,
int bit_depth, int color_type, int compression_method, int filter_method,
int interlace_method));
PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette,
png_uint_32 num_pal));
PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data,
png_size_t length));
PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr));
#ifdef PNG_WRITE_gAMA_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma));
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr,
png_fixed_point file_gamma));
#endif
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit,
int color_type));
#endif
#ifdef PNG_WRITE_cHRM_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr,
double white_x, double white_y,
double red_x, double red_y, double green_x, double green_y,
double blue_x, double blue_y));
#endif
PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
png_fixed_point int_white_x, png_fixed_point int_white_y,
png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
png_fixed_point int_blue_y));
#endif
#ifdef PNG_WRITE_sRGB_SUPPORTED
PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr,
int intent));
#endif
#ifdef PNG_WRITE_iCCP_SUPPORTED
PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr,
png_charp name, int compression_type,
png_charp profile, int proflen));
/* Note to maintainer: profile should be png_bytep */
#endif
#ifdef PNG_WRITE_sPLT_SUPPORTED
PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr,
png_sPLT_tp palette));
#endif
#ifdef PNG_WRITE_tRNS_SUPPORTED
PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans,
png_color_16p values, int number, int color_type));
#endif
#ifdef PNG_WRITE_bKGD_SUPPORTED
PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr,
png_color_16p values, int color_type));
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED
PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist,
int num_hist));
#endif
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
png_charp key, png_charpp new_key));
#endif
#ifdef PNG_WRITE_tEXt_SUPPORTED
PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key,
png_charp text, png_size_t text_len));
#endif
#ifdef PNG_WRITE_zTXt_SUPPORTED
PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key,
png_charp text, png_size_t text_len, int compression));
#endif
#ifdef PNG_WRITE_iTXt_SUPPORTED
PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr,
int compression, png_charp key, png_charp lang, png_charp lang_key,
png_charp text));
#endif
#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */
PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr,
png_infop info_ptr, png_textp text_ptr, int num_text));
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr,
png_int_32 x_offset, png_int_32 y_offset, int unit_type));
#endif
#ifdef PNG_WRITE_pCAL_SUPPORTED
PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose,
png_int_32 X0, png_int_32 X1, int type, int nparams,
png_charp units, png_charpp params));
#endif
#ifdef PNG_WRITE_pHYs_SUPPORTED
PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr,
png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
int unit_type));
#endif
#ifdef PNG_WRITE_tIME_SUPPORTED
PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr,
png_timep mod_time));
#endif
#ifdef PNG_WRITE_sCAL_SUPPORTED
#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr,
int unit, double width, double height));
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
int unit, png_charp width, png_charp height));
#endif
#endif
#endif
/* Called when finished processing a row of data */
PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
/* Internal use only. Called before first row of data */
PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
#ifdef PNG_READ_GAMMA_SUPPORTED
PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
png_byte bit_depth));
#endif
/* Combine a row of data, dealing with alpha, etc. if requested */
PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
int mask));
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Expand an interlaced row */
/* OLD pre-1.0.9 interface:
PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info,
png_bytep row, int pass, png_uint_32 transformations));
*/
PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr));
#endif
/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Grab pixels out of a row for an interlaced pass */
PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
png_bytep row, int pass));
#endif
/* Unfilter a row */
PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr,
png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter));
/* Choose the best filter to use and filter the row data */
PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr,
png_row_infop row_info));
/* Write out the filtered row. */
PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr,
png_bytep filtered_row));
/* Finish a row while reading, dealing with interlacing passes, etc. */
PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr));
/* Initialize the row buffers, etc. */
PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr));
/* Optional call to update the users info structure */
PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
png_infop info_ptr));
/* These are the functions that do the transformations */
#ifdef PNG_READ_FILLER_SUPPORTED
PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
png_bytep row, png_uint_32 filler, png_uint_32 flags));
#endif
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info,
png_bytep row));
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info,
png_bytep row));
#endif
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info,
png_bytep row));
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info,
png_bytep row));
#endif
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info,
png_bytep row, png_uint_32 flags));
#endif
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row));
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
defined(PNG_WRITE_PACKSWAP_SUPPORTED)
PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row));
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop
row_info, png_bytep row));
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info,
png_bytep row));
#endif
#ifdef PNG_READ_PACK_SUPPORTED
PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row));
#endif
#ifdef PNG_READ_SHIFT_SUPPORTED
PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row,
png_color_8p sig_bits));
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row));
#endif
#ifdef PNG_READ_16_TO_8_SUPPORTED
PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row));
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info,
png_bytep row, png_bytep palette_lookup, png_bytep quantize_lookup));
# ifdef PNG_CORRECT_PALETTE_SUPPORTED
PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr,
png_colorp palette, int num_palette));
# endif
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row));
#endif
#ifdef PNG_WRITE_PACK_SUPPORTED
PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info,
png_bytep row, png_uint_32 bit_depth));
#endif
#ifdef PNG_WRITE_SHIFT_SUPPORTED
PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row,
png_color_8p bit_depth));
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
#ifdef PNG_READ_GAMMA_SUPPORTED
PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
png_color_16p trans_color, png_color_16p background,
png_color_16p background_1,
png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
png_uint_16pp gamma_16_to_1, int gamma_shift));
#else
PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
png_color_16p trans_color, png_color_16p background));
#endif
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row,
png_bytep gamma_table, png_uint_16pp gamma_16_table,
int gamma_shift));
#endif
#ifdef PNG_READ_EXPAND_SUPPORTED
PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info,
png_bytep row, png_colorp palette, png_bytep trans, int num_trans));
PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
png_bytep row, png_color_16p trans_value));
#endif
/* The following decodes the appropriate chunks, and does error correction,
* then calls the appropriate callback for the chunk if it is valid.
*/
/* Decode the IHDR chunk */
PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#ifdef PNG_READ_bKGD_SUPPORTED
PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_cHRM_SUPPORTED
PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_gAMA_SUPPORTED
PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_hIST_SUPPORTED
PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_iCCP_SUPPORTED
PNG_EXTERN void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif /* PNG_READ_iCCP_SUPPORTED */
#ifdef PNG_READ_iTXt_SUPPORTED
PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_oFFs_SUPPORTED
PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_pCAL_SUPPORTED
PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_pHYs_SUPPORTED
PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_sCAL_SUPPORTED
PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_sPLT_SUPPORTED
PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif /* PNG_READ_sPLT_SUPPORTED */
#ifdef PNG_READ_sRGB_SUPPORTED
PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_tEXt_SUPPORTED
PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_tIME_SUPPORTED
PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_tRNS_SUPPORTED
PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
#ifdef PNG_READ_zTXt_SUPPORTED
PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
png_uint_32 length));
#endif
PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 length));
PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
png_bytep chunk_name));
/* Handle the transformations for reading and writing */
PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr));
PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr));
PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr));
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr));
PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
png_uint_32 length));
PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr));
PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr));
PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
png_bytep buffer, png_size_t buffer_length));
PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr));
PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr,
png_bytep buffer, png_size_t buffer_length));
PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr));
PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 length));
PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row));
PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr,
png_infop info_ptr));
PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr));
#ifdef PNG_READ_tEXt_SUPPORTED
PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 length));
PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr,
png_infop info_ptr));
#endif
#ifdef PNG_READ_zTXt_SUPPORTED
PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 length));
PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr,
png_infop info_ptr));
#endif
#ifdef PNG_READ_iTXt_SUPPORTED
PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr,
png_infop info_ptr, png_uint_32 length));
PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr,
png_infop info_ptr));
#endif
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
#ifdef PNG_MNG_FEATURES_SUPPORTED
PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info,
png_bytep row));
PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info,
png_bytep row));
#endif
/* Added at libpng version 1.4.0 */
#ifdef PNG_cHRM_SUPPORTED
PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr,
png_fixed_point int_white_x, png_fixed_point int_white_y,
png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
png_fixed_point int_blue_y));
#endif
#ifdef PNG_cHRM_SUPPORTED
#ifdef PNG_CHECK_cHRM_SUPPORTED
/* Added at libpng version 1.2.34 and 1.4.0 */
PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2,
unsigned long *hi_product, unsigned long *lo_product));
#endif
#endif
/* Added at libpng version 1.4.0 */
PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
int filter_type));
/* Free all memory used by the read (old method - NOT DLL EXPORTED) */
PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr,
png_infop end_info_ptr));
/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr));
#ifdef USE_FAR_KEYWORD /* memory model conversion function */
PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
int check));
#endif /* USE_FAR_KEYWORD */
/* Define PNG_DEBUG at compile time for debugging information. Higher
* numbers for PNG_DEBUG mean more debugging information. This has
* only been added since version 0.95 so it is not implemented throughout
* libpng yet, but more support will be added as needed.
*/
#ifdef PNG_DEBUG
#if (PNG_DEBUG > 0)
#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
#include
#if (PNG_DEBUG > 1)
#ifndef _DEBUG
# define _DEBUG
#endif
#ifndef png_debug
#define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE)
#endif
#ifndef png_debug1
#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1)
#endif
#ifndef png_debug2
#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2)
#endif
#endif
#else /* PNG_DEBUG_FILE || !_MSC_VER */
#ifndef PNG_DEBUG_FILE
#define PNG_DEBUG_FILE stderr
#endif /* PNG_DEBUG_FILE */
#if (PNG_DEBUG > 1)
/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on
* non-ISO compilers
*/
# ifdef __STDC__
# ifndef png_debug
# define png_debug(l,m) \
{ \
int num_tabs=l; \
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
}
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) \
{ \
int num_tabs=l; \
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
}
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
{ \
int num_tabs=l; \
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
}
# endif
# else /* __STDC __ */
# ifndef png_debug
# define png_debug(l,m) \
{ \
int num_tabs=l; \
char format[256]; \
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
m,PNG_STRING_NEWLINE); \
fprintf(PNG_DEBUG_FILE,format); \
}
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) \
{ \
int num_tabs=l; \
char format[256]; \
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
m,PNG_STRING_NEWLINE); \
fprintf(PNG_DEBUG_FILE,format,p1); \
}
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
{ \
int num_tabs=l; \
char format[256]; \
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
m,PNG_STRING_NEWLINE); \
fprintf(PNG_DEBUG_FILE,format,p1,p2); \
}
# endif
# endif /* __STDC __ */
#endif /* (PNG_DEBUG > 1) */
#endif /* _MSC_VER */
#endif /* (PNG_DEBUG > 0) */
#endif /* PNG_DEBUG */
#ifndef png_debug
#define png_debug(l, m)
#endif
#ifndef png_debug1
#define png_debug1(l, m, p1)
#endif
#ifndef png_debug2
#define png_debug2(l, m, p1, p2)
#endif
/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
#ifdef __cplusplus
}
#endif
#endif /* PNG_VERSION_INFO_ONLY */
#endif /* PNGPRIV_H */
================================================
FILE: src/main/jni/tiff/Android.mk
================================================
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_TIFF_SRC_FILES := \
libtiff/tif_dirread.c \
libtiff/tif_zip.c \
libtiff/tif_flush.c \
libtiff/tif_next.c \
libtiff/tif_ojpeg.c \
libtiff/tif_dirwrite.c \
libtiff/tif_dirinfo.c \
libtiff/tif_dir.c \
libtiff/tif_compress.c \
libtiff/tif_close.c \
libtiff/tif_tile.c \
libtiff/tif_open.c \
libtiff/tif_getimage.c \
libtiff/tif_pixarlog.c \
libtiff/tif_warning.c \
libtiff/tif_dumpmode.c \
libtiff/tif_jpeg.c \
libtiff/tif_jbig.c \
libtiff/tif_predict.c \
libtiff/mkg3states.c \
libtiff/tif_write.c \
libtiff/tif_error.c \
libtiff/tif_version.c \
libtiff/tif_print.c \
libtiff/tif_color.c \
libtiff/tif_read.c \
libtiff/tif_extension.c \
libtiff/tif_thunder.c \
libtiff/tif_lzw.c \
libtiff/tif_fax3.c \
libtiff/tif_luv.c \
libtiff/tif_codec.c \
libtiff/tif_unix.c \
libtiff/tif_packbits.c \
libtiff/tif_aux.c \
libtiff/tif_fax3sm.c \
libtiff/tif_swab.c \
libtiff/tif_strip.c
LOCAL_TIFF_SRC_FILES += port/lfind.c
###########################################################
LOCAL_SRC_FILES:= $(LOCAL_TIFF_SRC_FILES)
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/libtiff \
external/zlib \
external/jpeg
LOCAL_CFLAGS += -DAVOID_TABLES
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
LOCAL_STATIC_LIBRARIES := \
libjpeg
LOCAL_SHARED_LIBRARIES := \
libz
LOCAL_MODULE:= libtiff
LOCAL_PRELINK_MODULE:=false
include $(BUILD_SHARED_LIBRARY)
###########################################################
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES:= $(LOCAL_TIFF_SRC_FILES)
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/libtiff \
external/zlib \
external/jpeg
LOCAL_CFLAGS += -DAVOID_TABLES
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
LOCAL_STATIC_LIBRARIES := \
libjpeg
LOCAL_SHARED_LIBRARIES := \
libz
LOCAL_MODULE:= libtiff
include $(BUILD_STATIC_LIBRARY)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES = tools/tiffinfo.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/libtiff
LOCAL_SHARED_LIBRARIES = \
libtiff
LOCAL_MODULE:= tiffinfo
include $(BUILD_EXECUTABLE)
================================================
FILE: src/main/jni/tiff/COPYRIGHT
================================================
Copyright (c) 1988-1997 Sam Leffler
Copyright (c) 1991-1997 Silicon Graphics, Inc.
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee, provided
that (i) the above copyright notices and this permission notice appear in
all copies of the software and related documentation, and (ii) the names of
Sam Leffler and Silicon Graphics may not be used in any advertising or
publicity relating to the software without the specific, prior written
permission of Sam Leffler and Silicon Graphics.
THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.
================================================
FILE: src/main/jni/tiff/ChangeLog
================================================
2009-11-04 Bob Friesenhahn
* libtiff 3.9.2 released.
2009-11-03 Bob Friesenhahn
* tools/tiffcrop.c: Updated tiffcrop from Richard Nolde. This
version has undergone substantial testing with arbitrary sample
bit depths. Also eliminates GCC compilation warnings.
2009-11-02 Bob Friesenhahn
* port/libport.h: Added header file for porting prototypes and
extern declarations.
2009-10-31 Bob Friesenhahn
* libtiff/tif_dirwrite.c (TIFFWriteAnyArray): Add missing break
statement so writing an array of TIFF_DOUBLE works.
2009-10-29 Bob Friesenhahn
* libtiff/tif_dirread.c: Eliminate GCC "dereferencing type-punned
pointer" warnings.
2009-10-28 Bob Friesenhahn
* html/tools.html: Add manual page links, and a summary
description of tiffcrop.
2009-10-07 Bob Friesenhahn
* configure.ac: x86_64 should use the same fill order as i386.
2009-09-24 Bob Friesenhahn
* tools/tiffcrop.c, man/tiffcrop.1: New tiffcrop from Richard
Nolde. Major updates to add significant functionality for reading
and writing tile based images with bit depths not a multiple of 8
which cannot be handled by tiffcp.
2009-09-03 Bob Friesenhahn
* libtiff/tif_ojpeg.c (OJPEGWriteHeaderInfo): IJG JPEG 7 needs
do_fancy_upsampling=FALSE in order to read raw data. Resolves
"Bug 2090 - OJPEG crash with libjpeg v7".
http://bugzilla.maptools.org/show_bug.cgi?id=2090
2009-08-30 Bob Friesenhahn
* contrib/iptcutil/iptcutil.c,
libtiff/tif_getimage.c,libtiff/tif_jpeg.c,libtiff/tif_ojpeg.c,tools/tiffcrop.c,tools/tiffgt.c:
Applied patch from Oden Eriksson to allow building with GCC using
the "-Wformat -Werror=format-security" flags.
2009-08-28 Bob Friesenhahn
* libtiff 3.9.1 released.
2009-08-28 Frank Warmerdam
* libtiff/tif_dirwrite.c: Back out changes from 2007-11-22 that
resulted in the final strip not being written in some circumstances.
http://bugzilla.maptools.org/show_bug.cgi?id=2088
2009-08-27 Bob Friesenhahn
* libtiff/tif_write.c (TIFFAppendToStrip): Remove cast which
caused libtiff to output a wrong last strip with byte-count and
strip-offset of zero. This cast was added on the day of the 3.9.0
release.
* libtiff/tif_config.vc.h: tiffiop.h needs the TIFF_INT64_T and
TIFF_UINT64_T defines in order to compile. Copy existing
definitions from tiffconf.vc.h.
2009-08-21 Bob Friesenhahn
* test/Makefile.am (AUTOMAKE_OPTIONS): Colorized tests was not
actually activated since it needed to be enabled in this
Makefile.am. Also activated parallel-tests mode since it offers
useful features such as per-test .log files and a summary test
report .log file.
2009-08-20 Bob Friesenhahn
* libtiff 3.9.0 released.
* libtiff/tif_print.c (TIFFPrintDirectory): Applied patch for "tag
error may cause segfault in tif_print.c."
http://bugzilla.maptools.org/show_bug.cgi?id=1896
* tools/{rgb2ycbcr.c, tiff2rgba.c}: Applied patch for
CVE-2009-2347 libtiff: integer overflows in various inter-color
space conversion tools.
http://bugzilla.maptools.org/show_bug.cgi?id=2079
* configure.ac: Updated autotools. Autoconf 2.64, Automake 1.11,
libtool 2.2.6. Enabled support for silent build rules
(--enable-silent-rules or 'make V=0') and colorized tests.
2009-06-30 Frank Warmerdam
* libtiff/tif_luv.c: correct return codes from encoderow to be
1 on success instead of zero.
http://bugzilla.maptools.org/show_bug.cgi?id=2069
2009-06-22 Frank Warmerdam
* libtiff/tif_lzw.c: Fix buffer underflow bug.
http://bugzilla.maptools.org/show_bug.cgi?id=2065
2009-06-03 Frank Warmerdam
* libtiff/tif_write.c: do not override the planar configuration to be
contig for one sample files if planar configuration is already set.
http://bugzilla.maptools.org/show_bug.cgi?id=2057
2009-02-12 Frank Warmerdam
* libtiff/tif_luv.c: Fix handling of tiled logluv images.
http://bugzilla.maptools.org/show_bug.cgi?id=2005
2009-01-23 Frank Warmerdam
* libtiff/tif_predict.c: Add support for 32bit integer horz. predictors.
http://bugzilla.maptools.org/show_bug.cgi?id=1911
2009-01-20 Frank Warmerdam
* tools/tiffsplit.c: fix sampleformat to be shortv instead of longv.
2009-01-12 Bob Friesenhahn
* tools/tiff2ps.c: Remove spurious message printed to stderr.
2009-01-11 Bob Friesenhahn
* tools/tiff2ps.c: Incorporated significant functionality update
from Richard Nolde. In particular, support for rotating the image
by 90, 180, 270, and 'auto' has been added.
* tools/tiffcrop.c: Incorporated significant functionality update
from Richard Nolde.
2009-01-06 Bob Friesenhahn
* libtiff/tiffiop.h: Add private type declarations for int64, and
uint64 so that bundled utilities (like tiffcrop) can use it when
necessary.
2009-01-01 Bob Friesenhahn
* configure.ac: Updated to test for 64-bit types. This version of
the library does not require a 64-bit type, but tiffcrop needs it.
2008-12-31 Bob Friesenhahn
* Update to use current FSF autotools versions.
* libtiff/tiffio.h: GCC will now validate format specifications
for TIFFError(), TIFFErrorExt(), TIFFWarning(), and
TIFFWarningExt() in order to reveal bugs. Cleaned up resulting
warnings throughout for 32 bit build only.
2008-12-31 Frank Warmerdam
* tools/tiffcrop.c, man/tiffcrop.1: A major update from Richard
Nolde.
2008-12-21 Frank Warmerdam
* libtiff/tif_jpeg.c: Avoid errors if the application writes a full
strip for the last partial strip in a jpeg compressed file.
http://bugzilla.maptools.org/show_bug.cgi?id=1981
2008-12-21 Frank Warmerdam
* libtiff/tif_getimage.c, tiffio.h: More ABI corrections.
Removed SubsamplingHor/Ver from TIFFRGBAImage structure.
http://bugzilla.maptools.org/show_bug.cgi?id=1980
2008-12-18 Frank Warmerdam
* libtiff/tif_getimage.c,tiffio.h: removed all use of UaToAa and
Bitmap16to8 arrays in TIFFRGBAImage structure to restore ABI
compatability. These were just an attempt to speed up processing
with precalculated tables.
http://bugzilla.maptools.org/show_bug.cgi?id=1979
* libtiff/tif_codec.c: Avoid printing c->name if it does not exist.
2008-10-21 Andrey Kiselev
* libtiff/tif_jbig.c: Support the JBIG-KIT 2.0 (compatibility with
the older versions retained).
2008-09-05 Andrey Kiselev
* tools/tiffsplit.c: Use dynamically allocated array instead of static
when constructing output file names.
2008-09-03 Andrey Kiselev
* tools/tiffsplit.c: Get rid of unsafe strcpy()/strcat() calls when
doing the filename/path construction.
* tools/tiff2pdf.c: More appropriate format string in
t2p_write_pdf_string(); avoid signed/unsigned mismatch.
* libtiff/tif_lzw.c: Properly zero out the codetable. As per bug
http://bugzilla.maptools.org/show_bug.cgi?id=1929
* libtiff/tif_lzw.c: Properly zero out the string table. Fixes
CVE-2008-2327 security issue.
2008-05-24 Frank Warmerdam
* tif_codec.c: Avoid NULL pointer dereferencing for exotic
compression codec codes.
* tif_dirread.c: zero tif->tif_dir after freeing the directory
in TIFFReadCustomDirectory(). I don't exactly remember why this
was important.
* tif_dirwrite.c: Fix potential memory leak writing large double
tags.
* tif_dirread.c: Fix unchecked malloc result.
2008-01-30 Andrey Kiselev
* tif_fax3.c: Make find0span() and find1span() non-inline to
make MSVC 6.0 compiler happy.
2007-11-26 Frank Warmerdam
* tif_fax3.c: fix leak of FAXCS state (per bug 1603).
2007-11-23 Andrey Kiselev
* configure.com, libtiff/tif_vms.c: Better OpenVMS support. Patches
from Alexey Chupahin.
2007-11-22 Frank Warmerdam
* tif_write.c: Rip out the fancy logic in TIFFAppendToStrip() for
establishing if an existing tile can be rewritten to the same location
by comparing the current size to all the other blocks in the same
directory. This is dangerous in many situations and can easily
corrupt a file. (observed in esoteric GDAL situation that's hard to
document). This change involves leaving the stripbytecount[] values
unaltered till TIFFAppendToStrip(). Now we only write a block back
to the same location it used to be at if the new data is the same
size or smaller - otherwise we move it to the end of file.
* tif_dirwrite.c: Try to avoid writing out a full readbuffer of tile
data when writing the directory just because we have BEENWRITING at
some point in the past. This was causing odd junk to be written out
in a tile of data when a single tile had an interleaving of reading
and writing with reading last. (highlighted by gdal
autotest/gcore/tif_write.py test 7.
* tif_predict.c: use working buffer in PredictorEncodeTile to avoid
modifying callers buffer.
http://trac.osgeo.org/gdal/ticket/1965
* tif_predict.c/h, tif_lzw.c, tif_zip.c: Improvements so that
predictor based encoding and decoding works in read-write update
mode properly.
http://trac.osgeo.org/gdal/ticket/1948
2007-10-05 Frank Warmerdam
* tools/tiff2pdf.c: Fixed setting of alpha value per report on list.
2007-09-13 Frank Warmerdam
* tif_dirinfo.c: _TIFFMergeFields() now only merges in field
definitions that are missing. Existing definitions are silently
ignored. (Bug #1585)
2007-07-18 Andrey Kiselev
* libtiff/{Makefile.am, Makefile.v}: Do not distribute tiffconf.h,
remove tif_config.h/tiffconf.h during cleaning. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1573
2007-07-13 Andrey Kiselev
* libtiff 3.9.0beta released.
2007-07-12 Andrey Kiselev
* tools/tiff2pdf.c: Added missed extern optind as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1567
2007-07-03 Andrey Kiselev
* tools/tiff2ps.c: Added support 16-bit images as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1566
Patch from William Bader.
* tools/tiff2pdf.c: Fix for TIFFTAG_JPEGTABLES tag fetching and
significant upgrade of the whole utility as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1560
Now we don't need tiffiop.h in tiff2pdf anymore and will open output
PDF file using TIFFClientOpen() machinery as it is implemented
by Leon Bottou.
2007-06-29 Bob Friesenhahn
* libtiff/tif_dirinfo.c (_TIFFFindFieldInfo): Don't attempt to
bsearch() on a NULL fieldinfo list.
(_TIFFFindFieldInfoByName): Don't attempt to
lfind() on a NULL fieldinfo list.
2007-05-01 Andrey Kiselev
* libtiff/tif_dirwrite.c: Fixed problem introduced with a fix for a
byte swapping issue
http://bugzilla.remotesensing.org/show_bug.cgi?id=1363
As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1550
2007-04-27 Andrey Kiselev
* tools/tiff2pdf.c: Check the tmpfile() return status as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=154
2007-04-07 Andrey Kiselev
* libtiff/{tif_dir.h, tif_dirread.c, tif_dirinfo.c, tif_jpeg.c,
tif_fax3.c, tif_jbig.c, tif_luv.c, tif_ojpeg.c, tif_pixarlog.c,
tif_predict.c, tif_zip.c}: Finally fix bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1274
by introducing _TIFFMergeFieldInfo() returning integer error status
instead of void in case of problems with field merging (e.g., if the
field with such a tag already registered). TIFFMergeFieldInfo() in
public API remains void. Use _TIFFMergeFieldInfo() everywhere and
check returned value.
2007-04-07 Frank Warmerdam
* contrib/addtiffo/tif_overview.c: Fix problems with odd sized output
blocks in TIFF_DownSample_Subsampled() (bug 1542).
2007-04-06 Frank Warmerdam
* libtiff/tif_jpeg.c: Changed JPEGInitializeLibJPEG() so that it
will convert from decompressor to compressor or compress to decompress
if required by the force arguments. This works around a problem in
where the JPEGFixupTestSubsampling() may cause a decompressor to
be setup on a directory when later a compressor is required with the
force flag set. Occurs with the addtiffo program for instance.
2007-04-06 Andrey Kiselev
* libtiff/tif_dirwrite.c: Fixed swapping of byte arrays stored
in-place in tag offsets as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1363
* tools/tiffcrop.c, man/tiffcrop.1: Significant update in
functionality from Richard Nolde. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1525
2007-03-28 Frank Warmerdam
* libtiff/tif_fax3.c: "inline static" -> "static inline" for IRIC CC.
2007-03-07 Joris Van Damme
* libtiff/tif_getimage.c: workaround for 'Fractional scanline' error reading
OJPEG images with rowsperstrip that is not a multiple of vertical subsampling
factor. This bug is mentioned in:
http://bugzilla.remotesensing.org/show_bug.cgi?id=1390
http://www.asmail.be/msg0054766825.html
2007-03-07 Joris Van Damme
* libtiff/tif_win32.c: made inclusion of windows.h unconditional
* libtiff/tif_win32.c: replaced preprocessor indication for consiously
unused arguments by standard C indication for the same
2007-02-27 Andrey Kiselev
* libtiff/tif_dirread.c: Use uint32 type instead of tsize_t in byte
counters in TIFFFetchData(). Should finally fix the issue
http://bugzilla.remotesensing.org/show_bug.cgi?id=890
2007-02-24 Andrey Kiselev
* tools/tiffset.c: Properly handle tags with TIFF_VARIABLE writecount.
As per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1350
* libtiff/tif_dirread.c: Added special function to handle
SubjectDistance EXIF tag as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1362
* tools/tiff2pdf.c: Do not assume inches when the resolution units
do not specified. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1366
* tools/{tiffcp.c, tiffcrop.c}: Do not change RowsPerStrip value if
it was set as infinite. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1368
* tools/tiffcrop.c, man/tiffcrop.1: New tiffcrop utility contributed
by Richard Nolde. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1383
2007-02-22 Andrey Kiselev
* libtiff/tif_dir.c: Workaround for incorrect TIFFs with
ExtraSamples == 999 produced by Corel Draw. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1490
* libtiff/{tif_dirread.c, tif_read.c}: Type of the byte counters
changed from tsize_t to uint32 to be able to work with data arrays
larger than 2GB. Fixes bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=890
Idea submitted by Matt Hancher.
2007-01-31 Andrey Kiselev
* tools/tif2rgba.c: This utility does not work properly on big-endian
architectures. It was fixed including the bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1149
2007-01-15 Mateusz Loskot
* Submitted libtiff port for Windows CE platform
* libtiff/tif_config.wince.h: Added configuration header for WinCE.
* libtiff/tiffconf.wince.h: Ported old configuration header for WinCE.
* libtiff/tif_wince.c: Added WinCE-specific implementation of some
functons from tif_win32.c.
* libtiff/tif_win32.c: Disabled some functions already reimplemented in tif_wince.c.
* libtiff/tiffiop.h, port/lfind.c: Added conditional include of some
standard header files for Windows CE build.
* tools/tiffinfoce.c: Ported tiffinfo utility for Windows CE.
2006-11-19 Frank Warmerdam
* libtiff/tif_write.c: TIFFAppendToStrip() - clear sorted flag if
we move a strip.
http://bugzilla.remotesensing.org/show_bug.cgi?id=1359
2006-10-13 Andrey Kiselev
* libtiff/tif_dir.c: More fixes for vulnerabilities, reported
in Gentoo bug ():
http://bugs.gentoo.org/show_bug.cgi?id=142383
* libtiff/contrib/dbs/xtiff/xtiff.c: Make xtiff utility compilable.
Though it is still far from the state of being working and useful.
2006-10-12 Andrey Kiselev
* libtiff/tif_fax3.c: Save the state of printdir codec dependent
method.
* libtiff/tif_jpeg.c: Save the state of printdir codec dependent method
as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1273
* libtiff/tif_win32.c: Fixed problem with offset value manipulation
as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1322
* libtiff/{tif_read.c, tif_jpeg.c, tif_dir.c}: More fixes for
vulnerabilities, reported in Gentoo bug ():
http://bugs.gentoo.org/show_bug.cgi?id=142383
2006-09-28 Andrey Kiselev
* libtiff/{tif_fax3.c, tif_next.c, tif_pixarlog.c}: Fixed multiple
vulnerabilities, as per Gentoo bug ():
http://bugs.gentoo.org/show_bug.cgi?id=142383
2006-09-27 Frank Warmerdam
* libtiff/tif_lzw.c, libtiff/tif_zip.c: Fixed problems with mixing
encoding and decoding on the same read-write TIFF handle. The LZW
code can now maintain encode and decode state at the same time. The
ZIP code will switch back and forth as needed.
http://bugzilla.remotesensing.org/show_bug.cgi?id=757
2006-09-20 Frank Warmerdam
* libtiff: Rename config.h.vc and tif_config.h.vc to config.vc.h and
tif_config.vc.h for easier identification by folks using an IDE.
2006-07-25 Frank Warmerdam
* tif_msdos.c: Avoid handle leak for failed opens. c/o Thierry Pierron
2006-07-19 Frank Warmerdam
* tif_dirwrite.c: take care not to flush out buffer of strip/tile
data in _TIFFWriteDirectory if TIFF_BEENWRITING not set. Relates
to bug report by Peng Gao with black strip at bottom of images.
2006-07-12 Frank Warmerdam
* tif_dirwrite.c: make sure to use uint32 for wordcount in
TIFFWriteNormanTag if writecount is VARIABLE2 for ASCII fields.
It already seems to have been done for other field types. Needed
for "tiffset" on files with geotiff ascii text.
2006-07-04 Bob Friesenhahn
* {configure.ac, libtiff/tif_config.h.vc, libtiff/tif_jbig.c}
(JBIGDecode): jbg_newlen is not available in older JBIG-KIT and
its use does not appear to be required, so use it only when it is
available.
2006-06-24 Andrey Kiselev
* libtiff/tif_dirinfo.c: Added missed EXIF tag ColorSpace (40961).
* libtiff/tif_dirread.c: Move IFD fetching code in the separate
function TIFFFetchDirectory() avoiding code duplication in
TIFFReadDirectory() and TIFFReadCustomDirectory().
2006-06-19 Frank Warmerdam
* tools/tiff2pdf.c: Fix handling of -q values.
http://bugzilla.remotesensing.org/show_bug.cgi?id=587
2006-06-17 Frank Warmerdam
* tif_readdir.c: Added case in EstimateStripByteCounts() for tiled
files. Modified TIFFReadDirectory() to not invoke
EstimateStripByteCounts() for case where entry 0 and 1 are unequal
but one of them is zero.
http://bugzilla.remotesensing.org/show_bug.cgi?id=1204
2006-06-08 Andrey Kiselev
* libtiff/{tif_open.c, tif_dirread.c, tiffiop.h}: Move IFD looping
checking code in the separate function TIFFCheckDirOffset().
* libtiff/tif_aux.c: Added _TIFFCheckRealloc() function.
* tools/tiffcmp.c: Fixed floating point comparison logic as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1191
* libtiff/tif_fax3.c: Fixed problems in fax decoder as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1194
* tools/tiff2pdf.c: Fixed buffer overflow condition in
t2p_write_pdf_string() as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1196
2006-06-07 Andrey Kiselev
* {configure, configure.ac, libtiff/tif_jbig.c, tools/tiffcp.c}: Added
support for JBIG compression scheme (34661 code) contributed by Lee
Howard. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=896
* configure, configure.ac: OJPEG support enabled by default.
* contrib/ojpeg/: Removed. New OJPEG support does not need this patch.
2006-06-03 Bob Friesenhahn
* libtiff/{tif_dirinfo.c, tif_print.c} : Fix crash in
TIFFPrintDirectory(). Joris Van Damme authored the fix.
2006-04-21 Andrey Kiselev
* tools/tiff2pdf.c: Unified line ending characters (always use '\n')
as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1163
* README.vms, Makefile.am, configure.com, libtiff/{Makefile.am,
tif_config.h-vms, tif_stream.cxx, tif_vms.c, tiffconf.h-vms}:
Added support for OpenVMS by Alexey Chupahin, elvis_75@mail.ru.
2006-04-20 Andrey Kiselev
* tools/{fax2ps.c, fax2tiff.c, ppm2tiff.c, ras2tiff.c, tiff2pdf.c}:
Properly set the binary mode for stdin stream as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1141
* man/{bmp2tiff.1, fax2ps.1, fax2tiff.1, gif2tiff.1, ras2tiff.1,
raw2tiff.1, rgb2ycbcr.1, sgi2tiff.1, tiff2bw.1, tiff2pdf.1, tiff2ps.1,
tiff2rgba.1, tiffcmp.1, tiffcp.1, tiffdither.1, tiffdump.1, tiffgt.1,
tiffset.1}: Improvements in page formatting as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1140
* html/tools.html, html/man/Makefile.am, tools/tiff2pdf.c: Fixed
typos as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1139
2006-04-18 Frank Warmerdam
* nmake.opt: use /EHsc for VS2005 compatibility. Also define
_CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005.
2006-04-12 Joris Van Damme
* libtiff/tif_getimage.c: Added support for planarconfig separate
non-subsampled YCbCr (i.e. separate YCbCr with subsampling [1,1])
2006-04-11 Joris Van Damme
* libtiff/tif_getimage.c: Revision of all RGB(A) put routines
- Conversion of unassociated alpha to associated alpha now done with
more performant LUT, and calculation more correct
- Conversion of 16bit data to 8bit data now done with
more performant LUT, and calculation more correct
- Bugfix of handling of 16bit RGB with unassociated alpha
2006-04-11 Joris Van Damme
* libtiff/tif_getimage.c:
- When there is no alpha, gtTileSeparate and gtStripSeparate allocated
buffer for alpha strile and filled it, only to never read it back.
Removed allocation and fill.
- Minor rename of vars in gtTileSeparate and gtStripSeparate
anticipating planned functionality extension
2006-04-08 Joris Van Damme
* libtiff/tif_getimage.c: renamed pickTileContigCase to PickContigCase
and pickTileSeparateCase to PickSeparateCase as both work on strips as
well
* libtiff/tif_getimage.c: moved img->get selection from
TIFFRGBAImageBegin into PickContigCase and PickSeparateCase to create
logical hook for planned functionality extension
2006-04-08 Joris Van Damme
* libtiff/tif_ojpeg.c: resolved memory leak that was a consequence
of inappropriate use of jpeg_abort instead of jpeg_destroy
2006-04-07 Joris Van Damme
* libtiff/tif_getimage.c: replaced usage of TIFFScanlineSize in
gtStripContig with TIFFNewScanlineSize so as to fix buggy behaviour
on subsampled images - this ought to get sorted when we feel brave
enough to replace TIFFScanlineSize alltogether
* libtiff/tif_ojpeg.c: fixed bug in OJPEGReadSkip
2006-04-04 Joris Van Damme
* libtiff/tiffio.h: added new type tstrile_t
* libtiff/tif_dir.h: changed types of td_stripsperimage and td_nstrips
to new tstrile_t, types of td_stripoffset and td_stripbytecount to
toff_t*
* libtiff/tif_ojpeg.c: totally new implementation
* libtiff/tif_dirread.c: added several hacks to suit new support of
OJPEG
* libtiff/tif_getimage.c: removed TIFFTAG_JPEGCOLORMODE handling
of OJPEG images in favor of tif_getimage.c native handling of
YCbCr and desubsampling
2006-03-29 Frank Warmerdam
* libtiff/tif_jpeg.c: JPEGVSetField() so that altering the photometric
interpretation causes the "upsampled" flag to be recomputed. Fixes
peculiar bug where photometric flag had to be set before jpegcolormode
flag.
2006-03-25 Joris Van Damme
* libtiff/tif_jpeg.c: strip size related bugfix in encode raw
* libtiff/tif_strip.c: temporarilly added two new versions of
TIFFScanlineSize
- TIFFNewScanlineSize: proposed new version, after all related
issues and side-effects are sorted out
- TIFFOldScanlineSize: old version, from prior to 2006-03-21 change
This needs further sorting out.
2006-03-25 Joris Van Damme
* contrib/addtiffo/tif_ovrcache.c: bugfix to correctly pass size
of last truncated strip data to TIFFWriteEncodedStrip
2006-03-25 Joris Van Damme
* libtiff/{tif_jpeg.c, tif_strip.c}: bugfix of tif_jpeg decode raw
2006-03-25 Joris Van Damme
* libtiff/tif_getimage.c: bugfix/rewrite of putcontig8bitYCbCr22tile
* libtiff/tif_getimage.c: added putcontig8bitYCbCr12tile
* libtiff/tif_read.c: added support for new TIFF_NOREADRAW flag to
prepare the path for new tif_ojpeg.c
2006-03-23 Andrey Kiselev
* libtiff 3.8.2 released.
* tools/Makefile.am: Use runtime paths linker flags when rpath
option enabled.
2006-03-21 Andrey Kiselev
* libtiff/libtiff.def: Added missed exports as per bug
http://bugzilla.remotesensing.org/attachment.cgi?id=337
* contrib/addtiffo/Makefile.vc, libtiff/Makefile.vc, port/Makefile.vc,
tools/Makefile.vc: Makefiles improvements as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1128
* nmake.opt libtiff/{tif_config.h.vc, tif_unix.c, tiffio.h},
tools/{fax2ps.c, fax2tiff.c, tiff2pdf.c}: Fixed win32 I/O functions
usage as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1127
* libtiff/tif_strip.c: Take subsampling in account when calculating
TIFFScanlineSize().
* tools/tiffcp.c: Do not set RowsPerStrip bigger than image length.
2006-03-17 Andrey Kiselev
* tools/fax2tiff.c: Fixed wrong TIFFerror() invocations as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1125
* tools/fax2ps.c: Fixed reading the input stream from stdin as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1124
2006-03-16 Andrey Kiselev
* libtiff/tiffiop.h: Added decalration for
_TIFFSetDefaultCompressionState().
* libtiff/{tif_jpeg.c, tif_fax3.c, tif_zip.c, tif_pixarlog.c,
tif_lzw.c, tif_luv.c}: Use _TIFFSetDefaultCompressionState() in all
codec cleanup methods. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1120
2006-03-15 Andrey Kiselev
* libtiff/tif_jpeg.c: Do not cleanup codec state in TIFFInitJPEG(). As
per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1119
* tools/raw2tiff.c: Do not set RowsPerStrip larger than ImageLength.
As per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1110
* libtiff/tiffiop.h: dblparam_t typedef removed; GLOBALDATA macro
removed; move here the STRIP_SIZE_DEFAULT macro definition.
* libtiff/{tif_dirread.c, tif_strip.c}: Removed STRIP_SIZE_DEFAULT
macro definition.
* libtiff/tif_dir.c: Use double type instead of dblparam_t.
2006-03-14 Andrey Kiselev
* libtiff/tif_dirread.c: Do not check the PlanarConfig tag presence
in TIFFReadDirectory, because it is always set at the start of
function and we allow TIFFs without that tag set.
2005-03-13 Andrey Kiselev
* libtiff 3.8.1 released.
2006-03-07 Andrey Kiselev
* libtiff/tif_dirread.c: Fixed error reporting in TIFFFetchAnyArray()
function as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
* libtiff/tif_dirread.c: More wise check for integer overflow
condition as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
* libtiff/{tif_jpeg.c, tif_pixarlog.c, tif_fax3.c, tif_zip.c}:
Properly restore setfield/getfield methods in cleanup functions. As
per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
2006-03-03 Andrey Kiselev
* libtiff/{tif_predict.c, tif_predict.h}: Added new function
TIFFPredictorCleanup() to restore parent decode/encode/field methods.
* libtiff/{tif_lzw.c, tif_pixarlog.c, tif_zip.c}: Use
TIFFPredictorCleanup() in codec cleanup methods. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
* libtiff/tif_dirread.c: Fixed integer overflow condition in
TIFFFetchData() function. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
2006-03-01 Andrey Kiselev
* libtiff/tif_ojpeg.c: Set the ReferenceBlackWhite with the
TIFFSetField() method, not directly. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1043
* tools/ppm2tiff.c: Added support for PBM files as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1044
2006-02-27 Andrey Kiselev
* libtiff/tif_write.c: Small code rearrangement in TIFFWriteScanline()
to avoid crash as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1081.
2006-02-26 Andrey Kiselev
* tools/tiff2pdf.c: Functions t2p_sample_rgbaa_to_rgb() and
t2p_sample_rgba_to_rgb() was used in place of each other, that was
resulted in problems with RGBA images with associated alpha.
As per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1097
2006-02-23 Andrey Kiselev
* libtiff/tif_dirwrite.c: Properly write TIFFTAG_DOTRANGE tag as per
bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1088.
* libtiff/tif_print.c: Properly read TIFFTAG_PAGENUMBER,
TIFFTAG_HALFTONEHINTS, TIFFTAG_YCBCRSUBSAMPLING and TIFFTAG_DOTRANGE
tags as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1088.
* tools/tiff2ps.c: Properly scale all the pages when converting
multipage TIFF with /width/height/center options set. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1080
2006-02-15 Andrey Kiselev
* tools/tiff2pdf.c: Do not create output file until all option checks
will be done. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1072
* tools/bmp2tiff.c: Added ability to create multipage TIFFs from the
list of input files as per bug:
http://bugzilla.remotesensing.org/show_bug.cgi?id=1077
2006-02-09 Andrey Kiselev
* libtiff/tif_tile.c: Fix error reporting in TIFFCheckTile() as per
bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1063.
* tools/tiffgt.c: Avoid crashing in case of image unsupported by
TIFFRGBAImage interface.
* libtiff/tif_color.c: Avoid overflow in case of wrong input as per
bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1065.
2006-02-07 Frank Warmerdam
* tools/tiff2pdf.c: Fixed support for non-YCbCr encoded JPEG
compressed TIFF files, per submission from Dan Cobra.
2006-02-07 Andrey Kiselev
* libtiff/{tif_dirread.c, tif_packbits.c, tif_win32.c}: Properly
cast values to avoid warnings. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1033.
* libtiff/tif_dirinfo.c: Use TIFF_NOTYPE instead of 0 when
appropriate. As per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1033.
* libtiff/tif_aux.c: Fixed type of temporary variable in
_TIFFCheckMalloc() as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1033.
2006-02-06 Andrey Kiselev
* libtiff/tif_aux.c: Return static array when fetching default
YCbCrCoefficients (another problem, reported a the
http://bugzilla.remotesensing.org/show_bug.cgi?id=1029 entry).
2006-02-03 Andrey Kiselev
* libtiff/tif_dir.c: Special handling for PageNumber, HalftoneHints,
YCbCrSubsampling and DotRange tags as per bugs
http://bugzilla.remotesensing.org/show_bug.cgi?id=1029
http://bugzilla.remotesensing.org/show_bug.cgi?id=1034
* libtiff/tif_dirread.c: Use _TIFFGetExifFieldInfo() instead of
_TIFFGetFieldInfo() in TIFFReadEXIFDirectory() call as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1026.
2006-01-23 Andrey Kiselev
* libtool related stuff updated from the 2.1a branch.
2006-01-11 Frank Warmerdam
* tools/bmp2tiff,pal2rgb,ppm2tiff,ras2tiff,raw2tiff,sgi2tiff,
tiff2bw,tiffcp: Fixed jpeg option processing so -c jpeg:r:50 works
properly as per bug:
http://bugzilla.remotesensing.org/show_bug.cgi?id=1025
2006-01-09 Bob Friesenhahn
* configure.ac: Fix with_default_strip_size comparison as reported
by Norihiko Murase.
2006-01-08 Bob Friesenhahn
* test/Makefile.am (LIBTIFF): Due to linking against libtiff
incorrectly, tests were not actually testing the uninstalled
libtiff. Now they are.
2006-01-04 Andrey Kiselev
* libtiff/tif_dirinfo.c: Change definitions for TIFFTAG_ICCPROFILE,
TIFFTAG_PHOTOSHOP, TIFFTAG_RICHTIFFIPTC, TIFFTAG_XMLPACKET: readcount
should be uint32 value.
2006-01-02 Bob Friesenhahn
* html/man/Makefile.am (htmldoc): Fix htmldoc rule so that it can
be used if build directory is not the same as source directory.
* man/{TIFFGetField.3tiff, TIFFSetField.3tiff}: Documented
TIFFTAG_PHOTOSHOP, TIFFTAG_RICHTIFFIPTC, and TIFFTAG_XMLPACKET,
and re-sorted tag names in alphabetical order.
2005-12-29 Andrey Kiselev
* libtiff 3.8.0 released.
2005-12-28 Bob Friesenhahn
* tools/bmp2tiff.c (main): Fixed warning regarding returning
inconsistent types from a condition.
* tools/tiffcmp.c (CheckLongTag): Eliminate warning due to printf
format.
* tools/bmp2tiff.c: Reduce compilation warnings on big-endian CPUs.
2005-12-28 Joris Van Damme
* html/{index.html, support.hml, libtiff.html}: Cleaned up HTML
2005-12-27 Andrey Kiselev
* libtiff/tiffio.h: Added VC_EXTRALEAN definition before including
windows.h, to reduce the compile time.
2005-12-26 Bob Friesenhahn
* libtiff/tif_jpeg.c: Improve compilation under MinGW.
2005-12-26 Andrey Kiselev
* libtiff/{tif_dir.c, tif_dir.h, tif_dirread.c, tif_dirinfo.c}:
tiffFieldInfo and exifFieldInfo arrays definitions moved back to
tif_dirinfo.c; added _TIFFGetFieldInfo() and _TIFFGetExifFieldInfo()
private functions to retrieve FieldInfo arrays.
2005-12-24 Bob Friesenhahn
* html/build.html: Added some additional instructions for when
building using MSVC under Windows. Also fixed two HTML syntax
errors and used HTML Tidy to tidy up the HTML syntax and
formatting.
2005-12-24 Andrey Kiselev
* libtiff/{tif_aux.c, tif_dir.c, tif_dir.h, tif_dirwrite.c,
tif_print.c, tif_getimage.c}: Make InkSet, NumberOfInks, DotRange and
StoNits tags custom.
2005-12-23 Andrey Kiselev
* libtiff/{tif_aux.c, tif_dir.c, tif_dir.h, tif_print.c}: Make
WhitePoint tag custom.
* libtiff/{tif_dir.h, tiff.h}: More EXIF tags added.
2005-12-23 Joris Van Damme
* libtiff/tiffio.h: fixed typo that potentially resulted in
redefininition of USE_WIN32_FILEIO
* libtiff/*: Added more 'dual-mode' error handling: Done TIFFWarning
calls in core LibTiff.
2005-12-21 Andrey Kiselev
* libtiff/{tif_dir.c, tif_dir.h, tif_print.c}: Make RichTIFFIPTC,
Photoshop and ICCProfile tags custom.
2005-12-21 Joris Van Damme
* libtiff/*, contrib/*: Added 'dual-mode' error handling, enabling
newer code to get context indicator in error handler and still
remain compatible with older code: Done TIFFError calls everywhere
except in tools
2005-12-20 Andrey Kiselev
* tools/tiffcp.c: Added many error reporting messages; fixed integer
overflow as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=789
2005-12-16 Frank Warmerdam
* contrib/addtiffo/*: Major upgrade by Joris to support subsampled
YCbCr images in jpeg compressed TIFF files.
2005-12-14 Andrey Kiselev