2016
02.04

Yesterday, I found myself in need of a TIFF image splitter. Reason: The scanner in my office didn’t allow me to retain the settings after a document scan. So every time I choose to ‘End Scanning’, the output image quality setting is reset to default. Which means I need change the output settings for each of document that I want to scan. The only way was to scan all documents at one go. That lead me to the situation where a TIFF splitter is needed.

A quick Google-search brought me to a simple, free and open-source program called Tiff Splitter. It is exactly the kind of program that I need. It is simple, and does its job well.

Because it does the job well, I become interested to find out how exactly Tiff Splitter works. Since it’s an open-source, I can immediately take a dive and learn.

TiffSplit_2016-01-28_15-16-40

After we click, select an input file, or, drop a file, the event handlers will eventually call processFile method.

private void processFile(string fileName)
{
   // ... SNIP ...
   
   _configs.inputFile = fileName;

   // Configure the extractor
   RetObj retObj = TiffSplitCode.Prepare(_configs, out numOfPages);
   
   // ... SNIP ...
   
   // Let user select pages to extract
   PageSelection ps = new PageSelection(numOfPages);
   ps.ShowDialog();
   _configs.fromPage = ps.PageFrom;
   _configs.toPage = ps.PageTo;
   _configs.doOverwrite = ps.OverwriteFiles;
   
   // ... SNIP ...
   
   // do the work in separate thread
   backgroundWorkerSplit.RunWorkerAsync(_configs);
}

On the worker thread it will do the splitting

private void backgroundWorkerSplit_DoWork(object sender, DoWorkEventArgs e)
{
	ConfObj input = e.Argument as ConfObj;  
	RetObj retObj = TiffSplitCode.Split(input, _updateProgress);
	e.Result = retObj;
}

The actual work was done by TiffSplitCode

public static RetObj Split(ConfObj input, UpdateProgress updateProgress)
{
	int numOfPages = input.toPage - input.fromPage + 1;                               
	// save each image
	for (int i = 0; i < numOfPages; i++)
	{
		_coder.Save(input.fromPage - 1 + i);
		// ... SNIP ...
	}
	// ... SNIP ...
}


Hmm, it looks simple. But who is _coder? How does it able to distinguish PDF, TIFF or JPG? Different format definitely requires different treatment right (or so I thought) ?

The secret is in Prepare and CoderFactory method.

public static RetObj Prepare(ConfObj input, out int numOfPages)
{
	// .. Snipped: Validate input file ..	

	// overwrite output type if the input is PDF
	if (ext.ToUpper() == ".PDF")
		input.outputType = OutputType.PDF;

	// create output coder
	_coder = CoderFactory(input.outputType);

	// open file
	numOfPages = _coder.LoadImage(input.inputFile);

	// prepare
	_coder.Prepare(input);

	return retobj;
}

static private ICoder CoderFactory(OutputType type)
{
	switch (type)
	{
		case OutputType.TIF:
			return new TiffCoder();
		case OutputType.JPG:
			return new JpegCoder();
		case OutputType.PDF:
			return new PDFCoder();
		default:
			throw new Exception("Unknown output format.");
	}
}


So now it's clear that the actual loading and splitting in classes which implement ICoder interface. So for Tiff, the work is done by TiffCoder

public class TiffCoder : ICoder
{
	private Image _image;
	private FrameDimension _dim;
	
	// ... SNIP ...

	public int LoadImage(string fileName)
	{
		_inputImageName = fileName;
		_image = Image.FromFile(fileName);
		Guid guid = _image.FrameDimensionsList[0];
		_dim = new FrameDimension(guid);
		return _image.GetFrameCount(_dim);
	}


	public void Save(int pageNum)
	{
		_image.SelectActiveFrame(_dim, pageNum);
		string outputFileName = null;

		// ... SNIP: Output file name

		if (!_config.doOverwrite)
		{
			outputFileName = HelperMethods.ModifyFileName(outputFileName);
		}

		_image.Save(outputFileName);
	}

	// ... SNIP ...
}


Well that's interesting. The program actually uses .NET's System.Drawing.Image instead of some external library to handle TIFF. As a dig deeper, I found out that System.Drawing is actually a managed interface to Windows' native library, GDI+ (mind blown!)

I'll stop my exploration here, perhaps in the future I'll have the motivation to dig deeper than today. For more reading please check the following references:

  1. System.Drawing.Image source code
  2. brief introduction to GDI
  3. Microsoft GDI+ page
2016
01.27

Found via HN, rephrased for future reminder:

  1. Do not repeat yourself, always refactor/reuse, avoid copy-paste
  2. Name your variables for what they are for, not its type of data
  3. Name your methods for what they are going to do
  4. Don’t use magic number or string literals, use constants or readonly variables
  5. Strive to make your method testable (unit test, dependency injection, mock object)
  6. Don’t be afraid to ask for help
  7. See a bug? Fix it while you’re there, then move on
  8. Share your knowledge, it will help the point no. 6
  9. Don’t interrupt colleagues who are ‘in the flow’, related to point no. 6
  10. Take criticism with open-mind, defensive stance might turn this into religious-wars

Original source: 10 golden rules for becoming a better programmer

2015
10.07

Yesterday I was editing the data of Complete Ferry Schedule using JSON Table Editor in Chrome. Immediately I found that the “Output to JSON” button is no longer works. I opened JSON Table Editor in other browsers (Firefox, Microsoft Edge, Opera) but found that the button works fine.

Looking into Chrome’s Developer Tools, I found why the button was not working.

json.table.security.error

Alas, it’s an Uncaught Security Exception. This is the offending line:

if (opener && opener.JSONTableEditor)
{
	// ... Snipped ...
}

This part of the code was supposed to check if the current window is actually a child of previous instance of JSON Table Editor (this happens when you edit a cell which has value of a complex JavaScript object). If it does, it will update the cell value in the parent window. If it doesn’t, it will show the formatted JSON on the bottom of the page.

The obvious work around would be putting this checking inside a try-catch:

var checkedOpener;
try {
   if (opener && opener.JSONTableEditor)
      checkedOpener = opener;
}
catch (ex) {
   //Nothing to do here
}
if (checkedOpener)
{
	// ... Snipped ...
}

Problem solved!

Final Thoughts

The error is unique to Google Chrome. This bug is already reported to Chromium team on Feb 2015. Unfortunately, until today the bug’s is not yet resolved.

2015
10.06

About seven months ago, John Oliver, the Mega Reverend and CEO of the -now defunct- Our Lady of Perpetual Exemption (Be praise, be praise) warned USA about the dire state of the country’s infrastructures.

But alas, nobody heed to his call. And now they have this:

us.floods.2015

This reminds me of what my father used to say, “Prepare your umbrella before it rains”. But in this case, “prepare your dams before it rains heavily”.

2015
09.03

Today, I decided to test an old in-ear headphones that has been gathering dust in my table to see if it’s still working. Unfortunately, I found that left speaker is not as loud as the right speaker. Using it to listen any music will give me a disorienting effect. I was half-way from throwing this headphones into the rubbish bin. Suddenly, I remember that we can actually adjust the volume balance in Windows.

Here’s how I did it in my Windows 10 Professional:

  1. Right click on the Volume Icon in the System Tray. It will pop up something like below.
    volume-tray

  2. Click Sounds. A new window will pop up like below

    volume-sounds

  3. Click Playback tab.

    volume-playback

    Once above window show up, select the active device, then click Properties.

  4. Now the Speaker’s window will pop like below.

    volume-speakers

    Click the Levels tab.

  5. In the Levels tab, click the Balance button, as shown below.

    volume-levels

  6. Now the Balance window will pop up.
    volume-balance
    With this we can now adjust the balance between left and right speaker. The best way to adjust is while listening to music. This way we know immediately the best balance setting for the headphones.

That’s all. I hope it helps.

2015
08.25

I have tried, unsuccessfully, to upgrade my work PC to Windows 10 many times. It always stops at 20%. After trials and errors, I suspected that the failure was caused by any programs currently installed in my PC.

Voila, after removing some of the programs. I managed to successfully upgrade to Windows 10. Here are the list of programs that I removed from my PC:

  1. Visual Studio 2015 Community Edition
  2. Windows SDK for Visual Studio 2012
  3. Windows SDK for Visual Studio 2018

These programs should have been listed in the list of programs that need to be uninstalled before upgrading to Windows 10.

What do you think, did you have the same issue?