Category Archives: Programming

Resizable JavaFx Canvas

To make a JavaFx canvas resizable all that needs to be done is override the min/pref/max methods. Make it resizable and implement the resize method.

With this method no width/height listeners are necessary to trigger a redraw. It is also no longer necessary to bind the size of the width and height to the container.

public class ResizableCanvas extends Canvas {

    @Override
    public double minHeight(double width)
    {
        return 64;
    }

    @Override
    public double maxHeight(double width)
    {
        return 1000;
    }

    @Override
    public double prefHeight(double width)
    {
        return minHeight(width);
    }

    @Override
    public double minWidth(double height)
    {
        return 0;
    }

    @Override
    public double maxWidth(double height)
    {
        return 10000;
    }

    @Override
    public boolean isResizable()
    {
        return true;
    }

    @Override
    public void resize(double width, double height)
    {
        super.setWidth(width);
        super.setHeight(height);
        paint();
    }

Note that the resize method cannot simply call Node.resize(width,height), because the standard implementation is effectivele empty.

IAB startSetup NullPointerException

Another fine example of Googles ‘write once, let others fix our problems’. Even at this moment (June 2014) the ‘patch’ is still not in the released sdk. To solve the problem replace

 if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {

with

  PackageManager pm=mContext.getPackageManager();
  List<ResolveInfo> intentServices = pm.queryIntentServices(serviceIntent, 0);
  if (intentServices != null && !intentServices.isEmpty())

Then in the dispose code

replace

  if (mContext != null) mContext.unbindService(mServiceConn);

with

  if (mContext != null && mService!=null) mContext.unbindService(mServiceConn);

I hope this helps.

The Symbian/Qt/Nokia platform. A total nightmare.

In June/July 2011 I had the misfortune to program for a Symbian/Nokia phone. Really bad experience. Below  a list of all the shit I had to go through to get QtCreator working somewhat.

  • crappy error messages. ‘a data abort exception has occured’
  • qml is a complete paradigm shift
  • unstable operating system. ‘it might be in an unstable state if you interrupt the working of this program’
  • version control unfriendly. Often a file added by somebody else must be readded in the repository which leads to duplicate entries in the project file.
  • memory mapping of large files doesnt work
  • memory requirements are too stringent
  • debugger doesn’t work. One always gets memorydumps without access to the symbols.
  • bloody slow compilation
  • the X7 Symbian 3 phone is slow.
  • Try to get the audiostream from a decoder. With phonon it should be possible but it doesnt work.
  • just click on the ‘documentation’ tab left. You get an error ‘Die Seite konnte nicht gefunden werden ‘qthelp://com.nokia.qtcreator.220/qdoc//doc/index.html
  • sometimes code gets hidden and cannot be unhidden unless the project is opened and closed.
  • how can one create a subfolder ?
  • copying files to and from the phone more often than not does not work.
  • try to use phonon or qtmultimedia to access the decoded part of a video !
  • searching in all project files simply doesn’t work.
  • qt creator often seems to require compilation twice.  ‘build’ and then ‘run’, leads to a rebuild.
  • no linux, nor vmware. You must program in windows
  • QtCreator crashes when there are more than 4000 error messages from the compiler.
  • sometimes when adding a new file, it insists to add it somewhere in a subdirectory.
  • The arm processor in those phones is not fully functional. For instance the ‘smull’ and ‘adc’ instructions are not supported. Mainly because it is based on a too old model of the processor.
  • ‘piss-poor’ headphone volume; something many buyers noted as well
  • Filenames (without their paths) are used to identify files. So the same filename at twop different locations is treated by the make system as the same file.
  • How to set the volume of th phone ?  Yes a truly horendous hack by obtaining the address of a undocumented function and then hoping that it will actually point to the right thing ! http://bugreports.qt.nokia.com/browse/QTMOBILITY-830
  • No support from Nokia what_so_ever. Even if you are hired by them (which I inderectly was !)

I was so happy that I could stop programming for/on this utter swamp of a platform.

How to know whether a copy-on-write page is an actual copy ?

When I create a copy-on-write mapping (a MAP_PRIVATE) using mmap, then some pages of this mapping will be copied as soon as I write to specific addresses. At a certain point in my program I would like to figure out which pages have actually been copied. There is a call, called ‘mincore’, but that only reports whether the page is in memory or not, which is not the same as the page being copied or not.

In order to figure out what pages have been copied, the pagemap and kpageflags can be used. Below a quick test to check whether a page is in memory ‘SWAPBACKED’ as it is called. One problem remains of course, which is the problem that kpageflags is only accessible to the root.

int main(int argc, char* argv[])
{
  unsigned long long pagesize=getpagesize();
  assert(pagesize>0);
  int pagecount=4;
  int filesize=pagesize*pagecount;
  int fd=open("test.dat", O_RDWR);
  if (fd<=0)
    {
      fd=open("test.dat", O_CREAT|O_RDWR,S_IRUSR|S_IWUSR);
      printf("Created test.dat testfile\n");
    }
  assert(fd);
  int err=ftruncate(fd,filesize);
  assert(!err);

  char* M=(char*)mmap(NULL, filesize, PROT_READ|PROT_WRITE, MAP_PRIVATE,fd,0);
  assert(M!=(char*)-1);
  assert(M);
  printf("Successfully create private mapping\n");

The test setup contains 4 pages. page 0 and 2 are dirty

  strcpy(M,"I feel so dirty\n");
  strcpy(M+pagesize*2,"Christ on crutches\n");

page 3 has been read from.

  char t=M[pagesize*3];

page 1 will not be accessed

The pagemap file maps the process its virtual memory to actual pages, which can then be retrieved from the global kpageflags file later on. Read the file /usr/src/linux/Documentation/vm/pagemap.txt

  int mapfd=open("/proc/self/pagemap",O_RDONLY);
  assert(mapfd>0);
  unsigned long long target=((unsigned long)(void*)M)/pagesize;
  err=lseek64(mapfd, target*8, SEEK_SET);
  assert(err==target*8);
  assert(sizeof(long long)==8);

Here we read the page frame numbers for each of our virtual pages

  unsigned long long page2pfn[pagecount];
  err=read(mapfd,page2pfn,sizeof(long long)*pagecount);
  if (err<0)
    perror("Reading pagemap");
  if(err!=pagecount*8)
    printf("Could only read %d bytes\n",err);

Now we are about to read for each virtual frame, the actual pageflags

  int pageflags=open("/proc/kpageflags",O_RDONLY);
  assert(pageflags>0);
  for(int i = 0 ; i < pagecount; i++)
    {
      unsigned long long v2a=page2pfn[i];
      printf("Page: %d, flag %llx\n",i,page2pfn[i]);

      if(v2a&0x8000000000000000LL) // Is the virtual page present ?
        {
        unsigned long long pfn=v2a&0x3fffffffffffffLL;
        err=lseek64(pageflags,pfn*8,SEEK_SET);
        assert(err==pfn*8);
        unsigned long long pf;
        err=read(pageflags,&pf,8);
        assert(err==8);
        printf("pageflags are %llx with SWAPBACKED: %d\n",pf,(pf>>14)&1);
        }
    }
}

All in all, I’m not particularly happy with this approach since it requires access to a file that we in general can’t access and it is bloody complicated (how about a simple kernel call to retrieve the pageflags ?).

Converting a Photo to a Sketch

Original Photo

Value Propagation

The first step we perform is to propagate dark values. This can be found in the Gimp menu Filters | Distorts | Value Propagate. The settings are shown below

The total image after this step has a more consistent value distribution throughout the writing. This is better visible if we look in detail at the text.

Without dark value propagation with dark value propagation

 

Edge detection

The next step is an edge detection step based on the difference of Gaussians. This edge detection step will effectively make the background (which is currenltky still a bit grey) white. This is done with Gimp in Filters | Edge Detect | Difference of Gaussians. The settings are shown below

The effect on our example is shown below

An obvious effect of this operation is that the image becomes lighter in general

Light Intensitity

To solve this problem we apply an histogram normalization. In gimp this is in Colors | Auto | Normalize.  The result:

Removing the speckle

The remaining speckle can be removed with a selective gaussian blur. Filters | Blur | Selective Gaussian Blur.

Beware that this operation can take quite some time and might only be necessary when there is some anyoying speckle present.

Crop, rotate and perspective

The last step that can be performed is a rotation / cropping to align the image properly. The results are shown below, comparing the original image against the transformed image and then the pre-scaled image for your browser.

The prescaled image looks like