I have approx. 6000 PNG files (256*256 pixels) and want to combine them into a big PNG holding all of them programmatically.
What's the best/fastest way to do that?
(The purpose is printing on paper, so using some web-technology is not an option and having one, single picture file will eliminate many usage errors.)
I tried fahd's suggestion but I get a NullPointerException
when I try to create a BufferedImage
with 24576 pixels wide and 15360 pixels high. Any ideas?
How to merge PNG files online. Select or drop your PNG documents to upload for merge. Once upload completes, drag PNG document thumbnails to rearrange them (if needed). Click on Merge Now button to start merge process.
PNG itself is strictly a single-image format. However, it may be necessary to store multiple images within one file; for example, this is needed to convert some GIF files.
Make sure in Preview > Preferences > Images… "When opening files:"… "Open groups of files in the same window" is checked. 2. Select all the files you want to merge, right click on them and choose Open with Preview. 4.
Create a large image which you will write to. Work out its dimensions based on how many rows and columns you want.
BufferedImage result = new BufferedImage( width, height, //work these out BufferedImage.TYPE_INT_RGB); Graphics g = result.getGraphics();
Now loop through your images and draw them:
for(String image : images){ BufferedImage bi = ImageIO.read(new File(image)); g.drawImage(bi, x, y, null); x += 256; if(x > result.getWidth()){ x = 0; y += bi.getHeight(); } }
Finally write it out to file:
ImageIO.write(result,"png",new File("result.png"));
I had some similar need some time ago (huge images -and, I my case with 16 bitdepth- to have them fully in memory was not an option). And I ended coding a PNG library to do the read/write in a sequential way. In case someone find it useful, it's here.
Updated: here's a sample code:
/** * Takes several tiles and join them in a single image * * @param tiles Filenames of PNG files to tile * @param dest Destination PNG filename * @param nTilesX How many tiles per row? */ public class SampleTileImage { public static void doTiling(String tiles[], String dest, int nTilesX) { int ntiles = tiles.length; int nTilesY = (ntiles + nTilesX - 1) / nTilesX; // integer ceil ImageInfo imi1, imi2; // 1:small tile 2:big image PngReader pngr = new PngReader(new File(tiles[0])); imi1 = pngr.imgInfo; PngReader[] readers = new PngReader[nTilesX]; imi2 = new ImageInfo(imi1.cols * nTilesX, imi1.rows * nTilesY, imi1.bitDepth, imi1.alpha, imi1.greyscale, imi1.indexed); PngWriter pngw = new PngWriter(new File(dest), imi2, true); // copy palette and transparency if necessary (more chunks?) pngw.copyChunksFrom(pngr.getChunksList(), ChunkCopyBehaviour.COPY_PALETTE | ChunkCopyBehaviour.COPY_TRANSPARENCY); pngr.readSkippingAllRows(); // reads only metadata pngr.end(); // close, we'll reopen it again soon ImageLineInt line2 = new ImageLineInt(imi2); int row2 = 0; for (int ty = 0; ty < nTilesY; ty++) { int nTilesXcur = ty < nTilesY - 1 ? nTilesX : ntiles - (nTilesY - 1) * nTilesX; Arrays.fill(line2.getScanline(), 0); for (int tx = 0; tx < nTilesXcur; tx++) { // open several readers readers[tx] = new PngReader(new File(tiles[tx + ty * nTilesX])); readers[tx].setChunkLoadBehaviour(ChunkLoadBehaviour.LOAD_CHUNK_NEVER); if (!readers[tx].imgInfo.equals(imi1)) throw new RuntimeException("different tile ? " + readers[tx].imgInfo); } for (int row1 = 0; row1 < imi1.rows; row1++, row2++) { for (int tx = 0; tx < nTilesXcur; tx++) { ImageLineInt line1 = (ImageLineInt) readers[tx].readRow(row1); // read line System.arraycopy(line1.getScanline(), 0, line2.getScanline(), line1.getScanline().length * tx, line1.getScanline().length); } pngw.writeRow(line2, row2); // write to full image } for (int tx = 0; tx < nTilesXcur; tx++) readers[tx].end(); // close readers } pngw.end(); // close writer } public static void main(String[] args) { doTiling(new String[] { "t1.png", "t2.png", "t3.png", "t4.png", "t5.png", "t6.png" }, "tiled.png", 2); System.out.println("done"); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With