Tahir Hassan's Blog

My Technical Notes

Tuesday, 28 March 2017

Using Gimp for precise cropping

Gimp is an excellent tool for precisely cropping an image. Once Gimp is loaded, you an open an image by either using File → Open (Ctrl-o), or using invoking Gimp from the command line passing in the path of the file. Because Gimp takes a long time to load, it is not worth having multiple instances of it open; rather, have one instance open, and open the files you wish to edit in this one instance.

Once you have opened the image in Gimp, select the cropping tool:

Draw a rectangle anywhere on the screen. In the Tool Options, in the `Size` textboxes, set the aspect ratio, for example, 16 by 9.Then tick `Fixed` and select `Aspect Ratio` drop the drop down:

Because the aspect ratio is fixed, if you enter a new size value in the Size textbox and tab out of it, the other size value will change according to the ratio.

Drag the rectangle around to capture your desired region. Click on Image → "Crop to Selection". Save this new image.

Monday, 27 March 2017

Converting ORG to PDF with custom CSS styling

OrgMode is a very simple and easy to use plugin for Emacs that allows you to organize yourself using text only.

One drawback of it is that Emacs/OrgMode has a high learning curve: too many keyboard shortcuts to remember, requires use of lisp to customise output etc.

However, its main strength is that OrgMode files are purely text - and text is very easy to process.

Emacs OrgMode already has PDF output capability (via LaTeX). However, to style its output, you have to use custom Lisp functions containing LaTeX code. As I am unfamiliar with both LaTeX and Lisp, I wanted to use familiar technologies, such as CSS, to style the content, and use Emacs purely for editing the OrgMode files.

Installing Pandoc   Pandoc needs to be installed first.

Installing wkhtmltopdf   wkhtmltopdf also needs to be installed because that is what actually does the HTML to PDF conversion. You also have to add `C:\Program Files\wkhtmltopdf\bin` to the `PATH` variable so it is visible to Pandoc.

Including CSS   Below is a sample css file `sample.css` which makes `.done` tasks green:


.done {
    color: green;
}

Place it in the same folder as the `.org` folder for the commands below, which reference its path, to work.

OrgMode file   The commands will be run against the following OrgMode file, `doc.org`:


* DONE this is a done task
* DONE this is a second done task.

Pandoc Command   Execute the following command to create `doc.pdf` from `doc.org`:


pandoc -t html5 --css sample.css doc.org -o doc.pdf

The `-t html5` in the command ensures that it uses `wkhtmltopdf` to create the PDF document instead of LaTeX.

Sources

  • StackOverflow.com An answer explaining the user of pandoc to convert OrgMode to PDF

Saturday, 25 March 2017

Generating Random Strings in PowerShell

As part of unit testing my PowerShell functions, I have noticed a small potential issue with having data hard-coded into unit tests. Such tests can be made to pass by hard-coding the answer in the tested function. For instance we could have a unit test for a function called `Concat-String` that takes two `string` arguments and concatenates them together:


$result = Concat-String "Tahir" "Riyadh"
Assert-AreEqual "TahirRiyadh" $result

Such a test could easily be passed by hard-coding a return value:


Function Concat-String([string]$First, [string]$Second) {
    "TahirRiyadh"
}

(Of course, a unit-testing purist would say that you need multiple tests to prevent the possibility of hard-coded values, but that is besides the point - I only want to write one unit test, not many versions of the same test with different data).

Instead, what I am now using to generate test data is the following function, `New-RandomString`:


Add-Type -AssemblyName System.Security

Function New-RandomString {
    param([Parameter()][int]$Size=10)

    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_".ToCharArray();
    
    $bytes = & {
        $data = [byte[]]::new($Size)
        $crypto = [System.Security.Cryptography.RNGCryptoServiceProvider]::new();
        $crypto.GetBytes($data)
        $data
    }

    $str = [char[]]($bytes | % { $_ % $chars.Length } | % { $chars[$_] })

    [string]::new($str)
}

Instead of hard-coding test data in the unit test, `New-RandomString` can be used to give appropriate test values:


$firstVal = New-RandomString 15
$secondVal = New-RandomString 20
$result = Concat-String $firstVal $secondVal
$expected = $firstVal + $secondVal
Assert-AreEqual $expected $result

Such a test cannot be passed by hard-coding a correct return value. It can also be run multiple times to ensure that it passes i all cases.

Sources

Wednesday, 22 March 2017

Using DebugView for Debugging AutoHotkey Scripts

DebugView is an application made by SysInternals that can be used to view debug messages produced by applications.

To create a debug message using AutoHotkey, use the `OutputDebug` command:


OutputDebug, Hello World

Because many other applications also produce debug messages, you want to be able to show only those messages produced by your AutoHotkey script. For this, you can wrap the above command in a function that prepends `[AHK] ` to messages to make them searchable:


DebugMsg(Msg) {
    OutputDebug, [AHK] %Msg%
}

This function is called by passing in a string argument, as below demonstrates. The result is that `[AHK] Hello World` will appear in DebugView's message list.


DebugMsg("Hello World")

Configuring DebugView

Filter to only include [AHK] messages

To configure DebugView to only show messages from AutoHotkey, first show the "DebugView Filter" dialog, by either doing `Ctrl-L` or Edit → Filter/Highlight. In this dialog, in the `Include` field, add `[AHK]*` and press OK. This will not filter existing messages in the list, only new ones.

Highlighting messages by color
To highlight messages containing some text by color, first select a Filter from the list, and then in the colored textbox below it, enter some text to highlight:

Strangely enough, in contrast to the filtering behavior only affecting newly captured messages, the highlighting affects existing messages too.

Other...

If DebugView is not capturing messages (with filter set as `*`), then you may have to run it as administrator.

Sunday, 19 March 2017

Resizing Images using ImageMagick on Windows

ImageMagick is a handy commandline tool for every major platform that can be used to resize images (among its other uses). To install it on Windows, the recommended installer `ImageMagick-<version>-Q16-x64-dll.exe` worked fine and added `magick.exe` to the `PATH`. The installer recommends installing GhostScript for processing PDF and GhostScript, but because we are only using it to resize images, there is no need to install it.

When resizing an image, it is worth thinking about how big you want the resized image to be. To simplify matters, you can think of the resized image as fitting into a rectangle of $n$ by $m$ pixels. When an image is resized, its aspect ratio is maintained, but it has to fit inside this rectangle.

For illustration purposes, we use `magick.exe` to create a sample image file, `wizard.jpg`:


magick.exe wizard: wizard.jpg

This image is $480$ by $640$ pixels in size. For simplicity, let's say that we wish to shrink it so that it fits inside a $400$ by $400$ square. Its larger side (vertical), which is $640$, becomes $400$, therefore this side has shrunk by a percentage, $400/640$, which is $.625$. Its horizontal therefore will be $480 * .625$, which is $300$. In summary, the resized image will be $300$ by $400$ pixels in size.

To shrink it to this size, do:


magick.exe wizard.jpg -resize 400x400 resized-wizard.jpg

Sources

Adding a `.cmd` wrapper for an executable

When wanting to invoke an `.exe` on the commandline without specifying its full path, the usual course of action is to modify the `PATH` environment variable to include the `.exe` file's directory. A simple alternative, as described here, is to to create a `.cmd` wrapper for the `.exe` and place it in a folder which is already on the `PATH` environment variable.

An example `git.cmd` file is shown below. As mentioned earlier, you must put this `.cmd` into a folder which is in `PATH` environment variable.


@echo off
"C:\Program Files\Git\bin\git.exe" %*

`@echo off` disables echoing, and `%*` passes along all incoming arguments to the `git` executable.

On the Windows command-line, whether CMD or PowerShell, you can invoke an `.exe`, `.bat` or `.cmd` without specifying the `.extension`.

Saturday, 18 March 2017

PowerShell: Get a Service's Description

The result of `Get-Service` is a set of `System.ServiceProcess.ServiceController` objects, a type which does not have a property for the description shown in the Windows Services Window. The below sample code shows how to get the description for of the `XboxNetApiSvc` service.


& {
    $svc = [System.Management.ManagementObject]::new("Win32_Service.Name='XboxNetApiSvc'")
    $svc["Description"];
    $svc.Dispose();
}

In order to get the description for a `ServiceController` object, pass in the object's `Name` property in place of `XboxNetApiSvc`.