001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.sequence; 020 021import java.util.ArrayList; 022import java.util.Map.Entry; 023import java.util.TreeMap; 024 025import icy.image.IcyBufferedImage; 026 027/** 028 * @author Fabrice de Chaumont 029 */ 030public class VolumetricImage 031{ 032 protected final Sequence sequence; 033 protected final TreeMap<Integer, IcyBufferedImage> images; 034 035 public VolumetricImage(Sequence seq) 036 { 037 sequence = seq; 038 images = new TreeMap<Integer, IcyBufferedImage>(); 039 } 040 041 public VolumetricImage() 042 { 043 this(null); 044 } 045 046 /** 047 * Return number of loaded image 048 */ 049 public int getNumImage() 050 { 051 int result = 0; 052 053 synchronized (images) 054 { 055 for (Entry<Integer, IcyBufferedImage> entry : images.entrySet()) 056 if (entry.getValue() != null) 057 result++; 058 } 059 060 return result; 061 } 062 063 /** 064 * Return the size of list 065 */ 066 public int getSize() 067 { 068 synchronized (images) 069 { 070 if (images.isEmpty()) 071 return 0; 072 073 return images.lastKey().intValue() + 1; 074 } 075 } 076 077 /** 078 * Return true if the volumetricImage doesn't contains any image 079 */ 080 public boolean isEmpty() 081 { 082 return (getSize() == 0); 083 } 084 085 /** 086 * Return the first image 087 */ 088 public IcyBufferedImage getFirstImage() 089 { 090 final Entry<Integer, IcyBufferedImage> entry; 091 092 synchronized (images) 093 { 094 entry = images.firstEntry(); 095 } 096 097 if (entry != null) 098 return entry.getValue(); 099 100 return null; 101 } 102 103 public IcyBufferedImage getFirstNonNullImage() 104 { 105 synchronized (images) 106 { 107 for (IcyBufferedImage img : images.values()) 108 { 109 if (img != null) 110 return img; 111 } 112 } 113 114 return null; 115 } 116 117 /** 118 * Return the last image 119 */ 120 public IcyBufferedImage getLastImage() 121 { 122 final Entry<Integer, IcyBufferedImage> entry; 123 124 synchronized (images) 125 { 126 entry = images.lastEntry(); 127 } 128 129 if (entry != null) 130 return entry.getValue(); 131 132 return null; 133 } 134 135 /** 136 * Return image at position z 137 */ 138 public IcyBufferedImage getImage(int z) 139 { 140 synchronized (images) 141 { 142 return images.get(Integer.valueOf(z)); 143 } 144 } 145 146 /** 147 * Remove all image 148 */ 149 public void clear() 150 { 151 if (sequence != null) 152 sequence.beginUpdate(); 153 154 try 155 { 156 synchronized (images) 157 { 158 while (!images.isEmpty()) 159 { 160 final IcyBufferedImage image = images.pollFirstEntry().getValue(); 161 // raise event on sequence 162 if ((image != null) && (sequence != null)) 163 sequence.onImageRemoved(image); 164 } 165 } 166 } 167 finally 168 { 169 if (sequence != null) 170 sequence.endUpdate(); 171 } 172 } 173 174 /** 175 * Remove image at position z 176 */ 177 public boolean removeImage(int z) 178 { 179 final IcyBufferedImage image; 180 181 synchronized (images) 182 { 183 image = images.remove(Integer.valueOf(z)); 184 } 185 186 // raise event on sequence 187 if ((image != null) && (sequence != null)) 188 sequence.onImageRemoved(image); 189 190 return image != null; 191 } 192 193 /** 194 * Set an image at the specified position 195 * 196 * @param image 197 */ 198 public void setImage(int z, IcyBufferedImage image) 199 { 200 final IcyBufferedImage oldImg = getImage(z); 201 202 if (sequence != null) 203 sequence.beginUpdate(); 204 try 205 { 206 // set the new image 207 synchronized (images) 208 { 209 images.put(Integer.valueOf(z), image); 210 } 211 212 // raise event on sequence 213 if (sequence != null) 214 { 215 // we are replacing a previous image ? 216 if (oldImg != null) 217 sequence.onImageReplaced(oldImg, image); 218 else 219 sequence.onImageAdded(image); 220 } 221 } 222 finally 223 { 224 if (sequence != null) 225 sequence.endUpdate(); 226 } 227 } 228 229 /** 230 * Return all images of volume image as TreeMap (contains z position) 231 */ 232 public TreeMap<Integer, IcyBufferedImage> getImages() 233 { 234 synchronized (images) 235 { 236 return new TreeMap<Integer, IcyBufferedImage>(images); 237 } 238 } 239 240 /** 241 * Return all images of volume image 242 */ 243 public ArrayList<IcyBufferedImage> getAllImage() 244 { 245 synchronized (images) 246 { 247 return new ArrayList<IcyBufferedImage>(images.values()); 248 } 249 } 250 251 /** 252 * Remove empty element of image list 253 */ 254 public void pack() 255 { 256 if (sequence != null) 257 sequence.beginUpdate(); 258 try 259 { 260 synchronized (images) 261 { 262 for (Entry<Integer, IcyBufferedImage> entry : images.entrySet()) 263 { 264 final IcyBufferedImage image = entry.getValue(); 265 266 if (image == null) 267 removeImage(entry.getKey().intValue()); 268 } 269 } 270 } 271 finally 272 { 273 if (sequence != null) 274 sequence.endUpdate(); 275 } 276 } 277 278}