/// <summary> /// Fills DFBitmap with specified values. /// </summary> /// <param name="bitmap">DFBitmap to fill.</param> /// <param name="r">Red value.</param> /// <param name="g">Green value.</param> /// <param name="b">Blue value.</param> /// <param name="a">Alpha value.</param> static public void Fill(DFBitmap bitmap, byte r, byte g, byte b, byte a) { // Fill with value and alpha for (int pos = 0; pos < bitmap.Data.Length; pos += bitmap.FormatWidth) { bitmap.Data[pos] = r; bitmap.Data[pos + 1] = g; bitmap.Data[pos + 2] = b; bitmap.Data[pos + 3] = a; } }
/// <summary> /// Creates a clone of a DFBitmap. /// </summary> /// <param name="bitmap">DFBitmap source.</param> /// <returns>Cloned DFBitmap.</returns> public static DFBitmap CloneDFBitmap(DFBitmap bitmap) { // Create destination bitmap to receive normal image DFBitmap newBitmap = new DFBitmap(); newBitmap.Width = bitmap.Width; newBitmap.Height = bitmap.Height; newBitmap.Data = new byte[bitmap.Data.Length]; bitmap.Data.CopyTo(newBitmap.Data, 0); return newBitmap; }
/// <summary> /// Gets pixel DFColor from DFBitmap. /// </summary> /// <param name="bitmap">DFBitmap.</param> /// <param name="x">X position.</param> /// <param name="y">Y position.</param> /// <returns>DFColor.</returns> static public DFColor GetPixel(DFBitmap bitmap, int x, int y) { DFColor color = new DFColor(); int srcPos = y * bitmap.Stride + x * bitmap.FormatWidth; color.r = bitmap.Data[srcPos++]; color.g = bitmap.Data[srcPos++]; color.b = bitmap.Data[srcPos++]; color.a = bitmap.Data[srcPos++]; return(color); }
/// <summary> /// Creates a clone of a DFBitmap. /// </summary> /// <param name="bitmap">DFBitmap source.</param> /// <returns>Cloned DFBitmap.</returns> static public DFBitmap CloneDFBitmap(DFBitmap bitmap) { // Create destination bitmap to receive normal image DFBitmap newBitmap = new DFBitmap(); newBitmap.Width = bitmap.Width; newBitmap.Height = bitmap.Height; newBitmap.Data = new byte[bitmap.Data.Length]; bitmap.Data.CopyTo(newBitmap.Data, 0); return(newBitmap); }
/// <summary> /// Creates a clone of a DFBitmap. /// </summary> /// <param name="bitmap">DFBitmap source.</param> /// <param name="cloneData">True to clone data.</param> /// <returns>Cloned DFBitmap.</returns> public static DFBitmap CloneDFBitmap(DFBitmap bitmap, bool cloneData = true) { // Create destination bitmap to receive normal image DFBitmap newBitmap = new DFBitmap(); newBitmap.Width = bitmap.Width; newBitmap.Height = bitmap.Height; newBitmap.Data = new byte[bitmap.Data.Length]; newBitmap.Palette = bitmap.Palette; // Clone data if (cloneData) bitmap.Data.CopyTo(newBitmap.Data, 0); return newBitmap; }
public override DFBitmap GetDFBitmap(int record, int frame) { DFBitmap result = new DFBitmap(); if (record == 0 && frame == 0 && managedFile.Length > 0) { BinaryReader reader = managedFile.GetReader(); byte[] data = reader.ReadBytes(managedFile.Length); DFSize sz = GetSize(0); result.Width = sz.Width; result.Height = sz.Height; result.Data = data; } return result; }
/// <summary> /// Dye supported bitmap image based on dye index and type. /// </summary> /// <param name="srcBitmap">Source image.</param> /// <param name="dye">Dye index.</param> /// <param name="target">Dye target.</param> /// <returns>New DFBitmap dyed to specified colour.</returns> public static DFBitmap ChangeDye(DFBitmap srcBitmap, DyeColors dye, DyeTargets target) { const int clothingStart = 0x60; const int weaponsAndArmorStart = 0x70; // Clone bitmap and get colour table for swaps DFBitmap dstBitmap = DFBitmap.CloneDFBitmap(srcBitmap, false); byte[] swaps = GetDyeColorTable(dye, target); // Swaps range is based on target type int start; switch(target) { case DyeTargets.Clothing: start = clothingStart; break; case DyeTargets.WeaponsAndArmor: start = weaponsAndArmorStart; break; default: return dstBitmap; } // Swap indices start through start + 15 with colour table int rowPos; for (int y = 0; y < srcBitmap.Height; y++) { rowPos = y * srcBitmap.Width; for (int x = 0; x < srcBitmap.Width; x++) { int srcOffset = rowPos + x; byte index = srcBitmap.Data[srcOffset]; if (index >= start && index <= start + 0x0f) { int tintOffset = index - start; dstBitmap.Data[srcOffset] = swaps[tintOffset]; } else { dstBitmap.Data[srcOffset] = index; } } } return dstBitmap; }
/// <summary> /// Creates a clone of a DFBitmap. /// </summary> /// <param name="bitmap">DFBitmap source.</param> /// <param name="cloneData">True to clone data.</param> /// <returns>Cloned DFBitmap.</returns> static public DFBitmap CloneDFBitmap(DFBitmap bitmap, bool cloneData = true) { // Create destination bitmap to receive normal image DFBitmap newBitmap = new DFBitmap(); newBitmap.Width = bitmap.Width; newBitmap.Height = bitmap.Height; newBitmap.Data = new byte[bitmap.Data.Length]; newBitmap.Palette = bitmap.Palette; // Clone data if (cloneData) { bitmap.Data.CopyTo(newBitmap.Data, 0); } return(newBitmap); }
/// <summary> /// Sets pixel in DFBitmap. Colour formats only. /// </summary> /// <param name="bitmap">DFBitmap.</param> /// <param name="x">X position.</param> /// <param name="y">Y position.</param> /// <param name="colour">Fill colour.</param> static public void SetPixel(DFBitmap bitmap, int x, int y, DFColor color) { int pos = y * bitmap.Stride + x * bitmap.FormatWidth; if (bitmap.Format == Formats.RGBA) { bitmap.Data[pos++] = color.r; bitmap.Data[pos++] = color.g; bitmap.Data[pos++] = color.b; bitmap.Data[pos] = color.a; } else if (bitmap.Format == Formats.ARGB) { bitmap.Data[pos++] = color.a; bitmap.Data[pos++] = color.r; bitmap.Data[pos++] = color.g; bitmap.Data[pos] = color.b; } }
/// <summary> /// Changes mask index to another index. /// </summary> /// <param name="srcBitmap">Source image.</param> /// <param name="replaceWith">Index to substitute for mask index.</param> /// <returns>New DFBitmap with modified mask.</returns> public static DFBitmap ChangeMask(DFBitmap srcBitmap, byte replaceWith = 0) { const int mask = 0xff; // Clone bitmap DFBitmap dstBitmap = DFBitmap.CloneDFBitmap(srcBitmap, false); // Remove all instances of mask index for (int i = 0; i < srcBitmap.Data.Length; i++) { byte index = srcBitmap.Data[i]; if (index == mask) dstBitmap.Data[i] = replaceWith; else dstBitmap.Data[i] = index; } return dstBitmap; }
/// <summary> /// Constructor to create an empty image of size and format. /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="format"></param> public DFManualImage(int width, int height, DFBitmap.Formats format) { // Create bitmap object manualBitmap = new DFBitmap(); manualBitmap.Width = width; manualBitmap.Height = height; manualBitmap.Format = format; // Set stride (1 byte per pixel for indexed, 4 bytes per pixel for all other formats) switch (format) { case DFBitmap.Formats.Indexed: manualBitmap.Stride = width; break; default: manualBitmap.Stride = width * 4; break; } // Create bitmap data manualBitmap.Data = new byte[manualBitmap.Stride * height]; }
/// <summary> /// Constructor using a DFBitmap. /// </summary> /// <param name="dfBitmap">Source DFBitmap object.</param> public DFManualImage(DFBitmap dfBitmap) { manualBitmap = dfBitmap; }
/// <summary> /// Default constructor. /// </summary> public DFManualImage() { manualBitmap = new DFBitmap(); }
/// <summary> /// Sets pixel in DFBitmap. Colour formats only. /// </summary> /// <param name="bitmap">DFBitmap.</param> /// <param name="x">X position.</param> /// <param name="y">Y position.</param> /// <param name="r">Red value.</param> /// <param name="g">Green value.</param> /// <param name="b">Blue value.</param> /// <param name="a">Alpha value.</param> static public void SetPixel(DFBitmap bitmap, int x, int y, byte r, byte g, byte b, byte a) { SetPixel(bitmap, x, y, DFColor.FromRGBA(r, g, b, a)); }
/// <summary> /// Fills DFBitmap with specified colour. /// </summary> /// <param name="bitmap">DFBitmap to fill.</param> /// <param name="color">Source colour.</param> static public void Fill(DFBitmap bitmap, DFColor color) { Fill(bitmap, color.r, color.g, color.b, color.a); }
/// <summary> /// Sets pixel in DFBitmap. Colour formats only. /// </summary> /// <param name="bitmap">DFBitmap.</param> /// <param name="x">X position.</param> /// <param name="y">Y position.</param> /// <param name="colour">Fill colour.</param> public static void SetPixel(DFBitmap bitmap, int x, int y, DFColor color) { int pos = y * bitmap.Stride + x * bitmap.FormatWidth; if (bitmap.Format == Formats.RGBA) { bitmap.Data[pos++] = color.r; bitmap.Data[pos++] = color.g; bitmap.Data[pos++] = color.b; bitmap.Data[pos] = color.a; } else if (bitmap.Format == Formats.ARGB) { bitmap.Data[pos++] = color.a; bitmap.Data[pos++] = color.r; bitmap.Data[pos++] = color.g; bitmap.Data[pos] = color.b; } }
/// <summary> /// Tint a weapon image based on metal type. /// </summary> /// <param name="srcBitmap">Source weapon image.</param> /// <param name="size">Image size.</param> /// <param name="metalType">Metal type for tint.</param> public static void TintWeaponImage(DFBitmap srcBitmap, MetalTypes metalType) { // Must be indexed format if (srcBitmap.Format != DFBitmap.Formats.Indexed) return; byte[] swaps = GetMetalColors(metalType); int rowPos; for (int y = 0; y < srcBitmap.Height; y++) { rowPos = y * srcBitmap.Width; for (int x = 0; x < srcBitmap.Width; x++) { byte index = srcBitmap.Data[rowPos + x]; if (index >= 0x70 && index <= 0x7f) { int offset = index - 0x70; srcBitmap.Data[rowPos + x] = swaps[offset]; } } } }
/// <summary> /// Resize DFBitmap with a bicubic kernel. /// </summary> /// <param name="bitmap">DFBitmap source.</param> /// <param name="level">MipMap level.</param> /// <returns>SnapBitmap mipmap.</returns> public static DFBitmap ResizeBicubic(DFBitmap bitmap, int newWidth, int newHeight) { // Must be colour format if (bitmap.Format == DFBitmap.Formats.Indexed) return null; // Get start size int width = bitmap.Width; int height = bitmap.Height; // Create new bitmap DFBitmap newBitmap = new DFBitmap(); newBitmap.Width = newWidth; newBitmap.Height = newHeight; newBitmap.Format = bitmap.Format; newBitmap.Stride = newBitmap.Width * bitmap.FormatWidth; newBitmap.Data = new byte[newBitmap.Stride * newBitmap.Height]; // Scale factors double xFactor = (double)width / newWidth; double yFactor = (double)height / newHeight; // Coordinates of source points and coefficients double ox, oy, dx, dy, k1, k2; int ox1, oy1, ox2, oy2; // Destination pixel values double r, g, b, a; // Width and height decreased by 1 int ymax = height - 1; int xmax = width - 1; // Bicubic resize for (int y = 0; y < newHeight; y++) { // Y coordinates oy = (double)y * yFactor - 0.5f; oy1 = (int)oy; dy = oy - (double)oy1; for (int x = 0; x < newWidth; x++) { // X coordinates ox = (double)x * xFactor - 0.5f; ox1 = (int)ox; dx = ox - (double)ox1; // Initial pixel value r = g = b = a = 0; for (int n = -1; n < 3; n++) { // Get Y coefficient k1 = BiCubicKernel(dy - (double)n); oy2 = oy1 + n; if (oy2 < 0) oy2 = 0; if (oy2 > ymax) oy2 = ymax; for (int m = -1; m < 3; m++) { // Get X coefficient k2 = k1 * BiCubicKernel((double)m - dx); ox2 = ox1 + m; if (ox2 < 0) ox2 = 0; if (ox2 > xmax) ox2 = xmax; // Get pixel of original image int srcPos = (ox2 * bitmap.FormatWidth) + (bitmap.Stride * oy2); r += k2 * bitmap.Data[srcPos++]; g += k2 * bitmap.Data[srcPos++]; b += k2 * bitmap.Data[srcPos++]; a += k2 * bitmap.Data[srcPos]; } } // Set destination pixel int dstPos = (x * newBitmap.FormatWidth) + (newBitmap.Stride * y); newBitmap.Data[dstPos++] = (byte)r; newBitmap.Data[dstPos++] = (byte)g; newBitmap.Data[dstPos++] = (byte)b; newBitmap.Data[dstPos] = (byte)a; } } return newBitmap; }
protected override void Setup() { // Load native texture nativeTexture = DaggerfallUI.GetTextureFromImg(nativeImgName); if (!nativeTexture) throw new Exception("DaggerfallTravelMap: Could not load native texture."); // Always dim background ParentPanel.BackgroundColor = ScreenDimColor; // Setup native panel background NativePanel.BackgroundTexture = nativeTexture; // Populate the offset dict PopulateRegionOffsetDict(); // Don't allow automatic cancel, we will handle this locally AllowCancel = false; // Load picker colours regionPickerBitmap = DaggerfallUI.GetImgBitmap(regionPickerImgName); // Add region label regionLabel = DaggerfallUI.AddTextLabel(DaggerfallUI.DefaultFont, new Vector2(0, 2), string.Empty, NativePanel); regionLabel.HorizontalAlignment = HorizontalAlignment.Center; // Handle clicks NativePanel.OnMouseClick += ClickHandler; // Setup buttons for first time LoadButtonTextures(); SetupButtons(); UpdateSearchButtons(); // Region overlay panel regionTextureOverlayPanel = DaggerfallUI.AddPanel(regionTextureOverlayPanelRect, NativePanel); regionTextureOverlayPanel.Enabled = false; // Location cluster panel locationClusterPanel = DaggerfallUI.AddPanel(regionTextureOverlayPanelRect, regionTextureOverlayPanel); locationClusterPanel.HorizontalAlignment = HorizontalAlignment.Left; locationClusterPanel.VerticalAlignment = VerticalAlignment.Top; // Location cluster will be updated when user opens a region locationClusterColors = new Color32[(int)regionTextureOverlayPanelRect.width * (int)regionTextureOverlayPanelRect.height]; locationClusterTexture = new Texture2D((int)regionTextureOverlayPanelRect.width, (int)regionTextureOverlayPanelRect.height); locationClusterTexture.filterMode = DaggerfallUI.Instance.GlobalFilterMode; // Overlay to identify player region identifyRegionOverlayTexture = CreatePlayerRegionOverlayTexture(); // Identify region panel is displayed to show user what region they are in identifyRegionPanel = new Panel(); identifyRegionPanel.Position = new Vector2(0, 0); identifyRegionPanel.Size = NativePanel.Size; identifyRegionPanel.BackgroundTexture = identifyRegionOverlayTexture; identifyRegionPanel.Enabled = false; NativePanel.Components.Add(identifyRegionPanel); }
/// <summary> /// Fills DFBitmap with specified values. /// </summary> /// <param name="bitmap">DFBitmap to fill.</param> /// <param name="r">Red value.</param> /// <param name="g">Green value.</param> /// <param name="b">Blue value.</param> /// <param name="a">Alpha value.</param> public static void Fill(DFBitmap bitmap, byte r, byte g, byte b, byte a) { // Fill with value and alpha for (int pos = 0; pos < bitmap.Data.Length; pos += bitmap.FormatWidth) { bitmap.Data[pos] = r; bitmap.Data[pos + 1] = g; bitmap.Data[pos + 2] = b; bitmap.Data[pos + 3] = a; } }
/// <summary> /// Fills DFBitmap with specified colour. /// </summary> /// <param name="bitmap">DFBitmap to fill.</param> /// <param name="color">Source colour.</param> public static void Fill(DFBitmap bitmap, DFColor color) { Fill(bitmap, color.r, color.g, color.b, color.a); }
/// <summary> /// Sets pixel in DFBitmap. Colour formats only. /// </summary> /// <param name="bitmap">DFBitmap.</param> /// <param name="x">X position.</param> /// <param name="y">Y position.</param> /// <param name="r">Red value.</param> /// <param name="g">Green value.</param> /// <param name="b">Blue value.</param> /// <param name="a">Alpha value.</param> public static void SetPixel(DFBitmap bitmap, int x, int y, byte r, byte g, byte b, byte a) { SetPixel(bitmap, x, y, DFColor.FromRGBA(r, g, b, a)); }
protected override void Setup() { // Load native texture nativeTexture = DaggerfallUI.GetTextureFromImg(nativeImgName); if (!nativeTexture) throw new Exception("CreateCharRaceSelect: Could not load native texture."); // Load picker colours racePickerBitmap = DaggerfallUI.GetImgBitmap(racePickerImgName); // Setup native panel background NativePanel.BackgroundTexture = nativeTexture; // Add "Please select your home province..." prompt promptLabel = DaggerfallUI.AddTextLabel(DaggerfallUI.DefaultFont, new Vector2(0, 16), HardStrings.pleaseSelectYourHomeProvince, NativePanel); promptLabel.HorizontalAlignment = HorizontalAlignment.Center; promptLabel.TextColor = DaggerfallUI.DaggerfallDefaultTextColor; promptLabel.ShadowColor = DaggerfallUI.DaggerfallDefaultShadowColor; promptLabel.ShadowPosition = DaggerfallUI.DaggerfallDefaultShadowPos; // Handle clicks NativePanel.OnMouseClick += ClickHandler; }
/// <summary> /// Converts full colour DFBitmap to Color32 array. /// </summary> /// <param name="bitmap">Source DFBitmap.</param> /// <param name="flipY">Flip Y rows so bottom becomes top.</param> /// <returns>Color32 array.</returns> public static Color32[] ConvertToColor32(DFBitmap bitmap, bool flipY = true) { // Must be RGBA format if (bitmap.Format != DFBitmap.Formats.RGBA) return null; // Create destination array Color32[] colors = new Color32[bitmap.Width * bitmap.Height]; int index = 0; for (int y = 0; y < bitmap.Height; y++) { int rowOffset = (flipY) ? (bitmap.Height - 1 - y) * bitmap.Stride : y * bitmap.Stride; for (int x = 0; x < bitmap.Width; x++) { // Get color bytes int pos = rowOffset + x * bitmap.FormatWidth; byte r = bitmap.Data[pos++]; byte g = bitmap.Data[pos++]; byte b = bitmap.Data[pos++]; byte a = bitmap.Data[pos]; // Store in array colors[index++] = new Color32(r, g, b, a); } } return colors; }
/// <summary> /// Gets pixel DFColor from DFBitmap. /// </summary> /// <param name="bitmap">DFBitmap.</param> /// <param name="x">X position.</param> /// <param name="y">Y position.</param> /// <returns>DFColor.</returns> public static DFColor GetPixel(DFBitmap bitmap, int x, int y) { DFColor color = new DFColor(); int srcPos = y * bitmap.Stride + x * bitmap.FormatWidth; color.r = bitmap.Data[srcPos++]; color.g = bitmap.Data[srcPos++]; color.b = bitmap.Data[srcPos++]; color.a = bitmap.Data[srcPos++]; return color; }
/// <summary> /// Creates a grayscale version of bitmap based on colour theory. /// </summary> /// <param name="bitmap">Source DFBitmap.</param> /// <returns>Grayscale DFBitmap image.</returns> public static DFBitmap MakeGrayscale(DFBitmap bitmap) { // Must be a colour format if (bitmap.Format == DFBitmap.Formats.Indexed) return null; DFBitmap newBitmap = new DFBitmap(); newBitmap.Format = bitmap.Format; newBitmap.Initialise(bitmap.Width, bitmap.Height); // Make each pixel grayscale int srcPos = 0, dstPos = 0; for (int i = 0; i < bitmap.Width * bitmap.Height; i++) { // Get source color byte r = bitmap.Data[srcPos++]; byte g = bitmap.Data[srcPos++]; byte b = bitmap.Data[srcPos++]; byte a = bitmap.Data[srcPos++]; // Create grayscale color int grayscale = (int)(r * 0.3f + g * 0.59f + b * 0.11f); DFBitmap.DFColor dstColor = DFBitmap.DFColor.FromRGBA((byte)grayscale, (byte)grayscale, (byte)grayscale, a); // Write destination pixel newBitmap.Data[dstPos++] = dstColor.r; newBitmap.Data[dstPos++] = dstColor.g; newBitmap.Data[dstPos++] = dstColor.b; newBitmap.Data[dstPos++] = dstColor.a; } return newBitmap; }
// Creates the region overlay for current player region Texture2D CreatePlayerRegionOverlayTexture() { try { // Player must be inside a valid region int playerRegion = GetPlayerRegion(); if (playerRegion == -1) return null; if (regionPickerBitmap == null) regionPickerBitmap = DaggerfallUI.GetImgBitmap(regionPickerImgName); // Create a texture map overlay for the region area int width = regionPickerBitmap.Width; int height = regionPickerBitmap.Height; Texture2D texture = new Texture2D(width, height); texture.filterMode = DaggerfallUI.Instance.GlobalFilterMode; // Create array for region fill Color32[] colors = new Color32[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int srcOffset = y * width + x; int dstOffset = ((height - y - 1) * width) + x; int sampleRegion = regionPickerBitmap.Data[srcOffset] - 128; if (sampleRegion == playerRegion) colors[dstOffset] = identifyFlashColor; } } // Assign colors to texture texture.SetPixels32(colors, 0); texture.Apply(); return texture; } catch(Exception ex) { Debug.LogError(string.Format("{0}\n{1}", ex.TargetSite, ex.Message)); return null; } }