MyTileCache.java
5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
* ESO Archive
*
* $Id: MyTileCache.java,v 1.2 2009/02/20 23:10:11 abrighto Exp $
*
* who when what
* -------------- ---------- ----------------------------------------
* Allan Brighton 1999/11/16 created
*/
package jsky.image;
import java.awt.image.Raster;
import java.util.LinkedList;
import java.awt.Point;
/**
* Implements the JAI TileCache interface.
*
* @author Allan Brighton
* @version $Revision: 1.2 $
*/
public class MyTileCache {
/**
* Max amout of memory to cache
*/
private int memoryCapacity;
/**
* Max number of tiles to cache
*/
private int tileCapacity;
/**
* Two dimensional array of tiles, some of which may be null
*/
private Raster[][] tiles;
/**
* List of tile indexes (tileX,tileY), in order of age
*/
private LinkedList<Point> tileIndexes = new LinkedList<Point>();
/**
* Number of tiles cached so far
*/
private int numTiles = 0;
/**
* Create a new tile cache for an image with the given size.
*
* @param imageWidth The width of the image in pixels
* @param imageHeight The height of the image in pixels
* @param tileWidth The width of a tile in pixels
* @param tileHeight The height of a tile in pixels
* @param bytesPerPixel The number of bytes required for one pixel
* @param memoryCapacity The maximum number of bytes to allocate before discarding old tiles
*/
public MyTileCache(int imageWidth, int imageHeight, int tileWidth, int tileHeight,
int bytesPerPixel, int memoryCapacity) {
this.memoryCapacity = memoryCapacity;
// number of tiles we can keep in cache
tileCapacity = memoryCapacity / (tileWidth * tileHeight * bytesPerPixel);
if (tileCapacity == 0) {
tileCapacity = 1;
}
// Create slots for all tiles (a slot may be empty)
int numXTiles = imageWidth / tileWidth + 1;
int numYTiles = imageHeight / tileHeight + 1;
tiles = new Raster[numXTiles][numYTiles];
//System.out.println("XXX MyTileCache: tileCapacity = " + tileCapacity + ", memoryCapacity = " + memoryCapacity
// + ", numXTiles = " + numXTiles + ", numYTiles = " + numYTiles);
}
/**
* Create a new tile cache for an image with the given size.
* The maximum memory usage is set to 64MB.
*
* @param imageWidth The width of the image in pixels
* @param imageHeight The height of the image in pixels
* @param tileWidth The width of a tile in pixels
* @param tileHeight The height of a tile in pixels
* @param bytesPerPixel The number of bytes required for one pixel
*/
public MyTileCache(int imageWidth, int imageHeight, int tileWidth, int tileHeight,
int bytesPerPixel) {
this(imageWidth, imageHeight, tileWidth, tileHeight, bytesPerPixel, 1024 * 1024 * 20);
}
/**
* Adds a tile to the cache.
*
* @param tileX The X index of the tile in the tile grid.
* @param tileY The Y index of the tile in the tile grid.
* @param tile A <code>Raster</code> containging the tile data.
*/
public void add(int tileX, int tileY, Raster tile) {
if (numTiles >= tileCapacity) {
// remove oldest tile
Point p = tileIndexes.removeFirst();
tiles[(int) p.getX()][(int) p.getY()] = null;
numTiles--;
//System.out.println("XXX MyTileCache: remove tile to make room for add (" + ((int)p.getX()) + ", " + ((int)p.getY()) + ")");
}
tiles[tileX][tileY] = tile;
tileIndexes.add(new Point(tileX, tileY));
numTiles++;
//System.out.println("XXX MyTileCache: add tile (" + tileX + ", " + tileY + "), numTiles = " + numTiles + ", tileCapacity = " + tileCapacity);
}
/**
* Advises the cache that a tile is no longer needed. It is legal
* to implement this method as a no-op.
*
* @param tileX The X index of the tile in the tile grid.
* @param tileY The Y index of the tile in the tile grid.
*/
public void remove(int tileX, int tileY) {
tiles[tileX][tileY] = null;
if (tileIndexes.remove(new Point(tileX, tileY))) {
numTiles--;
}
}
/**
* Clear the tile cache, so that the memory may be reclaimed
*/
public void clear() {
LinkedList<Point> copy = new LinkedList<Point>(tileIndexes);
for (Point p : copy) {
remove((int) p.getX(), (int) p.getY());
}
System.gc();
}
/**
* Retrieves a tile. Returns <code>null</code> if the tile is not
* present in the cache.
*
* @param tileX The X index of the tile in the tile grid.
* @param tileY The Y index of the tile in the tile grid.
*/
public Raster getTile(int tileX, int tileY) {
return tiles[tileX][tileY];
}
/**
* Returns the tile capacity in tiles.
*/
public int getTileCapacity() {
return tileCapacity;
}
/**
* Returns the memory capacity in bytes.
*/
public long getMemoryCapacity() {
return memoryCapacity;
}
}