Tuesday, 22 July 2014

Render image rendtions dynamically in CQ5 - 2nd method


import java.awt.Dimension;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletException;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.commons.ImageHelper;
import com.day.cq.commons.SlingRepositoryException;
import com.day.cq.dam.api.Asset;
import com.day.cq.wcm.commons.AbstractImageServlet;
import com.day.image.Layer;

/**
 * Renders the image dynamically
 * Usage: /content/geometrixx/en/products/circle.thumbnail.500.500.jpg
 */
@Component
@Service
@org.apache.felix.scr.annotations.Properties({
      @org.apache.felix.scr.annotations.Property(name="sling.servlet.resourceTypes", value="sling/servlet/default"),
      @org.apache.felix.scr.annotations.Property(name="sling.servlet.selectors", value={"resize","thumb","thumbnail"}),
      @org.apache.felix.scr.annotations.Property(name="sling.servlet.extensions", value={"jpg", "png", "gif"}),
      @org.apache.felix.scr.annotations.Property(name="sling.servlet.methods", value="GET")
})
public class CustomThumbnailServlet extends AbstractImageServlet {

private static final long serialVersionUID = 1L;
private final Logger log = LoggerFactory.getLogger(this.getClass());

private final String ORIGINAL_PATH = "/jcr:content/renditions/original/jcr:content";
private Dimension DEFAULT_DIMENSION = null;

protected void writeLayer(SlingHttpServletRequest request, SlingHttpServletResponse response, AbstractImageServlet.ImageContext c, Layer layer)
        throws IOException, RepositoryException {

log.error("Calling  writeLayer");

int size = layer.getHeight() * layer.getWidth();
   if (size < 1048576)
   {
     ByteArrayOutputStream out = new ByteArrayOutputStream(size);
     layer.write(getImageType(), getImageQuality(), out);
     byte[] bytes = out.toByteArray();
     response.setContentLength(bytes.length);
     response.getOutputStream().write(bytes);
   }
   else {
     layer.write(getImageType(), getImageQuality(), response.getOutputStream());
   }
}

@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException{
Session session = null;
try {
 String[] selectors = request.getRequestPathInfo().getSelectors();
 String extension = request.getRequestPathInfo().getExtension();
 String imagePath = request.getRequestPathInfo().getResourcePath().substring(0, request.getRequestPathInfo().getResourcePath().indexOf("."));

 String type = getImageType(extension);
     if (type == null) {
       response.sendError(404, "Image type not supported");
       return;
     }
     response.setContentType(type);
   
     ImageContext context = new ImageContext(request, type);    
     session = (Session)request.getResourceResolver().adaptTo(Session.class);
   
     Resource resource = context.request.getResourceResolver().getResource(imagePath+"."+extension);
     Asset asset = resource.adaptTo(Asset.class);
   
     Layer layer = ImageHelper.createLayer(session.getNode(imagePath+"."+extension).getSession(), asset.getOriginal().getPath());
         
     DEFAULT_DIMENSION = new Dimension(layer.getWidth(), layer.getHeight());
     int maxHeight = selectors.length > 1 ? Integer.valueOf(selectors[1]).intValue() : (int)DEFAULT_DIMENSION.getHeight();
 int maxWidth = selectors.length > 2 ? Integer.valueOf(selectors[2]).intValue() : (int)DEFAULT_DIMENSION.getWidth();
   
     if (layer != null) {
     layer.resize(maxWidth, maxHeight, true);
         applyDiff(layer, context);
       }    
     writeLayer(request, response, context, layer);
   
} catch (RepositoryException e) {
     throw new SlingRepositoryException(e);
   }finally{
    if(session != null)
    session.logout();
   }
 }

protected Layer createLayer(ImageContext paramImageContext) throws RepositoryException, IOException {
return null;
}

 @Override
 protected String getImageType()
 {
   return "image/png";
 }

 @Override
 protected String getImageType(String ext)
 {
   if ("png".equals(ext))
     return "image/png";
   if ("gif".equals(ext))
     return "image/gif";
   if (("jpg".equals(ext)) || ("jpeg".equals(ext))) {
     return "image/jpg";
   }
   return null;
 }
}

4 comments:

  1. Excellent code. It helped a lot to understand how adaptive images work in CQ. Thanks a LOTT :D

    ReplyDelete
    Replies
    1. Could you please help us, I am getting an issue when one item is removed and then, I try to add a new one. it seems related to getEL Uncaught TypeError: Cannot read property 'getBoundingClientRect' of null
      at Object.getXY (widgets.min.js:formatted:1363)
      at Function.CQ.Ext.lib.Region.getRegion (widgets.min.js:formatted:7287)
      at constructor.CF_storeDropTargets (widgets.min.js:formatted:86069)
      at widgets.min.js:formatted:86113

      Delete
  2. Hi thanks for sharing that code. I always get an IndexOutofBoundException:

    /content/geometrixx/en/products/circle/jcr%3Acontent/par/image.thumbnail.500.500.jpg HTTP/1.1] com.day.cq.wcm.core.impl.WCMDebugFilter Exception: String index out of range: -1
    java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.substring(Unknown Source)
    at XXXX.CustomThumbnailServlet.doGet(CustomThumbnailServlet.java:72)

    Could you please help in pointing out what exactly am I doing wrong.

    ReplyDelete