Jump to content

Illnab1024

Members
  • Posts

    1,178
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by Illnab1024

  1. 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. 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 << 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. 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. >.> From experience, that has no bearing on whether or not he has time to deal with it at the moment.
  10. But what I do know is I found a math library from 2002 in C# with a nice little FFT algorithm in there...
  11. Pixels that don't exist should simply not be a part of the signal. If only I had a napkin to draw a poor 3D graph of a signal.. Oh, wait, "Song of Solomon" by Animals as Leaders spectrogram: The places of no signal would have no influence in the calculation of the waveform, were we to calculate the waveform, right? I dunno.
  12. 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.
  13. Ultimately to optimize the algorithm you would have to do the matching test for the current pixel AND the 8 pixels surrounding, figure out which pixel had the least matches surrounding it, and do the noise removal (average of the pixels surrounding it) on that pixel and not any of the others. What I originally proposed is more or less stupid in that it only half-works.
  14. Oh, right... I had thought about that halfway through before dismissing it-- CodeLab defines the default value for Amount1 in OnCreateConfigUI or whatnot as "" == string.Empty.. hooray for codelab?
  15. Have you saved the PNG from Paint.NET? Interlaced format or high bit depth may be an issue.
  16. 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).
  17. 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.
  18. 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
  19. Tha carpet don't math tha dra-- I mean the avatar don't match the sig. Scuse me. Also, 3337 posts.. tripleet?
  20. 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.
  21. 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
  22. 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
  23. Correct. If you really want ClearType/FreeType rendering, I suggest a plug-in to do so. I highly doubt it ever being built into Paint.NET...
  24. 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.
  25. Sorry, I was tired -- better word choice would have been "The Effects API isn't entirely stupid."
×
×
  • Create New...