2015-01-27 3 views
2

간단한 작업을하려고합니다. 바이너리 이미지가 있고 컬러 이미지에 바이너리 이미지를 오버레이하는 것이지만 이진 이미지의 흰색 픽셀은 빨간색이어야하고 검정색 투명해야합니다. 저는 JavaFx에 익숙하지만 저는이 문제에 익숙합니다. PixelReader를 사용하여 모든 픽셀을 반복 처리하여 얻을 수 있지만 더 쉬운 방법이라고 확신합니다. 나는 어떤 종류의 혼합 효과를 사용하려고 시도했지만 지금까지는 운이 없다. 는 나는 다음과 유사해야한다고 생각 : How to Blend two Image in javaFXjavafx에서 이미지 오버레이 마스크 만들기

Example of what I want to achieve

내가이 함께했다 : 이미지 이미지 = 새 이미지 ("/ circle.jpg", 거짓); ImageView iv = 새로운 ImageView (이미지);

Image mask = new Image("/mask.jpg", false); 
ImageView ivMask = new ImageView(mask); 

Rectangle r = new Rectangle(mask.getWidth(), mask.getHeight()); 
r.setFill(Color.RED); 

r.setBlendMode(BlendMode.MULTIPLY); // sets the white area red 

Group g = new Group(ivMask, r); // sets the white area red 


// this is not working as expected 
iv.setBlendMode(BlendMode.DIFFERENCE); 

Group g2 = new Group(iv, g); 

의견을 보내 주셔서 감사합니다. 오버레이를 만드는 것보다 픽셀 단위로 처리하는 것이 빠르다고 생각되면 알려 주시기 바랍니다. 픽셀 독자에 의해

솔루션은 다음과 같습니다

Pane root = new Pane(); 

// read the underlaying image 
root.getChildren().add(new ImageView(new Image("/src.jpg"))); 

Image mask = new Image("/mask.jpg"); 
PixelReader pixelReader = mask.getPixelReader(); 

Canvas resultCanvas = new Canvas(); 
root.getChildren().add(resultCanvas); 

GraphicsContext resultLayer = resultCanvas.getGraphicsContext2D(); 
for (int y = 0; y < mask.getHeight(); y++) { 
    for (int x = 0; x < mask.getWidth(); x++) { 
    if(pixelReader.getColor(x, y).equals(Color.WHITE)){ 
     resultLayer.fillRect(x, y, 1.0, 1.0); 
    } 
    } 
} 

건배!

답변

2

무슨 일을 잘못

차이 연산자는 픽셀이는, 그래서 대신 단색 빨강 오버레이의 RGB 구성 요소에 차이가 대신 설정 여부에 따라 이진 차이가없는 당신 블렌드 이미지의 RGB 구성 요소의 차이가 픽셀마다 다르기 때문에 멀티 오버레이를 얻을 수 있습니다.

당신은 혼합 모드와 masked bit-blit operation 비슷한 일을하려고하는

배경 (기본적를,은 OR 다음 검은 마스크에 흰색을 기준으로 픽셀 데이터의 AND). JavaFX 8에 내장 된 블렌드를 사용하면 약간의 어려움이있을 수 있습니다. 구현을 Swing has과 같이 노출하는 것 외에도 비트 블릿 스타일 기본 사항에 대한 블렌드 API에서 추가 지원을위한 기능 요청을 만들 수 있습니다 그래서 기본 블렌딩 엔진은 좀 더 많은 힘을 가지며 사용하기가 조금 더 쉽습니다.

대안

할 선호하는 것은 알파 채널에 검은 부분을 변환하는 포토샵과 같은 이미지 편집기에서 마스크를 프로세스 미리하는 것 - 다음 방금 위에 마스크 레이어 수 원본과 기본 합성 모드에서 가져옵니다.

알파 활성화 마스크를 빨간색으로 만들려면 mask.setBlendMode(BlendMode.RED)을 사용하거나 프로그램에서 사용하기 전에 이미지 편집기에서 마스크를 미리 채울 수 있습니다.

또 다른 방법은 질문에 PixelReader 솔루션을 사용하는 것입니다 (알파를 사용하기 위해 마스크를 사전 변환 할 수 없다면 괜찮습니다).

적절한 하드웨어에서 블렌드 작업을 하드웨어 가속화 할 수 있습니다.따라서 자주 사용하는 경우 블렌드를 사용하는 것이 더 빠를 수 있습니다 (그러나 어떤 종류의 성능 차이라도 알기 위해서는 큰 이미지에서 여러 블렌드를 매우 빨리 실행해야합니다).

샘플 솔루션 사용하여 혼합 작업

샘플 출력

blended

입력 이미지

original.jpg

original

stencil.jpg

stencil

당신이 대답과 함께 오는 하나가 될 것입니다 알고

import javafx.application.Application; 
import javafx.geometry.Insets; 
import javafx.scene.*; 
import javafx.scene.effect.BlendMode; 
import javafx.scene.image.*; 
import javafx.scene.layout.HBox; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.stage.Stage; 

public class Blended extends Application { 
    @Override 
    public void start(Stage stage) { 
     Image original = new Image(
      getClass().getResourceAsStream("original.jpg") 
     ); 

     Image stencil = new Image(
      getClass().getResourceAsStream("stencil.jpg") 
     ); 

     // first invert the stencil so that it is black on white rather than white on black. 
     Rectangle whiteRect = new Rectangle(stencil.getWidth(), stencil.getHeight()); 
     whiteRect.setFill(Color.WHITE); 
     whiteRect.setBlendMode(BlendMode.DIFFERENCE); 

     Group inverted = new Group(
       new ImageView(stencil), 
       whiteRect 
     ); 

     // overlay the black portions of the inverted mask onto the image. 
     inverted.setBlendMode(BlendMode.MULTIPLY); 
     Group overlaidBlack = new Group(
       new ImageView(original), 
       inverted 
     ); 

     // create a new mask with a red tint (red on black). 
     Rectangle redRect = new Rectangle(stencil.getWidth(), stencil.getHeight()); 
     redRect.setFill(Color.RED); 
     redRect.setBlendMode(BlendMode.MULTIPLY); 

     Group redStencil = new Group(
       new ImageView(stencil), 
       redRect 
     ); 

     // overlay the red mask on to the image. 
     redStencil.setBlendMode(BlendMode.ADD); 
     Group overlaidRed = new Group(
       overlaidBlack, 
       redStencil 
     ); 

     // display the original, composite image and stencil. 
     HBox layout = new HBox(10); 
     layout.getChildren().addAll(
       new ImageView(original), 
       overlaidRed, 
       new ImageView(stencil) 
     ); 
     layout.setPadding(new Insets(10)); 
     stage.setScene(new Scene(layout)); 
     stage.show(); 
    } 

    public static void main(String[] args) { 
     launch(); 
    } 
} 
+0

코드입니다. :-) – blaster

+0

나는 당신의 대답으로 무언가를 시도했다. 몇 가지 스텐실 (동일한 치수와 이진수)을 결합하고 싶습니다. 나는 스텐실 (스텐실 이미지를 의미 함)으로 행동해야하는 그룹을 만들었다. sth ImageView처럼 iv1 = 새로운 ImageView (스텐실 1); iv1.setBlendMode (BlendMode.ADD) 등등 ..이 그룹에 넣어. 여태까지는 그런대로 잘됐다. 거꾸로 된 스텐실을 만들기 위해 위의 코드를 사용하고 새로운 ImageView (스텐실)를 미리 만든 그룹으로 대체했습니다. 그러나 결과는 검은 색입니다. 어떤 제안? – blaster

+0

나는 당신의 코멘트 블래스터를 이해하지 못한다. 원래 질문과 다른 것을 시도하고 어려움을 겪고 있다면 새로운 질문을하십시오. – jewelsea