/*
* Copyright 2011 Uwe Krueger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mandelsoft.mand.tool.thumb;
import com.mandelsoft.mand.QualifiedMandelName;
import com.mandelsoft.mand.cm.ColormapSource;
import com.mandelsoft.mand.cm.ColormapSourceFactory;
import com.mandelsoft.mand.image.MandelImage;
import com.mandelsoft.mand.image.MandelImage.Factory;
import com.mandelsoft.mand.scan.MandelHandle;
import com.mandelsoft.mand.scan.MandelScanner;
import com.mandelsoft.mand.tool.AbstractMandelListModel;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.SwingWorker;
/**
*
* @author Uwe Krueger
*/
public abstract class MandelImageRequestQueue<E> {
private List<MandelImageSource> requests;
private Dimension maxSize;
private MandelImage.Factory factory;
private ColormapSourceFactory colmapfac;
private Worker worker;
public MandelImageRequestQueue()
{
this.requests=new ArrayList<MandelImageSource>();
}
public MandelImageRequestQueue(Factory factory,
ColormapSourceFactory colmapfac)
{
this.factory=factory;
this.colmapfac=colmapfac;
}
public abstract MandelScanner getMandelScanner();
synchronized
public void setMaxSize(Dimension maxSize)
{
this.maxSize=maxSize;
}
synchronized
public Dimension getMaxSize()
{
return maxSize;
}
public ColormapSourceFactory getColormapSourceFactory()
{
return colmapfac;
}
public void setColormapSourceFactory(ColormapSourceFactory colmapfac)
{
this.colmapfac=colmapfac;
}
synchronized
public void setFactory(MandelImage.Factory factory)
{
this.factory=factory;
}
synchronized
public MandelImage.Factory getFactory()
{
if (factory==null) factory=new MandelImage.Factory();
return factory;
}
synchronized
public void clear()
{
requests.clear();
}
synchronized
public ImageSource<QualifiedMandelName> requestImage(QualifiedMandelName n)
{
MandelImageSource src=new MandelImageSource(n);
requests.add(0,src);
if (worker==null) {
worker=new Worker();
worker.execute();
}
return src;
}
synchronized
public void reschedule(ImageSource<QualifiedMandelName> src)
{
if (requests.remove(src)) {
requests.add(0, (MandelImageSource)src);
}
}
synchronized
public void removeRequest(ImageSource<QualifiedMandelName> req)
{
requests.remove(req);
}
synchronized
private MandelImageSource getNextRequest()
{
if (requests.size()==0) {
worker=null;
return null;
}
MandelImageSource src=requests.get(0);
requests.remove(0);
return src;
}
///////////////////////////////////////////////////////////////////////
static private BufferedImage root;
synchronized
static private BufferedImage getDefaultImage()
{
if (root==null) {
try {
root=ImageIO.read(AbstractMandelListModel.class.
getResourceAsStream("resc/0.png"));
System.out.println("get default image: "+root);
}
catch (IOException ex) {
System.out.println("cannot find root image from classpath");
}
}
return root;
}
synchronized
private BufferedImage getImage(QualifiedMandelName n)
{
BufferedImage image=null;
ImageSource src=null;
if (n==null) {
return null;
}
MandelHandle mh=getMandelScanner().getMandelData(n);
if (mh!=null) {
try {
ColormapSource cms=null;
if (colmapfac!=null && !mh.getHeader().hasColormap()) {
cms=colmapfac.getColormapSource(n);
}
MandelImage mi=getFactory().getImage(mh.getData(),cms);
if (mi!=null) {
image=mi.getImage();
}
}
catch (IOException ex) {
System.out.println("no image available for "+n+": "+ex);
}
}
else {
System.out.println("no image available for "+n);
}
if (image!=null) {
return resize(image);
}
return null;
}
private BufferedImage resize(BufferedImage src)
{
if (src!=null && maxSize!=null) {
int w=0;
int h=0;
if (src.getHeight()>src.getWidth()) {
h=(int)maxSize.getHeight();
w=(int)(((double)src.getWidth())
/((double)src.getHeight())*h);
}
else {
w=(int)maxSize.getWidth();
h=(int)(((double)src.getHeight())
/((double)src.getWidth())*w);
}
BufferedImage image=new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g=image.createGraphics();
g.drawImage(src, 0, 0, w, h, null);
return image;
}
return src;
}
///////////////////////////////////////////////////////////////////////
private class MandelImageSource extends AbstractImageSource<QualifiedMandelName> {
private QualifiedMandelName spec;
public MandelImageSource(QualifiedMandelName spec)
{
this.spec=spec;
setImage(resize(getDefaultImage()));
}
public QualifiedMandelName getImageSpec()
{
return spec;
}
@Override
public void cancel()
{
removeRequest(this);
}
MandelImageRequestQueue getQueue()
{
return MandelImageRequestQueue.this;
}
}
//////////////////////////////////////////////////////////////////////////
private class Result {
MandelImageSource src;
BufferedImage image;
public Result(MandelImageSource src, BufferedImage image)
{
this.src=src;
this.image=image;
}
}
private class Worker extends SwingWorker<Void, Result> {
@Override
protected Void doInBackground() throws Exception
{
MandelImageSource src;
while ((src=getNextRequest())!=null) {
Result r=new Result(src,getImage(src.getImageSpec()));
this.publish(r);
Thread.sleep(10);
//Thread.yield();
}
return null;
}
@Override
protected void done()
{
}
@Override
protected void process(List<Result> chunks)
{
if (chunks!=null) {
for (Result r:chunks) {
if (r.image!=null) r.src.setImage(r.image);
}
}
}
}
}