aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Warp3DMap
diff options
context:
space:
mode:
authorMelanie2012-06-06 13:07:05 +0100
committerMelanie2012-06-06 13:07:05 +0100
commite733fb32cf76672cfddc25b3c9c02c50c025e2db (patch)
tree1535c9e7d70cdb5f2e0779db8fc85fb98ede7ca5 /OpenSim/Region/CoreModules/World/Warp3DMap
parentMerge branch 'master' into careminster (diff)
parentminor: Change log messages on Warp3DImageModule to show they are from this mo... (diff)
downloadopensim-SC_OLD-e733fb32cf76672cfddc25b3c9c02c50c025e2db.zip
opensim-SC_OLD-e733fb32cf76672cfddc25b3c9c02c50c025e2db.tar.gz
opensim-SC_OLD-e733fb32cf76672cfddc25b3c9c02c50c025e2db.tar.bz2
opensim-SC_OLD-e733fb32cf76672cfddc25b3c9c02c50c025e2db.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs OpenSim/Region/Framework/Scenes/Scene.cs OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
Diffstat (limited to 'OpenSim/Region/CoreModules/World/Warp3DMap')
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs380
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs (renamed from OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs)88
2 files changed, 251 insertions, 217 deletions
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 7bf675d..91252f7 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -84,218 +84,234 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
84 Debug.Assert(heightRanges.Length == 4); 84 Debug.Assert(heightRanges.Length == 4);
85 85
86 Bitmap[] detailTexture = new Bitmap[4]; 86 Bitmap[] detailTexture = new Bitmap[4];
87 Bitmap output = null;
88 BitmapData outputData = null;
87 89
88 if (textureTerrain) 90 try
89 { 91 {
90 // Swap empty terrain textureIDs with default IDs 92 if (textureTerrain)
91 for (int i = 0; i < textureIDs.Length; i++)
92 { 93 {
93 if (textureIDs[i] == UUID.Zero) 94 // Swap empty terrain textureIDs with default IDs
94 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; 95 for (int i = 0; i < textureIDs.Length; i++)
95 }
96
97 #region Texture Fetching
98
99 if (assetService != null)
100 {
101 for (int i = 0; i < 4; i++)
102 { 96 {
103 AssetBase asset; 97 if (textureIDs[i] == UUID.Zero)
104 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); 98 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
105 99 }
106 // Try to fetch a cached copy of the decoded/resized version of this texture 100
107 asset = assetService.GetCached(cacheID.ToString()); 101 #region Texture Fetching
108 if (asset != null) 102
109 { 103 if (assetService != null)
110 try 104 {
111 { 105 for (int i = 0; i < 4; i++)
112 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
113 detailTexture[i] = (Bitmap)Image.FromStream(stream);
114 }
115 catch (Exception ex)
116 {
117 m_log.Warn("Failed to decode cached terrain texture " + cacheID +
118 " (textureID: " + textureIDs[i] + "): " + ex.Message);
119 }
120 }
121
122 if (detailTexture[i] == null)
123 { 106 {
124 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG 107 AssetBase asset;
125 asset = assetService.Get(textureIDs[i].ToString()); 108 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
109
110 // Try to fetch a cached copy of the decoded/resized version of this texture
111 asset = assetService.GetCached(cacheID.ToString());
126 if (asset != null) 112 if (asset != null)
127 { 113 {
128 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 114 try
115 {
116 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
117 detailTexture[i] = (Bitmap)Image.FromStream(stream);
118 }
129 catch (Exception ex) 119 catch (Exception ex)
130 { 120 {
131 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); 121 m_log.Warn("Failed to decode cached terrain texture " + cacheID +
122 " (textureID: " + textureIDs[i] + "): " + ex.Message);
132 } 123 }
133 } 124 }
134 125
135 if (detailTexture[i] != null) 126 if (detailTexture[i] == null)
136 { 127 {
137 Bitmap bitmap = detailTexture[i]; 128 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
138 129 asset = assetService.Get(textureIDs[i].ToString());
139 // Make sure this texture is the correct size, otherwise resize 130 if (asset != null)
140 if (bitmap.Width != 256 || bitmap.Height != 256)
141 bitmap = ImageUtils.ResizeImage(bitmap, 256, 256);
142
143 // Save the decoded and resized texture to the cache
144 byte[] data;
145 using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
146 { 131 {
147 bitmap.Save(stream, ImageFormat.Png); 132 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
148 data = stream.ToArray(); 133 catch (Exception ex)
134 {
135 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
136 }
149 } 137 }
150 138
151 // Cache a PNG copy of this terrain texture 139 if (detailTexture[i] != null)
152 AssetBase newAsset = new AssetBase
153 { 140 {
154 Data = data, 141 Bitmap bitmap = detailTexture[i];
155 Description = "PNG", 142
156 Flags = AssetFlags.Collectable, 143 // Make sure this texture is the correct size, otherwise resize
157 FullID = cacheID, 144 if (bitmap.Width != 256 || bitmap.Height != 256)
158 ID = cacheID.ToString(), 145 {
159 Local = true, 146 using (Bitmap origBitmap = bitmap)
160 Name = String.Empty, 147 {
161 Temporary = true, 148 bitmap = ImageUtils.ResizeImage(origBitmap, 256, 256);
162 Type = (sbyte)AssetType.Unknown 149 }
163 }; 150 }
164 newAsset.Metadata.ContentType = "image/png"; 151
165 assetService.Store(newAsset); 152 // Save the decoded and resized texture to the cache
153 byte[] data;
154 using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
155 {
156 bitmap.Save(stream, ImageFormat.Png);
157 data = stream.ToArray();
158 }
159
160 // Cache a PNG copy of this terrain texture
161 AssetBase newAsset = new AssetBase
162 {
163 Data = data,
164 Description = "PNG",
165 Flags = AssetFlags.Collectable,
166 FullID = cacheID,
167 ID = cacheID.ToString(),
168 Local = true,
169 Name = String.Empty,
170 Temporary = true,
171 Type = (sbyte)AssetType.Unknown
172 };
173 newAsset.Metadata.ContentType = "image/png";
174 assetService.Store(newAsset);
175 }
166 } 176 }
167 } 177 }
168 } 178 }
179
180 #endregion Texture Fetching
169 } 181 }
170 182
171 #endregion Texture Fetching 183 // Fill in any missing textures with a solid color
172 } 184 for (int i = 0; i < 4; i++)
173
174 // Fill in any missing textures with a solid color
175 for (int i = 0; i < 4; i++)
176 {
177 if (detailTexture[i] == null)
178 { 185 {
179 // Create a solid color texture for this layer 186 if (detailTexture[i] == null)
180 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
181 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
182 { 187 {
183 using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) 188 // Create a solid color texture for this layer
184 gfx.FillRectangle(brush, 0, 0, 256, 256); 189 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
190 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
191 {
192 using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
193 gfx.FillRectangle(brush, 0, 0, 256, 256);
194 }
185 } 195 }
186 } 196 }
187 } 197
188 198 #region Layer Map
189 #region Layer Map 199
190 200 float[] layermap = new float[256 * 256];
191 float[] layermap = new float[256 * 256]; 201
192
193 for (int y = 0; y < 256; y++)
194 {
195 for (int x = 0; x < 256; x++)
196 {
197 float height = heightmap[y * 256 + x];
198
199 float pctX = (float)x / 255f;
200 float pctY = (float)y / 255f;
201
202 // Use bilinear interpolation between the four corners of start height and
203 // height range to select the current values at this position
204 float startHeight = ImageUtils.Bilinear(
205 startHeights[0],
206 startHeights[2],
207 startHeights[1],
208 startHeights[3],
209 pctX, pctY);
210 startHeight = Utils.Clamp(startHeight, 0f, 255f);
211
212 float heightRange = ImageUtils.Bilinear(
213 heightRanges[0],
214 heightRanges[2],
215 heightRanges[1],
216 heightRanges[3],
217 pctX, pctY);
218 heightRange = Utils.Clamp(heightRange, 0f, 255f);
219
220 // Generate two frequencies of perlin noise based on our global position
221 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
222 Vector3 vec = new Vector3
223 (
224 ((float)regionPosition.X + x) * 0.20319f,
225 ((float)regionPosition.Y + y) * 0.20319f,
226 height * 0.25f
227 );
228
229 float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
230 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
231 float noise = (lowFreq + highFreq) * 2f;
232
233 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
234 float layer = ((height + noise - startHeight) / heightRange) * 4f;
235 if (Single.IsNaN(layer)) layer = 0f;
236 layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
237 }
238 }
239
240 #endregion Layer Map
241
242 #region Texture Compositing
243
244 Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
245 BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
246
247 unsafe
248 {
249 // Get handles to all of the texture data arrays
250 BitmapData[] datas = new BitmapData[]
251 {
252 detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
253 detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
254 detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
255 detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
256 };
257
258 int[] comps = new int[]
259 {
260 (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
261 (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
262 (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
263 (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
264 };
265
266 for (int y = 0; y < 256; y++) 202 for (int y = 0; y < 256; y++)
267 { 203 {
268 for (int x = 0; x < 256; x++) 204 for (int x = 0; x < 256; x++)
269 { 205 {
270 float layer = layermap[y * 256 + x]; 206 float height = heightmap[y * 256 + x];
271 207
272 // Select two textures 208 float pctX = (float)x / 255f;
273 int l0 = (int)Math.Floor(layer); 209 float pctY = (float)y / 255f;
274 int l1 = Math.Min(l0 + 1, 3); 210
275 211 // Use bilinear interpolation between the four corners of start height and
276 byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; 212 // height range to select the current values at this position
277 byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; 213 float startHeight = ImageUtils.Bilinear(
278 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; 214 startHeights[0],
279 215 startHeights[2],
280 float aB = *(ptrA + 0); 216 startHeights[1],
281 float aG = *(ptrA + 1); 217 startHeights[3],
282 float aR = *(ptrA + 2); 218 pctX, pctY);
283 219 startHeight = Utils.Clamp(startHeight, 0f, 255f);
284 float bB = *(ptrB + 0); 220
285 float bG = *(ptrB + 1); 221 float heightRange = ImageUtils.Bilinear(
286 float bR = *(ptrB + 2); 222 heightRanges[0],
287 223 heightRanges[2],
288 float layerDiff = layer - l0; 224 heightRanges[1],
289 225 heightRanges[3],
290 // Interpolate between the two selected textures 226 pctX, pctY);
291 *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); 227 heightRange = Utils.Clamp(heightRange, 0f, 255f);
292 *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); 228
293 *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); 229 // Generate two frequencies of perlin noise based on our global position
230 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
231 Vector3 vec = new Vector3
232 (
233 ((float)regionPosition.X + x) * 0.20319f,
234 ((float)regionPosition.Y + y) * 0.20319f,
235 height * 0.25f
236 );
237
238 float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
239 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
240 float noise = (lowFreq + highFreq) * 2f;
241
242 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
243 float layer = ((height + noise - startHeight) / heightRange) * 4f;
244 if (Single.IsNaN(layer)) layer = 0f;
245 layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
294 } 246 }
295 } 247 }
296 248
249 #endregion Layer Map
250
251 #region Texture Compositing
252
253 output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
254 outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
255
256 unsafe
257 {
258 // Get handles to all of the texture data arrays
259 BitmapData[] datas = new BitmapData[]
260 {
261 detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
262 detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
263 detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
264 detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
265 };
266
267 int[] comps = new int[]
268 {
269 (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
270 (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
271 (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
272 (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
273 };
274
275 for (int y = 0; y < 256; y++)
276 {
277 for (int x = 0; x < 256; x++)
278 {
279 float layer = layermap[y * 256 + x];
280
281 // Select two textures
282 int l0 = (int)Math.Floor(layer);
283 int l1 = Math.Min(l0 + 1, 3);
284
285 byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0];
286 byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1];
287 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
288
289 float aB = *(ptrA + 0);
290 float aG = *(ptrA + 1);
291 float aR = *(ptrA + 2);
292
293 float bB = *(ptrB + 0);
294 float bG = *(ptrB + 1);
295 float bR = *(ptrB + 2);
296
297 float layerDiff = layer - l0;
298
299 // Interpolate between the two selected textures
300 *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
301 *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
302 *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
303 }
304 }
305
306 for (int i = 0; i < 4; i++)
307 detailTexture[i].UnlockBits(datas[i]);
308 }
309 }
310 finally
311 {
297 for (int i = 0; i < 4; i++) 312 for (int i = 0; i < 4; i++)
298 detailTexture[i].UnlockBits(datas[i]); 313 if (detailTexture[i] != null)
314 detailTexture[i].Dispose();
299 } 315 }
300 316
301 output.UnlockBits(outputData); 317 output.UnlockBits(outputData);
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index e6f2855..3c48d07 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -54,8 +54,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
54 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); 54 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3");
55 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); 55 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
56 56
57 private static readonly ILog m_log = 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 58
60 private Scene m_scene; 59 private Scene m_scene;
61 private IRendering m_primMesher; 60 private IRendering m_primMesher;
@@ -164,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
164 } 163 }
165 catch 164 catch
166 { 165 {
167 m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); 166 m_log.Warn("[WARP 3D IMAGE MODULE]: Failed to load StartupConfig");
168 } 167 }
169 168
170 m_colors.Clear(); 169 m_colors.Clear();
@@ -218,7 +217,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
218 Bitmap bitmap = renderer.Scene.getImage(); 217 Bitmap bitmap = renderer.Scene.getImage();
219 218
220 if (m_useAntiAliasing) 219 if (m_useAntiAliasing)
221 bitmap = ImageUtils.ResizeImage(bitmap, viewport.Width, viewport.Height); 220 {
221 using (Bitmap origBitmap = bitmap)
222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
223 }
222 224
223 return bitmap; 225 return bitmap;
224 } 226 }
@@ -233,7 +235,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
233 catch (Exception e) 235 catch (Exception e)
234 { 236 {
235 // JPEG2000 encoder failed 237 // JPEG2000 encoder failed
236 m_log.Error("[MAPTILE]: Failed generating terrain map: " + e); 238 m_log.Error("[WARP 3D IMAGE MODULE]: Failed generating terrain map: ", e);
237 } 239 }
238 240
239 return null; 241 return null;
@@ -332,8 +334,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
332 uint globalX, globalY; 334 uint globalX, globalY;
333 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); 335 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
334 336
335 Bitmap image = TerrainSplat.Splat(heightmap, textureIDs, startHeights, heightRanges, new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain); 337 warp_Texture texture;
336 warp_Texture texture = new warp_Texture(image); 338
339 using (
340 Bitmap image
341 = TerrainSplat.Splat(
342 heightmap, textureIDs, startHeights, heightRanges,
343 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
344 {
345 texture = new warp_Texture(image);
346 }
347
337 warp_Material material = new warp_Material(texture); 348 warp_Material material = new warp_Material(texture);
338 material.setReflectivity(50); 349 material.setReflectivity(50);
339 renderer.Scene.addMaterial("TerrainColor", material); 350 renderer.Scene.addMaterial("TerrainColor", material);
@@ -560,42 +571,46 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
560 { 571 {
561 try 572 try
562 { 573 {
563 Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream); 574 int pixelBytes;
564 width = bitmap.Width;
565 height = bitmap.Height;
566 575
567 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); 576 using (Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream))
568 int pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
569
570 // Sum up the individual channels
571 unsafe
572 { 577 {
573 if (pixelBytes == 4) 578 width = bitmap.Width;
579 height = bitmap.Height;
580
581 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
582 pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
583
584 // Sum up the individual channels
585 unsafe
574 { 586 {
575 for (int y = 0; y < height; y++) 587 if (pixelBytes == 4)
576 { 588 {
577 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 589 for (int y = 0; y < height; y++)
578
579 for (int x = 0; x < width; x++)
580 { 590 {
581 b += row[x * pixelBytes + 0]; 591 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
582 g += row[x * pixelBytes + 1]; 592
583 r += row[x * pixelBytes + 2]; 593 for (int x = 0; x < width; x++)
584 a += row[x * pixelBytes + 3]; 594 {
595 b += row[x * pixelBytes + 0];
596 g += row[x * pixelBytes + 1];
597 r += row[x * pixelBytes + 2];
598 a += row[x * pixelBytes + 3];
599 }
585 } 600 }
586 } 601 }
587 } 602 else
588 else
589 {
590 for (int y = 0; y < height; y++)
591 { 603 {
592 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 604 for (int y = 0; y < height; y++)
593
594 for (int x = 0; x < width; x++)
595 { 605 {
596 b += row[x * pixelBytes + 0]; 606 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
597 g += row[x * pixelBytes + 1]; 607
598 r += row[x * pixelBytes + 2]; 608 for (int x = 0; x < width; x++)
609 {
610 b += row[x * pixelBytes + 0];
611 g += row[x * pixelBytes + 1];
612 r += row[x * pixelBytes + 2];
613 }
599 } 614 }
600 } 615 }
601 } 616 }
@@ -617,7 +632,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
617 } 632 }
618 catch (Exception ex) 633 catch (Exception ex)
619 { 634 {
620 m_log.WarnFormat("[MAPTILE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", textureID, j2kData.Length, ex.Message); 635 m_log.WarnFormat(
636 "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}",
637 textureID, j2kData.Length, ex.Message);
638
621 width = 0; 639 width = 0;
622 height = 0; 640 height = 0;
623 return new Color4(0.5f, 0.5f, 0.5f, 1.0f); 641 return new Color4(0.5f, 0.5f, 0.5f, 1.0f);