aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Services/MapImageService/MapImageService.cs138
1 files changed, 105 insertions, 33 deletions
diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs
index 4887d1c..2db1d14 100644
--- a/OpenSim/Services/MapImageService/MapImageService.cs
+++ b/OpenSim/Services/MapImageService/MapImageService.cs
@@ -36,6 +36,7 @@ using System.Drawing.Imaging;
36using System.IO; 36using System.IO;
37using System.Net; 37using System.Net;
38using System.Reflection; 38using System.Reflection;
39using System.Threading;
39 40
40using Nini.Config; 41using Nini.Config;
41using log4net; 42using log4net;
@@ -65,6 +66,8 @@ namespace OpenSim.Services.MapImageService
65 private static bool m_Initialized = false; 66 private static bool m_Initialized = false;
66 private static string m_WaterTileFile = string.Empty; 67 private static string m_WaterTileFile = string.Empty;
67 private static Color m_Watercolor = Color.FromArgb(29, 71, 95); 68 private static Color m_Watercolor = Color.FromArgb(29, 71, 95);
69 private static Bitmap m_WaterBitmap = null;
70 private static byte[] m_WaterBytes = null;
68 71
69 public MapImageService(IConfigSource config) 72 public MapImageService(IConfigSource config)
70 { 73 {
@@ -87,6 +90,18 @@ namespace OpenSim.Services.MapImageService
87 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); 90 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
88 FillImage(waterTile, m_Watercolor); 91 FillImage(waterTile, m_Watercolor);
89 waterTile.Save(m_WaterTileFile, ImageFormat.Jpeg); 92 waterTile.Save(m_WaterTileFile, ImageFormat.Jpeg);
93 m_WaterBitmap = waterTile;
94 }
95
96 if (File.Exists(m_WaterTileFile))
97 {
98 m_WaterBitmap = new Bitmap(m_WaterTileFile);
99 using (MemoryStream ms = new MemoryStream())
100 {
101 m_WaterBitmap.Save(ms,ImageFormat.Jpeg);
102 ms.Seek(0, SeekOrigin.Begin);
103 m_WaterBytes = ms.ToArray();
104 }
90 } 105 }
91 } 106 }
92 } 107 }
@@ -139,30 +154,82 @@ namespace OpenSim.Services.MapImageService
139 return UpdateMultiResolutionFiles(x, y, scopeID, out reason); 154 return UpdateMultiResolutionFiles(x, y, scopeID, out reason);
140 } 155 }
141 156
157 // When large varregions start up, they can send piles of new map tiles. This causes
158 // this multi-resolution routine to be called a zillion times an causes much CPU
159 // time to be spent creating multi-resolution tiles that will be replaced when
160 // the next maptile arrives.
161 private class mapToMultiRez
162 {
163 public int xx;
164 public int yy;
165 public UUID scopeID;
166 public mapToMultiRez(int pX, int pY, UUID pscopeID)
167 {
168 xx = pX;
169 yy = pY;
170 scopeID = pscopeID;
171 }
172 };
173 private Queue<mapToMultiRez> multiRezToBuild = new Queue<mapToMultiRez>();
174
142 private bool UpdateMultiResolutionFiles(int x, int y, UUID scopeID, out string reason) 175 private bool UpdateMultiResolutionFiles(int x, int y, UUID scopeID, out string reason)
143 { 176 {
144 reason = String.Empty; 177 reason = String.Empty;
145 lock (m_Sync) 178
179 lock (multiRezToBuild)
146 { 180 {
147 // Stitch seven more aggregate tiles together 181 // m_log.DebugFormat("{0} UpdateMultiResolutionFilesAsync: scheduling update for <{1},{2}>", LogHeader, x, y);
148 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) 182 multiRezToBuild.Enqueue(new mapToMultiRez(x, y, scopeID));
149 { 183 if (multiRezToBuild.Count == 1)
150 // Calculate the width (in full resolution tiles) and bottom-left 184 Util.FireAndForget(
151 // corner of the current zoom level 185 DoUpdateMultiResolutionFilesAsync);
152 int width = (int)Math.Pow(2, (double)(zoomLevel - 1)); 186 }
153 int x1 = x - (x % width); 187
154 int y1 = y - (y % width); 188 return true;
189 }
155 190
156 if (!CreateTile(zoomLevel, x1, y1, scopeID)) 191 private void DoUpdateMultiResolutionFilesAsync(object o)
192 {
193 // let acumulate large region tiles
194 Thread.Sleep(60 * 1000); // large regions take time to upload tiles
195
196 while (multiRezToBuild.Count > 0)
197 {
198 mapToMultiRez toMultiRez = null;
199 lock (multiRezToBuild)
200 {
201 if (multiRezToBuild.Count > 0)
202 toMultiRez = multiRezToBuild.Dequeue();
203 }
204 if (toMultiRez != null)
205 {
206 int x = toMultiRez.xx;
207 int y = toMultiRez.yy;
208 UUID scopeID = toMultiRez.scopeID;
209 // m_log.DebugFormat("{0} DoUpdateMultiResolutionFilesAsync: doing build for <{1},{2}>", LogHeader, x, y);
210
211 int width = 1;
212 // Stitch seven more aggregate tiles together
213 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
157 { 214 {
158 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel); 215 // Calculate the width (in full resolution tiles) and bottom-left
159 reason = string.Format("Map tile at zoom level {0} failed", zoomLevel); 216 // corner of the current zoom level
160 return false; 217 width *= 2;
218 int x1 = x - (x % width);
219 int y1 = y - (y % width);
220
221 lock (m_Sync) // must lock the reading and writing of the maptile files
222 {
223 if (!CreateTile(zoomLevel, x1, y1, scopeID))
224 {
225 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel);
226 return;
227 }
228 }
161 } 229 }
162 } 230 }
163 } 231 }
164 232 return;
165 return true;
166 } 233 }
167 234
168 public byte[] GetMapTile(string fileName, UUID scopeID, out string format) 235 public byte[] GetMapTile(string fileName, UUID scopeID, out string format)
@@ -178,9 +245,9 @@ namespace OpenSim.Services.MapImageService
178 //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); 245 //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format);
179 return File.ReadAllBytes(fullName); 246 return File.ReadAllBytes(fullName);
180 } 247 }
181 else if (File.Exists(m_WaterTileFile)) 248 else if (m_WaterBytes != null)
182 { 249 {
183 return File.ReadAllBytes(m_WaterTileFile); 250 return (byte[])m_WaterBytes.Clone();
184 } 251 }
185 else 252 else
186 { 253 {
@@ -226,7 +293,7 @@ namespace OpenSim.Services.MapImageService
226 { 293 {
227 // Create a new output tile with a transparent background 294 // Create a new output tile with a transparent background
228 Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb); 295 Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb);
229 bm.MakeTransparent(); 296 //bm.MakeTransparent(); // 24bpp does not have transparency, this whould make it 32bpp
230 return bm; 297 return bm;
231 } 298 }
232 } 299 }
@@ -260,48 +327,53 @@ namespace OpenSim.Services.MapImageService
260 327
261 // Open the output tile (current zoom level) 328 // Open the output tile (current zoom level)
262 string outputFile = GetFileName(zoomLevel, xOut, yOut, scopeID); 329 string outputFile = GetFileName(zoomLevel, xOut, yOut, scopeID);
263 Bitmap output = GetOutputTileImage(outputFile); 330
264 if (output == null) 331 int ntiles = 0;
265 return false; 332 Bitmap output = (Bitmap)m_WaterBitmap.Clone();
266 FillImage(output, m_Watercolor);
267 333
268 if (inputBL != null) 334 if (inputBL != null)
269 { 335 {
270 ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0); 336 ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0);
271 inputBL.Dispose(); 337 inputBL.Dispose();
338 ntiles++;
272 } 339 }
273 if (inputBR != null) 340 if (inputBR != null)
274 { 341 {
275 ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0); 342 ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0);
276 inputBR.Dispose(); 343 inputBR.Dispose();
344 ntiles++;
277 } 345 }
278 if (inputTL != null) 346 if (inputTL != null)
279 { 347 {
280 ImageCopyResampled(output, inputTL, 0, 0, 0, 0); 348 ImageCopyResampled(output, inputTL, 0, 0, 0, 0);
281 inputTL.Dispose(); 349 inputTL.Dispose();
350 ntiles++;
282 } 351 }
283 if (inputTR != null) 352 if (inputTR != null)
284 { 353 {
285 ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0); 354 ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0);
286 inputTR.Dispose(); 355 inputTR.Dispose();
356 ntiles++;
287 } 357 }
288 358
289 // Write the modified output 359 // Write the modified output
290 try 360 if (ntiles == 0)
361 File.Delete(outputFile);
362
363 else
291 { 364 {
292 using (Bitmap final = new Bitmap(output)) 365
366 try
293 { 367 {
294 output.Dispose(); 368 output.Save(outputFile, ImageFormat.Jpeg);
295 final.Save(outputFile, ImageFormat.Jpeg);
296 } 369 }
297 } 370 catch (Exception e)
298 catch (Exception e) 371 {
299 { 372 m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e);
300 m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e); 373 }
301 } 374 } // Save also as png?
302
303 // Save also as png?
304 375
376 output.Dispose();
305 return true; 377 return true;
306 } 378 }
307 379