Jump to content

Illnab1024

Members
  • Posts

    1,178
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by Illnab1024

  1. How does this exactly work?

    In the DLL there's an embedded resource with the .exe produced by building the C code. That executable has a static array from `const CHAR_INFO outChar[80][25] = { { {L'0', 0xf} } };` which is printed directly to the console using ConsoleWriteW. The Plugin writes that .exe to file but writes over the static array inside the executable to change the "image" that gets written to the console.

    It's just a "for-fun" plugin; there's absolutely no point to saving an image as an executable file, and even though you could do it as a full-color bitmap and use Windows GDI stuff to display it, that's also pointless when there's Windows Photo Viewer. If I really wanted to have fun, I'd do a 16-bit .COM FileType using int 21 stuff, but I'm on a 64-bit system, so meh.

  2. Just relaxing, decided to make this for fun.

    QaGHa.jpg

    Hidden Content: C# source

    
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using PaintDotNet;
    using PaintDotNet.Data;
    using PaintDotNet.Rendering;
    using System.IO;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Drawing.Imaging;
    using System.Linq;
    
    namespace DotExeFileType
    {
     public class MyFileType : FileType
     {
    public MyFileType()
      : base("Exe File",
    	  FileTypeFlags.SupportsSaving,
    	  new String[] { ".exe" })
    {
    }
    
    protected override void OnSave(Document input, Stream output, SaveConfigToken token,
      Surface scratchSurface, ProgressEventHandler callback)
    {
      RenderArgs ra = new RenderArgs(new Surface(input.Size));
    
      // input.Render(ra);
      input.Render(ra, false);
      var img = ra.Bitmap;
      Bitmap cells = new Bitmap(80 * 8, 25 * 12);
      Graphics ctx = Graphics.FromImage(cells);
      ctx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
      ctx.DrawImage(img, 0, 0, 80 * 8, 25 * 12);
      ctx.Dispose();
      byte[] outArr = new byte[80*25*4];
    
    
      // Downsample to 4-bit colors
      for (int y = 0; y < 25*12; y++)
      {
    	for (int x = 0; x < 80*8; x++)
    	{
    	  Color c = cells.GetPixel(x, y);
    	  cells.SetPixel(x, y, bestMatch(ColorBgra.FromColor(cells.GetPixel(x, y))));
    	}
      }
    
      // Histogram the 8x12 characters and find
      // the closest match
      for (int y = 0; y < 25; y++)
      {
    	for (int x = 0; x < 80; x++)
    	{
    	  Dictionary<ColorBgra, int> histo = new Dictionary<ColorBgra, int>();
    	  for (int j = 0; j < 12; j++)
    	  {
    		for (int i = 0; i < 8; i++)
    		{
    		  ColorBgra col = ColorBgra.FromColor(cells.GetPixel(i + x * 8, j + y * 12));
    		  if (!histo.ContainsKey(col))
    			histo.Add(col, 1);
    		  else histo[col]++;
    		}
    	  }
    
    
    	  var histoList = histo
    		.OrderByDescending(k => k.Value).Select(k => k.Key)
    		.ToList();
    	  byte foreground = (byte)Enumerable.Range(0, ConsoleColors.Length)
    		.Where(i => ConsoleColors[i] == histoList[0])
    		.First();
    	  byte background;
    	  if (histoList.Count > 1)
    	  {
    		background = (byte)Enumerable.Range(0, ConsoleColors.Length)
    		  .Where(i => ConsoleColors[i] == histoList[1])
    		  .First();
    	  }
    	  else { background = foreground; }
    	  double ratio;
    	  if (histoList.Count > 1)
    		ratio = 96 * histo[histoList[0]] / (histo[histoList[0]] + histo[histoList[1]]);
    	  else ratio = 0;
    
    	  int bestCodepoint = 0;
    	  double bestRatioDiff = Double.MaxValue;
    	  for (int i = 0; i < CP437.Length; i++)
    	  {
    		if (Math.Abs((double)(CP437[i]) - ratio) < bestRatioDiff)
    		{
    		  bestRatioDiff = Math.Abs((double)(CP437[i]) - ratio);
    		  bestCodepoint = i;
    		}
    	  }
    
    	  var index = (y * 80 + x) * 4;
    	  outArr[index] = (byte)bestCodepoint;
    	  outArr[index + 1] = (byte)0;
    	  outArr[index + 2] = (byte)(foreground | (background << 4));
    	  outArr[index + 3] = (byte)0;
    	}
      }
    
      output.Write(ExeOut.OutExe, 0, (int)ArrayOffset);
      output.Write(outArr, 0, outArr.Length);
      output.Write(ExeOut.OutExe, (int)(ArrayOffset + outArr.Length),
    	(int)(ExeOut.OutExe.Length - (ArrayOffset + outArr.Length)));
    }
    
    protected override Document OnLoad(Stream input)
    {
    	throw new NotImplementedException();
    }
    
    ColorBgra[] ConsoleColors = {
    	ColorBgra.FromOpaqueInt32(0x000000),
    	ColorBgra.FromOpaqueInt32(0x000080),
    	ColorBgra.FromOpaqueInt32(0x008000),
    	ColorBgra.FromOpaqueInt32(0x008080),
    	ColorBgra.FromOpaqueInt32(0x800000),
    	ColorBgra.FromOpaqueInt32(0x800080),
    	ColorBgra.FromOpaqueInt32(0x808000),
    	ColorBgra.FromOpaqueInt32(0xC0C0C0),
    	ColorBgra.FromOpaqueInt32(0x808080),
    	ColorBgra.FromOpaqueInt32(0x0000FF),
    	ColorBgra.FromOpaqueInt32(0x00FF00),
    	ColorBgra.FromOpaqueInt32(0x00FFFF),
    	ColorBgra.FromOpaqueInt32(0xFF0000),
    	ColorBgra.FromOpaqueInt32(0xFF00FF),
    	ColorBgra.FromOpaqueInt32(0xFFFF00),
    	ColorBgra.FromOpaqueInt32(0xFFFFFF)
    	};
    
    // Generated from CodeLab and a screenshot!
    int[] CP437 = { 00, 38, 60, 38, 32, 40, 44, 20, 76, 32, 64, 37, 32, 32, 48, 40,
    	29, 29, 30, 28, 47, 40, 21, 36, 24, 24, 15, 15, 13, 20, 32, 32,
    	00, 22, 14, 42, 30, 20, 40, 08, 18, 18, 24, 14, 08, 08, 06, 14,
    	45, 23, 30, 27, 32, 29, 30, 27, 38, 30, 12, 16, 18, 12, 18, 20,
    	40, 36, 41, 30, 38, 35, 33, 34, 38, 22, 28, 38, 30, 45, 45, 34,
    	33, 41, 40, 31, 26, 36, 34, 38, 34, 30, 35, 22, 14, 22, 12, 08,
    	24, 33, 20, 33, 24, 26, 32, 33, 22, 28, 32, 24, 30, 25, 24, 32,
    	32, 23, 20, 22, 25, 22, 26, 22, 28, 22, 20, 16, 20, 14, 24, 23
    	};
    
    double colorDistance(ColorBgra a, ColorBgra 
    {
    	HsvColor aH = HsvColor.FromColor(a.ToColor());
    	HsvColor bH = HsvColor.FromColor(b.ToColor());
    	return Math.Abs(bH.Hue - aH.Hue) +
    		Math.Abs(bH.Saturation - aH.Saturation) +
    		Math.Abs(bH.Value - aH.Value);
    }
    
    ColorBgra bestMatch(ColorBgra c)
    {
    	double bestDist = Double.MaxValue;
    	ColorBgra bestCol = ColorBgra.Black;
    
    	for (int n = 0; n < 16; n++)
    	{
    		double curDist = colorDistance(c, ConsoleColors[n]);
    		if (curDist < bestDist)
    		{
    			bestCol = ConsoleColors[n];
    			bestDist = curDist;
    		}
    	}
    
    	return bestCol;
    }
    
    uint ArrayOffset = 0x418;
     }
    
     public class MyFileTypeFactory : IFileTypeFactory
     {
    public FileType[] GetFileTypeInstances()
    {
      return new FileType[] { new MyFileType() };
    }
     }
    }
    
    

    Hidden Content: c++ source

    
    #define WIN32_LEAN_AND_MEAN
    
    #include <Windows.h>
    
    // Stuff to pass WriteConsoleOutputW.  These are in the
    // .data segment (0x2400 in the .exe) in whatever order
    // the compiler felt like.
    CONSOLE_SCREEN_BUFFER_INFO outInfo;
    COORD outSize = {80, 25};
    COORD outPos = {0, 0};
    
    // Const, so it will be in (because we merged .rdata
    // into it) .text at 0x400 in the .exe.
    // Totally note I got the order wrong here but it doesn't
    // really matter since we're filling in these values elsewhere.
    const CHAR_INFO outChar[80][25] = { { {L'0', 0xf} } };
    
    // Custom entry-point to remind you not to link this
    // with the Visual C Run-Time library.
    int Main()
    {
     // Even though we use Unicode output, it's rare for
     // a Windows console to use Unicode.
     HANDLE conOut = GetStdHandle(STD_OUTPUT_HANDLE);
     HANDLE conIn  = GetStdHandle(STD_INPUT_HANDLE );
     GetConsoleScreenBufferInfo(conOut, &outInfo);
     outInfo.dwCursorPosition.X = 0;
     WriteConsoleOutputW(conOut, (CHAR_INFO*)outChar,
    outSize, outPos, &outInfo.srWindow);
     ReadConsoleW(conIn, (LPVOID)&outInfo, 1, 0, 0);
     outInfo.dwCursorPosition.Y += 25;
     SetConsoleCursorPosition(conOut, outInfo.dwCursorPosition);
     return 0;
    }
    

    Compile as x86, use /MERGE:".rdata=.text", /NODEFAULTLIB, and /MANIFEST:NO to link.

    Download: DotExeFileType.zip

    (Edited: Messed up the 'ratio' variable)

  3. Quick little codelab plugin: Color Star.

    It creates a specified number of colors equidistant in hue, similar to placing a regular polygon star on the color wheel and picking colors at the points.

    >> ColorStar.zip <<

    PU57i.jpg

    Source:

    Hidden Content: Source

    
    #region UICode
    int    Amount1=7;     //[1,100]Number
    double Amount2=2.0;   //[0,100]Angle
    double Amount3=10;    //[0,50]Saturation Deviation
    double Amount4=10;    //[0,50]Value Deviation
    #endregion
    void Render(Surface dst, Surface src, Rectangle rect)
    {
       Rectangle selection = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
       int width = selection.Right - selection.Left;
       int numCols = Amount1;
    
       for (int y = rect.Top; y < rect.Bottom; y++)
       {
           for (int x = rect.Left; x < rect.Right; x++)
           {
               dst[x,y] = colors[(int)Math.Floor(numCols * (double)x/width)];
           }
       }
    }
    List<ColorBgra> _colors = new List<ColorBgra>();
    
    internal struct Params { int a1; double a2; double a3; double a4;
       public Params(int p1, double p2, double p3, double p4)
       { a1 = p1; a2 = p2; a3 = p3; a4 = p4; }
       public override bool Equals(object obj)
       {
           Params param = (Params)obj;
           return param.a1 == a1 && param.a2 == a2 &&
             param.a3 == a3 && param.a4 == a4;
       }
    }
    
    Params lastParams;
    
    List<ColorBgra> colors
    {
       get
       {
           int numCols = Amount1;
           Params newParams = new Params(Amount1, Amount2, Amount3, Amount4);
           if (_colors.Count != numCols ||
                   !lastParams.Equals(newParams))
           {
               lastParams = newParams;
               double devSat = Amount3;
               double devVal = Amount4;
               double q = Amount2;
               _colors = new List<ColorBgra>(numCols);
               HsvColor primary = HsvColor.FromColor(EnvironmentParameters.PrimaryColor);
               double jump = q * 360 / numCols;
               double h = primary.Hue;
               double s = primary.Saturation;
               double v = primary.Value;
               Random r = new Random();
               for (int i = 0; i < numCols; i++)
               {
                   _colors.Add(ColorBgra.FromColor(new HsvColor(
                                   (int)((h += jump))%361,
                                   clamp((int)((s + devSat * r.NextDouble())), 100),
                                   clamp((int)((v + devVal * r.NextDouble())), 100)
                                   ).ToColor()));
               }
           }
           return _colors;
       }
    }
    
    int clamp(int n, int max)
    {
       if (n >= max) return max;
       if (n <= 0) return 0;
       return n;
    }
    

  4. As a get{} process for a public variable (with a private version solely for caching purposes), i.e.:

    private Surface _Dataz = new Surface;
    public Surface Dataz // Readonly, public variable; private _Dataz is read/writable.
    {
       get
       {
           if (NeedToRecalculate) // Where NeedToRecalculate represents a boolean value of whether or not we should recalculate;
                                  // i.e., if our EffectConfigToken has changed--and you need to set this NeedToRecalculate inside 
                                  // the render loop to ensure that the ConfigToken values are pertinent.
           {
               // Calculate your surface, store it to _Dataz and return the Surface.
               // Be sure to use _Dataz as your surface when calculating this, as you will double your memory otherwise
           }
           else return _Dataz;
       }
    }
    

    And it's your job to figure out how to do this in VB.NET ;)

  5. Remember that Render is called multiple times with many different arguments throughout the entire rendering process. You need to precalculate your surface so that you only calculate the path blur it on the first call of the render loop (after your dialog properties have changed). Also remember that this function can be called simultaneously on multiple threads, and there's usually no good way around that (by which I mean the workarounds tend to have more caveats than they're worth).

  6. Possible alternative Google Search API:

    http://code.google.com/apis/ajaxsearch/documentation/reference.html#_class_GimageSearch

    There is an Open License Yahoo Image Search API implementation here:

    http://www.codeproject.com/KB/IP/yahoo_image_search_api.aspx

    I know it's as nice as Google, but Bing does have a Windows API that includes Image Search:

    http://msdn.microsoft.com/en-us/library/62d89ce7-9e5e-430b-8147-8a271e6e8607

    I'm going to work on this issue now, the current implementation is a page scrape (well, technically a scrape of the Javascript portion of AJAX data from a result) and I nearly dislike having to do that enough to make me want to use the Bing API (I was thinking about that before reading this but didn't know if Microsoft provided an actual API for Bing).

  7. Also, some fun with networking! A polar distortion based off of an image taken from nik.bot.nu (advice: slightly maybe NSFW).

    Supposedly, this HSV algorithm works. I'm too tired to try to understand it atm, so I just threw it in there. It works I suppose. (takes a while to do everything, I think cause of several requests gone by without caching)

    #region UICode
    int Amount1=10;	//[0,300]Distortion length
    #endregion
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
       Surface img = nikbotImg;
       float[] vector = new float[2]{0,0};
       for (int y = rect.Top; y < rect.Bottom; y++)
       {
           for (int x = rect.Left; x < rect.Right; x++)
           {
               vector = calVector(x,y);
               dst[x,y] = src.GetBilinearSampleWrapped(x+vector[0],y+vector[1]);
           }
       }
    }
    static string nikbotBrowseUri = "http://nik.bot.nu/browse.fu?cnt=1&pn=0&srt=7&eq=0&rs=0&rt=0&da=7&nw=0";
    string imgUri = "http://nik.bot.nu/img/";
    string imgName;
    Surface nikbotImg
    {
       get
       {
           if(_nikbotImg == null)
           {
               getImage();
               return _nikbotImg;
           }
           return _nikbotImg;
       }
    }
    Surface _nikbotImg = null;
    double[] HSVcolor(byte r, byte g, byte 
    {   double[] a;
       double R = r/255d, G = g/255d, B = b/255d, v, x, f;
       int i;
       x = min(R, G, ;
       v = max(R, G, ;
       if(v == x) return new double[3]{0, 0, v};
       f = (R == x) ? G - B : ((G == x) ? B - R : R - G);
       i = (R == x) ? 3 : ((G == x) ? 5 : 1);
       a = new double[3]{i - f /(v - x), (v - x)/v, v};
       a[0] = a[0]*((2*Math.PI)/6d);
       return a;
    }
    double min(double a,double b,double c)
    {
       a = Math.Min(a,;
       return Math.Min(a,c);
    }
    double max(double a,double b,double c)
    {
       a = Math.Max(a,;
       return Math.Max(a,c);
    }
    float[] calVector(int x,int y)
    {
       ColorBgra p = nikbotImg[x,y];
       float[] vectorrrrr = new float[2]{0,0};
       double[] HSVal = HSVcolor(p.R, p.G, p.;
       double length, direction;
       length = HSVal[1]*HSVal[2]*(Amount1);
       direction = HSVal[0]; // Shud be radians, I hope.
       vectorrrrr[0] = (float)(Math.Sin(direction)*length);
       vectorrrrr[1] = (float)(Math.Cos(direction)*length);
       return vectorrrrr;
    }
    void getImage()
    {
       System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(nikbotBrowseUri);
       string resultPage = string.Empty;
       using (System.Net.HttpWebResponse httpWebResponse = (System.Net.HttpWebResponse)request.GetResponse())
       {
           using (System.IO.Stream responseStream = httpWebResponse.GetResponseStream())
           {
               using (System.IO.StreamReader reader = new System.IO.StreamReader(responseStream))
               {
                   resultPage = reader.ReadToEnd();
               }
           }
       }
       int imgIdx = resultPage.IndexOf("    imgIdx += 28;
       resultPage = resultPage.Remove(0,imgIdx);
       resultPage = resultPage.Remove(resultPage.IndexOf("\""),resultPage.Length-resultPage.IndexOf("\""));
       imgUri += resultPage;
       Image im = null;
       try
       {
           System.Net.HttpWebRequest request2 = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(imgUri);
           request2.Method = "GET";
           request2.Timeout = 10000;
           request2.ProtocolVersion = System.Net.HttpVersion.Version11;
           using (System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request2.GetResponse())
           {
               using (System.IO.Stream responseStream = response.GetResponseStream())
               {
                   im = Image.FromStream(responseStream);
               }
           }
       }
       catch (Exception ex)
       {
           MessageBox.Show("Lols, no image for you:"+ex.Message+Environment.NewLine+imgUri);
           return;
       }
       _nikbotImg = Surface.CopyFromBitmap((Bitmap)im);
    }
    

    Oh and by the way, I think this effect is simply amazing. Just, a personal note.

  8. When someone says something that is falsified by an obvious relation, would it not make sense that they are implying everything but that relation?

    In boolean terms, yes, it is indeed an AND, but I was talking about the quality of actually having free time with relation to the eventuality of it getting fixed, not both qualities with relation to that eventuality.

    On the bright side... while this is completely against the rules, you could make a dummy effect that loads Evan's plugins and gives them a different Assembly version...

  9. It would make sense that as long as the amount of cycles in a loop weren't based on a dynamic variable optimization would unroll it fully.

    Also, I was messing with convolution filter code a few days ago, and I don't exactly remember what I did as far as summing goes.. it was like.. ensure the sum of all elements in the kernel are 1 and then for each nonzero element, do math (summation), and then clamp to byte (either by modulo 256 or by <0 => 0, >255 => 255).

    Anyway, gaussian filter code is fun. Ha.

  10. Here's your "original" source:

    #region UICode
    int Amount1=20;	//[0,100]Tolerance
    int Amount2=1;    //[1,8]Matching pixels
    #endregion
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
       ColorBgra CurrentPixel;
       byte B, G, R;
       int totalB, totalG, totalR;
       int matches;
       double lowerLimitR, lowerLimitG, lowerLimitB;
       double upperLimitR, upperLimitG, upperLimitB;
       double percent, percentInverse;
       ColorBgra[] pixels = new ColorBgra[8]; // Array for containing surrounding pixels. Indices:
       // 0 1 2
       // 3 x 4 (x is the current pixel)
       // 5 6 7
       percent = (100-Amount1)/100;
       percentInverse = 1/percent;
       for (int y = rect.Top; y < rect.Bottom; y++)
       {
           for (int x = rect.Left; x < rect.Right; x++)
           {
               //Set limits:
               lowerLimitR = src[x,y].R * percent;
               lowerLimitG = src[x,y].G * percent;
               lowerLimitB = src[x,y].B * percent;
               upperLimitR = src[x,y].R * percentInverse;
               upperLimitG = src[x,y].G * percentInverse;
               upperLimitB = src[x,y].B * percentInverse;
               //Clear the loop variables
               totalB = 0;
               totalG = 0;
               totalR = 0;
               matches = 0;
               // Get our pixels.  Technically, you could use a kernel here,
               // But it's not worth it for 8 pixels.
               CurrentPixel = src[x,y];
               pixels[0] = src.GetBilinearSampleClamped(x-1, y-1);
               pixels[1] = src.GetBilinearSampleClamped(x  , y-1);
               pixels[2] = src.GetBilinearSampleClamped(x+1, y-1);
               pixels[3] = src.GetBilinearSampleClamped(x-1, y  );
               pixels[4] = src.GetBilinearSampleClamped(x+1, y  );
               pixels[5] = src.GetBilinearSampleClamped(x-1, y+1);
               pixels[6] = src.GetBilinearSampleClamped(x  , y+1);
               pixels[7] = src.GetBilinearSampleClamped(x+1, y+1);
               // Loop through the array and...
               foreach(ColorBgra s in pixels)
               {
                   // Test if the pixel matches,
                   if (s.B < upperLimitB && s.B > lowerLimitB &&
                       s.G < upperLimitG && s.G > lowerLimitG &&
                       s.R < upperLimitR && s.R > lowerLimitR)
                       matches++;
                   // and add to our total that we will average if needed.
                   totalB += s.B;
                   totalG += s.G;
                   totalR += s.R;
               }
               // Test for matches
               if (matches >= Amount2)
                   dst[x,y] = CurrentPixel;
               else // Average if needed.  Using src[,].A so stuff doesn't look goofy if it is antialiased.
                   dst[x,y] = ColorBgra.FromBgra(Int32Util.ClampToByte(totalB/8), Int32Util.ClampToByte(totalG/8), Int32Util.ClampToByte(totalR/8), CurrentPixel.A);
           }
       }
    }
    

    Now, notice the effect of this--it leaves a ring around any noise that is of the noise's intensity averaged with 7 pixels surrounding it. To combat this, you could, for example, make a public (technically static but codelab assumes static) boolean array (outside the Render function so that all instances of Render() can access it) of the dimensions of the selection and set that array[x,y] to true if you found noise, and then make sure that you don't repeat the dst[x,y] = ColorBgra.FromBgra(...) line if any of the surrounding pixels are true.

    Edit:

    Also.. you had wonderful bits about null. Remember always that null and not defined are two different things--you can define a variable as null if its type has support for a null value, however, attempting to access a variable that isn't in memory (such as something outside the bounds of an array) directly will crash the program. GetBilinearSampleClamped saves you any of the mess that is testing for constraints by simply returning the pixel closest to the point you're trying to access that exists on the given surface (think of lines going out from the defined surface that are the same pixel value as where they start on the edge).

  11. This thing does an xor encrypt on the selection from a series of sha512 hashes based on a user-input password. Works fine in codelab, screws up when compiled. I don't feel like putting it in a VS solution to make it work, and the CodeLab output source looks fine.

    Error:

    Full error message: PaintDotNet.WorkerThreadException: Worker thread threw an exception ---> System.NullReferenceException: Object reference not set to an instance of an object.

    at PasswordProtectEffect.PasswordProtectEffectPlugin.Render(Surface dst, Surface src, Rectangle rect)

    at PasswordProtectEffect.PasswordProtectEffectPlugin.OnRender(Rectangle[] rois, Int32 startIndex, Int32 length)

    I can't find it.

    Codelab source:

    #region UICode
    string Amount1 = "Password"; // Password
    #endregion
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
       byte[] hashValue;
       Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
       hashValue = getArray(selection);
       byte B, G, R, A;
       long offset;
       for (int j = rect.Top; j < rect.Bottom; j++)
       {
           for (int i = rect.Left; i < rect.Right; i++)
           {
               offset = 4*(selection.Width*(j-selection.Top)+(i-selection.Left));
               B = (byte)(src[i,j].B ^ hashValue[offset]);
               G = (byte)(src[i,j].G ^ hashValue[offset+1]);
               R = (byte)(src[i,j].R ^ hashValue[offset+2]);
               A = (byte)(src[i,j].A ^ hashValue[offset+3]);
               dst[i,j] = ColorBgra.FromBgra(B, G, R, A);
           }
       }
    }
    private string cachedAmount1 = string.Empty;
    private long arrayLength;
    private byte[] cachedArray;
    public byte[] getArray(Rectangle selection)
    {
       if(Amount1 == cachedAmount1)
       {
           return cachedArray;
       }
       arrayLength = selection.Width*selection.Height*4;
       byte[] ourArray = new byte[arrayLength]; // TAKE THAT, MEMORY!
       byte[] b;
       long iGo = arrayLength/64;
       System.Text.Encoding enc = new System.Text.ASCIIEncoding();
       for(int i = 0; i < iGo; i++)
       {
           System.Security.Cryptography.HashAlgorithm hash = new System.Security.Cryptography.SHA512Managed();
           b = hash.ComputeHash(enc.GetBytes(Amount1+i.ToString()));
           b.CopyTo(ourArray, i*64);
       }
       cachedArray = ourArray;
       cachedAmount1 = Amount1;        
       return ourArray;
    }
    

    And getArray() is fine.

  12. yes, so long as y != selection.Bottom... GetBilinearSampleWrapped/Clamped(x,y) is the easy way out (a bit more processing but not terribly much), a bounds check is easy but repetitive.

    As far as math goes:

    Try finding limits on the average for the given percentage instead of finding the average then testing against limits-- i.e.

    double lowerLimitR = src[,].R * (percent/100);

    double upperLimitR = src[,].R * (1/ (percent/100));

    Note that the values percent/100 and 1/(percent/100) can be calculated in onSetRenderInfo to save processing time. Also note that in the context of Paint.NET tolerance percent would have to be the user input percentage subtracted from 100.

    Additionally, most processing time nowadays gets spent on synchronous memory calls -- allocating thousands of blocks of memory is waaay more time-consuming than calculating some math functions--for example, selection options become slower when a selection becomes complex (undefinable by a simple function) since every pixel location must be stored into memory. Thus, for something such as this (math-heavy), the processing isn't that huge an issue until you start getting to the gaussian blur level, which is on the order of radius^2 *k operations per pixel (k because I really don't remember what the code looked like when I saw it last).

    If you want help writing code, I'd need to know what the result you're trying to achieve is. There's generally more than one way to do something, and your way likely isn't my way ;)

  13. Also, if you want some kind of suggestions on how the math works in The GIMP, you can always download the source ;) Blend modes are in...

    /app/base/base-enums.h:68 is the enum typedef,

    /app/composite/gimp-composite-generic.c is where some math's at.

    Additionally, for the sake of simplicity and being able to expand without getting confused really quickly, make an enum with all your blendmodes in it and a function of two surfaces (left-hand side, right-hand side) that uses the blend mode. It will be far less confusing than a huge switch in the middle of your render function. And also, with that, your drop-down list can just return the struct name instead of a string. Just a suggestion.

  14. Sparked from this and a bit of boredom, I took my first dive into antialiasing.

    Here's the code, comments are few and far between so if you read this ask and I'll clarify. The algorithm sucks. Why? GDI+ renders the whole string at size*16 onto our surface and completely ignores boundary clipping until it actually goes to write the data, meaning in this case it would be much more resource-efficient (although a memory hog) to make one huge surface for it and sample from that. But this is designed around the assumption that I could find a rendering library that doesn't suck.

    Anything blatantly obvious to you, point it out. This is more a coding exercise than anything to me--the results aren't worth publishing as it doesn't implement font hinting whatsoever. (Mainly 'cause I can't access those details through GDI+ anyway.)

    HQFont.zip

  15. The have access to a "destination surface" that gets transposed to the current layer's data, and they have access to most if not all (?) of the C# .NET system functions. There have been several plugins that actually use GDI to draw things to the canvas, such as boltbait's polygon/stars plugin.

    Out of boredom, I'm working on a plugin that does font rendering, except with more awesome sampling!

    On-topic: Yes, it's definitely possible ;)

  16. That is what I don't understand. You seem to feel strongly about it though, would you care to explain why is that the case?

    Rendering to subpixels is not advised at all for graphics processing -- it creates an image that when printed to a medium or scaled to a higher or lower resolution has those subpixel colors visible: i.e. it is only meant for LCD or CRT media which actually have subpixels.

×
×
  • Create New...