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

No comments:

Post a Comment