Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)

<< < (120/120)

Eleкtro:
Cómo iniciar el programa warp-cli.exe de la VPN de Cloudflare Warp pasándole un comando

Un simple método para ejecutar el programa warp-cli.exe de la VPN de Cloudflare Warp pasándole un comando (ej. "connect", "disconnect", etc):

Código
''' <summary>
''' Sends a custom command to the Cloudflare Warp CLI executable (<c>warp-cli.exe</c>)
''' and captures both standard output and error output.
''' </summary>
'''
''' <param name="command">
''' The command-line argument to be passed to warp-cli executable.
''' For example: <c>connect</c>, <c>disconnect</c>, <c>status</c>, etc.
''' </param>
'''
''' <param name="refOutput">
''' Returns the standard output returned by the warp-cli process.
''' </param>
'''
''' <param name="refErrorOutput">
''' Returns the standard error output returned by the warp-cli process.
''' </param>
'''
''' <param name="warpCliFilePath">
''' Optional path to the warp-cli executable. If <c>Nothing</c> is specified, the method defaults to:
''' <c>%ProgramFiles%\Cloudflare\Cloudflare Warp\warp-cli.exe</c>.
''' </param>
'''
''' <returns>
''' The exit code returned by the warp-cli process. A value of 0 typically indicates success.
''' </returns>
'''
''' <exception cref="System.IO.FileNotFoundException">
''' Thrown if the specified or default warp-cli executable file is not found on the system.
''' </exception>
'''
''' <exception cref="System.TimeoutException">
''' Thrown if the warp-cli process takes longer than 60 seconds to complete.
''' </exception>
'''
''' <exception cref="System.Exception">
''' Thrown if any other unexpected error occurs while attempting to execute the warp-cli process.
''' The original exception is wrapped as the inner exception.
''' </exception>
<DebuggerStepThrough>
Public Shared Function CloudflareWarpCliSendCommand(command As String,
                                                   ByRef refOutput As String,
                                                   ByRef refErrorOutput As String,
                                                   Optional warpCliFilePath As String = Nothing) As Integer
 
   ' Prevents concurrent execution of the method from multiple threads within the same process.
   ' This static lock object ensures that only one thread can execute the critical section at a time,
   ' avoiding race conditions or conflicts when invoking the Warp CLI.
   Static WarpCliLock As New Object()
 
   Static spaceChar As Char = " "c
 
   SyncLock WarpCliLock
       If String.IsNullOrEmpty(warpCliFilePath) Then
           warpCliFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
                                          "Cloudflare\Cloudflare Warp\warp-cli.exe")
       End If
 
       Try
           If Not System.IO.File.Exists(warpCliFilePath) Then
               Throw New System.IO.FileNotFoundException("The Warp CLI executable was not found.", warpCliFilePath)
           End If
 
           Using pr As New Process()
               pr.StartInfo.FileName = warpCliFilePath
               pr.StartInfo.Arguments = command
               pr.StartInfo.UseShellExecute = False
               pr.StartInfo.CreateNoWindow = True
               pr.StartInfo.RedirectStandardOutput = True
               pr.StartInfo.RedirectStandardError = True
 
               pr.Start()
               If Not pr.WaitForExit(60000) Then ' Waits a maximum of 60 seconds
                   pr.Kill()
                   Throw New TimeoutException("warp-cli process has timed out.")
               End If
 
               refOutput = pr.StandardOutput.ReadToEnd().Trim(Environment.NewLine.ToCharArray().Concat({spaceChar}).ToArray())
               refErrorOutput = pr.StandardError.ReadToEnd().Trim(Environment.NewLine.ToCharArray().Concat({spaceChar}).ToArray())
 
               Return pr.ExitCode
           End Using
 
       Catch ex As Exception
           Throw New Exception($"Failed to execute warp-cli process. See inner exception for details.", ex)
       End Try
   End SyncLock
End Function

Casos de uso reales: para conectar a la red de Cloudflare WARP en cualquier proyecto donde hagamos solicitudes http, por ejemplo en un web-crawler, a sitios web con riesgo de que puedan acabar bloqueando nuestra IP.


Tres métodos de extensión para dibujar texto sobre una imagen, o dibujar encima otra imagen (con capacidad opcional de usar transparencia) o un valor numérico, con una escala proporcional a la imagen y en una posición alineada a cualquiera de las esquinas o zonas centrales de la imagen (centro absoluto, parte superior central o parte inferior central) de la imagen.

Demostración de resultado de la extensión que dibuja un valor numérico (de forma alineada a la esquina inferior derecha de la imagen):



Código
''' <summary>
''' Draws an overlay image onto the specified <see cref="Image"/> at a given position and scale factor.
''' </summary>
'''
''' <param name="refImg">
''' The source <see cref="Image"/> to modify. The overlay image will be drawn directly on this image.
''' </param>
'''
''' <param name="overlayImg">
''' The overlay image to draw on the source <paramref name="refImg"/>.
''' </param>
'''
''' <param name="scale">
''' The relative image scale factor to determine overlay image size. Lower values increase the size of the overlay image.
''' </param>
'''
''' <param name="position">
''' The position/alignment where the overlay image should be drawn (e.g., bottom-right).
''' </param>
'''
''' <param name="margin">
''' The margin (in pixels) from the edge of the image to position the overlay image.
''' <para></para>
''' This value has different meaning depending on <paramref name="position"/> parameter:
''' <para></para>
''' <list type="bullet">
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.TopLeft"/>, <see cref="ContentAlignment.TopRight"/>,
'''       <para></para>
'''       <see cref="ContentAlignment.BottomLeft"/> and <see cref="ContentAlignment.BottomRight"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the diagonal offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.MiddleLeft"/> and <see cref="ContentAlignment.MiddleRight"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the horizontal offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.TopCenter"/> and <see cref="ContentAlignment.BottomCenter"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the vertical offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.MiddleCenter"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> is ignored.</description>
'''   </item>
''' </list>
''' </param>
'''
''' <param name="transparentColor">
''' Optional. A <see cref="Color"/> to use as transparency to draw the overlay image.
''' </param>
<DebuggerStepThrough>
<Extension>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Sub DrawImageScaled(ByRef refImg As Image, overlayImg As Image,
                      scale As Single, position As ContentAlignment, margin As Single,
                      Optional transparentColor As Color? = Nothing)
 
   If refImg Is Nothing Then
       Throw New ArgumentNullException(NameOf(refImg))
   End If
 
   If overlayImg Is Nothing Then
       Throw New ArgumentNullException(NameOf(overlayImg))
   End If
 
   If margin < 0 Then
       Throw New ArgumentOutOfRangeException(NameOf(margin), margin, "Margin must be greater than or equal to 0.")
   End If
 
   If scale < 1 Then
       Throw New ArgumentOutOfRangeException(NameOf(scale), scale, "Font scale must be greater than or equal to 1.")
   End If
 
   Using g As Graphics = Graphics.FromImage(refImg)
       g.SmoothingMode = SmoothingMode.AntiAlias
       g.InterpolationMode = InterpolationMode.HighQualityBicubic
       g.PixelOffsetMode = PixelOffsetMode.HighQuality
       g.CompositingQuality = CompositingQuality.HighQuality
 
       Dim targetSize As Single = Math.Max(refImg.Width, refImg.Height) / scale
       Dim aspectRatio As Single = CSng(overlayImg.Width / overlayImg.Height)
 
       Dim drawWidth As Single
       Dim drawHeight As Single
 
       If overlayImg.Width >= overlayImg.Height Then
           drawWidth = targetSize
           drawHeight = targetSize / aspectRatio
       Else
           drawHeight = targetSize
           drawWidth = targetSize * aspectRatio
       End If
 
       Dim posX As Single = 0
       Dim posY As Single = 0
 
       Select Case position
           Case ContentAlignment.TopLeft
               posX = margin
               posY = margin
 
           Case ContentAlignment.TopCenter
               posX = (refImg.Width - drawWidth) / 2
               posY = margin
 
           Case ContentAlignment.TopRight
               posX = refImg.Width - drawWidth - margin
               posY = margin
 
           Case ContentAlignment.MiddleLeft
               posX = margin
               posY = (refImg.Height - drawHeight) / 2
 
           Case ContentAlignment.MiddleCenter
               posX = (refImg.Width - drawWidth) / 2
               posY = (refImg.Height - drawHeight) / 2
 
           Case ContentAlignment.MiddleRight
               posX = refImg.Width - drawWidth - margin
               posY = (refImg.Height - drawHeight) / 2
 
           Case ContentAlignment.BottomLeft
               posX = margin
               posY = refImg.Height - drawHeight - margin
 
           Case ContentAlignment.BottomCenter
               posX = (refImg.Width - drawWidth) / 2
               posY = refImg.Height - drawHeight - margin
 
           Case ContentAlignment.BottomRight
               posX = refImg.Width - drawWidth - margin
               posY = refImg.Height - drawHeight - margin
 
           Case Else
               Throw New InvalidEnumArgumentException(NameOf(position), position, GetType(ContentAlignment))
       End Select
 
       If transparentColor.HasValue Then
           Using attr As New Imaging.ImageAttributes()
               attr.SetColorKey(transparentColor.Value, transparentColor.Value)
 
               Dim destRect As New Rectangle(CInt(posX), CInt(posY), CInt(drawWidth), CInt(drawHeight))
               g.DrawImage(overlayImg, destRect, 0, 0, overlayImg.Width, overlayImg.Height, GraphicsUnit.Pixel, attr)
           End Using
       Else
           g.DrawImage(overlayImg, posX, posY, drawWidth, drawHeight)
       End If
   End Using
End Sub
 
''' <summary>
''' Draws text onto the specified <see cref="Image"/> at a given position and scale factor.
''' </summary>
'''
''' <param name="refImg">
''' The <see cref="Image"/> to modify. The text will be drawn directly on this image.
''' </param>
'''
''' <param name="text">
''' The text to draw on the image.
''' </param>
'''
''' <param name="scale">
''' The relative image scale factor to determine font size. Lower values increase the size of the text.
''' <para></para>
''' Suggested value is from 10 to 20.
''' </param>
'''
''' <param name="position">
''' The position/alignment where the text should be drawn (e.g., bottom-right).
''' </param>
'''
''' <param name="margin">
''' The margin (in pixels) from the edge of the image to position the text.
''' <para></para>
''' This value has different meaning depending on <paramref name="position"/> parameter:
''' <para></para>
''' <list type="bullet">
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.TopLeft"/>, <see cref="ContentAlignment.TopRight"/>,
'''       <para></para>
'''       <see cref="ContentAlignment.BottomLeft"/> and <see cref="ContentAlignment.BottomRight"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the diagonal offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.MiddleLeft"/> and <see cref="ContentAlignment.MiddleRight"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the horizontal offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.TopCenter"/> and <see cref="ContentAlignment.BottomCenter"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the vertical offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.MiddleCenter"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> is ignored.</description>
'''   </item>
''' </list>
''' </param>
'''
''' <param name="font">
''' Optional. A custom <see cref="Font"/> to use. If not provided, a bold <c>Arial</c> font is used.
''' <para></para>
''' Note: Custom font size (<see cref="System.Drawing.Font.Size"/>) is ignored. It is determined by <paramref name="scale"/> parameter.
''' </param>
'''
''' <param name="textColor">
''' Optional. The color of the text.
''' <para></para>
''' Default value is <see cref="Color.White"/>.
''' </param>
'''
''' <param name="outlineColor">
''' Optional. The color of the text outline.
''' <para></para>
''' Default value is <see cref="Color.Black"/>.
''' </param>
'''
''' <param name="outlineThickness">
''' Optional. The thickness of the outline, in pixels.
''' <para></para>
''' Default value is 2 pixels.
''' </param>
<DebuggerStepThrough>
<Extension>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Sub DrawTextScaled(ByRef refImg As Image, text As String, scale As Single,
                     position As ContentAlignment, margin As Single,
                     Optional font As Font = Nothing,
                     Optional textColor As Color = Nothing,
                     Optional outlineColor As Color = Nothing,
                     Optional outlineThickness As Short = 2)
 
   If margin < 0 Then
       Throw New ArgumentOutOfRangeException(NameOf(margin), margin, "Margin must be greater than or equal to 0.")
   End If
 
   If scale < 1 Then
       Throw New ArgumentOutOfRangeException(NameOf(scale), scale, "Font scale must be greater than or equal to 1.")
   End If
 
   If textColor = Nothing Then
       textColor = Color.White
   End If
 
   If outlineColor = Nothing Then
       outlineColor = Color.Black
   End If
 
   Using g As Graphics = Graphics.FromImage(refImg)
       g.SmoothingMode = SmoothingMode.AntiAlias
       g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit
       g.InterpolationMode = InterpolationMode.HighQualityBicubic
       g.PixelOffsetMode = PixelOffsetMode.HighQuality
       g.CompositingQuality = CompositingQuality.HighQuality
 
       Dim rawFontSize As Single = Math.Max(refImg.Width, refImg.Height) / scale
       Dim maxAllowedFontSize As Single = Math.Min(refImg.Width, refImg.Height)
       Dim fontSize As Single = Math.Min(rawFontSize, maxAllowedFontSize)
 
       Using textFont As Font =
       If(font IsNot Nothing, New Font(font.FontFamily, fontSize, font.Style, GraphicsUnit.Pixel, font.GdiCharSet, font.GdiVerticalFont),
                              New Font("Arial", fontSize, FontStyle.Bold, GraphicsUnit.Pixel))
 
           Dim textSize As SizeF = g.MeasureString(text, textFont)
           Dim posX As Single = 0
           Dim posY As Single = 0
 
           Select Case position
               Case ContentAlignment.TopLeft
                   posX = margin
                   posY = margin
 
               Case ContentAlignment.TopCenter
                   posX = (refImg.Width - textSize.Width) / 2
                   posY = margin
 
               Case ContentAlignment.TopRight
                   posX = refImg.Width - textSize.Width - margin
                   posY = margin
 
               Case ContentAlignment.MiddleLeft
                   posX = margin
                   posY = (refImg.Height - textSize.Height) / 2
 
               Case ContentAlignment.MiddleCenter
                   posX = (refImg.Width - textSize.Width) / 2
                   posY = (refImg.Height - textSize.Height) / 2
 
               Case ContentAlignment.MiddleRight
                   posX = refImg.Width - textSize.Width - margin
                   posY = (refImg.Height - textSize.Height) / 2
 
               Case ContentAlignment.BottomLeft
                   posX = margin
                   posY = refImg.Height - textSize.Height - margin
 
               Case ContentAlignment.BottomCenter
                   posX = (refImg.Width - textSize.Width) / 2
                   posY = refImg.Height - textSize.Height - margin
 
               Case ContentAlignment.BottomRight
                   posX = refImg.Width - textSize.Width - margin
                   posY = refImg.Height - textSize.Height - margin
 
               Case Else
                   Throw New InvalidEnumArgumentException(NameOf(position), position, GetType(ContentAlignment))
           End Select
 
           Using outlineBrush As New SolidBrush(outlineColor)
 
               For dx As Short = -outlineThickness To outlineThickness
                   For dy As Short = -outlineThickness To outlineThickness
                       If dx <> 0 OrElse dy <> 0 Then
                           g.DrawString(text, textFont, outlineBrush, posX + dx, posY + dy)
                       End If
                   Next dy
               Next dx
           End Using
 
           Using textBrush As New SolidBrush(textColor)
               g.DrawString(text, textFont, textBrush, posX, posY)
           End Using
       End Using ' font
   End Using ' g
End Sub
 
''' <summary>
''' Draws a number onto the specified <see cref="Image"/> at a given position and scale factor.
''' </summary>
'''
''' <param name="refImg">
''' The <see cref="Image"/> to modify. The number will be drawn directly on this image.
''' </param>
'''
''' <param name="number">
''' The number to draw on the image.
''' </param>
'''
''' <param name="scale">
''' The relative image scale factor to determine font size. Lower values increase the size of the text.
''' <para></para>
''' Suggested value is from 10 to 20.
''' </param>
'''
''' <param name="position">
''' The position/alignment where the number should be drawn (e.g., bottom-right).
''' </param>
'''
''' <param name="margin">
''' The margin (in pixels) from the edge of the image to position the text.
''' <para></para>
''' This value has different meaning depending on <paramref name="position"/> parameter:
''' <para></para>
''' <list type="bullet">
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.TopLeft"/>, <see cref="ContentAlignment.TopRight"/>,
'''       <para></para>
'''       <see cref="ContentAlignment.BottomLeft"/> and <see cref="ContentAlignment.BottomRight"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the diagonal offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.MiddleLeft"/> and <see cref="ContentAlignment.MiddleRight"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the horizontal offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.TopCenter"/> and <see cref="ContentAlignment.BottomCenter"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> specifies the vertical offset.</description>
'''   </item>
'''   <item>
'''     <term>
'''       <see cref="ContentAlignment.MiddleCenter"/>
'''     </term>
'''     <description><para></para><paramref name="margin"/> is ignored.</description>
'''   </item>
''' </list>
''' </param>
'''
''' <param name="font">
''' Optional. A custom <see cref="Font"/> to use. If not provided, a bold <c>Arial</c> font is used.
''' <para></para>
''' Note: Custom font size (<see cref="System.Drawing.Font.Size"/>) is ignored. It is determined by <paramref name="scale"/> parameter.
''' </param>
'''
''' <param name="textColor">
''' Optional. The color of the text.
''' <para></para>
''' Default value is <see cref="Color.White"/>.
''' </param>
'''
''' <param name="outlineColor">
''' Optional. The color of the text outline.
''' <para></para>
''' Default value is <see cref="Color.Black"/>.
''' </param>
'''
''' <param name="outlineThickness">
''' Optional. The thickness of the outline, in pixels.
''' <para></para>
''' Default value is 2 pixels.
''' </param>
<DebuggerStepThrough>
<Extension>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Sub DrawNumberScaled(ByRef refImg As Image, number As Integer, scale As Single,
                       position As ContentAlignment, margin As Single,
                       Optional font As Font = Nothing,
                       Optional textColor As Color = Nothing,
                       Optional outlineColor As Color = Nothing,
                       Optional outlineThickness As Short = 2)
 
   DrawTextScaled(refImg, CStr(number), scale, position, margin, font, textColor, outlineColor, outlineThickness)
End Sub
 

Eleкtro:
Cuatro métodos de extensión para el tipo DateTime con los que obtener una representación de fecha o fecha y hora realmente amistosa.

Ejemplos:

  Fecha en inglés: 11 May, 2025
  Fecha en español: 11 de mayo de 2025
  Fecha en alemán: 11. Mai 2025

  Fecha y hora en inglés: 11 May, 2025 at 23:59:59
  Fecha y hora en español: 11 de mayo de 2025 a las 23:59:59

No soy experto en la representación por escrito de fechas en otros idiomas así que solo intenté perfeccionar estos tres. La representación en alemán estaría bien según me he informado, ya que se supone que se añade un punto de esa forma. En definitiva, creo que para ir tirando está bien así.

Código
''' <summary>
''' Converts a <see cref="Date"/> object to a long friendly date string based on the current culture.
''' <para></para>
''' For example:
''' <list type="bullet">
'''   <item><description>English<para></para>11 May, 2025</description></item>
'''   <item><description>Spanish<para></para>11 de mayo de 2025</description></item>
'''   <item><description>German<para></para>11. Mai 2025</description></item>
''' </list>
''' </summary>
'''
''' <param name="[date]">
''' The <see cref="Date"/> object to be formatted.
''' </param>
'''
''' <returns>
''' A string representing the formatted date, based on the current culture.
''' </returns>
<DebuggerStepThrough>
<Extension>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Function ToLongFriendlyDateString([date] As Date) As String
 
   Return DateExtensions.ToLongFriendlyDateString([date], CultureInfo.CurrentCulture)
End Function
 
''' <summary>
''' Converts a <see cref="Date"/> object to a long friendly date string based on the specified culture.
''' <para></para>
''' For example:
''' <list type="bullet">
'''   <item><description>English<para></para>11 May, 2025</description></item>
'''   <item><description>Spanish<para></para>11 de mayo de 2025</description></item>
'''   <item><description>German<para></para>11. Mai 2025</description></item>
''' </list>
''' </summary>
'''
''' <param name="[date]">
''' The <see cref="Date"/> object to be formatted.
''' </param>
'''
''' <param name="provider">
''' The culture information used to format the date.
''' </param>
'''
''' <returns>
''' A string representing the formatted date, based on the specified culture.
''' </returns>
<DebuggerStepThrough>
<Extension>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Function ToLongFriendlyDateString([date] As Date, provider As IFormatProvider) As String
 
   Dim culture As CultureInfo = TryCast(provider, CultureInfo)
   If culture IsNot Nothing Then
 
       Select Case culture.TwoLetterISOLanguageName.ToLower()
           Case "es", "ca", "gl", "pt" ' Spanish, Catalonian, Galego, Portuguese
               Return [date].ToString("dd 'de' MMMM 'de' yyyy", provider)
 
           Case "de" ' Deutsch
               Return [date].ToString("dd'.' MMMM yyyy", provider)
 
           Case Else ' Do nothing.
               Exit Select
       End Select
   End If
 
   Return [date].ToString("dd MMMM, yyyy", provider)
End Function
 
''' <summary>
''' Converts a <see cref="Date"/> object to a long friendly date string based on the current culture.
''' <para></para>
''' For example:
''' <list type="bullet">
'''   <item><description>English<para></para>11 May, 2025 at 23:59:59</description></item>
'''   <item><description>Spanish<para></para>11 de mayo de 2025 a las 23:59:59</description></item>
''' </list>
''' </summary>
'''
''' <param name="[date]">
''' The <see cref="Date"/> object to be formatted.
''' </param>
'''
''' <returns>
''' A string representing the formatted date, based on the current culture.
''' </returns>
<DebuggerStepThrough>
<Extension>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Function ToLongFriendlyDateAndTimeString([date] As Date) As String
 
   Return DateExtensions.ToLongFriendlyDateAndTimeString([date], CultureInfo.CurrentCulture)
End Function
 
''' <summary>
''' Converts a <see cref="Date"/> object to a long friendly date string based on the specifies culture.
''' <para></para>
''' For example:
''' <list type="bullet">
'''   <item><description>English<para></para>11 May, 2025 at 23:59:59</description></item>
'''   <item><description>Spanish<para></para>11 de mayo de 2025 a las 23:59:59</description></item>
''' </list>
''' </summary>
'''
''' <param name="[date]">
''' The <see cref="Date"/> object to be formatted.
''' </param>
'''
''' <param name="provider">
''' The culture information used to format the date.
''' </param>
'''
''' <returns>
''' A string representing the formatted date, based on the specified culture.
''' </returns>
<DebuggerStepThrough>
<Extension>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Function ToLongFriendlyDateAndTimeString([date] As Date, provider As IFormatProvider) As String
 
   Dim culture As CultureInfo = TryCast(provider, CultureInfo)
   If culture IsNot Nothing Then
 
       Select Case culture.TwoLetterISOLanguageName.ToLower()
           Case "en" ' English
               Return [date].ToString($"'{ToLongFriendlyDateString([date], provider)}' 'at' HH:mm:ss", provider)
 
           Case "es" ' Spanish
               Return [date].ToString($"'{ToLongFriendlyDateString([date], provider)}' 'a las' HH:mm:ss", provider)
 
           Case Else ' Do nothing.
               Exit Select
       End Select
   End If
 
   Return [date].ToString($"'{ToLongFriendlyDateString([date], provider)}' '—' HH:mm:ss", provider)
End Function

Eleкtro:
Librería .NET para automatizar el uso de rar.exe de RARLab (WinRAR)

Esto es un wrapper .NET completo para la herramienta por línea de comandos rar.exe oficial de RARLab. Esta librería permite a los desarrolladores de .NET acceder y controlar fácilmente casi todas las funciones de rar.exe, como comprimir, extraer, listar, testar, crear volúmenes de recuperación y administrar archivos RAR, desde sus aplicaciones.

Llevaba mucho tiempo queriendo hacer esto, bastantes años hace que se me ocurrió la idea por que hay infinidad de librerías disponibles en la mayoría de lenguajes de programación para manejar formatos ZIP y 7Zip entre otros muchos, pero para el formato RAR, en especial el formato RARv5 son muy escasas... probablemente por desinterés y/o por ser un formato privativo. Lo cierto es que no conozco ningún otro wrapper del executable rar.exe, ni tampoco un wrapper que en lugar de depender de rar.exe haga llamadas nativas a una librería oficial de RARLab.

El caso es que nunca empecé este proyecto por simple pereza. Me parecía muy interesante pero al mismo tiempo no me resultaba necesario en realidad desarrollar una infraestructura completa para configurar el lanzamiento del proceso de rar.exe pasándole un comando cualquiera, cosa que podía escribir en una sola línea como esta: Process.Start(".\rar.exe", "argumentos") — pero claro, esto es algo muy codificado en el código por así decirlo, no es tan bonito o elegante o profesional como configurar una sofisticada clase para construir los argumentos y controlar el lanzamiento del proceso con sus códigos de salida y demás.

Así que siempre lo estuve aplazando. Y cuando finalmente decidí empezar, hace cosa de unas semanas, esperaba poder compartirlo con ustedes en formato de "snippet" en este hilo, es decir algo de un tamaño reducido, pero fui demasiado ingenuo ya que al final el trabajo ha alcanzado la cantidad de 9 clases para representar diversos comandos, 17 enumeraciones y otras tantas clases para otros elementos integrados, haciendo un total de 37 archivos separados de código fuente.

Así que no me ha quedado más remedio que compartirlo en GitHub, y aquí lo comparto con ustedes:

  👉 📦 RARLab's rar.exe .NET Wrapper Library

Como he dicho, esto es una librería, un archivo dll para administrar el uso del archivo rar.exe. Es totalmente "universal", se puede usar en proyectos de VB.NET o de C#, bajo .NET Framework o NET 5.0+ (el proyecto habría que migrarlo), no hay dependencias más allá del archivo 'rar.exe' de WinRAR y la licencia del producto, que deben ser administrados por el usuario.


El README.md del repositorio en GitHub incluye un ejemplo de uso para VB.NET y también para C#.

Además, en el código fuente de todas las nueve clases que representan los 'Comandos', incluyen un apartado, arriba del todo de la clase, con un ejemplo de uso para VB.NET, y también en la propia documentación XML de la clase.

De todas formas, aquí les dejo un ejemplo de uso completo para VB.NET

 — Construir un Comando para la creación de archivos RAR utilizando la clase RarCreationCommand:

Código
Imports DevCase.RAR
Imports DevCase.RAR.Commands

Código
Dim archivePath As String = "C:\New Archive.rar"
Dim filesToAdd As String = "C:\Directory to add\"
 
Dim command As New RarCreationCommand(RarCreationMode.Add, archivePath, filesToAdd) With {
   .RarExecPath = ".\rar.exe",
   .RarLicenseData = "(Your license key)",
   .RecurseSubdirectories = True,
   .EncryptionProperties = Nothing,
   .SolidCompression = False,
   .CompressionMode = RarCompressionMode.Normal,
   .DictionarySize = RarDictionarySize.Mb__128,
   .OverwriteMode = RarOverwriteMode.Overwrite,
   .FilePathMode = RarFilePathMode.ExcludeBaseDirFromFileNames,
   .FileTimestamps = RarFileTimestamps.All,
   .AddQuickOpenInformation = TriState.True,
   .ProcessHardLinksAsLinks = True,
   .ProcessSymbolicLinksAsLinks = TriState.True,
   .DuplicateFileMode = RarDuplicateFileMode.Enabled,
   .FileChecksumMode = RarFileChecksumMode.BLAKE2sp,
   .ArchiveComment = New RarArchiveComment("Hello world!"),
   .RecoveryRecordPercentage = 0,
   .VolumeSplitOptions = Nothing,
   .FileTypesToStore = Nothing
}

 — Para obtener los argumentos completos de la línea de comandos de nuestro Comando:

Código
Console.WriteLine($"Command-line arguments: {command}")
Código
MessageBox.Show(command.ToString())

 — Ejecutar nuestro Comando usando la clase RarCommandExecutor:

Código
Using rarExecutor As New RarCommandExecutor(command)
 
   AddHandler rarExecutor.OutputDataReceived,
       Sub(sender As Object, e As DataReceivedEventArgs)
           Console.WriteLine($"[Output] {Date.Now:yyyy-MM-dd HH:mm:ss} - {e.Data}")
       End Sub
 
   AddHandler rarExecutor.ErrorDataReceived,
       Sub(sender As Object, e As DataReceivedEventArgs)
           If e.Data IsNot Nothing Then
               Console.WriteLine($"[Error] {Date.Now:yyyy-MM-dd HH:mm:ss} - {e.Data}")
           End If
       End Sub
 
   AddHandler rarExecutor.Exited,
       Sub(sender As Object, e As EventArgs)
           Dim pr As Process = DirectCast(sender, Process)
           Dim rarExitCode As RarExitCode = DirectCast(pr.ExitCode, RarExitCode)
           Console.WriteLine($"[Exited] {Date.Now:yyyy-MM-dd HH:mm:ss} - rar.exe process has terminated with exit code {pr.ExitCode} ({rarExitCode})")
       End Sub
 
   Dim exitcode As RarExitCode = rarExecutor.ExecuteRarAsync().Result
End Using

**Aincrad**:
Genial snippets nuevos , gracias.  ;-)

Eleкtro:
Cita de: **Aincrad** en  1 Junio 2025, 23:45 pm

Genial snippets nuevos , gracias.  ;-)


Te lo agradezco!


Varios métodos para crear efectos de transición de imagen con la librería ImageMagick:

Magick.NET-Q8-AnyCPUMagick.NET-Q16-AnyCPU
El número de frames del efecto de transición y el tiempo de la secuencia de animación son configurables.

Estos efectos son ideales para generar presentaciones de imágenes en animaciones GIF...


Barrido direccional:

 

Código
''' <summary>
''' Generates a sequence of transition frames between two <see cref="MagickImage"/> instances,
''' progressively revealing the second image over the first one in a specified direction.
''' </summary>
'''
''' <param name="firstImage">
''' The starting image of the transition.
''' </param>
'''
''' <param name="secondImage">
''' The image to swipe in over <paramref name="firstImage"/>.
''' </param>
'''
''' <param name="direction">
''' The direction in which the swipe effect must occur.
''' </param>
'''
''' <param name="steps">
''' The number of intermediate frames to generate for the transition.
''' <para></para>
''' A higher value may result in a smoother, slower visual transition,  
''' at the cost of increased processing time to generate the effect
''' and increased number of images / file size for the resulting animation.
''' <para></para>
''' Minimum value is 3. Default value is 5.
''' </param>
'''
''' <param name="animationDelay">
''' The time in 1/100ths of a second which must expire before splaying the next image in the transition sequence.
''' <para></para>
''' Default value is 1 (10 milliseconds).
''' </param>
'''
''' <param name="frameTransformation">
''' An <see cref="Action(Of MagickImage)"/> delegate that applies custom transformations to each frame (<see cref="MagickImage"/> object)
''' used to create the transition animation. This allows fine-tuning of image properties such as format,
''' color profile, quality and other supported properties and methods by <see cref="MagickImage"/> class.
''' <para></para>
''' Note: <paramref name="animationDelay"/> value cannot be overridden in <paramref name="frameTransformation"/> delegate.
''' <para></para>
''' Code Example in VB.NET:
''' <code>Dim transformation As Action(Of MagickImage) =
'''     Sub(x As MagickImage)
'''         x.AnimationDelay = 1 ' 10 milliseconds
'''         x.Format = MagickFormat.Jpg
'''         x.Quality = 90
'''     End Sub
'''</code>
'''
''' Code Example in C#:
''' <code>Action&lt;MagickImage&gt; transformation = (MagickImage x) =&gt; {
'''     x.AnimationDelay = 1; // 1 10 milliseconds
'''     x.Format = MagickFormat.Jpg;
'''     x.Quality = 90;
''' };</code>
''' </param>
'''
''' <returns>
''' An <see cref="IList"/> of <see cref="MagickImage"/> objects representing each frame of the transition animation.
''' <para></para>
''' All frames returned must be disposed of by the caller to free resources when no longer needed.
''' </returns>
<DebuggerStepThrough>
Public Shared Function GenerateSwipeTransition(firstImage As MagickImage, secondImage As MagickImage,
                                              direction As System.Windows.Forms.FlowDirection,
                                              steps As Integer, animationDelay As Integer,
                                              Optional frameTransformation As Action(Of MagickImage) = Nothing) As IList(Of MagickImage)
 
   If firstImage Is Nothing Then
       Throw New ArgumentNullException(NameOf(firstImage))
   End If
   If secondImage Is Nothing Then
       Throw New ArgumentNullException(NameOf(secondImage))
   End If
   If steps < 3 Then
       Throw New ArgumentOutOfRangeException(NameOf(steps), steps,
                   "The steps value must be equal to or greater than three.")
   End If
   If animationDelay <= 0 Then
       Throw New ArgumentOutOfRangeException(NameOf(animationDelay), animationDelay,
                   "The animation delay value must be greater than zero.")
   End If
 
   Dim frames As New List(Of MagickImage)
 
   For i As Integer = 1 To steps
       Dim ratio As Double = i / steps
 
       Using secondCropped As New MagickImage(secondImage)
           Dim cropWidth As UInteger = secondImage.Width
           Dim cropHeight As UInteger = secondImage.Height
           Dim offsetX As Integer = 0
           Dim offsetY As Integer = 0
           Dim drawX As Integer = 0
           Dim drawY As Integer = 0
 
           Select Case direction
 
               Case System.Windows.Forms.FlowDirection.LeftToRight
                   cropWidth = CUInt(secondImage.Width * ratio)
                   offsetX = 0
                   drawX = 0
 
               Case System.Windows.Forms.FlowDirection.RightToLeft
                   cropWidth = CUInt(secondImage.Width * ratio)
                   offsetX = CInt(secondImage.Width - cropWidth)
                   drawX = offsetX
 
               Case System.Windows.Forms.FlowDirection.TopDown
                   cropHeight = CUInt(secondImage.Height * ratio)
                   offsetY = 0
                   drawY = 0
 
               Case System.Windows.Forms.FlowDirection.BottomUp
                   cropHeight = CUInt(secondImage.Height * ratio)
                   offsetY = CInt(secondImage.Height - cropHeight)
                   drawY = offsetY
 
           End Select
 
           Dim geometry As New MagickGeometry(offsetX, offsetY, cropWidth, cropHeight)
           secondCropped.Crop(geometry)
           secondCropped.ResetPage()
 
           Dim frame As New MagickImage(firstImage)
           frame.Composite(secondCropped, drawX, drawY, CompositeOperator.Over)
 
           frameTransformation?.Invoke(frame)
           frame.AnimationDelay = CUInt(animationDelay)
 
           frames.Add(frame)
       End Using
   Next
 
   Return frames
End Function


Fundido de entrada de imagen B sobre imagen A:


Código
''' <summary>
''' Generates a sequence of transition frames between two <see cref="MagickImage"/> instances,
''' gradually fading in the second image over the first one.
''' </summary>
'''
''' <param name="firstImage">
''' The starting image of the transition.
''' </param>
'''
''' <param name="secondImage">
''' The image to fade in over <paramref name="firstImage"/>.
''' </param>
'''
''' <param name="steps">
''' The number of intermediate frames to generate for the transition.
''' <para></para>
''' A higher value may result in a smoother, slower visual transition,  
''' at the cost of increased processing time to generate the effect
''' and increased number of images / file size for the resulting animation.
''' <para></para>
''' Minimum value is 3. Default value is 5.
''' </param>
'''
''' <param name="animationDelay">
''' The time in 1/100ths of a second which must expire before splaying the next image in the transition sequence.
''' <para></para>
''' Default value is 1 (10 milliseconds).
''' </param>
'''
''' <param name="frameTransformation">
''' An <see cref="Action(Of MagickImage)"/> delegate that applies custom transformations to each frame (<see cref="MagickImage"/> object)
''' used to create the transition animation. This allows fine-tuning of image properties such as format,
''' color profile, quality and other supported properties and methods by <see cref="MagickImage"/> class.
''' <para></para>
''' Note: <paramref name="animationDelay"/> value cannot be overridden in <paramref name="frameTransformation"/> delegate.
''' <para></para>
''' Code Example in VB.NET:
''' <code>Dim transformation As Action(Of MagickImage) =
'''     Sub(x As MagickImage)
'''         x.AnimationDelay = 1 ' 10 milliseconds
'''         x.Format = MagickFormat.Jpg
'''         x.Quality = 90
'''     End Sub
'''</code>
'''
''' Code Example in C#:
''' <code>Action&lt;MagickImage&gt; transformation = (MagickImage x) =&gt; {
'''     x.AnimationDelay = 1; // 1 10 milliseconds
'''     x.Format = MagickFormat.Jpg;
'''     x.Quality = 90;
''' };</code>
''' </param>
'''
''' <returns>
''' An <see cref="IList"/> of <see cref="MagickImage"/> objects representing each frame of the transition animation.
''' <para></para>
''' All frames returned must be disposed of by the caller to free resources when no longer needed.
''' </returns>
<DebuggerStepThrough>
Public Shared Function GenerateFadeInOverTransition(firstImage As MagickImage, secondImage As MagickImage,
                                                   steps As Integer, animationDelay As Integer,
                                                   Optional frameTransformation As Action(Of MagickImage) = Nothing) As IList(Of MagickImage)
 
   If firstImage Is Nothing Then
       Throw New ArgumentNullException(NameOf(firstImage))
   End If
   If secondImage Is Nothing Then
       Throw New ArgumentNullException(NameOf(secondImage))
   End If
   If steps < 3 Then
       Throw New ArgumentOutOfRangeException(NameOf(steps), steps,
                   "The steps value must be equal to or greater than three.")
   End If
   If animationDelay <= 0 Then
       Throw New ArgumentOutOfRangeException(NameOf(animationDelay), animationDelay,
                   "The animation delay value must be greater than zero.")
   End If
 
   Dim frames As New List(Of MagickImage)
 
   For i As Integer = 0 To steps
       Dim alpha As Double = i / steps
 
       Dim frame As New MagickImage(firstImage)
       Using overlay As New MagickImage(secondImage)
           overlay.Alpha(AlphaOption.On)
           overlay.Evaluate(Channels.Alpha, EvaluateOperator.Multiply, alpha)
           frame.Composite(overlay, CompositeOperator.Over)
 
           frameTransformation?.Invoke(frame)
           frame.AnimationDelay = CUInt(animationDelay)
 
           frames.Add(frame)
       End Using
   Next
 
   Return frames
End Function


Fundido de entrada negro:



Código
''' <summary>
''' Generates a sequence of transition frames, gradually fading in from black the specified <see cref="MagickImage"/> object.
''' </summary>
'''
''' <param name="image">
''' The <see cref="MagickImage"/> object to fade in from black.
''' </param>
'''
''' <param name="steps">
''' The number of intermediate frames to generate for the transition.
''' <para></para>
''' A higher value may result in a smoother, slower visual transition,  
''' at the cost of increased processing time to generate the effect
''' and increased number of images / file size for the resulting animation.
''' <para></para>
''' Minimum value is 3. Default value is 5.
''' </param>
'''
''' <param name="animationDelay">
''' The time in 1/100ths of a second which must expire before splaying the next image in the transition sequence.
''' <para></para>
''' Default value is 1 (10 milliseconds).
''' </param>
'''
''' <param name="frameTransformation">
''' An <see cref="Action(Of MagickImage)"/> delegate that applies custom transformations to each frame (<see cref="MagickImage"/> object)
''' used to create the transition animation. This allows fine-tuning of image properties such as format,
''' color profile, quality and other supported properties and methods by <see cref="MagickImage"/> class.
''' <para></para>
''' Note: <paramref name="animationDelay"/> value cannot be overridden in <paramref name="frameTransformation"/> delegate.
''' <para></para>
''' Code Example in VB.NET:
''' <code>Dim transformation As Action(Of MagickImage) =
'''     Sub(x As MagickImage)
'''         x.AnimationDelay = 1 ' 10 milliseconds
'''         x.Format = MagickFormat.Jpg
'''         x.Quality = 90
'''     End Sub
'''</code>
'''
''' Code Example in C#:
''' <code>Action&lt;MagickImage&gt; transformation = (MagickImage x) =&gt; {
'''     x.AnimationDelay = 1; // 1 10 milliseconds
'''     x.Format = MagickFormat.Jpg;
'''     x.Quality = 90;
''' };</code>
''' </param>
'''
''' <returns>
''' An <see cref="IList"/> of <see cref="MagickImage"/> objects representing each frame of the transition animation.
''' <para></para>
''' All frames returned must be disposed of by the caller to free resources when no longer needed.
''' </returns>
<DebuggerStepThrough>
Public Shared Function GenerateFadeInFromBlackTransition(image As MagickImage,
                                                        steps As Integer, animationDelay As Integer,
                                                        Optional frameTransformation As Action(Of MagickImage) = Nothing) As IList(Of MagickImage)
 
 
   If image Is Nothing Then
       Throw New ArgumentNullException(NameOf(image))
   End If
   If steps < 3 Then
       Throw New ArgumentOutOfRangeException(NameOf(steps), steps,
                   "The steps value must be equal to or greater than three.")
   End If
   If animationDelay <= 0 Then
       Throw New ArgumentOutOfRangeException(NameOf(animationDelay), animationDelay,
                   "The animation delay value must be greater than zero.")
   End If
 
   Dim frames As New List(Of MagickImage)
 
   Using black As New MagickImage(MagickColors.Black, image.Width, image.Height)
       For i As Integer = 0 To steps
           Dim alpha As Double = i / steps
           Using fadeImg As New MagickImage(image)
               fadeImg.Alpha(AlphaOption.On)
               fadeImg.Evaluate(Channels.Alpha, EvaluateOperator.Multiply, alpha)
 
               Dim background As New MagickImage(black)
               background.Composite(fadeImg, CompositeOperator.Over)
 
               frameTransformation?.Invoke(background)
               background.AnimationDelay = CUInt(animationDelay)
 
               frames.Add(background)
           End Using
       Next
   End Using
 
   Return frames
End Function


Fundido de salida a negro para la imagen A, y fundido de entrada desde negro para la imagen B:





Código
''' <summary>
''' Generates a sequence of transition frames between two <see cref="MagickImage"/> instances,
''' gradually fading out to black the first image, then fading in from black the second image.
''' </summary>
'''
''' <param name="firstImage">
''' The image to fade out to black.
''' </param>
'''
''' <param name="secondImage">
''' The image to fade in from black.
''' </param>
'''
''' <param name="steps">
''' The number of intermediate frames to generate for the transition.
''' <para></para>
''' A higher value may result in a smoother, slower visual transition,  
''' at the cost of increased processing time to generate the effect
''' and increased number of images / file size for the resulting animation.
''' <para></para>
''' Minimum value is 3. Default value is 5.
''' </param>
'''
''' <param name="animationDelay">
''' The time in 1/100ths of a second which must expire before splaying the next image in the transition sequence.
''' <para></para>
''' Default value is 1 (10 milliseconds).
''' </param>
'''
''' <param name="frameTransformation">
''' An <see cref="Action(Of MagickImage)"/> delegate that applies custom transformations to each frame (<see cref="MagickImage"/> object)
''' used to create the transition animation. This allows fine-tuning of image properties such as format,
''' color profile, quality and other supported properties and methods by <see cref="MagickImage"/> class.
''' <para></para>
''' Note: <paramref name="animationDelay"/> value cannot be overridden in <paramref name="frameTransformation"/> delegate.
''' <para></para>
''' Code Example in VB.NET:
''' <code>Dim transformation As Action(Of MagickImage) =
'''     Sub(x As MagickImage)
'''         x.AnimationDelay = 1 ' 10 milliseconds
'''         x.Format = MagickFormat.Jpg
'''         x.Quality = 90
'''     End Sub
'''</code>
'''
''' Code Example in C#:
''' <code>Action&lt;MagickImage&gt; transformation = (MagickImage x) =&gt; {
'''     x.AnimationDelay = 1; // 1 10 milliseconds
'''     x.Format = MagickFormat.Jpg;
'''     x.Quality = 90;
''' };</code>
''' </param>
'''
''' <returns>
''' An <see cref="IList"/> of <see cref="MagickImage"/> objects representing each frame of the transition animation.
''' <para></para>
''' All frames returned must be disposed of by the caller to free resources when no longer needed.
''' </returns>
<DebuggerStepThrough>
Public Shared Function GenerateFadeOutAndFadeInToBlackTransition(firstImage As MagickImage, secondImage As MagickImage,
                                                                steps As Integer, animationDelay As Integer,
                                                                Optional frameTransformation As Action(Of MagickImage) = Nothing) As IList(Of MagickImage)
 
   If firstImage Is Nothing Then
       Throw New ArgumentNullException(NameOf(firstImage))
   End If
   If secondImage Is Nothing Then
       Throw New ArgumentNullException(NameOf(secondImage))
   End If
   If steps < 3 Then
       Throw New ArgumentOutOfRangeException(NameOf(steps), steps,
                   "The steps value must be equal to or greater than three.")
   End If
   If animationDelay <= 0 Then
       Throw New ArgumentOutOfRangeException(NameOf(animationDelay), animationDelay,
                   "The animation delay value must be greater than zero.")
   End If
 
   Dim frames As New List(Of MagickImage)
   Using blackImage As New MagickImage(MagickColors.Black, firstImage.Width, firstImage.Height)
 
       ' PHASE 1: Fade firstImage to black
       For i As Integer = 0 To steps
           Dim alpha As Double = 1.0 - (i / steps)
 
           Dim background As New MagickImage(blackImage)
           firstImage.Alpha(AlphaOption.On)
           firstImage.Evaluate(Channels.Alpha, EvaluateOperator.Multiply, alpha)
 
           background.Composite(firstImage, CompositeOperator.Over)
 
           frameTransformation?.Invoke(background)
           background.AnimationDelay = CUInt(animationDelay)
 
           frames.Add(background)
       Next
 
       ' PHASE 2: Fade in secondImage from black
       For i As Integer = 1 To steps ' Empieza en 1 para no duplicar el frame negro
           Dim alpha As Double = i / steps
 
           Using baseImage As New MagickImage(secondImage)
               Dim background As New MagickImage(blackImage)
               baseImage.Alpha(AlphaOption.On)
               baseImage.Evaluate(Channels.Alpha, EvaluateOperator.Multiply, alpha)
 
               background.Composite(baseImage, CompositeOperator.Over)
 
               frameTransformation?.Invoke(background)
               background.AnimationDelay = CUInt(animationDelay)
 
               frames.Add(background)
           End Using
       Next
 
       Return frames
   End Using
 
End Function


Fundido de salida a negro:

Código
''' <summary>
''' Generates a sequence of transition frames, gradually fading out to black the specified <see cref="MagickImage"/> object.
''' </summary>
'''
''' <param name="image">
''' The <see cref="MagickImage"/> object to fade out to black.
''' </param>
'''
''' <param name="steps">
''' The number of intermediate frames to generate for the transition.
''' <para></para>
''' A higher value may result in a smoother, slower visual transition,  
''' at the cost of increased processing time to generate the effect
''' and increased number of images / file size for the resulting animation.
''' <para></para>
''' Minimum value is 3. Default value is 5.
''' </param>
'''
''' <param name="animationDelay">
''' The time in 1/100ths of a second which must expire before splaying the next image in the transition sequence.
''' <para></para>
''' Default value is 1 (10 milliseconds).
''' </param>
'''
''' <param name="frameTransformation">
''' An <see cref="Action(Of MagickImage)"/> delegate that applies custom transformations to each frame (<see cref="MagickImage"/> object)
''' used to create the transition animation. This allows fine-tuning of image properties such as format,
''' color profile, quality and other supported properties and methods by <see cref="MagickImage"/> class.
''' <para></para>
''' Note: <paramref name="animationDelay"/> value cannot be overridden in <paramref name="frameTransformation"/> delegate.
''' <para></para>
''' Code Example in VB.NET:
''' <code>Dim transformation As Action(Of MagickImage) =
'''     Sub(x As MagickImage)
'''         x.Format = MagickFormat.Jpg
'''         x.Quality = 90
'''     End Sub
'''</code>
'''
''' Code Example in C#:
''' <code>Action&lt;MagickImage&gt; transformation = (MagickImage x) =&gt; {
'''     x.AnimationDelay = 1; // 1 10 milliseconds
'''     x.Format = MagickFormat.Jpg;
'''     x.Quality = 90;
''' };</code>
''' </param>
'''
''' <returns>
''' An <see cref="IList"/> of <see cref="MagickImage"/> objects representing each frame of the transition animation.
''' <para></para>
''' All frames returned must be disposed of by the caller to free resources when no longer needed.
''' </returns>
<DebuggerStepThrough>
Public Shared Function GenerateFadeOutToBlackTransition(image As MagickImage,
                                                       steps As Integer, animationDelay As Integer,
                                                       Optional frameTransformation As Action(Of MagickImage) = Nothing) As IList(Of MagickImage)
 
   If image Is Nothing Then
       Throw New ArgumentNullException(NameOf(image))
   End If
   If steps < 3 Then
       Throw New ArgumentOutOfRangeException(NameOf(steps), steps,
                   "The steps value must be equal to or greater than three.")
   End If
   If animationDelay <= 0 Then
       Throw New ArgumentOutOfRangeException(NameOf(animationDelay), animationDelay,
                   "The animation delay value must be greater than zero.")
   End If
 
   Dim frames As New List(Of MagickImage)
   Using black As New MagickImage(MagickColors.Black, image.Width, image.Height)
       For i As Integer = 0 To steps
           Dim alpha As Double = 1.0 - (i / steps)
           Using fadeImg As New MagickImage(image)
               fadeImg.Alpha(AlphaOption.On)
               fadeImg.Evaluate(Channels.Alpha, EvaluateOperator.Multiply, alpha)
 
               Dim background As New MagickImage(black)
               background.Composite(fadeImg, CompositeOperator.Over)
 
               frameTransformation?.Invoke(background)
               background.AnimationDelay = CUInt(animationDelay)
 
               frames.Add(background)
           End Using
       Next
   End Using
 
   Return frames
End Function

Nota: además de esto escribí un método para generar un GIF animado a partir de un array de imágenes, pero no puedo compartirlo aquí ya que utiliza diversos elementos de mi librería comercial y es mucho lío extraer por separado cada código necesario para insertarlo y compartirlo aquí.

Navegación

[0] Índice de Mensajes

[*] Página Anterior