public unsafe Bitmap TerrainToBitmap(Bitmap mapbmp) { BitmapProcessing.FastBitmap unsafeBMP = new BitmapProcessing.FastBitmap(mapbmp); unsafeBMP.LockBitmap(); DateTime start = DateTime.Now; int tc = Environment.TickCount; //m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); // These textures should be in the AssetCache anyway, as every client conneting to this // region needs them. Except on start, when the map is recreated (before anyone connected), // and on change of the estate settings (textures and terrain values), when the map should // be recreated. RegionSettings settings = m_scene.RegionInfo.RegionSettings; // the four terrain colors as HSVs for interpolation HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, defaultColor1)); HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, defaultColor2)); HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, defaultColor3)); HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, defaultColor4)); float levelNElow = (float)settings.Elevation1NE; float levelNEhigh = (float)settings.Elevation2NE; float levelNWlow = (float)settings.Elevation1NW; float levelNWhigh = (float)settings.Elevation2NW; float levelSElow = (float)settings.Elevation1SE; float levelSEhigh = (float)settings.Elevation2SE; float levelSWlow = (float)settings.Elevation1SW; float levelSWhigh = (float)settings.Elevation2SW; float waterHeight = (float)settings.WaterHeight; ITerrainChannel heightmap = m_scene.RequestModuleInterface<ITerrainChannel>(); double[,] hm = heightmap.GetDoubles(m_scene); for (int y = 0; y < (int)Constants.RegionSize; y++) { float rowRatio = y / ((float)Constants.RegionSize - 1); // 0 - 1, for interpolation for (int x = 0; x < (int)Constants.RegionSize; x++) { float columnRatio = x / ((float)Constants.RegionSize - 1); // 0 - 1, for interpolation // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left int yr = ((int)Constants.RegionSize - 1) - y; float heightvalue = getHeight(hm, x, y); if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) heightvalue = 0; if (heightvalue > waterHeight) { // add a bit noise for breaking up those flat colors: // - a large-scale noise, for the "patches" (using an doubled s-curve for sharper contrast) // - a small-scale noise, for bringing in some small scale variation //float bigNoise = (float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f; // map to 0.0 - 1.0 //float smallNoise = (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * .5f + .5f; //float hmod = heightvalue + smallNoise * 3f + S(S(bigNoise)) * 10f; float hmod = heightvalue + (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * 1.5f + 1.5f + // 0 - 3 S(S((float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f)) * 10f; // 0 - 10 // find the low/high values for this point (interpolated bilinearily) // (and remember, x=0,y=0 is SW) float low = levelSWlow * (1f - rowRatio) * (1f - columnRatio) + levelSElow * (1f - rowRatio) * columnRatio + levelNWlow * rowRatio * (1f - columnRatio) + levelNElow * rowRatio * columnRatio; float high = levelSWhigh * (1f - rowRatio) * (1f - columnRatio) + levelSEhigh * (1f - rowRatio) * columnRatio + levelNWhigh * rowRatio * (1f - columnRatio) + levelNEhigh * rowRatio * columnRatio; if (high < low) { // someone tried to fool us. High value should be higher than low every time float tmp = high; high = low; low = tmp; } HSV hsv; if (hmod <= low) hsv = hsv1; // too low else if (hmod >= high) hsv = hsv4; // too high else { // HSV-interpolate along the colors // first, rescale h to 0.0 - 1.0 hmod = (hmod - low) / (high - low); // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 if (hmod < 1f / 3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f); else if (hmod < 2f / 3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f); else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f); } // Shade the terrain for shadows if (x < ((int)Constants.RegionSize - 1) && y < ((int)Constants.RegionSize - 1)) { float hfvaluecompare = getHeight(hm, x + 1, y + 1); // light from north-east => look at land height there if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare)) hfvaluecompare = 0f; float hfdiff = heightvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower hfdiff *= 0.06f; // some random factor so "it looks good" if (hfdiff > 0.02f) { float highlightfactor = 0.18f; // NE is lower than here // We have to desaturate and lighten the land at the same time hsv.s = (hsv.s - (hfdiff * highlightfactor) > 0f) ? hsv.s - (hfdiff * highlightfactor) : 0f; hsv.v = (hsv.v + (hfdiff * highlightfactor) < 1f) ? hsv.v + (hfdiff * highlightfactor) : 1f; } else if (hfdiff < -0.02f) { // here is lower than NE: // We have to desaturate and blacken the land at the same time hsv.s = (hsv.s + hfdiff > 0f) ? hsv.s + hfdiff : 0f; hsv.v = (hsv.v + hfdiff > 0f) ? hsv.v + hfdiff : 0f; } } //get the data from the original image Color hsvColor = hsv.toColor(); unsafeBMP.SetPixel(x, (255 - y), hsvColor); } else { // We're under the water level with the terrain, so paint water instead of land heightvalue = waterHeight - heightvalue; if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) heightvalue = 0f; else if (heightvalue > 19f) heightvalue = 19f; else if (heightvalue < 0f) heightvalue = 0f; heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0 unsafeBMP.SetPixel(x, (255 - y), WATER_COLOR); } } } if (m_mapping != null) m_mapping.Clear(); unsafeBMP.UnlockBitmap(); //m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); return mapbmp; }
// Compute the average color of a texture. private unsafe Color computeAverageColor(Bitmap bmp) { BitmapProcessing.FastBitmap unsafeBMP = new BitmapProcessing.FastBitmap(bmp); // we have 256 x 256 pixel, each with 256 possible color-values per // color-channel, so 2^24 is the maximum value we can get, adding everything. unsafeBMP.LockBitmap(); int r = 0; int g = 0; int b = 0; for (int y = 0; y < bmp.Height; y += 10) { for (int x = 0; x < bmp.Width; x += 10) { Color pixel = unsafeBMP.GetPixel(x, y); r += pixel.R; g += pixel.G; b += pixel.B; } } unsafeBMP.UnlockBitmap(); int pixels = (bmp.Width * bmp.Height) / (10 * 10); return Color.FromArgb((int)r / pixels, (int)g / pixels, (int)b / pixels); }
public void PaintEffect(ITerrainChannel map, UUID userID, float rx, float ry, float rz, float strength, float duration, float BrushSize, List<Scene> scene) { if (locked) return; locked = true; strength = TerrainUtil.MetersToSphericalStrength(BrushSize); int x, y; int xFrom = (int)(rx - BrushSize + 0.5); int xTo = (int)(rx + BrushSize + 0.5) + 1; int yFrom = (int)(ry - BrushSize + 0.5); int yTo = (int)(ry + BrushSize + 0.5) + 1; if (xFrom < 0) xFrom = 0; if (yFrom < 0) yFrom = 0; if (xTo > map.Width) xTo = map.Width; if (yTo > map.Height) yTo = map.Height; //ONLY get cached assets, since this is a local asset ONLY AssetBase paintAsset = map.Scene.AssetService.Get(map.Scene.RegionInfo.RegionSettings.PaintableTerrainTexture.ToString()); if (paintAsset == null) { paintAsset = new AssetBase(map.Scene.RegionInfo.RegionSettings.PaintableTerrainTexture, "PaintableTerrainTexture-" + map.Scene.RegionInfo.RegionID, (sbyte)AssetType.Texture, UUID.Zero.ToString()); paintAsset.Flags = AssetFlags.Deletable; AssetBase defaultTexture = map.Scene.AssetService.Get(RegionSettings.DEFAULT_TERRAIN_TEXTURE_2.ToString());//Nice grass if (defaultTexture == null) //Erm... what to do! return; paintAsset.Data = defaultTexture.Data;//Eventually we need to replace this with an interpolation of the existing textures! } AssetBase textureToApply = map.Scene.AssetService.Get(m_textureToPaint.ToString()); //The texture the client wants to paint if (textureToApply == null) return; Image paintiTexture = map.Scene.RequestModuleInterface<IJ2KDecoder> ().DecodeToImage (paintAsset.Data); if (paintiTexture == null) return; Image textureToAddiTexture = map.Scene.RequestModuleInterface<IJ2KDecoder> ().DecodeToImage (textureToApply.Data); if (textureToAddiTexture == null) { paintiTexture.Dispose(); return; } BitmapProcessing.FastBitmap paintTexture = new BitmapProcessing.FastBitmap((Bitmap)paintiTexture); BitmapProcessing.FastBitmap textureToAddTexture = new BitmapProcessing.FastBitmap((Bitmap)textureToAddiTexture); paintTexture.LockBitmap(); textureToAddTexture.LockBitmap(); // blend in map for (x = xFrom; x < xTo; x++) { for (y = yFrom; y < yTo; y++) { if (!map.Scene.Permissions.CanTerraformLand(userID, new Vector3(x, y, 0))) continue; Color c = textureToAddTexture.GetPixel((int)(((float)x / (float)map.Scene.RegionInfo.RegionSizeX * (float)textureToAddiTexture.Width)), (int)(((float)y / (float)map.Scene.RegionInfo.RegionSizeX) * (float)textureToAddiTexture.Height)); Color cc = paintTexture.GetPixel((int)(((float)x / (float)map.Scene.RegionInfo.RegionSizeX) * (float)textureToAddiTexture.Width), (int)(((float)y / (float)map.Scene.RegionInfo.RegionSizeX) * (float)textureToAddiTexture.Height)); paintTexture.SetPixel((int)(((float)x / (float)map.Scene.RegionInfo.RegionSizeX) * (float)paintiTexture.Width), (int)(((float)y / (float)map.Scene.RegionInfo.RegionSizeX) * (float)paintiTexture.Height), c); cc = paintTexture.GetPixel((int)(((float)x / (float)map.Scene.RegionInfo.RegionSizeX * (float)textureToAddiTexture.Width)), (int)(((float)y / (float)map.Scene.RegionInfo.RegionSizeX) * (float)textureToAddiTexture.Height)); } } map.Scene.AssetService.Delete(paintAsset.ID); paintTexture.UnlockBitmap(); textureToAddTexture.UnlockBitmap(); paintAsset.Data = OpenJPEG.EncodeFromImage(paintTexture.Bitmap(), false); paintAsset.Flags = AssetFlags.Deletable; map.Scene.RegionInfo.RegionSettings.PaintableTerrainTexture = UUID.Random(); paintAsset.ID = map.Scene.RegionInfo.RegionSettings.PaintableTerrainTexture.ToString(); map.Scene.AssetService.Store(paintAsset); map.Scene.RequestModuleInterface<IEstateModule>().sendRegionHandshakeToAll(); locked = false; }
public unsafe Bitmap TerrainToBitmap(Bitmap mapbmp) { BitmapProcessing.FastBitmap unsafeBMP = new BitmapProcessing.FastBitmap(mapbmp); unsafeBMP.LockBitmap(); //DateTime start = DateTime.Now; //m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); // These textures should be in the AssetCache anyway, as every client conneting to this // region needs them. Except on start, when the map is recreated (before anyone connected), // and on change of the estate settings (textures and terrain values), when the map should // be recreated. RegionSettings settings = m_scene.RegionInfo.RegionSettings; // the four terrain colors as HSVs for interpolation HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, defaultColor1)); HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, defaultColor2)); HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, defaultColor3)); HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, defaultColor4)); float levelNElow = (float)settings.Elevation1NE; float levelNEhigh = (float)settings.Elevation2NE; float levelNWlow = (float)settings.Elevation1NW; float levelNWhigh = (float)settings.Elevation2NW; float levelSElow = (float)settings.Elevation1SE; float levelSEhigh = (float)settings.Elevation2SE; float levelSWlow = (float)settings.Elevation1SW; float levelSWhigh = (float)settings.Elevation2SW; float waterHeight = (float)settings.WaterHeight; ITerrainChannel heightmap = m_scene.RequestModuleInterface<ITerrainChannel>(); float sizeRatio = (float)m_scene.RegionInfo.RegionSizeX / (float)Constants.RegionSize; for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += sizeRatio) { float rowRatio = y / (m_scene.RegionInfo.RegionSizeY - 1); // 0 - 1, for interpolation for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += sizeRatio) { float columnRatio = x / (m_scene.RegionInfo.RegionSizeX - 1); // 0 - 1, for interpolation float heightvalue = getHeight (heightmap, (int)x, (int)y); if (heightvalue > waterHeight) { // add a bit noise for breaking up those flat colors: // - a large-scale noise, for the "patches" (using an doubled s-curve for sharper contrast) // - a small-scale noise, for bringing in some small scale variation //float bigNoise = (float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f; // map to 0.0 - 1.0 //float smallNoise = (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * .5f + .5f; //float hmod = heightvalue + smallNoise * 3f + S(S(bigNoise)) * 10f; float hmod = heightvalue; // 0 - 10 // find the low/high values for this point (interpolated bilinearily) // (and remember, x=0,y=0 is SW) float low = levelSWlow * (1f - rowRatio) * (1f - columnRatio) + levelSElow * (1f - rowRatio) * columnRatio + levelNWlow * rowRatio * (1f - columnRatio) + levelNElow * rowRatio * columnRatio; float high = levelSWhigh * (1f - rowRatio) * (1f - columnRatio) + levelSEhigh * (1f - rowRatio) * columnRatio + levelNWhigh * rowRatio * (1f - columnRatio) + levelNEhigh * rowRatio * columnRatio; if (high < low) { // someone tried to fool us. High value should be higher than low every time float tmp = high; high = low; low = tmp; } HSV hsv; if (hmod <= low) hsv = hsv1; // too low else if (hmod >= high) hsv = hsv4; // too high else { // HSV-interpolate along the colors // first, rescale h to 0.0 - 1.0 hmod = (hmod - low) / (high - low); // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 if (hmod < 1f / 3f) hsv = interpolateHSV (ref hsv1, ref hsv2, hmod * 3f); else if (hmod < 2f / 3f) hsv = interpolateHSV (ref hsv2, ref hsv3, (hmod * 3f) - 1f); else hsv = interpolateHSV (ref hsv3, ref hsv4, (hmod * 3f) - 2f); } //get the data from the original image Color hsvColor = hsv.toColor (); unsafeBMP.SetPixel ((int)(x / sizeRatio),(int)(((m_scene.RegionInfo.RegionSizeY - 1) - y) / sizeRatio), hsvColor); } else { // We're under the water level with the terrain, so paint water instead of land unsafeBMP.SetPixel ((int)(x / sizeRatio), (int)(((m_scene.RegionInfo.RegionSizeY - 1) - y) / sizeRatio), WATER_COLOR); } } } if (m_mapping != null) { SaveCache (); m_mapping.Clear (); } unsafeBMP.UnlockBitmap(); //m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (DateTime.Now - start).TotalSeconds + " ms"); return unsafeBMP.Bitmap(); }
public SculptMap(Bitmap bm, int lod) { int bmW = bm.Width; int bmH = bm.Height; if (bmW == 0 || bmH == 0) throw new Exception("SculptMap: bitmap has no data"); int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image bool needsScaling = false; width = bmW; height = bmH; while (width * height > numLodPixels) { width >>= 1; height >>= 1; needsScaling = true; } try { if (needsScaling) bm = ScaleImage(bm, width, height, System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor); } catch (Exception e) { throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); } if (width * height > lod * lod) { width >>= 1; height >>= 1; } int numBytes = (width + 1) * (height + 1); redBytes = new byte[numBytes]; greenBytes = new byte[numBytes]; blueBytes = new byte[numBytes]; BitmapProcessing.FastBitmap unsafeBMP = new BitmapProcessing.FastBitmap(bm); unsafeBMP.LockBitmap(); //Lock the bitmap for the unsafe operation int byteNdx = 0; try { for (int y = 0; y <= height; y++) { for (int x = 0; x <= width; x++) { int bmY = y < height ? y * 2 : y * 2 - 1; int bmX = x < width ? x * 2 : x * 2 - 1; Color pixel = unsafeBMP.GetPixel(bmX, bmY); redBytes[byteNdx] = pixel.R; greenBytes[byteNdx] = pixel.G; blueBytes[byteNdx] = pixel.B; ++byteNdx; } } } catch (Exception e) { throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString()); } //All done, unlock unsafeBMP.UnlockBitmap(); width++; height++; }
private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror) { int numRows = bitmap.Height / scale; int numCols = bitmap.Width / scale; List<List<Coord>> rows = new List<List<Coord>>(numRows); float pixScale = 1.0f / 256.0f; int imageX, imageY = 0; int rowNdx, colNdx; BitmapProcessing.FastBitmap unsafeBMP = new BitmapProcessing.FastBitmap(bitmap); unsafeBMP.LockBitmap(); //Lock the bitmap for the unsafe operation for (rowNdx = 0; rowNdx <= numRows; rowNdx++) { List<Coord> row = new List<Coord>(numCols); imageY = rowNdx * scale; if (rowNdx == numRows) imageY--; for (colNdx = 0; colNdx <= numCols; colNdx++) { imageX = colNdx * scale; if (colNdx == numCols) imageX--; Color pixel = unsafeBMP.GetPixel(imageX, imageY); if (pixel.A != 255) { pixel = Color.FromArgb(255, pixel.R, pixel.G, pixel.B); unsafeBMP.SetPixel(imageX, imageY, pixel); } if (mirror) row.Add(new Coord(-(pixel.R * pixScale - 0.5f), pixel.G * pixScale - 0.5f, pixel.B * pixScale - 0.5f)); else row.Add(new Coord(pixel.R * pixScale - 0.5f, pixel.G * pixScale - 0.5f, pixel.B * pixScale - 0.5f)); } rows.Add(row); } unsafeBMP.UnlockBitmap(); return rows; }
/// <summary> /// converts a bitmap to a list of lists of coords, while scaling the image. /// the scaling is done in floating point so as to allow for reduced vertex position /// quantization as the position will be averaged between pixel values. this routine will /// likely fail if the bitmap width and height are not powers of 2. /// </summary> /// <param name="bitmap"></param> /// <param name="scale"></param> /// <param name="mirror"></param> /// <returns></returns> private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror) { int numRows = bitmap.Height / scale; int numCols = bitmap.Width / scale; List<List<Coord>> rows = new List<List<Coord>>(numRows); float pixScale = 1.0f / (scale * scale); pixScale /= 255; int imageX, imageY = 0; int rowNdx, colNdx; BitmapProcessing.FastBitmap unsafeBMP = new BitmapProcessing.FastBitmap(bitmap); unsafeBMP.LockBitmap(); //Lock the bitmap for the unsafe operation for (rowNdx = 0; rowNdx < numRows; rowNdx++) { List<Coord> row = new List<Coord>(numCols); for (colNdx = 0; colNdx < numCols; colNdx++) { imageX = colNdx * scale; int imageYStart = rowNdx * scale; int imageYEnd = imageYStart + scale; int imageXEnd = imageX + scale; float rSum = 0.0f; float gSum = 0.0f; float bSum = 0.0f; for (; imageX < imageXEnd; imageX++) { for (imageY = imageYStart; imageY < imageYEnd; imageY++) { Color pixel = unsafeBMP.GetPixel(imageX, imageY); if (pixel.A != 255) { pixel = Color.FromArgb(255, pixel.R, pixel.G, pixel.B); unsafeBMP.SetPixel(imageX, imageY, pixel); } rSum += pixel.R; gSum += pixel.G; bSum += pixel.B; } } if (mirror) row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); else row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); } rows.Add(row); } unsafeBMP.UnlockBitmap(); return rows; }
public Bitmap Shade (Bitmap source, Color shade, float percent, bool greyScale) { BitmapProcessing.FastBitmap b = new BitmapProcessing.FastBitmap (source); b.LockBitmap (); for (int y = 0; y < source.Height; y++) { for (int x = 0; x < source.Width; x++) { Color c = b.GetPixel (x, y); if (greyScale) { int luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11); b.SetPixel (x, y, Color.FromArgb (c.A, luma, luma, luma)); } else { float amtFrom = 1 - percent; int lumaR = (int)(c.R * amtFrom + shade.R * percent); int lumaG = (int)(c.G * amtFrom + shade.G * percent); int lumaB = (int)(c.B * amtFrom + shade.B * percent); b.SetPixel (x, y, Color.FromArgb (c.A, lumaR, lumaG, lumaB)); } } } b.UnlockBitmap (); return b.Bitmap(); }
private void Draw(string data, UUID id, string extraParams) { // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 int width = 256; int height = 256; int alpha = 255; // 0 is transparent Color bgColour = Color.White; // Default background color char altDataDelim = ';'; char[] paramDelimiter = { ',' }; char[] nvpDelimiter = { ':' }; extraParams = extraParams.Trim(); extraParams = extraParams.ToLower(); string[] nvps = extraParams.Split(paramDelimiter); int temp = -1; foreach (string pair in nvps) { string[] nvp = pair.Split(nvpDelimiter); string name = ""; string value = ""; if (nvp[0] != null) { name = nvp[0].Trim(); } if (nvp.Length == 2) { value = nvp[1].Trim(); } switch (name) { case "width": temp = parseIntParam(value); if (temp != -1) { if (temp < 1) { width = 1; } else if (temp > 2048) { width = 2048; } else { width = temp; } } break; case "height": temp = parseIntParam(value); if (temp != -1) { if (temp < 1) { height = 1; } else if (temp > 2048) { height = 2048; } else { height = temp; } } break; case "alpha": temp = parseIntParam(value); if (temp != -1) { if (temp < 0) { alpha = 0; } else if (temp > 255) { alpha = 255; } else { alpha = temp; } } // Allow a bitmap w/o the alpha component to be created else if (value.ToLower() == "false") { alpha = 256; } break; case "bgcolour": case "bgcolor": int hex = 0; if (Int32.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) { bgColour = Color.FromArgb(hex); } else { bgColour = Color.FromName(value); } break; case "altdatadelim": altDataDelim = value.ToCharArray()[0]; break; case "": // blank string has been passed do nothing just use defaults break; default: // this is all for backwards compat, all a bit ugly hopfully can be removed in future // could be either set alpha or just an int if (name == "setalpha") { alpha = 0; // set the texture to have transparent background (maintains backwards compat) } else { // this function used to accept an int on its own that represented both // width and height, this is to maintain backwards compat, could be removed // but would break existing scripts temp = parseIntParam(name); if (temp != -1) { if (temp > 1024) temp = 1024; if (temp < 128) temp = 128; width = temp; height = temp; } } break; } } Bitmap bitmap; if (alpha == 256) { bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); } else { bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); } Graphics graph = Graphics.FromImage(bitmap); // this is really just to save people filling the // background color in their scripts, only do when fully opaque if (alpha >= 255) { graph.FillRectangle(new SolidBrush(bgColour), 0, 0, width, height); } BitmapProcessing.FastBitmap fastBitmap = new BitmapProcessing.FastBitmap(bitmap); fastBitmap.LockBitmap(); for (int w = 0; w < bitmap.Width; w++) { if (alpha <= 255) { for (int h = 0; h < bitmap.Height; h++) { fastBitmap.SetPixel(w, h, Color.FromArgb(alpha, fastBitmap.GetPixel(w, h))); } } } fastBitmap.UnlockBitmap(); bitmap = fastBitmap.Bitmap(); graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; graph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; GDIDraw(data, graph, altDataDelim); byte[] imageJ2000 = new byte[0]; try { imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, false); } catch (Exception) { m_log.Error( "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); } m_textureManager.ReturnData(id, imageJ2000); }