TatukGIS menu

Blogs

New API to edit pixel layers

DK11.1 extended API enables easy pixel layer manipulation and querying.

We offer a two sets of commands: Lock and Loop.

TGIS_LayerPixel.Lock

This is a bit low level function responsible for locking an area of a pixel layer for querying and writing. For a layer fully residing in memory, this may not seem so important. But with a huge file, performing the operation on a disk and on final resolution is not very efficient. Lock enables limiting the area of operation to any subset area of the full image, at the desired resolution, so the locked area is small enough to perform the operations efficiently. Furthermore, if a region is locked in at a lower resolution than the layer resolution, write changes are intelligently propagated back. This sample (which is derived form the PixelEdit DK source code sample) shows how to create and fill a layer (C# DK.NET):


  lp = new TGIS_LayerJPG();
  try
  {
    lp.Build(
      "test.jpg", TGIS_CSFactory.ByEPSG(4326),
      TGIS_Utils.GisExtent(-180, -90, 180, 90), 360, 180
    );
  
    // direct access to pixels
    lck = lp.Lock(TGIS_Utils.GisExtent(-45, -45, 45, 45), lp.CS, true);
    try
    {
      for (x = lck.Bounds.Left; x <= lck.Bounds.Right; x++)
      {
        for (y = lck.Bounds.Top; y <= lck.Bounds.Bottom; y++)
        {
          lck.Bitmap[lck.BitmapPos(x, y)] = (int)TGIS_Color.Red.ARGB;
        }
      }
    }
    finally
    {
      lp.Unlock(lck);
    }
    lp.SaveData();
  }
  finally
  {
    lp.Dispose();
  }
TGIS_LayerPixel.Loop

Sometimes we need something more like, for example, find all pixels within an area defined by a polygon. In the following example, we calculate the average pixel color within the area defined by a polygon and fill back the bitmap with the found color:

PixelAvgColor.jpg
Image layer modified - area of Spain filled with average color value.

  for each (TGIS_PixelItem px in lp.Loop(polygon.Extent, 0, polygon, "T", false))
  {
      r = r + px.Color.R;
      g = g + px.Color.G;
      b = b + px.Color.B;
      cnt++;
  }
  
  cl = TGIS_Color.FromARGB( 127, r/cnt, g/cnt, b/cnt);

  // and set pixels back
  for each (TGIS_PixelItem px in lp.Loop(polygon.Extent, 0, polygon, "T", true))
  {
    px.Color = cl;
  }

 

Sometimes we need something even more, such as finding a profile terrain. We can query against a linear feature (any TGIS_ShapeArc shape):


  for each (TatukGIS.NDK.TGIS_PixelItem px in lp.Loop(0, line, false))
  {
    Memo.AppendText(
      String.Format("Distance: {0}, Height:{1}\r\n", px.Distance, px.Value)
    );
  }

 

As you may have noticed, we use almost the same syntax as used with TGIS_LayerVector.Loops. And, yes, we support pixel selection. So, for example, you can query for pixels located inside a polygon area, located outside a polygon, located within a buffer, touching the polygon boundary, and more.

The features described in this blog are available on all DK11 editions and development platforms. Take a look at the DK documentation for Delphi and .NET.

Posted: January 27, 2017