elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Tutorial básico de Quickjs


  Mostrar Mensajes
Páginas: 1 2 3 4 [5] 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... 238
41  Programación / .NET (C#, VB.NET, ASP) / Re: Librería de códigos C# (Compartan aquí sus códigos) en: 22 Octubre 2018, 18:59 pm
BatchedCoroutines: Iterar coroutinas una a una

Queréis que vuestras ConcurrentQueues se ejecuten una por una? No problemo, con esta implementación to hard-codeada lo conseguiréis:

Código
  1. using GTAMapper.Extensions.Threading;
  2. using System;
  3. using System.Collections;
  4. using UnityEngine;
  5.  
  6. namespace GTAMapper.Extensions
  7. {
  8.    public static class BatchedCoroutines
  9.    {
  10.        public static IEnumerator BatchCoroutines(
  11.            MonoBehaviour monoBehaviour,
  12.            Action finish,
  13.            Func<int, bool>[] waitUntil = null,
  14.            params Tuple<Action<object>, ConcurrentQueuedCoroutines<object>>[] tuple) // Tuple<Action<T>, ConcurrentQueuedCoroutines<T>> || dynamic
  15.                                                                                      // Fix for: https://stackoverflow.com/questions/15417174/using-the-params-keyword-for-generic-parameters-in-c-sharp
  16.        {
  17.            int i = 0;
  18.  
  19.            foreach (var val in tuple)
  20.            {
  21.                if (waitUntil != null && waitUntil[i] != null)
  22.                    yield return new WaitUntil(() => waitUntil[i](i));
  23.  
  24.                yield return val.Item2.GetCoroutine(monoBehaviour, val.Item1);
  25.  
  26.                ++i;
  27.            }
  28.  
  29.            finish?.Invoke();
  30.        }
  31.    }
  32. }

Un ejemplo de implementación:

Código
  1.        protected ConcurrentQueuedCoroutines<object> debuggingCoroutine = new ConcurrentQueuedCoroutines<object>(),
  2.                                                     colorCoroutine = new ConcurrentQueuedCoroutines<object>();
  3.  
  4. namespace GTAMapper.Core {
  5.    public class Program : MonoBehaviour {
  6.        public void Start() {
  7.        StartCoroutine(BatchedCoroutines.BatchCoroutines(
  8.                this,
  9.                () => areCoroutinesCollected = true,
  10.                F.GetFuncs(null, (_ii) => debuggingCoroutine.Queue.Count > 0),
  11.                new Tuple<Action<object>, ConcurrentQueuedCoroutines<object>>((obj) =>
  12.                {
  13.                    Tuple<int, Color> tuple = (Tuple<int, Color>)obj;
  14.  
  15.                    int i = tuple.Item1,
  16.                            _x = i % width,
  17.                            _y = i / width;
  18.  
  19.                    UnityEngine.Color actualColor = debugTexture.GetPixel(_x, _y),
  20.                                          mixedColor = UnityEngine.Color.Lerp(actualColor, tuple.Item2, .5f);
  21.  
  22.                    if (actualColor != mixedColor)
  23.                    {
  24.                        debugTexture.SetPixel(_x, _y, mixedColor);
  25.                        debugTexture.Apply();
  26.                    }
  27.                }, colorCoroutine),
  28.                new Tuple<Action<object>, ConcurrentQueuedCoroutines<object>>((obj) =>
  29.                {
  30.                    Color[] colors = (Color[])obj;
  31.  
  32.                    debugTexture.SetPixels32(colors.CastBack().ToArray());
  33.                    debugTexture.Apply();
  34.                }, debuggingCoroutine)));
  35.          }
  36.     }
  37. }

Básicamente, en las dos Queues vamos haciendo Enqueue donde sea necesario (en otro thread).

Cuando todo haya acabado, desde el primer thread, llamamos a que se ejecute lo que acabo de mostrar.

Y en mi caso por ejemplo, esto sirve para mostrar pixel a pixel donde se ha iterado una imagen.

Y lo siguiente que ocurre es que la imagen se rellena con el algoritmo de flood-fill que enseñe el otro día. (Básicamente, para saber si se ha hecho bien)

Nota: Si queréis el código de GetFuncs es este:

Código
  1. using System;
  2.  
  3. public static class F {
  4.        public static Func<int, bool>[] GetFuncs(params Func<int, bool>[] waitUntil)
  5.        {
  6.            return waitUntil;
  7.        }
  8. }
42  Programación / .NET (C#, VB.NET, ASP) / Re: Librería de códigos C# (Compartan aquí sus códigos) en: 22 Octubre 2018, 18:55 pm
ConcurrentQueuedCoroutines: Implementación Thread-Safe de ConcurrentQueues dentro de Coroutinas

La idea de esta utilidad es que cuando tu almacenas items desde otro thread, puedas acceder desde el thread principal.

Mezclando esta idea, con coroutinas, que básicamente, es un sistema del prehistorico que implementó Unity en su momento, que funciona de la siguiente forma, se crea un IEnumerator (con yields), el cual cada MoveNext se ejecuta en cada frame (yield return null) o cuando el programador especifique (yield return new WaitForSeconds(3) equivalente a Thread.Sleep(3000)) (por tal de no atorar el Main Thread, sí, Unity se ejecuta en un solo hilo).

Entonces, teniendo estas 2 cosas, porque no hacer Dequeue en cada MoveNext?

Código
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6.  
  7. namespace GTAMapper.Extensions.Threading
  8. {
  9.    public class ConcurrentQueuedCoroutines<T>
  10.    {
  11.        private List<Coroutine> coroutines;
  12.        private Coroutine coroutine;
  13.        private MonoBehaviour Mono;
  14.  
  15.        public ConcurrentQueue<object> Queue { get; private set; }
  16.  
  17.        public Action<T> Action { get; private set; }
  18.        public bool Debugging { get; set; }
  19.        public float SecondsToWait { get; private set; }
  20.  
  21.        private ConcurrentQueuedCoroutines()
  22.        {
  23.        }
  24.  
  25.        public ConcurrentQueuedCoroutines(float secondsToWait = -1)
  26.        {
  27.            Queue = new ConcurrentQueue<object>();
  28.            coroutines = new List<Coroutine>();
  29.            SecondsToWait = secondsToWait;
  30.        }
  31.  
  32.        public Coroutine StartCoroutine(MonoBehaviour monoBehaviour, Action<T> action)
  33.        {
  34.            coroutines.Add(monoBehaviour.StartCoroutine(InternalCoroutine()));
  35.            Mono = monoBehaviour;
  36.            Action = action;
  37.  
  38.            return coroutine;
  39.        }
  40.  
  41.        public Coroutine StartCoroutineOnce(MonoBehaviour monoBehaviour, Action<T> action)
  42.        {
  43.            if (Debugging)
  44.                Debug.Log("Starting dequeing!");
  45.  
  46.            if (coroutine == null)
  47.            {
  48.                coroutine = monoBehaviour.StartCoroutine(InternalCoroutine());
  49.                Mono = monoBehaviour;
  50.                Action = action;
  51.            }
  52.  
  53.            return coroutine;
  54.        }
  55.  
  56.        public void StopCoroutine()
  57.        {
  58.            if (coroutine != null && Mono != null)
  59.                Mono.StopCoroutine(coroutine);
  60.        }
  61.  
  62.        public void StopAllCoroutines()
  63.        {
  64.            if (Mono != null && coroutines != null && coroutines.Count > 0)
  65.                coroutines.ForEach((c) => Mono.StopCoroutine(c));
  66.        }
  67.  
  68.        public IEnumerator GetCoroutine(MonoBehaviour mono, Action<T> action)
  69.        {
  70.            Mono = mono;
  71.            Action = action;
  72.            return InternalCoroutine();
  73.        }
  74.  
  75.        private IEnumerator InternalCoroutine()
  76.        {
  77.            if (Debugging)
  78.                Debug.Log($"Starting dequeing {Queue.Count} values!");
  79.  
  80.            while (Queue.Count > 0)
  81.            {
  82.                object value = null;
  83.                bool dequeued = Queue.TryDequeue(out value);
  84.  
  85.                if (!dequeued)
  86.                {
  87.                    if (SecondsToWait == -1)
  88.                        yield return new WaitForEndOfFrame();
  89.                    else
  90.                        yield return new WaitForSeconds(SecondsToWait);
  91.  
  92.                    continue;
  93.                }
  94.  
  95.                Action?.Invoke((T)value);
  96.  
  97.                if (SecondsToWait == -1)
  98.                    yield return new WaitForEndOfFrame();
  99.                else
  100.                    yield return new WaitForSeconds(SecondsToWait);
  101.            }
  102.        }
  103.    }
  104. }

Y diréis, y para que sirve esta chorra, pues por ejemplo, lo que se puede conseguir, es visualizar como se recorre una textura.





En el próximo post o enseñaré un caso de uso.
43  Programación / .NET (C#, VB.NET, ASP) / Re: Librería de códigos C# (Compartan aquí sus códigos) en: 22 Octubre 2018, 18:48 pm
Thread Safe Bool: Implementación Thread-Safe de bools

El otro día me pasaba que al asignar una variable que estaba declarada en ambito de la clase desde otro thread, al leerla desde otro thread no me devolvía el resultado esperado, por eso os traigo esta utilidad.

Código
  1. using System.Threading;
  2.  
  3. namespace GTAMapper.Extensions.Threading
  4. {
  5.    /// <summary>
  6.    /// Thread safe enter once into a code block:
  7.    /// the first call to CheckAndSetFirstCall returns always true,
  8.    /// all subsequent call return false.
  9.    /// </summary>
  10.    public class ThreadSafeBool
  11.    {
  12.        private static int NOTCALLED = 0,
  13.                           CALLED = 1;
  14.  
  15.        private int _state = NOTCALLED;
  16.  
  17.        /// <summary>Explicit call to check and set if this is the first call</summary>
  18.        public bool Value
  19.        {
  20.            get
  21.            {
  22.                return Interlocked.Exchange(ref _state, CALLED) == NOTCALLED;
  23.            }
  24.        }
  25.  
  26.        /// <summary>usually init by false</summary>
  27.        public static implicit operator ThreadSafeBool(bool called)
  28.        {
  29.            return new ThreadSafeBool() { _state = called ? CALLED : NOTCALLED };
  30.        }
  31.  
  32.        public static implicit operator bool(ThreadSafeBool cast)
  33.        {
  34.            if (cast == null)
  35.                return false;
  36.  
  37.            return cast.Value;
  38.        }
  39.    }
  40. }

Extraído de: https://www.codeproject.com/Tips/375559/Implement-Thread-Safe-One-shot-Bool-Flag-with-Inte
44  Programación / .NET (C#, VB.NET, ASP) / Re: Interactuar con formulario Web !! en: 21 Octubre 2018, 16:38 pm


Muy fan. :xD :xD :xD
45  Programación / .NET (C#, VB.NET, ASP) / Re: Error en Codigo Minusculas a Mayusculas C# en: 21 Octubre 2018, 16:36 pm
Básicamente, esa "j" no pinta nada ahí :rolleyes:
46  Programación / Programación General / Re: Tengo un error en C# en: 21 Octubre 2018, 06:50 am
En vez de usar =, usa Substring(...).Replace(..., ...)

Con esto ya valdría:

Código
  1. etiqueta = etiqueta.Replace(equiteta.Substring(0, 1), banco_palabras[numero_palabra].Substring(0, 1));

Básicamente, estás asignando un valor a una función (método del tipo nativo string) cosa que no se puede.
47  Programación / .NET (C#, VB.NET, ASP) / Re: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets) en: 19 Octubre 2018, 08:50 am
Te cuento de forma rápida lo que pretendo.

En el mapa hay x cantidad de colores predefinidos, tantos como enumeraciones tengas.

En este caso: Building, Asphalt, LightPavement, Pavement, Grass, DryGrass, Sand, Dirt, Mud, Water, Rails, Tunnel, BadCodingDark, BadCodingLight, BuildingLight, son 15.

Lo que pasa con esa imagen es hay micro variaciones de color. Quizás hay 100 tonos distintos de Grass con variaciones de pares en la escala RGB (es decir, nunca te vas a encontrar tonos que tengan un (0, 241, 0, 255), para el caso de un verde), y quizás con un rango total de ±10. Es decir, 5 posibilidades entre los 3 componentes: 5^3=125 tonos de verde.

Estos tonos son inperceptibles al ojo humano. Quizás se hizo por algun motivo (ya le metere saturación para ver si sigue algún patrón o algo. Estos de Rockstar te meten easter eggs hasta en los mapas).

Entonces lo que hago primero es iterar todos los colores. Mientras itero, voy comparando pixel a pixel, con los colores definidos en el diccionario, pero no los comparo literalmente (==), si no que saco un porcentaje de similitud. Y estás microvariaciones, como digo, como máximo su diferencia puede ser de ±10.

El porcentaje (con el mayor offset posible) sera en este caso: (255, 255, 255, 255) --> (245, 245, 245, 255) = 0.9609375 = 96,1% (un 3,9% de diferencia), vamos bien, ya que yo comparo con hasta un 10%, es decir una variación de ±25, es decir 25/2=12,5^3=1953 posibilidades, imagina.

Teniendo ese porcentaje, pues ya al debugear lo unico que hago es agrupar todos los colores (antes lo que hacia era posterizarlos, pero no me moló la idea, por eso hay un método de posterización) y sumar sus respectivas agrupaciones, pasamos de +1600 colores a unos 15 o menos (algunos no los detecta bien, otros directamente, no están presentes).

Un saludo.
48  Foros Generales / Foro Libre / Re: un gran theft auto en España ? en: 18 Octubre 2018, 20:29 pm
Pon la fuente y lo sabremos. ;D
49  Programación / .NET (C#, VB.NET, ASP) / Re: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets) en: 18 Octubre 2018, 19:51 pm
Leer los pixeles de una imagen y contarlos siguiendo un diccionario estático de colores

Básicamente, la funcionalidad que tiene esto, es definir un diccionario estático de colores (con una enumeración donde se especifiquen los apartados que hay (si fuese necesario)), se itera todo pixel a pixel, y cada color se compara con la muestra sacando el porcentaje de similitud, si la similitud es del 90% o mayor se da por hecho que ese color pertenece a x enumeración del diccionario.

Para más INRI, le he añadido la utilidad de que se pueda leer desde Internet, lo que cambia si queremos leerlo desde el disco es que tenemos que llamar únicamente a System.IO.File.ReadAllBytes.

Aquí el codigo: https://github.com/z3nth10n/GTA-ColorCount/blob/master/CountColors/Program.cs

Nota: Tiene una versión compilada (para el que lo quiera probar).
Nota2: No está optimizado (memory leak & no se ha mirado si se puede optimizar desde el punto de vista de procesamiento de cpu), asi que, si se elige guardar puede llegar a ocupar 1GB en memoria (la imagen tiene 7000x5000, en bruto son unos 140MB (7000x5000x4 (ARGB)) en memoria.)

Codigo en VB.NET:

Código
  1. Imports System
  2. Imports System.Net
  3. Imports System.Drawing
  4. Imports System.Drawing.Imaging
  5. Imports System.Runtime.InteropServices
  6. Imports System.IO
  7. Imports System.Collections.Generic
  8. Imports System.Linq
  9. Imports Color = zenthion.Color
  10. Imports System.Diagnostics
  11. Imports System.Reflection
  12.  
  13. Public Enum GroundType
  14. Building
  15. Asphalt
  16. LightPavement
  17. Pavement
  18. Grass
  19. DryGrass
  20. Sand
  21. Dirt
  22. Mud
  23. Water
  24. Rails
  25. Tunnel
  26. BadCodingDark
  27. BadCodingLight
  28. BuildingLight
  29. End Enum
  30.  
  31. Public Enum OrderingType
  32. ByColor
  33. [ByVal]
  34. ByName
  35. End Enum
  36.  
  37. Public Class Program
  38. Public Shared colorToCompare As Color = Color.white
  39. Public Shared orderingType As OrderingType = OrderingType.ByVal
  40. Public Shared isDarkened As Boolean = False, isPosterized As Boolean = False, isOrdered As Boolean = True, saveTexture As Boolean = False
  41.  
  42. Private Shared ReadOnly Property SavingPath() As String
  43. Get
  44. Return Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "texture.png")
  45. End Get
  46. End Property
  47.  
  48. Public Shared Sub Main()
  49. Dim imageBytes() As Byte = Nothing
  50.  
  51. ' OriginalTexture: http://i.imgur.com/g9fRYbm.png
  52. ' TextureColor: https://image.ibb.co/dP3Nvf/texture-Color.png
  53.  
  54. Dim url As String = "https://image.ibb.co/dP3Nvf/texture-Color.png"
  55.  
  56. Using webClient = New WebClient()
  57. imageBytes = webClient.DownloadData(url)
  58. End Using
  59.  
  60. Dim sw As Stopwatch = Stopwatch.StartNew()
  61.  
  62. isDarkened = url = "https://image.ibb.co/dP3Nvf/texture-Color.png"
  63.  
  64.  
  65. Dim colors As IEnumerable(Of Color) = Nothing
  66.  
  67. Dim bitmap As Bitmap = Nothing
  68. Dim dict = GetColorCount(bitmap, imageBytes, (If(isDarkened, F.DarkenedMapColors, F.mapColors)).Values.AsEnumerable(), colors, isPosterized)
  69.  
  70. Console.WriteLine(DebugDict(dict))
  71. Console.WriteLine("Num of colors: {0}", dict.Keys.Count)
  72.  
  73. If saveTexture Then
  74. colors.ToArray().SaveBitmap(7000, 5000, SavingPath)
  75. End If
  76.  
  77. bitmap.Dispose()
  78. sw.Stop()
  79.  
  80. Console.WriteLine("Ellapsed: {0} s", (sw.ElapsedMilliseconds / 1000F).ToString("F2"))
  81.  
  82. Console.Read()
  83. End Sub
  84.  
  85. Private Shared Function DebugDict(ByVal dict As Dictionary(Of Color, Integer)) As String
  86. Dim num = dict.Select(Function(x) New With {Key .Name = x.Key.GetGroundType(isPosterized), Key .Similarity = x.Key.ColorSimilaryPerc(colorToCompare), Key .Val = x.Value, Key .ColR = x.Key.r, Key .ColG = x.Key.g, Key .ColB = x.Key.b}).GroupBy(Function(x) x.Name).Select(Function(x) New With {Key .Name = x.Key, Key .Similarity = x.Average(Function(y) y.Similarity), Key .Val = x.Sum(Function(y) y.Val), Key .Col = New Color(CByte(x.Average(Function(y) y.ColR)), CByte(x.Average(Function(y) y.ColG)), CByte(x.Average(Function(y) y.ColB)))})
  87.  
  88. Dim num1 = num
  89.  
  90. If isOrdered Then
  91. num1 = If(orderingType = OrderingType.ByName, num.OrderBy(Function(x) x.Name), num.OrderByDescending(Function(x)If(orderingType = OrderingType.ByColor, x.Col.ColorSimilaryPerc(colorToCompare), x.Val)))
  92. End If
  93.  
  94. Dim num2 = num1.Select(Function(x) String.Format("[{2}] {0}: {1}", x.Name, x.Val.ToString("N0"), x.Similarity.ToString("F2")))
  95.  
  96. Return String.Join(Environment.NewLine, num2)
  97. End Function
  98.  
  99. Public Shared Function GetColorCount(ByRef image As Bitmap, ByVal arr() As Byte, ByVal colors As IEnumerable(Of Color), <System.Runtime.InteropServices.Out()> ByRef imageColors As IEnumerable(Of Color), Optional ByVal isPosterized As Boolean = False) As Dictionary(Of Color, Integer)
  100. Dim count As New Dictionary(Of Color, Integer)()
  101.  
  102. Using stream As Stream = New MemoryStream(arr)
  103. image = CType(System.Drawing.Image.FromStream(stream), Bitmap)
  104. End Using
  105.  
  106. 'Color[]
  107. imageColors = image.ToColor() '.ToArray();
  108.  
  109. 'Parallel.ForEach(Partitioner.Create(imageColors, true).GetOrderableDynamicPartitions(), colorItem =>
  110. For Each colorItem As Color In imageColors
  111. ' .Value
  112. Dim thresholedColor As Color = If((Not isPosterized), colorItem.GetSimilarColor(colors), colorItem) '.RoundColorOff(65);
  113.  
  114. If Not count.ContainsKey(thresholedColor) Then
  115. count.Add(thresholedColor, 1)
  116. Else
  117. count(thresholedColor) += 1
  118. End If
  119. Next colorItem
  120.  
  121. Dim posterizedColors As Dictionary(Of Color, Integer) = If(isPosterized, New Dictionary(Of Color, Integer)(), count)
  122.  
  123. If isPosterized Then
  124. For Each kv In count
  125. Dim pColor As Color = kv.Key.Posterize(16)
  126.  
  127. If Not posterizedColors.ContainsKey(pColor) Then
  128. posterizedColors.Add(pColor, kv.Value)
  129. Else
  130. posterizedColors(pColor) += kv.Value
  131. End If
  132. Next kv
  133. End If
  134.  
  135. Return posterizedColors
  136. End Function
  137. End Class
  138.  
  139. Public Module F
  140. Public mapColors As New Dictionary(Of GroundType, Color)() From {
  141. { GroundType.Building, Color.white },
  142. { GroundType.Asphalt, Color.black },
  143. { GroundType.LightPavement, New Color(206, 207, 206, 255) },
  144. { GroundType.Pavement, New Color(156, 154, 156, 255) },
  145. { GroundType.Grass, New Color(57, 107, 41, 255) },
  146. { GroundType.DryGrass, New Color(123, 148, 57, 255) },
  147. { GroundType.Sand, New Color(231, 190, 107, 255) },
  148. { GroundType.Dirt, New Color(156, 134, 115, 255) },
  149. { GroundType.Mud, New Color(123, 101, 90, 255) },
  150. { GroundType.Water, New Color(115, 138, 173, 255) },
  151. { GroundType.Rails, New Color(74, 4, 0, 255) },
  152. { GroundType.Tunnel, New Color(107, 105, 99, 255) },
  153. { GroundType.BadCodingDark, New Color(127, 0, 0, 255) },
  154. { GroundType.BadCodingLight, New Color(255, 127, 127, 255) }
  155. }
  156.  
  157. Private _darkened As Dictionary(Of GroundType, Color)
  158.  
  159. Public ReadOnly Property DarkenedMapColors() As Dictionary(Of GroundType, Color)
  160. Get
  161. If _darkened Is Nothing Then
  162. _darkened = GetDarkenedMapColors()
  163. End If
  164.  
  165. Return _darkened
  166. End Get
  167. End Property
  168.  
  169. Private BmpStride As Integer = 0
  170.  
  171. Private Function GetDarkenedMapColors() As Dictionary(Of GroundType, Color)
  172. ' We will take the last 2 elements
  173.  
  174. Dim last2 = mapColors.Skip(mapColors.Count - 2)
  175.  
  176. Dim exceptLast2 = mapColors.Take(mapColors.Count - 2)
  177.  
  178. Dim dict As New Dictionary(Of GroundType, Color)()
  179.  
  180. dict.AddRange(exceptLast2.Select(Function(x) New KeyValuePair(Of GroundType, Color)(x.Key, x.Value.Lerp(Color.black,.5F))))
  181.  
  182. dict.Add(GroundType.BuildingLight, Color.white)
  183.  
  184. dict.AddRange(last2)
  185.  
  186. Return dict
  187. End Function
  188.  
  189. <System.Runtime.CompilerServices.Extension> _
  190. Public Sub AddRange(Of TKey, TValue)(ByVal dic As Dictionary(Of TKey, TValue), ByVal dicToAdd As IEnumerable(Of KeyValuePair(Of TKey, TValue)))
  191. dicToAdd.ForEach(Sub(x) dic.Add(x.Key, x.Value))
  192. End Sub
  193.  
  194. <System.Runtime.CompilerServices.Extension> _
  195. Public Sub ForEach(Of T)(ByVal source As IEnumerable(Of T), ByVal action As Action(Of T))
  196. For Each item In source
  197. action(item)
  198. Next item
  199. End Sub
  200.  
  201. 'INSTANT VB NOTE: The parameter color was renamed since it may cause conflicts with calls to static members of the user-defined type with this name:
  202. <System.Runtime.CompilerServices.Extension> _
  203. Public Function Posterize(ByVal color_Renamed As Color, ByVal level As Byte) As Color
  204. Dim r As Byte = 0, g As Byte = 0, b As Byte = 0
  205.  
  206. Dim value As Double = color_Renamed.r \ 255.0
  207. value *= level - 1
  208. value = Math.Round(value)
  209. value /= level - 1
  210.  
  211. r = CByte(value * 255)
  212. value = color_Renamed.g \ 255.0
  213. value *= level - 1
  214. value = Math.Round(value)
  215. value /= level - 1
  216.  
  217. g = CByte(value * 255)
  218. value = color_Renamed.b \ 255.0
  219. value *= level - 1
  220. value = Math.Round(value)
  221. value /= level - 1
  222.  
  223. b = CByte(value * 255)
  224.  
  225. Return New Color(r, g, b, 255)
  226. End Function
  227.  
  228. <System.Runtime.CompilerServices.Extension> _
  229. Public Function GetGroundType(ByVal c As Color, ByVal isPosterized As Boolean) As String
  230. Dim mapToUse = If(Program.isDarkened, DarkenedMapColors, mapColors)
  231. Dim kvColor As KeyValuePair(Of GroundType, Color) = mapToUse.FirstOrDefault(Function(x)If(isPosterized, x.Value.ColorSimilaryPerc(c) >.9F, x.Value = c))
  232.  
  233. If Not kvColor.Equals(Nothing) Then
  234. Return kvColor.Key.ToString()
  235. Else
  236. Return c.ToString()
  237. End If
  238. End Function
  239.  
  240. <System.Runtime.CompilerServices.Extension> _
  241. Public Function GetSimilarColor(ByVal c1 As Color, ByVal cs As IEnumerable(Of Color)) As Color
  242. Return cs.OrderBy(Function(x) x.ColorThreshold(c1)).FirstOrDefault()
  243. End Function
  244.  
  245. <System.Runtime.CompilerServices.Extension> _
  246. Public Function ColorThreshold(ByVal c1 As Color, ByVal c2 As Color) As Integer
  247. Return (Math.Abs(c1.r - c2.r) + Math.Abs(c1.g - c2.g) + Math.Abs(c1.b - c2.b))
  248. End Function
  249.  
  250. <System.Runtime.CompilerServices.Extension> _
  251. Public Function ColorSimilaryPerc(ByVal a As Color, ByVal b As Color) As Single
  252. Return 1F - (a.ColorThreshold(b) / (256F * 3))
  253. End Function
  254.  
  255. <System.Runtime.CompilerServices.Extension> _
  256. Public Function RoundColorOff(ByVal c As Color, Optional ByVal roundTo As Byte = 5) As Color
  257. Return New Color(c.r.RoundOff(roundTo), c.g.RoundOff(roundTo), c.b.RoundOff(roundTo), 255)
  258. End Function
  259.  
  260. <System.Runtime.CompilerServices.Extension> _
  261. Public Function RoundOff(ByVal i As Byte, Optional ByVal roundTo As Byte = 5) As Byte
  262. Return CByte(CByte(Math.Ceiling(i / CDbl(roundTo))) * roundTo)
  263. End Function
  264.  
  265. <System.Runtime.CompilerServices.Extension> _
  266. Public Iterator Function ToColor(ByVal bmp As Bitmap) As IEnumerable(Of Color)
  267. Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
  268. Dim bmpData As BitmapData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
  269.  
  270. Dim ptr As IntPtr = bmpData.Scan0
  271.  
  272. Dim bytes As Integer = bmpData.Stride * bmp.Height
  273. Dim rgbValues(bytes - 1) As Byte
  274.  
  275. ' Copy the RGB values into the array.
  276. Marshal.Copy(ptr, rgbValues, 0, bytes)
  277.  
  278. BmpStride = bmpData.Stride
  279.  
  280. For column As Integer = 0 To bmpData.Height - 1
  281. For row As Integer = 0 To bmpData.Width - 1
  282. ' Little endian
  283. Dim b As Byte = CByte(rgbValues((column * BmpStride) + (row * 4)))
  284. Dim g As Byte = CByte(rgbValues((column * BmpStride) + (row * 4) + 1))
  285. Dim r As Byte = CByte(rgbValues((column * BmpStride) + (row * 4) + 2))
  286.  
  287. Yield New Color(r, g, b, 255)
  288. Next row
  289. Next column
  290.  
  291. ' Unlock the bits.
  292. bmp.UnlockBits(bmpData)
  293. End Function
  294.  
  295. <System.Runtime.CompilerServices.Extension> _
  296. Public Sub SaveBitmap(ByVal bmp() As Color, ByVal width As Integer, ByVal height As Integer, ByVal path As String)
  297. Dim stride As Integer = BmpStride
  298. Dim rgbValues((BmpStride * height) - 1) As Byte
  299.  
  300. For column As Integer = 0 To height - 1
  301. For row As Integer = 0 To width - 1
  302. Dim i As Integer = Pn(row, column, width)
  303.  
  304. ' Little endian
  305. rgbValues((column * BmpStride) + (row * 4)) = bmp(i).b
  306. rgbValues((column * BmpStride) + (row * 4) + 1) = bmp(i).g
  307. rgbValues((column * BmpStride) + (row * 4) + 2) = bmp(i).r
  308. rgbValues((column * BmpStride) + (row * 4) + 3) = bmp(i).a
  309. Next row
  310. Next column
  311.  
  312. Using image As New Bitmap(width, height, width * 4, PixelFormat.Format32bppArgb, Marshal.UnsafeAddrOfPinnedArrayElement(rgbValues, 0))
  313. image.Save(path)
  314. End Using
  315. End Sub
  316.  
  317. Public Function Pn(ByVal x As Integer, ByVal y As Integer, ByVal w As Integer) As Integer
  318. Return x + (y * w)
  319. End Function
  320. End Module
  321.  
  322. Public Module Mathf
  323. <System.Runtime.CompilerServices.Extension> _
  324. Public Function Clamp(Of T As IComparable(Of T))(ByVal val As T, ByVal min As T, ByVal max As T) As T
  325. If val.CompareTo(min) < 0 Then
  326. Return min
  327. ElseIf val.CompareTo(max) > 0 Then
  328. Return max
  329. Else
  330. Return val
  331. End If
  332. End Function
  333.  
  334. ' Interpolates between /a/ and /b/ by /t/. /t/ is clamped between 0 and 1.
  335. Public Function Lerp(ByVal a As Single, ByVal b As Single, ByVal t As Single) As Single
  336. Return a + (b - a) * Clamp01(t)
  337. End Function
  338.  
  339. ' Clamps value between 0 and 1 and returns value
  340. Public Function Clamp01(ByVal value As Single) As Single
  341. If value < 0F Then
  342. Return 0F
  343. ElseIf value > 1F Then
  344. Return 1F
  345. Else
  346. Return value
  347. End If
  348. End Function
  349. End Module
  350.  
  351. Namespace zenthion
  352. ''' <summary>
  353. ''' Struct Color
  354. ''' </summary>
  355. ''' <seealso cref="System.ICloneable" />
  356. <Serializable>
  357. Public Structure Color
  358. Implements ICloneable
  359.  
  360. ''' <summary>
  361. ''' Clones this instance.
  362. ''' </summary>
  363. ''' <returns>System.Object.</returns>
  364. Public Function Clone() As Object Implements ICloneable.Clone
  365. Return MemberwiseClone()
  366. End Function
  367.  
  368. ''' <summary>
  369. ''' The r
  370. ''' </summary>
  371. Public r, g, b, a As Byte
  372.  
  373. ''' <summary>
  374. ''' Gets the white.
  375. ''' </summary>
  376. ''' <value>The white.</value>
  377. Public Shared ReadOnly Property white() As Color
  378. Get
  379. Return New Color(255, 255, 255)
  380. End Get
  381. End Property
  382.  
  383. ''' <summary>
  384. ''' Gets the red.
  385. ''' </summary>
  386. ''' <value>The red.</value>
  387. Public Shared ReadOnly Property red() As Color
  388. Get
  389. Return New Color(255, 0, 0)
  390. End Get
  391. End Property
  392.  
  393. ''' <summary>
  394. ''' Gets the green.
  395. ''' </summary>
  396. ''' <value>The green.</value>
  397. Public Shared ReadOnly Property green() As Color
  398. Get
  399. Return New Color(0, 255, 0)
  400. End Get
  401. End Property
  402.  
  403. ''' <summary>
  404. ''' Gets the blue.
  405. ''' </summary>
  406. ''' <value>The blue.</value>
  407. Public Shared ReadOnly Property blue() As Color
  408. Get
  409. Return New Color(0, 0, 255)
  410. End Get
  411. End Property
  412.  
  413. ''' <summary>
  414. ''' Gets the yellow.
  415. ''' </summary>
  416. ''' <value>The yellow.</value>
  417. Public Shared ReadOnly Property yellow() As Color
  418. Get
  419. Return New Color(255, 255, 0)
  420. End Get
  421. End Property
  422.  
  423. ''' <summary>
  424. ''' Gets the gray.
  425. ''' </summary>
  426. ''' <value>The gray.</value>
  427. Public Shared ReadOnly Property gray() As Color
  428. Get
  429. Return New Color(128, 128, 128)
  430. End Get
  431. End Property
  432.  
  433. ''' <summary>
  434. ''' Gets the black.
  435. ''' </summary>
  436. ''' <value>The black.</value>
  437. Public Shared ReadOnly Property black() As Color
  438. Get
  439. Return New Color(0, 0, 0)
  440. End Get
  441. End Property
  442.  
  443. ''' <summary>
  444. ''' Gets the transparent.
  445. ''' </summary>
  446. ''' <value>The transparent.</value>
  447. Public Shared ReadOnly Property transparent() As Color
  448. Get
  449. Return New Color(0, 0, 0, 0)
  450. End Get
  451. End Property
  452.  
  453. ''' <summary>
  454. ''' Initializes a new instance of the <see cref="Color"/> struct.
  455. ''' </summary>
  456. ''' <param name="r">The r.</param>
  457. ''' <param name="g">The g.</param>
  458. ''' <param name="b">The b.</param>
  459. Public Sub New(ByVal r As Byte, ByVal g As Byte, ByVal b As Byte)
  460. Me.r = r
  461. Me.g = g
  462. Me.b = b
  463. a = Byte.MaxValue
  464. End Sub
  465.  
  466. ''' <summary>
  467. ''' Initializes a new instance of the <see cref="Color"/> struct.
  468. ''' </summary>
  469. ''' <param name="r">The r.</param>
  470. ''' <param name="g">The g.</param>
  471. ''' <param name="b">The b.</param>
  472. ''' <param name="a">a.</param>
  473. Public Sub New(ByVal r As Byte, ByVal g As Byte, ByVal b As Byte, ByVal a As Byte)
  474. Me.r = r
  475. Me.g = g
  476. Me.b = b
  477. Me.a = a
  478. End Sub
  479.  
  480. ''' <summary>
  481. ''' Implements the ==.
  482. ''' </summary>
  483. ''' <param name="c1">The c1.</param>
  484. ''' <param name="c2">The c2.</param>
  485. ''' <returns>The result of the operator.</returns>
  486. Public Shared Operator =(ByVal c1 As Color, ByVal c2 As Color) As Boolean
  487. Return c1.r = c2.r AndAlso c1.g = c2.g AndAlso c1.b = c2.b AndAlso c1.a = c2.a
  488. End Operator
  489.  
  490. ''' <summary>
  491. ''' Implements the !=.
  492. ''' </summary>
  493. ''' <param name="c1">The c1.</param>
  494. ''' <param name="c2">The c2.</param>
  495. ''' <returns>The result of the operator.</returns>
  496. Public Shared Operator <>(ByVal c1 As Color, ByVal c2 As Color) As Boolean
  497. Return Not(c1.r = c2.r AndAlso c1.g = c2.g AndAlso c1.b = c2.b AndAlso c1.a = c2.a)
  498. End Operator
  499.  
  500. ''' <summary>
  501. ''' Returns a hash code for this instance.
  502. ''' </summary>
  503. ''' <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
  504. Public Overrides Function GetHashCode() As Integer
  505. Return GetHashCode()
  506. End Function
  507.  
  508. ''' <summary>
  509. ''' Determines whether the specified <see cref="System.Object" /> is equal to this instance.
  510. ''' </summary>
  511. ''' <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
  512. ''' <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
  513. Public Overrides Function Equals(ByVal obj As Object) As Boolean
  514. Dim c As Color = DirectCast(obj, Color)
  515. Return r = c.r AndAlso g = c.g AndAlso b = c.b
  516. End Function
  517.  
  518. ''' <summary>
  519. ''' Implements the -.
  520. ''' </summary>
  521. ''' <param name="c1">The c1.</param>
  522. ''' <param name="c2">The c2.</param>
  523. ''' <returns>The result of the operator.</returns>
  524. Public Shared Operator -(ByVal c1 As Color, ByVal c2 As Color) As Color
  525. Return New Color(CByte(Mathf.Clamp(c1.r - c2.r, 0, 255)), CByte(Mathf.Clamp(c2.g - c2.g, 0, 255)), CByte(Mathf.Clamp(c2.b - c2.b, 0, 255)))
  526. End Operator
  527.  
  528. ''' <summary>
  529. ''' Implements the +.
  530. ''' </summary>
  531. ''' <param name="c1">The c1.</param>
  532. ''' <param name="c2">The c2.</param>
  533. ''' <returns>The result of the operator.</returns>
  534. Public Shared Operator +(ByVal c1 As Color, ByVal c2 As Color) As Color
  535. Return New Color(CByte(Mathf.Clamp(c1.r + c2.r, 0, 255)), CByte(Mathf.Clamp(c2.g + c2.g, 0, 255)), CByte(Mathf.Clamp(c2.b + c2.b, 0, 255)))
  536. End Operator
  537.  
  538. ''' <summary>
  539. ''' Lerps the specified c2.
  540. ''' </summary>
  541. ''' <param name="c2">The c2.</param>
  542. ''' <param name="t">The t.</param>
  543. ''' <returns>Color.</returns>
  544. Public Function Lerp(ByVal c2 As Color, ByVal t As Single) As Color
  545. Return New Color(CByte(Mathf.Lerp(r, c2.r, t)), CByte(Mathf.Lerp(g, c2.g, t)), CByte(Mathf.Lerp(b, c2.b, t)))
  546. End Function
  547.  
  548. ''' <summary>
  549. ''' Inverts this instance.
  550. ''' </summary>
  551. ''' <returns>Color.</returns>
  552. Public Function Invert() As Color
  553. Return New Color(CByte(Mathf.Clamp(Byte.MaxValue - r, 0, 255)), CByte(Mathf.Clamp(Byte.MaxValue - g, 0, 255)), CByte(Mathf.Clamp(Byte.MaxValue - b, 0, 255)))
  554. End Function
  555.  
  556. ''' <summary>
  557. ''' Returns a <see cref="System.String" /> that represents this instance.
  558. ''' </summary>
  559. ''' <returns>A <see cref="System.String" /> that represents this instance.</returns>
  560. Public Overrides Function ToString() As String
  561. If Me = white Then
  562. Return "white"
  563. ElseIf Me = transparent Then
  564. Return "transparent"
  565. ElseIf Me = red Then
  566. Return "red"
  567. ElseIf Me = blue Then
  568. Return "blue"
  569. ElseIf Me = black Then
  570. Return "black"
  571. ElseIf Me = green Then
  572. Return "green"
  573. ElseIf Me = yellow Then
  574. Return "yellow"
  575. Else
  576. Return String.Format("({0}, {1}, {2}, {3})", r, g, b, a)
  577. End If
  578. End Function
  579.  
  580. ''' <summary>
  581. ''' Fills the specified x.
  582. ''' </summary>
  583. ''' <param name="x">The x.</param>
  584. ''' <param name="y">The y.</param>
  585. ''' <returns>Color[].</returns>
  586. Public Shared Iterator Function Fill(ByVal x As Integer, ByVal y As Integer) As IEnumerable(Of Color)
  587. For i As Integer = 0 To (x * y) - 1
  588. Yield black
  589. Next i
  590. End Function
  591. End Structure
  592. End Namespace

Nota: A pesar de haber sido convertido con un conversor se ha comprobado en: https://dotnetfiddle.net/1vbkgG
Nota2: La idea era que se ejecutase de forma online y si le poneis una imagen más pequeña deberia sacar los pixeles, pero como digo no se puede, por tema de web clouds y recursos compartidos.
Nota3: Le he metido esta imagen (https://vignette.wikia.nocookie.net/gta-myths/images/8/80/Gtasa-blank.png/revision/latest?cb=20161204212845) pero me da un error que ahora mismo no me puedo parar a comprobar:

Citar
Run-time exception (line -1): Arithmetic operation resulted in an overflow.

Stack Trace:

[System.OverflowException: Arithmetic operation resulted in an overflow.]
   at F.ColorThreshold(Color c1, Color c2)
   at F._Closure$__3._Lambda$__15(Color x)
   at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)
   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
   at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__1.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at F.GetSimilarColor(Color c1, IEnumerable`1 cs)
   at Program.GetColorCount(Bitmap& image, Byte[] arr, IEnumerable`1 colors, IEnumerable`1& imageColors, Boolean isPosterized)
   at Program.Main()

Y creo que eso es todo.

Un saludo.

PD: La razón de que el código esté mitad comentado y mitad sin comentar es porque la parte de la clase Color es una implementación propia de la clase Color que hice hace tiempo y la introducí en mi Lerp2API.
PD2: Este código (el del ColorThreshold y lo de GetSimilarity, todo lo demás lo he escrito esta mañana y tarde) realmente lo estaba usando en mi proyecto de San Andreas Unity (de los últimos commits que hice antes de irme de este y empezar uno nuevo a solas).
PD3: Todo esto es parte de un proceso de depuración un tanto largo que me ha servido para constrastar de donde me venían unos valores. Para ser más concretos, tengo un algoritmo que saca los contornos de los edificios que he estado optimizando (el cual empecé en 2016, y después de un año he retomado), y bueno, yo esperaba que me devolviese unos 2600 edificios, pero se me han devuelto unos 1027k  y hay unos 1029k pixeles en la última imagen que he puesto (lo podéis comprobar vosotros mismos), así que ya se por donde seguir. Espero que vosotros también hagáis lo mismo con lo que escribo. ;) :P
50  Programación / .NET (C#, VB.NET, ASP) / Re: Librería de Snippets para VB.NET !! (Compartan aquí sus snippets) en: 18 Octubre 2018, 09:28 am
Como rellenar un array siguiendo el algoritmo Flood Fill usando HashSet

https://es.wikipedia.org/wiki/Algoritmo_de_relleno_por_difusi%C3%B3n

Código
  1. Imports System.Collections.Generic
  2. Imports System.Linq
  3. Imports System.Runtime.CompilerServices
  4. Imports System.Runtime.InteropServices
  5.  
  6. Module F
  7.    <Extension()>
  8.    Sub FloodFill(Of T)(ByVal source As T(), ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal target As T, ByVal replacement As T)
  9.        Dim i As Integer = 0
  10.        FloodFill(source, x, y, width, height, target, replacement, i)
  11.    End Sub
  12.  
  13.    <Extension()>
  14.    Sub FloodFill(Of T)(ByVal source As T(), ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal target As T, ByVal replacement As T, <Out> ByRef i As Integer)
  15.        i = 0
  16.        Dim queue As HashSet(Of Integer) = New HashSet(Of Integer)()
  17.        queue.Add(Pn(x, y, width))
  18.  
  19.        While queue.Count > 0
  20.            Dim _i As Integer = queue.First(), _x As Integer = _i Mod width, _y As Integer = _i / width
  21.            queue.Remove(_i)
  22.            If source(_i).Equals(target) Then source(_i) = replacement
  23.  
  24.            For offsetX As Integer = -1 To 2 - 1
  25.  
  26.                For offsetY As Integer = -1 To 2 - 1
  27.                    If offsetX = 0 AndAlso offsetY = 0 OrElse offsetX = offsetY OrElse offsetX = -offsetY OrElse -offsetX = offsetY Then Continue For
  28.                    Dim targetIndex As Integer = Pn(_x + offsetX, _y + offsetY, width)
  29.                    Dim _tx As Integer = targetIndex Mod width, _ty As Integer = targetIndex / width
  30.                    If _tx < 0 OrElse _ty < 0 OrElse _tx >= width OrElse _ty >= height Then Continue For
  31.  
  32.                    If Not queue.Contains(targetIndex) AndAlso source(targetIndex).Equals(target) Then
  33.                        queue.Add(targetIndex)
  34.                        i += 1
  35.                    End If
  36.                Next
  37.            Next
  38.        End While
  39.    End Sub
  40.  
  41.    Function Pn(ByVal x As Integer, ByVal y As Integer, ByVal w As Integer) As Integer
  42.        Return x + (y * w)
  43.    End Function
  44. End Module

Código
  1. using System.Collections.Generic;
  2. using System.Linq;
  3.  
  4. public static class F
  5. {
  6.    /// <summary>
  7.           /// Floods the fill.
  8.           /// </summary>
  9.           /// <typeparam name="T"></typeparam>
  10.           /// <param name="source">The source.</param>
  11.           /// <param name="x">The x.</param>
  12.           /// <param name="y">The y.</param>
  13.           /// <param name="width">The width.</param>
  14.           /// <param name="height">The height.</param>
  15.           /// <param name="target">The target to replace.</param>
  16.           /// <param name="replacement">The replacement.</param>
  17.    public static void FloodFill<T>(this T[] source, int x, int y, int width, int height, T target, T replacement)
  18.    {
  19.        int i = 0;
  20.  
  21.        FloodFill(source, x, y, width, height, target, replacement, out i);
  22.    }
  23.  
  24.    /// <summary>
  25.           /// Floods the array following Flood Fill algorithm
  26.           /// </summary>
  27.           /// <typeparam name="T"></typeparam>
  28.           /// <param name="source">The source.</param>
  29.           /// <param name="x">The x.</param>
  30.           /// <param name="y">The y.</param>
  31.           /// <param name="width">The width.</param>
  32.           /// <param name="height">The height.</param>
  33.           /// <param name="target">The target to replace.</param>
  34.           /// <param name="replacement">The replacement.</param>
  35.           /// <param name="i">The iterations made (if you want to debug).</param>
  36.    public static void FloodFill<T>(this T[] source, int x, int y, int width, int height, T target, T replacement, out int i)
  37.    {
  38.        i = 0;
  39.  
  40.        // Queue of pixels to process. :silbar:
  41.        HashSet<int> queue = new HashSet<int>();
  42.  
  43.        queue.Add(Pn(x, y, width));
  44.  
  45.        while (queue.Count > 0)
  46.        {
  47.            int _i = queue.First(),
  48.              _x = _i % width,
  49.              _y = _i / width;
  50.  
  51.            queue.Remove(_i);
  52.  
  53.            if (source[_i].Equals(target))
  54.                source[_i] = replacement;
  55.  
  56.            for (int offsetX = -1; offsetX < 2; offsetX++)
  57.                for (int offsetY = -1; offsetY < 2; offsetY++)
  58.                {
  59.                    // do not check origin or diagonal neighbours
  60.                    if (offsetX == 0 && offsetY == 0 || offsetX == offsetY || offsetX == -offsetY || -offsetX == offsetY)
  61.                        continue;
  62.  
  63.                    int targetIndex = Pn(_x + offsetX, _y + offsetY, width);
  64.                    int _tx = targetIndex % width,
  65.                      _ty = targetIndex / width;
  66.  
  67.                    // skip out of bounds point
  68.                    if (_tx < 0 || _ty < 0 || _tx >= width || _ty >= height)
  69.                        continue;
  70.  
  71.                    if (!queue.Contains(targetIndex) && source[targetIndex].Equals(target))
  72.                    {
  73.                        queue.Add(targetIndex);
  74.                        ++i;
  75.                    }
  76.                }
  77.        }
  78.    }
  79.  
  80.    public static int Pn(int x, int y, int w)
  81.    {
  82.        return x + (y * w);
  83.    }
  84. }

EDIT: Añadidos using + función PN + codigo en VB.NET que para eso son los snippets de VB

Prueba de concepto: https://dotnetfiddle.net/ZacRiB

Un saludo.
Páginas: 1 2 3 4 [5] 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... 238
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines