/// <summary> /// Calculates the code for overlapping multiple brightness gradients. /// <para>The final code will use the channel of the first BrightnessHDMA object passed.</para> /// </summary> /// <param name="hdma">An array of BrightnessHDMA object that will be overlapped for the final code.</param> /// <returns>The final code.</returns> public static string MultiCode(params BrightnessHDMA[] hdma) { if (hdma == null || hdma.Length == 0) { return(null); } int channel = hdma[0].Channel; EffectClasses.HDMATable table = new HDMATable(".BrightTable"); using (Bitmap b = BitmapEffects.OverlapImages(hdma.Select(h => h.EffectImage).ToArray())) { byte scanlines = 1; int now = 0; int compare = 0x0F - (b.GetPixel(0, 0).A / 17); for (int y = 1; y < b.Height; y++, scanlines++) { now = 0x0F - (b.GetPixel(0, y).A / 17); if (compare != now || scanlines >= 0x80) { table.Add(new HDMATableEntry(TableValueType.db, scanlines, (byte)compare)); compare = now; scanlines = 0; } } if (table.TotalScanlines != Scanlines) { table.Add(new HDMATableEntry(TableValueType.db, scanlines, (byte)now)); } table.Add(HDMATableEntry.End); DMAMode mode = (table[0].Values.Length == 1 ? DMAMode.P : DMAMode.PP); ASMCodeBuilder code = new ASMCodeBuilder(); int channelAdd = 16 * channel; table.Name = ".BrightTable"; code.AppendLabel(INITLabel, "Code to be inserted INIT"); code.OpenNewBlock(); code.AppendCode("\tREP #$20", "16 bit mode"); code.AppendCode("\tLDA #$" + (((Registers.Brightness & 0xFF) << 8) + (int)mode).ToString("X4")); code.AppendCode("\tSTA $" + (Registers.DMAMode + channelAdd).ToString("X4")); code.AppendCode("\tLDA #" + table.Name, "load high and low byte of table address"); code.AppendCode("\tSTA $" + (Registers.DMALowByte + channelAdd).ToString("X4")); code.AppendCode("\tSEP #$20", "back to 8 bit mode"); code.AppendCode("\tLDA.b #" + table.Name + ">>16", "load bank byte of table address"); code.AppendCode("\tSTA $" + (Registers.DMABankByte + channelAdd).ToString("X4")); code.AppendCode("\tLDA #$" + (1 << channel).ToString("X2")); code.AppendCode("\tTSB $" + RAM.HDMAEnable[RAM.SA1].ToString("X4"), "enable HDMA channel " + channel); code.AppendCode("\tRTS"); code.CloseBlock(); code.AppendEmptyLine(); code.AppendTable(table); return(code.ToString()); } }
/// <summary> /// Sets up the color math and calculates the values for the HDMA table based on the entries of Values /// </summary> private void Setup() { Table.Clear(); byte totalScanlines = 0; Bitmap bg1 = OriginalImages.BG1; Bitmap bg2 = OriginalImages.BG2; Bitmap bg3 = OriginalImages.BG3; Bitmap bg4 = OriginalImages.BG4; foreach (PixelScanline pix in Values) { if (pix.Scanline > 0x80) { Table.Add(new HDMATableEntry(TableValueType.db, 0x80, (byte)((pix.Pixelation << 4) + (byte)pix.BGs))); Table.Add(new HDMATableEntry(TableValueType.db, (byte)(pix.Scanline - 0x80), (byte)((pix.Pixelation << 4) + (byte)pix.BGs))); } else { Table.Add(new HDMATableEntry(TableValueType.db, pix.Scanline, (byte)((pix.Pixelation << 4) + (byte)pix.BGs))); } if (pix.BGs.HasFlag(PixelationBGs.BG1)) { bg1 = BitmapEffects.PixelLine(pix.Scanline, pix.Pixelation, totalScanlines, bg1); } if (pix.BGs.HasFlag(PixelationBGs.BG2)) { bg2 = BitmapEffects.PixelLine(pix.Scanline, pix.Pixelation, totalScanlines, bg2); } if (pix.BGs.HasFlag(PixelationBGs.BG3)) { bg3 = BitmapEffects.PixelLine(pix.Scanline, pix.Pixelation, totalScanlines, bg3); } if (pix.BGs.HasFlag(PixelationBGs.BG4)) { bg4 = BitmapEffects.PixelLine(pix.Scanline, pix.Pixelation, totalScanlines, bg4); } totalScanlines += pix.Scanline; if (totalScanlines >= Scanlines) { break; } } if (totalScanlines < Scanlines) { Table.Add(new HDMATableEntry(TableValueType.db, 1, 0)); } ColorMath.BG1 = bg1; ColorMath.BG2 = bg2; ColorMath.BG3 = bg3; ColorMath.BG4 = bg4; ColorMath.OBJ = OriginalImages.OBJ; Table.Add(HDMATableEntry.End); }
public ColorMath(BitmapCollection Collection) : this() { BG1 = Collection.BG1; BG2 = Collection.BG2; BG3 = Collection.BG3; BG4 = Collection.BG4; OBJ = Collection.OBJ; FixedColor = BitmapEffects.FromColor(Collection.FixedColor, LayerSizes); }
/// <summary> /// Creates a base image with the preset setting of Amplitede and Width /// </summary> /// <param name="basePic">The base for the disordered image</param> /// <returns>The according to the settings disordered image</returns> public override Bitmap StaticPic(Bitmap basePic) { Reset(); Bitmap NewOne = new Bitmap(basePic); //NewOne gets overwritten with the disordered image. //_Breite * i sets the start of the to move setction. //_Breite sets how thick the to move section is. //_IArr[i % 16] says how many pixel to move the image to the right. for (int i = 0; i *_width < NewOne.Height; i++) { NewOne = BitmapEffects.MoveLine((_width * i), _width, _IArr[i % 16] / 2, NewOne, Direction); } if (!EnableTable) { return(NewOne); } using (Graphics g = Graphics.FromImage(NewOne)) { int totalCount = 0; foreach (var entry in EnabledWaveCollection) { int height = entry.LineCount; if (!entry.Value) { if (NewOne.Height <= totalCount + height) { height = NewOne.Height - totalCount; } var rec = Original.Clone(new Rectangle(0, totalCount, NewOne.Width, height), NewOne.PixelFormat); g.DrawImage(rec, 0, totalCount); } totalCount += height; if (totalCount >= NewOne.Height) { break; } } /* * if (totalCount < bm.Height) * g.DrawImage( * _yEffect.Original.Clone(new Rectangle(0, totalCount, bm.Width, (bm.Height - totalCount)), * bm.PixelFormat), 0, totalCount);*/ } return(NewOne); }
internal void UpdateImage() { if (Table == null) { return; } Bitmap bm = BitmapEffects.FromColor(Color.Transparent, 1, Scanlines); int counter = 0; foreach (HDMATableEntry entry in Table) { if (entry.ValueType == TableValueType.End) { break; } if (entry.ValueType == TableValueType.Single) { for (int y = counter; y < counter + entry.Scanlines - 0x80 && y < Scanlines; y++) { for (int x = 0; x < bm.Width; x++) { bm.SetPixel(x, y, Color.FromArgb(255 - (entry.Values[y] & 0x0F) * 17, 0, 0, 0)); } } counter += entry.Scanlines - 0x80; } else if (entry.ValueType == TableValueType.db) { for (int y = counter; y < counter + entry.Scanlines && y < Scanlines; y++) { for (int x = 0; x < bm.Width; x++) { bm.SetPixel(x, y, Color.FromArgb(255 - (entry.Values[0] & 0x0F) * 17, 0, 0, 0)); } } counter += entry.Scanlines; } else { //fixme exception throw new HDMAException(); } } Bitmap retImg = new Bitmap(256, Scanlines); using (TextureBrush brush = new TextureBrush(bm, WrapMode.Tile)) using (Graphics gr = Graphics.FromImage(retImg)) gr.FillRectangle(brush, 0, 0, retImg.Width, retImg.Height); EffectImage = retImg; }
/// <summary> /// Combines two black/white masks in a new bitmap /// </summary> /// <param name="mask1">The first mask for the merge</param> /// <param name="mask2">The second mask for the merge</param> /// <param name="logic">How to merge the masks</param> /// <returns>The merged masks</returns> private Bitmap MergeMasks(Bitmap mask1, Bitmap mask2, WindowMaskLogic logic) { Bitmap[] windowLogicMasks = new Bitmap[4]; Rectangle maskRec = new Rectangle(new Point(0, 0), mask2.Size); //needs to run if there is any OR, XOR, XNOR => baiscally if there is any that is not And if (logic != WindowMaskLogic.And) { Bitmap mask = new Bitmap(mask1); ImageAttributes attr = new ImageAttributes(); attr.SetColorKey(Color.White, Color.White); using (Graphics g = Graphics.FromImage(mask)) { g.DrawImage(mask2, maskRec, maskRec.X, maskRec.Y, maskRec.Width, maskRec.Height, GraphicsUnit.Pixel, attr); } windowLogicMasks[(int)WindowMaskLogic.Or] = mask; } //needs to run if there is any AND, XOR, XNOR => baiscally if there is any that is not Or if (logic != WindowMaskLogic.Or) { Bitmap mask = new Bitmap(mask1); ImageAttributes attr = new ImageAttributes(); attr.SetColorKey(Color.Black, Color.Black); using (Graphics g = Graphics.FromImage(mask)) { g.DrawImage(mask2, maskRec, maskRec.X, maskRec.Y, maskRec.Width, maskRec.Height, GraphicsUnit.Pixel, attr); } windowLogicMasks[(int)WindowMaskLogic.And] = mask; } if (logic == WindowMaskLogic.Xor || logic == WindowMaskLogic.XNor) { Bitmap mask = new Bitmap(windowLogicMasks[(int)WindowMaskLogic.Or]); ImageAttributes attr = new ImageAttributes(); attr.SetColorKey(Color.Black, Color.Black); using (Graphics g = Graphics.FromImage(mask)) { g.DrawImage(BitmapEffects.Invert(windowLogicMasks[(int)WindowMaskLogic.And]), maskRec, maskRec.X, maskRec.Y, maskRec.Width, maskRec.Height, GraphicsUnit.Pixel, attr); } mask.Save("XOR.png"); windowLogicMasks[(int)WindowMaskLogic.Xor] = mask; windowLogicMasks[(int)WindowMaskLogic.XNor] = BitmapEffects.Invert(mask); } return(windowLogicMasks[(int)logic]); }
public override Bitmap NextAnimateFrame(Bitmap basePic) { Bitmap newBM = new Bitmap(basePic); int offset = 0; foreach (var bar in Bars) { Bitmap single; int index = (int)(bar.Multiplier * Frame) % _frames.Length; if (_frames[index] == null) { single = BitmapEffects.MoveLine(0, basePic.Height, index, basePic, Orientation.Left); _frames[index] = single; } else { single = _frames[index]; } using (Graphics g = Graphics.FromImage(newBM)) { int scanlines = 0; if (offset + bar.Scanline >= basePic.Height) { scanlines = basePic.Height - offset; } else { scanlines = bar.Scanline; } Rectangle rect = new Rectangle(0, offset, basePic.Width, scanlines); g.SetClip(rect); g.Clear(Color.Transparent); //delete the part to be moved before drawing over it. g.ResetClip(); g.DrawImageUnscaled(single.Clone(rect, basePic.PixelFormat), rect); } offset += bar.Scanline; if (offset >= basePic.Height) { break; } } Frame++; return(newBM); }
/* * ============================================================================================================= * Constructors * ============================================================================================================= */ public ColorMath() { MainScreenDesignation = ScreenDesignation.BG1 | ScreenDesignation.OBJ; SubScreenDesignation = ScreenDesignation.BG2 | ScreenDesignation.BG4 | ScreenDesignation.BG3; ColorMathDesignation = ColorMathMode.Backdrop; LayerSizes = new Size(256, HDMA.Scanlines); BG1 = new Bitmap(LayerSizes.Width, LayerSizes.Height); BG2 = new Bitmap(LayerSizes.Width, LayerSizes.Height); BG3 = new Bitmap(LayerSizes.Width, LayerSizes.Height); BG4 = new Bitmap(LayerSizes.Width, LayerSizes.Height); OBJ = new Bitmap(LayerSizes.Width, LayerSizes.Height); FixedColor = new Bitmap(LayerSizes.Width, LayerSizes.Height); Backdrop = BitmapEffects.FromColor(Color.Black, LayerSizes); //default: White = hide nothing WindowingMask1 = BitmapEffects.FromColor(Color.White, LayerSizes); WindowingMask2 = BitmapEffects.FromColor(Color.White, LayerSizes); }
/// <summary> /// Creates a Bitmap depending on the settings and the internal counter, which also get's increased at the end. /// </summary> /// <param name="basePic">The still (unchanged) image.</param> /// <returns>Depending on the settings moved image.</returns> public override Bitmap NextAnimateFrame(Bitmap basePic) { Bitmap NewOne; try { int index = (int)(Frame * _speed) % _animationFrames.Length; //only calculate new frame if we don't have one yet. if (_animationFrames[index] == null) { NewOne = new Bitmap(basePic); for (int i = 0; i *_width < NewOne.Height; i++) { //NewOne gets overwritten with the disordered image. //_Breite * i sets the start of the to move setction. //_Breite sets how thick the to move section is. //_IArr[(i + _rounds) % 16] says how many pixel to move the image to the right. NewOne = BitmapEffects.MoveLine((_width * i), _width, _IArr[(i + index) % 16] / 2, NewOne, Direction); } _animationFrames[index] = NewOne; } else { //load frame from memory NewOne = _animationFrames[index]; } //SPEED_FACTOR multiplication because _speed < 1. So it would get reeeaaally slow. //_dRounds = (_dRounds + (_speed * SPEED_FACTOR)) % 16; //actual _rounds only increases ever so often due to cast. //_rounds = (int)_dRounds; Frame++; if (!EnableTable) { return(NewOne); } Bitmap img = new Bitmap(NewOne.Width, NewOne.Height); using (Graphics g = Graphics.FromImage(img)) { int totalCount = 0; foreach (var entry in EnabledWaveCollection) { int height = entry.LineCount; Bitmap toUse = entry.Value ? NewOne : basePic; if (img.Height <= totalCount + height) { height = img.Height - totalCount; } var rec = toUse.Clone(new Rectangle(0, totalCount, img.Width, height), toUse.PixelFormat); g.DrawImage(rec, 0, totalCount); totalCount += height; if (totalCount >= img.Height) { break; } } if (totalCount < img.Height) { g.DrawImage( basePic.Clone(new Rectangle(0, totalCount, img.Width, (img.Height - totalCount)), img.PixelFormat), 0, totalCount); } } return(img); } catch (Exception ex) { ThrowExceptionEvent(ex); return(StaticPic(basePic)); } }
public BrightnessHDMA() { EffectImage = BitmapEffects.FromColor(Color.Transparent, 256, Scanlines); }
public bool CheckAndSplitMask(Bitmap mask, ColorMath math) { //array of with array for each line. //each line has entrys with the color and the start position of that color in that line ColPos[][] C_Arr = new ColPos[Scanlines][]; BitmapData data = mask.LockBits(new Rectangle(new Point(0, 0), mask.Size), ImageLockMode.ReadWrite, mask.PixelFormat); byte[] bytes = new byte[data.Height * data.Stride]; System.Runtime.InteropServices.Marshal.Copy(data.Scan0, bytes, 0, bytes.Length); for (int y = 0; y < mask.Height; y++) { Color ColorToCheck = BitmapEffects.GetPixel(data, bytes, 0, y); //mask.GetPixel(0, y); List <ColPos> CList = new List <ColPos>(); CList.Add(new ColPos(ColorToCheck, 0)); for (int x = 1; x < mask.Width; x++) { Color c = BitmapEffects.GetPixel(data, bytes, x, y); if (ColorToCheck == c) //mask.GetPixel(x, y)) { continue; } ColorToCheck = c; //mask.GetPixel(x, y); CList.Add(new ColPos(ColorToCheck, x)); } C_Arr[y] = CList.ToArray(); } mask.UnlockBits(data); //if more then two black/white transitions appear in (any) line bool black3 = C_Arr.Any((CA => CA.Count(c => c.Color.Name == "ff000000") > 2)); bool white3 = C_Arr.Any((CA => CA.Count(c => c.Color.Name == "ffffffff") > 2)); //3 transitions in both won't work eg. black-white-black-white-black-white if (black3 && white3) { return(false); } int[] BlackLines; int[] WhiteLines; //get all the lines with 3 black transitions. //can't be more then 3 because that would result in more then 3 white trans. in the same line. IEnumerable <ColPos[]> Puff = C_Arr.Where((CA => CA.Count(c => c.Color.Name == "ff000000") > 2)); //an array of indeces to those lines. BlackLines = new int[Puff.Count()]; int i = 0; foreach (ColPos[] cp in Puff) { BlackLines[i] = Array.IndexOf(C_Arr, cp); i++; } //same for white. Puff = C_Arr.Where((CA => CA.Count(c => c.Color.Name == "ffffffff") > 2)); WhiteLines = new int[Puff.Count()]; i = 0; foreach (ColPos[] cp in Puff) { WhiteLines[i] = Array.IndexOf(C_Arr, cp); i++; } Bitmap w1 = BitmapEffects.FromColor(Color.White, 256, 224); Bitmap w2 = BitmapEffects.FromColor(Color.White, 256, 224); BitmapData w1Data = w1.LockBits(new Rectangle(0, 0, w1.Width, w1.Height), ImageLockMode.ReadWrite, w1.PixelFormat); BitmapData w2Data = w2.LockBits(new Rectangle(0, 0, w2.Width, w2.Height), ImageLockMode.ReadWrite, w2.PixelFormat); byte[] w1Bytes = new byte[w1Data.Height * w1Data.Stride]; byte[] w2Bytes = new byte[w2Data.Height * w2Data.Stride]; System.Runtime.InteropServices.Marshal.Copy(w1Data.Scan0, w1Bytes, 0, w1Bytes.Length); System.Runtime.InteropServices.Marshal.Copy(w2Data.Scan0, w2Bytes, 0, w2Bytes.Length); Table = new HDMATable(".windowTable"); HDMATableEntry entry = null; HDMATableEntry lastEntry = null; //if any line in this image requires 3 black and 2 white, one window (bm1) has to be inverted. bool WindowInverted = C_Arr.Any(cp => (cp.Count(c => c.Color.Name == "ff000000") == 3 && cp.Count(c => c.Color.Name == "ffffffff") == 2)); for (int y = 0; y < Scanlines; y++) { entry = new HDMATableEntry(TableValueType.db, (byte)(1 + y - Table.TotalScanlines), 0xFF, 0x00, 0xFF, 0x00); int countBlack = C_Arr[y].Count(cp => cp.Color.Name == "ff000000"); int countWhite = C_Arr[y].Count(cp => cp.Color.Name == "ffffffff"); Func <int, int, int, bool> BlackFromTill = (window, from, till) => { if (till == 0x100) { till = 0xFF; } if (window == 1) { for (int x = from; x < till; x++) { BitmapEffects.SetPixel(w1Data, ref w1Bytes, x, y, Color.Black); } entry.Values[0] = (byte)from; entry.Values[1] = (byte)till; return(true); } else if (window == 2) { for (int x = from; x < till; x++) { BitmapEffects.SetPixel(w2Data, ref w2Bytes, x, y, Color.Black); } entry.Values[2] = (byte)from; entry.Values[3] = (byte)till; return(true); } return(false); }; if (countBlack == 1 && countWhite == 0) { // whole line black. // if window get's inverted, line can be left unchanged. if (!WindowInverted) { BlackFromTill(1, 0, w1.Width); // if not, whole line black } } else if (countBlack == 2 && countWhite == 1) { //outer black, inner white (black-white-black) if (WindowInverted) //if window 1 is inverted it can be done using one window. { BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position); //The part white in the mask will be black in w1 } else //window 1 not inveted: { BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); // first black part of mask in window 1, BlackFromTill(2, C_Arr[y][2].Position, w2.Width); // and the second in window 2. } } else if (countBlack == 3 && countWhite == 2) { //black-white-black-white-black //1 window inverted, the other not (not possible otherwise). //meaning window 1 will be inverted. BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][4].Position); // windows 1 will be black from the beginning of the first white BlackFromTill(2, C_Arr[y][2].Position, C_Arr[y][3].Position); // till the end of the second. Windows 2 is the middle black part. } //else if (countBlack == 3 && countWhite == 3) //... IMPOSSIBRU <.< else if (countBlack == 2 && countWhite == 3) { //white-black-white-black-white //both windows have to be uninverted. (or playing with XOR setting) BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position); // window 1 black for first black part of mask BlackFromTill(2, C_Arr[y][3].Position, C_Arr[y][4].Position); // windows 2 black for second part. } else if (countBlack == 1 && countWhite == 2) { //outer white inner black (white-black-white) if (WindowInverted) //if windows 1 is inverted, we have to use window 2 and set window 1 black on the whole line { BlackFromTill(1, 0, w1.Width); // window 1 completly black BlackFromTill(2, C_Arr[y][1].Position, C_Arr[y][2].Position); // window 2 black where mask is black. } else { BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position); // if not inverted, simply use window 1. } } else if (countBlack == 0 && countWhite == 1) { //whole line visible if (WindowInverted) { BlackFromTill(1, 0, w1.Width); // if window 1 inverted, whole line black } } else if (countBlack == 2 && countWhite == 2) { //problem: unknown if black-white-black-white or white-black-white-black #region 2/2 if (C_Arr[y][0].Color.Name == "ff000000") //if fisrt part black then B-W-B-W { if (WindowInverted) //inverted: { BlackFromTill(1, C_Arr[y][1].Position, w1.Width); // the -W-B-W area will be black, so inverted makes the first bar black BlackFromTill(2, C_Arr[y][2].Position, C_Arr[y][3].Position); // window 2 simply makes second bar black } else //not inverted { BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); // first bar in window 1 BlackFromTill(2, C_Arr[y][2].Position, C_Arr[y][3].Position); // guess what } } else // first bar not black, thus W-B-W-B { if (WindowInverted) //inverted: { BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][3].Position); // the W-B-W- area will be black, inverting makes the last bar black. BlackFromTill(2, C_Arr[y][1].Position, C_Arr[y][2].Position); // window 2 will be black where the first bar is. } else //not inverted { BlackFromTill(1, C_Arr[y][1].Position, C_Arr[y][2].Position); // first bar in window 2 BlackFromTill(2, C_Arr[y][3].Position, w2.Width); // ... } } #endregion } else if (countBlack == 1 && countWhite == 1) { //problem: unknown if black-white or white-black if (C_Arr[y][0].Color.Name == "ff000000") //first bar is black thus B-W { if (WindowInverted) //inverted: { BlackFromTill(1, C_Arr[y][1].Position, w1.Width); //set second bar (white) to black due to inverting } else //not inverted { BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); //first bar (black) in window one to black } } else //first bar not black thus W-B { if (WindowInverted) //inverted: { BlackFromTill(1, C_Arr[y][0].Position, C_Arr[y][1].Position); // set white part black; } else //not inverted { BlackFromTill(1, C_Arr[y][1].Position, w1.Width); //set second bar black. } } } if ((lastEntry != null && !entry.Values.SequenceEqual(lastEntry.Values)) || entry.Scanlines == 0x81) { Table.Add(lastEntry); entry.Scanlines = 1; } lastEntry = (HDMATableEntry)entry.Clone(); } //end of for-loop Table.Add(lastEntry); //the last last entry Table.Add(HDMATableEntry.End); //the actual end. System.Runtime.InteropServices.Marshal.Copy(w1Bytes, 0, w1Data.Scan0, w1Bytes.Length); System.Runtime.InteropServices.Marshal.Copy(w2Bytes, 0, w2Data.Scan0, w2Bytes.Length); w1.UnlockBits(w1Data); w2.UnlockBits(w2Data); math.WindowingMask1 = w1; math.WindowingMask2 = w2; math.Window1Inverted = WindowInverted ? (WindowingLayers)0x3F : 0; return(true); }
public WindowingHDMA() { Orignal = BitmapEffects.FromColor(Color.White, 256, Scanlines); }
/// <summary> /// Gets the screen as it would be displayed by the SNES. /// </summary> /// <returns></returns> public Bitmap GetScreen() { if (BG1 == null || BG2 == null || BG3 == null || BG4 == null) { throw new ArgumentNullException("BGs need to be initialized"); } if (FixedColor == null) { throw new ArgumentNullException("FixedColor need to be initialized"); } if (Backdrop == null) { throw new ArgumentNullException("Backdrop need to be initialized"); } Bitmap main, sub; Bitmap statusBar = new Bitmap(LayerSizes.Width, LayerSizes.Height); Bitmap bg3_remain = new Bitmap(LayerSizes.Width, LayerSizes.Height); //cut layer 3 into status bar end rest. using (Graphics g = Graphics.FromImage(statusBar)) g.DrawImageUnscaledAndClipped(BG3, new Rectangle(0, 0, statusBar.Width, StatusBarHeight)); using (Graphics g = Graphics.FromImage(bg3_remain)) { Rectangle rec = new Rectangle(0, StatusBarHeight, bg3_remain.Width, bg3_remain.Height - StatusBarHeight); g.DrawImageUnscaledAndClipped(BG3.Clone(rec, BG3.PixelFormat), rec); } Func <bool, bool, bool, bool, WindowMaskLogic, Bitmap, Bitmap> doWindowing = (enable1, enable2, invert1, invert2, logic, bg) => { Bitmap mask1 = invert1 ? BitmapEffects.Invert(WindowingMask1) : WindowingMask1; Bitmap mask2 = invert2 ? BitmapEffects.Invert(WindowingMask2) : WindowingMask2; if (enable1 && enable2) { return(BitmapEffects.ApplyMask(bg, MergeMasks(mask1, mask2, logic), 0.5f)); } else if (enable1) { return(BitmapEffects.ApplyMask(bg, mask1, 0.5f)); } else if (enable2) { return(BitmapEffects.ApplyMask(bg, mask2, 0.5f)); } else { return(bg); } }; Bitmap bg1Windowed = doWindowing(Window1Enabled.HasFlag(WindowingLayers.BG1), Window2Enabled.HasFlag(WindowingLayers.BG1), Window1Inverted.HasFlag(WindowingLayers.BG1), Window2Inverted.HasFlag(WindowingLayers.BG1), Bg1MaskLogic, BG1); Bitmap bg2Windowed = doWindowing(Window1Enabled.HasFlag(WindowingLayers.BG2), Window2Enabled.HasFlag(WindowingLayers.BG2), Window1Inverted.HasFlag(WindowingLayers.BG2), Window2Inverted.HasFlag(WindowingLayers.BG2), Bg2MaskLogic, BG2); Bitmap statusBarWindowed = doWindowing(Window1Enabled.HasFlag(WindowingLayers.BG3), Window2Enabled.HasFlag(WindowingLayers.BG3), Window1Inverted.HasFlag(WindowingLayers.BG3), Window2Inverted.HasFlag(WindowingLayers.BG3), Bg3MaskLogic, statusBar); Bitmap bg3RemainWindowed = doWindowing(Window1Enabled.HasFlag(WindowingLayers.BG3), Window2Enabled.HasFlag(WindowingLayers.BG3), Window1Inverted.HasFlag(WindowingLayers.BG3), Window2Inverted.HasFlag(WindowingLayers.BG3), Bg3MaskLogic, bg3_remain); Bitmap bg4Windowed = doWindowing(Window1Enabled.HasFlag(WindowingLayers.BG4), Window2Enabled.HasFlag(WindowingLayers.BG4), Window1Inverted.HasFlag(WindowingLayers.BG4), Window2Inverted.HasFlag(WindowingLayers.BG4), Bg4MaskLogic, BG4); Bitmap objWindowed = doWindowing(Window1Enabled.HasFlag(WindowingLayers.OBJ), Window2Enabled.HasFlag(WindowingLayers.OBJ), Window1Inverted.HasFlag(WindowingLayers.OBJ), Window2Inverted.HasFlag(WindowingLayers.OBJ), ObjMaskLogic, OBJ); Bitmap colorWindowed = BitmapEffects.FromColor(Color.Black, LayerSizes); Bitmap colorWindowedHoles = doWindowing(Window1Enabled.HasFlag(WindowingLayers.Color), Window2Enabled.HasFlag(WindowingLayers.Color), Window1Inverted.HasFlag(WindowingLayers.Color), Window2Inverted.HasFlag(WindowingLayers.Color), ColorMaskLogic, BitmapEffects.FromColor(Color.White, LayerSizes)); //colorWindowsedHoles is white with holes where the black should be using (Graphics g = Graphics.FromImage(colorWindowed)) g.DrawImage(colorWindowedHoles, 0, 0); #region Sub Screen List <Bitmap> BGs = new List <Bitmap>(); if (SubScreenDesignation.HasFlag(ScreenDesignation.OBJ) && !Hide.HasFlag(ScreenDesignation.OBJ)) { BGs.Add(SubScreenWindowMaskDesignation.HasFlag(ScreenDesignation.OBJ) ? objWindowed : OBJ); } if (SubScreenDesignation.HasFlag(ScreenDesignation.BG1) && !Hide.HasFlag(ScreenDesignation.BG1)) { BGs.Add(SubScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG1) ? bg1Windowed : BG1); } if (SubScreenDesignation.HasFlag(ScreenDesignation.BG2) && !Hide.HasFlag(ScreenDesignation.BG2)) { BGs.Add(SubScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG2) ? bg2Windowed : BG2); } //layer 3 special (status bar split) onyl lower part if (SubScreenDesignation.HasFlag(ScreenDesignation.BG3) && !Hide.HasFlag(ScreenDesignation.BG3)) { BGs.Add(SubScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG3) ? bg3RemainWindowed : bg3_remain); } if (SubScreenDesignation.HasFlag(ScreenDesignation.BG4) && !Hide.HasFlag(ScreenDesignation.BG4)) { BGs.Add(SubScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG4) ? bg4Windowed : BG4); } BGs.Add(FixedColor); sub = BitmapEffects.OverlapImages(BGs.ToArray()); #endregion #region Main Screen BGs.Clear(); if (MainScreenDesignation.HasFlag(ScreenDesignation.OBJ) && !Hide.HasFlag(ScreenDesignation.OBJ)) { Bitmap objUse = MainScreenWindowMaskDesignation.HasFlag(ScreenDesignation.OBJ) ? objWindowed : OBJ; if (ColorMathDesignation.HasFlag(ColorMathMode.OBJ)) { BGs.Add(ApplyColorMath(objUse, AddColor ? FixedColor : sub, ColorMathDesignation, colorWindowed, ClipToBlack, PreventColorMath)); } else { BGs.Add(objUse); } } if (MainScreenDesignation.HasFlag(ScreenDesignation.BG1) && !Hide.HasFlag(ScreenDesignation.BG1)) { Bitmap bg1Use = MainScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG1) ? bg1Windowed : BG1; if (ColorMathDesignation.HasFlag(ColorMathMode.BG1)) { BGs.Add(ApplyColorMath(bg1Use, AddColor ? FixedColor : sub, ColorMathDesignation, colorWindowed, ClipToBlack, PreventColorMath)); } else { BGs.Add(bg1Use); } } if (MainScreenDesignation.HasFlag(ScreenDesignation.BG2) && !Hide.HasFlag(ScreenDesignation.BG2)) { Bitmap bg2Use = MainScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG2) ? bg2Windowed : BG2; if (ColorMathDesignation.HasFlag(ColorMathMode.BG2)) { BGs.Add(ApplyColorMath(bg2Use, AddColor ? FixedColor : sub, ColorMathDesignation, colorWindowed, ClipToBlack, PreventColorMath)); } else { BGs.Add(bg2Use); } } if (MainScreenDesignation.HasFlag(ScreenDesignation.BG3) && !Hide.HasFlag(ScreenDesignation.BG3)) { //layer 3 special (status bar split) onyl lower half Bitmap bg3Use = MainScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG3) ? bg3RemainWindowed : bg3_remain; if (ColorMathDesignation.HasFlag(ColorMathMode.BG3)) { BGs.Add(ApplyColorMath(bg3Use, AddColor ? FixedColor : sub, ColorMathDesignation, colorWindowed, ClipToBlack, PreventColorMath)); } else { BGs.Add(bg3Use); } } if (MainScreenDesignation.HasFlag(ScreenDesignation.BG4) && !Hide.HasFlag(ScreenDesignation.BG4)) { Bitmap bg4Use = MainScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG3) ? bg4Windowed : BG4; if (ColorMathDesignation.HasFlag(ColorMathMode.BG4)) { BGs.Add(ApplyColorMath(bg4Use, AddColor ? FixedColor : sub, ColorMathDesignation, colorWindowed, ClipToBlack, PreventColorMath)); } else { BGs.Add(bg4Use); } } //handle the backdrop too if (ColorMathDesignation.HasFlag(ColorMathMode.Backdrop)) { BGs.Add(ApplyColorMath(Backdrop, AddColor ? FixedColor : sub, ColorMathDesignation, colorWindowed, ClipToBlack, PreventColorMath)); } else { BGs.Add(Backdrop); } main = BitmapEffects.OverlapImages(BGs.ToArray()); #endregion BGs.Clear(); //check windowing for status bar if (MainScreenDesignation.HasFlag(ScreenDesignation.BG3) && !Hide.HasFlag(ScreenDesignation.BG3)) { BGs.Add(MainScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG3) ? statusBarWindowed : statusBar); } //if not main, check subscreen. (still put it before main for display purpose) else if (SubScreenDesignation.HasFlag(ScreenDesignation.BG3) && !Hide.HasFlag(ScreenDesignation.BG3)) { BGs.Add(SubScreenWindowMaskDesignation.HasFlag(ScreenDesignation.BG3) ? statusBarWindowed : statusBar); } BGs.Add(main); BGs.Add(sub); return(BitmapEffects.OverlapImages(BGs.ToArray())); }
/// <summary> /// Sets the FixedColor property based on a desired color. /// </summary> /// <param name="color">The color for the Bitmap</param> public void SetBackdrop(Color color) { Backdrop = BitmapEffects.FromColor(color, LayerSizes); }
/// <summary> /// Sets the FixedColor property based on a desired color. /// </summary> /// <param name="color">The color for the Bitmap</param> public void SetFixedColor(Color color) { FixedColor = BitmapEffects.FromColor(color, LayerSizes); }