├── src ├── test │ ├── resources │ │ ├── test │ │ │ ├── temp │ │ │ │ └── dummy.txt │ │ │ ├── apgn │ │ │ │ ├── readme.txt │ │ │ │ ├── 025_apng.png │ │ │ │ ├── clock_apng.png │ │ │ │ ├── bouncing_apng.png │ │ │ │ ├── loading_apng.png │ │ │ │ ├── withstill_apng.png │ │ │ │ ├── keepandnoblend.a.png │ │ │ │ ├── apngf_000_clock_apng.png │ │ │ │ ├── apngf_012_clock_apng.png │ │ │ │ ├── apngf_013_clock_apng.png │ │ │ │ └── apngf_014_clock_apng.png │ │ │ ├── testg1.png │ │ │ ├── testg2.png │ │ │ ├── stripes.png │ │ │ ├── stripes2.png │ │ │ ├── stripes5.png │ │ │ ├── testg1i.png │ │ │ ├── testg1p.png │ │ │ ├── testg2i.png │ │ │ ├── testrgb3.png │ │ │ ├── stripe_none.png │ │ │ ├── bad_testg1crc.png │ │ │ ├── bad_truncated.png │ │ │ ├── stripe_none64.png │ │ │ ├── stripes0idat.png │ │ │ ├── stripes_rgb8.png │ │ │ ├── stripesoptim.png │ │ │ ├── bad_missingidat.png │ │ │ ├── bad_testrgb3_noend.png │ │ │ ├── bad_stripes_extratrailing.png │ │ │ ├── bad_stripes_rgb8_truncatedidat.png │ │ │ └── readme.txt │ │ ├── colormodels │ │ │ ├── 08.png │ │ │ ├── 16.png │ │ │ ├── 01g.png │ │ │ ├── 01p.png │ │ │ ├── 02g.png │ │ │ ├── 02p.png │ │ │ ├── 04g.png │ │ │ ├── 04gt.png │ │ │ ├── 04p.png │ │ │ ├── 04pt.png │ │ │ ├── 08a.png │ │ │ ├── 08ag.png │ │ │ ├── 08ax.png │ │ │ ├── 08g.png │ │ │ ├── 08p.png │ │ │ ├── 08pt.png │ │ │ ├── 08t.png │ │ │ ├── 16a.png │ │ │ ├── 16ag.png │ │ │ ├── 16g.png │ │ │ ├── 16gt.png │ │ │ ├── 16t.png │ │ │ ├── 08ax2.png │ │ │ ├── 08axnoa.png │ │ │ └── readme.txt │ │ ├── grays │ │ │ ├── g08-srgb.png │ │ │ ├── g16-srgb.png │ │ │ ├── g08-gama1.png │ │ │ ├── g08-nosrgb.png │ │ │ ├── g16-gama1.png │ │ │ ├── g16-nosrgb.png │ │ │ ├── ga08-gama1.png │ │ │ ├── ga08-srgb.png │ │ │ ├── ga16-gama1.png │ │ │ ├── ga16-srgb.png │ │ │ ├── rgb08-srgb.png │ │ │ ├── rgb16-srgb.png │ │ │ ├── g08-gama2_2.png │ │ │ ├── g16-gama2_2.png │ │ │ ├── ga08-gama2_2.png │ │ │ ├── ga08-nosrgb.png │ │ │ ├── ga16-gama2_2.png │ │ │ ├── ga16-nosrgb.png │ │ │ ├── rgb08-gama1.png │ │ │ ├── rgb08-gama2_2.png │ │ │ ├── rgb08-nosrgb.png │ │ │ ├── rgb16-gama1.png │ │ │ ├── rgb16-gama2_2.png │ │ │ ├── rgb16-nosrgb.png │ │ │ ├── rgba08-gama1.png │ │ │ ├── rgba08-nosrgb.png │ │ │ ├── rgba08-srgb.png │ │ │ ├── rgba16-gama1.png │ │ │ ├── rgba16-nosrgb.png │ │ │ ├── rgba16-srgb.png │ │ │ ├── rgba08-gama2_2.png │ │ │ └── rgba16-gama2_2.png │ │ ├── misc │ │ │ ├── pngjclasses.odg │ │ │ ├── readme.txt │ │ │ ├── optipng.sh │ │ │ ├── ispng.pl │ │ │ └── mvn_notes.txt │ │ ├── testsuite1 │ │ │ ├── PngSuite.png │ │ │ ├── basi0g01.png │ │ │ ├── basi0g02.png │ │ │ ├── basi0g04.png │ │ │ ├── basi0g08.png │ │ │ ├── basi0g16.png │ │ │ ├── basi2c08.png │ │ │ ├── basi2c16.png │ │ │ ├── basi3p01.png │ │ │ ├── basi3p02.png │ │ │ ├── basi3p04.png │ │ │ ├── basi3p08.png │ │ │ ├── basi4a08.png │ │ │ ├── basi4a16.png │ │ │ ├── basi6a08.png │ │ │ ├── basi6a16.png │ │ │ ├── basn0g01.png │ │ │ ├── basn0g02.png │ │ │ ├── basn0g04.png │ │ │ ├── basn0g08.png │ │ │ ├── basn0g16.png │ │ │ ├── basn2c08.png │ │ │ ├── basn2c16.png │ │ │ ├── basn3p01.png │ │ │ ├── basn3p02.png │ │ │ ├── basn3p04.png │ │ │ ├── basn3p08.png │ │ │ ├── basn4a08.png │ │ │ ├── basn4a16.png │ │ │ ├── basn6a08.png │ │ │ ├── basn6a16.png │ │ │ ├── bgai4a08.png │ │ │ ├── bgai4a16.png │ │ │ ├── bgan6a08.png │ │ │ ├── bgan6a16.png │ │ │ ├── bgbn4a08.png │ │ │ ├── bggn4a16.png │ │ │ ├── bgwn6a08.png │ │ │ ├── bgyn6a16.png │ │ │ ├── ccwn2c08.png │ │ │ ├── ccwn3p08.png │ │ │ ├── cdfn2c08.png │ │ │ ├── cdhn2c08.png │ │ │ ├── cdsn2c08.png │ │ │ ├── cdun2c08.png │ │ │ ├── ch1n3p04.png │ │ │ ├── ch2n3p08.png │ │ │ ├── cm0n0g04.png │ │ │ ├── cm7n0g04.png │ │ │ ├── cm9n0g04.png │ │ │ ├── cs3n2c16.png │ │ │ ├── cs3n3p08.png │ │ │ ├── cs5n2c08.png │ │ │ ├── cs5n3p08.png │ │ │ ├── cs8n2c08.png │ │ │ ├── cs8n3p08.png │ │ │ ├── ct0n0g04.png │ │ │ ├── ct1n0g04.png │ │ │ ├── cten0g04.png │ │ │ ├── ctfn0g04.png │ │ │ ├── ctgn0g04.png │ │ │ ├── cthn0g04.png │ │ │ ├── ctjn0g04.png │ │ │ ├── ctzn0g04.png │ │ │ ├── f00n0g08.png │ │ │ ├── f00n2c08.png │ │ │ ├── f01n0g08.png │ │ │ ├── f01n2c08.png │ │ │ ├── f02n0g08.png │ │ │ ├── f02n2c08.png │ │ │ ├── f03n0g08.png │ │ │ ├── f03n2c08.png │ │ │ ├── f04n0g08.png │ │ │ ├── f04n2c08.png │ │ │ ├── f99n0g04.png │ │ │ ├── g03n0g16.png │ │ │ ├── g03n2c08.png │ │ │ ├── g03n3p04.png │ │ │ ├── g04n0g16.png │ │ │ ├── g04n2c08.png │ │ │ ├── g04n3p04.png │ │ │ ├── g05n0g16.png │ │ │ ├── g05n2c08.png │ │ │ ├── g05n3p04.png │ │ │ ├── g07n0g16.png │ │ │ ├── g07n2c08.png │ │ │ ├── g07n3p04.png │ │ │ ├── g10n0g16.png │ │ │ ├── g10n2c08.png │ │ │ ├── g10n3p04.png │ │ │ ├── g25n0g16.png │ │ │ ├── g25n2c08.png │ │ │ ├── g25n3p04.png │ │ │ ├── oi1n0g16.png │ │ │ ├── oi1n2c16.png │ │ │ ├── oi2n0g16.png │ │ │ ├── oi2n2c16.png │ │ │ ├── oi4n0g16.png │ │ │ ├── oi4n2c16.png │ │ │ ├── oi9n0g16.png │ │ │ ├── oi9n2c16.png │ │ │ ├── pp0n2c16.png │ │ │ ├── pp0n6a08.png │ │ │ ├── ps1n0g08.png │ │ │ ├── ps1n2c16.png │ │ │ ├── ps2n0g08.png │ │ │ ├── ps2n2c16.png │ │ │ ├── s01i3p01.png │ │ │ ├── s01n3p01.png │ │ │ ├── s02i3p01.png │ │ │ ├── s02n3p01.png │ │ │ ├── s03i3p01.png │ │ │ ├── s03n3p01.png │ │ │ ├── s04i3p01.png │ │ │ ├── s04n3p01.png │ │ │ ├── s05i3p02.png │ │ │ ├── s05n3p02.png │ │ │ ├── s06i3p02.png │ │ │ ├── s06n3p02.png │ │ │ ├── s07i3p02.png │ │ │ ├── s07n3p02.png │ │ │ ├── s08i3p02.png │ │ │ ├── s08n3p02.png │ │ │ ├── s09i3p02.png │ │ │ ├── s09n3p02.png │ │ │ ├── s32i3p04.png │ │ │ ├── s32n3p04.png │ │ │ ├── s33i3p04.png │ │ │ ├── s33n3p04.png │ │ │ ├── s34i3p04.png │ │ │ ├── s34n3p04.png │ │ │ ├── s35i3p04.png │ │ │ ├── s35n3p04.png │ │ │ ├── s36i3p04.png │ │ │ ├── s36n3p04.png │ │ │ ├── s37i3p04.png │ │ │ ├── s37n3p04.png │ │ │ ├── s38i3p04.png │ │ │ ├── s38n3p04.png │ │ │ ├── s39i3p04.png │ │ │ ├── s39n3p04.png │ │ │ ├── s40i3p04.png │ │ │ ├── s40n3p04.png │ │ │ ├── tbbn0g04.png │ │ │ ├── tbbn2c16.png │ │ │ ├── tbbn3p08.png │ │ │ ├── tbgn2c16.png │ │ │ ├── tbgn3p08.png │ │ │ ├── tbrn2c08.png │ │ │ ├── tbwn0g16.png │ │ │ ├── tbwn3p08.png │ │ │ ├── tbyn3p08.png │ │ │ ├── tp0n0g08.png │ │ │ ├── tp0n2c08.png │ │ │ ├── tp0n3p08.png │ │ │ ├── tp1n3p08.png │ │ │ ├── xbadidat.png │ │ │ ├── xc1n0g08.png │ │ │ ├── xc9n2c08.png │ │ │ ├── xcrn0g04.png │ │ │ ├── xcsn0g01.png │ │ │ ├── xd0n2c08.png │ │ │ ├── xd3n2c08.png │ │ │ ├── xd9n2c08.png │ │ │ ├── xdtn0g01.png │ │ │ ├── xhdn0g08.png │ │ │ ├── xlfn0g04.png │ │ │ ├── xs1n0g01.png │ │ │ ├── xs2n0g01.png │ │ │ ├── xs4n0g01.png │ │ │ ├── xs7n0g01.png │ │ │ ├── z00n2c08.png │ │ │ ├── z03n2c08.png │ │ │ ├── z06n2c08.png │ │ │ ├── z09n2c08.png │ │ │ ├── xbadidat2.png │ │ │ ├── basi0g01_ni.png │ │ │ ├── basi0g02_ni.png │ │ │ ├── basi0g04_ni.png │ │ │ ├── basi0g08_ni.png │ │ │ ├── basi0g16_ni.png │ │ │ ├── basi2c08_ni.png │ │ │ ├── basi2c16_ni.png │ │ │ ├── basi3p01_ni.png │ │ │ ├── basi3p02_ni.png │ │ │ ├── basi3p04_ni.png │ │ │ ├── basi3p08_ni.png │ │ │ ├── basi4a08_ni.png │ │ │ ├── basi4a16_ni.png │ │ │ ├── basi6a08_ni.png │ │ │ ├── basi6a16_ni.png │ │ │ ├── bgai4a08_ni.png │ │ │ ├── bgai4a16_ni.png │ │ │ ├── ccwn3p08_tc.png │ │ │ ├── ch2n3p08_tc.png │ │ │ ├── s01i3p01_ni.png │ │ │ ├── s02i3p01_ni.png │ │ │ ├── s03i3p01_ni.png │ │ │ ├── s04i3p01_ni.png │ │ │ ├── s05i3p02_ni.png │ │ │ ├── s06i3p02_ni.png │ │ │ ├── s07i3p02_ni.png │ │ │ ├── s08i3p02_ni.png │ │ │ ├── s09i3p02_ni.png │ │ │ ├── s32i3p04_ni.png │ │ │ ├── s33i3p04_ni.png │ │ │ ├── s34i3p04_ni.png │ │ │ ├── s35i3p04_ni.png │ │ │ ├── s36i3p04_ni.png │ │ │ ├── s37i3p04_ni.png │ │ │ ├── s38i3p04_ni.png │ │ │ ├── s39i3p04_ni.png │ │ │ ├── s40i3p04_ni.png │ │ │ ├── tbbn3p08_tc.png │ │ │ ├── z09n2c08_idats.png │ │ │ ├── PngSuite.LICENSE │ │ │ └── PngSuite.README │ │ ├── pngj-tests-token-readme.txt │ │ └── logging.properties │ └── java │ │ ├── readme.txt │ │ └── ar │ │ └── com │ │ └── hjg │ │ └── pngj │ │ ├── misc │ │ ├── IPngWriterFactory.java │ │ ├── MappedCounterInt.java │ │ ├── Pair.java │ │ └── NullOs.java │ │ ├── samples │ │ ├── package.html │ │ ├── SampleShowChunks.java │ │ ├── SampleReadEvenLines.java │ │ ├── SampleRemoveGama.java │ │ ├── SampleCreateStripes.java │ │ ├── SampleMirrorImage.java │ │ ├── SampleConvPalToTrueColor.java │ │ ├── SampleCreateOrangeGradient.java │ │ ├── CreateHuge.java │ │ ├── CreateVeryHuge.java │ │ ├── SampleImgDiff.java │ │ ├── SampleTileImage.java │ │ └── ChunkSeqReaderIdatRaw.java │ │ ├── test │ │ ├── ErrorHandlingTests.java │ │ ├── PngjTest.java │ │ ├── PngFilterStreamTest.java │ │ ├── TestMisc.java │ │ ├── RemoveChunksNgTest.java │ │ ├── FilterPreserveTest.java │ │ ├── ChunkSequenceSkipTest.java │ │ └── TextChunksTest.java │ │ ├── DeinterlacerTest.java │ │ ├── awt │ │ └── PngReaderBI.java │ │ └── cli │ │ ├── ShowFilterInfo.java │ │ └── ShowPngInfo.java ├── main │ ├── java │ │ ├── ar │ │ │ └── com │ │ │ │ └── hjg │ │ │ │ └── pngj │ │ │ │ ├── IImageLineFactory.java │ │ │ │ ├── IPngWriterFactory.java │ │ │ │ ├── PngjPrematureEnding.java │ │ │ │ ├── chunks │ │ │ │ ├── package.html │ │ │ │ ├── ChunkPredicate.java │ │ │ │ ├── PngBadCharsetException.java │ │ │ │ ├── ChunkLoadBehaviour.java │ │ │ │ ├── PngChunkMultiple.java │ │ │ │ ├── PngChunkIEND.java │ │ │ │ ├── PngChunkIDAT.java │ │ │ │ ├── PngChunkUNKNOWN.java │ │ │ │ ├── PngChunkSingle.java │ │ │ │ ├── PngChunkTEXT.java │ │ │ │ ├── PngChunkGAMA.java │ │ │ │ ├── PngChunkSTER.java │ │ │ │ ├── PngChunkSRGB.java │ │ │ │ ├── PngChunkACTL.java │ │ │ │ ├── PngChunkHIST.java │ │ │ │ ├── PngChunkFDAT.java │ │ │ │ ├── PngChunkZTXT.java │ │ │ │ ├── PngChunkOFFS.java │ │ │ │ ├── PngChunkTextVar.java │ │ │ │ ├── PngChunkICCP.java │ │ │ │ ├── PngChunkPLTE.java │ │ │ │ └── PngChunkTIME.java │ │ │ │ ├── pixels │ │ │ │ ├── package.html │ │ │ │ └── CompressorStreamLz4.java │ │ │ │ ├── PngjInputException.java │ │ │ │ ├── ErrorBehaviour.java │ │ │ │ ├── PngjBadCrcException.java │ │ │ │ ├── PngjOutputException.java │ │ │ │ ├── PngjBadSignature.java │ │ │ │ ├── PngjException.java │ │ │ │ ├── PngjUnsupportedException.java │ │ │ │ ├── PngjExceptionInternal.java │ │ │ │ ├── IChunkFactory.java │ │ │ │ ├── IImageLineArray.java │ │ │ │ ├── PngReaderByte.java │ │ │ │ ├── ChunkSeqBuffering.java │ │ │ │ ├── IBytesConsumer.java │ │ │ │ ├── PngHelperInternal2.java │ │ │ │ ├── PngWriterHc.java │ │ │ │ ├── IImageLineSetFactory.java │ │ │ │ ├── PngReaderInt.java │ │ │ │ ├── IImageLine.java │ │ │ │ ├── RowInfo.java │ │ │ │ ├── ChunkSeqSkipping.java │ │ │ │ ├── package.html │ │ │ │ ├── IImageLineSet.java │ │ │ │ ├── DeflatedChunkReader.java │ │ │ │ └── PngReaderFilter.java │ │ └── about.html │ ├── resources │ │ └── NOTICE.txt │ └── javadoc │ │ └── overview.html ├── site │ └── NOTICE.txt ├── about.html └── assembly │ └── fulldist.xml ├── .gitignore └── README.md /src/test/resources/test/temp/dummy.txt: -------------------------------------------------------------------------------- 1 | dummy file -------------------------------------------------------------------------------- /src/test/resources/test/apgn/readme.txt: -------------------------------------------------------------------------------- 1 | APGN related 2 | 3 | apngf_* is not APGN but only a frame from an APGN -------------------------------------------------------------------------------- /src/test/resources/test/testg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/testg1.png -------------------------------------------------------------------------------- /src/test/resources/test/testg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/testg2.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/16.png -------------------------------------------------------------------------------- /src/test/resources/grays/g08-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g08-srgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/g16-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g16-srgb.png -------------------------------------------------------------------------------- /src/test/resources/test/stripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripes.png -------------------------------------------------------------------------------- /src/test/resources/test/stripes2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripes2.png -------------------------------------------------------------------------------- /src/test/resources/test/stripes5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripes5.png -------------------------------------------------------------------------------- /src/test/resources/test/testg1i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/testg1i.png -------------------------------------------------------------------------------- /src/test/resources/test/testg1p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/testg1p.png -------------------------------------------------------------------------------- /src/test/resources/test/testg2i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/testg2i.png -------------------------------------------------------------------------------- /src/test/resources/test/testrgb3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/testrgb3.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/01g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/01g.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/01p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/01p.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/02g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/02g.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/02p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/02p.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/04g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/04g.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/04gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/04gt.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/04p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/04p.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/04pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/04pt.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08a.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08ag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08ag.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08ax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08ax.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08g.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08p.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08pt.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08t.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/16a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/16a.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/16ag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/16ag.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/16g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/16g.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/16gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/16gt.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/16t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/16t.png -------------------------------------------------------------------------------- /src/test/resources/grays/g08-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g08-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/g08-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g08-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/g16-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g16-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/g16-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g16-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga08-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga08-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga08-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga08-srgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga16-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga16-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga16-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga16-srgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb08-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb08-srgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb16-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb16-srgb.png -------------------------------------------------------------------------------- /src/test/resources/misc/pngjclasses.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/misc/pngjclasses.odg -------------------------------------------------------------------------------- /src/test/resources/test/stripe_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripe_none.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08ax2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08ax2.png -------------------------------------------------------------------------------- /src/test/resources/colormodels/08axnoa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/colormodels/08axnoa.png -------------------------------------------------------------------------------- /src/test/resources/grays/g08-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g08-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/grays/g16-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/g16-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga08-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga08-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga08-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga08-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga16-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga16-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/grays/ga16-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/ga16-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb08-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb08-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb08-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb08-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb08-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb08-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb16-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb16-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb16-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb16-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgb16-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgb16-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba08-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba08-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba08-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba08-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba08-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba08-srgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba16-gama1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba16-gama1.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba16-nosrgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba16-nosrgb.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba16-srgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba16-srgb.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/025_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/025_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/bad_testg1crc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/bad_testg1crc.png -------------------------------------------------------------------------------- /src/test/resources/test/bad_truncated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/bad_truncated.png -------------------------------------------------------------------------------- /src/test/resources/test/stripe_none64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripe_none64.png -------------------------------------------------------------------------------- /src/test/resources/test/stripes0idat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripes0idat.png -------------------------------------------------------------------------------- /src/test/resources/test/stripes_rgb8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripes_rgb8.png -------------------------------------------------------------------------------- /src/test/resources/test/stripesoptim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/stripesoptim.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/PngSuite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/PngSuite.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi4a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi4a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi4a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi4a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi6a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi6a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi6a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi6a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn0g02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn0g02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn4a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn4a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn4a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn4a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn6a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn6a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basn6a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basn6a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgai4a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgai4a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgai4a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgai4a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgan6a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgan6a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgan6a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgan6a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgbn4a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgbn4a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bggn4a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bggn4a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgwn6a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgwn6a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgyn6a16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgyn6a16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ccwn2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ccwn2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ccwn3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ccwn3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cdfn2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cdfn2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cdhn2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cdhn2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cdsn2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cdsn2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cdun2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cdun2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ch1n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ch1n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ch2n3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ch2n3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cm0n0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cm0n0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cm7n0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cm7n0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cm9n0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cm9n0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cs3n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cs3n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cs3n3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cs3n3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cs5n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cs5n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cs5n3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cs5n3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cs8n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cs8n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cs8n3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cs8n3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ct0n0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ct0n0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ct1n0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ct1n0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cten0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cten0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ctfn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ctfn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ctgn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ctgn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/cthn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/cthn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ctjn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ctjn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ctzn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ctzn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f00n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f00n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f00n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f00n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f01n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f01n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f01n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f01n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f02n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f02n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f02n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f02n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f03n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f03n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f03n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f03n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f04n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f04n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f04n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f04n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/f99n0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/f99n0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g03n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g03n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g03n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g03n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g03n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g03n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g04n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g04n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g04n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g04n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g04n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g04n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g05n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g05n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g05n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g05n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g05n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g05n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g07n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g07n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g07n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g07n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g07n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g07n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g10n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g10n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g10n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g10n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g10n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g10n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g25n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g25n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g25n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g25n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/g25n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/g25n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi1n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi1n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi1n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi1n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi2n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi2n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi2n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi2n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi4n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi4n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi4n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi4n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi9n0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi9n0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/oi9n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/oi9n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/pp0n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/pp0n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/pp0n6a08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/pp0n6a08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ps1n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ps1n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ps1n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ps1n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ps2n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ps2n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ps2n2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ps2n2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s01i3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s01i3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s01n3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s01n3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s02i3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s02i3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s02n3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s02n3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s03i3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s03i3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s03n3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s03n3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s04i3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s04i3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s04n3p01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s04n3p01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s05i3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s05i3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s05n3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s05n3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s06i3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s06i3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s06n3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s06n3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s07i3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s07i3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s07n3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s07n3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s08i3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s08i3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s08n3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s08n3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s09i3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s09i3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s09n3p02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s09n3p02.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s32i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s32i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s32n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s32n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s33i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s33i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s33n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s33n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s34i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s34i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s34n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s34n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s35i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s35i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s35n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s35n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s36i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s36i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s36n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s36n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s37i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s37i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s37n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s37n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s38i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s38i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s38n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s38n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s39i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s39i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s39n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s39n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s40i3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s40i3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s40n3p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s40n3p04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbbn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbbn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbbn2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbbn2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbbn3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbbn3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbgn2c16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbgn2c16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbgn3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbgn3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbrn2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbrn2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbwn0g16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbwn0g16.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbwn3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbwn3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbyn3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbyn3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tp0n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tp0n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tp0n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tp0n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tp0n3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tp0n3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tp1n3p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tp1n3p08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xbadidat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xbadidat.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xc1n0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xc1n0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xc9n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xc9n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xcrn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xcrn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xcsn0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xcsn0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xd0n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xd0n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xd3n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xd3n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xd9n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xd9n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xdtn0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xdtn0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xhdn0g08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xhdn0g08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xlfn0g04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xlfn0g04.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xs1n0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xs1n0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xs2n0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xs2n0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xs4n0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xs4n0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xs7n0g01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xs7n0g01.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/z00n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/z00n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/z03n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/z03n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/z06n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/z06n2c08.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/z09n2c08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/z09n2c08.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba08-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba08-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/grays/rgba16-gama2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/grays/rgba16-gama2_2.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/clock_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/clock_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/bad_missingidat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/bad_missingidat.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/xbadidat2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/xbadidat2.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/bouncing_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/bouncing_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/loading_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/loading_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/withstill_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/withstill_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/bad_testrgb3_noend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/bad_testrgb3_noend.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g01_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g01_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g02_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g02_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g08_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g08_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi0g16_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi0g16_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi2c08_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi2c08_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi2c16_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi2c16_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p01_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p01_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p02_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p02_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi3p08_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi3p08_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi4a08_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi4a08_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi4a16_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi4a16_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi6a08_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi6a08_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/basi6a16_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/basi6a16_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgai4a08_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgai4a08_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/bgai4a16_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/bgai4a16_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ccwn3p08_tc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ccwn3p08_tc.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/ch2n3p08_tc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/ch2n3p08_tc.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s01i3p01_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s01i3p01_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s02i3p01_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s02i3p01_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s03i3p01_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s03i3p01_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s04i3p01_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s04i3p01_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s05i3p02_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s05i3p02_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s06i3p02_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s06i3p02_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s07i3p02_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s07i3p02_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s08i3p02_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s08i3p02_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s09i3p02_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s09i3p02_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s32i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s32i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s33i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s33i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s34i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s34i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s35i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s35i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s36i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s36i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s37i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s37i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s38i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s38i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s39i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s39i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/s40i3p04_ni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/s40i3p04_ni.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/tbbn3p08_tc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/tbbn3p08_tc.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | .classpath 3 | .project 4 | /site/ 5 | build/ 6 | /target/ 7 | .idea 8 | .classes/ 9 | priv/ 10 | notingit/ 11 | -------------------------------------------------------------------------------- /src/test/resources/test/apgn/keepandnoblend.a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/keepandnoblend.a.png -------------------------------------------------------------------------------- /src/test/resources/testsuite1/z09n2c08_idats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/testsuite1/z09n2c08_idats.png -------------------------------------------------------------------------------- /src/test/java/readme.txt: -------------------------------------------------------------------------------- 1 | The code in this folder includes some miscelaneous utilities, examples, and informal tests. 2 | It's not included in the library jar. -------------------------------------------------------------------------------- /src/test/resources/test/apgn/apngf_000_clock_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/apngf_000_clock_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/apngf_012_clock_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/apngf_012_clock_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/apngf_013_clock_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/apngf_013_clock_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/apgn/apngf_014_clock_apng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/apgn/apngf_014_clock_apng.png -------------------------------------------------------------------------------- /src/test/resources/test/bad_stripes_extratrailing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/bad_stripes_extratrailing.png -------------------------------------------------------------------------------- /src/test/resources/test/bad_stripes_rgb8_truncatedidat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonbloy/pngj/HEAD/src/test/resources/test/bad_stripes_rgb8_truncatedidat.png -------------------------------------------------------------------------------- /src/test/resources/pngj-tests-token-readme.txt: -------------------------------------------------------------------------------- 1 | Don't remove this file, its presence is used as a token to find out the resources directory in some tests 2 | 3 | BTW: images and other files in test*/* are used in testcases, dont change them -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IImageLineFactory.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Image Line factory. 5 | */ 6 | public interface IImageLineFactory { 7 | public T createImageLine(ImageInfo iminfo); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IPngWriterFactory.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.io.OutputStream; 4 | 5 | public interface IPngWriterFactory { 6 | public PngWriter createPngWriter(OutputStream outputStream, ImageInfo imgInfo); 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/testsuite1/PngSuite.LICENSE: -------------------------------------------------------------------------------- 1 | PngSuite 2 | -------- 3 | 4 | Permission to use, copy, modify and distribute these images for any 5 | purpose and without fee is hereby granted. 6 | 7 | 8 | (c) Willem van Schaik, 1996, 2011 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjPrematureEnding.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | public class PngjPrematureEnding extends PngjInputException { 4 | 5 | public PngjPrematureEnding(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/test/resources/misc/readme.txt: -------------------------------------------------------------------------------- 1 | In this directory we store miscelaneous development resources 2 | (notes, cheatsheets, scripts) that we want to store in GIT. 3 | 4 | These are rather PNGJ-developer-private ( public docs should go to src/site/resources ) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | Contains the code related to chunk management for the PNGJ library.

5 |

6 | Only needed by client code if some special chunk handling is required. 7 |

8 | 9 | 10 | -------------------------------------------------------------------------------- /src/site/NOTICE.txt: -------------------------------------------------------------------------------- 1 | PNGJ : PNG image IO Java library 2 | Copyright 2009-2012 Hernán J. González 3 | 4 | This product includes software developed by: 5 | Hernán J. González 6 | (Buenos Aires, Argentina) 7 | hgonzalez@gmail.com 8 | http://hjg.com.ar/ 9 | http://stackexchange.com/users/103559/leonbloy 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/misc/IPngWriterFactory.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.misc; 2 | 3 | import java.io.OutputStream; 4 | 5 | import ar.com.hjg.pngj.ImageInfo; 6 | import ar.com.hjg.pngj.PngWriter; 7 | 8 | public interface IPngWriterFactory { 9 | public PngWriter createPngWriter(OutputStream outputStream, ImageInfo imgInfo); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/NOTICE.txt: -------------------------------------------------------------------------------- 1 | PNGJ : PNG image IO Java library 2 | Copyright 2009-2012 Hernán J. González 3 | 4 | This product includes software developed by: 5 | Hernán J. González 6 | (Buenos Aires, Argentina) 7 | hgonzalez@gmail.com 8 | http://hjg.com.ar/ 9 | http://stackexchange.com/users/103559/leonbloy 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/ChunkPredicate.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | /** 4 | * Decides if another chunk "matches", according to some criterion 5 | */ 6 | public interface ChunkPredicate { 7 | /** 8 | * The other chunk matches with this one 9 | * 10 | * @param chunk 11 | * @return true if match 12 | */ 13 | boolean match(PngChunk chunk); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/pixels/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | Mostly related with logic specific to reading/writing pixels. 5 |

6 |

7 | Includes ImageLine related classes, and rows filtering 8 |

9 |

10 | Some classes like ImageLineInt should belong here, but we keep them in the main package for backward compatibility. 11 | 12 |

13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | Some examples, tests and development-deployment utilities. 5 | This is not included in the main jar. 6 |

7 | Classes Sample* are examples. 8 |

9 | You can copy and modify this classes for your own use, but only as boilerplate. 10 | Don't rely on any of this being present or compatible in next releases. 11 |

12 | 13 | 14 | -------------------------------------------------------------------------------- /src/test/resources/misc/optipng.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DIR=`dirname "$0"` 4 | #OPTS="-backup -f0-5 -zm8 -zs0 -i0 -nx -zc9" 5 | # 6 | OPTS="-f0-5 -zs0 -zc6 -zm8 -i0 -nx -force " 7 | # -zs0 estrategy default 8 | # -i0 don't interlace 9 | # -zm8 memory level 8 (default) 10 | # -zc6 zlib compression level 6 11 | $DIR/optipng.exe $OPTS $1 12 | 13 | # or better: 14 | # find . -name '*.png' -exec echo "optipng.exe -f0-5 -zs0 -zc6 -zm8 -i0 -nx -force " '{}' \; 15 | -------------------------------------------------------------------------------- /src/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

7 | PNGJ: A simple library for reading/writing PNG images. 8 |

9 |

10 | See the docs and source of the samples for more. 11 |

12 |

13 | http://code.google.com/p/pngj/
14 | PNGJ 15 |

16 |

17 | Hernán J. González
18 | hgonzalez@gmail.com 19 |

20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

7 | PNGJ: A simple library for reading/writing PNG images. 8 |

9 |

10 | See the docs and source of the samples for more. 11 |

12 |

13 | http://code.google.com/p/pngj/
14 | PNGJ 15 |

16 |

17 | Hernán J. González
18 | hgonzalez@gmail.com 19 |

20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjInputException.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Exception thrown when reading a PNG. 5 | */ 6 | public class PngjInputException extends PngjException { 7 | private static final long serialVersionUID = 1L; 8 | 9 | public PngjInputException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | public PngjInputException(String message) { 14 | super(message); 15 | } 16 | 17 | public PngjInputException(Throwable cause) { 18 | super(cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/ErrorBehaviour.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | public enum ErrorBehaviour { 4 | STRICT(0), // default mode: any error aborts reading with exception 5 | LENIENT1_CRC(1), // CRC errors only trigger warning (or nothing if not checking) 6 | LENIENT2_ANCILLARY(3), // also: content errors in ancillary chunks are ignored 7 | SUPER_LENIENT(5); // we try hard to read, even garbage, without throwing exceptions 8 | final int c; 9 | 10 | private ErrorBehaviour(int c) { 11 | this.c = c; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjBadCrcException.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Exception thrown by bad CRC check 5 | */ 6 | public class PngjBadCrcException extends PngjInputException { 7 | private static final long serialVersionUID = 1L; 8 | 9 | public PngjBadCrcException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | public PngjBadCrcException(String message) { 14 | super(message); 15 | } 16 | 17 | public PngjBadCrcException(Throwable cause) { 18 | super(cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjOutputException.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Exception thrown by writing process 5 | */ 6 | public class PngjOutputException extends PngjException { 7 | private static final long serialVersionUID = 1L; 8 | 9 | public PngjOutputException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | public PngjOutputException(String message) { 14 | super(message); 15 | } 16 | 17 | public PngjOutputException(Throwable cause) { 18 | super(cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/misc/ispng.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # if file is not PNG but ends in .png , renames it to .bad 4 | 5 | my $filename = $ARGV[0]; 6 | open FILE, "<:raw", $filename or die "Couldn't open $filename $!"; 7 | my $rr; 8 | read(FILE, $rr, 4) ; 9 | $png = $rr eq "\x89PNG"; 10 | #print "[$rr png=$png]\n"; 11 | close FILE; 12 | if( lc($filename) =~ /\.png$/) { 13 | if(! $png) { 14 | rename $filename, $filename . ".bad"; 15 | print STDERR "bad png $filename renaming $filename.bad \n"; 16 | } 17 | } 18 | exit ($png ? 0: 1); 19 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjBadSignature.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Exception thrown by bad signature (not a PNG file) 5 | */ 6 | public class PngjBadSignature extends PngjInputException { 7 | private static final long serialVersionUID = 1L; 8 | 9 | public PngjBadSignature(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | public PngjBadSignature(String message) { 14 | super(message); 15 | } 16 | 17 | public PngjBadSignature(Throwable cause) { 18 | super(cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjException.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Generic exception for this library. It's a RuntimeException (unchecked) 5 | */ 6 | public class PngjException extends RuntimeException { 7 | private static final long serialVersionUID = 1L; 8 | 9 | public PngjException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | public PngjException(String message) { 14 | super(message); 15 | } 16 | 17 | public PngjException(Throwable cause) { 18 | super(cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngBadCharsetException.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.PngjException; 4 | 5 | public class PngBadCharsetException extends PngjException { 6 | private static final long serialVersionUID = 1L; 7 | 8 | public PngBadCharsetException(String message, Throwable cause) { 9 | super(message, cause); 10 | } 11 | 12 | public PngBadCharsetException(String message) { 13 | super(message); 14 | } 15 | 16 | public PngBadCharsetException(Throwable cause) { 17 | super(cause); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/logging.properties: -------------------------------------------------------------------------------- 1 | # configuration file for Java logging in Tests 2 | 3 | # Notice that for this to take effect during JUNit tests, 4 | # you should inherit PngjTest which loads this statically in @BeforeClass method 5 | 6 | handlers= java.util.logging.ConsoleHandler 7 | java.util.logging.ConsoleHandler.level = FINE 8 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 9 | java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] %4$-7s %5$s [%2$s]%n 10 | #ar.com.hjg.pngj.level = WARNING 11 | ar.com.hjg.pngj.level = INFO 12 | #ar.com.hjg.pngj.level = FINE 13 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/misc/MappedCounterInt.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.misc; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | public class MappedCounterInt { 8 | 9 | private Map map = new HashMap(); 10 | 11 | public void add(String k, int v) { 12 | if (!map.containsKey(k)) 13 | map.put(k, v); 14 | else 15 | map.put(k, map.get(k) + v); 16 | } 17 | 18 | public int get(String k) { 19 | return map.containsKey(k) ? map.get(k) : 0; 20 | } 21 | 22 | public Set getKeys() { 23 | return map.keySet(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjUnsupportedException.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Exception thrown because of some valid feature of PNG standard that this 5 | * library does not support. 6 | */ 7 | public class PngjUnsupportedException extends PngjException { 8 | private static final long serialVersionUID = 1L; 9 | 10 | public PngjUnsupportedException(String message, Throwable cause) { 11 | super(message, cause); 12 | } 13 | 14 | public PngjUnsupportedException(String message) { 15 | super(message); 16 | } 17 | 18 | public PngjUnsupportedException(Throwable cause) { 19 | super(cause); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/misc/Pair.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.misc; 2 | 3 | /** 4 | * Utility class that wraps two objects in one 5 | */ 6 | public class Pair { 7 | public final TA a; 8 | public final TB b; 9 | 10 | /** 11 | * factory method 12 | */ 13 | public static Pair createPair(TA a, TB b) { 14 | return new Pair(a, b); 15 | } 16 | 17 | /** 18 | * private constructor - use instead factory method 19 | */ 20 | private Pair(final TA a, final TB b) { 21 | this.a = a; 22 | this.b = b; 23 | } 24 | 25 | public String toString() { 26 | return "(" + a + ", " + b + ")"; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngjExceptionInternal.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Exception for anomalous internal problems (sort of asserts) that point to 5 | * some issue with the library 6 | * 7 | * @author Hernan J Gonzalez 8 | * 9 | */ 10 | public class PngjExceptionInternal extends RuntimeException { 11 | private static final long serialVersionUID = 1L; 12 | 13 | public PngjExceptionInternal(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | 17 | public PngjExceptionInternal(String message) { 18 | super(message); 19 | } 20 | 21 | public PngjExceptionInternal(Throwable cause) { 22 | super(cause); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/ErrorHandlingTests.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import java.io.InputStream; 4 | 5 | import org.junit.Test; 6 | 7 | import ar.com.hjg.pngj.ChunkSeqReaderPng; 8 | import ar.com.hjg.pngj.PngReader; 9 | import ar.com.hjg.pngj.PngjException; 10 | import junit.framework.TestCase; 11 | 12 | public class ErrorHandlingTests { 13 | @Test 14 | public void testReadIncomplete() throws PngjException { 15 | InputStream is = TestSupport.istream("test/bad_truncated.png"); 16 | PngReader r = new PngReader(is); 17 | //r.readRows(); 18 | //r.end(); 19 | //TestCase.assertFalse(r.getChunkseq().isDone()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/ChunkLoadBehaviour.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | /** 4 | * What to do with ancillary (non-critical) chunks when reading. 5 | *

6 | * 7 | */ 8 | public enum ChunkLoadBehaviour { 9 | /** 10 | * All non-critical chunks are skipped 11 | */ 12 | LOAD_CHUNK_NEVER, 13 | /** 14 | * Load chunk if "safe to copy" 15 | */ 16 | LOAD_CHUNK_IF_SAFE, 17 | /** 18 | * Load only most important chunk: TRNS 19 | */ 20 | LOAD_CHUNK_MOST_IMPORTANT, 21 | /** 22 | * Load all chunks.
23 | * Notice that other restrictions might apply, see 24 | * PngReader.skipChunkMaxSize PngReader.skipChunkIds 25 | */ 26 | LOAD_CHUNK_ALWAYS; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IChunkFactory.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import ar.com.hjg.pngj.chunks.ChunkRaw; 4 | import ar.com.hjg.pngj.chunks.PngChunk; 5 | 6 | /** 7 | * Factory to create a {@link PngChunk} from a {@link ChunkRaw}. 8 | *

9 | * Used by {@link PngReader} 10 | */ 11 | public interface IChunkFactory { 12 | 13 | /** 14 | * @param chunkRaw 15 | * Chunk in raw form. Data can be null if it was skipped or 16 | * processed directly (eg IDAT) 17 | * @param imgInfo 18 | * Not normally necessary, but some chunks want this info 19 | * @return should never return null. 20 | */ 21 | public PngChunk createChunk(ChunkRaw chunkRaw, ImageInfo imgInfo); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/misc/NullOs.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.misc; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | /** 7 | * Trivial output stream that discards written bytes. It keeps a count of sent 8 | * bytes. 9 | */ 10 | public class NullOs extends OutputStream { 11 | private long cont = 0; 12 | 13 | @Override 14 | public void write(int arg0) throws IOException { 15 | cont++; 16 | } 17 | 18 | @Override 19 | public void write(byte[] b, int off, int len) throws IOException { 20 | cont += len; 21 | } 22 | 23 | @Override 24 | public void write(byte[] b) throws IOException { 25 | cont += b.length; 26 | } 27 | 28 | public long getBytes() { 29 | return cont; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkMultiple.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | 5 | /** 6 | * PNG chunk type (abstract) that allows multiple instances in same image. 7 | */ 8 | public abstract class PngChunkMultiple extends PngChunk { 9 | 10 | protected PngChunkMultiple(String id, ImageInfo imgInfo) { 11 | super(id, imgInfo); 12 | } 13 | 14 | @Override 15 | public final boolean allowsMultiple() { 16 | return true; 17 | } 18 | 19 | /** 20 | * NOTE: this chunk uses the default Object's equals() hashCode() 21 | * implementation. 22 | * 23 | * This is the right thing to do, normally. 24 | * 25 | * This is important, eg see ChunkList.removeFromList() 26 | */ 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleShowChunks.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.test.TestSupport; 6 | 7 | /** 8 | * prints chunks list 9 | */ 10 | public class SampleShowChunks { 11 | 12 | public static void showChunks(File file, boolean includeidat) { 13 | 14 | PngReaderDumb png = new PngReaderDumb(file); 15 | png.setIncludeIdat(includeidat); 16 | png.readAll(); 17 | for (int i = 0; i < png.getChunks().size(); i++) { 18 | System.out.println("Chunk " + (i + 1) + ": " + png.getChunks().get(i)); 19 | } 20 | } 21 | 22 | public static void main(String[] args) throws Exception { 23 | showChunks(new File(TestSupport.getResourcesDir(), TestSupport.PNG_TEST_STRIPES), true); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IImageLineArray.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * This interface is just for the sake of unifying some methods of 5 | * {@link ImageLineHelper} that can use both {@link ImageLineInt} or 6 | * {@link ImageLineByte}. It's not very useful outside that, and the user should 7 | * not rely much on this. 8 | */ 9 | public interface IImageLineArray { 10 | public ImageInfo getImageInfo(); 11 | 12 | public FilterType getFilterType(); 13 | 14 | /** 15 | * length of array (should correspond to samples) 16 | */ 17 | public int getSize(); 18 | 19 | /** 20 | * Get i-th element of array (for 0 to size-1). The meaning of this is type 21 | * dependent. For ImageLineInt and ImageLineByte is the sample value. 22 | */ 23 | public int getElem(int i); 24 | } 25 | -------------------------------------------------------------------------------- /src/assembly/fulldist.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | full 4 | 5 | tar.gz 6 | 8 | 9 | 10 | 11 | false 12 | runtime 13 | lib 14 | 15 | 16 | 17 | 18 | src/site 19 | . 20 | 21 | 22 | target 23 | . 24 | 25 | *.jar 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkIEND.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | 5 | /** 6 | * IEND chunk. 7 | *

8 | * see http://www.w3.org/TR/PNG/#11IEND 9 | */ 10 | public class PngChunkIEND extends PngChunkSingle { 11 | public final static String ID = ChunkHelper.IEND; 12 | 13 | // http://www.w3.org/TR/PNG/#11IEND 14 | // this is a dummy placeholder 15 | public PngChunkIEND(ImageInfo info) { 16 | super(ID, info); 17 | } 18 | 19 | @Override 20 | public ChunkOrderingConstraint getOrderingConstraint() { 21 | return ChunkOrderingConstraint.NA; 22 | } 23 | 24 | @Override 25 | public ChunkRaw createRawChunk() { 26 | ChunkRaw c = new ChunkRaw(0, ChunkHelper.b_IEND, false); 27 | return c; 28 | } 29 | 30 | @Override 31 | public void parseFromRaw(ChunkRaw c) { 32 | // this is not used 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkIDAT.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | 5 | /** 6 | * IDAT chunk. 7 | *

8 | * see http://www.w3.org/TR/PNG/#11IDAT 9 | *

10 | * This is dummy placeholder - we write/read this chunk (actually several) by 11 | * special code. 12 | */ 13 | public class PngChunkIDAT extends PngChunkMultiple { 14 | public final static String ID = ChunkHelper.IDAT; 15 | 16 | // http://www.w3.org/TR/PNG/#11IDAT 17 | public PngChunkIDAT(ImageInfo i) { 18 | super(ID, i); 19 | } 20 | 21 | @Override 22 | public ChunkOrderingConstraint getOrderingConstraint() { 23 | return ChunkOrderingConstraint.NA; 24 | } 25 | 26 | @Override 27 | public ChunkRaw createRawChunk() {// does nothing 28 | return null; 29 | } 30 | 31 | @Override 32 | public void parseFromRaw(ChunkRaw c) { // does nothing 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngReaderByte.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * Trivial extension of {@link PngReader} that uses {@link ImageLineByte} 8 | *

9 | * The factory is set at construction time. Remember that this could still be 10 | * changed at runtime. 11 | */ 12 | public class PngReaderByte extends PngReader { 13 | 14 | public PngReaderByte(File file) { 15 | super(file); 16 | setLineSetFactory(ImageLineSetDefault.getFactoryByte()); 17 | } 18 | 19 | public PngReaderByte(InputStream inputStream) { 20 | super(inputStream); 21 | setLineSetFactory(ImageLineSetDefault.getFactoryByte()); 22 | } 23 | 24 | /** 25 | * Utility method that casts {@link #readRow()} return to 26 | * {@link ImageLineByte}. 27 | */ 28 | public ImageLineByte readRowByte() { 29 | return (ImageLineByte) readRow(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/ChunkSeqBuffering.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * This loads the png as a plain sequence of chunks, buffering all 5 | * 6 | * Useful to do things like insert or delete a ancilllary chunk. This does not 7 | * distinguish IDAT from others 8 | **/ 9 | public class ChunkSeqBuffering extends ChunkSeqReader { 10 | protected boolean checkCrc = true; 11 | 12 | public ChunkSeqBuffering() { 13 | super(); 14 | } 15 | 16 | @Override 17 | protected boolean isIdatKind(String id) { 18 | return false; 19 | } 20 | 21 | @Override 22 | protected boolean shouldCheckCrc(int len, String id) { 23 | return checkCrc; 24 | } 25 | 26 | public void setCheckCrc(boolean checkCrc) { 27 | this.checkCrc = checkCrc; 28 | } 29 | 30 | @Override 31 | protected DeflatedChunksSet createIdatSet(String id) { 32 | throw new RuntimeException("Should not get here"); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/PngjTest.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import java.util.logging.Logger; 4 | 5 | import org.junit.After; 6 | import org.junit.BeforeClass; 7 | 8 | public class PngjTest { 9 | 10 | /** change to false if you want to inspect the temporary files */ 11 | protected boolean clearTempFiles = true; 12 | 13 | @BeforeClass 14 | public static void setup() { 15 | System.setProperty("java.util.logging.config.file", 16 | ClassLoader.getSystemResource("logging.properties").getPath()); 17 | //testLogger(); 18 | } 19 | 20 | private static void testLogger() { 21 | Logger log = Logger.getLogger(PngjTest.class.getName()); 22 | log.severe("Testing log SEVERE"); 23 | log.warning("Testing log WARN"); 24 | log.info("Testing log INFO"); 25 | log.fine("Testing log FINE"); 26 | } 27 | 28 | @After 29 | public void tearDown() { 30 | if (clearTempFiles) { 31 | TestSupport.cleanAll(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkUNKNOWN.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | 5 | /** 6 | * Placeholder for UNKNOWN (custom or not) chunks. 7 | *

8 | * For PngReader, a chunk is unknown if it's not registered in the chunk factory 9 | */ 10 | public class PngChunkUNKNOWN extends PngChunkMultiple { // unkown, custom or not 11 | 12 | public PngChunkUNKNOWN(String id, ImageInfo info) { 13 | super(id, info); 14 | } 15 | 16 | @Override 17 | public ChunkOrderingConstraint getOrderingConstraint() { 18 | return ChunkOrderingConstraint.NONE; 19 | } 20 | 21 | @Override 22 | public ChunkRaw createRawChunk() { 23 | return raw; 24 | } 25 | 26 | @Override 27 | public void parseFromRaw(ChunkRaw c) { 28 | 29 | } 30 | 31 | /* does not do deep copy! */ 32 | public byte[] getData() { 33 | return raw.data; 34 | } 35 | 36 | /* does not do deep copy! */ 37 | public void setData(byte[] data) { 38 | raw.data = data; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IBytesConsumer.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Bytes consumer. 5 | * 6 | * An object implementing can be fed with bytes. 7 | * 8 | * It can consume in steps, so each time it's fed with n bytes it can eat 9 | * between 1 and n bytes. 10 | */ 11 | public interface IBytesConsumer { 12 | /** 13 | * Eats some bytes, at most len (perhaps less). 14 | *

15 | * Returns bytes actually consumed. 16 | * 17 | * It returns -1 if the object didn't consume bytes because it was done or 18 | * closed 19 | * 20 | * It should only returns 0 if len is 0 21 | */ 22 | int consume(byte[] buf, int offset, int len); 23 | 24 | /** 25 | * The consumer is DONE when it does not need more bytes, 26 | * either because it ended normally, or abnormally 27 | * Typically this implies it will return -1 if consume() is called afterwards, 28 | * but it might happen that it will consume more (unneeded) bytes anwyway 29 | * */ 30 | boolean isDone(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngHelperInternal2.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.io.File; 4 | import java.io.OutputStream; 5 | 6 | /** 7 | * For organization purposes, this class is the onlt that uses classes not in 8 | * GAE (Google App Engine) white list 9 | *

10 | * You should not use this class in GAE 11 | */ 12 | final class PngHelperInternal2 { 13 | 14 | /** 15 | * WARNING: this uses FileOutputStream which is not allowed in 16 | * GoogleAppEngine 17 | * 18 | * In GAE, dont use this 19 | * 20 | * @param f 21 | * @param allowoverwrite 22 | * @return 23 | */ 24 | static OutputStream ostreamFromFile(File f, boolean allowoverwrite) { 25 | java.io.FileOutputStream os = null; // this will fail in GAE! 26 | if (f.exists() && !allowoverwrite) 27 | throw new PngjOutputException("File already exists: " + f); 28 | try { 29 | os = new java.io.FileOutputStream(f); 30 | } catch (Exception e) { 31 | throw new PngjInputException("Could not open for write" + f, e); 32 | } 33 | return os; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngWriterHc.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.io.File; 4 | import java.io.OutputStream; 5 | 6 | import ar.com.hjg.pngj.pixels.PixelsWriter; 7 | import ar.com.hjg.pngj.pixels.PixelsWriterMultiple; 8 | 9 | /** Pngwriter with High compression EXPERIMENTAL */ 10 | public class PngWriterHc extends PngWriter { 11 | 12 | public PngWriterHc(File file, ImageInfo imgInfo, boolean allowoverwrite) { 13 | super(file, imgInfo, allowoverwrite); 14 | setFilterType(FilterType.FILTER_SUPER_ADAPTIVE); 15 | } 16 | 17 | public PngWriterHc(File file, ImageInfo imgInfo) { 18 | super(file, imgInfo); 19 | } 20 | 21 | public PngWriterHc(OutputStream outputStream, ImageInfo imgInfo) { 22 | super(outputStream, imgInfo); 23 | } 24 | 25 | @Override 26 | protected PixelsWriter createPixelsWriter(ImageInfo imginfo) { 27 | PixelsWriterMultiple pw = new PixelsWriterMultiple(imginfo); 28 | return pw; 29 | } 30 | 31 | public PixelsWriterMultiple getPixelWriterMultiple() { 32 | return (PixelsWriterMultiple) pixelsWriter; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkSingle.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | 5 | /** 6 | * PNG chunk type (abstract) that does not allow multiple instances in same 7 | * image. 8 | */ 9 | public abstract class PngChunkSingle extends PngChunk { 10 | 11 | protected PngChunkSingle(String id, ImageInfo imgInfo) { 12 | super(id, imgInfo); 13 | } 14 | 15 | public final boolean allowsMultiple() { 16 | return false; 17 | } 18 | 19 | @Override 20 | public int hashCode() { 21 | final int prime = 31; 22 | int result = 1; 23 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 24 | return result; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object obj) { 29 | if (this == obj) 30 | return true; 31 | if (obj == null) 32 | return false; 33 | if (getClass() != obj.getClass()) 34 | return false; 35 | PngChunkSingle other = (PngChunkSingle) obj; 36 | if (id == null) { 37 | if (other.id != null) 38 | return false; 39 | } else if (!id.equals(other.id)) 40 | return false; 41 | return true; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IImageLineSetFactory.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Factory of {@link IImageLineSet}, used by {@link PngReader}. 5 | *

6 | * 7 | * @param 8 | * Generic type of IImageLine 9 | */ 10 | public interface IImageLineSetFactory { 11 | /** 12 | * Creates a new {@link IImageLineSet} 13 | * 14 | * If singleCursor=true, the caller will read and write one row fully at a 15 | * time, in order (it'll never try to read out of order lines), so the 16 | * implementation can opt for allocate only one line. 17 | * 18 | * @param imgInfo 19 | * Image info 20 | * @param singleCursor 21 | * : will read/write one row at a time 22 | * @param nlines 23 | * : how many lines we plan to read 24 | * @param noffset 25 | * : how many lines we want to skip from the original image 26 | * (normally 0) 27 | * @param step 28 | * : row step (normally 1) 29 | */ 30 | public IImageLineSet create(ImageInfo imgInfo, boolean singleCursor, int nlines, int noffset, int step); 31 | } 32 | -------------------------------------------------------------------------------- /src/test/resources/test/readme.txt: -------------------------------------------------------------------------------- 1 | These images are uses for testing, they shouldn't be modified. 2 | 3 | Some have comments in tEXt chunk 4 | 5 | stripe_none.png Same as stripes.png, with filter NONE 6 | stripe_none64.png Same as stripes_none.png, posterized to 64 levels 7 | stripes.png Reference image. 8bpp, grayscale 8 | stripes_rgb8.png 9 | stripes0idat.png Same as stripes.png, but with two zero-sized IDAT 10 | stripes2.png 11 | stripes5.png Same as stripes.png, but with small IDATs (5 bytes) 12 | stripesoptim.png 13 | testg1.png Small 8 bpp 9x11. See text comment for contents 14 | testg1i.png Same as testg1 but interlaced 15 | 16 | testg1i.png 17 | testg1p.png Single pixel (1x1) 18 | testg2.png 19 | testg2i.png 3x3 interlaced 20 | testrgb3.png 21 | 22 | bad_missingidat.png 23 | bad_stripes_rgb8_truncatedidat.png 24 | bad_testrgb3_noend.png 25 | bad_truncated.png 26 | bad_testg1crc.png 27 | bad_stripes_extratrailing.png Same as stripes.png with extra junk trailing bytes (valid, noty really bad) 28 | -------------------------------------------------------------------------------- /src/test/resources/testsuite1/PngSuite.README: -------------------------------------------------------------------------------- 1 | PNGSUITE 2 | ---------------- 3 | 4 | testset for PNG-(de)coders 5 | created by Willem van Schaik 6 | ------------------------------------ 7 | 8 | This is a collection of graphics images created to test the png applications 9 | like viewers, converters and editors. All (as far as that is possible) 10 | formats supported by the PNG standard are represented. 11 | 12 | The suite consists of the following files: 13 | 14 | - PngSuite.README - this file 15 | - PngSuite.LICENSE - the PngSuite is freeware 16 | - PngSuite.png - image with PngSuite logo 17 | - PngSuite.tgz - archive of all PNG testfiles 18 | - PngSuite.zip - same in .zip format for PCs 19 | 20 | 21 | -------- 22 | (c) Willem van Schaik 23 | willem@schaik.com 24 | Calgary, April 2011 25 | 26 | 27 | 28 | --------------------- 29 | 30 | Added by Hernan J Gonzalez hgonzalez@gmail.com 31 | 32 | For every interlaced image the same non-interlaced version with the suffix _ni 33 | Eg: s40i3p04.png s40i3p04_ni.png 34 | 35 | For a few paletted images, the same true color with the suffix _tc 36 | Eg: ch2n3p08.png -> ch2n3p08_tc.png -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngReaderInt.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * Trivial extension of {@link PngReader} that uses {@link ImageLineInt}. 8 | *

9 | * In the current implementation this is quite dummy/redundant, because (for 10 | * backward compatibility) PngReader already uses a {@link ImageLineInt}. 11 | *

12 | * The factory is set at construction time. Remember that this could still be 13 | * changed at runtime. 14 | */ 15 | public class PngReaderInt extends PngReader { 16 | 17 | public PngReaderInt(File file) { 18 | super(file); // not necessary to set factory, PngReader already does that 19 | } 20 | 21 | public PngReaderInt(InputStream inputStream) { 22 | super(inputStream); 23 | } 24 | 25 | /** 26 | * Utility method that casts the IImageLine to a ImageLineInt 27 | * 28 | * This only make sense for this concrete class 29 | * 30 | */ 31 | public ImageLineInt readRowInt() { 32 | IImageLine line = readRow(); 33 | if (line instanceof ImageLineInt) 34 | return (ImageLineInt) line; 35 | else 36 | throw new PngjException("This is not a ImageLineInt : " + line.getClass()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkTEXT.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngjException; 5 | 6 | /** 7 | * tEXt chunk. 8 | *

9 | * see http://www.w3.org/TR/PNG/#11tEXt 10 | */ 11 | public class PngChunkTEXT extends PngChunkTextVar { 12 | public final static String ID = ChunkHelper.tEXt; 13 | 14 | public PngChunkTEXT(ImageInfo info) { 15 | super(ID, info); 16 | } 17 | 18 | public PngChunkTEXT(ImageInfo info, String key, String val) { 19 | super(ID, info); 20 | setKeyVal(key, val); 21 | } 22 | 23 | @Override 24 | public ChunkRaw createRawChunk() { 25 | if (key == null || key.trim().length() == 0) 26 | throw new PngjException("Text chunk key must be non empty"); 27 | byte[] b = ChunkHelper.toBytesLatin1(key + "\0" + val); 28 | ChunkRaw chunk = createEmptyChunk(b.length, false); 29 | chunk.data = b; 30 | return chunk; 31 | } 32 | 33 | @Override 34 | public void parseFromRaw(ChunkRaw c) { 35 | int i; 36 | for (i = 0; i < c.data.length; i++) 37 | if (c.data[i] == 0) 38 | break; 39 | key = ChunkHelper.toStringLatin1(c.data, 0, i); 40 | i++; 41 | val = i < c.data.length ? ChunkHelper.toStringLatin1(c.data, i, c.data.length - i) : ""; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/PngFilterStreamTest.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.util.List; 5 | 6 | import javax.imageio.ImageIO; 7 | 8 | import junit.framework.TestCase; 9 | 10 | import org.junit.Test; 11 | 12 | import ar.com.hjg.pngj.PngReaderFilter; 13 | import ar.com.hjg.pngj.chunks.PngChunk; 14 | 15 | /** this shows how to use the Callback mode */ 16 | public class PngFilterStreamTest { 17 | 18 | @Test 19 | public void testBufferedImage() throws Exception { 20 | PngReaderFilter reader = new PngReaderFilter(TestSupport.istream("test/stripes.png")); 21 | BufferedImage image1 = ImageIO.read(reader); 22 | reader.readUntilEndAndClose(); 23 | List chunks = reader.getChunksList(); 24 | /* 25 | * System.out.println(chunks.size()); 26 | * System.out.println(reader.getChunksList()); 27 | * System.out.println(TestSupport.showChunks(reader.getChunksList())); 28 | * System.out.println(chunks.size()); 29 | */ 30 | 31 | TestCase.assertTrue(reader.getChunkseq().isDone()); 32 | TestCase.assertTrue(reader.getChunkseq().isClosed()); 33 | TestCase.assertEquals("IHDR[13] pHYs[9] tIME[7] iTXt[30] IEND[0] ", TestSupport.showChunks(chunks)); 34 | TestCase.assertEquals(reader.getChunkseq().getImageInfo().cols, image1.getWidth()); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkGAMA.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngHelperInternal; 5 | import ar.com.hjg.pngj.PngjException; 6 | 7 | /** 8 | * gAMA chunk. 9 | *

10 | * see http://www.w3.org/TR/PNG/#11gAMA 11 | */ 12 | public class PngChunkGAMA extends PngChunkSingle { 13 | public final static String ID = ChunkHelper.gAMA; 14 | 15 | // http://www.w3.org/TR/PNG/#11gAMA 16 | private double gamma; 17 | 18 | public PngChunkGAMA(ImageInfo info) { 19 | super(ID, info); 20 | } 21 | 22 | @Override 23 | public ChunkOrderingConstraint getOrderingConstraint() { 24 | return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT; 25 | } 26 | 27 | @Override 28 | public ChunkRaw createRawChunk() { 29 | ChunkRaw c = createEmptyChunk(4, true); 30 | int g = (int) (gamma * 100000 + 0.5); 31 | PngHelperInternal.writeInt4tobytes(g, c.data, 0); 32 | return c; 33 | } 34 | 35 | @Override 36 | public void parseFromRaw(ChunkRaw chunk) { 37 | if (chunk.len != 4) 38 | throw new PngjException("bad chunk " + chunk); 39 | int g = PngHelperInternal.readInt4fromBytes(chunk.data, 0); 40 | gamma = ((double) g) / 100000.0; 41 | } 42 | 43 | public double getGamma() { 44 | return gamma; 45 | } 46 | 47 | public void setGamma(double gamma) { 48 | this.gamma = gamma; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleReadEvenLines.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.IImageLine; 6 | import ar.com.hjg.pngj.IImageLineSet; 7 | import ar.com.hjg.pngj.ImageInfo; 8 | import ar.com.hjg.pngj.PngReader; 9 | import ar.com.hjg.pngj.PngWriter; 10 | import ar.com.hjg.pngj.chunks.ChunkCopyBehaviour; 11 | 12 | /** 13 | * 14 | */ 15 | public class SampleReadEvenLines { 16 | 17 | public static void convert(String origFilename, String destFilename) { 18 | PngReader pngr = new PngReader(new File(origFilename)); 19 | ImageInfo imr = pngr.imgInfo; 20 | 21 | ImageInfo imw = new ImageInfo(imr.cols, imr.rows / 2, imr.bitDepth, imr.alpha, imr.greyscale, imr.indexed); 22 | IImageLineSet imlines = pngr.readRows(0, imw.rows, 2); // half of the 23 | // lines 24 | PngWriter pngw = new PngWriter(new File(destFilename), imw, true); 25 | pngw.copyChunksFrom(pngr.getChunksList(), ChunkCopyBehaviour.COPY_ALL); // all chunks are queued 26 | pngw.writeRows(imlines); 27 | pngw.end(); 28 | pngr.end(); 29 | } 30 | 31 | public static void main(String[] args) throws Exception { 32 | if (args.length != 2 || args[0].equals(args[1])) { 33 | System.err.println("Arguments: [pngsrc] [pngdest]"); 34 | System.exit(1); 35 | } 36 | convert(args[0], args[1]); 37 | System.out.println("Done. Result in " + args[1]); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkSTER.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngjException; 5 | 6 | /** 7 | * sTER chunk. 8 | *

9 | * see http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.sTER 10 | */ 11 | public class PngChunkSTER extends PngChunkSingle { 12 | public final static String ID = "sTER"; 13 | 14 | // http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.sTER 15 | private byte mode; // 0: cross-fuse layout 1: diverging-fuse layout 16 | 17 | public PngChunkSTER(ImageInfo info) { 18 | super(ID, info); 19 | } 20 | 21 | @Override 22 | public ChunkOrderingConstraint getOrderingConstraint() { 23 | return ChunkOrderingConstraint.BEFORE_IDAT; 24 | } 25 | 26 | @Override 27 | public ChunkRaw createRawChunk() { 28 | ChunkRaw c = createEmptyChunk(1, true); 29 | c.data[0] = (byte) mode; 30 | return c; 31 | } 32 | 33 | @Override 34 | public void parseFromRaw(ChunkRaw chunk) { 35 | if (chunk.len != 1) 36 | throw new PngjException("bad chunk length " + chunk); 37 | mode = chunk.data[0]; 38 | } 39 | 40 | /** 41 | * 0: cross-fuse layout 1: diverging-fuse layout 42 | */ 43 | public byte getMode() { 44 | return mode; 45 | } 46 | 47 | /** 48 | * 0: cross-fuse layout 1: diverging-fuse layout 49 | */ 50 | public void setMode(byte mode) { 51 | this.mode = mode; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkSRGB.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngHelperInternal; 5 | import ar.com.hjg.pngj.PngjException; 6 | 7 | /** 8 | * sRGB chunk. 9 | *

10 | * see http://www.w3.org/TR/PNG/#11sRGB 11 | */ 12 | public class PngChunkSRGB extends PngChunkSingle { 13 | public final static String ID = ChunkHelper.sRGB; 14 | 15 | // http://www.w3.org/TR/PNG/#11sRGB 16 | 17 | public static final int RENDER_INTENT_Perceptual = 0; 18 | public static final int RENDER_INTENT_Relative_colorimetric = 1; 19 | public static final int RENDER_INTENT_Saturation = 2; 20 | public static final int RENDER_INTENT_Absolute_colorimetric = 3; 21 | 22 | private int intent; 23 | 24 | public PngChunkSRGB(ImageInfo info) { 25 | super(ID, info); 26 | } 27 | 28 | @Override 29 | public ChunkOrderingConstraint getOrderingConstraint() { 30 | return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT; 31 | } 32 | 33 | @Override 34 | public void parseFromRaw(ChunkRaw c) { 35 | if (c.len != 1) 36 | throw new PngjException("bad chunk length " + c); 37 | intent = PngHelperInternal.readInt1fromByte(c.data, 0); 38 | } 39 | 40 | @Override 41 | public ChunkRaw createRawChunk() { 42 | ChunkRaw c = null; 43 | c = createEmptyChunk(1, true); 44 | c.data[0] = (byte) intent; 45 | return c; 46 | } 47 | 48 | public int getIntent() { 49 | return intent; 50 | } 51 | 52 | public void setIntent(int intent) { 53 | this.intent = intent; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/DeinterlacerTest.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.util.Random; 4 | 5 | import junit.framework.TestCase; 6 | 7 | import org.junit.Test; 8 | 9 | import ar.com.hjg.pngj.Deinterlacer; 10 | import ar.com.hjg.pngj.ImageInfo; 11 | import ar.com.hjg.pngj.test.PngjTest; 12 | 13 | public class DeinterlacerTest extends PngjTest { 14 | Random rand = new Random(); 15 | 16 | void test1(int cols, int rows) { 17 | String msg = String.format("cols=%d rows=%d", cols, rows); 18 | ImageInfo imi = new ImageInfo(cols, rows, 8, true); 19 | Deinterlacer ih = new Deinterlacer(imi); 20 | int np = 0; // pixles 21 | int nr = 0; 22 | TestCase.assertFalse(msg, ih.isEnded()); 23 | int[][] im = new int[rows][cols]; 24 | do { 25 | nr++; 26 | // System.out.println("p="+ih.getPass() + " r="+ih.getCurrRowSubimg() + "/" + 27 | // ih.getRows()+ 28 | // " cols="+ih.getCols()); 29 | int colssub = ih.getCols(); 30 | for (int cc = 0; cc < colssub; cc++) { 31 | int x = ih.getoX() + cc * ih.getdX(); 32 | int y = ih.getCurrRowReal(); 33 | TestCase.assertEquals(msg, im[y][x], 0); 34 | im[y][x]++; 35 | } 36 | np += colssub; 37 | } while (ih.nextRow()); 38 | 39 | TestCase.assertEquals(msg, cols * rows, np); 40 | TestCase.assertEquals(msg, ih.getTotalRows(), nr); 41 | TestCase.assertTrue(msg, ih.isEnded()); 42 | 43 | } 44 | 45 | @Test 46 | public void checkAll() { 47 | for (int r = 1; r < 77; r++) 48 | for (int c = 1; c < 88; c++) 49 | test1(c, r); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkACTL.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngHelperInternal; 5 | 6 | /** 7 | * acTL chunk. For APGN, not PGN standard 8 | *

9 | * see 10 | * https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk 11 | *

12 | */ 13 | public class PngChunkACTL extends PngChunkSingle { 14 | public final static String ID = "acTL"; 15 | private int numFrames; 16 | private int numPlays; 17 | 18 | public PngChunkACTL(ImageInfo info) { 19 | super(ID, info); 20 | } 21 | 22 | @Override 23 | public ChunkOrderingConstraint getOrderingConstraint() { 24 | return ChunkOrderingConstraint.BEFORE_IDAT; 25 | } 26 | 27 | @Override 28 | public ChunkRaw createRawChunk() { 29 | ChunkRaw c = createEmptyChunk(8, true); 30 | PngHelperInternal.writeInt4tobytes((int) numFrames, c.data, 0); 31 | PngHelperInternal.writeInt4tobytes((int) numPlays, c.data, 4); 32 | return c; 33 | } 34 | 35 | @Override 36 | public void parseFromRaw(ChunkRaw chunk) { 37 | numFrames = PngHelperInternal.readInt4fromBytes(chunk.data, 0); 38 | numPlays = PngHelperInternal.readInt4fromBytes(chunk.data, 4); 39 | } 40 | 41 | public int getNumFrames() { 42 | return numFrames; 43 | } 44 | 45 | public void setNumFrames(int numFrames) { 46 | this.numFrames = numFrames; 47 | } 48 | 49 | public int getNumPlays() { 50 | return numPlays; 51 | } 52 | 53 | public void setNumPlays(int numPlays) { 54 | this.numPlays = numPlays; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleRemoveGama.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.PngReader; 6 | import ar.com.hjg.pngj.PngWriter; 7 | import ar.com.hjg.pngj.chunks.ChunkPredicate; 8 | import ar.com.hjg.pngj.chunks.PngChunk; 9 | import ar.com.hjg.pngj.chunks.PngChunkGAMA; 10 | 11 | /** 12 | * Remove GAMA chunk, if present 13 | * 14 | * These could be done more efficienty, by treating IDAT chunks as ancillary 15 | * chunks See RemoveChunks for an example 16 | * 17 | * 18 | */ 19 | public class SampleRemoveGama { 20 | 21 | public static void convert(String origFilename, String destFilename) { 22 | PngReader pngr = new PngReader(new File(origFilename)); 23 | PngWriter pngw = new PngWriter(new File(destFilename), pngr.imgInfo, false); 24 | pngw.setFilterPreserve(true); 25 | pngw.copyChunksFrom(pngr.getChunksList(), new ChunkPredicate() { 26 | public boolean match(PngChunk chunk) { 27 | return chunk.id.equals(PngChunkGAMA.ID); 28 | } 29 | }); 30 | for (int row = 0; row < pngr.imgInfo.rows; row++) { 31 | pngw.writeRow(pngr.readRow(row)); 32 | } 33 | pngw.end(); 34 | pngr.end(); 35 | } 36 | 37 | public static void main(String[] args) throws Exception { 38 | if (args.length != 2 || args[0].equals(args[1])) { 39 | System.err.println("Copies image removing gamma chunk (no color correction)"); 40 | System.err.println("Arguments: [pngsrc] [pngdest]"); 41 | System.exit(1); 42 | } 43 | convert(args[0], args[1]); 44 | System.out.println("Done. Result in " + args[1]); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkHIST.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngHelperInternal; 5 | import ar.com.hjg.pngj.PngjException; 6 | 7 | /** 8 | * hIST chunk. 9 | *

10 | * see http://www.w3.org/TR/PNG/#11hIST
11 | * only for palette images 12 | */ 13 | public class PngChunkHIST extends PngChunkSingle { 14 | public final static String ID = ChunkHelper.hIST; 15 | 16 | private int[] hist = new int[0]; // should have same lenght as palette 17 | 18 | public PngChunkHIST(ImageInfo info) { 19 | super(ID, info); 20 | } 21 | 22 | @Override 23 | public ChunkOrderingConstraint getOrderingConstraint() { 24 | return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT; 25 | } 26 | 27 | @Override 28 | public void parseFromRaw(ChunkRaw c) { 29 | if (!imgInfo.indexed) 30 | throw new PngjException("only indexed images accept a HIST chunk"); 31 | int nentries = c.data.length / 2; 32 | hist = new int[nentries]; 33 | for (int i = 0; i < hist.length; i++) { 34 | hist[i] = PngHelperInternal.readInt2fromBytes(c.data, i * 2); 35 | } 36 | } 37 | 38 | @Override 39 | public ChunkRaw createRawChunk() { 40 | if (!imgInfo.indexed) 41 | throw new PngjException("only indexed images accept a HIST chunk"); 42 | ChunkRaw c = null; 43 | c = createEmptyChunk(hist.length * 2, true); 44 | for (int i = 0; i < hist.length; i++) { 45 | PngHelperInternal.writeInt2tobytes(hist[i], c.data, i * 2); 46 | } 47 | return c; 48 | } 49 | 50 | public int[] getHist() { 51 | return hist; 52 | } 53 | 54 | public void setHist(int[] hist) { 55 | this.hist = hist; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/javadoc/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | PNGJ: a pure Java library for PNG image encoding/decoding 4 |

5 | Main features: 6 |

    7 |
  • Very efficient in memory usage and speed. 8 |
  • Pure Java (requires 5 or greater). 9 |
  • Small and self contained. No dependencies on third party libraries, nor even on java.awt.*/javax.imageio.* 10 |
  • Runs on GAE (Google App Engine) and Android 11 |
  • Allows to read/write progressively, row by row. This means that 12 | you can process huge images without needing to load them fully in memory. 13 |
  • Reads all PNG color models (true color, gray, palette, all bit depths: 1-2-4-8-16, 14 | with-without alpha). Interlaced PNG is supported (though not welcomed). 15 |
  • Writes all PNG color models - interlaced PNG writing is not supported. 16 |
  • Full support for metadata (CHUNKS) handling. 17 |
  • Supports (since 2.0) asyncronous reading. 18 |
  • The format of the pixel data (read and write) is extensible (since 2.0) 19 | and very efficient (no double copies). 20 |
  • Supports (since 2.0) low level tweaking and extension in the reader. 21 |
  • Open source (Apache 2.0 licence) 22 |
23 |

24 | Note that this is a relatively low-level library. 25 | It does not provide any high-level image processing (eg, resizing, 26 | colour conversions), nor tries to abstract the concrete image format 27 | (as BufferedImage does, for example). In particular, the default format 28 | of the scanlines (as wrapped in ImageLineInt or ImageLineByte) is not 29 | abstract, the meaning of the values depends on the image color model and bitdepth. 30 | 31 | 32 | 33 |

34 | 35 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/TestMisc.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.IImageLine; 6 | import ar.com.hjg.pngj.PngReader; 7 | import ar.com.hjg.pngj.PngWriter; 8 | 9 | /** 10 | * Methods of this class are designed for debug and testing PNGJ library, they 11 | * are not optimized 12 | */ 13 | public class TestMisc { 14 | 15 | /** intermixes two images (same size!) n rows from each */ 16 | public static void mixInBands(File f1, File f2, File dest, int nrowsband, boolean increaseband) { 17 | PngReader pngr1 = new PngReader(f1); 18 | PngReader pngr2 = new PngReader(f2); 19 | if (!pngr2.imgInfo.equals(pngr1.imgInfo)) 20 | throw new RuntimeException("must be same type"); 21 | PngWriter pngw = new PngWriter(dest, pngr1.imgInfo, false); 22 | pngw.copyChunksFrom(pngr1.getChunksList()); 23 | int which = 1; 24 | int nr = 0; 25 | for (int i = 0; i < pngr1.imgInfo.rows; i++) { 26 | IImageLine line1 = pngr1.readRow(); 27 | IImageLine line2 = pngr2.readRow(); 28 | pngw.writeRow(which == 1 ? line1 : line2); 29 | nr++; 30 | if (nr == nrowsband) { 31 | which = which == 2 ? 1 : which + 1; 32 | nr = 0; 33 | if (which == 1 && increaseband) 34 | nrowsband++; 35 | } 36 | } 37 | pngr1.end(); 38 | pngr2.end(); 39 | pngw.end(); 40 | System.out.println("done: see " + dest); 41 | } 42 | 43 | public static void main(String[] args) { 44 | File f1 = TestSupport.absFile(new File("..\\..\\priv\\imgsetx\\l\\nosuave.png")); 45 | File f2 = TestSupport.absFile(new File("..\\..\\priv\\imgsetx\\l\\suave.png")); 46 | File f3 = TestSupport.absFile(new File("..\\..\\priv\\imgsetx\\l\\suavenosuave2.png")); 47 | mixInBands(f1, f2, f3, 1, true); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IImageLine.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * General format-translated image line. 5 | *

6 | * The methods from this interface provides translation from/to PNG raw 7 | * unfiltered pixel data, for each image line. This doesn't make any assumptions 8 | * of underlying storage. 9 | *

10 | * The user of this library will not normally use this methods, but instead will 11 | * cast to a more concrete implementation, as {@link ImageLineInt} or 12 | * {@link ImageLineByte} with its methods for accessing the pixel values. 13 | */ 14 | public interface IImageLine { 15 | 16 | /** 17 | * Extract pixels from a raw unlfiltered PNG row. Len is the total amount of 18 | * bytes in the array, including the first byte (filter type) 19 | * 20 | * Arguments offset and step (0 and 1 for non interlaced) are in PIXELS. 21 | * It's guaranteed that when step==1 then offset=0 22 | * 23 | * Notice that when step!=1 the data is partial, this method will be called 24 | * several times 25 | * 26 | * Warning: the data in array 'raw' starts at position 0 and has 'len' 27 | * consecutive bytes. 'offset' and 'step' refer to the pixels in destination 28 | */ 29 | void readFromPngRaw(byte[] raw, int len, int offset, int step); 30 | 31 | /** 32 | * This is called when the read for the line has been completed (eg for 33 | * interlaced). It's called exactly once for each line. This is provided in 34 | * case the class needs to to some postprocessing. 35 | */ 36 | void endReadFromPngRaw(); 37 | 38 | /** 39 | * Writes the line to a PNG raw byte array, in the unfiltered PNG format 40 | * Notice that the first byte is the filter type, you should write it only 41 | * if you know it. 42 | * 43 | */ 44 | void writeToPngRaw(byte[] raw); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleCreateStripes.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.ImageInfo; 6 | import ar.com.hjg.pngj.ImageLineHelper; 7 | import ar.com.hjg.pngj.ImageLineInt; 8 | import ar.com.hjg.pngj.PngWriter; 9 | import ar.com.hjg.pngj.chunks.PngChunkTextVar; 10 | 11 | /** 12 | * grayscale image - distorted diagonal stripes 13 | */ 14 | public class SampleCreateStripes { 15 | 16 | public static void makeTestImage(PngWriter png) { 17 | int cols = png.imgInfo.cols; 18 | int rows = png.imgInfo.rows; 19 | png.getMetadata().setDpi(123.0); 20 | png.getMetadata().setTimeNow(0); 21 | png.getMetadata().setText(PngChunkTextVar.KEY_Software, "pngj test"); 22 | double t1 = (cols + rows) / 16.0; // typical period 23 | ImageLineInt iline = new ImageLineInt(png.imgInfo); 24 | png.setIdatMaxSize(2000); 25 | for (int i = 0; i < rows; i++) { 26 | double fase = Math.sin(1.3 * i / t1); 27 | for (int j = 0; j < cols; j++) { 28 | double sin = Math.sin((i + j) * Math.PI / t1 + fase); 29 | iline.getScanline()[j] = ImageLineHelper.clampTo_0_255((int) ((sin + 1) * 127 + 0.5)); 30 | } 31 | png.writeRow(iline, i); 32 | } 33 | png.end(); 34 | } 35 | 36 | public static void createTest(String name, int cols, int rows) { 37 | PngWriter i2 = new PngWriter(new File(name), new ImageInfo(cols, rows, 8, false, true, false), true); 38 | makeTestImage(i2); 39 | System.out.println("Done: " + name); 40 | } 41 | 42 | public static void main(String[] args) throws Exception { 43 | if (args.length < 3) { 44 | System.err.println("Arguments: [pngdest] [cols] [rows]"); 45 | System.exit(1); 46 | } 47 | int cols = Integer.parseInt(args[1]); 48 | int rows = Integer.parseInt(args[2]); 49 | createTest(args[0], cols, rows); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/RowInfo.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Packs information of current row. Only used internally 5 | */ 6 | class RowInfo { 7 | public final ImageInfo imgInfo; 8 | public final Deinterlacer deinterlacer; 9 | public final boolean imode; // Interlaced 10 | int dY, dX, oY, oX; // current step and offset (in pixels) 11 | int rowNseq; // row number (from 0) in sequential read order 12 | int rowNreal; // row number in the real image 13 | int rowNsubImg; // current row in the virtual subsampled image; this increments (by 1) from 0 to rows/dy 7 times 14 | int rowsSubImg, colsSubImg; // size of current subimage , in pixels 15 | int bytesRow; 16 | int pass; // 1-7 17 | byte[] buf; // non-deep copy 18 | int buflen; // valid bytes in buffer (include filter byte) 19 | 20 | public RowInfo(ImageInfo imgInfo, Deinterlacer deinterlacer) { 21 | this.imgInfo = imgInfo; 22 | this.deinterlacer = deinterlacer; 23 | this.imode = deinterlacer != null; 24 | } 25 | 26 | void update(int rowseq) { 27 | rowNseq = rowseq; 28 | if (imode) { 29 | pass = deinterlacer.getPass(); 30 | dX = deinterlacer.dX; 31 | dY = deinterlacer.dY; 32 | oX = deinterlacer.oX; 33 | oY = deinterlacer.oY; 34 | rowNreal = deinterlacer.getCurrRowReal(); 35 | rowNsubImg = deinterlacer.getCurrRowSubimg(); 36 | rowsSubImg = deinterlacer.getRows(); 37 | colsSubImg = deinterlacer.getCols(); 38 | bytesRow = (imgInfo.bitspPixel * colsSubImg + 7) / 8; 39 | } else { 40 | pass = 1; 41 | dX = dY = 1; 42 | oX = oY = 0; 43 | rowNreal = rowNsubImg = rowseq; 44 | rowsSubImg = imgInfo.rows; 45 | colsSubImg = imgInfo.cols; 46 | bytesRow = imgInfo.bytesPerRow; 47 | } 48 | } 49 | 50 | void updateBuf(byte[] buf, int buflen) { 51 | this.buf = buf; 52 | this.buflen = buflen; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/resources/misc/mvn_notes.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | To update version (normally not needed) 4 | mvn versions:set -DnewVersion=1.0.3-SNAPSHOT 5 | 6 | RUN mvn from GIT bash, from inside pngj/ 7 | 8 | javadoc: 9 | mvn javadoc:javadoc 10 | mvn javadoc:jar 11 | 12 | jar: 13 | mvn install 14 | mvn install -DskipTests 15 | mvn source:test-jar 16 | mvn source:jar 17 | mvn source:test-jar 18 | 19 | dist: 20 | mvn assembly:single 21 | 22 | === uploads snapshot (see first that you have GPG + GIT working) 23 | ( git push should work without password ) 24 | ( gpg --list-keys should work) 25 | 26 | mvn clean deploy 27 | 28 | === upload releASE to sonatype: 29 | https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide#SonatypeOSSMavenRepositoryUsageGuide-7a.DeploySnapshotsandStageReleaseswithMaven 30 | 31 | mvn release:clean 32 | mvn release:prepare WARNING: this uploads to git!!! 33 | mvn release:perform 34 | 35 | After this, the artifacts are deployed to sonatype 36 | https://oss.sonatype.org/content/repositories/snapshots/ar/com/hjg/pngj/ 37 | 38 | To release to central repository: http://central.sonatype.org/pages/releasing-the-deployment.html 39 | 40 | 41 | https://oss.sonatype.org/ 42 | 43 | Login at 44 | 45 | https://oss.sonatype.org 46 | 47 | (don't be fooled by the 2.1.0.SNAPSHOT repository, that does not matter) 48 | Look into "Staging Repositories", check that the latest included the three artifacts (jar,source, javadocs), and "close" it 49 | (to "close" it means that you can't add artifacts (jars) to it) 50 | YOu should receive a mail when done. 51 | 52 | Then, release it. One it appears in the main list, to should be sync with central Maven automatically in several hours 53 | 54 | --------- 55 | Problem:; CLM data is not available for this artifact 56 | (this is not to worry) 57 | 58 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleMirrorImage.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.ImageInfo; 6 | import ar.com.hjg.pngj.ImageLineInt; 7 | import ar.com.hjg.pngj.PngReader; 8 | import ar.com.hjg.pngj.PngWriter; 9 | import ar.com.hjg.pngj.chunks.ChunkCopyBehaviour; 10 | 11 | /** 12 | * Mirrors an image, along the rows. This works for ALL image types, see also 13 | * TestPngSuite 14 | */ 15 | public class SampleMirrorImage { 16 | 17 | public static void mirror(File orig, File dest, boolean overwrite) { 18 | PngReader pngr = new PngReader(orig); 19 | PngWriter pngw = new PngWriter(dest, pngr.imgInfo, overwrite); 20 | pngw.copyChunksFrom(pngr.getChunksList(), ChunkCopyBehaviour.COPY_ALL_SAFE); 21 | for (int row = 0; row < pngr.imgInfo.rows; row++) { 22 | ImageLineInt line = (ImageLineInt) pngr.readRow(row); 23 | mirrorLineInt(pngr.imgInfo, line.getScanline()); 24 | pngw.writeRow(line, row); 25 | } 26 | pngr.end(); 27 | pngw.end(); 28 | } 29 | 30 | private static void mirrorLineInt(ImageInfo imgInfo, int[] line) { // unpacked line 31 | int channels = imgInfo.channels; 32 | for (int c1 = 0, c2 = imgInfo.cols - 1; c1 < c2; c1++, c2--) { // swap pixels (not samples!) 33 | for (int i = 0; i < channels; i++) { 34 | int aux = line[c1 * channels + i]; 35 | line[c1 * channels + i] = line[c2 * channels + i]; 36 | line[c2 * channels + i] = aux; 37 | } 38 | } 39 | } 40 | 41 | public static void main(String[] args) throws Exception { 42 | if (args.length != 2 || args[0].equals(args[1])) { 43 | System.err.println("Arguments: [pngsrc] [pngdest]"); 44 | System.exit(1); 45 | } 46 | File file1 = new File(args[0]); 47 | File file2 = new File(args[1]); 48 | mirror(file1, file2, false); 49 | System.out.printf("Done: %s -> %s\n", file1.toString(), file2.toString()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PNGJ: Java library for PNG encoding 2 | 3 | PNGJ is a pure Java library for high performance reading and writing of PNG images 4 | 5 | --- 6 | 7 | ## Downloads 8 | 9 | You can download the latest release from here http://hjg.com.ar/pngj/ or use the [Maven Central repository](https://search.maven.org/search?q=pngj) 10 | 11 | ## Main features 12 | 13 | * Very efficient in memory usage and speed 14 | * Pure Java (8 or greater) 15 | * Small and self contained. No dependencies on third party libraries, nor even on `java.awt.*` or `javax.imageio.*` 16 | * Runs on __Android__ and __GAE__ (Google App Engine) 17 | * Allows to read and write progressively, row by row. This means that you can process huge images without needing to load them fully in memory. 18 | * Reads and writes all PNG color models. Interlaced PNG is supported (though not welcomed) for reading. 19 | * Full support for __metadata__ handling ("chunks"). 20 | * The format of the pixel data (for read and write) is extensible and efficient (no double copies). 21 | * Supports asyncronous reading and low level tweaking and extension in the reader. 22 | * Basic support for APNG reading 23 | * Open source (Apache licence). Available in Maven Central repository. 24 | 25 | ## What is this for? 26 | 27 | This is a relatively low level library, its goal is to code and decode PNG images from/to raw pixels, optimizing memory usage and speed. 28 | It does not provide any high-level image processing (eg, resizing, colour conversions), it does not try to abstract the concrete PNG color model (as `BufferedImage` does, for example). 29 | In particular, the default format of the scanlines (as wrapped in `ImageLineInt` or `ImageLineByte`) is not abstract, the meaning of the values depends on the image color model and bitdepth. 30 | 31 | ## More documentation 32 | 33 | * [Javadocs](http://hjg.com.ar/pngj/apidocs/) 34 | * [Wiki](https://github.com/leonbloy/pngj/wiki) 35 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkFDAT.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngHelperInternal; 5 | import ar.com.hjg.pngj.PngjException; 6 | 7 | /** 8 | * fdAT chunk. For APGN, not PGN standard 9 | *

10 | * see 11 | * https://wiki.mozilla.org/APNG_Specification#.60fdAT.60:_The_Frame_Data_Chunk 12 | *

13 | * This implementation does not support buffering, this should be not managed 14 | * similar to a IDAT chunk 15 | * 16 | */ 17 | public class PngChunkFDAT extends PngChunkMultiple { 18 | public final static String ID = "fdAT"; 19 | private int seqNum; 20 | private byte[] buffer; // normally not allocated - if so, it's the raw data, includes the 4bytes seqNum 21 | int datalen; // length of idat data, excluding seqNUm (= chunk.len-4) 22 | 23 | public PngChunkFDAT(ImageInfo info) { 24 | super(ID, info); 25 | } 26 | 27 | @Override 28 | public ChunkOrderingConstraint getOrderingConstraint() { 29 | return ChunkOrderingConstraint.AFTER_IDAT; 30 | } 31 | 32 | @Override 33 | public ChunkRaw createRawChunk() { 34 | if (buffer == null) 35 | throw new PngjException("not buffered"); 36 | ChunkRaw c = createEmptyChunk(datalen + 4, false); 37 | c.data = buffer; // shallow copy! 38 | return c; 39 | } 40 | 41 | @Override 42 | public void parseFromRaw(ChunkRaw chunk) { 43 | seqNum = PngHelperInternal.readInt4fromBytes(chunk.data, 0); 44 | datalen = chunk.len - 4; 45 | buffer = chunk.data; 46 | } 47 | 48 | public int getSeqNum() { 49 | return seqNum; 50 | } 51 | 52 | public void setSeqNum(int seqNum) { 53 | this.seqNum = seqNum; 54 | } 55 | 56 | public byte[] getBuffer() { 57 | return buffer; 58 | } 59 | 60 | public void setBuffer(byte[] buffer) { 61 | this.buffer = buffer; 62 | } 63 | 64 | public int getDatalen() { 65 | return datalen; 66 | } 67 | 68 | public void setDatalen(int datalen) { 69 | this.datalen = datalen; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleConvPalToTrueColor.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.ImageInfo; 6 | import ar.com.hjg.pngj.ImageLineHelper; 7 | import ar.com.hjg.pngj.ImageLineInt; 8 | import ar.com.hjg.pngj.PngReader; 9 | import ar.com.hjg.pngj.PngWriter; 10 | import ar.com.hjg.pngj.chunks.ChunkCopyBehaviour; 11 | import ar.com.hjg.pngj.chunks.PngChunkPLTE; 12 | import ar.com.hjg.pngj.chunks.PngChunkTRNS; 13 | 14 | /** 15 | * This converts a paletted image to a True color image If the image has 16 | * transparency (tRNS chunk) it generates a RGBA image, elsewhere a RGB 17 | */ 18 | public class SampleConvPalToTrueColor { 19 | 20 | public static void convertToTc(File orig, File copy) { 21 | PngReader pngr = new PngReader(orig); 22 | if (!pngr.imgInfo.indexed) 23 | throw new RuntimeException("Not indexed image"); 24 | PngChunkPLTE plte = pngr.getMetadata().getPLTE(); 25 | PngChunkTRNS trns = pngr.getMetadata().getTRNS(); // transparency metadata, can be null 26 | boolean alpha = trns != null; 27 | ImageInfo im2 = new ImageInfo(pngr.imgInfo.cols, pngr.imgInfo.rows, 8, alpha); 28 | PngWriter pngw = new PngWriter(copy, im2, false); 29 | pngw.copyChunksFrom(pngr.getChunksList(), ChunkCopyBehaviour.COPY_ALL_SAFE); 30 | int[] buf = null; 31 | for (int row = 0; row < pngr.imgInfo.rows; row++) { 32 | ImageLineInt line1 = (ImageLineInt) pngr.readRow(row); 33 | buf = ImageLineHelper.palette2rgb(line1, plte, trns, buf); 34 | ImageLineInt line2 = new ImageLineInt(pngw.imgInfo, buf); 35 | pngw.writeRow(line2); 36 | } 37 | pngr.end(); 38 | pngw.end(); 39 | } 40 | 41 | public static void main(String[] args) throws Exception { 42 | if (args.length != 2 || args[0].equals(args[1])) { 43 | System.err.println("Arguments: [pngsrc] [pngdest]"); 44 | System.exit(1); 45 | } 46 | convertToTc(new File(args[0]), new File(args[1])); 47 | System.out.println("Done: " + args[1]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleCreateOrangeGradient.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.OutputStream; 6 | 7 | import ar.com.hjg.pngj.ImageInfo; 8 | import ar.com.hjg.pngj.ImageLineHelper; 9 | import ar.com.hjg.pngj.ImageLineInt; 10 | import ar.com.hjg.pngj.PngWriter; 11 | import ar.com.hjg.pngj.chunks.PngChunkTextVar; 12 | 13 | public class SampleCreateOrangeGradient { 14 | 15 | private static void create(OutputStream outputStream, int cols, int rows) { 16 | ImageInfo imi = new ImageInfo(cols, rows, 8, false); // 8 bits per channel, no alpha 17 | // open image for writing to a output stream 18 | PngWriter png = new PngWriter(outputStream, imi); 19 | // add some optional metadata (chunks) 20 | png.getMetadata().setDpi(100.0); 21 | png.getMetadata().setTimeNow(0); // 0 seconds fron now = now 22 | png.getMetadata().setText(PngChunkTextVar.KEY_Title, "just a text image"); 23 | png.getMetadata().setText("my key", "my text"); 24 | ImageLineInt iline = new ImageLineInt(imi); 25 | for (int col = 0; col < imi.cols; col++) { // this line will be written to all rows 26 | int r = 255; 27 | int g = 127; 28 | int b = 255 * col / imi.cols; 29 | ImageLineHelper.setPixelRGB8(iline, col, r, g, b); // orange-ish gradient 30 | } 31 | for (int row = 0; row < png.imgInfo.rows; row++) { 32 | png.writeRow(iline); 33 | } 34 | png.end(); 35 | } 36 | 37 | public static void main(String[] args) throws Exception { 38 | if (args.length < 3) { 39 | System.err.println("Arguments: [pngdest] [cols] [rows]"); 40 | System.exit(1); 41 | } 42 | int cols = Integer.parseInt(args[1]); 43 | int rows = Integer.parseInt(args[2]); 44 | File file = new File(args[0]); 45 | if (file.exists()) 46 | throw new Exception("Cowardly refusing to overwrite " + file); 47 | create(new FileOutputStream(file), cols, rows); 48 | System.out.println(file + " created"); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/awt/PngReaderBI.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.awt; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.File; 5 | import java.io.InputStream; 6 | 7 | import ar.com.hjg.pngj.IImageLine; 8 | import ar.com.hjg.pngj.IImageLineSet; 9 | import ar.com.hjg.pngj.PngReader; 10 | import ar.com.hjg.pngj.awt.ImageLineBI.Png2BufferedImageAdapter; 11 | import ar.com.hjg.pngj.chunks.PngChunkPLTE; 12 | import ar.com.hjg.pngj.chunks.PngChunkTRNS; 13 | 14 | public class PngReaderBI extends PngReader { 15 | 16 | boolean preferCustomInsteadOfBGR = true; 17 | 18 | public PngReaderBI(File file) { 19 | super(file); 20 | } 21 | 22 | public PngReaderBI(InputStream inputStream, boolean shouldCloseStream) { 23 | super(inputStream, shouldCloseStream); 24 | } 25 | 26 | public PngReaderBI(InputStream inputStream) { 27 | super(inputStream); 28 | } 29 | 30 | @Override 31 | protected IImageLineSet createLineSet(boolean singleCursor, int nlines, int noffset, 32 | int step) { 33 | PngChunkPLTE pal = (PngChunkPLTE) getChunksList().getById1(PngChunkPLTE.ID);// perhaps null; 34 | PngChunkTRNS trns = (PngChunkTRNS) getChunksList().getById1(PngChunkTRNS.ID);// perhaps null; 35 | Png2BufferedImageAdapter adapter = new Png2BufferedImageAdapter(getCurImgInfo(), pal, trns); 36 | adapter.setPreferCustom(preferCustomInsteadOfBGR); 37 | return new ImageLineSetBI(getCurImgInfo(), adapter, singleCursor, nlines, noffset, step); 38 | } 39 | 40 | public void setPreferCustomInsteadOfBGR(boolean b) { 41 | preferCustomInsteadOfBGR = b; 42 | } 43 | 44 | public ImageLineSetBI getImageLineSetBI() { 45 | if (imlinesSet != null) 46 | return (ImageLineSetBI) imlinesSet; 47 | else 48 | return null; 49 | } 50 | 51 | public BufferedImage readAll() { 52 | readRows(); 53 | end(); 54 | return getImageLineSetBI().image; 55 | } 56 | 57 | public BufferedImage readAll(int lines, int offset, int step) { 58 | readRows(lines, offset, step); 59 | end(); 60 | return getImageLineSetBI().image; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkZTXT.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | 6 | import ar.com.hjg.pngj.ImageInfo; 7 | import ar.com.hjg.pngj.PngjException; 8 | 9 | /** 10 | * zTXt chunk. 11 | *

12 | * see http://www.w3.org/TR/PNG/#11zTXt 13 | */ 14 | public class PngChunkZTXT extends PngChunkTextVar { 15 | public final static String ID = ChunkHelper.zTXt; 16 | 17 | // http://www.w3.org/TR/PNG/#11zTXt 18 | public PngChunkZTXT(ImageInfo info) { 19 | super(ID, info); 20 | } 21 | 22 | @Override 23 | public ChunkRaw createRawChunk() { 24 | if (key == null || key.trim().length() == 0) 25 | throw new PngjException("Text chunk key must be non empty"); 26 | try { 27 | ByteArrayOutputStream ba = new ByteArrayOutputStream(); 28 | ba.write(ChunkHelper.toBytesLatin1(key)); 29 | ba.write(0); // separator 30 | ba.write(0); // compression method: 0 31 | byte[] textbytes = ChunkHelper.compressBytes(ChunkHelper.toBytesLatin1(val), true); 32 | ba.write(textbytes); 33 | byte[] b = ba.toByteArray(); 34 | ChunkRaw chunk = createEmptyChunk(b.length, false); 35 | chunk.data = b; 36 | return chunk; 37 | } catch (IOException e) { 38 | throw new PngjException(e); 39 | } 40 | } 41 | 42 | @Override 43 | public void parseFromRaw(ChunkRaw c) { 44 | int nullsep = -1; 45 | for (int i = 0; i < c.data.length; i++) { // look for first zero 46 | if (c.data[i] != 0) 47 | continue; 48 | nullsep = i; 49 | break; 50 | } 51 | if (nullsep < 0 || nullsep > c.data.length - 2) 52 | throw new PngjException("bad zTXt chunk: no separator found"); 53 | key = ChunkHelper.toStringLatin1(c.data, 0, nullsep); 54 | int compmet = (int) c.data[nullsep + 1]; 55 | if (compmet != 0) 56 | throw new PngjException("bad zTXt chunk: unknown compression method"); 57 | byte[] uncomp = ChunkHelper.compressBytes(c.data, nullsep + 2, c.data.length - nullsep - 2, false); // uncompress 58 | val = ChunkHelper.toStringLatin1(uncomp); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/RemoveChunksNgTest.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import java.io.File; 4 | 5 | import junit.framework.TestCase; 6 | 7 | import org.junit.Test; 8 | 9 | import ar.com.hjg.pngj.PngjException; 10 | import ar.com.hjg.pngj.cli.RemoveChunks; 11 | 12 | public class RemoveChunksNgTest { 13 | 14 | @Test 15 | public void test1() throws Exception { 16 | File ori = TestSupport.absFile(TestSupport.PNG_TEST_STRIPES2); 17 | File dest = newFile(); 18 | 19 | RemoveChunks.run(new String[] { "-kPHYS", "-q", ori.toString(), dest.toString() }); 20 | String oric = TestSupport.getChunksSummary(ori.toString(), true); 21 | String destc = TestSupport.getChunksSummary(dest.toString(), false); 22 | TestCase.assertEquals( 23 | "IHDR[13] pHYs[9] tEXt[19] IDAT[2000] IDAT[2000] IDAT[2000] IDAT[610] tIME[7] tEXt[18] IEND[0] ", oric); 24 | TestCase.assertEquals("IHDR[13] pHYs[9] IDAT[2000] IDAT[2000] IDAT[2000] IDAT[610] IEND[0] ", destc); 25 | } 26 | 27 | @Test 28 | public void test3() throws Exception { 29 | // will work even with bad CRC 30 | File ori = TestSupport.absFile(TestSupport.PNG_TEST_BADCRC); 31 | File dest = newFile(); 32 | 33 | RemoveChunks.run(new String[] { "-q", "-f", "-rTIME,PHYS", ori.toString(), dest.toString() }); 34 | String oric = TestSupport.getChunksSummary(ori.toString(), true); 35 | String destc = TestSupport.getChunksSummary(dest.toString(), true); 36 | TestCase.assertEquals("IHDR[13] pHYs[9] IDAT[65] IEND[0] ", oric); 37 | TestCase.assertEquals("IHDR[13] IDAT[65] IEND[0] ", destc); 38 | } 39 | 40 | @Test(expected = PngjException.class) 41 | public void test4() throws Exception { 42 | // NON FAST MODE; CHECKS CRC 43 | File ori = TestSupport.absFile(TestSupport.PNG_TEST_BADCRC); 44 | File dest = newFile(); 45 | 46 | RemoveChunks.run(new String[] { "-q", "-rTIME,PHYS", ori.toString(), dest.toString() }); 47 | } 48 | 49 | private File newFile() { 50 | File f = new File(TestSupport.getTempDir(), "RemoveChunksNgTest.png"); 51 | f.deleteOnExit(); 52 | return f; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkOFFS.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngHelperInternal; 5 | import ar.com.hjg.pngj.PngjException; 6 | 7 | /** 8 | * oFFs chunk. 9 | *

10 | * see http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.oFFs 11 | */ 12 | public class PngChunkOFFS extends PngChunkSingle { 13 | public final static String ID = "oFFs"; 14 | 15 | // http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.oFFs 16 | private long posX; 17 | private long posY; 18 | private int units; // 0: pixel 1:micrometer 19 | 20 | public PngChunkOFFS(ImageInfo info) { 21 | super(ID, info); 22 | } 23 | 24 | @Override 25 | public ChunkOrderingConstraint getOrderingConstraint() { 26 | return ChunkOrderingConstraint.BEFORE_IDAT; 27 | } 28 | 29 | @Override 30 | public ChunkRaw createRawChunk() { 31 | ChunkRaw c = createEmptyChunk(9, true); 32 | PngHelperInternal.writeInt4tobytes((int) posX, c.data, 0); 33 | PngHelperInternal.writeInt4tobytes((int) posY, c.data, 4); 34 | c.data[8] = (byte) units; 35 | return c; 36 | } 37 | 38 | @Override 39 | public void parseFromRaw(ChunkRaw chunk) { 40 | if (chunk.len != 9) 41 | throw new PngjException("bad chunk length " + chunk); 42 | posX = PngHelperInternal.readInt4fromBytes(chunk.data, 0); 43 | if (posX < 0) 44 | posX += 0x100000000L; 45 | posY = PngHelperInternal.readInt4fromBytes(chunk.data, 4); 46 | if (posY < 0) 47 | posY += 0x100000000L; 48 | units = PngHelperInternal.readInt1fromByte(chunk.data, 8); 49 | } 50 | 51 | /** 52 | * 0: pixel, 1:micrometer 53 | */ 54 | public int getUnits() { 55 | return units; 56 | } 57 | 58 | /** 59 | * 0: pixel, 1:micrometer 60 | */ 61 | public void setUnits(int units) { 62 | this.units = units; 63 | } 64 | 65 | public long getPosX() { 66 | return posX; 67 | } 68 | 69 | public void setPosX(long posX) { 70 | this.posX = posX; 71 | } 72 | 73 | public long getPosY() { 74 | return posY; 75 | } 76 | 77 | public void setPosY(long posY) { 78 | this.posY = posY; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkTextVar.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | 5 | /** 6 | * Superclass (abstract) for three textual chunks (TEXT, ITXT, ZTXT) 7 | */ 8 | public abstract class PngChunkTextVar extends PngChunkMultiple { 9 | protected String key; // key/val: only for tEXt. lazy computed 10 | protected String val; 11 | 12 | // http://www.w3.org/TR/PNG/#11keywords 13 | public final static String KEY_Title = "Title"; // Short (one line) title or caption for image 14 | public final static String KEY_Author = "Author"; // Name of image's creator 15 | public final static String KEY_Description = "Description"; // Description of image (possibly long) 16 | public final static String KEY_Copyright = "Copyright"; // Copyright notice 17 | public final static String KEY_Creation_Time = "Creation Time"; // Time of original image creation 18 | public final static String KEY_Software = "Software"; // Software used to create the image 19 | public final static String KEY_Disclaimer = "Disclaimer"; // Legal disclaimer 20 | public final static String KEY_Warning = "Warning"; // Warning of nature of content 21 | public final static String KEY_Source = "Source"; // Device used to create the image 22 | public final static String KEY_Comment = "Comment"; // Miscellaneous comment 23 | 24 | protected PngChunkTextVar(String id, ImageInfo info) { 25 | super(id, info); 26 | } 27 | 28 | @Override 29 | public ChunkOrderingConstraint getOrderingConstraint() { 30 | return ChunkOrderingConstraint.NONE; 31 | } 32 | 33 | public static class PngTxtInfo { 34 | public String title; 35 | public String author; 36 | public String description; 37 | public String creation_time;// = (new Date()).toString(); 38 | public String software; 39 | public String disclaimer; 40 | public String warning; 41 | public String source; 42 | public String comment; 43 | 44 | } 45 | 46 | public String getKey() { 47 | return key; 48 | } 49 | 50 | public String getVal() { 51 | return val; 52 | } 53 | 54 | public void setKeyVal(String key, String val) { 55 | this.key = key; 56 | this.val = val; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/ChunkSeqSkipping.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import ar.com.hjg.pngj.ChunkReader.ChunkReaderMode; 7 | import ar.com.hjg.pngj.chunks.ChunkRaw; 8 | 9 | /** 10 | * This simple reader skips all chunks contents and stores the chunkRaw in a 11 | * list. Useful to read chunks structure. 12 | * 13 | * Optionally the contents might be processed. This doesn't distinguish IDAT 14 | * chunks 15 | */ 16 | public class ChunkSeqSkipping extends ChunkSeqReader { 17 | 18 | private List chunks = new ArrayList(); 19 | private boolean skip = true; 20 | 21 | /** 22 | * @param skipAll 23 | * if true, contents will be truly skipped, and CRC will not be 24 | * computed 25 | */ 26 | public ChunkSeqSkipping(boolean skipAll) { 27 | super(); 28 | skip = skipAll; 29 | } 30 | 31 | public ChunkSeqSkipping() { 32 | this(true); 33 | } 34 | 35 | protected ChunkReader createChunkReaderForNewChunk(String id, int len, long offset, boolean skip) { 36 | return new ChunkReader(len, id, offset, skip ? ChunkReaderMode.SKIP : ChunkReaderMode.PROCESS) { 37 | @Override 38 | protected void chunkDone() { 39 | postProcessChunk(this); 40 | } 41 | 42 | @Override 43 | protected void processData(int offsetinChhunk, byte[] buf, int off, int len) { 44 | processChunkContent(getChunkRaw(), offsetinChhunk, buf, off, len); 45 | } 46 | }; 47 | } 48 | 49 | protected void processChunkContent(ChunkRaw chunkRaw, int offsetinChhunk, byte[] buf, int off, int len) { 50 | // does nothing 51 | } 52 | 53 | @Override 54 | protected void postProcessChunk(ChunkReader chunkR) { 55 | super.postProcessChunk(chunkR); 56 | chunks.add(chunkR.getChunkRaw()); 57 | } 58 | 59 | @Override 60 | protected boolean shouldSkipContent(int len, String id) { 61 | return skip; 62 | } 63 | 64 | @Override 65 | protected boolean isIdatKind(String id) { 66 | return false; 67 | } 68 | 69 | public List getChunks() { 70 | return chunks; 71 | } 72 | 73 | @Override 74 | protected DeflatedChunksSet createIdatSet(String id) { 75 | throw new RuntimeException("Should not get here"); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/cli/ShowFilterInfo.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.cli; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | import ar.com.hjg.pngj.test.TestSupport; 7 | 8 | /** 9 | * See help 10 | */ 11 | public class ShowFilterInfo { 12 | static StringBuilder help = new StringBuilder(); 13 | 14 | public static void run(String[] args) { 15 | 16 | help.append(" Shows row filtering info for PNG files. \n"); 17 | help.append(" Options: \n"); 18 | help.append(" -n: use newlines \n"); 19 | help.append(" -s: summary \n"); 20 | help.append(" -sp: summary with percentajes \n"); 21 | help.append(" -g[num]: maximum number of groups to show (0:none -1:all) (default:5) \n"); 22 | help.append(" Accepts paths in the form 'mypath/*' (all pngs in dir) or 'mypath/**' (idem recursive) \n"); 23 | 24 | CliArgs cli = CliArgs.buildFrom(args, help); 25 | cli.checkAtLeastNargs(1); 26 | ShowFilterInfo me = new ShowFilterInfo(); 27 | me.useNewlines = cli.hasOpt("n"); 28 | me.withSummary = cli.hasOpt("s"); 29 | me.withSummaryPercent = cli.getOpt("s", "").startsWith("p"); 30 | me.maxGroupsToShow = Integer.parseInt(cli.getOpt("g", "5")); 31 | me.listpng = cli.listPngsFromArgs(); 32 | cli.checkNoMoreOpts(); 33 | if (!(me.withSummary || me.withSummaryPercent || me.maxGroupsToShow != 0)) 34 | cli.badUsageAbort("You must either specify a summary or a non-zero group size"); 35 | me.doit(); 36 | } 37 | 38 | private List listpng; 39 | private boolean useNewlines = false; 40 | private boolean withSummaryPercent = false; 41 | private boolean withSummary = false; 42 | private int maxGroupsToShow; 43 | 44 | private void doit() { 45 | for (File f : listpng) 46 | doitForFile(f); 47 | } 48 | 49 | public void doitForFile(File file) { 50 | System.out.printf("%s\t", file.toString()); 51 | try { 52 | String info = TestSupport.showFilters(file, maxGroupsToShow, useNewlines, withSummary, withSummaryPercent); 53 | System.out.printf("%s", info); 54 | } catch (Exception e) { 55 | System.out.printf("%s : %s", ShowPngInfo.BAD_OR_NOT_PNG, e.getMessage()); 56 | } 57 | System.out.println(""); 58 | } 59 | 60 | public static void main(String[] args) { 61 | run(args); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | PNGJ main package 5 |

6 |

7 | Users of this library should rarely need more than the public members of this package.
8 | Newcomers: start with PngReader and PngWriter. 9 |

10 |

11 | Example of use: this code reads a true colour PNG image (RGB8 or RGBA8) 12 | and reduces the red channel by half, increasing the green by 20. 13 | It copies all the "safe" metadata from the original image, and adds a textual metadata. 14 | 15 |

16 |   public static void convert(String origFilename, String destFilename) {
17 |     // you can also use PngReader (esentially the same) or PngReaderByte 
18 |     PngReaderInt pngr = new PngReaderInt(new File(origFilename));  
19 |     System.out.println(pngr.toString());
20 |     int channels = pngr.imgInfo.channels;
21 |     if (channels < 3 || pngr.imgInfo.bitDepth != 8)
22 |        throw new RuntimeException("For simplicity this supports only RGB8/RGBA8 images");
23 |     // writer with same image properties as original
24 |     PngWriter pngw = new PngWriter(new File(destFilename), pngr.imgInfo, true);
25 |     // instruct the writer to grab all ancillary chunks from the original
26 |     pngw.copyChunksFrom(pngr.getChunksList(), ChunkCopyBehaviour.COPY_ALL_SAFE);
27 |     // add a textual chunk to writer
28 |     pngw.getMetadata().setText(PngChunkTextVar.KEY_Description, "Decreased red and increased green");
29 |     // also: while(pngr.hasMoreRows())
30 |     for (int row = 0; row < pngr.imgInfo.rows; row++) {  
31 |        ImageLineInt l1 = pngr.readRowInt(); // each element is a sample
32 |        int[] scanline = l1.getScanline(); // to save typing
33 |        for (int j = 0; j < pngr.imgInfo.cols; j++) {
34 |           scanline[j * channels] /= 2;
35 |           scanline[j * channels + 1] = ImageLineHelper.clampTo_0_255(scanline[j * channels + 1] + 20);
36 |        }
37 |        pngw.writeRow(l1);
38 |     }
39 |     pngr.end(); // it's recommended to end the reader first, in case there are trailing chunks to read
40 |     pngw.end();
41 |  }
42 | 
43 | 
44 | 45 | For more examples, see the tests and samples. 46 | 47 |

48 | 49 | 50 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/CreateHuge.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.OutputStream; 6 | 7 | import ar.com.hjg.pngj.FilterType; 8 | import ar.com.hjg.pngj.ImageInfo; 9 | import ar.com.hjg.pngj.ImageLineHelper; 10 | import ar.com.hjg.pngj.ImageLineInt; 11 | import ar.com.hjg.pngj.PngWriter; 12 | import ar.com.hjg.pngj.pixels.PixelsWriterDefault; 13 | import ar.com.hjg.pngj.test.TestSupport; 14 | 15 | /** 16 | * Creates a huge image 17 | *

18 | * This is mainly for profiling 19 | */ 20 | public class CreateHuge { 21 | 22 | /** 23 | * if filename==null, the image is writen to a black hole (like a /dev/null 24 | */ 25 | public static void createHuge(String filename, final int cols, final int rows) throws Exception { 26 | OutputStream os = filename == null ? TestSupport.createNullOutputStream() 27 | : new FileOutputStream(new File(filename)); 28 | PngWriter png = new PngWriter(os, new ImageInfo(cols, rows, 8, false)); 29 | ((PixelsWriterDefault) png.getPixelsWriter()).setFilterType(FilterType.FILTER_AVERAGE); 30 | png.setIdatMaxSize(0x10000); 31 | png.setCompLevel(6); 32 | ImageLineInt iline1 = new ImageLineInt(png.imgInfo); 33 | ImageLineInt iline2 = new ImageLineInt(png.imgInfo); 34 | ImageLineInt iline = iline1; 35 | for (int j = 0; j < cols; j++) { 36 | ImageLineHelper.setPixelRGB8(iline1, j, ((j & 0xFF) << 16) | (((j * 3) & 0xFF) << 8) | (j * 2) & 0xFF); 37 | ImageLineHelper.setPixelRGB8(iline2, j, (j * 13) & 0xFFFFFF); 38 | } 39 | long t0 = System.currentTimeMillis(); 40 | for (int row = 0; row < rows; row++) { 41 | iline = row % 4 == 0 ? iline2 : iline1; 42 | png.writeRow(iline, row); 43 | } 44 | png.end(); 45 | int dt = (int) (System.currentTimeMillis() - t0); 46 | System.out.println("Created: " + png.imgInfo.toString()); 47 | System.out.printf("%d msecs, %.1f msecs/MPixel \n", dt, dt * 1000000.0 / (cols * rows)); 48 | } 49 | 50 | public static void run3(int cols, int rows) throws Exception { 51 | createHuge(null, cols, rows); 52 | createHuge(null, cols, rows); 53 | createHuge(null, cols, rows); 54 | } 55 | 56 | public static void main(String[] args) throws Exception { 57 | run3(5000, 5000); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/CreateVeryHuge.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileOutputStream; 6 | import java.io.OutputStream; 7 | import java.util.Random; 8 | 9 | import ar.com.hjg.pngj.FilterType; 10 | import ar.com.hjg.pngj.ImageInfo; 11 | import ar.com.hjg.pngj.ImageLineHelper; 12 | import ar.com.hjg.pngj.ImageLineInt; 13 | import ar.com.hjg.pngj.PngWriter; 14 | import ar.com.hjg.pngj.test.TestSupport; 15 | 16 | /** 17 | * Creates a VERY huge image (more than 2GB!!!) 18 | *

19 | */ 20 | public class CreateVeryHuge { 21 | 22 | public static void createVeryHuge(String filename, final int cols, final int rows) { 23 | OutputStream os = null; 24 | try { 25 | os = filename == null ? TestSupport.createNullOutputStream() : new FileOutputStream(new File(filename)); 26 | } catch (FileNotFoundException e) { 27 | e.printStackTrace(); 28 | } 29 | PngWriter png = new PngWriter(os, new ImageInfo(cols, rows, 8, false)); 30 | png.setFilterType(FilterType.FILTER_NONE); // no compression at PNG prediction level 31 | png.setIdatMaxSize(0x10000 * 256); 32 | png.setCompLevel(0); // // no compression at ZLIB level 33 | ImageLineInt iline1 = new ImageLineInt(png.imgInfo); 34 | Random r = new Random(); 35 | for (int j = 0; j < cols; j++) { // pure noise line 36 | ImageLineHelper.setPixelRGB8(iline1, j, r.nextInt(256), r.nextInt(256), r.nextInt(256)); 37 | } 38 | long t0 = System.currentTimeMillis(); 39 | for (int row = 0; row < rows; row++) { 40 | png.writeRow(iline1, row); 41 | } 42 | png.end(); 43 | int dt = (int) (System.currentTimeMillis() - t0); 44 | System.out.println("Created: " + png.imgInfo.toString()); 45 | System.out.printf("%d msecs, %.1f msecs/MPixel \n", dt, dt * 1000000.0 / (cols * rows)); 46 | } 47 | 48 | public void testOnNullDevice() { 49 | createVeryHuge(null, 30000, 30000); 50 | } 51 | 52 | static void doitOnDisk() throws Exception { 53 | String filename = "C:/temp/huge.png"; 54 | // createVeryHuge(filename,30000,30000); // WARNING: this creates an image of 55 | // about 2.5 Gb !!! 56 | SampleShowChunks.showChunks(new File(filename), true); 57 | } 58 | 59 | public static void main(String[] args) throws Exception { 60 | doitOnDisk(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/IImageLineSet.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | /** 4 | * Set of {@link IImageLine} elements. 5 | *

6 | * This is actually a "virtual" set, it can be implemented in several ways; for 7 | * example 8 | *

    9 | *
  • Cursor-like: stores only one line, which is implicitly moved when 10 | * requested
  • 11 | *
  • All lines: all lines stored as an array of IImageLine
  • 12 | *
  • Subset of lines: eg, only first 3 lines, or odd numbered lines. Or a band 13 | * of neighbours lines that is moved like a cursor.
  • The ImageLine that 14 | * PngReader returns is hosted by a IImageLineSet (this abstraction allows the 15 | * implementation to deal with interlaced images cleanly) but the library user 16 | * does not normally needs to know that (or rely on that), except for the 17 | * {@link PngReader#readRows()} method. 18 | *
19 | */ 20 | public interface IImageLineSet { 21 | 22 | /** 23 | * Asks for imageline corresponding to row n in the original image 24 | * (zero based). This can trigger side effects in this object (eg, advance a 25 | * cursor, set current row number...) In some scenarios, this should be 26 | * consider as alias to (pseudocode) 27 | * positionAtLine(n); getCurrentLine(); 28 | *

29 | * Throws exception if not available. The caller is supposed to know what 30 | * he/she is doing 31 | **/ 32 | public IImageLine getImageLine(int n); 33 | 34 | /** 35 | * Like {@link #getImageLine(int)} but uses the raw numbering inside the 36 | * LineSet This makes little sense for a cursor 37 | * 38 | * @param n 39 | * Should normally go from 0 to {@link #size()} 40 | * @return 41 | */ 42 | public IImageLine getImageLineRawNum(int n); 43 | 44 | /** 45 | * Returns true if the set contain row n (in the original 46 | * image,zero based) currently allocated. 47 | *

48 | * If it's a single-cursor, this should return true only if it's positioned 49 | * there. (notice that hasImageLine(n) can return false, but getImageLine(n) 50 | * can be ok) 51 | * 52 | **/ 53 | public boolean hasImageLine(int n); 54 | 55 | /** 56 | * Internal size of allocated rows This is informational, it should rarely 57 | * be important for the caller. 58 | **/ 59 | public int size(); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkICCP.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngjException; 5 | 6 | /** 7 | * iCCP chunk. 8 | *

9 | * See {@link http://www.w3.org/TR/PNG/#11iCCP} 10 | */ 11 | public class PngChunkICCP extends PngChunkSingle { 12 | public final static String ID = ChunkHelper.iCCP; 13 | 14 | // http://www.w3.org/TR/PNG/#11iCCP 15 | private String profileName; 16 | private byte[] compressedProfile; // copmression/decopmresion is done in getter/setter 17 | 18 | public PngChunkICCP(ImageInfo info) { 19 | super(ID, info); 20 | } 21 | 22 | @Override 23 | public ChunkOrderingConstraint getOrderingConstraint() { 24 | return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT; 25 | } 26 | 27 | @Override 28 | public ChunkRaw createRawChunk() { 29 | ChunkRaw c = createEmptyChunk(profileName.length() + compressedProfile.length + 2, true); 30 | System.arraycopy(ChunkHelper.toBytesLatin1(profileName), 0, c.data, 0, profileName.length()); 31 | c.data[profileName.length()] = 0; 32 | c.data[profileName.length() + 1] = 0; 33 | System.arraycopy(compressedProfile, 0, c.data, profileName.length() + 2, compressedProfile.length); 34 | return c; 35 | } 36 | 37 | @Override 38 | public void parseFromRaw(ChunkRaw chunk) { 39 | int pos0 = ChunkHelper.posNullByte(chunk.data); 40 | profileName = ChunkHelper.toStringLatin1(chunk.data, 0, pos0); 41 | int comp = (chunk.data[pos0 + 1] & 0xff); 42 | if (comp != 0) 43 | throw new PngjException("bad compression for ChunkTypeICCP"); 44 | int compdatasize = chunk.data.length - (pos0 + 2); 45 | compressedProfile = new byte[compdatasize]; 46 | System.arraycopy(chunk.data, pos0 + 2, compressedProfile, 0, compdatasize); 47 | } 48 | 49 | /** 50 | * The profile should be uncompressed bytes 51 | */ 52 | public void setProfileNameAndContent(String name, byte[] profile) { 53 | profileName = name; 54 | compressedProfile = ChunkHelper.compressBytes(profile, true); 55 | } 56 | 57 | public void setProfileNameAndContent(String name, String profile) { 58 | setProfileNameAndContent(name, ChunkHelper.toBytesLatin1(profile)); 59 | } 60 | 61 | public String getProfileName() { 62 | return profileName; 63 | } 64 | 65 | /** 66 | * uncompressed 67 | **/ 68 | public byte[] getProfile() { 69 | return ChunkHelper.compressBytes(compressedProfile, false); 70 | } 71 | 72 | public String getProfileAsString() { 73 | return ChunkHelper.toStringLatin1(getProfile()); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkPLTE.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import ar.com.hjg.pngj.ImageInfo; 4 | import ar.com.hjg.pngj.PngjException; 5 | 6 | /** 7 | * PLTE chunk. 8 | *

9 | * see http://www.w3.org/TR/PNG/#11PLTE 10 | *

11 | * Critical chunk 12 | */ 13 | public class PngChunkPLTE extends PngChunkSingle { 14 | public final static String ID = ChunkHelper.PLTE; 15 | 16 | // http://www.w3.org/TR/PNG/#11PLTE 17 | private int nentries = 0; 18 | /** 19 | * RGB8 packed in one integer 20 | */ 21 | private int[] entries; 22 | 23 | public PngChunkPLTE(ImageInfo info) { 24 | super(ID, info); 25 | } 26 | 27 | @Override 28 | public ChunkOrderingConstraint getOrderingConstraint() { 29 | return ChunkOrderingConstraint.NA; 30 | } 31 | 32 | @Override 33 | public ChunkRaw createRawChunk() { 34 | int len = 3 * nentries; 35 | int[] rgb = new int[3]; 36 | ChunkRaw c = createEmptyChunk(len, true); 37 | for (int n = 0, i = 0; n < nentries; n++) { 38 | getEntryRgb(n, rgb); 39 | c.data[i++] = (byte) rgb[0]; 40 | c.data[i++] = (byte) rgb[1]; 41 | c.data[i++] = (byte) rgb[2]; 42 | } 43 | return c; 44 | } 45 | 46 | @Override 47 | public void parseFromRaw(ChunkRaw chunk) { 48 | setNentries(chunk.len / 3); 49 | for (int n = 0, i = 0; n < nentries; n++) { 50 | setEntry(n, (int) (chunk.data[i++] & 0xff), (int) (chunk.data[i++] & 0xff), (int) (chunk.data[i++] & 0xff)); 51 | } 52 | } 53 | 54 | public void setNentries(int n) { 55 | nentries = n; 56 | if (nentries < 1 || nentries > 256) 57 | throw new PngjException("invalid pallette - nentries=" + nentries); 58 | if (entries == null || entries.length != nentries) { // alloc 59 | entries = new int[nentries]; 60 | } 61 | } 62 | 63 | public int getNentries() { 64 | return nentries; 65 | } 66 | 67 | public void setEntry(int n, int r, int g, int b) { 68 | entries[n] = ((r << 16) | (g << 8) | b); 69 | } 70 | 71 | public int getEntry(int n) { 72 | return entries[n]; 73 | } 74 | 75 | public void getEntryRgb(int n, int[] rgb) { 76 | getEntryRgb(n, rgb, 0); 77 | } 78 | 79 | public void getEntryRgb(int n, int[] rgb, int offset) { 80 | int v = entries[n]; 81 | rgb[offset + 0] = ((v & 0xff0000) >> 16); 82 | rgb[offset + 1] = ((v & 0xff00) >> 8); 83 | rgb[offset + 2] = (v & 0xff); 84 | } 85 | 86 | public int minBitDepth() { 87 | if (nentries <= 2) 88 | return 1; 89 | else if (nentries <= 4) 90 | return 2; 91 | else if (nentries <= 16) 92 | return 4; 93 | else 94 | return 8; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/chunks/PngChunkTIME.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.chunks; 2 | 3 | import java.util.Calendar; 4 | 5 | import ar.com.hjg.pngj.ImageInfo; 6 | import ar.com.hjg.pngj.PngHelperInternal; 7 | import ar.com.hjg.pngj.PngjException; 8 | 9 | /** 10 | * tIME chunk. 11 | *

12 | * see http://www.w3.org/TR/PNG/#11tIME 13 | */ 14 | public class PngChunkTIME extends PngChunkSingle { 15 | public final static String ID = ChunkHelper.tIME; 16 | 17 | // http://www.w3.org/TR/PNG/#11tIME 18 | private int year, mon, day, hour, min, sec; 19 | 20 | public PngChunkTIME(ImageInfo info) { 21 | super(ID, info); 22 | } 23 | 24 | @Override 25 | public ChunkOrderingConstraint getOrderingConstraint() { 26 | return ChunkOrderingConstraint.NONE; 27 | } 28 | 29 | @Override 30 | public ChunkRaw createRawChunk() { 31 | ChunkRaw c = createEmptyChunk(7, true); 32 | PngHelperInternal.writeInt2tobytes(year, c.data, 0); 33 | c.data[2] = (byte) mon; 34 | c.data[3] = (byte) day; 35 | c.data[4] = (byte) hour; 36 | c.data[5] = (byte) min; 37 | c.data[6] = (byte) sec; 38 | return c; 39 | } 40 | 41 | @Override 42 | public void parseFromRaw(ChunkRaw chunk) { 43 | if (chunk.len != 7) 44 | throw new PngjException("bad chunk " + chunk); 45 | year = PngHelperInternal.readInt2fromBytes(chunk.data, 0); 46 | mon = PngHelperInternal.readInt1fromByte(chunk.data, 2); 47 | day = PngHelperInternal.readInt1fromByte(chunk.data, 3); 48 | hour = PngHelperInternal.readInt1fromByte(chunk.data, 4); 49 | min = PngHelperInternal.readInt1fromByte(chunk.data, 5); 50 | sec = PngHelperInternal.readInt1fromByte(chunk.data, 6); 51 | } 52 | 53 | public void setNow(int secsAgo) { 54 | Calendar d = Calendar.getInstance(); 55 | d.setTimeInMillis(System.currentTimeMillis() - 1000 * (long) secsAgo); 56 | year = d.get(Calendar.YEAR); 57 | mon = d.get(Calendar.MONTH) + 1; 58 | day = d.get(Calendar.DAY_OF_MONTH); 59 | hour = d.get(Calendar.HOUR_OF_DAY); 60 | min = d.get(Calendar.MINUTE); 61 | sec = d.get(Calendar.SECOND); 62 | } 63 | 64 | public void setYMDHMS(int yearx, int monx, int dayx, int hourx, int minx, int secx) { 65 | year = yearx; 66 | mon = monx; 67 | day = dayx; 68 | hour = hourx; 69 | min = minx; 70 | sec = secx; 71 | } 72 | 73 | public int[] getYMDHMS() { 74 | return new int[] { year, mon, day, hour, min, sec }; 75 | } 76 | 77 | /** format YYYY/MM/DD HH:mm:SS */ 78 | public String getAsString() { 79 | return String.format("%04d/%02d/%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/FilterPreserveTest.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import java.io.File; 4 | 5 | import junit.framework.TestCase; 6 | 7 | import org.junit.Test; 8 | 9 | import ar.com.hjg.pngj.PngReader; 10 | import ar.com.hjg.pngj.PngReaderByte; 11 | import ar.com.hjg.pngj.PngWriter; 12 | 13 | public class FilterPreserveTest { 14 | 15 | private File origFile() { 16 | return new File(TestSupport.getResourcesDir(), "test/stripesoptim.png"); 17 | } 18 | 19 | private File newFile() { 20 | return new File(TestSupport.getTempDir(), "stripes2.png"); 21 | } 22 | 23 | @Test 24 | public void testDontPreserve1() { 25 | PngReader pngr = new PngReader(origFile()); 26 | File dest = newFile(); 27 | PngWriter pngw = new PngWriter(dest, pngr.imgInfo); 28 | 29 | for (int i = 0; i < pngr.imgInfo.rows; i++) { 30 | pngw.writeRow(pngr.readRow()); 31 | } 32 | pngr.end(); 33 | pngw.end(); 34 | String f1 = TestSupport.showFilters(origFile(), 30, false); 35 | String f2 = TestSupport.showFilters(dest, 30, false); 36 | TestCase.assertFalse(f1.equals(f2)); // must be different 37 | } 38 | 39 | @Test 40 | public void testPreserve1() { 41 | PngReader pngr = new PngReader(origFile()); 42 | File dest = newFile(); 43 | PngWriter pngw = new PngWriter(dest, pngr.imgInfo); 44 | pngw.setFilterPreserve(true); 45 | for (int i = 0; i < pngr.imgInfo.rows; i++) { 46 | pngw.writeRow(pngr.readRow()); 47 | } 48 | pngr.end(); 49 | pngw.end(); 50 | String f1 = TestSupport.showFilters(origFile(), 30, false); 51 | String f2 = TestSupport.showFilters(dest, 30, false); 52 | TestCase.assertEquals(f1, f2); // must be different 53 | } 54 | 55 | @Test 56 | public void testDontPreserve2() { 57 | PngReaderByte pngr = new PngReaderByte(origFile()); 58 | File dest = newFile(); 59 | PngWriter pngw = new PngWriter(dest, pngr.imgInfo); 60 | pngw.writeRows(pngr.readRows()); 61 | pngr.end(); 62 | pngw.end(); 63 | String f1 = TestSupport.showFilters(origFile(), 30, false); 64 | String f2 = TestSupport.showFilters(dest, 30, false); 65 | TestCase.assertFalse(f1.equals(f2)); // must be different 66 | } 67 | 68 | @Test 69 | public void testPreserve2() { 70 | PngReaderByte pngr = new PngReaderByte(origFile()); 71 | File dest = newFile(); 72 | PngWriter pngw = new PngWriter(dest, pngr.imgInfo); 73 | pngw.setFilterPreserve(true); 74 | pngw.writeRows(pngr.readRows()); 75 | pngr.end(); 76 | pngw.end(); 77 | String f1 = TestSupport.showFilters(origFile(), 30, false); 78 | String f2 = TestSupport.showFilters(dest, 30, false); 79 | TestCase.assertEquals(f1, f2); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/DeflatedChunkReader.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import ar.com.hjg.pngj.chunks.PngChunkFDAT; 4 | 5 | /** 6 | * 7 | * Specialization of ChunkReader, for IDAT-like chunks. These chunks are part of 8 | * a set of similar chunks (contiguos normally, not necessariyl) which conforms 9 | * a zlib stream 10 | */ 11 | public abstract class DeflatedChunkReader extends ChunkReader { 12 | 13 | protected final DeflatedChunksSet deflatedChunksSet; 14 | protected boolean alsoBuffer = false; 15 | 16 | protected boolean skipBytes = false; // fDAT (APNG) skips 4 bytes) 17 | protected byte[] skippedBytes; // only for fDAT 18 | protected int seqNumExpected = -1; // only for fDAT 19 | 20 | public DeflatedChunkReader(int clen, String chunkid, boolean checkCrc, long offsetInPng, 21 | DeflatedChunksSet iDatSet) { 22 | super(clen, chunkid, offsetInPng, ChunkReaderMode.PROCESS); 23 | this.deflatedChunksSet = iDatSet; 24 | if (chunkid.equals(PngChunkFDAT.ID)) { 25 | skipBytes = true; 26 | skippedBytes = new byte[4]; 27 | } 28 | iDatSet.appendNewChunk(this); 29 | } 30 | 31 | /** 32 | * Delegates to ChunkReaderDeflatedSet.processData() 33 | */ 34 | @Override 35 | protected void processData(int offsetInchunk, byte[] buf, int off, int len) { 36 | if (skipBytes && offsetInchunk < 4) {// only for APNG (sigh) 37 | for (int oc = offsetInchunk; oc < 4 && len > 0; oc++, off++, len--) 38 | skippedBytes[oc] = buf[off]; 39 | } 40 | if (len > 0) { // delegate to idatSet 41 | 42 | deflatedChunksSet.processBytes(buf, off, len); 43 | if (alsoBuffer) { // very rare! 44 | System.arraycopy(buf, off, getChunkRaw().data, read, len); 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * only a stupid check for fDAT (I wonder how many APGN readers do this) 51 | */ 52 | @Override 53 | protected void chunkDone() { 54 | if (skipBytes && getChunkRaw().id.equals(PngChunkFDAT.ID)) { 55 | if (seqNumExpected >= 0) { 56 | int seqNum = PngHelperInternal.readInt4fromBytes(skippedBytes, 0); 57 | if (seqNum != seqNumExpected) 58 | throw new PngjInputException( 59 | "bad chunk sequence for fDAT chunk " + seqNum + " expected " + seqNumExpected); 60 | } 61 | } 62 | } 63 | 64 | @Override 65 | public boolean isFromDeflatedSet() { 66 | return true; 67 | } 68 | 69 | /** 70 | * In some rare cases you might want to also buffer the data? 71 | */ 72 | public void setAlsoBuffer() { 73 | if (read > 0) 74 | throw new RuntimeException("too late"); 75 | alsoBuffer = true; 76 | getChunkRaw().allocData(); 77 | } 78 | 79 | /** only relevant for fDAT */ 80 | public void setSeqNumExpected(int seqNumExpected) { 81 | this.seqNumExpected = seqNumExpected; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/pixels/CompressorStreamLz4.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.pixels; 2 | 3 | import java.util.zip.Deflater; 4 | 5 | import ar.com.hjg.pngj.IdatChunkWriter; 6 | import ar.com.hjg.pngj.PngjOutputException; 7 | 8 | /** 9 | * This class uses a quick compressor to get a rough estimate of deflate 10 | * compression ratio. 11 | * 12 | * This just ignores the outputStream, and the deflater related parameters 13 | */ 14 | public class CompressorStreamLz4 extends CompressorStream { 15 | 16 | private final DeflaterEstimatorLz4 lz4; 17 | 18 | private byte[] buf; // lazily allocated, only if needed 19 | private final int buffer_size; 20 | // bufpos=bytes in buffer yet not compressed (bytesIn include this) 21 | private int inbuf = 0; 22 | 23 | private static final int MAX_BUFFER_SIZE = 16000; 24 | 25 | public CompressorStreamLz4(IdatChunkWriter os, int maxBlockLen, long totalLen) { 26 | super(os, maxBlockLen, totalLen); 27 | lz4 = new DeflaterEstimatorLz4(); 28 | buffer_size = (int) (totalLen > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : totalLen); 29 | } 30 | 31 | public CompressorStreamLz4(IdatChunkWriter os, int maxBlockLen, long totalLen, Deflater def) { 32 | this(os, maxBlockLen, totalLen);// edlfater ignored 33 | } 34 | 35 | public CompressorStreamLz4(IdatChunkWriter os, int maxBlockLen, long totalLen, int deflaterCompLevel, 36 | int deflaterStrategy) { 37 | this(os, maxBlockLen, totalLen); // paramters ignored 38 | } 39 | 40 | @Override 41 | public void mywrite(byte[] b, int off, int len) { 42 | if (len == 0) 43 | return; 44 | if (done || closed) 45 | throw new PngjOutputException("write beyond end of stream"); 46 | bytesIn += len; 47 | while (len > 0) { 48 | if (inbuf == 0 && (len >= MAX_BUFFER_SIZE || bytesIn == totalbytes)) { 49 | // direct copy (buffer might be null or empty) 50 | bytesOut += lz4.compressEstim(b, off, len); 51 | len = 0; 52 | } else { 53 | if (buf == null) 54 | buf = new byte[buffer_size]; 55 | int len1 = inbuf + len <= buffer_size ? len : buffer_size - inbuf; // to copy 56 | if (len1 > 0) 57 | System.arraycopy(b, off, buf, inbuf, len1); 58 | inbuf += len1; 59 | len -= len1; 60 | off += len1; 61 | if (inbuf == buffer_size) 62 | compressFromBuffer(); 63 | } 64 | } 65 | } 66 | 67 | void compressFromBuffer() { 68 | if (inbuf > 0) { 69 | bytesOut += lz4.compressEstim(buf, 0, inbuf); 70 | inbuf = 0; 71 | } 72 | } 73 | 74 | @Override 75 | public void done() { 76 | if (!done) { 77 | compressFromBuffer(); 78 | done = true; 79 | } 80 | } 81 | 82 | @Override 83 | public void close() { 84 | done(); 85 | if (!closed) { 86 | super.close(); 87 | buf = null; 88 | } 89 | } 90 | 91 | public void reset() { 92 | super.reset(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleImgDiff.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | 5 | import ar.com.hjg.pngj.ImageLineInt; 6 | import ar.com.hjg.pngj.PngReader; 7 | 8 | /** 9 | * Utility (and example) to verify that two images are identical. Computes the 10 | * maximum difference. 11 | * 12 | * TODO: Add alpha 13 | */ 14 | public class SampleImgDiff { 15 | /** 16 | * asume que las imagenes son equivalentes res[0]=maxima diferencia (suma 17 | * valores absoluto sobre todos los canales) res[1]=columna en que se produce 18 | * 19 | * ignores alpha 20 | */ 21 | private static int[] computeDiffLine(ImageLineInt l1, ImageLineInt l2) { 22 | double maxDif = -1; 23 | int maxDifCol = -1; 24 | double dif; 25 | int channels = l1.imgInfo.channels; 26 | int[] scanline1 = l1.getScanline(); 27 | int[] scanline2 = l2.getScanline(); 28 | for (int col = 0; col < l1.imgInfo.cols; col++) { 29 | dif = Math.abs(scanline1[col * channels] - scanline2[col * channels]) 30 | + Math.abs(scanline1[col * channels + 1] - scanline2[col * channels + 1]) 31 | + Math.abs(scanline1[col * channels + 2] - scanline2[col * channels + 2]); 32 | if (channels == 4) 33 | dif += Math.abs(scanline1[col * channels + 3] - scanline2[col * channels + 3]); 34 | if (dif > maxDif) { 35 | maxDif = dif; 36 | maxDifCol = col; 37 | } 38 | } 39 | return new int[] { (int) (maxDif + 0.5), maxDifCol }; 40 | } 41 | 42 | public static void showDiff(String f1, String f2) { 43 | int maxDif = -1; 44 | int maxDifCol = -1; 45 | int maxDifRow = -1; 46 | PngReader i1 = new PngReader(new File(f1)); 47 | PngReader i2 = new PngReader(new File(f2)); 48 | System.out.println(i1.toString()); 49 | System.out.println(i2.toString()); 50 | if (i1.imgInfo.channels < 3) 51 | throw new RuntimeException("Images must be RGB or RGBA"); 52 | if (!i1.imgInfo.equals(i2.imgInfo)) 53 | throw new RuntimeException("Images must be comparable (same sizes and type) "); 54 | int rows = i1.imgInfo.rows; 55 | for (int row = 0; row < rows; row++) { 56 | ImageLineInt l1 = (ImageLineInt) i1.readRow(row); 57 | ImageLineInt l2 = (ImageLineInt) i2.readRow(row); 58 | int[] res = computeDiffLine(l1, l2); 59 | if (res[0] > maxDif) { 60 | maxDif = res[0]; 61 | maxDifCol = res[1]; 62 | maxDifRow = row; 63 | } 64 | } 65 | i1.end(); 66 | i2.end(); 67 | if (maxDif == 0) 68 | System.out.println("No difference"); 69 | else 70 | System.out.printf("Images differ. MaxDif=%d [%d %d]\n", maxDif, maxDifCol, maxDifRow); 71 | } 72 | 73 | public static void main(String[] args) { 74 | if (args.length != 2 || args[0].equals(args[1])) { 75 | System.err.println("Enter two filenames (images to be compared)"); 76 | System.exit(1); 77 | } 78 | showDiff(args[0], args[1]); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/SampleTileImage.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.File; 4 | import java.util.Arrays; 5 | 6 | import ar.com.hjg.pngj.ImageInfo; 7 | import ar.com.hjg.pngj.ImageLineInt; 8 | import ar.com.hjg.pngj.PngReader; 9 | import ar.com.hjg.pngj.PngWriter; 10 | import ar.com.hjg.pngj.chunks.ChunkCopyBehaviour; 11 | import ar.com.hjg.pngj.chunks.ChunkLoadBehaviour; 12 | 13 | /** 14 | * Takes several tiles and join them in a single image 15 | * 16 | * @param tiles Filenames of PNG files to tile 17 | * @param dest Destination PNG filename 18 | * @param nTilesX How many tiles per row? 19 | */ 20 | public class SampleTileImage { 21 | 22 | public static void doTiling(String tiles[], String dest, int nTilesX) { 23 | int ntiles = tiles.length; 24 | int nTilesY = (ntiles + nTilesX - 1) / nTilesX; // integer ceil 25 | ImageInfo imi1, imi2; // 1:small tile 2:big image 26 | PngReader pngr = new PngReader(new File(tiles[0])); 27 | imi1 = pngr.imgInfo; 28 | PngReader[] readers = new PngReader[nTilesX]; 29 | imi2 = new ImageInfo(imi1.cols * nTilesX, imi1.rows * nTilesY, imi1.bitDepth, imi1.alpha, imi1.greyscale, 30 | imi1.indexed); 31 | PngWriter pngw = new PngWriter(new File(dest), imi2, true); 32 | // copy palette and transparency if necessary (more chunks?) 33 | pngw.copyChunksFrom(pngr.getChunksList(), 34 | ChunkCopyBehaviour.COPY_PALETTE | ChunkCopyBehaviour.COPY_TRANSPARENCY); 35 | pngr.end(); // close, we'll reopen it again soon 36 | ImageLineInt line2 = new ImageLineInt(imi2); 37 | int row2 = 0; 38 | for (int ty = 0; ty < nTilesY; ty++) { 39 | int nTilesXcur = ty < nTilesY - 1 ? nTilesX : ntiles - (nTilesY - 1) * nTilesX; 40 | Arrays.fill(line2.getScanline(), 0); 41 | for (int tx = 0; tx < nTilesXcur; tx++) { // open serveral readers 42 | readers[tx] = new PngReader(new File(tiles[tx + ty * nTilesX])); 43 | readers[tx].setChunkLoadBehaviour(ChunkLoadBehaviour.LOAD_CHUNK_NEVER); 44 | if (!readers[tx].imgInfo.equals(imi1)) 45 | throw new RuntimeException("different tile ? " + readers[tx].imgInfo); 46 | } 47 | for (int row1 = 0; row1 < imi1.rows; row1++, row2++) { 48 | for (int tx = 0; tx < nTilesXcur; tx++) { 49 | ImageLineInt line1 = (ImageLineInt) readers[tx].readRow(row1); // read line 50 | System.arraycopy(line1.getScanline(), 0, line2.getScanline(), line1.getScanline().length * tx, 51 | line1.getScanline().length); 52 | } 53 | pngw.writeRow(line2, row2); // write to full image 54 | } 55 | for (int tx = 0; tx < nTilesXcur; tx++) 56 | readers[tx].end(); // close readers 57 | } 58 | pngw.end(); // close writer 59 | } 60 | 61 | public static void main(String[] args) { 62 | doTiling(new String[] { "t1.png", "t2.png", "t3.png", "t4.png", "t5.png", "t6.png" }, "tiled.png", 2); 63 | System.out.println("done"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/resources/colormodels/readme.txt: -------------------------------------------------------------------------------- 1 | Small images, one of each type (approx) 2 | The 't' suffix means that it includes a TRNS chunk 3 | 4 | 01g.png 1g b_BINARY;cm=Index,ps=1,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 1g 5 | 01p.png 1p b_BINARY;cm=Index,ps=1,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 1p 6 | 02g.png 2g b_BINARY;cm=Index,ps=2,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 2g 7 | 02p.png 2p b_BINARY;cm=Index,ps=2,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 2p 8 | 04g.png 4g b_BINARY;cm=Index,ps=4,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 4g 9 | 04gt.png 4gt b_BINARY;cm=Index,ps=4,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 4g 10 | 04p.png 4p b_BINARY;cm=Index,ps=4,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 4p 11 | 04pt.png 4pt b_BINARY;cm=Index,ps=4,ha=Y,ap=N,cs=[8, 8, 8, 8];srgb=true;sm=MultiPixelPacked;db=Byte,0,bo=NA 4pt 12 | 08.png 8 3b_BGR;cm=Component,ps=24,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=PixelInterleaved;db=Byte,0,bo=[2, 1, 0] 8 13 | 08a.png 8a 4b_ABGR;cm=Component,ps=32,ha=Y,ap=N,cs=[8, 8, 8, 8];srgb=true;sm=PixelInterleaved;db=Byte,0,bo=[3, 2, 1, 0] 8a 14 | 08ag.png 8ag CUSTOM;cm=Component,ps=16,ha=Y,ap=N,cs=[8, 8];srgb=false;sm=PixelInterleaved;db=Byte,0,bo=[0, 1] 8ag 15 | 08g.png 8g b_GRAY;cm=Component,ps=8,ha=N,ap=N,cs=[8];srgb=false;sm=PixelInterleaved;db=Byte,0,bo=[0] 8g 16 | 08p.png 8p b_INDEXED;cm=Index,ps=8,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=PixelInterleaved;db=Byte,0,bo=[0] 8p 17 | 08pt.png 8pt b_INDEXED;cm=Index,ps=8,ha=Y,ap=N,cs=[8, 8, 8, 8];srgb=true;sm=PixelInterleaved;db=Byte,0,bo=[0] 8pt 18 | 08t.png 8t 3b_BGR;cm=Component,ps=24,ha=N,ap=N,cs=[8, 8, 8];srgb=true;sm=PixelInterleaved;db=Byte,0,bo=[2, 1, 0] 8 19 | 16.png 16 CUSTOM;cm=Component,ps=48,ha=N,ap=N,cs=[16, 16, 16];srgb=true;sm=PixelInterleaved;db=UShort,1,bo=[0, 1, 2] 16 20 | 16a.png 16a CUSTOM;cm=Component,ps=64,ha=Y,ap=N,cs=[16, 16, 16, 16];srgb=true;sm=PixelInterleaved;db=UShort,1,bo=[0, 1, 2, 3] 16a 21 | 16ag.png 16ag CUSTOM;cm=Component,ps=32,ha=Y,ap=N,cs=[16, 16];srgb=false;sm=PixelInterleaved;db=UShort,1,bo=[0, 1] 16ag 22 | 16g.png 16g u_GRAY;cm=Component,ps=16,ha=N,ap=N,cs=[16];srgb=false;sm=PixelInterleaved;db=UShort,1,bo=[0] 16g 23 | 16gt.png 16gt u_GRAY;cm=Component,ps=16,ha=N,ap=N,cs=[16];srgb=false;sm=PixelInterleaved;db=UShort,1,bo=[0] 16g 24 | 16t.png 16t CUSTOM;cm=Component,ps=48,ha=N,ap=N,cs=[16, 16, 16];srgb=true;sm=PixelInterleaved;db=UShort,1,bo=[0, 1, 2] 16 -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/samples/ChunkSeqReaderIdatRaw.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.samples; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | 6 | import ar.com.hjg.pngj.ChunkReader; 7 | import ar.com.hjg.pngj.PngjOutputException; 8 | import ar.com.hjg.pngj.chunks.ChunkRaw; 9 | 10 | public class ChunkSeqReaderIdatRaw extends ChunkSeqReaderOpaque { 11 | private final OutputStream rawOs; 12 | private final OutputStream idatOs; 13 | public boolean checkCrc = true; 14 | public boolean omitFilterByte = false; 15 | 16 | /** 17 | * This reader writes the chunks directly to the rawOs output, except that the 18 | * IDAT stream is decompressed and writen to idatOs 19 | * 20 | * @param is 21 | * @param rawOs 22 | * @param idatOs 23 | * @param rowsize 24 | */ 25 | public ChunkSeqReaderIdatRaw(OutputStream rawOs, OutputStream idatOs) { 26 | super(); 27 | this.rawOs = rawOs; 28 | this.idatOs = idatOs; 29 | bufferChunks = false; // we force processing for all chunks 30 | 31 | } 32 | 33 | @Override 34 | protected void checkSignature(byte[] buf) { 35 | super.checkSignature(buf); 36 | // we also write this to rawOs 37 | writeToOs(rawOs, buf, 0, buf.length); 38 | } 39 | 40 | @Override 41 | protected void processChunkContent(ChunkRaw chunkRaw, int offInChunk, byte[] buf, int off, int len) { 42 | if (offInChunk == 0 && rawOs != null) { // this can be called several times for a single 43 | // chunk, we do this only the first time 44 | chunkRaw.writeChunkHeader(rawOs); 45 | } 46 | writeToOs(rawOs, buf, off, len); 47 | // PngHelperInternal.debug("processChunkContent " + chunkRaw); 48 | 49 | } 50 | 51 | @Override 52 | protected void startNewChunk(int len, String id, long offset) { 53 | // PngHelperInternal.debug("startNewChunk " + id); 54 | super.startNewChunk(len, id, offset); 55 | } 56 | 57 | @Override 58 | protected void postProcessChunk(ChunkReader chunkR) { 59 | if (!isIdatKind(chunkR.getChunkRaw().id)) 60 | chunkR.getChunkRaw().writeChunkCrc(rawOs); 61 | // PngHelperInternal.debug("postprocessing " + chunkR.getChunkRaw()); 62 | super.postProcessChunk(chunkR); 63 | } 64 | 65 | @Override 66 | protected void processIdatInflatedData(byte[] inflatedRow, int off, int len) { 67 | if (len > 0) 68 | writeToOs(idatOs, inflatedRow, off, len); 69 | } 70 | 71 | @Override 72 | protected void processIdatDone() { 73 | try { 74 | if (idatOs != null) 75 | idatOs.close(); 76 | } catch (IOException e) { 77 | throw new PngjOutputException(e); 78 | } 79 | } 80 | 81 | @Override 82 | protected boolean shouldCheckCrc(int len, String id) { 83 | return checkCrc; 84 | } 85 | 86 | protected void writeToOs(OutputStream o, byte[] buf, int off, int len) { 87 | try { 88 | if (o != null) 89 | o.write(buf, off, len); 90 | } catch (IOException e) { 91 | throw new PngjOutputException(e); 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/ChunkSequenceSkipTest.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.io.FileInputStream; 6 | import java.io.InputStream; 7 | 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | import org.junit.rules.ExpectedException; 11 | 12 | import ar.com.hjg.pngj.ChunkSeqSkipping; 13 | import ar.com.hjg.pngj.PngjException; 14 | import ar.com.hjg.pngj.PngjInputException; 15 | import ar.com.hjg.pngj.chunks.ChunkRaw; 16 | 17 | /** 18 | * Very basic reading 19 | */ 20 | public class ChunkSequenceSkipTest extends PngjTest { 21 | 22 | @Rule 23 | public ExpectedException expectedEx = ExpectedException.none(); 24 | 25 | String stripesChunks = "IHDR[13] pHYs[9] IDAT[2000] IDAT[2000] IDAT[2000] IDAT[610] tIME[7] iTXt[30] IEND[0] "; 26 | 27 | /** 28 | * just reads the chunks, all skipped 29 | */ 30 | @Test 31 | public void testReadChunksSkip() { 32 | ChunkSeqSkipping c = new ChunkSeqSkipping(); 33 | TestSupport.feedFromStreamTest(c, "test/stripes.png"); 34 | String chunksSummary = TestSupport.showChunksRaw(c.getChunks()); 35 | TestCase.assertEquals(6785, c.getBytesCount()); 36 | // test that the offsets are consistent with lengths 37 | long offset = 8; 38 | for (ChunkRaw cr : c.getChunks()) { 39 | TestCase.assertEquals(offset, cr.getOffset()); 40 | offset += cr.len + 12; 41 | } 42 | TestCase.assertEquals(stripesChunks, chunksSummary); 43 | } 44 | 45 | /** 46 | * valid png, identical wish stripes.png, but with extra trailing bytes, 47 | */ 48 | @Test 49 | public void testReadWithExtraTrailing() throws Exception { 50 | ChunkSeqSkipping c = new ChunkSeqSkipping(); 51 | TestSupport.feedFromStreamTest(c, "test/bad_stripes_extratrailing.png", -1); 52 | TestCase.assertEquals(6785, c.getBytesCount()); 53 | TestCase.assertEquals(stripesChunks, TestSupport.showChunksRaw(c.getChunks())); 54 | } 55 | 56 | /** 57 | * invalid png (missing bytes) 58 | */ 59 | @Test 60 | public void testReadIncomplete() throws PngjException { 61 | expectedEx.expect(PngjInputException.class); 62 | expectedEx.expectMessage("premature ending"); 63 | ChunkSeqSkipping c = new ChunkSeqSkipping(); 64 | TestSupport.feedFromStreamTest(c, "test/bad_truncated.png"); 65 | throw new RuntimeException("should not reach here"); 66 | } 67 | 68 | @Test 69 | public void testReadIncomplete2() throws PngjException { 70 | { 71 | ChunkSeqSkipping c = new ChunkSeqSkipping(); 72 | InputStream is = TestSupport.istream("test/bad_truncated.png"); 73 | c.feedFromInputStream(is); 74 | TestCase.assertFalse(c.isDone()); 75 | c.close(); 76 | TestCase.assertFalse(c.isDone()); 77 | } 78 | { 79 | ChunkSeqSkipping c = new ChunkSeqSkipping(); 80 | InputStream is = TestSupport.istream("test/stripes.png"); 81 | c.feedFromInputStream(is); 82 | TestCase.assertTrue(c.isDone()); 83 | } 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/test/TextChunksTest.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.test; 2 | 3 | import java.io.File; 4 | import java.util.HashMap; 5 | 6 | import junit.framework.TestCase; 7 | 8 | import org.junit.Test; 9 | 10 | import ar.com.hjg.pngj.PngReader; 11 | import ar.com.hjg.pngj.PngWriter; 12 | import ar.com.hjg.pngj.chunks.ChunkHelper; 13 | import ar.com.hjg.pngj.chunks.PngChunk; 14 | import ar.com.hjg.pngj.chunks.PngChunkTextVar; 15 | 16 | public class TextChunksTest { 17 | 18 | @Test 19 | public void testTestChunks() { 20 | HashMap texts = new HashMap(); 21 | texts.put("key1", "val"); 22 | texts.put("empty1", ""); 23 | texts.put("unicode1", "Hernán"); 24 | texts.put("zero1", "Hola\0chau"); 25 | texts.put("key2", "val"); 26 | texts.put("empty2", ""); 27 | texts.put("unicode2", "Hernán"); 28 | texts.put("zero2", "Hello\0bye"); 29 | texts.put("key3", "val"); 30 | texts.put("empty3", ""); 31 | texts.put("unicode3", "Hernán"); 32 | texts.put("zero3", "Hello\0bye"); 33 | texts.put("nolatin1", "Hernán\u1230"); 34 | 35 | File file1 = TestSupport.getTmpFile("testtext"); 36 | PngWriter png = TestSupport.prepareFileTmp(file1); 37 | 38 | png.getMetadata().setText("key1", texts.get("key1"), false, false); 39 | png.getMetadata().setText("key2", texts.get("key2"), true, false); 40 | png.getMetadata().setText("key3", texts.get("key3"), true, true); 41 | 42 | png.getMetadata().setText("empty1", texts.get("empty1"), false, false); 43 | png.getMetadata().setText("empty2", texts.get("empty2"), true, false); 44 | png.getMetadata().setText("empty3", texts.get("empty3"), true, true); 45 | 46 | png.getMetadata().setText("unicode1", texts.get("unicode1"), false, false); 47 | png.getMetadata().setText("unicode2", texts.get("unicode2"), true, false); 48 | png.getMetadata().setText("unicode3", texts.get("unicode3"), true, true); 49 | 50 | png.getMetadata().setText("nolatin1", texts.get("nolatin1"), false, false); 51 | 52 | png.getMetadata().setText("zero1", texts.get("zero1"), false, false); 53 | png.getMetadata().setText("zero2", texts.get("zero2"), true, false); 54 | png.getMetadata().setText("zero3", texts.get("zero3"), true, true); 55 | 56 | TestSupport.endFileTmp(png); 57 | 58 | PngReader pngr = new PngReader(file1); 59 | pngr.readSkippingAllRows(); 60 | int ok = 0; 61 | for (PngChunk c : pngr.getChunksList().getChunks()) { 62 | if (!ChunkHelper.isText(c)) 63 | continue; 64 | ok++; 65 | PngChunkTextVar ct = (PngChunkTextVar) c; 66 | String key = ct.getKey(); 67 | String val = ct.getVal(); 68 | //System.out.println(c.id + " chunk. Key:" + key + " val='" + val + "'" + " exp:'" +texts.get(key) +"'"); 69 | TestCase.assertEquals("Invalid value at key " + key, texts.get(key), val); 70 | } 71 | TestCase.assertEquals("number of text chunks does not coincide", texts.keySet().size(), ok); 72 | 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/ar/com/hjg/pngj/cli/ShowPngInfo.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj.cli; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | import ar.com.hjg.pngj.IImageLine; 7 | import ar.com.hjg.pngj.PngReaderByte; 8 | 9 | /** see help */ 10 | public class ShowPngInfo { 11 | 12 | static StringBuilder help = new StringBuilder(); 13 | 14 | public static void run(String[] args) { 15 | 16 | help.append("Shows some info and/or digest for PNG file. \n"); 17 | help.append(" Columns are tab separated, in the order: basic_info raw_pix_size compress_size digest \n"); 18 | help.append(" (if bad or not png image, as message starting with '" + BAD_OR_NOT_PNG + "' is shown) \n"); 19 | help.append(" Options: \n"); 20 | help.append(" -i: basic image info as compact string \n"); 21 | help.append(" -s: size raw pixels \n"); 22 | help.append(" -c: compressed idat size \n"); 23 | help.append(" -d: digest of full raw pixel data and palette \n"); 24 | help.append(" Accepts paths in the form 'mypath/*' (all pngs in dir) or 'mypath/**' (idem recursive) \n"); 25 | 26 | CliArgs cli = CliArgs.buildFrom(args, help); 27 | cli.checkAtLeastNargs(1); 28 | ShowPngInfo me = new ShowPngInfo(); 29 | me.showCompatInfo = cli.hasOpt("i"); 30 | me.showFullPixelsDigest = cli.hasOpt("d"); 31 | me.showRawPixelSize = cli.hasOpt("s"); 32 | me.showIdatCompressedSize = cli.hasOpt("c"); 33 | me.listpng = cli.listPngsFromArgs(); 34 | cli.checkNoMoreOpts(); 35 | me.doit(); 36 | } 37 | 38 | public static final String BAD_OR_NOT_PNG = "BAD_OR_NOT_PNG_FILE"; 39 | 40 | private List listpng; 41 | private boolean showCompatInfo = false; 42 | private boolean showFullPixelsDigest; 43 | private boolean showRawPixelSize; 44 | private boolean showIdatCompressedSize; 45 | 46 | private ShowPngInfo() { 47 | } 48 | 49 | private void doit() { 50 | for (File f : listpng) 51 | doitForFile(f); 52 | } 53 | 54 | @SuppressWarnings("unused") 55 | private void doitForFile(File f) { 56 | System.out.printf("%s\t", f.toString()); 57 | try { 58 | PngReaderByte png = new PngReaderByte(f); 59 | png.prepareSimpleDigestComputation(); 60 | if (showIdatCompressedSize || showFullPixelsDigest) { 61 | IImageLine iline; 62 | while (png.hasMoreRows()) 63 | iline = png.readRow(); 64 | } 65 | png.close();// abort 66 | if (showCompatInfo) 67 | System.out.printf("%s\t", png.toStringCompact()); 68 | if (showRawPixelSize) 69 | System.out.printf("%d\t", png.imgInfo.getTotalRawBytes()); 70 | if (showIdatCompressedSize) 71 | System.out.printf("%d\t", png.getChunkseq().getIdatBytes()); 72 | if (showFullPixelsDigest) 73 | System.out.printf("%s\t", png.getSimpleDigestHex()); 74 | } catch (Exception e) { 75 | System.out.printf("%s: %s\t", BAD_OR_NOT_PNG, e.getMessage()); 76 | } 77 | System.out.println(""); 78 | 79 | } 80 | 81 | public static void main(String[] args) { 82 | run(args); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/ar/com/hjg/pngj/PngReaderFilter.java: -------------------------------------------------------------------------------- 1 | package ar.com.hjg.pngj; 2 | 3 | import java.io.FilterInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.List; 7 | 8 | import ar.com.hjg.pngj.chunks.PngChunk; 9 | 10 | /** 11 | * This class allows to use a simple PNG reader as an input filter, wrapping a 12 | * ChunkSeqReaderPng in callback mode. 13 | * 14 | * In this sample implementation, all IDAT chunks are skipped and the rest are 15 | * stored. An example of use, that lets us grab the Metadata and let the pixels 16 | * go towards a BufferedImage: 17 | * 18 | * 19 | *

 20 |  * PngReaderFilter reader = new PngReaderFilter(new FileInputStream("image.png"));
 21 |  * BufferedImage image1 = ImageIO.read(reader);
 22 |  * reader.readUntilEndAndClose(); // in case ImageIO.read() does not read the traling chunks (it happens)
 23 |  * 
24 | * 25 | */ 26 | public class PngReaderFilter extends FilterInputStream { 27 | 28 | private ChunkSeqReaderPng chunkseq; 29 | 30 | public PngReaderFilter(InputStream arg0) { 31 | super(arg0); 32 | chunkseq = createChunkSequenceReader(); 33 | } 34 | 35 | protected ChunkSeqReaderPng createChunkSequenceReader() { 36 | return new ChunkSeqReaderPng(true) { 37 | @Override 38 | public boolean shouldSkipContent(int len, String id) { 39 | return super.shouldSkipContent(len, id) || id.equals("IDAT"); 40 | } 41 | 42 | @Override 43 | protected boolean shouldCheckCrc(int len, String id) { 44 | return false; 45 | } 46 | 47 | @Override 48 | protected void postProcessChunk(ChunkReader chunkR) { 49 | super.postProcessChunk(chunkR); 50 | } 51 | }; 52 | } 53 | 54 | @Override 55 | public void close() throws IOException { 56 | super.close(); 57 | chunkseq.close(); 58 | } 59 | 60 | @Override 61 | public int read() throws IOException { 62 | int r = super.read(); 63 | if (r > 0) 64 | chunkseq.feedAll(new byte[] { (byte) r }, 0, 1); 65 | return r; 66 | } 67 | 68 | @Override 69 | public int read(byte[] b, int off, int len) throws IOException { 70 | int res = super.read(b, off, len); 71 | if (res > 0) 72 | chunkseq.feedAll(b, off, res); 73 | return res; 74 | } 75 | 76 | @Override 77 | public int read(byte[] b) throws IOException { 78 | int res = super.read(b); 79 | if (res > 0) 80 | chunkseq.feedAll(b, 0, res); 81 | return res; 82 | } 83 | 84 | public void readUntilEndAndClose() throws IOException { 85 | BufferedStreamFeeder br = new BufferedStreamFeeder(this.in); 86 | while ((!chunkseq.isDone()) && br.hasPendingBytes()) { 87 | if (br.feed(chunkseq) < 1) 88 | break; 89 | } 90 | br.close(); 91 | close(); 92 | } 93 | 94 | public List getChunksList() { 95 | return chunkseq.getChunks(); 96 | } 97 | 98 | public ChunkSeqReaderPng getChunkseq() { 99 | return chunkseq; 100 | } 101 | 102 | } 103 | --------------------------------------------------------------------------------