diff --git a/data-access/servlet/src/main/java/datasets/Cutout.java b/data-access/servlet/src/main/java/datasets/Cutout.java
index 9cb950779ea27a69ac4c3f8613bf33e0d407acce..096312f53c49d3ebfb88c240666e05648c045edf 100644
--- a/data-access/servlet/src/main/java/datasets/Cutout.java
+++ b/data-access/servlet/src/main/java/datasets/Cutout.java
@@ -19,7 +19,7 @@ public interface Cutout
    public CutResult doFile(String relPathname, int hdunum, Pos pos, Band band, Time time, Pol pol,
          boolean countNullValues, FitsCard[] extraCards)
          throws IOException, InterruptedException;
-;
+
 
 }
 
diff --git a/data-access/servlet/src/main/java/datasets/CutoutImpl.java b/data-access/servlet/src/main/java/datasets/CutoutImpl.java
index cd2a6e9e6af5d42934dca63c0c4e182580f7d3a8..b584ed6a5ca91e5c9f1c886b921faeca51c05e6d 100644
--- a/data-access/servlet/src/main/java/datasets/CutoutImpl.java
+++ b/data-access/servlet/src/main/java/datasets/CutoutImpl.java
@@ -47,14 +47,6 @@ class CutoutImpl implements Cutout
       this.settings = settings;
    }
 
-/*
-   public DatasetsImpl(Settings settings, Subsurvey[] subsurveys)
-   {
-      LOGGER.info("trace DatasetsImpl(settings, subsurveys)");
-      this.settings = settings;
-      this.subsurveys = subsurveys;
-   }
-*/
 
    private String genRegionForVlkbOverlapCmd(Pos pos, Band band)
    {
@@ -182,57 +174,111 @@ class CutoutImpl implements Cutout
       }
 
 
-   public CutResult doFile(String relPathname, int hdunum,
-         Pos pos, Band band, Time time, Pol pol,
-         boolean countNullValues, FitsCard[] extraCards)
-         throws IOException, InterruptedException
+
+   private NullValueCount doCountNullValues(String absPathname, int hdunum)
+      throws IOException, InterruptedException
       {
-         LOGGER.info("trace: " + pos.toString() );
+         ByteArrayOutputStream bos = new ByteArrayOutputStream();
+         if(bos == null)
+            throw new AssertionError("byte output stream for bounds was not created, is null");
 
-         CutResult cutResult = new CutResult();
+         String[] cmdBounds = new String[3];
+         cmdBounds[0] = "/usr/local/bin/vlkb";
+         cmdBounds[1] = "nullvals";
+         cmdBounds[2] = absPathname;
 
-         if(settings.amqpConn.isHostnameEmpty())
-         {
-            LOGGER.info("Using doStream() to local file");
+         ExecCmd exec = new ExecCmd();
+         exec.doRun(bos, cmdBounds);
+         LOGGER.info("exec NullVals exitValue: " + exec.exitValue);
 
-            String absSubimgPathname = settings.fitsPaths.cutouts()
-               + "/" + generateSubimgPathname(relPathname, hdunum);
+         bos.close();
 
-            LOGGER.info("Uses local filename : " + absSubimgPathname);
+         boolean hasResult = (exec.exitValue == 0);
+         if(hasResult)
+         {
+            String nullValsString = new String(bos.toByteArray());
+            LOGGER.info("vlkb nullvals: " + nullValsString);
 
-            OutputStream fileOutputStream = new FileOutputStream( new File(absSubimgPathname) );
+            if((nullValsString != null) && nullValsString.trim().isEmpty())
+            {
+               throw new AssertionError("'vlkb nullvals' returned empty string");
+            }
 
-            doStream(relPathname, hdunum, pos, band, time, pol, fileOutputStream);
+            // parse result: '<fill-ratio> <nullvals-count> <tot-count>'
 
-            // engine returns absPathname see common/cutout.cpp::do_cutout_file()
-            cutResult.filename = absSubimgPathname;
-            cutResult.filesize = Files.size(Paths.get(absSubimgPathname));
+            String[] splitStr = nullValsString.trim().split("\\s+");
+            if(splitStr.length != 3) throw new AssertionError("'vlkb nullvals' did not return 3 numbers but: " + nullValsString);
 
-            if(countNullValues)
-            {
-               LOGGER.info("NullValuesCount not implemented when used with Cutout::doStream()");
-            }
-         }
+            NullValueCount nvc = new NullValueCount();
+            nvc.percent = Double.parseDouble(splitStr[0]);
+            nvc.nullCount = Long.parseLong(splitStr[1]);
+            nvc.totalCount = Long.parseLong(splitStr[2]);
+            return nvc;
+         } 
          else
          {
-            LOGGER.info("Using AMQP");
+            throw new AssertionError("'vlkb nullvals' exited without results for: " + absPathname);
+         }
+      }
 
-            JsonEncoder jReq = new JsonEncoder();
-            jReq.add(relPathname, hdunum);
-            jReq.add(pos);
-            jReq.add(band);
-            jReq.add(time);
-            jReq.add(pol);
-            jReq.add(countNullValues);
-            jReq.add(extraCards);
 
-            String outJson = doRpc( jReq.toString() );
 
-            cutResult = JsonDecoder.responseFromCutoutJson( outJson );
+   public CutResult doFile(String relPathname, int hdunum,
+         Pos pos, Band band, Time time, Pol pol,
+         boolean countNullValues, FitsCard[] extraCards)
+      throws IOException, InterruptedException
+   {
+      LOGGER.info("trace: " + pos.toString() );
+
+      CutResult cutResult = new CutResult();
+
+      if(settings.amqpConn.isHostnameEmpty())
+      {
+         LOGGER.info("Using doStream() to local file");
+
+         String absSubimgPathname = settings.fitsPaths.cutouts()
+            + "/" + generateSubimgPathname(relPathname, hdunum);
+
+         LOGGER.info("Uses local filename : " + absSubimgPathname);
+
+         OutputStream fileOutputStream = new FileOutputStream( new File(absSubimgPathname) );
+
+         doStream(relPathname, hdunum, pos, band, time, pol, fileOutputStream);
+
+         // engine returns absPathname see common/cutout.cpp::do_cutout_file()
+         cutResult.filename = absSubimgPathname;
+         cutResult.filesize = Files.size(Paths.get(absSubimgPathname));
+
+         if(countNullValues)
+         {
+              cutResult.nullValueCount = doCountNullValues(absSubimgPathname, 1);
          }
 
-         return cutResult;
+         if(extraCards == null || (extraCards.length < 1))
+         {
+            LOGGER.info("Adding extraCards to cut-file not implemented when using 'vlkb' exec (implemented in engine vlkbd/AMQP)");
+         }
       }
+      else
+      {
+         LOGGER.info("Using AMQP");
+
+         JsonEncoder jReq = new JsonEncoder();
+         jReq.add(relPathname, hdunum);
+         jReq.add(pos);
+         jReq.add(band);
+         jReq.add(time);
+         jReq.add(pol);
+         jReq.add(countNullValues);
+         jReq.add(extraCards);
+
+         String outJson = doRpc( jReq.toString() );
+
+         cutResult = JsonDecoder.responseFromCutoutJson( outJson );
+      }
+
+      return cutResult;
+   }