Search in sources :

Example 1 with AssetHandler

use of com.day.cq.dam.api.handler.AssetHandler in project aem-core-wcm-components by Adobe-Marketing-Cloud.

the class AdaptiveImageServlet method resizeAndStream.

/**
     * Calling this method will copy the image's bytes into the response's output stream, after performing all the needed transformations
     * on the requested image.
     *
     * @param request         the request
     * @param response        the response
     * @param image           the image component resource
     * @param imageProperties the image properties
     * @param resizeWidth     the width to which the image has to be resized
     */
private void resizeAndStream(SlingHttpServletRequest request, SlingHttpServletResponse response, Resource image, ValueMap imageProperties, int resizeWidth) throws IOException {
    if (resizeWidth < 0) {
        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        return;
    }
    String fileReference = imageProperties.get(DownloadResource.PN_REFERENCE, String.class);
    String imageType = getImageType(request.getRequestPathInfo().getExtension());
    String extension = mimeTypeService.getExtension(imageType);
    Asset asset = null;
    Resource imageFile = null;
    if (StringUtils.isNotEmpty(fileReference)) {
        // the image is coming from DAM
        final Resource assetResource = request.getResourceResolver().getResource(fileReference);
        if (assetResource == null) {
            LOGGER.error(String.format("Unable to find resource %s used by image %s.", fileReference, image.getPath()));
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        asset = assetResource.adaptTo(Asset.class);
        if (asset == null) {
            LOGGER.error(String.format("Unable to adapt resource %s used by image %s to an asset.", fileReference, image.getPath()));
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        if ("gif".equalsIgnoreCase(extension)) {
            LOGGER.debug("GIF asset detected; will render the original rendition.");
            stream(response, asset.getOriginal().getStream(), imageType);
            return;
        }
    } else {
        imageFile = image.getChild(DownloadResource.NN_FILE);
        if ("gif".equalsIgnoreCase(extension)) {
            LOGGER.debug("GIF file detected; will render the original file.");
            InputStream is = imageFile.adaptTo(InputStream.class);
            if (is != null) {
                stream(response, is, imageType);
            }
            return;
        }
    }
    if (asset != null) {
        int rotationAngle = getRotation(image, imageProperties);
        Rectangle rectangle = getCropRect(image, imageProperties);
        if (rotationAngle != 0 || rectangle != null || resizeWidth > 0) {
            int originalWidth = getDimension(asset.getMetadataValue(DamConstants.TIFF_IMAGEWIDTH));
            int originalHeight = getDimension(asset.getMetadataValue(DamConstants.TIFF_IMAGELENGTH));
            AssetHandler assetHandler = assetStore.getAssetHandler(imageType);
            Layer layer = null;
            boolean appliedRotationOrCropping = false;
            if (rectangle != null) {
                double scaling;
                Rendition webRendition = getAWebRendition(asset);
                double renditionWidth = 1280D;
                if (webRendition != null) {
                    try {
                        renditionWidth = Double.parseDouble(webRendition.getName().split("\\.")[2]);
                        LOGGER.debug("Found rendition {} with width {}px; assuming the cropping rectangle was calculated using this " + "rendition.", webRendition.getPath(), renditionWidth);
                    } catch (NumberFormatException e) {
                        LOGGER.warn("Cannot determine rendition width for {}. Will fallback to 1280px.", webRendition.getPath());
                    }
                } else {
                    renditionWidth = originalWidth;
                }
                if (originalWidth > renditionWidth) {
                    scaling = (double) originalWidth / renditionWidth;
                } else {
                    scaling = renditionWidth / originalWidth;
                }
                layer = new Layer(assetHandler.getImage(asset.getOriginal()));
                if (Math.abs(scaling - 1.0D) != 0) {
                    Rectangle scaledRectangle = new Rectangle((int) (rectangle.x * scaling), (int) (rectangle.y * scaling), (int) (rectangle.getWidth() * scaling), (int) (rectangle.getHeight() * scaling));
                    layer.crop(scaledRectangle);
                } else {
                    layer.crop(rectangle);
                }
                appliedRotationOrCropping = true;
            }
            if (rotationAngle != 0) {
                if (layer == null) {
                    layer = new Layer(assetHandler.getImage(asset.getOriginal()));
                }
                layer.rotate(rotationAngle);
                LOGGER.debug("Applied rotation transformation ({} degrees).", rotationAngle);
                appliedRotationOrCropping = true;
            }
            if (!appliedRotationOrCropping) {
                Rendition rendition = asset.getRendition(String.format(DamConstants.PREFIX_ASSET_WEB + ".%d.%d.%s", resizeWidth, resizeWidth, extension));
                if (rendition != null) {
                    LOGGER.debug("Found rendition {} with a width equal to the resize width ({}px); rendering.", rendition.getPath(), resizeWidth);
                    stream(response, rendition.getStream(), imageType);
                } else {
                    int resizeHeight = calculateResizeHeight(originalWidth, originalHeight, resizeWidth);
                    if (resizeHeight > 0 && resizeHeight != originalHeight) {
                        layer = new Layer(assetHandler.getImage(asset.getOriginal()));
                        layer.resize(resizeWidth, resizeHeight);
                        response.setContentType(imageType);
                        LOGGER.debug("Resizing asset {} to requested width of {}px; rendering.", asset.getPath(), resizeWidth);
                        layer.write(imageType, 1.0, response.getOutputStream());
                    } else {
                        LOGGER.debug("Rendering the original asset {} since its width ({}px) is either smaller than the requested " + "width ({}px) or since no resize is needed.", asset.getPath(), originalWidth, resizeWidth);
                        stream(response, asset.getOriginal().getStream(), imageType);
                    }
                }
            } else {
                resizeAndStreamLayer(response, layer, imageType, resizeWidth);
            }
        } else {
            LOGGER.debug("No need to perform any processing on asset {}; rendering.", asset.getPath());
            stream(response, asset.getOriginal().getStream(), imageType);
        }
    } else if (imageFile != null) {
        InputStream is = null;
        try {
            is = imageFile.adaptTo(InputStream.class);
            int rotationAngle = getRotation(image, imageProperties);
            Rectangle rectangle = getCropRect(image, imageProperties);
            if (rotationAngle != 0 || rectangle != null || resizeWidth > 0) {
                Layer layer = null;
                if (rectangle != null) {
                    layer = new Layer(is);
                    layer.crop(rectangle);
                    LOGGER.debug("Applied cropping transformation.");
                }
                if (rotationAngle != 0) {
                    if (layer == null) {
                        layer = new Layer(is);
                    }
                    layer.rotate(rotationAngle);
                    LOGGER.debug("Applied rotation transformation ({} degrees).", rotationAngle);
                }
                if (layer == null) {
                    layer = new Layer(is);
                }
                resizeAndStreamLayer(response, layer, imageType, resizeWidth);
            } else {
                LOGGER.debug("No need to perform any processing on file {}; rendering.", imageFile.getPath());
                stream(response, is, imageType);
            }
        } finally {
            IOUtils.closeQuietly(is);
        }
    }
}
Also used : InputStream(java.io.InputStream) Rendition(com.day.cq.dam.api.Rendition) DownloadResource(com.day.cq.commons.DownloadResource) Resource(org.apache.sling.api.resource.Resource) ImageResource(com.day.cq.commons.ImageResource) Asset(com.day.cq.dam.api.Asset) AssetHandler(com.day.cq.dam.api.handler.AssetHandler) Layer(com.day.image.Layer)

Example 2 with AssetHandler

use of com.day.cq.dam.api.handler.AssetHandler in project aem-core-wcm-components by Adobe-Marketing-Cloud.

the class AdaptiveImageServletTest method init.

@Before
public void init() throws IOException {
    resourceResolver = aemContext.resourceResolver();
    servlet = new AdaptiveImageServlet();
    Whitebox.setInternalState(servlet, "mimeTypeService", mockedMimeTypeService);
    AssetHandler assetHandler = mock(AssetHandler.class);
    AssetStore assetStore = mock(AssetStore.class);
    when(assetStore.getAssetHandler(anyString())).thenReturn(assetHandler);
    when(assetHandler.getImage(any(Rendition.class))).thenAnswer(new Answer<BufferedImage>() {

        @Override
        public BufferedImage answer(InvocationOnMock invocationOnMock) throws Throwable {
            Rendition rendition = invocationOnMock.getArgumentAt(0, Rendition.class);
            return ImageIO.read(rendition.getStream());
        }
    });
    Whitebox.setInternalState(servlet, "assetStore", assetStore);
    activateServlet(servlet);
}
Also used : Rendition(com.day.cq.dam.api.Rendition) InvocationOnMock(org.mockito.invocation.InvocationOnMock) AssetHandler(com.day.cq.dam.api.handler.AssetHandler) AssetStore(com.day.cq.dam.api.handler.store.AssetStore) BufferedImage(java.awt.image.BufferedImage) Before(org.junit.Before)

Example 3 with AssetHandler

use of com.day.cq.dam.api.handler.AssetHandler in project aem-core-wcm-components by Adobe-Marketing-Cloud.

the class AdaptiveImageServletTest method setUp.

@BeforeEach
void setUp() throws Exception {
    internalSetUp(TEST_BASE);
    context.load().binaryFile("/image/" + PNG_IMAGE_RECTANGLE_BINARY_NAME, PNG_RECTANGLE_ASSET_PATH + "/jcr:content/renditions/original");
    context.load().binaryFile("/image/" + "cq5dam.web.1280.1280_" + PNG_IMAGE_BINARY_NAME, PNG_RECTANGLE_ASSET_PATH + "/jcr:content/renditions/cq5dam.web.1280.1280.png");
    context.load().binaryFile("/image/" + PNG_IMAGE_SMALL_BINARY_NAME, PNG_SMALL_ASSET_PATH + "/jcr:content/renditions/original");
    context.load().binaryFile("/image/" + "cq5dam.web.1280.1280_" + PNG_IMAGE_BINARY_NAME, PNG_SMALL_ASSET_PATH + "/jcr:content/renditions/cq5dam.web.1280.1280.png");
    resourceResolver = context.resourceResolver();
    AssetHandler assetHandler = mock(AssetHandler.class);
    AssetStore assetStore = mock(AssetStore.class);
    AdaptiveImageServletMetrics metrics = mock(AdaptiveImageServletMetrics.class);
    when(metrics.startDurationRecording()).thenReturn(mock(Timer.Context.class));
    when(assetStore.getAssetHandler(anyString())).thenReturn(assetHandler);
    IIORegistry registry = IIORegistry.getDefaultInstance();
    Iterator iter = registry.getServiceProviders(ImageReaderSpi.class, true);
    // Force ImageIO to pick TwelveMonkeys plugins for JPG and TIFF
    while (iter.hasNext()) {
        ImageReaderSpi provider = (ImageReaderSpi) iter.next();
        if (!provider.getClass().getName().contains("twelvemonkeys") && ((Arrays.stream(provider.getFormatNames()).filter(f -> "JPG".equalsIgnoreCase(f)).count() > 0) || (Arrays.stream(provider.getFormatNames()).filter(f -> "TIFF".equalsIgnoreCase(f)).count() > 0))) {
            registry.deregisterServiceProvider(provider);
        }
    }
    when(assetHandler.getImage(any(Rendition.class))).thenAnswer(invocation -> {
        Rendition rendition = invocation.getArgument(0);
        return ImageIO.read(rendition.getStream());
    });
    servlet = new AdaptiveImageServlet(mockedMimeTypeService, assetStore, metrics, ADAPTIVE_IMAGE_SERVLET_DEFAULT_RESIZE_WIDTH, AdaptiveImageServlet.DEFAULT_MAX_SIZE);
    testLogger = Utils.mockLogger(AdaptiveImageServlet.class, "LOGGER");
}
Also used : IIORegistry(javax.imageio.spi.IIORegistry) ImageReaderSpi(javax.imageio.spi.ImageReaderSpi) Rendition(com.day.cq.dam.api.Rendition) Iterator(java.util.Iterator) AssetHandler(com.day.cq.dam.api.handler.AssetHandler) AssetStore(com.day.cq.dam.api.handler.store.AssetStore) BeforeEach(org.junit.jupiter.api.BeforeEach)

Aggregations

Rendition (com.day.cq.dam.api.Rendition)3 AssetHandler (com.day.cq.dam.api.handler.AssetHandler)3 AssetStore (com.day.cq.dam.api.handler.store.AssetStore)2 DownloadResource (com.day.cq.commons.DownloadResource)1 ImageResource (com.day.cq.commons.ImageResource)1 Asset (com.day.cq.dam.api.Asset)1 Layer (com.day.image.Layer)1 BufferedImage (java.awt.image.BufferedImage)1 InputStream (java.io.InputStream)1 Iterator (java.util.Iterator)1 IIORegistry (javax.imageio.spi.IIORegistry)1 ImageReaderSpi (javax.imageio.spi.ImageReaderSpi)1 Resource (org.apache.sling.api.resource.Resource)1 Before (org.junit.Before)1 BeforeEach (org.junit.jupiter.api.BeforeEach)1 InvocationOnMock (org.mockito.invocation.InvocationOnMock)1