2015-10-14 10:15:00 +02:00
2006-04-03 00:59:53 +02:00
// ViewImage.java
// -----------------------
// part of YaCy
2008-07-20 19:14:51 +02:00
// (C) by Michael Peter Christen; mc@yacy.net
2006-04-03 00:59:53 +02:00
// first published on http://www.anomic.de
// Frankfurt, Germany, 2006
// created 03.04.2006
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import java.awt.Container ;
2015-10-14 10:15:00 +02:00
import java.awt.Dimension ;
2014-05-22 15:01:58 +02:00
import java.awt.Graphics2D ;
2006-04-03 00:59:53 +02:00
import java.awt.Image ;
import java.awt.MediaTracker ;
2015-11-26 09:30:43 +01:00
import java.awt.Rectangle ;
2011-05-07 09:45:02 +02:00
import java.awt.image.BufferedImage ;
import java.awt.image.Raster ;
2015-11-26 09:30:43 +01:00
import java.io.ByteArrayOutputStream ;
2015-12-21 01:05:59 +01:00
import java.io.File ;
2006-10-03 13:05:48 +02:00
import java.io.IOException ;
2015-11-18 10:15:06 +01:00
import java.io.InputStream ;
2015-11-26 09:30:43 +01:00
import java.util.Iterator ;
2011-03-22 12:00:55 +01:00
import java.util.Map ;
2006-04-03 00:59:53 +02:00
2015-11-18 10:15:06 +01:00
import javax.imageio.ImageIO ;
2015-11-26 09:30:43 +01:00
import javax.imageio.ImageReader ;
2015-11-18 10:15:06 +01:00
import javax.imageio.stream.ImageInputStream ;
2013-09-15 00:30:23 +02:00
import net.yacy.cora.document.id.DigestURL ;
2014-12-28 14:53:55 +01:00
import net.yacy.cora.document.id.MultiProtocolURL ;
2012-09-25 21:20:03 +02:00
import net.yacy.cora.federate.yacy.CacheStrategy ;
2013-05-20 22:05:28 +02:00
import net.yacy.cora.protocol.ClientIdentification ;
2012-06-26 00:08:25 +02:00
import net.yacy.cora.protocol.Domains ;
2010-08-23 14:32:02 +02:00
import net.yacy.cora.protocol.HeaderFramework ;
import net.yacy.cora.protocol.RequestHeader ;
2011-03-22 12:00:55 +01:00
import net.yacy.cora.storage.ConcurrentARC ;
2013-07-09 14:28:25 +02:00
import net.yacy.cora.util.ConcurrentLog ;
2016-01-08 23:18:13 +01:00
import net.yacy.data.InvalidURLLicenceException ;
2013-02-13 00:33:53 +01:00
import net.yacy.data.URLLicense ;
2016-01-08 23:18:13 +01:00
import net.yacy.http.servlets.TemplateMissingParameterException ;
2015-12-21 01:05:59 +01:00
import net.yacy.kelondro.util.FileUtils ;
2011-03-22 12:00:55 +01:00
import net.yacy.kelondro.util.MemoryControl ;
2013-04-25 11:33:17 +02:00
import net.yacy.kelondro.workflow.WorkflowProcessor ;
2014-12-19 17:38:58 +01:00
import net.yacy.peers.graphics.EncodedImage ;
2012-07-02 13:57:29 +02:00
import net.yacy.repository.Blacklist.BlacklistType ;
2015-11-18 10:15:06 +01:00
import net.yacy.repository.LoaderDispatcher ;
2011-09-25 18:59:06 +02:00
import net.yacy.search.Switchboard ;
2012-09-21 15:48:16 +02:00
import net.yacy.server.serverObjects ;
import net.yacy.server.serverSwitch ;
2006-04-03 00:59:53 +02:00
public class ViewImage {
2015-12-21 01:05:59 +01:00
private static Map < String , Image > iconcache = new ConcurrentARC < String , Image > ( 1000 ,
Math . max ( 10 , Math . min ( 32 , WorkflowProcessor . availableCPU * 2 ) ) ) ;
private static String defaulticon = " htroot/env/grafics/dfltfvcn.ico " ;
private static byte [ ] defaulticonb = null ;
2015-10-14 10:15:00 +02:00
2015-11-05 09:45:19 +01:00
/ * *
2016-01-08 23:18:13 +01:00
* Try parsing image from post " url " parameter ( authenticated users ) or from " code " parameter ( non authenticated users ) .
2015-11-05 09:45:19 +01:00
* When image format is not supported , return directly image data . When
* image could be parsed , try encoding to target format specified by header
* " EXT " .
*
* @param header
* request header
* @param post
* post parameters
* @param env
* environment
* @return an { @link EncodedImage } instance encoded in format specified in
2015-12-01 09:55:47 +01:00
* post , or an InputStream pointing to original image data .
* Return and EncodedImage with empty data when image format is not supported ,
* a read / write or any other error occured while loading resource .
2015-11-05 09:45:19 +01:00
* @throws IOException
2015-12-01 09:55:47 +01:00
* when specified url is malformed .
2015-11-05 09:45:19 +01:00
* Sould end in a HTTP 500 error whose processing is more
2015-11-18 10:15:06 +01:00
* consistent across browsers than a response with zero content
* bytes .
2015-11-05 09:45:19 +01:00
* /
public static Object respond ( final RequestHeader header , final serverObjects post , final serverSwitch env )
throws IOException {
2015-10-14 10:15:00 +02:00
final Switchboard sb = ( Switchboard ) env ;
2016-01-08 23:18:13 +01:00
if ( post = = null ) {
throw new TemplateMissingParameterException ( " please fill at least url or code parameter " ) ;
}
2015-10-14 10:15:00 +02:00
String urlString = post . get ( " url " , " " ) ;
final String urlLicense = post . get ( " code " , " " ) ;
String ext = header . get ( " EXT " , null ) ;
final boolean auth = Domains . isLocalhost ( header . get ( HeaderFramework . CONNECTION_PROP_CLIENTIP , " " ) )
| | sb . verifyAuthentication ( header ) ; // handle access rights
DigestURL url = null ;
2016-01-08 23:18:13 +01:00
if ( auth ) {
/* Authenticated user : rely on url parameter*/
if ( urlString . length ( ) > 0 ) {
2015-12-01 09:55:47 +01:00
url = new DigestURL ( urlString ) ;
2016-01-08 23:18:13 +01:00
} else {
throw new TemplateMissingParameterException ( " missing required url parameter " ) ;
2015-12-01 09:55:47 +01:00
}
2016-01-08 23:18:13 +01:00
} else {
/* Non authenticated user : rely on urlLicense parameter */
if ( ( urlLicense . length ( ) > 0 ) ) {
urlString = URLLicense . releaseLicense ( urlLicense ) ;
if ( urlString ! = null ) {
url = new DigestURL ( urlString ) ;
} else { // license is gone (e.g. released/remove in prev calls)
ConcurrentLog . fine ( " ViewImage " , " image urlLicense not found key= " + urlLicense ) ;
/* Caller is responsible for handling this with appropriate HTTP status code */
throw new InvalidURLLicenceException ( ) ;
}
} else {
throw new TemplateMissingParameterException ( " missing required code parameter " ) ;
}
2015-10-14 10:15:00 +02:00
}
// get the image as stream
if ( MemoryControl . shortStatus ( ) ) {
iconcache . clear ( ) ;
}
EncodedImage encodedImage = null ;
Image image = iconcache . get ( urlString ) ;
if ( image ! = null ) {
encodedImage = new EncodedImage ( image , ext , post . getBoolean ( " isStatic " ) ) ;
} else {
2015-11-18 10:15:06 +01:00
ImageInputStream imageInStream = null ;
InputStream inStream = null ;
try {
2015-12-21 01:05:59 +01:00
String urlExt = MultiProtocolURL . getFileExtension ( url . getFileName ( ) ) ;
2015-12-01 01:06:01 +01:00
if ( ext ! = null & & ext . equalsIgnoreCase ( urlExt ) & & isBrowserRendered ( urlExt ) ) {
return openInputStream ( post , sb . loader , auth , url ) ;
}
/ *
* When opening a file , the most efficient is to open
* ImageInputStream directly on file
* /
if ( url . isFile ( ) ) {
imageInStream = ImageIO . createImageInputStream ( url . getFSFile ( ) ) ;
} else {
inStream = openInputStream ( post , sb . loader , auth , url ) ;
imageInStream = ImageIO . createImageInputStream ( inStream ) ;
}
2015-11-18 10:15:06 +01:00
// read image
encodedImage = parseAndScale ( post , auth , urlString , ext , imageInStream ) ;
2015-12-01 01:06:01 +01:00
} catch ( Exception e ) {
2015-12-21 01:05:59 +01:00
/ * Exceptions are not propagated here : many error causes are possible , network errors ,
* incorrect or unsupported format , bad ImageIO plugin . . .
* Instead return an empty EncodedImage . Caller is responsible for handling this correctly ( 500 status code response ) * /
if ( " favicon.ico " . equalsIgnoreCase ( url . getFileName ( ) ) ) { // but on missing favicon just present a default (occures frequently by call from searchitem.html)
// currently yacysearchitem assigns "hosturl/favicon.ico" (to look for the filename should not much interfere with other situatios)
if ( defaulticonb = = null ) { // load the default icon once
try {
defaulticonb = FileUtils . read ( new File ( sb . getAppPath ( ) , defaulticon ) ) ;
} catch ( final IOException initicon ) {
defaulticonb = new byte [ 0 ] ;
}
}
encodedImage = new EncodedImage ( defaulticonb , ext , post . getBoolean ( " isStatic " ) ) ;
} else {
encodedImage = new EncodedImage ( new byte [ 0 ] , ext , post . getBoolean ( " isStatic " ) ) ;
}
2015-11-18 10:15:06 +01:00
} finally {
/ *
* imageInStream . close ( ) method doesn ' t close source input
* stream
* /
if ( inStream ! = null ) {
try {
inStream . close ( ) ;
} catch ( IOException ignored ) {
}
}
}
2015-10-14 10:15:00 +02:00
}
return encodedImage ;
}
2015-11-05 09:45:19 +01:00
2015-11-18 10:15:06 +01:00
/ * *
* Open input stream on image url using provided loader . All parameters must
* not be null .
*
* @param post
* post parameters .
* @param loader .
* Resources loader .
* @param auth
* true when user has credentials to load full images .
* @param url
* image url .
* @return an open input stream instance ( don ' t forget to close it ) .
* @throws IOException
2015-12-01 01:06:01 +01:00
* when a read / write error occured .
2015-11-18 10:15:06 +01:00
* /
private static InputStream openInputStream ( final serverObjects post , final LoaderDispatcher loader ,
final boolean auth , DigestURL url ) throws IOException {
InputStream inStream = null ;
if ( url ! = null ) {
try {
String agentName = post . get ( " agentName " , auth ? ClientIdentification . yacyIntranetCrawlerAgentName
: ClientIdentification . yacyInternetCrawlerAgentName ) ;
ClientIdentification . Agent agent = ClientIdentification . getAgent ( agentName ) ;
inStream = loader . openInputStream ( loader . request ( url , false , true ) , CacheStrategy . IFEXIST ,
BlacklistType . SEARCH , agent ) ;
} catch ( final IOException e ) {
2015-12-01 01:06:01 +01:00
/** No need to log full stack trace (in most cases resource is not available because of a network error) */
2015-12-09 01:21:00 +01:00
ConcurrentLog . fine ( " ViewImage " , " cannot load image. URL : " + url . toNormalform ( true ) ) ;
2015-11-18 10:15:06 +01:00
throw e ;
}
}
if ( inStream = = null ) {
throw new IOException ( " Input stream could no be open " ) ;
}
return inStream ;
}
2015-10-14 10:15:00 +02:00
/ * *
2015-10-21 02:49:51 +02:00
* @param formatName
* informal file format name . For example : " png " .
* @return true when image format is rendered by browser and not by
* ViewImage internals
* /
public static boolean isBrowserRendered ( String formatName ) {
/ *
* gif images are not loaded because of an animated gif bug within jvm
* which sends java into an endless loop with high CPU
* /
/ *
* svg images not supported by jdk , but by most browser , deliver just
* content ( without crop / scale )
* /
return ( " gif " . equalsIgnoreCase ( formatName ) | | " svg " . equalsIgnoreCase ( formatName ) ) ;
}
/ * *
2015-11-18 10:15:06 +01:00
* Process source image to try to produce an EncodedImage instance
* eventually scaled and clipped depending on post parameters . When
* processed , imageInStream is closed .
2015-10-21 02:49:51 +02:00
*
* @param post
* request post parameters . Must not be null .
* @param auth
* true when access rigths are OK .
* @param urlString
2015-11-18 10:15:06 +01:00
* image source URL as String . Must not be null .
2015-10-21 02:49:51 +02:00
* @param ext
2015-11-18 10:15:06 +01:00
* target image file format . May be null .
* @param imageInStream
* open stream on image content . Must not be null .
2015-11-05 09:45:19 +01:00
* @return an EncodedImage instance .
* @throws IOException
2015-12-01 01:06:01 +01:00
* when image could not be parsed or encoded to specified format .
2015-10-14 10:15:00 +02:00
* /
2015-10-21 02:49:51 +02:00
protected static EncodedImage parseAndScale ( serverObjects post , boolean auth , String urlString , String ext ,
2015-11-18 10:15:06 +01:00
ImageInputStream imageInStream ) throws IOException {
2015-12-01 01:06:01 +01:00
EncodedImage encodedImage ;
2015-10-21 02:49:51 +02:00
2015-11-26 09:30:43 +01:00
// BufferedImage image = ImageIO.read(imageInStream);
Iterator < ImageReader > readers = ImageIO . getImageReaders ( imageInStream ) ;
if ( ! readers . hasNext ( ) ) {
2015-11-18 10:15:06 +01:00
try {
2015-11-26 09:30:43 +01:00
/* When no reader can be found, we have to close the stream */
2015-11-18 10:15:06 +01:00
imageInStream . close ( ) ;
} catch ( IOException ignoredException ) {
}
2015-12-01 01:06:01 +01:00
String errorMessage = " Image format ( " + ext + " ) is not supported. " ;
ConcurrentLog . fine ( " ViewImage " , errorMessage + " Image URL : " + urlString ) ;
2015-11-05 09:45:19 +01:00
/ *
* Throw an exception , wich will end in a HTTP 500 response , better
* handled by browsers than an empty image
* /
2015-12-01 01:06:01 +01:00
throw new IOException ( errorMessage ) ;
2015-11-05 09:45:19 +01:00
}
2015-11-26 09:30:43 +01:00
ImageReader reader = readers . next ( ) ;
reader . setInput ( imageInStream , true , true ) ;
2015-10-14 10:15:00 +02:00
2015-11-18 10:15:06 +01:00
int maxwidth = post . getInt ( " maxwidth " , 0 ) ;
int maxheight = post . getInt ( " maxheight " , 0 ) ;
final boolean quadratic = post . containsKey ( " quadratic " ) ;
boolean isStatic = post . getBoolean ( " isStatic " ) ;
2015-11-26 09:30:43 +01:00
BufferedImage image = null ;
boolean returnRaw = true ;
2015-11-18 10:15:06 +01:00
if ( ! auth | | maxwidth ! = 0 | | maxheight ! = 0 ) {
2015-10-14 10:15:00 +02:00
2015-11-18 10:15:06 +01:00
// find original size
2015-11-26 09:30:43 +01:00
final int originWidth = reader . getWidth ( 0 ) ;
final int originHeigth = reader . getHeight ( 0 ) ;
2015-10-14 10:15:00 +02:00
2015-11-18 10:15:06 +01:00
// in case of not-authorized access shrink the image to
// prevent
// copyright problems, so that images are not larger than
// thumbnails
Dimension maxDimensions = calculateMaxDimensions ( auth , originWidth , originHeigth , maxwidth , maxheight ) ;
2015-10-14 10:15:00 +02:00
2015-11-18 10:15:06 +01:00
// if a quadratic flag is set, we cut the image out to be in
// quadratic shape
int w = originWidth ;
int h = originHeigth ;
if ( quadratic & & originWidth ! = originHeigth ) {
2015-11-26 09:30:43 +01:00
Rectangle square = getMaxSquare ( originHeigth , originWidth ) ;
h = square . height ;
w = square . width ;
2015-11-18 10:15:06 +01:00
}
2015-10-14 10:15:00 +02:00
2015-11-18 10:15:06 +01:00
Dimension finalDimensions = calculateDimensions ( w , h , maxDimensions ) ;
2015-10-14 10:15:00 +02:00
2015-11-26 09:30:43 +01:00
if ( originWidth ! = finalDimensions . width | | originHeigth ! = finalDimensions . height ) {
returnRaw = false ;
image = readImage ( reader ) ;
if ( quadratic & & originWidth ! = originHeigth ) {
image = makeSquare ( image ) ;
}
2015-11-18 10:15:06 +01:00
image = scale ( finalDimensions . width , finalDimensions . height , image ) ;
2015-10-14 10:15:00 +02:00
}
2015-11-18 10:15:06 +01:00
if ( finalDimensions . width = = 16 & & finalDimensions . height = = 16 ) {
// this might be a favicon, store image to cache for
// faster
// re-load later on
2015-11-26 09:30:43 +01:00
if ( image = = null ) {
returnRaw = false ;
image = readImage ( reader ) ;
}
2015-11-18 10:15:06 +01:00
iconcache . put ( urlString , image ) ;
2015-10-30 16:20:28 +01:00
}
2015-10-14 10:15:00 +02:00
}
2015-11-26 09:30:43 +01:00
/* Image do not need to be scaled or cropped */
if ( returnRaw ) {
if ( ! reader . getFormatName ( ) . equalsIgnoreCase ( ext ) | | imageInStream . getFlushedPosition ( ) ! = 0 ) {
/ *
* image parsing and reencoding is only needed when source image
* and target formats differ , or when first bytes have been discarded
* /
returnRaw = false ;
image = readImage ( reader ) ;
}
2015-11-18 10:15:06 +01:00
}
2015-11-26 09:30:43 +01:00
if ( returnRaw ) {
byte [ ] imageData = readRawImage ( imageInStream ) ;
encodedImage = new EncodedImage ( imageData , ext , isStatic ) ;
} else {
/ *
* An error can still occur when transcoding from buffered image to
2015-12-01 01:06:01 +01:00
* target ext : in that case EncodedImage . getImage ( ) is empty .
2015-11-26 09:30:43 +01:00
* /
encodedImage = new EncodedImage ( image , ext , isStatic ) ;
if ( encodedImage . getImage ( ) . length ( ) = = 0 ) {
2015-12-01 01:06:01 +01:00
String errorMessage = " Image could not be encoded to format : " + ext ;
ConcurrentLog . fine ( " ViewImage " , errorMessage + " . Image URL : " + urlString ) ;
throw new IOException ( errorMessage ) ;
2015-11-26 09:30:43 +01:00
}
}
2015-10-14 10:15:00 +02:00
return encodedImage ;
}
2015-11-26 09:30:43 +01:00
/ * *
* Read image using specified reader and close ImageInputStream source .
* Input must have bean set before using
* { @link ImageReader # setInput ( Object ) }
*
* @param reader
* image reader . Must not be null .
* @return buffered image
* @throws IOException
* when an error occured
* /
private static BufferedImage readImage ( ImageReader reader ) throws IOException {
BufferedImage image ;
try {
image = reader . read ( 0 ) ;
} finally {
reader . dispose ( ) ;
Object input = reader . getInput ( ) ;
if ( input instanceof ImageInputStream ) {
try {
( ( ImageInputStream ) input ) . close ( ) ;
} catch ( IOException ignoredException ) {
}
}
}
return image ;
}
/ * *
* Read image data without parsing .
*
* @param inStream
* image source . Must not be null . First bytes must not have been marked discarded ( { @link ImageInputStream # getFlushedPosition ( ) } must be zero )
* @return image data as bytes
* @throws IOException
* when a read / write error occured .
* /
private static byte [ ] readRawImage ( ImageInputStream inStream ) throws IOException {
byte [ ] buffer = new byte [ 4096 ] ;
int l = 0 ;
ByteArrayOutputStream outStream = new ByteArrayOutputStream ( ) ;
inStream . seek ( 0 ) ;
try {
while ( ( l = inStream . read ( buffer ) ) > = 0 ) {
outStream . write ( buffer , 0 , l ) ;
}
return outStream . toByteArray ( ) ;
} finally {
try {
inStream . close ( ) ;
} catch ( IOException ignored ) {
}
}
}
2015-10-14 10:15:00 +02:00
/ * *
* Calculate image dimensions from image original dimensions , max
* dimensions , and target dimensions .
*
* @return dimensions to render image
* /
2015-10-21 02:49:51 +02:00
protected static Dimension calculateDimensions ( final int originWidth , final int originHeight , final Dimension max ) {
int resultWidth ;
int resultHeight ;
2015-10-14 10:15:00 +02:00
if ( max . width < originWidth | | max . height < originHeight ) {
// scale image
final double hs = ( originWidth < = max . width ) ? 1 . 0 : ( ( double ) max . width ) / ( ( double ) originWidth ) ;
final double vs = ( originHeight < = max . height ) ? 1 . 0 : ( ( double ) max . height ) / ( ( double ) originHeight ) ;
final double scale = Math . min ( hs , vs ) ;
// if (!auth) scale = Math.min(scale, 0.6); // this is for copyright
// purpose
if ( scale < 1 . 0 ) {
resultWidth = Math . max ( 1 , ( int ) ( originWidth * scale ) ) ;
resultHeight = Math . max ( 1 , ( int ) ( originHeight * scale ) ) ;
} else {
resultWidth = Math . max ( 1 , originWidth ) ;
resultHeight = Math . max ( 1 , originHeight ) ;
}
} else {
// do not scale
resultWidth = originWidth ;
resultHeight = originHeight ;
}
return new Dimension ( resultWidth , resultHeight ) ;
}
/ * *
* Calculate image maximum dimentions from original and specified maximum
* dimensions
*
* @param auth
* true when acces rigths are OK .
* @return maximum dimensions to render image
* /
protected static Dimension calculateMaxDimensions ( final boolean auth , final int originWidth , final int originHeight ,
final int maxWidth , final int maxHeight ) {
int resultWidth ;
int resultHeight ;
// in case of not-authorized access shrink the image to prevent
// copyright problems, so that images are not larger than thumbnails
if ( auth ) {
resultWidth = ( maxWidth = = 0 ) ? originWidth : maxWidth ;
resultHeight = ( maxHeight = = 0 ) ? originHeight : maxHeight ;
} else if ( ( originWidth > 16 ) | | ( originHeight > 16 ) ) {
resultWidth = Math . min ( 96 , originWidth ) ;
resultHeight = Math . min ( 96 , originHeight ) ;
} else {
resultWidth = 16 ;
resultHeight = 16 ;
}
return new Dimension ( resultWidth , resultHeight ) ;
}
/ * *
* Scale image to specified dimensions
*
* @param width
* target width
* @param height
* target height
* @param image
* image to scale . Must not be null .
* @return a scaled image
* /
2015-11-20 14:35:36 +01:00
protected static BufferedImage scale ( final int width , final int height , final BufferedImage image ) {
2015-10-14 10:15:00 +02:00
// compute scaled image
2015-11-20 14:35:36 +01:00
Image scaled = image . getScaledInstance ( width , height , Image . SCALE_AREA_AVERAGING ) ;
2015-10-14 10:15:00 +02:00
final MediaTracker mediaTracker = new MediaTracker ( new Container ( ) ) ;
mediaTracker . addImage ( scaled , 0 ) ;
try {
mediaTracker . waitForID ( 0 ) ;
} catch ( final InterruptedException e ) {
}
// make a BufferedImage out of that
2015-11-20 14:35:36 +01:00
BufferedImage result = new BufferedImage ( width , height , BufferedImage . TYPE_INT_ARGB ) ;
2015-10-14 10:15:00 +02:00
try {
2015-11-20 14:35:36 +01:00
result . createGraphics ( ) . drawImage ( scaled , 0 , 0 , width , height , null ) ;
2015-10-14 10:15:00 +02:00
// check outcome
2015-11-20 14:35:36 +01:00
final Raster raster = result . getData ( ) ;
int [ ] pixel = new int [ raster . getSampleModel ( ) . getNumBands ( ) ] ;
2015-10-14 10:15:00 +02:00
pixel = raster . getPixel ( 0 , 0 , pixel ) ;
} catch ( final Exception e ) {
2015-11-20 14:35:36 +01:00
/ *
* Exception may be caused by source image color model : try now to
* convert to RGB before scaling
* /
try {
BufferedImage converted = EncodedImage . convertToRGB ( image ) ;
scaled = converted . getScaledInstance ( width , height , Image . SCALE_AREA_AVERAGING ) ;
mediaTracker . addImage ( scaled , 1 ) ;
try {
mediaTracker . waitForID ( 1 ) ;
} catch ( final InterruptedException e2 ) {
}
result = new BufferedImage ( width , height , BufferedImage . TYPE_INT_ARGB ) ;
result . createGraphics ( ) . drawImage ( scaled , 0 , 0 , width , height , null ) ;
// check outcome
final Raster raster = result . getData ( ) ;
int [ ] pixel = new int [ result . getSampleModel ( ) . getNumBands ( ) ] ;
pixel = raster . getPixel ( 0 , 0 , pixel ) ;
} catch ( Exception e2 ) {
result = image ;
}
ConcurrentLog . fine ( " ViewImage " , " Image could not be scaled " ) ;
2015-10-14 10:15:00 +02:00
}
2015-11-20 14:35:36 +01:00
return result ;
2015-10-14 10:15:00 +02:00
}
2015-11-05 09:45:19 +01:00
2015-11-26 09:30:43 +01:00
/ * *
*
* @param h
* image height
* @param w
* image width
* @return max square area fitting inside dimensions
* /
protected static Rectangle getMaxSquare ( final int h , final int w ) {
Rectangle square ;
if ( w > h ) {
final int offset = ( w - h ) / 2 ;
square = new Rectangle ( offset , 0 , h , h ) ;
} else {
final int offset = ( h - w ) / 2 ;
square = new Rectangle ( 0 , offset , w , w ) ;
}
return square ;
}
2015-10-14 10:15:00 +02:00
/ * *
* Crop image to make a square
*
* @param image
* image to crop
* @return
* /
2015-11-26 09:30:43 +01:00
protected static BufferedImage makeSquare ( BufferedImage image ) {
final int w = image . getWidth ( ) ;
final int h = image . getHeight ( ) ;
2015-10-14 10:15:00 +02:00
if ( w > h ) {
2015-10-30 05:18:16 +01:00
final BufferedImage dst = new BufferedImage ( h , h , BufferedImage . TYPE_INT_ARGB ) ;
2015-10-14 10:15:00 +02:00
Graphics2D g = dst . createGraphics ( ) ;
2015-10-21 02:49:51 +02:00
final int offset = ( w - h ) / 2 ;
2015-11-26 09:30:43 +01:00
try {
g . drawImage ( image , 0 , 0 , h - 1 , h - 1 , offset , 0 , h + offset , h - 1 , null ) ;
} finally {
g . dispose ( ) ;
}
2015-10-14 10:15:00 +02:00
image = dst ;
} else {
2015-10-30 05:18:16 +01:00
final BufferedImage dst = new BufferedImage ( w , w , BufferedImage . TYPE_INT_ARGB ) ;
2015-10-14 10:15:00 +02:00
Graphics2D g = dst . createGraphics ( ) ;
2015-10-21 02:49:51 +02:00
final int offset = ( h - w ) / 2 ;
2015-11-26 09:30:43 +01:00
try {
g . drawImage ( image , 0 , 0 , w - 1 , w - 1 , 0 , offset , w - 1 , w + offset , null ) ;
} finally {
g . dispose ( ) ;
}
2015-10-14 10:15:00 +02:00
image = dst ;
}
return image ;
}
2011-06-13 23:44:03 +02:00
2006-04-03 00:59:53 +02:00
}