ColorSnatch Release 1.2.0

 

What’s new in 1.2.0

Added:

  • Screen freeze — freeze screen updates to sample the color of elements that change on mouse‑hover
  • Point lock — monitor a color at a fixed screen location independently of cursor movement
  • Auto‑name colors — automatically generate names for new colors or rename existing ones using a color dictionary
  • Averaged color sampling — improved handling of color noise by sampling around cursor position
  • Remove duplicates from color list — keep your list clean and unique
  • Ctrl + Arrows hotkeys — fine‑tune cursor movement for precise color sampling
  • Linux (X11) support — ColorSnatch now works on Linux alongside Windows

Changed:

  • The UI is now resizable for better flexibility

Fixed:

  • UI flickering on startup
  • Missing CSS file filter when opening a color list

Download the latest version

Visit the ColorSnatch download page

LogSight Release 1.0.0

LogSight Release 1.0.0

This is to announce the official launch of LogSight version 1.0.0! This first stable release, brings powerful log analysis and monitoring capabilities to your development workflow.

Motivation

Like many developers, we often face the challenge of analyzing application log files—especially archives sent by users when troubleshooting elusive bugs. Searching for unusual behavior or pinpointing root causes can feel like looking for a needle in a haystack. Existing solutions rarely offered an interface tailored for quickly highlighting patterns or anomalies, particularly for diverse log formats. LogSight was born from the need for an application that lets you easily highlight multiple patterns with colors, making deep dives into complex logs far more manageable.

Key Features

  • Highlight multiple log patterns using customizable colors, making investigation intuitive.
  • Real-time monitoring and alerting to catch anomalies early.
  • Flexible parser definitions to adapt to various log formats.
  • Quick search tools to easily find relevant log entries.
  • Can work on local files and stdin.

To start using LogSight, download here.

Recall Wifi Release 1.0.0

I’m please to announce the launch of Recall Wifi, a compact and portable Windows tool that lets you instantly recover your saved Wi‑Fi passwords, manage network connections, and secure your wireless credentials.

What Recall Wifi Can Do

  • Recover WEP, WPA, WPA2, and WPA3 passwords stored on your system.
  • Analyze your saved networks for weak or vulnerable passwords.
  • Import or export saved networks securely (AES 256‑bit encryption optional).
  • Delete unnecessary or outdated network profiles.
  • Connect to or disconnect from saved networks with ease.
  • Access networks saved on disabled or inactive network adapters.
  • Run anywhere—no installation required; just download and launch.
Ready to get started? Visit the Downloads page to grab the latest version.

ColorSnatch 1.1.0

Color Snatch 1.1.0

I’m happy unveil the latest update for my lightweight desktop color picker and editor.

Here’s what’s new in this release:

Added

  • Harmonious Color Scheme Generator
  • Modify hotkeys for color capture and copy
  • Load colors from stylesheets (.css files)
  • Optionally capture color on mouse click

Changed

  • Scroll to newly added color in list

Fixed

  • Improved color and cursor preview performance
  • Current zoom level not being updated and saved
  • Memory error when app is closed

Download ColorSnatch from here.

ColorSnatch 1.0.0 Released

ColorSnatch 1.0.0 Released

Announcing the first official release of ColorSnatch, a lightweight cross-platform desktop color picker and color editor utility designed for developers, designers, and digital creatives!

Feature Highlights

  • Wide range of color code formats: RGB, HEX, HSL, CMYK, RGB Decimal, and HSV/HSB
  • 3x, 6x, and 9x magnification cursor preview
  • Color list for saving, cataloguing, and re-using picked colors
  • Convert color codes between formats (developer/designer friendly)
  • Optional stay-on-top behavior
  • Copy any color code to the clipboard
  • Save or load color lists to and from an external file
  • Assign name or notes to any saved color

Download ColorSnatch from here.

I look forward to your feedback and suggestions as I continue to improve ColorSnatch!

Happy coloring!

Secure Synchronization using SSH

Allows you to synchronize a directory over a secure shell connection. It also has functionality to allow you to run commands remotely, all without leaving the comfort of your local machine.

Installation

    1. Ensure Python 3 and pip are installed.
    2. Install with the following command
    pip install -r requirements.txt
    3. Run with python secure-sync.py

Usage

See secure-sync.py --help for help with parameters.

Running Commands Remotely

You can run arbitrary commands on the remote machine by populating your local directory (created by secure-sync) with a .command file. secure-sync will recognize this file and will cd to the equivalent directory on the remote machine and execute the commands in this file line by line, piping their output to your local machine.

Download

secure-sync.zip 11/04/2017 7 Kb

Dropbox Folder Restoration using Python

Restores any dropbox folder to a previous state. If a file did not exist at the specified time, it will be deleted. Handles unicode parameter input and processing of subfolders.

Example

To restore the folder /photos/tokyo to the way it was on March 7th, 2016:
python dropbox-restore.py /photos/tokyo 2016-03-07

Note: the path /photos/tokyo should be relative to your Dropbox folder; it should not include the path to the Dropbox folder on your hard drive. You will be prompted to confirm access to your Dropbox account through your web browser.

Installation

    1. Ensure Python 3.4 or higher and pip are installed.
    2. Install Dropbox Python API with the following command
    pip install dropbox
    3. Download dropbox-restore.py

Additional Notes

If you wish to modify the source code, you must obtain your own API keys from Dropbox and insert them into the APP_KEY and APP_SECRET fields.

Specifying a time is not officially supported because the time zone is ignored currently. However, it seems like Dropbox always uses UTC, so you can try specifying UTC times at your own risk by specifying the date and time in the format YYYY-MM-DD-HH-MM-SS on the command line. Be warned that Dropbox’s documentation does not guarantee that they will always use UTC, so this can break at any time.

Download

dropbox-restore.py 03/07/2016 5.5 Kb

Recursive Folder Synchronization using VBScript

This is a script written years ago that I still find useful; I had a need to apply updates to many local machines that had no network access from an external hard drive. It synchronizes the contents (files and subfolders) of two folders. Each folder is traversed recursively and any missing subfolders and files are copied both ways. If corresponding folders contain files with matching file names but with different timestamps, the file with the oldest timestamp will be overwritten.

Option Explicit

ForceScriptEngine("cscript")

Dim wshArgs
Set wshArgs = Wscript.Arguments
If WshArgs.Count = 2 Then
  Call SyncFolders(WshArgs.Item(0), WshArgs.Item(1))
  ' Also run once in reverse to catch mismatching subfolder count:
  Call SyncFolders(WshArgs.Item(1), WshArgs.Item(0))
Else
  Wscript.Echo("Wrong number of arguments. Syntax: SyncFolders Folder1 Folder2")
  Wscript.Sleep(3000) ' To allow Function syntax popup message to be seen.
End If

Sub SyncFolders(strFolder1, strFolder2)
  Dim objFileSys
  Dim objFolder1
  Dim objFolder2
  Dim objFile1
  Dim objFile2
  Dim objSubFolder
  Dim arrFolders
  Dim i
  Set objFileSys = CreateObject("Scripting.FileSystemObject")
  arrFolders = Array(strFolder1, strFolder2)
  For i = 0 To 1 ' Make sure that missing folders are created first:
    If objFileSys.FolderExists(arrFolders(i)) = False Then
      wscript.echo("Creating folder " & arrFolders(i))
      objFileSys.CreateFolder(arrFolders(i))
    End If
  Next
  Set objFolder1 = objFileSys.GetFolder(strFolder1)
  Set objFolder2 = objFileSys.GetFolder(strFolder2)
  For i = 0 To 1
    If i = 1 Then ' Reverse direction of file compare in second run
      Set objFolder1 = objFileSys.GetFolder(strFolder2)
      Set objFolder2 = objFileSys.GetFolder(strFolder1)
    End If
    For Each objFile1 in objFolder1.files
      If Not objFileSys.FileExists(objFolder2 & "\" & objFile1.name) Then
        Wscript.Echo("Copying " & objFolder1 & "\" & objFile1.name & _
          " to " & objFolder2 & "\" & objFile1.name)
        objFileSys.CopyFile objFolder1 & "\" & objFile1.name, _
          objFolder2 & "\" & objFile1.name
      Else
        Set objFile2 = objFileSys.GetFile(objFolder2 & "\" & objFile1.name)
        If objFile1.DateLastModified > objFile2.DateLastModified Then
          Wscript.Echo("Overwriting " & objFolder2 & "\" & objFile1.name & _
            " with " & objFolder1 & "\" & objFile1.name)
          objFileSys.CopyFile objFolder1 & "\" & objFile1.name, _
            objFolder2 & "\" & objFile1.name    
        End If
      End If
    Next
  Next
  For Each objSubFolder in objFolder1.subFolders
    Call SyncFolders(strFolder1 & "\" & objSubFolder.name, strFolder2 & _
      "\" & objSubFolder.name)
  Next
  Set objFileSys = Nothing
End Sub

Sub ForceScriptEngine(strScriptEng)
  ' Forces this script to be run under the desired scripting host.
  ' Valid arguments are "wscript" or "cscript".
  ' The command line arguments are passed on to the new call.
  Dim arrArgs
  Dim strArgs
  For Each arrArgs In WScript.Arguments
    strArgs = strArgs & " " & Chr(34) & arrArgs & Chr(34)
  Next
  If Lcase(Right(Wscript.FullName, 12)) = "\wscript.exe" Then
    If Instr(1, Wscript.FullName, strScriptEng, 1) = 0 Then
      CreateObject("Wscript.Shell").Run "cscript.exe //Nologo " & _
        Chr(34) & Wscript.ScriptFullName & Chr(34) & strArgs
      Wscript.Quit
    End If
  Else
    If Instr(1, Wscript.FullName, strScriptEng, 1) = 0 Then
      CreateObject("Wscript.Shell").Run "wscript.exe " & Chr(34) & _
        Wscript.ScriptFullName & Chr(34) & strArgs
      Wscript.Quit
    End If
  End If
End Sub

When only one-way sync is needed (only folder 2 is modified), use this version:

Option Explicit

ForceScriptEngine("cscript")

Dim wshArgs
Set wshArgs = Wscript.Arguments
If WshArgs.Count = 2 Then
  Call SyncFolders(WshArgs.Item(0), WshArgs.Item(1))
Else
  Wscript.Echo("Wrong number of arguments. Syntax: SyncFolders Folder1 Folder2")
  Wscript.Sleep(3000) ' To allow Function syntax popup message to be seen.
End If

Sub SyncFolders(strFolder1, strFolder2)
  ' Note: This version only copies from folder1 to folder2
  Dim objFileSys
  Dim objFolder1
  Dim objFolder2
  Dim objFile1
  Dim objFile2
  Dim objSubFolder
  Dim arrFolders
  Dim i
  arrFolders = Array(strFolder1, strFolder2)
  Set objFileSys = CreateObject("Scripting.FileSystemObject")
  For i = 0 To 1 ' Make sure that missing folders are created first:
    If objFileSys.FolderExists(arrFolders(i)) = False Then
      wscript.echo("Creating folder " & arrFolders(i))
      objFileSys.CreateFolder(arrFolders(i))
    End If
  Next
  Set objFolder1 = objFileSys.GetFolder(strFolder1)
  Set objFolder2 = objFileSys.GetFolder(strFolder2)
  For Each objFile1 in objFolder1.files
    If Not objFileSys.FileExists(objFolder2 & "\" & objFile1.name) Then
      Wscript.Echo("Copying " & objFolder1 & "\" & objFile1.name & _
        " to " & objFolder2 & "\" & objFile1.name)
      objFileSys.CopyFile objFolder1 & "\" & objFile1.name, _
        objFolder2 & "\" & objFile1.name
    Else
      Set objFile2 = objFileSys.GetFile(objFolder2 & "\" & objFile1.name)
      If objFile1.DateLastModified > objFile2.DateLastModified Then
        Wscript.Echo("Overwriting " & objFolder2 & "\" & objFile1.name & _
          " with " & objFolder1 & "\" & objFile1.name)
        objFileSys.CopyFile objFolder1 & "\" & objFile1.name, _
          objFolder2 & "\" & objFile1.name    
      End If
    End If
  Next
  For Each objSubFolder in objFolder1.subFolders
    Call SyncFolders(strFolder1 & "\" & objSubFolder.name, strFolder2 & _
      "\" & objSubFolder.name)
  Next
  Set objFileSys = Nothing
End Sub

Sub ForceScriptEngine(strScriptEng)
  ' Forces this script to be run under the desired scripting host.
  ' Valid arguments are "wscript" or "cscript".
  ' The command line arguments are passed on to the new call.
  Dim arrArgs
  Dim strArgs
  For Each arrArgs In WScript.Arguments
    strArgs = strArgs & " " & Chr(34) & arrArgs & Chr(34)
  Next
  If Lcase(Right(Wscript.FullName, 12)) = "\wscript.exe" Then
    If Instr(1, Wscript.FullName, strScriptEng, 1) = 0 Then
      CreateObject("Wscript.Shell").Run "cscript.exe //Nologo " & _
        Chr(34) & Wscript.ScriptFullName & Chr(34) & strArgs
      Wscript.Quit
    End If
  Else
    If Instr(1, Wscript.FullName, strScriptEng, 1) = 0 Then
      CreateObject("Wscript.Shell").Run "wscript.exe " & Chr(34) & _
        Wscript.ScriptFullName & Chr(34) & strArgs
      Wscript.Quit
    End If
  End If
End Sub

Oil Painting Filter in C#

Converting an image to make it look like an oil painting is not only a nice effect, but is also an easy to implement algorithm. This article demonstrates how to create an oil painting effect from an image. The oil painting filter consists of two main components: color gradients and pixel color intensities. Result images express a lesser degree of detail and tend to appear to have smaller color ranges.

Implementation

The following steps are required for the algorithm:

  1. Iterate each pixel – Every pixel forming part of the source image should be iterated. When iterating a pixel determine the neighboring pixel values based on the specified filter size (or radius).
  2. Calculate color intensityDetermine the Color Intensity of each pixel being iterated and that of the neighboring pixels. The neighboring pixels included should extend to a range determined by the Filter Size specified. The calculated value should be reduced in order to match a value ranging from zero to the number of Intensity Levels specified.
  3. Determine maximum neighborhood color intensity – When calculating the color intensities of a pixel neighborhood determine the maximum intensity value. In addition, record the occurrence of each intensity level and sum each of the Red, Green and Blue pixel color component values equating to the same intensity level.
  4. Assign the result pixel – The value assigned to the corresponding pixel in the resulting image equates to the pixel color sum total, where those pixels expressed the same intensity level. The sum total should be averaged by dividing the color sum total by the intensity level occurrence

When calculating color intensity reduced to fit the number of levels specified the formula can be expressed as follows:

colorintensityalgorithm.png

The variables in the above formula can be described as follows:

  • i – Intensity: the calculated intensity value.
  • R – Red: The value of the pixel’s red color component.
  • G – Green:
  • B – Blue:
  • l – Number of intensity levels: the maximum number of intensity levels specified.

Result Image: Filter 15, Levels 30

Oil Painting - Filter 15, Levels 30

The sample source code defines OilPaintFilter method, an extension method targeting the Bitmap class. This method determines the maximum color intensity from a pixel’s neighbors.

public static Bitmap OilPaintFilter(this Bitmap sourceBitmap, int levels, int filterSize)
        {
            Bitmap image;
            ArgbColor[] originalData;
            ArgbColor[] resultData;
            Size size;

            image = sourceBitmap;
            size = image.Size;

            originalData = image.GetPixelsFrom32BitArgbImage();
            resultData = new ArgbColor[size.Width * size.Height];

            int[] intensityBin = new int[levels];
            int[] blueBin = new int[levels];
            int[] greenBin = new int[levels];
            int[] redBin = new int[levels];

            levels = levels - 1;

            int filterOffset = (filterSize - 1) / 2;
            int byteOffset = 0;
            int calcOffset = 0;
            int currentIntensity = 0;
            int maxIntensity = 0;
            int maxIndex = 0;

            double blue = 0;
            double green = 0;
            double red = 0;

            for (int offsetY = filterOffset; offsetY < size.Height - filterOffset; offsetY++)
            {
                for (int offsetX = filterOffset; offsetX < size.Width - filterOffset; offsetX++)
                {
                    ArgbColor result;

                    blue = green = red = 0;

                    currentIntensity = maxIntensity = maxIndex = 0;

                    intensityBin = new int[levels + 1];
                    blueBin = new int[levels + 1];
                    greenBin = new int[levels + 1];
                    redBin = new int[levels + 1];

                    byteOffset = offsetY * size.Width + offsetX;

                    for (int filterY = -filterOffset; filterY <= filterOffset; filterY++)
                    {
                        for (int filterX = -filterOffset; filterX <= filterOffset; filterX++)
                        {
                            calcOffset = byteOffset + (filterX) + (filterY * size.Width);

                            currentIntensity = (int)Math.Round(((double)(originalData[calcOffset].R +
                                                originalData[calcOffset].G + originalData[calcOffset].B) / 3.0 * (levels)) / 255.0);

                            intensityBin[currentIntensity] += 1;
                            blueBin[currentIntensity] += originalData[calcOffset].B;
                            greenBin[currentIntensity] += originalData[calcOffset].G;
                            redBin[currentIntensity] += originalData[calcOffset].R;

                            if (intensityBin[currentIntensity] > maxIntensity)
                            {
                                maxIntensity = intensityBin[currentIntensity];
                                maxIndex = currentIntensity;
                            }
                        }
                    }

                    blue = blueBin[maxIndex] / maxIntensity;
                    green = greenBin[maxIndex] / maxIntensity;
                    red = redBin[maxIndex] / maxIntensity;

                    result.A = 255;
                    result.R = ClipByte(red);
                    result.G = ClipByte(green);
                    result.B = ClipByte(blue);

                    resultData[byteOffset] = result;
                }
            }

            return resultData.ToBitmap(size); ;
        }

Downloads

OilPaintingFilter.zip 13 Nov 2014 137 KB

iTunes 11 Style Scroller

Spent a couple of hours seeing if I could recreate the album scroller found in the store view of the latest version of iTunes. Uses CSS3 transforms for animation and some jQuery to handle interaction. Definitely needs tidying up, and probably only works in WebKit and latest browsers for now.

Click Me