/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.server.headlessclient.dataui; import java.awt.Dimension; import org.apache.wicket.markup.html.DynamicWebResource; import org.apache.wicket.protocol.http.WebResponse; import org.apache.wicket.util.string.StringValueConversionException; import org.apache.wicket.util.time.Time; import com.servoy.j2db.util.Debug; import com.servoy.j2db.util.HTTPUtils; import com.servoy.j2db.util.ImageLoader; import com.servoy.j2db.util.MimeTypes; /** * A {@link DynamicWebResource} that will or can resize itself based on the {@link Dimension} it gets. * * @author jcompagner */ public final class MediaResource extends DynamicWebResource { /** * @author jcompagner * */ private final class MediaResourceState extends ResourceState { /** * @param lastModifiedTime */ public MediaResourceState(Time lastModifiedTime) { this.lastModifiedTime = lastModifiedTime; } /** * @see wicket.resource.DynamicByteArrayResource.ResourceState#getData() */ @Override public byte[] getData() { return resized == null ? bs : resized; } /** * @see wicket.resource.DynamicByteArrayResource.ResourceState#getContentType() */ @Override public String getContentType() { return contentType; } /** * @see wicket.resource.DynamicByteArrayResource.ResourceState#getLength() */ @Override public int getLength() { return getData().length; } } private static final long serialVersionUID = 1L; private boolean reduce; private boolean enlarge; private boolean keepAspect; byte[] resized; private Dimension resizedSize; private final byte[] bs; String contentType; private Dimension succededScaledDimension; private double iconWidth; private double iconHeight; private final Time lastModifiedTime; MediaResource() { bs = new byte[0]; lastModifiedTime = null; } public MediaResource(byte[] bs, int mediaOptions) { this(bs, mediaOptions, null); } public MediaResource(byte[] bs, int mediaOptions, Time lastModifiedTime) { this.lastModifiedTime = lastModifiedTime; this.bs = bs == null ? new byte[0] : bs; this.succededScaledDimension = this.resizedSize = ImageLoader.getSize(this.bs); this.iconWidth = succededScaledDimension.getWidth(); this.iconHeight = succededScaledDimension.getHeight(); this.reduce = (mediaOptions & 2) == 2; this.enlarge = (mediaOptions & 4) == 4; this.keepAspect = (mediaOptions & 8) == 8; this.contentType = MimeTypes.getContentType(bs); this.setCacheable(true); } @Override public ResourceState getResourceState() { int mediaOptions = 0; int width = 0; int height = 0; try { mediaOptions = getParameters().getInt("option", 0); //$NON-NLS-1$ width = getParameters().getInt("w", 0); //$NON-NLS-1$ height = getParameters().getInt("h", 0); //$NON-NLS-1$ } catch (StringValueConversionException ex) { Debug.error(ex); } if (mediaOptions != 0 && mediaOptions != 1 && width != 0 && height != 0) { checkResize(new Dimension(width, height)); } return new MediaResourceState(lastModifiedTime); } public String getContentType() { return contentType; } public void checkResize(Dimension size) { boolean resize = succededScaledDimension == null ? true : !succededScaledDimension.equals(size); double widthChange = 0; double heightChange = 0; double width = size.getWidth(); double height = size.getHeight(); // if it doesn't fit then resize == true // check then if we have to,or can, resize the original. if (resize) { succededScaledDimension = size; widthChange = iconWidth / width; heightChange = iconHeight / height; resize = widthChange > 1.01 || heightChange > 1.01 || widthChange < 0.99 || heightChange < 0.99; if (resize) { if (!(reduce && enlarge)) { if (reduce) { if (widthChange < 0.99 && heightChange < 0.99) { // may only reduce, so no resize resize = false; } else if (widthChange > 1.01 && heightChange > 1.01) { if (keepAspect) { if (widthChange > heightChange) { width = (int)(iconWidth / widthChange); height = (int)(iconHeight / widthChange); } else { width = (int)(iconWidth / heightChange); height = (int)(iconHeight / heightChange); } } } else if (widthChange > 1.01) { width = (int)(iconWidth / widthChange); if (keepAspect) { height = (int)(iconHeight / widthChange); } } else if (heightChange > 1.01) { height = (int)(iconHeight / heightChange); if (keepAspect) { width = (int)(iconWidth / heightChange); } } } else if (enlarge) { if (widthChange > 1.01 && heightChange > 1.01) { // may only reduce, so no resize resize = false; } else if (widthChange < 0.99 && heightChange < 0.99) { if (keepAspect) { if (widthChange > heightChange) { width = (int)(iconWidth / widthChange); height = (int)(iconHeight / widthChange); } else { width = (int)(iconWidth / heightChange); height = (int)(iconHeight / heightChange); } } } else if (widthChange < 0.99) { width = (int)(iconWidth / widthChange); if (keepAspect) { height = (int)(iconHeight / widthChange); } } else if (heightChange < 0.99) { height = (int)(iconHeight / heightChange); if (keepAspect) { width = (int)(iconWidth / heightChange); } } } else { resize = false; } } else { if (keepAspect) { if (widthChange > heightChange) { width = (int)(iconWidth / widthChange); height = (int)(iconHeight / widthChange); } else { width = (int)(iconWidth / heightChange); height = (int)(iconHeight / heightChange); } } } } } if (resize) { resized = ImageLoader.resize(this.bs, width <= 0 ? 1 : (int)width, height <= 0 ? 1 : (int)height, keepAspect); } if (resized == null) { resized = bs; } resizedSize = ImageLoader.getSize(resized); contentType = MimeTypes.getContentType(resized); return; } /** * @return */ public int getWidth() { return resizedSize == null ? 0 : resizedSize.width; } /** * @return */ public int getHeight() { return resizedSize == null ? 0 : resizedSize.height; } /** * @see wicket.markup.html.WebResource#setHeaders(wicket.protocol.http.WebResponse) */ @Override protected void setHeaders(WebResponse response) { super.setHeaders(response); if (!isCacheable()) { HTTPUtils.setNoCacheHeaders(response.getHttpServletResponse()); // response.setHeader("Cache-Control", "no-cache"); // response.setHeader("Pragma", "no-cache"); // response.setDateHeader("Expires", -1); } } public byte[] getRawData() { return bs; } }