diff --git a/changelog.md b/changelog.md
index f7447159840584b0f21b0c0455b4ddf7935ea2b0..cf6edb6d808d20c44f857f73e3de264f8a211466 100644
--- a/changelog.md
+++ b/changelog.md
@@ -4,8 +4,9 @@ Changes in tpcclib
 This is a concise list of changes; commit messages can be found in the
 [Git repository](https://gitlab.utu.fi/vesoik/tpcclib.git).
 
-## version 0.8.1 (2023-06-30, in development)
+## version 0.8.1 (2023-08-18, in development)
 
+- Added application flat2nii.
 - Updates in test scripts.
 
 ## version 0.8.0 (2023-06-29)
diff --git a/v2/simimg/CMakeLists.txt b/v2/simimg/CMakeLists.txt
index 935588dcd29522a1fcf16ef11f83670b36f9a6a4..d460593a1a9d86e0220487bd9e63f659c55a9199 100644
--- a/v2/simimg/CMakeLists.txt
+++ b/v2/simimg/CMakeLists.txt
@@ -43,6 +43,7 @@ link_directories (${CMAKE_BINARY_DIR}/v2/libtpcimage)
 
 # Add executable that is built from the source file(s) 
 # The extensions are automatically found. 
+add_executable (flat2nii flat2nii.c) 
 add_executable (hist2svg hist2svg.c) 
 add_executable (simboxes simboxes.c) 
 add_executable (simcirc simcirc.c) 
@@ -50,6 +51,7 @@ add_executable (simelli simelli.c)
 add_executable (tac2nii tac2nii.c) 
 
 # Link the executable to the libraries. 
+target_link_libraries (flat2nii tpcimage tpcdcm tpcecat tpcextensions m)
 target_link_libraries (hist2svg tpctacmod tpcift tpctac tpcextensions m)
 target_link_libraries (simboxes tpcift tpccsv tpcextensions m)
 target_link_libraries (simcirc tpcift tpccsv tpcextensions m)
@@ -59,6 +61,7 @@ target_link_libraries (tac2nii tpcimage tpcdcm tpcecat tpctac tpcift tpccsv tpce
 # Install the executable(s)
 install (
   PROGRAMS
+  ${CMAKE_CURRENT_BINARY_DIR}/flat2nii${CMAKE_EXECUTABLE_SUFFIX}
   ${CMAKE_CURRENT_BINARY_DIR}/hist2svg${CMAKE_EXECUTABLE_SUFFIX}
   ${CMAKE_CURRENT_BINARY_DIR}/simboxes${CMAKE_EXECUTABLE_SUFFIX}
   ${CMAKE_CURRENT_BINARY_DIR}/simcirc${CMAKE_EXECUTABLE_SUFFIX}
@@ -79,19 +82,25 @@ set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BIN
 #
 # Simple tests
 #
+add_test(flat2niiUsage flat2nii "--help")
 add_test(hist2svgUsage hist2svg "--help")
 add_test(simboxesUsage simboxes "--help")
 add_test(simcircUsage simcirc "--help")
 add_test(simelliUsage simelli "--help")
 add_test(tac2niiUsage tac2nii "--help")
 set_tests_properties(
-  hist2svgUsage simboxesUsage simcircUsage simelliUsage tac2niiUsage 
+  flat2niiUsage hist2svgUsage simboxesUsage simcircUsage simelliUsage tac2niiUsage 
   PROPERTIES PASS_REGULAR_EXPRESSION "Usage: *"
 )
 
 #
 # Run test scripts
 # 
+add_test (
+  NAME flat2niiTests
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test/flat2nii
+  COMMAND bash "./test_flat2nii.sh"
+)
 add_test (
   NAME hist2svgTests
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test/hist2svg
diff --git a/v2/simimg/flat2nii.c b/v2/simimg/flat2nii.c
new file mode 100644
index 0000000000000000000000000000000000000000..b230b9baeaba0262dd5f49febde4ba3d18da20b9
--- /dev/null
+++ b/v2/simimg/flat2nii.c
@@ -0,0 +1,318 @@
+/** @file flat2nii.c
+ *  @brief Create NIfTI format PET image with contents from binary flat file.
+ *  @copyright (c) Turku PET Centre
+ *  @author Vesa Oikonen
+ */
+/// @cond
+/*****************************************************************************/
+#include "tpcclibConfig.h"
+/*****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <math.h>
+#include <string.h>
+#include <time.h>
+/*****************************************************************************/
+#include "tpcextensions.h"
+//#include "tpcift.h"
+//#include "tpccsv.h"
+//#include "tpctac.h"
+#include "tpcdcm.h"
+#include "tpcecat.h"
+#include "tpcnifti.h"
+#include "tpcimage.h"
+/*****************************************************************************/
+
+/*****************************************************************************/
+static char *info[] = {
+  "Create a 4D PET image file in NIfTI 1S format, with contents from",
+  "the 32-bit float values in flat binary file.",
+  "Flat file must contain the pixel values in order t>z>y>x.",
+  " ",
+  "Usage: @P [Options] flatfile xdim ydim zdim tdim imagefile",
+  " ",
+  "Options:",
+  " -pxlsize=<x,y,z>",
+  "     Pixel sizes in x, y, and z dimensions in mm; by default 1 mm each.",
+  " -stdoptions", // List standard options like --help, -v, etc
+  " ",
+  "Examples:",
+  "     @P -pxlsize=2.5,2.5,3.0 data.bin 128 128 63 25 output",
+  " ",
+  "See also: img2flat, tac2nii, nii_ehdr, img2tif, simboxes, simcirc, pxl2mask",
+  " ",
+  "Keywords: image, NIfTI, simulation, software testing",
+  0};
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* Turn on the globbing of the command line, since it is disabled by default in
+   mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
+   In Unix&Linux wildcard command line processing is enabled by default. */
+/*
+#undef _CRT_glob
+#define _CRT_glob -1
+*/
+int _dowildcard = -1;
+/*****************************************************************************/
+
+/*****************************************************************************/
+/**
+ *  Main
+ */
+/*****************************************************************************/
+int main(int argc, char **argv)
+{
+  int    ai, help=0, version=0, verbose=1;
+  char   flatfile[FILENAME_MAX], dbname[FILENAME_MAX];
+  int    dimx=0, dimy=0, dimz=0, dimt=0;
+  double pxlsize[3]={1.0,1.0,1.0};
+  int    ret=0;
+
+
+  /*
+   *  Get arguments
+   */
+  if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
+  flatfile[0]=dbname[0]=(char)0;
+
+  /* Options */
+  for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
+    char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
+    if(strncasecmp(cptr, "PXLSIZE=", 8)==0) {
+      if(atofList(cptr+8, ",", pxlsize, 3)<3)
+        {fprintf(stderr, "Error: invalid pixel sizes.\n"); return(1);}
+      if(!(pxlsize[0]>0.0) || !(pxlsize[1]>0.0) || !(pxlsize[2]>0.0))
+        {fprintf(stderr, "Error: invalid pixel sizes.\n"); return(1);}
+      continue;
+    }
+    if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
+    fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
+    return(1);
+  } else break; // tac name argument may start with '-'
+
+  TPCSTATUS status; statusInit(&status);
+  statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
+  status.verbose=verbose-1;
+  
+  /* Print help or version? */
+  if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
+  if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
+  if(version) {tpcPrintBuild(argv[0], stdout); return(0);}  
+
+  /* Process other arguments, starting from the first non-option */
+  ret=0;
+  if(ai<argc) {strlcpy(flatfile, argv[ai], FILENAME_MAX); ai++;}
+  if(ai<argc) {if(atoiCheck(argv[ai++], &dimx)) ret++;}
+  if(ai<argc) {if(atoiCheck(argv[ai++], &dimy)) ret++;}
+  if(ai<argc) {if(atoiCheck(argv[ai++], &dimz)) ret++;}
+  if(ai<argc) {if(atoiCheck(argv[ai++], &dimt)) ret++;}
+  if(ret || dimx<1 || dimy<1 || dimz<1 || dimt<0) {
+    fprintf(stderr, "Error: invalid dimension.\n");
+    return(1);  
+  }
+  if(ai<argc) {strlcpy(dbname, argv[ai], FILENAME_MAX); ai++;}
+  if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
+
+  /* Is something missing or wrong? */
+  if(!dbname[0]) {
+    fprintf(stderr, "Error: missing command-line argument; use option --help\n");
+    return(1);
+  }
+  
+  /* In verbose mode print arguments and options */
+  if(verbose>1) {
+    printf("flatfile := %s\n", flatfile);
+    printf("dbname := %s\n", dbname);
+    printf("dimx := %d\n", dimx);
+    printf("dimy := %d\n", dimy);
+    printf("dimz := %d\n", dimz);
+    printf("dimt := %d\n", dimt);
+    printf("sizex := %g\n", pxlsize[0]);
+    printf("sizey := %g\n", pxlsize[1]);
+    printf("sizez := %g\n", pxlsize[2]);
+    fflush(stdout);
+  }
+
+  /* Make NIfTI filenames */
+  if(verbose>1) printf("Make NIfTI file names\n");
+  char hdrfile[FILENAME_MAX], imgfile[FILENAME_MAX], siffile[FILENAME_MAX];
+  if(niftiCreateFNames(dbname, hdrfile, imgfile, siffile, IMG_FORMAT_NIFTI_1S)) {
+    fprintf(stderr, "  Error: invalid NIfTI name %s\n", dbname);
+    return(1);
+  }
+
+
+  /* Allocate memory for float data */
+  if(verbose>1) printf("Allocate memory for flat data\n");
+  size_t pxlNr=(size_t)dimz*dimy*dimx*dimt;
+  float *fdata;
+  fdata=(float*)calloc(pxlNr, sizeof(float));
+  if(fdata==NULL) {
+    fprintf(stderr, "Error: out of memory.\n");
+    return(2);
+  }
+
+  /*
+   *  Read the binary file
+   */
+  {
+    FILE *fp;
+    if(verbose>1) printf("Opening input datafile %s\n", flatfile);
+    if((fp=fopen(flatfile, "rb")) == NULL) {
+      fprintf(stderr, "Error: cannot open file %s\n", flatfile); 
+      free(fdata); return(3);
+    }
+    float *fptr=fdata;
+    size_t rnr=fread((char*)fptr, 4, pxlNr, fp);
+    if(rnr==0) {
+      fprintf(stderr, "Error: cannot read file %s\n", flatfile); 
+      fclose(fp); free(fdata); return(3);
+    }
+    if(rnr<pxlNr) {
+      fprintf(stderr, "Error: binary file does not contain data for all pixels.\n"); 
+      fclose(fp); free(fdata); return(3);
+    }
+    /* Check that we are at the end of the binary file; feof() does not help here */
+    char buf[10];
+    rnr=fread(buf, 4, 1, fp);
+    if(rnr!=0) {
+      fprintf(stderr, "Error: mismatching matrix size and binary data.\n"); 
+      fclose(fp); free(fdata); return(3);
+    }
+    fclose(fp);
+  }
+
+  /* Find the range of pixel values */
+  float pxlmin, pxlmax; pxlmin=pxlmax=nanf("");
+  for(size_t i=0; i<pxlNr; i++) if(!isfinite(pxlmin) || fdata[i]<pxlmin) pxlmin=fdata[i];
+  for(size_t i=0; i<pxlNr; i++) if(!isfinite(pxlmax) || fdata[i]>pxlmax) pxlmax=fdata[i];
+  if(verbose>1) {
+    printf("  pxlmin := %g\n", pxlmin);
+    printf("  pxlmax := %g\n", pxlmax);
+  }
+
+
+  /* 
+   *  Set NIfTI header contents
+   */
+  if(verbose>1) printf("Fill NIfTI header\n");
+  NIFTI_DSR dsr;
+  dsr.n=1;
+  /* Set NIfTI byte order to current machines byte order */
+  dsr.byte_order=endianLittle();
+  /* Initiate header structures with zeroes */
+  memset(&dsr.h1, 0, sizeof(NIFTI_1_HEADER));
+  memset(&dsr.e, 0, sizeof(NIFTI_EXTENDER));
+  /* Set header */
+  dsr.h1.sizeof_hdr=NIFTI1_HEADER_SIZE;
+  strcpy(dsr.h1.data_type, "");
+  strlcpy(dsr.h1.db_name, dbname, 17);
+  dsr.h1.extents=16384; // not used in NIfTI, but required for Analyze compatibility
+  dsr.h1.regular='r'; // not used in NIfTI, but required for Analyze compatibility
+  dsr.h1.dim_info='\0'; // MRI slice ordering
+  /* Image dimension */
+  for(int i=0; i<8; i++) dsr.h1.dim[i]=1;
+  dsr.h1.dim[0]=4;
+  dsr.h1.dim[1]=dimx;
+  dsr.h1.dim[2]=dimy;
+  dsr.h1.dim[3]=dimz;
+  dsr.h1.dim[4]=dimt;
+  dsr.h1.intent_p1=0.0;
+  dsr.h1.intent_p2=0.0;
+  dsr.h1.intent_p3=0.0;
+  dsr.h1.intent_code=NIFTI_INTENT_NONE;
+  dsr.h1.datatype=NIFTI_DT_FLOAT; // data as floats, so no need to scale
+  dsr.h1.bitpix=32;
+  dsr.h1.slice_start=0;
+  for(int i=0; i<8; i++) dsr.h1.pixdim[i]=0.0;
+  // https://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/qsform.html
+  dsr.h1.pixdim[0]=1.0; // Set to either 1.0 or -1.0
+  dsr.h1.pixdim[1]=pxlsize[0]; // pixel size in x dimension
+  dsr.h1.pixdim[2]=pxlsize[1]; // pixel size in y dimension
+  dsr.h1.pixdim[3]=pxlsize[2]; // pixel size in z dimension
+  dsr.h1.vox_offset=352; // Would be 0 for 1D format
+  dsr.h1.scl_slope=1.0; // no need to scale pixel values
+  dsr.h1.scl_inter=0.0; // no need to scale pixel values
+  dsr.h1.slice_end=0;
+  dsr.h1.slice_code=0;
+  dsr.h1.xyzt_units=NIFTI_UNITS_MM+NIFTI_UNITS_SEC;
+  dsr.h1.cal_max=pxlmax;
+  dsr.h1.cal_min=pxlmin;
+  dsr.h1.slice_duration=0.0;
+  dsr.h1.toffset=0.0;
+  dsr.h1.glmax=dsr.h1.cal_max; // unused in NIfTI
+  dsr.h1.glmin=0; // unused in NIfTI
+  strlcpy(dsr.h1.descrip, "flat2nii", 80);
+  strcpy(dsr.h1.aux_file, "");
+  dsr.h1.qform_code=0;
+  dsr.h1.sform_code=0;
+  dsr.h1.quatern_b=0;
+  dsr.h1.quatern_c=0;
+  dsr.h1.quatern_d=0;
+  dsr.h1.qoffset_x=0;
+  dsr.h1.qoffset_y=0;
+  dsr.h1.qoffset_z=0;
+  for(int i=0; i<4; i++) dsr.h1.srow_x[i]=0;
+  for(int i=0; i<4; i++) dsr.h1.srow_y[i]=0;
+  for(int i=0; i<4; i++) dsr.h1.srow_z[i]=0;
+  strcpy(dsr.h1.intent_name, "");
+  strcpy(dsr.h1.magic, "n+1");  // Would be "ni1" for 1D format
+  /* Extension is left as 0 0 0 0 */
+
+
+  /*
+   *  Write NIfTI header
+   */
+  if(verbose>1) printf("Writing NIfTI header\n");
+  /* Delete previous NIfTI */
+  /* It does not need to be valid NIfTI format, just that the file names match */
+  if(fileExist(hdrfile)) remove(hdrfile);
+  if(fileExist(imgfile)) remove(imgfile);
+  //if(fileExist(siffile)) remove(siffile);
+  /* Write NIfTI header */
+  if(niftiWriteHeader(hdrfile, &dsr, verbose-1)) {
+    fprintf(stderr, "Error: cannot write header.\n");
+    free(fdata);
+    return(11);
+  }
+
+  /*
+   *  Write NIfTI matrix data
+   */
+  if(verbose>1) printf("Writing NIfTI image data\n");
+  FILE *fp=fopen(imgfile, "r+b");
+  if(fp==NULL) {
+    fprintf(stderr, "Error: cannot open %s for write.\n", imgfile);
+    free(fdata);
+    if(fileExist(hdrfile)) remove(hdrfile);
+    if(fileExist(imgfile)) remove(imgfile);
+    return(12);
+  }
+  /* Move file pointer to the place of matrix data start */
+  if(fseeko(fp, (size_t)dsr.h1.vox_offset, SEEK_SET)!=0) {
+    fprintf(stderr, "Error: invalid file write position.\n");
+    fclose(fp); free(fdata);
+    if(fileExist(hdrfile)) remove(hdrfile);
+    if(fileExist(imgfile)) remove(imgfile);
+    return(13);
+  }
+  /* Write data */
+  if(fwrite(fdata, sizeof(float), pxlNr, fp) != pxlNr) {
+    fprintf(stderr, "Error: cannot write image matrix.\n");
+    fclose(fp); free(fdata);
+    if(fileExist(hdrfile)) remove(hdrfile);
+    if(fileExist(imgfile)) remove(imgfile);
+    return(14);
+  }
+  fclose(fp); free(fdata);
+  if(verbose>0) printf("written %s\n", imgfile);
+
+  return(0);
+}
+/*****************************************************************************/
+
+/*****************************************************************************/
+/// @endcond
+/*****************************************************************************/
diff --git a/v2/simimg/test/flat2nii/test_flat2nii.sh b/v2/simimg/test/flat2nii/test_flat2nii.sh
new file mode 100644
index 0000000000000000000000000000000000000000..731103a2dba9e148b4430823506bc170c91f5a8f
--- /dev/null
+++ b/v2/simimg/test/flat2nii/test_flat2nii.sh
@@ -0,0 +1,168 @@
+#!/bin/bash
+#: Title      : test_flat2nii
+#: Date       : 2023-08-18
+#: Author     : "Vesa Oikonen" <vesa.oikonen@utu.fi>
+#: Options    : None
+
+# Set the name of executable to test
+if [ -n "${OS+1}" ] && [ "$OS" = "Windows_NT" ]; then
+EXT=.exe;
+else
+EXT=;
+fi
+PROGRAM=../../flat2nii$EXT;
+if [ ! -f $PROGRAM ]; then
+  printf "Failed: executable does not exist.\n"
+  exit 1
+fi
+
+printf "=====================================================================\n"
+printf "creating test data for %s\n" $PROGRAM
+printf "=====================================================================\n"
+
+
+if [ ! -f flat1.txt ] || [ ! -f flat1.bin ]; then
+  printf "\n creating flat1.txt \n"
+  printf "frame 1 plane 1\n"
+  printf "0 0 0 0 0\n" >  flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "frame 1 plane 2\n"
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "frame 1 plane 3\n"
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "0 0 0 0 0\n" >> flat1.txt
+  printf "frame 2 plane 1\n"
+  printf "1 0 0 0 0\n" >> flat1.txt
+  printf "0 1 0 0 0\n" >> flat1.txt
+  printf "0 0 1 0 0\n" >> flat1.txt
+  printf "0 0 0 1 0\n" >> flat1.txt
+  printf "0 0 0 0 1\n" >> flat1.txt
+  printf "0 0 0 0 1\n" >> flat1.txt
+  printf "frame 2 plane 2\n"
+  printf "2 2 0 0 0\n" >> flat1.txt
+  printf "2 2 2 0 0\n" >> flat1.txt
+  printf "0 2 2 2 0\n" >> flat1.txt
+  printf "0 0 2 2 2\n" >> flat1.txt
+  printf "0 0 0 2 2\n" >> flat1.txt
+  printf "0 0 0 0 2\n" >> flat1.txt
+  printf "frame 2 plane 3\n"
+  printf "3 3 0 0 0\n" >> flat1.txt
+  printf "3 3 3 0 0\n" >> flat1.txt
+  printf "0 3 3 3 0\n" >> flat1.txt
+  printf "0 0 3 3 3\n" >> flat1.txt
+  printf "0 0 0 3 3\n" >> flat1.txt
+  printf "0 0 0 0 3\n" >> flat1.txt
+
+  printf "\n creating flat1.bin \n"
+  asc2flat flat1.txt flat1.bin
+  if [ $? -ne 0 ] ; then printf "Failed!\n" ; exit 1 ; fi
+fi
+
+
+
+printf "=====================================================================\n"
+printf "testing %s\n" $PROGRAM
+printf "=====================================================================\n"
+
+
+printf "\n\n 1.0.0 \n"
+printf " Test case: Make image from flat file. \n"
+printf " Expected result: Correct image created. \n\n"
+
+rm -f output.nii
+
+$PROGRAM flat1.bin 5 6 3 2 output
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+img2tif -s output.nii
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+img2flat --silent output.nii output.bin
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+diff flat1.bin output.bin
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n passed. \n"
+
+nii_lhdr output.nii > header.txt
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+iftisval header.txt pixdim "1 1 1 1 0 0 0 0"
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n passed. \n"
+
+
+printf "\n\n 1.0.1 \n"
+printf " Test case: Same but set pixel size and overwrite existing image. \n"
+printf " Expected result: Correct image created. \n\n"
+
+$PROGRAM -pxlsize=2.2,2.3,2.5 flat1.bin 5 6 3 2 output
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+
+nii_lhdr output.nii > header.txt
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+iftisval header.txt pixdim "1 2.2 2.3 2.5 0 0 0 0"
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n passed. \n"
+
+
+
+printf "\n\n 2.0.0 \n"
+printf " Test case: Missing argument. \n"
+printf " Expected result: Error. \n\n"
+
+$PROGRAM flat1.bin 5 6 3 2 1>stdout.txt 2>&1
+if [ $? -eq 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+iftisval stdout.txt Error "missing command-line argument; use option --help"
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n passed. \n"
+
+$PROGRAM flat1.bin 5 6 3 output 1>stdout.txt 2>&1
+if [ $? -eq 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+iftisval stdout.txt Error "invalid dimension."
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n passed. \n"
+
+
+
+printf "\n\n 2.1.0 \n"
+printf " Test case: Mismatching matrix size. \n"
+printf " Expected result: Error. \n\n"
+
+$PROGRAM flat1.bin 5 6 3 3 output 1>stdout.txt 2>&1
+if [ $? -eq 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+iftisval stdout.txt Error "binary file does not contain data for all pixels."
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n passed. \n"
+
+$PROGRAM flat1.bin 5 6 3 1 output 1>stdout.txt 2>&1
+if [ $? -eq 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n ok \n"
+iftisval stdout.txt Error "mismatching matrix size and binary data."
+if [ $? -ne 0 ] ; then printf "\nFailed!\n" ; exit 1 ; fi
+printf "\n passed. \n"
+
+
+printf "\n===================================================================\n"
+printf "   All passed! \n"
+printf "===================================================================\n"
+exit 0
+