Skip to main content


Improve your negatives scanning

My personal experience of scanning negatives used to be rather poor: pale colours, blurry details, colour noise, etc. On the picture below the same image scanned from 35mm negative some while ago is compared to the improved one. The techniques described below are applied to the image on the right. Both scans are done via Plustek OpticFilm 8100 scanner. The sequence and logic of operations is what matters the most, and thus, they will be applicable to a wide range of other devices.

Improving negative scan process. A picture taken in Marseille, France. Kiev 4a, Kodak Portra 160.

The main idea is to allow your scanner to acquire an image with highest possible resolution avoiding scanner software image processing as much as possible. And only then the image can be digitally altered  in dedicated software (GIMP, Photoshop). Why? Because some of software scanner features, i.e. dust removal, grain reduction, decrease the image quality, i.e. blurring the fine details of acquired image. As in…
Recent posts

Inkscape extension example

Recently, when preparing figures for publications using Inkscape, I decided to simplify my life. Some of the figures can be described as 2x2, 2x3, or even 2x6 grids. Sometimes it is very awkward to rearrange them if you decide to switch from 2x6 to 3x4 or vice versa. It would be nice to have an Inkscape extension, which will minimize the efforts.

For the sake of simplicity we assume that all the elements are equal in width and should be rearranged symmetrically with respect to the vertical axis. Also, the element should be ordered according to its relative to the other elements location. The top left element is the first and the bottom right is the last one. So for example, you can visually prepare the elements and then tidy them up with a single click of our magic button.

Hint: before developing a similar extension, you may want to check the standard Align and Distribute tool (Ctrl+Shift+A).

Before writing any actual code let's take a look at some official Inkscape extensions info…

How to solve the cabal ld: library not found issue on Mac OS X

Today, after upgrading haskell platform, bumped onto a strange cabal installer problem:
$ cabal install distributive-0.4.4 Resolving dependencies...
[1 of 1] Compiling Main ( /var/folders/2k/6dnfg_x43_a21poayfbpnby40000gn/T/distributive-0.4.4-27117/distributive-0.4.4/dist/setup/setup.hs, /var/folders/2k/6dnfg_x43_a21poayfbpnby40000gn/T/distributive-0.4.4-27117/distributive-0.4.4/dist/setup/Main.o )
Linking /var/folders/2k/6dnfg_x43_a21poayfbpnby40000gn/T/distributive-0.4.4-27117/distributive-0.4.4/dist/setup/setup ...
Configuring distributive-0.4.4...
Building distributive-0.4.4...
Preprocessing library distributive-0.4.4...
[1 of 2] Compiling Data.Distributive.Generic ( src/Data/Distributive/Generic.hs, dist/build/Data/Distributive/Generic.o )
[2 of 2] Compiling Data.Distributive ( src/Data/Distributive.hs, dist/build/Data/Distributive.o )
ld: library not found for -lHStransformers-compat-
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Failed to …

How to program SPI flash memory on Digilent Nexys4 and other 7th generation devices using Vivado 2014.x

Update: The methods described below work also on Vivado 2015! Please let me know if you had any issues with other Vivado versions.

The information in the official user guides and tutorials seems to be fragmentary and sometimes out-of-date, that's why I decided to fill in this gap, not waiting for the official Xilinx updates. Our goal is to show how to program the SPI flash memory of the 7th generation Xilinx devices with Vivado 2014 on example of Nexys4 board.

Note: before we start, we assume you already have a working project, that means the generated bitstream file works on your device. If not, you may want to go directly to the Program the SPI flash section to test your Nexys4 board with prepared .mcs file.
PlanConfigure the hardware to work with SPI flash memoryRegenerate the bitstream fileConvert the bitstream file into the "Prom" formatProgram the SPI flashBoot the device Configure the hardware to work with SPI flash memory Open the synthesized or implemented design…

How to install and run Vivado 2014.x

Now I am going to share some experience in the FPGA area. It appears, the now-supported tool by Xilinx, Vivado, may be ridiculously tricky to install on Ubuntu.

The main gotcha is actually to run the installer. So if you use the web-installer (approx 73MB), you may run into a "no file found" problem while installer self extracting. Looking around the official Xilinx support site, you will find a "fix". For the sake of installation, you need to temporarily replace /bin/sh -> /bin/dash with /bin/bash.

$ sudo rm /bin/sh $ sudo ln -s /bin/bash /bin/sh
Then you may wonder how to run the Vivado machinery. To simplify things, I have created a simple shell script in my home:

source /[installation path]/Xilinx/Vivado/2014.[x]/[installation path]/Xilinx/Vivado/2014.[x]/bin/vivado
Do not forget to

$ chmod +x .
And voila

./ ****** Vivado v2014.2 (64-bit) **** SW Build 932637 on Wed Jun 11 13:08:52 MDT 2014 **** IP Build 924643 on…

Vim tip: calculate an expression

Whenever need to evaluate an expression while editing code in Vim? No need to switch the window.
Use :echo.
Try this :echo 2+2 or this :echo sqrt(2). How about :echo pow(2,10)? Surprise, 1024.

Code sugar and high-level concepts

Let us multiply all the elements from the set {1, 2, 13} by all the elements of {7, 5}.
Thinking in imperative languages, one may come with two nested loops (or iterators).

Speaking C++
#include <iostream> using namespace std; int main() { int a [] = {1, 2, 13}; int b [] = {7, 5}; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { cout << a[i] * b[j] << endl; } } return 0; }
In Python I'd rather utilize a list comprehension
>>>  [a * b for a in [1, 2, 13] for b in [7, 5]]
The same goes to the blocks in ruby
> [1, 2, 13].each do |x| [7, 5].each { |y| puts x * y } end
One may find analogous list comprehensions in Haskell. But they aren't cool here.
All you need is applicative functors aka Control.Applicative
(*) <$> [1,2,13] <*> [7,5] Bonus: have you noticed, the C++ code contains a bug which is passed by the compiler? There are only two elements in array b, not three! The pr…