class StreamImageView implements ActionListener, AncestorListener
{
    private final BufferedImage image;
    private JScrollPane scrollPane;
    private JLabel label;
    private ZoomMenu zoomMenu;
    private RotationMenu rotationMenu;

    /**
     * constructor.
     * @param image instance of BufferedImage.
     */
    StreamImageView(BufferedImage image)
    {
        this.image = image;
        initUI();
    }

    private void initUI()
    {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        zoomMenu = ZoomMenu.getInstance();
        zoomMenu.changeZoomSelection(zoomMenu.getImageZoomScale());

        label = new JLabel();
        label.setBorder(new LineBorder(Color.BLACK));
        label.setAlignmentX(Component.CENTER_ALIGNMENT);
        addImage(zoomImage(image, zoomMenu.getImageZoomScale(), RotationMenu.getRotationDegrees()));

        panel.add(Box.createVerticalGlue());
        panel.add(label);
        panel.add(Box.createVerticalGlue());

        scrollPane = new JScrollPane();
        scrollPane.setPreferredSize(new Dimension(300, 400));
        scrollPane.addAncestorListener(this);
        scrollPane.setViewportView(panel);
    }

    /**
     * Returns the view i.e container containing image.
     * @return A JComponent instance.
     */
    JComponent getView()
    {
        return scrollPane;
    }

    private Image zoomImage(BufferedImage origin, float scale, int rotation)
    {
        BufferedImage rotatedImage = ImageUtil.getRotatedImage(origin, rotation);
        int resizedWidth = (int) (rotatedImage.getWidth() * scale);
        int resizedHeight = (int) (rotatedImage.getHeight() * scale);
        return rotatedImage.getScaledInstance(resizedWidth, resizedHeight, Image.SCALE_SMOOTH);
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent)
    {
        String actionCommand = actionEvent.getActionCommand();
        if (ZoomMenu.isZoomMenu(actionCommand) || RotationMenu.isRotationMenu(actionCommand))
        {
            addImage(zoomImage(image, ZoomMenu.getZoomScale(), RotationMenu.getRotationDegrees()));
            zoomMenu.setImageZoomScale(ZoomMenu.getZoomScale());
        }
    }

    private void addImage(Image img)
    {<FILL_FUNCTION_BODY>}

    @Override
    public void ancestorAdded(AncestorEvent ancestorEvent)
    {
        zoomMenu.addMenuListeners(this);
        zoomMenu.setEnableMenu(true);
        
        rotationMenu = RotationMenu.getInstance();
        rotationMenu.addMenuListeners(this);
        rotationMenu.setRotationSelection(RotationMenu.ROTATE_0_DEGREES);
        rotationMenu.setEnableMenu(true);
    }

    @Override
    public void ancestorRemoved(AncestorEvent ancestorEvent)
    {
        zoomMenu.setEnableMenu(false);
        rotationMenu.setEnableMenu(false);
    }

    @Override
    public void ancestorMoved(AncestorEvent ancestorEvent)
    {
    }
}

        // for JDK9; see explanation in PagePane
        AffineTransform tx = GraphicsEnvironment.getLocalGraphicsEnvironment().
                getDefaultScreenDevice().getDefaultConfiguration().getDefaultTransform();
        label.setSize((int) Math.ceil(img.getWidth(null) / tx.getScaleX()), 
                      (int) Math.ceil(img.getHeight(null) / tx.getScaleY()));
        label.setIcon(new HighResolutionImageIcon(img, label.getWidth(), label.getHeight()));
        label.revalidate();
    
<no_super_class>