[SCALA] 어떻게 하나 개의 큰 PNG 파일에 여러 개의 PNG 파일을 결합?
SCALA어떻게 하나 개의 큰 PNG 파일에 여러 개의 PNG 파일을 결합?
나는 약이있다. 6000 개 PNG 파일 (256 * 256 픽셀) 및 프로그래밍 모두를 들고 큰 PNG로 결합하고 싶다.
그렇게 할 수있는 최선의 / 가장 빠른 방법은 무엇입니까?
(목적은 그래서, 그림 파일이 많은 사용 오류를 제거 할 옵션을 선택하지 않습니다 일부 웹 기술을 사용하고 하나를 가지고, 용지에 인쇄됩니다.)
나는 파드의 제안을 시도하지만 높은 폭 24,576 픽셀 15,360 픽셀 BufferedImage를 만들려고 할 때 나는 NullPointerException이 얻을. 어떤 아이디어?
해결법
-
==============================
1.당신이 쓸 것이다 큰 이미지를 만듭니다. 당신이 원하는 얼마나 많은 행과 열을 기반으로 차원을 작업 할 수 있습니다.
당신이 쓸 것이다 큰 이미지를 만듭니다. 당신이 원하는 얼마나 많은 행과 열을 기반으로 차원을 작업 할 수 있습니다.
BufferedImage result = new BufferedImage( width, height, //work these out BufferedImage.TYPE_INT_RGB); Graphics g = result.getGraphics();
이제 이미지를 통해 루프는 그들을 잡아 :
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(); } }
마지막으로 파일에 쓰는 :
ImageIO.write(result,"png",new File("result.png"));
-
==============================
2.나는 (완전히 메모리에이 옵션이 아니었다 16 bitdepth-와 나는 내 경우, 큰 이미지 -와) 몇 시간 전에 몇 가지 유사한 필요가 있었다. 그리고 순차적 인 방법으로 읽기 / 쓰기를 할 수있는 PNG 라이브러리를 코딩했다. 경우 누군가 그것은 여기, 유용 찾을 수 있습니다.
나는 (완전히 메모리에이 옵션이 아니었다 16 bitdepth-와 나는 내 경우, 큰 이미지 -와) 몇 시간 전에 몇 가지 유사한 필요가 있었다. 그리고 순차적 인 방법으로 읽기 / 쓰기를 할 수있는 PNG 라이브러리를 코딩했다. 경우 누군가 그것은 여기, 유용 찾을 수 있습니다.
업데이트 : 여기에 샘플 코드입니다 :
/** * 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"); } }
-
==============================
3.나는 그것이 "처리 및 재 인코딩없이"가능할 것이다 표시되지 않습니다. 당신이 자바를 사용하여 주장하는 경우 난 그냥 당신이 JAI (프로젝트 페이지 여기)를 사용하는 것이 좋습니다. 당신은 하나의 큰 BufferedImage를 만드는 작은 이미지를로드하고 더 큰 하나를 그릴 것이라고으로.
나는 그것이 "처리 및 재 인코딩없이"가능할 것이다 표시되지 않습니다. 당신이 자바를 사용하여 주장하는 경우 난 그냥 당신이 JAI (프로젝트 페이지 여기)를 사용하는 것이 좋습니다. 당신은 하나의 큰 BufferedImage를 만드는 작은 이미지를로드하고 더 큰 하나를 그릴 것이라고으로.
아니면 그냥 ImageMagick이 몽타주를 사용합니다 :
montage *.png output.png
몽타주에 대한 자세한 내용은 사용을 참조하십시오.
-
==============================
4.PNG 형식은 타일에 대한 지원이 없다, 그래서 당신은 최소한 압축 해제 및 데이터 스트림을 다시 압축에서 탈출 할 수있는 방법은 없습니다. 모든 이미지의 팔레트가 동일 (또는 모든 결석) 인 경우, 이것은 당신이 정말로해야 할 유일한 일이다. (나는 또한 이미지가 인터레이스되지 않습니다 있으리라 믿고있어.)
PNG 형식은 타일에 대한 지원이 없다, 그래서 당신은 최소한 압축 해제 및 데이터 스트림을 다시 압축에서 탈출 할 수있는 방법은 없습니다. 모든 이미지의 팔레트가 동일 (또는 모든 결석) 인 경우, 이것은 당신이 정말로해야 할 유일한 일이다. (나는 또한 이미지가 인터레이스되지 않습니다 있으리라 믿고있어.)
당신은 한 번에 PNG 파일 오픈 한 "행"을 가진 데이터 스트림에서 적절한 크기의 청크를 읽고 출력 스트림을 작성, 스트리밍 방식으로이 작업을 수행 할 수 있습니다. 이 방법은 메모리에 전체 이미지를 보관할 필요가없는 것입니다. 가장 효율적인 방법은 자신을 libpng를 상단에이 프로그램을하는 것입니다. 당신 때문에 화소 예측의 메모리에 픽셀 조금 더보다 주사선을 유지해야 할 수도 있습니다.
그러나 단지 ImageMagick를, netpbm의 명령 줄 유틸리티를 사용하거나 비슷한 당신에게 약간의 이득이 될 것인가에 대한 개발 많은 시간을 절약 할 수 있습니다.
-
==============================
5.다른 사람들이 지적했듯이, 자바를 사용하는 것은 반드시 여기에 가장 좋은 방법이 아니다.
다른 사람들이 지적했듯이, 자바를 사용하는 것은 반드시 여기에 가장 좋은 방법이 아니다.
자바, 당신의 최선의 방법을 사용하려고하는 경우 - 당신은 당신이 메모리 여러 번에 전체 데이터 집합을 읽은 다음 다시 그것을 쓸 수 있도록 메모리에 충분히 짧은있어 가정 -와의 RenderedImage을 구현하는 것입니다 수요에 따라 디스크 떨어져 당신의 PNG 파일을 읽 클래스입니다. 당신이 당신의 자신의 새로운 BufferedImage를 만든 다음 그것을 작성하려고하면, PNG 작가는 데이터의 추가 사본이 생성됩니다. 당신이 당신의 자신의 RenderedImage를 작성하는 경우, 당신은 ImageIO.write (myImageSet, "PNG", myFileName)에 전달할 수 있습니다. 희망 그들은 모두 같은 것 - 당신은 당신의 첫번째 PNG에서의 SampleModel와 ColorModel의 정보를 복사 할 수 있습니다.
당신은 전체 이미지가 여러 타일 (원본 이미지 당 하나 개의 타일) 인 척하면, ImageIO.write는 전체 이미지 데이터 세트의 크기 가지는 WritableRaster를 생성하며, 그것을 채우기 위해 RenderedImage.copyData의 구현을 호출합니다 데이터. setRect (DX, DY, 래스터) 방법을 사용하여 - - 당신이 충분한 메모리가있는 경우, 이것은 당신이 데이터의 거대한 목표 세트를 얻을 그냥 그것으로 모든 이미지 데이터를 덤프 할 수 있기 때문에 (갈 수있는 가장 쉬운 방법은 다음 ) 다시에 대해 걱정할 필요가 없습니다. 나는이 메모리를 절약 할 수 있는지 여부를 테스트하지 않은,하지만 그것을해야 나에게 보인다.
당신은 전체 이미지가 하나의 타일 인 척하는 경우 또는, ImageIO.write는 래스터를 들어으로 getTile (0,0)를 사용하여, 그 전체 이미지에 해당하는 대응을 요청합니다. 그래서 당신은 차례로 자신의 DataBuffer를 만들 수 있습니다 자신의 래스터를 만들어야합니다. 나는이 방법을 시도했을 때, 최소 메모리 사용량이 있음을 성공적으로 15360x25600 RGB PNG가 기록 된 이미지의 픽셀 당 겨우 4 바이트 이상이다, (우연히 스칼라에서), 그래서 약간의 오버 헤드를 위 한 전체 이미지에있다 -Xmx1700M했다 썼다 기억.
안타깝게도 PNG 작가의 기본 구현은 메모리에 전체 픽셀 배열을한다고 가정하지만 - 그것은 덩어리 괜찮 작동합니다 - PNG 데이터 형식 자체는 메모리에 전체 이미지를 필요 아니다.
-
==============================
6.빗질 이미지
빗질 이미지
private static void combineALLImages(String screenNames, int screens) throws IOException, InterruptedException { System.out.println("screenNames --> D:\\screenshots\\screen screens --> 0,1,2 to 10/.."); int rows = screens + 1; int cols = 1; int chunks = rows * cols ; File[] imgFiles = new File[chunks]; String files = ""; for (int i = 0; i < chunks; i++) { files = screenNames + i + ".jpg"; imgFiles[i] = new File(files); System.out.println(screenNames + i + ".jpg"+"\t Screens : "+screens); } BufferedImage sample = ImageIO.read(imgFiles[0]); //Initializing the final image BufferedImage finalImg = new BufferedImage(sample.getWidth() * cols, sample.getHeight() * rows, sample.getType()); int index = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { BufferedImage temp = ImageIO.read(imgFiles[index]); finalImg.createGraphics().drawImage(temp, sample.getWidth() * j, sample.getHeight() * i, null); System.out.println(screenNames + index + ".jpg"); index++; } } File final_Image = new File("D:\\Screenshots\\FinalImage.jpg"); ImageIO.write(finalImg, "jpeg", final_Image); }
-
==============================
7.당신은 다른 (무손실) 이미지 형식 떨어져 일을 튀는 것이 가장 좋은 선택 일 수 있습니다. (당신은 기껏 타일의 한 행을 저장해야하므로이 디스크에 단지 하나의 큰 배열의 프로그래밍 방식에 타일을 넣어)하지만, 픽셀 당 12 바이트 (공간이 매우 낭비이다 PPM은 사용에 죽은 쉽습니다! ).
당신은 다른 (무손실) 이미지 형식 떨어져 일을 튀는 것이 가장 좋은 선택 일 수 있습니다. (당신은 기껏 타일의 한 행을 저장해야하므로이 디스크에 단지 하나의 큰 배열의 프로그래밍 방식에 타일을 넣어)하지만, 픽셀 당 12 바이트 (공간이 매우 낭비이다 PPM은 사용에 죽은 쉽습니다! ).
이어서 거대 PNG 형식으로 중간 및 회전을 취하는 표준 컨버터 (예컨대 ppm2png)를 사용한다.
-
==============================
8.하나 개의 큰 이미지로 타일에 합류에 대한 간단한 파이썬 스크립트 :
하나 개의 큰 이미지로 타일에 합류에 대한 간단한 파이썬 스크립트 :
import Image TILESIZE = 256 ZOOM = 15 def merge_images( xmin, xmax, ymin, ymax, output) : out = Image.new( 'RGB', ((xmax-xmin+1) * TILESIZE, (ymax-ymin+1) * TILESIZE) ) imx = 0; for x in range(xmin, xmax+1) : imy = 0 for y in range(ymin, ymax+1) : tile = Image.open( "%s_%s_%s.png" % (ZOOM, x, y) ) out.paste( tile, (imx, imy) ) imy += TILESIZE imx += TILESIZE out.save( output )
운영:
merge_images(18188, 18207, 11097, 11111, "output.png")
예를 들어 15_18188_11097.png를 들어, % ZOOM_ % XCORD_ % YCORD.png처럼라는 이름의 파일에 사용
-
==============================
9.이 같은 사용 ImageMagick과의 몽타주 :
이 같은 사용 ImageMagick과의 몽타주 :
montage *.png montage.png
당신은 여기에서 매개 변수에 대한 자세한 정보를 찾을 수 있습니다
행운을 빕니다
from https://stackoverflow.com/questions/3922276/how-to-combine-multiple-pngs-into-one-big-png-file by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 볼품를 사용하여 중첩 된지도에 중첩 된 경우 클래스를 변환 (0) | 2019.11.12 |
---|---|
[SCALA] 일반적인 방법에서 원래 수집 유형을 반환 (0) | 2019.11.12 |
[SCALA] MutableList와 ListBuffer의 차이 (0) | 2019.11.12 |
[SCALA] 어떻게 스칼라 스트림 클래스와 큰 CSV 파일을 읽습니까? (0) | 2019.11.12 |
[SCALA] 방법은 최종 않는 이유는 스칼라 컴파일러는 꼬리 호출 최적화를 적용하지 않습니다? (0) | 2019.11.12 |