Skip to content
Advertisement

Can not get the right color when hovering over image node in javafx

When I hover over the Image I am getting the wrong color value in some pixels of the image, which seems to be a kind of pixel shift.

I am using a MouseMoved event on the ImageView to get the x and y coordinates of the cursor on the image, then I create a Color instance using the color from those coordinates. Finally, I use that color to fill a Circle node.

I would like to know why it is returning the wrong color value for some pixels.

PS: I tried that on png and jpeg images but the same thing is happening.

This is the initialize method of the controller where I am setting the event listener to the ImageView:

 @FXML
    public ImageView inputImage;

    public void initialize() {

        inputImage.setOnMouseMoved(event -> {
            int xPosition = (int) event.getX();
            int yPosition = (int) event.getY();

            Color pixelColor = inputImage.getImage().getPixelReader().getColor(xPosition, yPosition);

            circleColor.setFill(pixelColor);
        });
    }

A part of the FXML file :

            <VBox HBox.hgrow="ALWAYS" alignment="CENTER">
                <HBox alignment="CENTER">
                    <VBox.margin>
                        <Insets bottom="50.0"/>
                    </VBox.margin>

                    <ImageView fx:id="inputImage" pickOnBounds="true" preserveRatio="true" fitHeight="300"
                               fitWidth="300">
                        <Image url="@../Resources/Default-image.png" backgroundLoading="true"/>
                    </ImageView>
                </HBox>

                <HBox alignment="CENTER">
                    <Button onAction="#handleFileChooserClick" text="load image"/>
                </HBox>
            </VBox>

            <VBox prefWidth="200" alignment="TOP_CENTER">
                <padding>
                    <Insets top="60" bottom="60"/>
                </padding>

                <VBox alignment="TOP_CENTER">
                    <Circle radius="70" fill="orange" stroke="black" fx:id="circleColor"/>
                    <VBox.margin>
                        <Insets bottom="50.0"/>
                    </VBox.margin>
                </VBox>

                <Button textAlignment="CENTER" text="Isolate Color"/>
            </VBox>

This how it looks like : enter image description here

Advertisement

Answer

you’re explicitly setting the fitwidth / fitheight through fxml so the display resolution may differ from the original image resolution if the image dimensions are not equal to the manually set fit width and height.

what you need to do is convert the mouse position x and y accordingly from the display range of [0…displayWidth] and [0…displayHeight] to the original dimensions [0…originalWidth] [0…originalHeight].

now the tricky part is that when you use preserveRatio, the display dimensions are calculated and are not always equal to the fit width and height, this answer describes a way to get the display width and height of an imageView that uses preserve ratio.

now that you have the display dimensions and the original dimensions, you can calculate a new pair (x, y) :

int adjustedX = mouseX * originalWidth / displayWidth;
int adjustedY = mouseY * originalHeight / displayHeight;

and you can use those to get the color from the input image.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement