Thursday, September 22, 2016

fileReadUpdate

code was looked over again and several issues noted:

# the image display loop did not correspond with the reading of pixels
# the display of read images loops infintely
# writing to a 3DArray was obsolete as we are only reading luminance information
# the data from each image in the stack was being written to disk separately - was deemed more unified to have all data in one file - which means knowing how to divide / modulate the bits upon reading
----------------------------------------
After further development
----------------------------------------
A list is used to add all luminance values sequentially
All values for all images in a stack are written to one file
A header is added containing image width, height and stack size
ascii output option removed

The "image Reader" reads the pixels for each image before displaying the next image in the display "Form"

new problems: (fixed)
if the file already exists, it is appended to
a new file should be made with an incremented suffix before the file extension

with FileMode.Create mode any existing file is overwritten

testing for file existence link:
https://www.dotnetperls.com/file-exists
----------------------------------------
to do:
----------------------------------------
revise tif floating point details so data can be read properly

there needs to be an image size limit and bitmap stack limit to be checked for
The form size is fixed - its is not being read from the image (from the seq) size
read and write times and feedback to the user in the console
console arguments/options

keep the image Form on top of other windows:
https://msdn.microsoft.com/en-us/library/aa984361(v=vs.71).aspx
----------------------------------------
notes:
----------------------------------------
Test sequential images are png files
a default float  type in c# is 32bit, 4 bytes, therefore the header uses 12 bytes.

image width, height, stack 'depth'
all subsequent values are floating point luminance values

A smaller data unit could possible be used

code:
https://docs.google.com/document/d/1udKRnybNhA2uYiszSP27vyKUWdabEduRkFPRZZztAVc/edit?usp=sharing

"MidSem" break Development

Goals:
* Finish Bitmap stack reading.
#tested previous code under VS2013

* Get Cuda software tested and installed

Make sure Linnet is on track with interface stuff.
Possibly help her with

problems:

Downloaded VS 2013 Community Edition which is not supported on "cross x86_32 on x86_64" architectures

Got a CUDA card - but my power supply is not compatible with it.
Switched to Dell Inspiron lap top and CUDA is running

found the "picking" demo that handles mouse interaction with a 3D model
code format is different to other simpler example file s- ie the spinning cubes - classes are defined.

some code to work through:
//--------------------------------------------------------------------------------------
// Checks if mouse point hits geometry the scene.
//--------------------------------------------------------------------------------------
HRESULT Pick()
{
    HRESULT hr;
    D3DXVECTOR3 vPickRayDir;
    D3DXVECTOR3 vPickRayOrig;
    const DXGI_SURFACE_DESC* pd3dsdBackBuffer = DXUTGetDXGIBackBufferSurfaceDesc();

    g_nNumIntersections = 0L;

    // Get the pick ray from the mouse position
    if( GetCapture() )
    {
        const D3DXMATRIX* pmatProj = g_Camera.GetProjMatrix();

        POINT ptCursor;
        GetCursorPos( &ptCursor );
        ScreenToClient( DXUTGetHWND(), &ptCursor );

        // Compute the vector of the pick ray in screen space
        D3DXVECTOR3 v;
        v.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) / pmatProj->_11;
        v.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
        v.z = 1.0f;

        // Get the inverse view matrix
        const D3DXMATRIX matView = *g_Camera.GetViewMatrix();
        const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix();
        D3DXMATRIX mWorldView = matWorld * matView;
        D3DXMATRIX m;
        D3DXMatrixInverse( &m, NULL, &mWorldView );

        // Transform the screen space pick ray into 3D space
        vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;
        vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;
        vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;
        vPickRayOrig.x = m._41;
        vPickRayOrig.y = m._42;
        vPickRayOrig.z = m._43;
    }

    // Get the picked triangle
    if( GetCapture() )
    {
        ID3DX10Mesh* pMesh;
        const D3D10_INPUT_ELEMENT_DESC* pDesc = NULL;
        UINT nDeclCount;
        g_pD3DXMesh->GetVertexDescription( &pDesc, &nDeclCount);
        g_pD3DXMesh->CloneMesh( D3DX10_MESH_32_BIT, pDesc[0].SemanticName, pDesc, nDeclCount, &pMesh);

        DWORD* pIndices;
        D3DVERTEX* pVertices;
        pVertices = (D3DVERTEX*)g_Mesh.GetRawVerticesAt(0);
        pIndices = (DWORD*)g_Mesh.GetRawIndicesAt(0);

        if( g_bUseD3DXIntersect )
        {
            // When calling D3DXIntersect, one can get just the closest intersection and not
            // need to work with a D3DXBUFFER.  Or, to get all intersections between the ray and
            // the mesh, one can use a D3DXBUFFER to receive all intersections.  We show both
            // methods.
            if( !g_bAllHits )
            {
                // Collect only the closest intersection
                UINT nFace;
                FLOAT fBary1, fBary2, fDist;
                UINT nHitCount = 0;
                g_pD3DXMesh->Intersect( &vPickRayOrig, &vPickRayDir, &nHitCount, &nFace, &fBary1, &fBary2, &fDist, NULL);
                if( nHitCount > 0 )
                {
                    g_nNumIntersections = 1;
                    g_IntersectionArray[0].dwFace = nFace;
                    g_IntersectionArray[0].fBary1 = fBary1;
                    g_IntersectionArray[0].fBary2 = fBary2;
                    g_IntersectionArray[0].fDist = fDist;
                }
                else
                {
                    g_nNumIntersections = 0;
                }
            }
            else
            {
                // Collect all intersections
                ID3D10Blob* pBuffer = NULL;
                D3DXINTERSECTINFO* pIntersectInfoArray;
                if( FAILED( hr = g_pD3DXMesh->Intersect( &vPickRayOrig, &vPickRayDir, &g_nNumIntersections, NULL,
                                                         NULL, NULL, NULL, &pBuffer) ) )
                {
                    SAFE_RELEASE( pMesh );
                    return hr;
                }
                if( g_nNumIntersections > 0 )
                {
                    pIntersectInfoArray = ( D3DXINTERSECTINFO* )pBuffer->GetBufferPointer();
                    if( g_nNumIntersections > MAX_INTERSECTIONS )
                        g_nNumIntersections = MAX_INTERSECTIONS;
                    for( DWORD iIntersection = 0; iIntersection < g_nNumIntersections; iIntersection++ )
                    {
                        g_IntersectionArray[iIntersection].dwFace = pIntersectInfoArray[iIntersection].FaceIndex;
                        g_IntersectionArray[iIntersection].fBary1 = pIntersectInfoArray[iIntersection].U;
                        g_IntersectionArray[iIntersection].fBary2 = pIntersectInfoArray[iIntersection].V;
                        g_IntersectionArray[iIntersection].fDist = pIntersectInfoArray[iIntersection].Dist;
                    }
                }
                SAFE_RELEASE( pBuffer );
            }

        }
        else
        {
            // Not using D3DX
            DWORD dwNumFaces = (DWORD)g_Mesh.GetNumIndices(0)/3;
            FLOAT fBary1, fBary2;
            FLOAT fDist;
            for( DWORD i = 0; i < dwNumFaces; i++ )
            {
                D3DXVECTOR3 v0 = pVertices[pIndices[3 * i + 0]].p;
                D3DXVECTOR3 v1 = pVertices[pIndices[3 * i + 1]].p;
                D3DXVECTOR3 v2 = pVertices[pIndices[3 * i + 2]].p;

                // Check if the pick ray passes through this point
                if( IntersectTriangle( vPickRayOrig, vPickRayDir, v0, v1, v2,
                                       &fDist, &fBary1, &fBary2 ) )
                {
                    if( g_bAllHits || g_nNumIntersections == 0 || fDist < g_IntersectionArray[0].fDist )
                    {
                        if( !g_bAllHits )
                            g_nNumIntersections = 0;
                        g_IntersectionArray[g_nNumIntersections].dwFace = i;
                        g_IntersectionArray[g_nNumIntersections].fBary1 = fBary1;
                        g_IntersectionArray[g_nNumIntersections].fBary2 = fBary2;
                        g_IntersectionArray[g_nNumIntersections].fDist = fDist;
                        g_nNumIntersections++;
                        if( g_nNumIntersections == MAX_INTERSECTIONS )
                            break;
                    }
                }
            }
        }

        // Now, for each intersection, add a triangle to g_pVB and compute texture coordinates
        if( g_nNumIntersections > 0 )
        {
            D3DVERTEX* v;
            D3DVERTEX* vThisTri;
            DWORD* iThisTri;
            D3DVERTEX v1, v2, v3;
            INTERSECTION* pIntersection;

            g_pVB->Map( D3D10_MAP_WRITE_DISCARD, 0, ( void** )&v );

            for( DWORD iIntersection = 0; iIntersection < g_nNumIntersections; iIntersection++ )
            {
                pIntersection = &g_IntersectionArray[iIntersection];

                vThisTri = &v[iIntersection * 3];
                iThisTri = &pIndices[3 * pIntersection->dwFace];
                // get vertices hit
                vThisTri[0] = pVertices[iThisTri[0]];
                vThisTri[1] = pVertices[iThisTri[1]];
                vThisTri[2] = pVertices[iThisTri[2]];

                // If all you want is the vertices hit, then you are done.  In this sample, we
                // want to show how to infer texture coordinates as well, using the BaryCentric
                // coordinates supplied by D3DXIntersect
                FLOAT dtu1 = vThisTri[1].tu - vThisTri[0].tu;
                FLOAT dtu2 = vThisTri[2].tu - vThisTri[0].tu;
                FLOAT dtv1 = vThisTri[1].tv - vThisTri[0].tv;
                FLOAT dtv2 = vThisTri[2].tv - vThisTri[0].tv;
                pIntersection->tu = vThisTri[0].tu + pIntersection->fBary1 * dtu1 + pIntersection->fBary2 * dtu2;
                pIntersection->tv = vThisTri[0].tv + pIntersection->fBary1 * dtv1 + pIntersection->fBary2 * dtv2;
            }

            g_pVB->Unmap();
        }


        SAFE_RELEASE( pMesh );
       
    }

    return S_OK;
}







Tuesday, September 20, 2016

CUDA - "Compute Unified Device Architecture"

painful journey so far:
Monday:
CUDA 7.5 not working on VS2015 Community edition

Tuesday
CUDA 7.5 not working on VS2013 Community edition
ISO install failed for VS 2013 Ultimate Edition 
(mounted ISO file as a virtual drive and tried to install over the virtual drive)

Stack overflow reports Windows 10 should be possible
NVidia/CUDA download reports compatibility with Windows 10.
Web install finally worked for VS Ultimate (4+ hours uninstall/install !)

Wed
Downloaded "File Checksum Integrity Verifier utility" to verify downloaded
https://support.microsoft.com/en-us/kb/889768

CUDA 7.5 not installing properly under windows 10
custom install may have worked
Need to test CUDA capabilies in VS

NVidia CUDA 'classes' /training.
https://devblogs.nvidia.com/parallelforall/easy-introduction-cuda-c-and-c/

https://developer.nvidia.com/how-to-cuda-c-cpp

I noticed nothing was compiling in VS2013
as each project was looking for a non-existant v140 compiler left over from the V2015 install

this has been remedied by setting the project compiler manually
for each project

DX samples files are compiling on VS2013 again.

Thursday

Wednesday, September 14, 2016

DX HUD

http://gorkempacaci.blogspot.in/2007/12/how-to-print-text-in-directx.html

Saturday, September 10, 2016

c# arrays

2Dimensional Arrays in c# are different to those in Java
Normal declaration would be interpreted (with an error) as a "jagged array"
(an array of arrays of different length)

http://stackoverflow.com/questions/4384202/compiler-error-invalid-rank-specifier-expected-or-on-two-dimensional-ar

C# FileIO

libpng notes

more llibpng resources:
back-compat tracker of versions
http://abi-laboratory.pro/tracker/timeline/libpng/

test Images:
http://www.schaik.com/pngsuite/

recent developments (2016)
https://github.com/glennrp/libpng
http://libpng.sourceforge.net

*there are multiple distributions:
for windows:
http://gnuwin32.sourceforge.net/packages/libpng.htm

getting the libs to work in  VS2015:

the manual:
http://www.libpng.org/pub/png/libpng-manual.txt

Wednesday, September 7, 2016

Weekly Blog Update

a problematic week:

* Downloaded CMake and skimmed over the reading material,
which gave me the understanding that CMake simply was made to simplfy the code build process. The Gui provides a source path and build path for binary files to be made to.

* Compiled the open Dicom solution - "Imebra" with CMake on VS2015 but was not able to compile any code that used it for some errors.
(insert errors here)

* investigated the Dicom Specification and decided it was too complex for indepth reading and that TIF libs werre simpler to install and get working.


* Tried again to compile several TIF libraries on Visual Studion2015 - with no success.
list which one:

*libTiff is written in c but I thought i would have a go at converting to c++
but not successful.
errors:

* in desperation started writing a TIF reader in (linux) c++ with plans to port over to windows.
heavily referenced Paul Bourkes TIF format description here
http://paulbourke.net/dataformats/tiff/

and the official TIF 6.0 Specification
https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf

My code can only 'read' single frame TIF files, and only uncompressed.
(as outlined in the Image J help files and like Dicon , TIF files can bundle several images in the one format if required.)

When I say read - the code simply  reads in binary bytes, counting them and detects the Image Tags - ie from looking at the spec, bytes 4 and 5 (0-based) describe the offset in bytes from the beginning of the file to the first IFD (not sure of the acronym - but i think of it as Image File Descriptor, or Indexed file descriptor).

The IFD has fixed allocations of bytes for TAGS, or snippets of information such as the data type that describes the pixels.

* this was deemed as unnessesary development - a library already exists to allow us to read TIF pixel values - we just have to get it working - so this has been 'shelved'.

raw (untidy) code is here, 643 lines:

/*
 * File:   main.cpp
 * Author: phil0411
 * Created on 7 Sept 2016, 2:33 PM
 */

#include <stdlib.h>
#include <cstdlib>
 

#include <iostream>
#include <fstream>
#include <sstream>

#include <cstring>
#include <string>

#include <errno.h>
#include <iomanip>

#include <bitset>
//#include <c++/4.8/bits/stl_bvector.h>
#include <stdio.h>
//#include <c++/4.8/iosfwd>
#include <vector>

#include <c++/4.8/bits/stl_bvector.h>

//CONST's
#define byteRowLengthHex 4
//#define byteRowLengthBin 4
#define byteColHeight 4
#define maxBytes 4096

using namespace std;

//GLOBALS
int byteRowLengthBin = 4;
bool dataReadout = false;
int dirCount = 0;
int tag = 0;
int type = 0;
int count = 0;
int move= 0; //offset to the next IFD
int term = 0;

int pow(int base, int exp){
   
    for(int i=0;i<exp;i++)
    {
        base = (base * base);
    }
    return base;
   
}
//simple min function
uint dpmin(uint a, uint b){
    if(a<b){
        return a;
    }else return b;
}

//reverse a byte of 8 bits
string revByte(string bt){
   
    //check
    string null;
    int len = sizeof(bt);
    if(len!=8){
        cout << "byte error - non 8-bit byte" << endl;
        exit(1);
    }
   
    cout << "input byte: " << bt << endl;
    char bits[8];
   
    for(int i=0;i<len;i++){
        bits[i] = bt[len-i-1];
    }
    cout << "reversed byte: " << bits << endl;
   
    return null + bits;
}

string get_file_contents(const char *filename)
{
  ifstream in(filename, ios::in | ios::binary);
  if (in)
  {
    string contents;
    in.seekg(0, ios::end);
    contents.resize(in.tellg());
    in.seekg(0, ios::beg);
    in.read(&contents[0], contents.size());
    in.close();
    return(contents);
  }
  throw(errno);
}

    //read2
    // An unsigned char can store 1 Bytes (8bits) of data (0-255)
    typedef unsigned char BYTE;
    // Get the size of a file
    long getFileSize(FILE *file)
    {
        long lCurPos, lEndPos;
        lCurPos = ftell(file);
        fseek(file, 0, 2);
        lEndPos = ftell(file);
        fseek(file, lCurPos, 0);
        return lEndPos;
    }

    void div(){
        cout << "////////////////////////////////\n";
    }
   
    //not implemented / called yet
    void checkHeaderIdentifier(BYTE fileBuf){
        //detect TAGS - should be in a file checker
        /*
        int n;
        char char_i = (char)'I';
        char char_m = (char)'M';
        char char_4 = (char)'4';
        char char_2 = (char)'2';
       
        char code = (char) (fileBuf[0]);
        char code2 = (char) (fileBuf[1]);
       
        cout << "code: " << code << " & " << "char_i: " << char_i << endl;
       
        if(char_i==code && char_i==code2){
            cout << "tiff is little ENDIAN" << endl;
        }else if(char_m==code && char_m==code2){
            cout << "tiff is big ENDIAN" << endl;
        }else{
            //not a TIF
            cout << "header doesnt match a TIF file, char#0!= char#1" << endl;
        }
       
        //compare 42
        //second half of the header is an offset to the TAG (bytes 4,5,6,7))
        //convert hex to dec
        */
    }
   
    //Make a space every now and then for <TAGS> & console readability in BINARY
    void* form(int i, int ifd, bool binToggle){
        //HEADER
        if (i==0){
            cout << "<header[8]>\n";
            div();
            cout << "(<Endian II/MM >< 42 00 >\t [2][2]\n";
            cout << "offset to IFD#1 \t\t [4]\n";
        }
        //END HEADER
        if(i==8){
            cout << "\n<end header>\n";
            div();
            //byteRowLengthBin = 3;   //RGB if the image was RGBA
                                    //we would need 4
                                    //for neat output to the CLI
            dataReadout = true;
        }
        //ENTRY COUNT
        if(i==ifd){
            dataReadout = false;
            cout << "\n</Data>\n";
            cout << "<DirEntry Count>";
        }
        /*
        if(i==(ifd+1)){//add globals along side of bin data
            cout << "\t" << dirCount << endl;
        }
        */
        //TAG
        if(i==(ifd+2)){// TAG offset by +2 because of Entry Dir Count
            cout << "\n</Dir Entry Count>\n";
            cout << "<IFD>\n";
            cout << "<TAG>\n";
        }
        /*broken
        if(i==(ifd+3)){//add globals along side of bin data
            cout << "\t" << tag << endl;
        }
        */
        if(i== ifd+4)
        {//TYPE
            cout << "\n</TAG>\n";
            cout << "<TYPE>\n";
        }
        if(i==(ifd+6)){//COUNT
            cout << "\n</TYPE> 4 is 24bit data RGB\n";
            cout << "<COUNT>\n";
        }
        if(i==(ifd+10)){//VALUE
            cout << "\n</COUNT>\n";
            cout << "<VALUE/OFFSET>\n";
        }
        if(i==(ifd+14)){//END OF IFD
            cout << "\n</VALUE/OFFSET>\n";
            cout << "</IFD>\n";
        }
        if(i==(ifd+18)){//POINTER TO NEXT IFD
            cout << "\n<OFFSET to NEXT IFD>\n";
            }
        if(i==(ifd+20)){//POINTER TO NEXT IFD
            cout << "\n</OFFSET>\n";
        }
        //endl
        if(dataReadout){
            if(i%3==2) cout << endl;
        }else{
            if(i%4==0) cout << endl;
        }
       
        if(!binToggle){
            //HEX//
            //if(i%byteRowLengthBin==0 || i%byteColHeight==0) cout << endl;
        }else{
            //BIN//
            //if(i%byteRowLengthBin==0 ) cout << " ";
            if(i%4==0 ) cout << " ";
        }
    }

   
    int main() //http://www.dreamincode.net/forums/topic/170054-understanding-and-reading-binary-files-in-c/
    {
        const char *filePath = "bwtif2.tif";
        BYTE *fileBuf;          // Pointer to our buffered data
        FILE *file = NULL;      // File pointer
       
       
        // Open the file in binary mode using the "rb" format string
        // This also checks if the file exists and/or can be opened for reading correctly
        if ((file = fopen(filePath, "rb")) == NULL)
            cout << "Could not open specified file" << endl;
        else{
            cout << "File opened successfully" << endl;
            cout << "only reads *single* uncompressed TIFF images correctly" << endl;
        }
        //checkHeaderIdentifier
        //checkHeaderIdentifier(fileBuf);
       
        // Get the size of the file in bytes
        long fileSize = getFileSize(file);
        //cout << "filSize: " << fileSize << "bytes " << endl;
        //this is not acccurate for some reason
        // Allocate space in the buffer for the whole file
        fileBuf = new BYTE[fileSize];
       
        // Read the file in to the buffer
        fread(fileBuf, fileSize, 1, file);
        //Now that we have the entire file buffered,
        //we can take a look at some binary information
        int kill = dpmin(fileSize,maxBytes);
        //////
        //HEX
        //////
        /*
        cout << "Hex:" << endl;
        for (int i = 0; i < kill; i++)
        {
            form(i, false);//false = HEX formatting
            printf("%04d ", fileBuf[i]);
        }
        cout << endl;
        */
        ///////////////////
        //BINARY
        ///////////////////
        //int kill = dpmin(fileSize,maxBytes);//already present above
        //Get offset #1 to first IFD
        int IFD1 = 0; //(bytes 4.5.6.7)
        for(int b=7;b>3;b--){
            IFD1 += ((int) fileBuf[b]);
        }
        cout << "offset to IFD1" << IFD1 << " (bytes)" << endl;
        cout << "offset to IFD1" << IFD1 - 2 << " minus header" << endl;
        //cout << "\nBIN:" << endl;
       
        for (int i=0; i < kill; i++) //maxBytes = maxBytes to print out
        {
            //formatting
            form(i, IFD1, true);//true = BIN formatting
            string binString = " " + (bitset<8>(fileBuf[i])).to_string();
            cout << binString;
        }
       
       
        cout << "offset to the TAG (pixels are before the TAG)= \n";
        cout << "unsigned LONG (4 bytes and range = 0 to 4,294,967,295)\n";
        /*
         * so 40 00 is 4 bytes - good
         * conversion to int gave me 40 ?
         * bin would be
         * 0100 0000 0000 0000 = 2^15
         *
         * pixel size is only 4 by 4 though = 16 pixels
         *
         */
        //printf("2^15 = %d\n", pow(2,15));
       
        ////////////////////
        //GET OFFSET #1
        ////////////////////
       
        int offset; //4 byte offset (a long (tO account for big images)))
        for(int b=7;b>3;b--){
            offset += ((int) fileBuf[b]);
        }
        cout << "reverse read offset:" << offset << " bytes" << endl;
        cout << "reverse read offset:" << offset-2 << " minus header" << endl;
        //read image IFD (12 bytes)
        /////////////////////
        //Directory Entries//
        /////////////////////
        int d;
        cout << "\nDirectory Entries = \n";
       
        //reverse order again
        //int dirCount = 0; //now a global
        for(d=(offset+1);d>=offset;d--){
            cout << "dirCount byte = " << ((int) fileBuf[d]) << " ";
            dirCount += ((int) fileBuf[d]);
        }
        cout << "# of Dir Entries = " << dirCount<< endl;
        cout << "(each Dir entry is 12 bytes)\n";
        cout << "(TAG(2B), TYPE(2B), COUNT(4B), VALUE(4B)):\n";
        cout << endl;
        exit(0);
        //move up past dirCount
        offset+=2;
       
        ///////////////////////////
        //Print Directory Entries//
        ///////////////////////////
       
        //TAG (2 bytes)
        ///////////////
        d = offset; //dc is the start of our Dir Entry
        //int tag = 0;//now a global
        for(d+1;d<=offset;d--){//1 is the size-1
            tag += ((int) fileBuf[d]);
            cout << "tag: " << tag << " ";
        }
        cout << endl;
        offset+=2;
       
        //TYPE (2 bytes)
        ////////////////
        d = offset; //dc is the start of our Dir Entry
        //int type = 0;//now global
        for(d+1;d<=offset;d--){//1 is the size-1
            type += ((int) fileBuf[d]);
            cout << "type: " << type << " ";
        }
        cout << endl;
        offset+=2;

        //COUNT (4 bytes)
        /////////////////
        d = offset; //dc is the start of our Dir Entry
        //int count = 0;
        for(d+3;d<=offset;d--){//1 is the size-1
            count += ((int) fileBuf[d]);
            cout << "count: " << count << " ";
        }
        cout << endl;
        offset+=4;
       
        //OFFSET (4 bytes)
        //////////////////
        d = offset; //dc is the start of our Dir Entry
        //int move = 0;
        for(d+3;d<=offset;d--){//3 is the size-1
            move += ((int) fileBuf[d]);
            cout << "new offset: " << move << " ";
        }
        cout << endl;
        offset +=4;
       
        //END SEQUENCE (4 bytes of all zeros)
        /////////////////////////////////////
        d = offset;
        //int term = 0;
        for(d+3;d<=offset;d--){//3 is the size-1
            term += ((int) fileBuf[d]);
            cout << "sum of terminating zeros (should equal zero) = " << term << " ";
        }
        cout << endl;
        offset +=4;
       
        for (int i=0; i < kill; i++) //maxBytes = maxBytes to print out
        {
            //formatting
            form(i, IFD1, true);//true = BIN formatting
            string binString = " " + (bitset<8>(fileBuf[i])).to_string();
            cout << binString;
        }
        /*
        cout << "CHECKS\n";
        cout << "offset now = " << offset << " bytes" << endl;
        cout << "offset - header = " << offset-8 << " bytes" << endl;
        cout << "offset - header - terminator = " << offset-8-4 << " bytes" << endl;
        cout << "Total Dir Structure = " << offset-40-8-4 << " bytes" << endl;
        cout << "Total Dir Structure/12bytes per dir entry = " << (offset-52)/12 << " Dir Entries" << endl;
        cout << "dirCount == (calculated DirCount)?" << endl;
        cout << dirCount << " = " << ((offset-42)/12) << endl;
        */
       
        //TAGS from Paul Bourke
        //http://paulbourke.net/dataformats/tiff/
       
        /* Read the footer *//* The number of directory entries (14) */

       /* Width tag, short int */
       /*
        * a short int can be signed or unsigned
        * if signed it has a range of -2^7 to +(2^7)-1 (minus the count of 0)
        * if UNsigned it has a range of -0 to +(2^8)-1 (minus the count of 0)
        *
        */
       /* Height tag, short int */
      
       /* Bits per sample tag, short int */
       //"0102000300000003"

       /* Compression flag, short int */
       //"010300030000000100010000"

       /* Photometric interpolation tag, short int */
       //"010600030000000100020000"

       /* Strip offset tag, long int */
       //"011100040000000100000008"

       /* Orientation flag, short int */
       //"011200030000000100010000"

       /* Sample per pixel tag, short int */
       //"011500030000000100030000"

       /* Rows per strip tag, short int */
       //"0116000300000001"
      
       /* Strip byte count flag, long int */
       //"0117000400000001"
      
       /* Minimum sample value flag, short int */
       //"0118000300000003"
      
       /* Maximum sample value tag, short int */
       //"0119000300000003"

       /* Planar configuration tag, short int */
        //"011c00030000000100010000"

       /* Sample format tag, short int */
       //"0153000300000003"

       /* End of the directory entry */
        //"00000000"

       /* Bits for each colour channel */
       //"000800080008"

       /* Minimum value for each component */
       //"000000000000"

       /* Maximum value per channel */
       //"00ff00ff00ff"

       /* Samples per pixel for each channel */
       //"000100010001"
       
        /////////////////////////////////////////////////////////////////////////
        //DONE
        /////////////////////////////////////////////////////////////////////////
        //STATS
        cout << "Stats\n";
        cout << "dir count:" << dirCount << endl;
        cout << "TAG:" << tag << endl;
        cout << "Type:" << type << endl;
        cout << "Count:" << count << endl;
        cout << "Value/Offset:" << move << endl;
       
        cin.get();// simply allows the user to terminate with enter on the //console
        delete[]fileBuf;
            fclose(file);   // don't forget
       
        return 0;
    }
 

//pad with zeros if need be
string padZero(string bin){
    stringstream padding;
    //get count
    int l = sizeof(bin);
    cout << "padZero info:size = " << l;
    //add zeros
    if(l<8){
        for(int i=0;i<(8-l);i++){
            //add the zero tot he front
            padding << "0";
        }
    }
    //concat
    padding << bin;
    cout << "padding: " << padding;
    return padding.str();
}

void info(char* file){
    cout <<  "\n16 bit tif bytes will be made up of pairs of bytes...\n";
    cout <<  "32 bit tif bytes will be made up of groups of 4 bytes...\n";
    cout << "IEEE fp numbers\n";
    cout <<  "the first bit is the sign bit\n";
    cout <<  "the next 5 bits are the exponent\n";
    cout <<  "the next 10 bits are the mantissa\n";
   
    cout <<  "according to the TFF spec the header is 8 bytes\n\n";
    cout << "file is:" << file << "/n read L > R " << "\n";
    cout << "file is incompressed (TIF_UNC)\n\n";
   
    //CHECK ENDIANESS
        //if bytes 1 and 2 are 'I" the file is little-endian
        //if bytes 1 and 2 are 'M" the file is big-endian
        //therefore if byte != byte 2 there is a problem ?
        cout << "little Endien = II, big Endien  = MM\n";
        //cout << contents.at(0) << "\n";
        //cout << contents.at(1) << "\n\n";
}

/**
 * binary to floating point conversion
 * @param
 * @return
 */
/*
void btof(char[] binNum){
    //int s = atoi(binNum[0]);
    //cout << "sign bit = " << s << endl;
    cout << endl;
}
*/

/**
 *
 * @param argc
 * @param argv
 * @return
 *
 * header
 * II little endien
 * MM big endien
 * 00 42(dec) or 002a (hex) - a '42' identifier
 *
 * the remaining 4 bytes is the offset
 * from the start of the file to the
 * first ifd
 * (if there is only one image, there is only one ifd)
 *
 */
int main2(int argc, char** argv) {
   
    if(argc != 1){
        cout << "need one argument, the file name\n";
        exit(1);
    }
   
    //cout << btof("10010100");
   
    //FILES TO READ
    char file[] = "bwtif._tif";//16x16 uncompressed color tif
    char file2[] = "data";
   
    //PRINT FILE INFO
    //info(file);
   
    //FILE IS SPECIFIED HERE
    ifstream stream(file2, ios::in | ios::binary);
   
    //vector<int> contents(256);
    //contents.reserve(512);
    //vector<int> contents((istreambuf_iterator<char>(stream)), istreambuf_iterator<char>());
   
    vector<int> contents((istreambuf_iterator<char>(stream)), istreambuf_iterator<char>());
   
    cout << "<header>" << endl;
   
    //LOOP
    //for(int i=0;i< sizeof(contents) || i < maxBytes;i++) {
    for(int i=0;i< sizeof(contents);i++){
    //for(int i=0;i < 8;i++) {
        int value = contents.at(i);
        //hexdump
        //cout  << "hexdata#" << dec << setw(4) << (i+1) << "\t" << hex << value << endl;
        //97 is the dec code for ascii a
        //CONVERT TO HEX
        //printf("hex:%x \n", _itoa(value, hexString, 16));
       
        stringstream ss;
        //convert to binary
        //string binary = bitset<8>(128).to_string(); //to binary
        //cout<<binary<<"\n";
        //ss << "byte# " << i << "\t" << bitset<8>(value).to_string();
       
        /**
         * bitset
         */
        ss << bitset<8>(value).to_string();
       
        //PAD
        //ss << padZero(ss);
        //ss<< value; // int decimal_value
       
       
        //PRINT BYTES
        //carriage return every second byte
        if(i==8) cout << "<end header>\n\n" << "<body>" << endl;
        cout << ss.str();
        if((i+1)% byteRowLengthBin==0){
            cout << endl;
        }else{
            cout << " ";
        }
    }
    cout << "<end body>>\n";
        cout << "file size: " << sizeof(contents) << setw(5) << " bytes" << endl;
    return 0;
}

 
output from running this code with a simple tif file specified (bwtif2.tif)

File opened successfully
only reads *single* uncompressed TIFF images correctly
offset to IFD156 (bytes)
offset to IFD154 minus header
<header[8]>
////////////////////////////////
(<Endian II/MM >< 42 00 >        [2][2]
offset to IFD#1                  [4]

  01001001 01001001 00101010 00000000
  00111000 00000000 00000000 00000000
<end header>
////////////////////////////////

  00000000 00000000 00000000
 11111111  11111111 11111111
 00000000 00000000  00000000
 11111111 11111111 11111111
  11111111 11111111 11111111
 00000000  00000000 00000000
 11111111 11111111  11111111
 00000000 00000000 00000000
  00000000 00000000 00000000
 11111111  11111111 11111111
 00000000 00000000  00000000
 11111111 11111111 11111111
  11111111 11111111 11111111
 00000000  00000000 00000000
 11111111 11111111  11111111
 00000000 00000000 00000000

</Data>
<DirEntry Count>
  00010000 00000000
</Dir Entry Count>
<IFD>
<TAG>
 11111110 00000000
</TAG>
<TYPE>

  00000100 00000000
</TYPE> 4 is 24bit data RGB
<COUNT>
 00000001 00000000
  00000000 00000000
</COUNT>
<VALUE/OFFSET>
 00000000 00000000
  00000000 00000000
</VALUE/OFFSET>
</IFD>
 00000000 00000001
  00000011 00000000
<OFFSET to NEXT IFD>
 00000001 00000000
</OFFSET>
/*

 * further unprocessed image tags / metadata
*/
  00000000 00000000 00000100 00000000
  00000000 00000000 00000001 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 00000100 00000000
  00000000 00000000 00000010 00000001
  00000011 00000000 00000011 00000000
  00000000 00000000 00001110 00000001
  00000000 00000000 00000011 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 00000001 00000000
  00000000 00000000 00000110 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 00000010 00000000
  00000000 00000000 00001101 00000001
  00000010 00000000 00111000 00000000
  00000000 00000000 00010100 00000001
  00000000 00000000 00010001 00000001
  00000100 00000000 00000001 00000000
  00000000 00000000 00001000 00000000
  00000000 00000000 00010010 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 00000001 00000000
  00000000 00000000 00010101 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 00000011 00000000
  00000000 00000000 00010110 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 01000000 00000000
  00000000 00000000 00010111 00000001
  00000100 00000000 00000001 00000000
  00000000 00000000 00110000 00000000
  00000000 00000000 00011010 00000001
  00000101 00000000 00000001 00000000
  00000000 00000000 11111110 00000000
  00000000 00000000 00011011 00000001
  00000101 00000000 00000001 00000000
  00000000 00000000 00000110 00000001
  00000000 00000000 00011100 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 00000001 00000000
  00000000 00000000 00101000 00000001
  00000011 00000000 00000001 00000000
  00000000 00000000 00000010 00000000
  00000000 00000000 00000000 00000000
  00000000 00000000 01001000 00000000
  00000000 00000000 00000001 00000000
  00000000 00000000 01001000 00000000
  00000000 00000000 00000001 00000000
  00000000 00000000 00001000 00000000
  00001000 00000000 00001000 00000000
  00101111 01101000 01101111 01101101
  01100101 00101111 01000011 01010011
  01000101 01001101 00101111 01110000
  01101000 01101001 01101100 00110000
  00110100 00110001 00110001 00101111
  01001110 01100101 01110100 01000010
  01100101 01100001 01101110 01110011
  01010000 01110010 01101111 01101010
  01100101 01100011 01110100 01110011
  00101111 01100011 01110000 01110000
  01010100 01100101 01110011 01110100
  00101111 01100010 01110111 01110100
  01101001 01100110 00110010 00101110
  01110100 01101001 01100110 00000000offset to the TAG (pixels are before the TAG)=
unsigned LONG (4 bytes and range = 0 to 4,294,967,295)
reverse read offset:6315552 bytes
reverse read offset:6315550 minus header

* the green txt above corresponds to the pixel data in my test TIF image that the file read.

* Attempted to port this code over to c++ on Windows but did not succeed.
Need to look pre-processor directives that allow code to be cross platform.

*Briefly started looking at tifHul as a TIF solution
http://jhove.sourceforge.net/tiff-hul.html

*revisited working Direct X files and began planning how pixel values would be represented in 3D:

Pixel values could be interpreted as unsigned integers between 0 and 255
or possibly as 16 or 32 bit floating point numbers.

If integers, we simply compare to a threshold value to determine if we will draw a cube in 3D representing that pixel.

If floats we can round to the nearest integer, to begin with then investigate further. Postion accuracy in 3D space will depend or be related to the overall scene size, but we can assume we will need floating point accuracy for surgical simulaltion.

Once this is done , we need to read in a bitmap stack or sequence and stack our drawn cubes correctly according to the images. Ideally we want the data for all "slices" to be all accessible simultaneously if possible, subject to memory constraints.

# pngLib was downloaded
 (for linux)
but unable to decipher the installation 'instructions' or the simple instrutions did not work
./configure
make
make install

#Libtif.net was also downloaded but not yet investigated.
http://bitmiracle.com/libtif