Document-Archiver / com.sophisticatedapps.archiving.document-archiver

https://document-archiver.github.io/
Apache License 2.0
25 stars 4 forks source link

Better image support #15

Open Dansoftowner opened 3 years ago

Dansoftowner commented 3 years ago

Hi @stephansann ,

I would make an enhancement request. There should be a zoom support when you open images, because if I open a large picture like this: Screenshot I can't see anything of it because it is displayed in a simple ImageView.

I had to implement a good zooming support for images in my project, so I can recommend you to have a look at GestureFX, it allows you to build a zoomable pane around your node (in this case image-view).

Best regards Daniel

stephansann commented 3 years ago

Hi @Dansoftowner

I agree the current solution is not optimal.

I'll have a look what I can do about it and also at the suggested library.

Best regards Stephan

stephansann commented 3 years ago

Hi @Dansoftowner

This was pretty easy to add. If you like check it out with the latest SNAPSHOT-build: https://repository.sophisticatedapps.com/snapshots/com/sophisticatedapps/archiving/document-archiver/2.1.0-SNAPSHOT/document-archiver-2.1.0-20210511.101138-3-linux.zip

As alway thanks for the suggestion and the interesting hint to a solution.

Best regards Stephan

Dansoftowner commented 3 years ago

Hi @stephansann

So nice work! I would make an improvement suggestion: it would be nice to have the ability to zoom the image by double-clicking it, what do you think?

Best regards Daniel

stephansann commented 3 years ago

Hi @Dansoftowner

Thanks for the suggestion.

I already saw the matching code snippet on the project page, but I found the behavior too arbitrary. No image viewer I know behaves this way. So what happens if I double-click again? 4x zoom? Or going back to 1x? (Maybe 2x zoom was also not big enough!?)

I would love to implement it the way Safari shows an image:

I started to try out to do it this way, but there are some obstacles:

I guess if one spends a lot of time with it, one could make it work the "Safari way". But there are more important things to add.

Anyhow if you already have experience from your project, feel free to suggest a matching code for com.sophisticatedapps.archiving.documentarchiver.controller.DisplayFilePaneController.DisplayImageNodeAssembler#assemble 😉

Best regards Stephan

stephansann commented 3 years ago

Hi @Dansoftowner

A slightly related note: I just introduced the rotation of images based on EXIF data: https://repository.sophisticatedapps.com/snapshots/com/sophisticatedapps/archiving/document-archiver/2.1.0-SNAPSHOT/document-archiver-2.1.0-20210513.141304-4-linux.zip

Anyhow I nailed it only 80%. javafx.scene.Node#setRotate was giving me a hard time. After hours of trial and error I now got to a point where everything is rotated correctly and the image is not only shown in one half, is being misplaced or similar misconducts I saw on my attempts. But still images which are rotated 90 degrees get cropped to a square. Now I'm on my wits' end.

You said you have some experience with ImageViews!? Any idea from your side? This is my current code:

    protected static class DisplayImageNodeAssembler implements DisplayFileNodeAssembler {

        @Override
        public Region assemble(DisplayFilePaneController aDisplayFilePaneController, File aFile, Stage aStage,
                               double aPrefWidth, double aPrefHeight) {

            ImageUtil.OrientationInformation tmpOrientationInformation = ImageUtil.getOrientationInformation(aFile);
            double tmpImageRotationCw = tmpOrientationInformation.getRotationCw();
            boolean tmpImageTilted = ((tmpImageRotationCw != 0) && (tmpImageRotationCw != 180));

            try (BufferedInputStream tmpInputStream = new BufferedInputStream(new FileInputStream(aFile))) {

                // Creating the Image and ImageView objects.
                Image tmpImage = new Image(tmpInputStream);
                ImageView tmpImageView = new ImageView(tmpImage);

                // Do we need to rotate?
                if (tmpImageRotationCw > 0) {

                    double tmpViewPortWidth = (tmpImageTilted ? tmpImage.getHeight() : tmpImage.getWidth());
                    double tmpViewPortHeight = (tmpImageTilted ? tmpImage.getWidth() : tmpImage.getHeight());
                    tmpImageView.setViewport(new Rectangle2D(0, 0, tmpViewPortWidth, tmpViewPortHeight));

                    tmpImageView.setRotate(tmpImageRotationCw);
                }

                //Setting the image view parameters
                tmpImageView.setX(0);
                tmpImageView.setY(10);
                tmpImageView.setPreserveRatio(true);
                adjustHorizontalSize(tmpImageView, tmpImageTilted, aPrefWidth);

                GesturePane tmpPane = new GesturePane(new Pane(tmpImageView));
                tmpPane.widthProperty().addListener((anObservable, anOldValue, aNewValue) ->
                        adjustHorizontalSize(tmpImageView, tmpImageTilted, aNewValue.doubleValue()));

                return (tmpPane);
            }
            catch (Exception e) {

                throw (new RuntimeException("Image could not be loaded."));
            }
        }

        private void adjustHorizontalSize(ImageView anImageView, boolean anIsTilted, double aSize) {

            if (!anIsTilted) {

                anImageView.setFitWidth(aSize);
            }
            else {

                anImageView.setFitHeight(aSize);
            }
        }
    }

Thanks and best regards Stephan