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
Thursday, September 22, 2016
"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;
}
* 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
Stack overflow reports Windows 10 should be possible
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
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
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
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
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
* 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
Friday, September 2, 2016
Wednesday, August 31, 2016
GCode
G Code *(Geometric Code) aka RS-274
or G&N cdeo as descibed on you tubehttps://www.youtube.com/watch?v=r5bimWKeMbY
GCode is a code language for CnC machines
it controls how and where a machine moves
code vary for different machines
movements are done with Cartesion Coordinates.
X indicates the X axis
Y indicates the vetical postion of the machines Y axis
(usually Y is also up in world space for CAD software, with the exception of 3DsMax)
Z controls depth or Z axis
numbers direcly following X,Y,Z are the distances the machine should travel in that direction
specific Codes can change the units of measurement
ie G20 will mean subsequent code will be executed in inches
ie G21 will mean subsequent code will be executed in mm
the machines speed is determined by the code
ie G00 use max speed
spindle rotation speed I also controlled
G01 - move at a feed rate (determined by F)
some codes are like predetermied movements
G20 - makes a clockwise circular motion, G30 in in a counter clockwise circular motion
G02 circular interpolation clockwise, G03 circular interpolation counter clockwise
an Arc is determined by I, J for incremental centers and J determines the radius
ie to arc (clockwise) from p1 to p2, p2 must be a point tot he right of p1 or in the + X axis
(if it was negative in X in relation to p1 then it would form a counter clockwise arc)
the center of the arc would lie at the midpoint of P1 and P2
the center is specified with coordinates I and J
the radius of the arc is specified in the GCode - this will give us the arc.
the Gcode would be :
X_Y_I_J_F_
where X,Y is the pos of p1, I,J is the pos of the arcs center (relative to the start),
and F is the feed rate - how fast to move the nozzle/end mill.
G90 - set the coordinate system to absolute (the arc center is always relative to the start point)
G91 - set the coordinate system to relative (aka incremental)
MCodes (misc machine codes) ie
M06 tool change on a CnC machines
Init code
Saftety codes - cancel offsets - set measurements etc.
N07 tool change and speed setting
then the actual movements are specified
Ncodes - return the machine to the home position then stop and rewind the program in preparation for another print.
nozzle is sometimes referred to as the end mill.
a complete set of GCodes is refferred to as a part program
start and end of GCode is indicated with a %
Prep codes are unique to machines
M15 tells the machine to stop the spindle
typically a nozzle is lifted up in Y above a machines part
GCodes are typically simulated for identify errors and prevent expensive machine damage.
GCode Tutorials
http://linuxcnc.org/docs/html/gcode.html (Quick Reference)https://www.youtube.com/watch?v=r5bimWKeMbY
https://www.youtube.com/watch?v=hq47wq9qBbs
https://www.youtube.com/watch?v=iMx_UYrvuos (HAAS)
TCPC - controlling part and machine 'tip' at the same time akin to rotating worldspace in a
3D virtual environmenthttps://www.youtube.com/watch?v=HxPjH4v5iEg
code Details : http://reprap.org/wiki/G-code
or G&N cdeo as descibed on you tubehttps://www.youtube.com/watch?v=r5bimWKeMbY
GCode is a code language for CnC machines
it controls how and where a machine moves
code vary for different machines
movements are done with Cartesion Coordinates.
X indicates the X axis
Y indicates the vetical postion of the machines Y axis
(usually Y is also up in world space for CAD software, with the exception of 3DsMax)
Z controls depth or Z axis
numbers direcly following X,Y,Z are the distances the machine should travel in that direction
specific Codes can change the units of measurement
ie G20 will mean subsequent code will be executed in inches
ie G21 will mean subsequent code will be executed in mm
the machines speed is determined by the code
ie G00 use max speed
spindle rotation speed I also controlled
G01 - move at a feed rate (determined by F)
some codes are like predetermied movements
G20 - makes a clockwise circular motion, G30 in in a counter clockwise circular motion
G02 circular interpolation clockwise, G03 circular interpolation counter clockwise
an Arc is determined by I, J for incremental centers and J determines the radius
ie to arc (clockwise) from p1 to p2, p2 must be a point tot he right of p1 or in the + X axis
(if it was negative in X in relation to p1 then it would form a counter clockwise arc)
the center of the arc would lie at the midpoint of P1 and P2
the center is specified with coordinates I and J
the radius of the arc is specified in the GCode - this will give us the arc.
the Gcode would be :
X_Y_I_J_F_
where X,Y is the pos of p1, I,J is the pos of the arcs center (relative to the start),
and F is the feed rate - how fast to move the nozzle/end mill.
G90 - set the coordinate system to absolute (the arc center is always relative to the start point)
G91 - set the coordinate system to relative (aka incremental)
MCodes (misc machine codes) ie
M06 tool change on a CnC machines
Init code
Saftety codes - cancel offsets - set measurements etc.
N07 tool change and speed setting
then the actual movements are specified
Ncodes - return the machine to the home position then stop and rewind the program in preparation for another print.
nozzle is sometimes referred to as the end mill.
a complete set of GCodes is refferred to as a part program
start and end of GCode is indicated with a %
Prep codes are unique to machines
M15 tells the machine to stop the spindle
typically a nozzle is lifted up in Y above a machines part
GCodes are typically simulated for identify errors and prevent expensive machine damage.
GCode Tutorials
http://linuxcnc.org/docs/html/gcode.html (Quick Reference)https://www.youtube.com/watch?v=r5bimWKeMbY
https://www.youtube.com/watch?v=hq47wq9qBbs
https://www.youtube.com/watch?v=iMx_UYrvuos (HAAS)
TCPC - controlling part and machine 'tip' at the same time akin to rotating worldspace in a
3D virtual environmenthttps://www.youtube.com/watch?v=HxPjH4v5iEg
code Details : http://reprap.org/wiki/G-code
Week 5 research - Image J
A quick search revealed that image J supports "bitmap stacks".
So more research follows:
"ImageJ can display multiple spatially or temporally related images in a single window. These image sets are called stacks. The images that make up a stack are called slices. In stacks, a pixel (which represents 2D image data in a bitmap image) becomes a voxel (volumetric pixel), i.e., an intensity value on a regular grid in a three dimensional space."
Stacks are stored in RAM - Virtual Stacks are stored on the disk, and are read only, bu there are work arounds. TIF Virtual stacks can be accessed faster then JPG virtual stacks
JPG can be converted to TIF.
TIF is the Native format of imageJ:
TIFF (Tagged Image File Format) is the ‘default’ format of ImageJ
Images can be 1–bit, 8–bit, 16–bit (unsigned1), 32–bit (real) or RGB color.
TIFF files with multiple images of the same type and size open as Stacks or Hyperstacks.
ImageJ opens lossless compressed TIFF files (see II Image Types: Lossy Compression and Metadata) by the LZW, PackBits and ZIP (Deflate/Inflate) [2] compression schemes.
In addition, TIFF files can be opened and saved as ZIP archives. Tiff tags and information needed to import the file (number of images, offset to first images, gap between images) are printed to the Log Window when ImageJ is running in Debug Mode (Edit.Options.Misc..., see Settings and Preferences).
Imported sequences are sorted by image number instead of filename and the tags are preserved when DICOM images are saved in TIFF format.
Tiff bitmapstacks can be "flattened " with a montage feature under the stacks menu
Chapter 12 of the Manual is on Volumes
So more research follows:
"ImageJ can display multiple spatially or temporally related images in a single window. These image sets are called stacks. The images that make up a stack are called slices. In stacks, a pixel (which represents 2D image data in a bitmap image) becomes a voxel (volumetric pixel), i.e., an intensity value on a regular grid in a three dimensional space."
Stacks are stored in RAM - Virtual Stacks are stored on the disk, and are read only, bu there are work arounds. TIF Virtual stacks can be accessed faster then JPG virtual stacks
JPG can be converted to TIF.
TIF is the Native format of imageJ:
TIFF (Tagged Image File Format) is the ‘default’ format of ImageJ
Images can be 1–bit, 8–bit, 16–bit (unsigned1), 32–bit (real) or RGB color.
TIFF files with multiple images of the same type and size open as Stacks or Hyperstacks.
ImageJ opens lossless compressed TIFF files (see II Image Types: Lossy Compression and Metadata) by the LZW, PackBits and ZIP (Deflate/Inflate) [2] compression schemes.
In addition, TIFF files can be opened and saved as ZIP archives. Tiff tags and information needed to import the file (number of images, offset to first images, gap between images) are printed to the Log Window when ImageJ is running in Debug Mode (Edit.Options.Misc..., see Settings and Preferences).
DICON also supported:
DICOM (Digital Imaging and Communications in Medicine) is a standard popular in the medical imaging community.
Support in ImageJ is limited to uncompressed DICOM files.
DICOM files containing multiple images open as Stacks. Use Image.Show Info... [i] to display the DICOM header information.
A DICOM sequence can be opened using File.Import.Image Sequence...
A DICOM sequence can be opened using File.Import.Image Sequence...
or by dragging and dropping the folder on the ‘ImageJ’ window.
Imported sequences are sorted by image number instead of filename and the tags are preserved when DICOM images are saved in TIFF format.
ImageJ supports custom DICOM dictionaries, such as the one at http://imagej.nih.gov/ij/download/docs/DICOM_Dictionary.txt.
More information can be found at the Center for Advanced Brain Imaging.
Tiff bitmapstacks can be "flattened " with a montage feature under the stacks menu
Chapter 12 of the Manual is on Volumes
Tuesday, August 30, 2016
GUI stuff - using houdini as an example
* to check your directX version: START->dxdiag
his is Houdini's technical layout mode - its shows the features of a 3D interface
we may or may not want to use.
Major Sections shown here (note the interface is very customisable)
Top row: file menus through to help menu
Under this: shelves - basically shortcuts to commands like make a cube at the origin
shelves are grouped into like minded tools or tool all using the same tech like polygons or volumes
Left: tall list like view:
tree view - a scene hierarchy, clicking on a leaf or node in the tree is the same as selecting the graphical representation of an object in the viewport (see below)
center: Viewport - where the openGL graphics is drawn representing the 3D scene
viewport top right yellow text: select camera to look through
TABS above openGL viewport"
#Scene view - currently displaying a single perspective view
can be split into four view like more CAD oriented software.
#Animation Editor - animation graph with 2D navigation (pan,zoom, zoom extends, frame, frame selected) and keyframing abilities
#render view, # Composite view, # motion FX view - beyond our scope
#Viewport left vertical ribbon: Mouse Selection Options
select objects, components, hierarchies with the mouse
select mouse modes (lasso, laser pointer, box-drag, circle-drag)
move, rotate, scale - I never use these, I use hot keys instead (Q,W,E,R)
adjust object pivot
Snaps (grid, curve, point etc)
render region - beyond our scope
inspect object properties by mouse over ?
flipbook/playblast animation
#lower Ribbon - Animation Controls - beyond our scope
animation playback,
timeslider
jogging controls - +1 single frame , minus 1 single frame
frame entry field
keyframe button
loop mode (play once, loop, ping pong)
audio
time global Settings ie playback rate in fps, min and max speed threshold
#Right Ribbon: Viewport Display Options - more suitable for us
show grid
lock camera to navigation
show lighting, texturing, ambient occlusion, realtime lighting level of accuracy
show points
show point normals
show point numbers
show primitive numbers
show primitive normals
show object names
show background image
show customized attributes
all this could really all be bundled into HUD (Heads up display) for us
# lower center: Python shell / Command feedback
# Top-Right: Node graph view - object level (this toggles to subobject level when required)
node hierarchy also shown here with node connections (wires)
# lower Right : Node Parameters
this is sensitive to which node is selected.
shows all relative information on a node:
Transforms, render settings
Shaders assigned
misc - including custom display color, icon scale etc.
*Any object hcan have custom data or meta data attached.
his is Houdini's technical layout mode - its shows the features of a 3D interface
we may or may not want to use.
Major Sections shown here (note the interface is very customisable)
Top row: file menus through to help menu
Under this: shelves - basically shortcuts to commands like make a cube at the origin
shelves are grouped into like minded tools or tool all using the same tech like polygons or volumes
Left: tall list like view:
tree view - a scene hierarchy, clicking on a leaf or node in the tree is the same as selecting the graphical representation of an object in the viewport (see below)
center: Viewport - where the openGL graphics is drawn representing the 3D scene
viewport top right yellow text: select camera to look through
TABS above openGL viewport"
#Scene view - currently displaying a single perspective view
can be split into four view like more CAD oriented software.
#Animation Editor - animation graph with 2D navigation (pan,zoom, zoom extends, frame, frame selected) and keyframing abilities
#render view, # Composite view, # motion FX view - beyond our scope
#Viewport left vertical ribbon: Mouse Selection Options
select objects, components, hierarchies with the mouse
select mouse modes (lasso, laser pointer, box-drag, circle-drag)
move, rotate, scale - I never use these, I use hot keys instead (Q,W,E,R)
adjust object pivot
Snaps (grid, curve, point etc)
render region - beyond our scope
inspect object properties by mouse over ?
flipbook/playblast animation
#lower Ribbon - Animation Controls - beyond our scope
animation playback,
timeslider
jogging controls - +1 single frame , minus 1 single frame
frame entry field
keyframe button
loop mode (play once, loop, ping pong)
audio
time global Settings ie playback rate in fps, min and max speed threshold
#Right Ribbon: Viewport Display Options - more suitable for us
show grid
lock camera to navigation
show lighting, texturing, ambient occlusion, realtime lighting level of accuracy
show points
show point normals
show point numbers
show primitive numbers
show primitive normals
show object names
show background image
show customized attributes
all this could really all be bundled into HUD (Heads up display) for us
# lower center: Python shell / Command feedback
# Top-Right: Node graph view - object level (this toggles to subobject level when required)
node hierarchy also shown here with node connections (wires)
# lower Right : Node Parameters
this is sensitive to which node is selected.
shows all relative information on a node:
Transforms, render settings
Shaders assigned
misc - including custom display color, icon scale etc.
*Any object hcan have custom data or meta data attached.
Wednesday, August 24, 2016
Client Meeting #1
A late introduction to our client Dr Greg Ruthenbeck
has revealed some directions to look into:
- he has already a lot of experience in the field so he can steer us in certain directions
the meeting revealed:
* dont assume we have convert between volumetric formats and triangles/"shells" right away or at all, maybe some 3D printers can print from a voxel format, a print is afterall just 3D space discretised (broken up into lots of cubes)
this reminds me the 2D world - of conversion from vector graphics to bitmaps
- you dont want to do it too soon - you may be open for a loss of data or image quality. or even a slight change in perception of an image when converting from vectors to a bitmap - may not be desirable
* pre-existing software to look into
Shapeways - triangle manip ? / libraries
searching for this gave me more of a 3D model market place ?
but then I saw this
http://www.shapeways.com/tutorials/supported-applications
Image J - powerful openSource image (voxel as well ?) manipulation
I had a quick look but couldnt see any mention to voxels
http://imagej.net/Welcome
DirectX as an alternative to openGL
- better support / documentation is an advantge
wikipedia:
DirectX is a set of low-level Application Programming Interfaces (APIs) that provides Windows programs with high-performance hardware-accelerated multimedia support. DirectX enables the program to easily determine the hardware capabilities of your computer, and then sets the program parameters to match.
*File Formats
Input
bitmap stacks (arrays of bitmaps)
DICON
http://www.dicomlibrary.com/dicom/
Output
stl (a shell of triangles for 3D printing) see previous post
gcode - an ascii printing description format to control a CNC machine
Action List
Follow up email for "the Client"
Download a Stanford 3D file of each available format
- done, i downloaded the partial brain
http://graphics.stanford.edu/data/voldata/
can i ?
Access it 3D with Code
Display it using direct 3D with navigation
Manipulate it in Direct 3D
Gantt Chart of tasks - can only be done after a WBS work breakdown structure
(a list of tasks we need to do)
(gantt chart is sure to be updated each week)
Draft Requirements Specification
modelling - boolean operations are needed GUI design -
we will need a HUD with useful info ie fps, triangle count, voxel count
we will know what we need to see as we go
(this could be useful to inject supporting structures)
what (libraries) can we lean on ?
Final Requirements spec due on Friday week.
List of New terms:
CT scan (Computer Tomography)
CNC
wikipedia:
A CNC router is a computer-controlled cutting machine related to the hand held router used for cutting various hard materials, such as wood, composites, aluminium, steel, plastics, and foams. CNC stands for computer numerical control.
MRI scan Magenetic Resonance Image/Imagery
http://insideinsides.blogspot.com.au/
Houdini can convert MRI to 3D models for us and thus to Voxels or a shell
http://www.3dde.com/plugins_page.htm
possibly MRI data available here can be converted to voxels:
https://www.nlm.nih.gov/research/visibl
GCode - an output format for printing.
Shell (triangle model ("hollow"))
Ray Marching- as i understand it - 'probing' a bunch of cubes with rays in
order to define / approximate a volume surface
has revealed some directions to look into:
- he has already a lot of experience in the field so he can steer us in certain directions
the meeting revealed:
* dont assume we have convert between volumetric formats and triangles/"shells" right away or at all, maybe some 3D printers can print from a voxel format, a print is afterall just 3D space discretised (broken up into lots of cubes)
this reminds me the 2D world - of conversion from vector graphics to bitmaps
- you dont want to do it too soon - you may be open for a loss of data or image quality. or even a slight change in perception of an image when converting from vectors to a bitmap - may not be desirable
* pre-existing software to look into
Shapeways - triangle manip ? / libraries
searching for this gave me more of a 3D model market place ?
but then I saw this
http://www.shapeways.com/tutorials/supported-applications
Image J - powerful openSource image (voxel as well ?) manipulation
I had a quick look but couldnt see any mention to voxels
http://imagej.net/Welcome
DirectX as an alternative to openGL
- better support / documentation is an advantge
wikipedia:
DirectX is a set of low-level Application Programming Interfaces (APIs) that provides Windows programs with high-performance hardware-accelerated multimedia support. DirectX enables the program to easily determine the hardware capabilities of your computer, and then sets the program parameters to match.
*File Formats
Input
bitmap stacks (arrays of bitmaps)
DICON
http://www.dicomlibrary.com/dicom/
Output
stl (a shell of triangles for 3D printing) see previous post
gcode - an ascii printing description format to control a CNC machine
Action List
Follow up email for "the Client"
Download a Stanford 3D file of each available format
- done, i downloaded the partial brain
http://graphics.stanford.edu/data/voldata/
can i ?
Access it 3D with Code
Display it using direct 3D with navigation
Manipulate it in Direct 3D
Gantt Chart of tasks - can only be done after a WBS work breakdown structure
(a list of tasks we need to do)
(gantt chart is sure to be updated each week)
Draft Requirements Specification
modelling - boolean operations are needed GUI design -
we will need a HUD with useful info ie fps, triangle count, voxel count
we will know what we need to see as we go
(this could be useful to inject supporting structures)
what (libraries) can we lean on ?
Final Requirements spec due on Friday week.
List of New terms:
CT scan (Computer Tomography)
CNC
wikipedia:
A CNC router is a computer-controlled cutting machine related to the hand held router used for cutting various hard materials, such as wood, composites, aluminium, steel, plastics, and foams. CNC stands for computer numerical control.
MRI scan Magenetic Resonance Image/Imagery
http://insideinsides.blogspot.com.au/
Houdini can convert MRI to 3D models for us and thus to Voxels or a shell
http://www.3dde.com/plugins_page.htm
possibly MRI data available here can be converted to voxels:
https://www.nlm.nih.gov/research/visibl
GCode - an output format for printing.
Shell (triangle model ("hollow"))
Ray Marching- as i understand it - 'probing' a bunch of cubes with rays in
order to define / approximate a volume surface
Subscribe to:
Posts (Atom)