Programming in C#, Java, and god knows what not

Replacing Bitmap In-Place

Illustration

Sometime even the simplest application can cause the exception. For example let’s just open an image, edit it, and save it afterward. Something like this:

var image = new Bitmap("test.jpg");
// do something with image
image.Save("test.jpg");

This code will throw the really helpful “A generic error occurred in GDI+.” exception.

Fortunately, there is more than one way to skin this cat. Rather similar (and equivalent) code will work:

Bitmap image;
using (var stream = new FileStream("test.jpg", FileMode.Open)) {
    image = (Bitmap)Bitmap.FromStream(stream);
}
// do something with image
image.Save("test.jpg");

A slightly different embodiment of the same idea.

Post-Quantum Cryptography – Round Two

See also round 1 and round 3.


After a bit more than a year since round one, we are now in the round two of post-quantum cryptography standardization process.

NIST Status Report trimmed original list of 69 algorithms to 26 that will be further studied. Based on the previous experience I would think there will be a third round in a year or so but NIST leaves open a possibility that we’ll immediately get the two finalists (one for public key exchange and one for signing).

My Star Trek key signing favorite (CRYSTALS-DILITHIUM) is actually still in the game and a further analysis is encouraged - probably as close as it gets to a positive review from NIST. It’s key exchange brother CRYSTALS-KYBER might have gone a bit too far with it’s “fishy” security proof but more analysis is needed there.

Star Wars universe is also strong with NewHope key exchange algorithm. Force is indeed strong within this one and I would dare to say it remains a strong favorite - especially due to it’s current use in Chrome.

NTRU Prime is still in there but NIST did notice a bit overly optimistic security level claims that might need to be adjusted in the future. I believe constant-time decryption this algorithm brings is a really interesting thing - especially when it comes to hardware and side-channel attacks.

I noted FALCON for its performance with a small memory footprint and that won it enough points to get into round two. However, difficulty of correct implementation and a huge potential for side-channel attacks might leave it here.

DAGS, which I loved for it’s tweakability of server/client load unfortunately stayed in round one. Likewise, RLCE-KEM noted for its performance was left behind too - largely due to complexity of (correct) implementation.

One algorithm I didn’t note in round one is Three Bears. Not only it has an awesome name and uses Mersenne primes but it also offers excellent performance. Might be a worthy challenger to NewHope.

Next update in 12-18 months. :)

Displaying EOL Symbol in Visual Studio Code

inline right

As soon as I started playing with Visual Studio Code a bit more, I found it’s whitespace rendering function lacking. While it does render spaces and tabs, I found it hard to deal with the absence of EOL marking. Yes, Visual Studio Code does show that information in status line and the whole thing is not really per line setting as Code will “normalize” line endings upon load but I simply missed those buggers.

I did find a couple extensions doing it but none really worked seamlessly as I wanted them. For one, they had a separate setting for turning them on/off. While I do love my EOL characters, I don’t want to see them all the time and I definitely don’t want to go into settings to change their state when there’s perfectly good Toggle Render Whitespace menu option available. Moreover, I wanted color of EOL to fit with the existing whitespace theme rendering instead configuring it separately.

I guess it was time to make my own extension.

Well, first, there is a really good guide through building simple extension. While it might not go deep into the topic, you will have both working extension and knowledge how to debug it by the time you’re done.

Secondly, if you go into %USERPROFILE%\.vscode\extensions directory (on Windows), you will see all extensions there - including their source code. I might not be the biggest fan of JavaScript (or TypeScript) but I am definitely the fan of learning by example. If you see some other extension doing something really close to what you need, you can see how it’s working and start from there.

Lastly, publishing extension is easy too. Assuming you got your package setup correctly, you’re just a few lines away from having it in the wild world.

To sum it up, creating and publishing extension was rather interesting and easy experiment. While JavaScript and occasionally flaky documentation did cause me to spend way too much time on this, it wasn’t all too bad. Debugging experience is acceptable and it feels nice to actually make something you’ll use. Not sure I’ll repeat it any time soon but I will definitely keep it in mind.

If it sounds interesting, you can install extension from within Visual Studio Code if you search for Render CRLF, check it’s marketplace page, or take a look at the source code.

Image.FromStream Doesn't Always Preserve Exif Data

Reading Exif files within C# is easy. For example, if you want to know camera model, it is enough to simply loop through image’s properties and read it:

private static string GetCameraModel(Image image) {
    foreach (var property in image.PropertyItems) {
        if (property.Id == ExifTag.CameraModel) { //0x0110
            return ASCIIEncoding.ASCII.GetString(property.Value).Trim('\0');
        }
    }
    return null; //no model found
}

However, if you want to do anything with the file you cannot simply load it with Image.FromFile as .NET keeps image open all the way until disposal. Easy enough, just load image with Image.FromStream, like this:

Image image;
using (var stream = new FileStream(this.File.FullName, FileMode.Open, FileAccess.Read)) {
    image = Image.FromStream(stream);
}
return GetCameraModel(image);

Image loaded in this manner will not contain any Exif - just the image data. The default stream loader just tossed everything that’s not picture away. If you want to preserve picture, you need to explicitly tell it:

Image image;
using (var stream = new FileStream(this.File.FullName, FileMode.Open, FileAccess.Read)) {
    image = Image.FromStream(stream, useEmbeddedColorManagement: true, validateImageData: true);
}
return GetCameraModel(image);

Now you can read all the Exif data you can handle. :)


PS: Interestingly, it seems that on Windows 7 it works either way.

Unscaled Doesn't Mean It Won't Scale

One application I created had to show a simple, fixed image on screen. As it’s size is fixed and no resizing is needed, one might assume following code would be sufficient:

var left = (ClientRectangle.Width - bitmap.Width) / 2;
var top = (ClientRectangle.Height - bitmap.Height) / 2;
e.Graphics.DrawImageUnscaled(bitmap, left, top);
e.Graphics.DrawRectangle(SystemPens.WindowText, top, left, bitmap.Width, bitmap.Height);

Illustration

However, running this code might result in image significantly larger than the rectangle.

You see, DrawImageUnscaled will not necessarily ignore all scaling. It will attempt to preserve physical size - not size in pixels. So, if you have a screen punching above ancient 96 DPI, you will see scaling happen.

So, if you want to draw unscaled image, just use the normal DrawImage function and specify the size yourself.

Annotating Icons

Placing icon in tray is usually quite straightforward. You usually just take application icon and assign it to NotifyIcon. But what if you want to add a small annotation to tray icon (e.g. small shield)?

Well, you can do something like this. Just get application icon and draw another image on it. Yes, it does require a bit of calculation to get it into the bottom right corner but nothing that a little math cannot handle.

private static Icon GetAnnotatedIcon(Bitmap annotation) {
  var icon = GetApplicationIcon();

  if (icon != null) {
    var image = icon.ToBitmap();
    if (icon != null) {
      using (var g = Graphics.FromImage(image)) {
        g.DrawImage(annotation, (int)g.VisibleClipBounds.Width - annotation.Width - 2, (int)g.VisibleClipBounds.Height - annotation.Height - 2);
        g.Flush();
      }
    }
    return Icon.FromHandle(image.GetHicon());
  }
  return null;
}

There is only one magic moment above - how to get application icon. Fortunately, a bit of P/Invoke goes a long way.

private static Icon GetApplicationIcon() {
  var hLibrary = NativeMethods.LoadLibrary(Assembly.GetEntryAssembly().Location);
  if (!hLibrary.Equals(IntPtr.Zero)) {
    var hIcon = NativeMethods.LoadImage(hLibrary, "#32512", NativeMethods.IMAGE_ICON, 20, 20, 0);
    if (!hIcon.Equals(System.IntPtr.Zero)) {
      var icon = Icon.FromHandle(hIcon);
      if (icon != null) { return icon; }
    }
  }
  return null;
}

private static class NativeMethods {
  public const UInt32 IMAGE_ICON = 1;

  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
  static extern internal IntPtr LoadImage(IntPtr hInstance, String lpIconName, UInt32 uType, Int32 cxDesired, Int32 cyDesired, UInt32 fuLoad);

  [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
  static extern internal IntPtr LoadLibrary(string lpFileName);
}

And yes, this code doesn’t take DPI into account so your high-definition icon might suffer - let’s leave that for some other post. :)

Changing Git Commit Message

Every once in a while I figure a typo as I am hitting git commit. Mind you, it’s not that I am making a typo once in a while - I do typos all the time - I only notice them once in a while. :)

What follows is a common pair of commands:

git reset --soft HEAD~
git commit -m"Corrected spelling."

As I did with other git operations I do often enough, I decided to make it an alias:

git config --global alias.redo '!git reset --soft HEAD~ && git commit'

Now I can use a single git command to do correction:

git redo -m"Corrected spelling."

Even better, if comment is not given, command will simply move the latest commit back into the staging area.

Might not be a huge change but it does make a common operation faster.

Omitting Quotes From DebuggerDisplay

Using DebuggerDisplay is both simple and really helps with troubleshooting. However, its automatic quoting of strings can sometime result in less than optimal tooltip display.

For example, if you have Key and Value field with “Foo” and “Bar” as their respective content, you might end up with the following attribute:

DebuggerDisplay("{Key}: {Value}");

This will result in "Foo": "Bar" tooltip text. While not a big deal, these excessive quotes can be a bit of annoyance. Fortunately, you can tell DebuggerDisplay to stops its auto-quoting:

DebuggerDisplay("{Key,nq}: {Value,nq}");

This will result in much nicer-looking Foo: Bar output.

TimeSpan and HH:mm

Illustration

Time printing and parsing is always “fun” regardless of language but, for most of time C#, actually has it much better than one would expect. However, sometime one can get surprised by small details.

One application had the following (extremely simplified) code writing time entries:

var text = someDate.ToString("HH:mm", CultureInfo.InvariantCulture);

Other application had the (also simplified) parsing code:

var someTime = TimeSpan.ParseExact(text, "HH:mm", CultureInfo.InvariantCulture);

And all I got was System.FormatException: 'Input string was not in a correct format.'

Issue was not in text, all entries were valid time. Nope, issue was in a slight difference between custom DataTime and custom TimeSpan specifiers.

Reading documentation it’s really easy to note the first error as these is a clear warning: “The custom TimeSpan format specifiers do not include placeholder separator symbols.” In short that means we cannot use colon (:) as a TimeSpan separator. Nope, we need to escape it using backslash (\) character. I find this one mildly annoying as not implementing time separators into TimeSpan seems like a pretty basic functionality.

But there is also a second error that’s be invisible if you’re not watching carefully. TimeSpan has no knowledge of H specifier. It understands only its lowercase brother h. I would personally argue this is wrong. If any of those two had to be used, it should have been H as it denotes time more uniquely.

In any case, the corrected code was as follows:

var someTime = TimeSpan.ParseExact(text, "hh\\:mm", CultureInfo.InvariantCulture);

Ideally one would always want to use the same format for output as the input but just because semantics of one class are the same as the other for your use case, you cannot count of format specifier to be the same.

Broken Korean and Japanese in RichTextBox

For a while now my QText utility had an elusive issue. I got multiple reports from Korean and Japanese people that text input doesn’t work properly. Unfortunately they often wouldn’t leave e-mail or wouldn’t feed me with more information to understand the issue.

But eventually, one nice Korean gentleman did manage to show the problem by taking video of him taking notes in Notepad and QText side by side. To reproduce it on my side, I installed Korean keyboard and tried to repeat his (English) sequence: EKS CNR ZL.

In Notepad that sequence resulted with “단축키” while my QText caused text to read “단ㅊㅜㄱ키”. Due to my knowledge of the Korean Starcraft scene, I was aware that Korean letters are grouped into blocks. And obviously QText was somehow messing it up.

After a bit of bumbling around, I found the issue was in OnSelectionChanged handler with further analysis showing the SelectionLength property to be the one causing the actual issue:

protected override void OnSelectionChanged(EventArgs e) {
  this.IsSelectionEmpty = (^^this.SelectionLength^^ == 0);
  if (^^this.SelectionLength^^ == 0) { this.CaretPosition = this.SelectionStart; }
  base.OnSelectionChanged(e);
}

Next stop was Microsoft’s Reference Source for .NET where took a look into RichTextBox.cs and SelectionLength property only to see the following comment:

// RichTextBox allows the user to select the EOF character,
// but we don't want to include this in the SelectionLength.
// So instead of sending EM_GETSEL, we just obtain the SelectedText and return
// the length of it.

This little innocent note actually pointed toward SelectedText property which does a lot of work internally, including sending EM_STREAMOUT message. This call unfortunately terminates IME entry a bit early and Korean character block boundaries get broken.

Fix I decided on was to ignore EOF issue from the comment and use EM_EXGETSEL message to determine what is the current selection length. Short version of committed code went something like this:

protected override void OnSelectionChanged(EventArgs e) {
  var range = new NativeMethods.CHARRANGE();
  NativeMethods.SendMessage(this.Handle, NativeMethods.EM_EXGETSEL, IntPtr.Zero, ref range);
  this.IsSelectionEmpty = this.IsSelectionEmpty = (range.cpMin == range.cpMax);
  if (this.IsSelectionEmpty) { this.CaretPosition = range.cpMin; }
}

private class NativeMethods {
  internal const int WM_USER = 0x0400;
  internal const int EM_EXGETSEL = WM_USER + 52;

  [StructLayout(LayoutKind.Sequential)]
  internal struct CHARRANGE {
    public int cpMin;
    public int cpMax;
  }

  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
  internal static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, ref CHARRANGE lParam);
}