Search in sources :

Example 6 with MCRTiledPictureProps

use of org.mycore.imagetiler.MCRTiledPictureProps in project mycore by MyCoRe-Org.

the class MCRTileCombineServlet method think.

/**
 * prepares render process and gets IView2 file and combines tiles.
 * The image dimensions and path are determined from {@link HttpServletRequest#getPathInfo()}:
 * <code>/{zoomAlias}/{derivateID}/{absoluteImagePath}</code>
 * where <code>zoomAlias</code> is mapped like this:
 * <table>
 * <caption>Mapping of zoomAlias to actual zoom level</caption>
 * <tr><th>zoomAlias</th><th>zoom level</th></tr>
 * <tr><td>'MIN'</td><td>1</td></tr>
 * <tr><td>'MID'</td><td>2</td></tr>
 * <tr><td>'MAX'</td><td>3</td></tr>
 * <tr><td>default and all others</td><td>0</td></tr>
 * </table>
 *
 * See {@link #init()} how to attach a footer to every generated image.
 */
@Override
protected void think(final MCRServletJob job) throws IOException, JDOMException {
    final HttpServletRequest request = job.getRequest();
    try {
        String pathInfo = request.getPathInfo();
        if (pathInfo.startsWith("/")) {
            pathInfo = pathInfo.substring(1);
        }
        String zoomAlias = pathInfo.substring(0, pathInfo.indexOf('/'));
        pathInfo = pathInfo.substring(zoomAlias.length() + 1);
        final String derivate = pathInfo.substring(0, pathInfo.indexOf('/'));
        String imagePath = pathInfo.substring(derivate.length());
        LOGGER.info("Zoom-Level: {}, derivate: {}, image: {}", zoomAlias, derivate, imagePath);
        final Path iviewFile = MCRImage.getTiledFile(MCRIView2Tools.getTileDir(), derivate, imagePath);
        try (FileSystem fs = MCRIView2Tools.getFileSystem(iviewFile)) {
            Path iviewFileRoot = fs.getRootDirectories().iterator().next();
            final MCRTiledPictureProps pictureProps = MCRTiledPictureProps.getInstanceFromDirectory(iviewFileRoot);
            final int maxZoomLevel = pictureProps.getZoomlevel();
            request.setAttribute(THUMBNAIL_KEY, iviewFile);
            LOGGER.info("IView2 file: {}", iviewFile);
            int zoomLevel = 0;
            switch(zoomAlias) {
                case "MIN":
                    zoomLevel = 1;
                    break;
                case "MID":
                    zoomLevel = 2;
                    break;
                case "MAX":
                    zoomLevel = 3;
                    break;
            }
            HttpServletResponse response = job.getResponse();
            if (zoomLevel > maxZoomLevel) {
                switch(maxZoomLevel) {
                    case 2:
                        zoomAlias = "MID";
                        break;
                    case 1:
                        zoomAlias = "MIN";
                        break;
                    default:
                        zoomAlias = "THUMB";
                        break;
                }
                if (!imagePath.startsWith("/"))
                    imagePath = "/" + imagePath;
                String redirectURL = response.encodeRedirectURL(MessageFormat.format("{0}{1}/{2}/{3}{4}", request.getContextPath(), request.getServletPath(), zoomAlias, derivate, imagePath));
                response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
                response.setHeader("Location", redirectURL);
                response.flushBuffer();
                return;
            }
            if (zoomLevel == 0 && footerImpl == null) {
                // we're done, sendThumbnail is called in render phase
                return;
            }
            ImageReader reader = MCRIView2Tools.getTileImageReader();
            try {
                BufferedImage combinedImage = MCRIView2Tools.getZoomLevel(iviewFileRoot, pictureProps, reader, zoomLevel);
                if (combinedImage != null) {
                    if (footerImpl != null) {
                        BufferedImage footer = footerImpl.getFooter(combinedImage.getWidth(), derivate, imagePath);
                        combinedImage = attachFooter(combinedImage, footer);
                    }
                    request.setAttribute(IMAGE_KEY, combinedImage);
                } else {
                    response.sendError(HttpServletResponse.SC_NOT_FOUND);
                }
            } finally {
                reader.dispose();
            }
        }
    } finally {
        LOGGER.info("Finished sending {}", request.getPathInfo());
    }
}
Also used : HttpServletRequest(javax.servlet.http.HttpServletRequest) Path(java.nio.file.Path) FileSystem(java.nio.file.FileSystem) HttpServletResponse(javax.servlet.http.HttpServletResponse) MCRTiledPictureProps(org.mycore.imagetiler.MCRTiledPictureProps) ImageReader(javax.imageio.ImageReader) BufferedImage(java.awt.image.BufferedImage)

Example 7 with MCRTiledPictureProps

use of org.mycore.imagetiler.MCRTiledPictureProps in project mycore by MyCoRe-Org.

the class MCRIVIEWIIIFImageImpl method provide.

@Override
public BufferedImage provide(String identifier, MCRIIIFImageSourceRegion region, MCRIIIFImageTargetSize targetSize, MCRIIIFImageTargetRotation rotation, MCRIIIFImageQuality imageQuality, String format) throws MCRIIIFImageNotFoundException, MCRIIIFImageProvidingException, MCRIIIFUnsupportedFormatException, MCRAccessException {
    long resultingSize = (long) targetSize.getHeight() * targetSize.getWidth() * (imageQuality.equals(MCRIIIFImageQuality.color) ? 3 : 1);
    long maxImageSize = MCRConfiguration.instance().getLong(MAX_BYTES);
    if (resultingSize > maxImageSize) {
        throw new MCRIIIFImageProvidingException("Maximal image size is " + (maxImageSize / 1024 / 1024) + "MB. [" + resultingSize + "/" + maxImageSize + "]");
    }
    if (!SUPPORTED_FORMATS.contains(format.toLowerCase(Locale.ENGLISH))) {
        throw new MCRIIIFUnsupportedFormatException(format);
    }
    Path tiledFile = tileFileProvider.getTiledFile(identifier);
    MCRTiledPictureProps tiledPictureProps = getTiledPictureProps(tiledFile);
    int sourceWidth = region.getX2() - region.getX1();
    int sourceHeight = region.getY2() - region.getY1();
    double targetWidth = targetSize.getWidth();
    double targetHeight = targetSize.getHeight();
    double rotatationRadians = Math.toRadians(rotation.getDegrees());
    double sinRotation = Math.sin(rotatationRadians);
    double cosRotation = Math.cos(rotatationRadians);
    final int height = (int) (Math.abs(targetWidth * sinRotation) + Math.abs(targetHeight * cosRotation));
    final int width = (int) (Math.abs(targetWidth * cosRotation) + Math.abs(targetHeight * sinRotation));
    BufferedImage targetImage;
    switch(imageQuality) {
        case bitonal:
            targetImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
            break;
        case gray:
            targetImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
            break;
        case color:
        default:
            if (transparentFormats.contains(format)) {
                targetImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
            } else {
                targetImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            }
    }
    // this value determines the zoom level!
    double largestScaling = Math.max(targetWidth / sourceWidth, targetHeight / sourceHeight);
    // We always want to use the the best needed zoom level!
    int sourceZoomLevel = (int) Math.min(Math.max(0, Math.ceil(tiledPictureProps.getZoomlevel() - Math.log(largestScaling) / LOG_HALF)), tiledPictureProps.getZoomlevel());
    // largestScaling is the real scale which is needed! zoomLevelScale is the scale of the nearest zoom level!
    double zoomLevelScale = Math.min(1.0, Math.pow(0.5, tiledPictureProps.getZoomlevel() - sourceZoomLevel));
    // this is the scale which is needed from the nearest zoom level to the required size of image
    double drawScaleX = (targetWidth / (sourceWidth * zoomLevelScale)), drawScaleY = (targetHeight / (sourceHeight * zoomLevelScale));
    // absolute region in zoom level this nearest zoom level
    double x1 = region.getX1() * zoomLevelScale, x2 = region.getX2() * zoomLevelScale, y1 = region.getY1() * zoomLevelScale, y2 = region.getY2() * zoomLevelScale;
    // now we detect the tiles to draw!
    int x1Tile = (int) Math.floor(x1 / 256), y1Tile = (int) Math.floor(y1 / 256), x2Tile = (int) Math.ceil(x2 / 256), y2Tile = (int) Math.ceil(y2 / 256);
    try (FileSystem zipFileSystem = MCRIView2Tools.getFileSystem(tileFileProvider.getTiledFile(identifier))) {
        Path rootPath = zipFileSystem.getPath("/");
        Graphics2D graphics = targetImage.createGraphics();
        if (rotation.isMirrored()) {
            graphics.scale(-1, 1);
            graphics.translate(-width, 0);
        }
        int xt = (int) ((targetWidth - 1) / 2), yt = (int) ((targetHeight - 1) / 2);
        graphics.translate((width - targetWidth) / 2, (height - targetHeight) / 2);
        graphics.rotate(rotatationRadians, xt, yt);
        graphics.scale(drawScaleX, drawScaleY);
        graphics.translate(-x1, -y1);
        graphics.scale(zoomLevelScale, zoomLevelScale);
        graphics.setClip(region.getX1(), region.getY1(), sourceWidth, sourceHeight);
        graphics.scale(1 / zoomLevelScale, 1 / zoomLevelScale);
        LOGGER.info(String.format(Locale.ROOT, "Using zoom-level: %d and scales %s/%s!", sourceZoomLevel, drawScaleX, drawScaleY));
        for (int x = x1Tile; x < x2Tile; x++) {
            for (int y = y1Tile; y < y2Tile; y++) {
                ImageReader imageReader = MCRIView2Tools.getTileImageReader();
                BufferedImage tile = MCRIView2Tools.readTile(rootPath, imageReader, sourceZoomLevel, x, y);
                graphics.drawImage(tile, x * 256, y * 256, null);
            }
        }
    } catch (IOException e) {
        throw new MCRIIIFImageProvidingException("Error while reading tiles!", e);
    }
    return targetImage;
}
Also used : Path(java.nio.file.Path) FileSystem(java.nio.file.FileSystem) MCRIIIFImageProvidingException(org.mycore.iiif.image.impl.MCRIIIFImageProvidingException) IOException(java.io.IOException) MCRIIIFUnsupportedFormatException(org.mycore.iiif.image.impl.MCRIIIFUnsupportedFormatException) MCRTiledPictureProps(org.mycore.imagetiler.MCRTiledPictureProps) ImageReader(javax.imageio.ImageReader) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D)

Example 8 with MCRTiledPictureProps

use of org.mycore.imagetiler.MCRTiledPictureProps in project mycore by MyCoRe-Org.

the class MCRImageThumbnailGenerator method getThumbnail.

@Override
public Optional<BufferedImage> getThumbnail(MCRPath path, int size) throws IOException {
    Path iviewFile = MCRImage.getTiledFile(MCRIView2Tools.getTileDir(), path.getOwner(), path.getFileName().toString());
    MCRTiledPictureProps iviewFileProps = getIviewFileProps(iviewFile);
    final double width = iviewFileProps.getWidth();
    final double height = iviewFileProps.getHeight();
    final int newWidth = width > height ? (int) Math.ceil(size * width / height) : size;
    final int newHeight = width > height ? size : (int) Math.ceil(size * height / width);
    // this value determines the zoom level!
    final double scale = newWidth / width;
    // We always want to use the the best needed zoom level!
    int sourceZoomLevel = (int) Math.min(Math.max(0, Math.ceil(iviewFileProps.getZoomlevel() - Math.log(scale) / Math.log(1.0 / 2.0))), iviewFileProps.getZoomlevel());
    // scale is the real scale which is needed! zoomLevelScale is the scale of the nearest zoom level!
    double zoomLevelScale = Math.min(1.0, Math.pow(0.5, iviewFileProps.getZoomlevel() - sourceZoomLevel));
    // this is the scale which is needed from the nearest zoom level to the required size of image
    double drawScale = (newWidth / (width * zoomLevelScale));
    try (FileSystem zipFileSystem = MCRIView2Tools.getFileSystem(iviewFile)) {
        Path rootPath = zipFileSystem.getPath("/");
        ImageReader imageReader = MCRIView2Tools.getTileImageReader();
        BufferedImage testTile = MCRIView2Tools.readTile(rootPath, imageReader, sourceZoomLevel, 0, 0);
        BufferedImage targetImage = getTargetImage(newWidth, newHeight, testTile);
        Graphics2D graphics = targetImage.createGraphics();
        graphics.scale(drawScale, drawScale);
        for (int x = 0; x < Math.ceil(width * zoomLevelScale / 256); x++) {
            for (int y = 0; y < Math.ceil(height * zoomLevelScale / 256); y++) {
                BufferedImage tile = MCRIView2Tools.readTile(rootPath, imageReader, sourceZoomLevel, x, y);
                graphics.drawImage(tile, x * 256, y * 256, null);
            }
        }
        return Optional.of(targetImage);
    }
}
Also used : MCRPath(org.mycore.datamodel.niofs.MCRPath) Path(java.nio.file.Path) FileSystem(java.nio.file.FileSystem) MCRTiledPictureProps(org.mycore.imagetiler.MCRTiledPictureProps) ImageReader(javax.imageio.ImageReader) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D)

Example 9 with MCRTiledPictureProps

use of org.mycore.imagetiler.MCRTiledPictureProps in project mycore by MyCoRe-Org.

the class MCRTilingAction method run.

/**
 * takes a {@link MCRTileJob} and tiles the referenced {@link MCRImage} instance.
 *
 * Also this updates tileJob properties of {@link MCRTileJob} in the database.
 */
public void run() {
    tileJob.setStart(new Date());
    MCRImage image;
    Path tileDir = MCRIView2Tools.getTileDir();
    try {
        image = getMCRImage();
        image.setTileDir(tileDir);
    } catch (IOException e) {
        LOGGER.error("Error while retrieving image for job: {}", tileJob, e);
        return;
    }
    MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
    mcrSession.setUserInformation(MCRSystemUserInformation.getSystemUserInstance());
    Transaction transaction = null;
    try (Session session = MCRHIBConnection.instance().getSession()) {
        MCRTileEventHandler tileEventHandler = new MCRTileEventHandler() {

            Transaction transaction;

            @Override
            public void preImageReaderCreated() {
                transaction = session.beginTransaction();
            }

            @Override
            public void postImageReaderCreated() {
                // beside tileJob, no write access so far
                session.clear();
                if (transaction.getStatus().isOneOf(TransactionStatus.ACTIVE)) {
                    transaction.commit();
                }
            }
        };
        try {
            MCRTiledPictureProps picProps = image.tile(tileEventHandler);
            tileJob.setFinished(new Date());
            tileJob.setStatus(MCRJobState.FINISHED);
            tileJob.setHeight(picProps.getHeight());
            tileJob.setWidth(picProps.getWidth());
            tileJob.setTiles(picProps.getTilesCount());
            tileJob.setZoomLevel(picProps.getZoomlevel());
        } catch (IOException e) {
            LOGGER.error("IOException occured while tiling a queued picture", e);
            throw e;
        }
        transaction = session.beginTransaction();
        session.update(tileJob);
        transaction.commit();
    } catch (Exception e) {
        LOGGER.error("Error while getting next tiling job.", e);
        if (transaction != null && transaction.getStatus().isOneOf(TransactionStatus.ACTIVE)) {
            transaction.rollback();
        }
        try {
            Files.deleteIfExists(MCRImage.getTiledFile(tileDir, tileJob.getDerivate(), tileJob.getPath()));
        } catch (IOException e1) {
            LOGGER.error("Could not delete tile file after error!", e);
        }
    } finally {
        MCRSessionMgr.releaseCurrentSession();
        mcrSession.close();
    }
}
Also used : MCRPath(org.mycore.datamodel.niofs.MCRPath) Path(java.nio.file.Path) MCRSession(org.mycore.common.MCRSession) Transaction(org.hibernate.Transaction) MCRTileEventHandler(org.mycore.imagetiler.MCRTileEventHandler) IOException(java.io.IOException) MCRTiledPictureProps(org.mycore.imagetiler.MCRTiledPictureProps) Date(java.util.Date) MCRImage(org.mycore.imagetiler.MCRImage) IOException(java.io.IOException) Session(org.hibernate.Session) MCRSession(org.mycore.common.MCRSession)

Aggregations

MCRTiledPictureProps (org.mycore.imagetiler.MCRTiledPictureProps)9 Path (java.nio.file.Path)8 BufferedImage (java.awt.image.BufferedImage)6 FileSystem (java.nio.file.FileSystem)6 ImageReader (javax.imageio.ImageReader)6 MCRPath (org.mycore.datamodel.niofs.MCRPath)4 Graphics2D (java.awt.Graphics2D)3 IOException (java.io.IOException)3 Graphics (java.awt.Graphics)1 FileSystemNotFoundException (java.nio.file.FileSystemNotFoundException)1 Date (java.util.Date)1 ZipFile (java.util.zip.ZipFile)1 HttpServletRequest (javax.servlet.http.HttpServletRequest)1 HttpServletResponse (javax.servlet.http.HttpServletResponse)1 Session (org.hibernate.Session)1 Transaction (org.hibernate.Transaction)1 JDOMException (org.jdom2.JDOMException)1 MCRException (org.mycore.common.MCRException)1 MCRSession (org.mycore.common.MCRSession)1 MCRCommand (org.mycore.frontend.cli.annotation.MCRCommand)1