1    /*
2    Copyright 2002 by Ralph Hartley
3    This software is licenced under the terms of the
4    Gnu Public Licence
5    */
6    
7    import java.lang.ref.*;
8    import java.awt.geom.*;
9    import java.awt.image.*;
10   import java.awt.*;
11   import java.util.*;
12   
13   public class ImageJob extends CacheRef implements java.io.Serializable{
14   
15     private static final long serialVersionUID = Version.getSUID();
16   
17     public static double SCALEFACT = 2;
18   
19     public int index;
20     public double scale;
21     public Segment seg;
22     public AffineTransform trans;
23     AffineTransform rtrans;
24   
25     transient HashSet users = new HashSet();;
26   
27     public transient boolean pending = false;
28   
29     public ImageJob(Segment seg,int index) {
30   //    file.fragments.add(this);
31       this.seg = seg;
32       this.index = index;
33       
34       scale = 1;
35       for (int i=0;i<index;i++) scale *= SCALEFACT;
36   
37       rtrans = (AffineTransform)seg.map.overlaytrans.clone();
38       rtrans.scale(1/scale,1/scale);
39     }
40     
41     public boolean equals(Object that) {
42       return((that instanceof ImageJob) &&
43              ((ImageJob)that).seg == seg &&
44              ((ImageJob)that).index == index);
45     }
46   
47     public int hashCode() {
48       return(seg.hashCode() + index);
49     }
50   
51     public boolean check() {
52       return(rtrans!=null && (trans!=null || ref==null));
53     }
54   
55     public String toString() {
56       return(seg.getName()+" index = "+index+" scale = "+scale);
57     }
58   
59     public void setImage(BufferedImage image) {
60       if (image!=null && getTrans()!=null) {
61         set(image);
62       }
63     }
64     
65   
66     public AffineTransform getTrans() {
67       if (trans != null) return(trans);
68   
69       if (rtrans==null) {
70         rtrans = (AffineTransform)seg.map.overlaytrans.clone();
71         rtrans.scale(1/scale,1/scale);
72       }
73   
74       Rectangle2D bounds = seg.getBounds(rtrans);
75       try {
76         trans = rtrans.createInverse();
77       } catch (Exception e) {
78         ErrorLog.exception(e,"Error reducing segment "+seg.name);
79         ref = null;
80         return(null);
81       }
82       trans.translate(bounds.getX(),bounds.getY());
83       return(trans);
84     }
85   
86   
87   /*
88     private void readObject(java.io.ObjectInputStream stream)
89         throws java.io.IOException,java.lang.ClassNotFoundException {
90       stream.defaultReadObject();
91       size = new Point2D.Double(stream.readDouble(),stream.readDouble());
92     }
93   
94     private void writeObject(java.io.ObjectOutputStream stream)
95         throws java.io.IOException,java.lang.ClassNotFoundException {
96       stream.defaultWriteObject();
97       stream.writeDouble(size.getX());
98       stream.writeDouble(size.getY());
99     }
100  */
101  
102    public void addUser(Component user) {
103      if (isReady()) user.repaint();
104      else
105        if (users==null) users = new HashSet();
106        synchronized(users) {
107          users.add(new TransparentWeakReference(user));
108        }
109    }
110  
111    public boolean load() {
112  
113      seg.solve();
114  
115      if (index!=0 && Segment.dobig)
116        seg.cookers[0].load();
117  
118      if (!lock(true)) {
119  
120        for (int s=index-1;s>=0;s--) {
121          BufferedImage big = (BufferedImage)seg.cookers[s].get();
122          if (big!=null) {
123            int fact = 1<<(index-s);
124            int w = big.getWidth()/fact;
125            int h = big.getHeight()/fact;
126            BufferedImage res = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
127            Raster bigrast = big.getRaster();
128            WritableRaster small = res.getRaster();
129            int[] pixel = null;
130            for (int i=0;i<w;i++)
131              for (int j=0;j<h;j++) {
132                pixel = bigrast.getPixel(i*fact,j*fact,pixel);
133                small.setPixel(i,j,pixel);
134              }
135            big=null;
136            bigrast=null;
137            small=null;
138  
139            setImage(res);
140  
141  //          Rectangle2D bounds = seg.getBounds(rtrans);
142  //          try {
143  //            trans = rtrans.createInverse();
144  //          } catch (Exception e) {
145  //            ErrorLog.exception(e,"Error reducing segment "+seg.name);
146  //            ref = null;
147  //            return(false);
148  //          }
149  //          trans.translate(bounds.getX(),bounds.getY());
150  //
151  //          set(res);
152            lock(true);
153            res=null;
154  
155            break;
156          }
157        }
158      
159        if (!lock(true)) {
160  
161          Image rawimage=seg.isource.getImage();
162          
163          Rectangle2D bounds = seg.getBounds(rtrans);
164          
165          if (Double.isInfinite(bounds.getWidth()) || Double.isNaN(bounds.getWidth())) {
166            System.out.println("bad width "+bounds.getWidth());
167            ErrorLog.log("bad width "+bounds.getWidth());
168            ref=null;
169            return(false);
170          }
171  
172  
173          BufferedImage res = null;
174          try {
175  
176            res = seg.map.getImage(rawimage,rtrans,bounds,seg.boundary,
177          			 seg.name+" (%"+(int)(100/scale)+" size) ",seg.transparent);
178        
179  //          trans = rtrans.createInverse();
180  //          trans.translate(bounds.getX(),bounds.getY());
181        
182  //        } catch (OutOfMemoryError e) {
183  //          ErrorLog.exception(e,"Out of memory morphing segment "+seg.name);
184  //          ref = null;
185  //          return(false);
186          } catch (Exception e) {
187            ErrorLog.exception(e,"Error morphing segment "+seg.name);
188            ref = null;
189            return(false);
190          } finally { 
191            CartoFrame.message.setText("");
192            rawimage = null;
193          }
194          setImage(res);
195          lock(true);
196          res = null;
197        }
198      }
199  
200      if (Segment.thumbs) {
201        if (index<Segment.levels-1) {
202          seg.cookers[Segment.levels-1].load();
203          seg.cookers[Segment.levels-1].lock(false);
204        }
205        else
206          seg.thumbnail = (BufferedImage)get();
207      }
208      
209      if (users!=null)
210        synchronized(users) {
211          ImageThread.addUsers(users);
212          users.clear();
213        }
214      
215  //    System.out.println("load done");
216      return(true);
217    }
218  
219    static Color[] dbgcolors = {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW,Color.PINK};
220    static int dbgcnt = 0;
221  
222    public boolean isReady() {
223      return(ref!=null);
224    }
225  }
226