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;
}
}
Excellent code. It helped a lot to understand how adaptive images work in CQ. Thanks a LOTT :D
ReplyDeleteThanks
DeleteCould 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
Deleteat 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
Hi thanks for sharing that code. I always get an IndexOutofBoundException:
ReplyDelete/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.