It is currently Fri Apr 28, 2017 8:43 pm

All times are UTC - 5 hours




 Page 1 of 1 [ 16 posts ] 
Author Message
 Post subject: Shader VMK 33 - GrayArray2d
PostPosted: Sun Sep 29, 2013 6:04 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
The GrayArray2d class is created in this VMK and the mko file format is described in detail. The 010 Editor template files are also included with this VMK so that mko files can be parsed correctly if you use that binary editor.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Sun Aug 23, 2015 7:19 pm 

Joined: Fri Aug 22, 2014 3:54 pm
Posts: 17
Hey Marek,

I'm trying to convert some images of mine into their GrayScale counterpart to load in via the MKO file format for Array2D. I'm not sure if I'm doing it correctly though since I can never make the images appear properly. They are always horribly distorted beyond recognition.

Since the basic format, as explained in the video is

[header]
http://www.MarekKnows.com
version
type
Width (unsigned char)
Height (unsigned char)
[/header]
[data]
Data... (unsigned char)
[/data]

I tried to convert a picture of mine by using the average method Gray = ((r+b+g)/3). The issue I think I'm running into is that the width and height are unchanged, but I just converted 3 pixels into 1, so my width and height essentially got divided by 3. I've tried to correct this by just writing the Gray value 3 times, but it still doesn't fix the issue. Do you have any suggestions?


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Sun Aug 23, 2015 8:38 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
if you are converting a color picture into a black and white picture, you should still have the same number of pixels. ie if your original image is 600x300 pixels in size, when you convert it to b/w, it should still be 600x300 pixels in size not 200x100.

If you have a color image, each pixel will have a red,green,and blue value associated with it. That means that each pixel will be 3 bytes big. If you have a black and white image, then each pixel will only have one byte representing the color. That is where the factor of 3 comes in.

So you need to convert each pixels color to gray scale for all the pixels.

Does that make sense?


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Sat Aug 29, 2015 5:00 pm 

Joined: Fri Aug 22, 2014 3:54 pm
Posts: 17
Marek wrote:
if you are converting a color picture into a black and white picture, you should still have the same number of pixels. ie if your original image is 600x300 pixels in size, when you convert it to b/w, it should still be 600x300 pixels in size not 200x100.

If you have a color image, each pixel will have a red,green,and blue value associated with it. That means that each pixel will be 3 bytes big. If you have a black and white image, then each pixel will only have one byte representing the color. That is where the factor of 3 comes in.

So you need to convert each pixels color to gray scale for all the pixels.

Does that make sense?



I've been working on this since, and I still can't seem to figure out what I'm messing up with. My code is below to convert a BMP into a MKO GrayArray2d format. Can you perhaps tell me where it is failing at?

void ConvertBMP(const string& strFile){
   int i;
   // Little error checking is performed. Expects perfect files
   ifstream fin;
   stringstream ss, buf;
   vector<string> result;
   unsigned char info[54];

   fin.open(strFile, ifstream::binary);
   if (!fin.is_open()){
      cout << "Error opening file " << strFile << endl;
      return;
   }
   fin.read(reinterpret_cast<char*>(&info), sizeof(unsigned char)*54);

   // extract image height and width from header
   int width = *(int*)&info[18];
   int height = *(int*)&info[22];
   int size = 3 * width * height;
   vector<unsigned char> data;

   cout << "BMP Height = " << height << endl;
   cout << "BMP Width = " << width << endl;
   for (unsigned p = 0; p < size; p++){
      unsigned char d = 0;
      fin.read(reinterpret_cast<char*>(&d), sizeof(unsigned char));
      data.push_back(d);
   }
   fin.close();

   for (i = 0; i < size; i += 3)
   {
      unsigned char tmp = data[i];
      data[i] = data[i + 2];
      data[i + 2] = tmp;
   }
   // Output
   string strOutFilename = strFile.substr(0, strFile.find_first_of(".")) + string(".mko");
   cout << "Attempting to create file " << strOutFilename << endl;
   ofstream fout(strOutFilename, ofstream::binary);
   if (!fout.is_open()){
      cout << "Failed to write file.\n";
      return;
   }

   // Prepare MarekHeaders
   string strIdentifier(20, 0);
   strIdentifier = "www.MarekKnows.com";
   unsigned version = 1;
   unsigned type = 1; // GrayArray2d file
   unsigned uwidth = width;
   unsigned uheight = height;


   cout << "Writing MKO header...\n";
   // Write Header Data
   fout.write(strIdentifier.c_str(), sizeof(char)* 20);
   fout.write(reinterpret_cast<char*>(&version), sizeof(unsigned));
   fout.write(reinterpret_cast<char*>(&type), sizeof(unsigned));
   fout.write(reinterpret_cast<char*>(&uwidth), sizeof(unsigned));
   fout.write(reinterpret_cast<char*>(&uwidth), sizeof(unsigned));


   cout << "Writing grayscale data...\n";
   // Make use of Method 3
   // http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/
   //
   for (i = 0; i < size; i += 3)
   {
      //unsigned char Gray = (data[i] * 0.2126 + data[i + 1] * 0.7152 + data[i + 2] * 0.0722);
      unsigned char Gray = (data[i] + data[i + 1] + data[i + 2])/3;
      fout.write(reinterpret_cast<char*>(&Gray), sizeof(unsigned char));
      fout.write(reinterpret_cast<char*>(&Gray), sizeof(unsigned char));
      fout.write(reinterpret_cast<char*>(&Gray), sizeof(unsigned char));
   }

   fout.close();

   cout << "Conversion complete!\n";
}


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Sat Aug 29, 2015 7:55 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
firstly, did you confirm that you are reading the data from the BMP file correctly? I noticed that you are not checking the number of bits per pixel, which is the color depth of the image. Typical values are 1, 4, 8, 16, 24 and 32.

You need to know this so that you know how many bits per pixel you have stored in the BMP file so that you can load the correct data in.

The other thing that looks wrong in your code is the way that you are writing the grayscale data. The header looks okay but the data part looks wrong. If your image is 10 pixels wide by 5 pixels high, then you need to write out 50 unsigned char values for all the pixels to be stored in the file.

Assuming your BMP has RGB values for each pixel, then for each pixel you want to calculate the gray value and store it out.

So your loop should look something like:

int numPixels = bmpWidth * bmpHeight;
std::vector<unsigned char> grayData( numPixels, 0 );

for( int iPixel = 0; iPixel < numPixels; ++iPixel ) {
  //assuming 3 bytes per pixel
  unsigned char ucRed = 0;
  fin.read(reinterpret_cast<char*>(&ucRed), sizeof(unsigned char));
  unsigned char ucGreen = 0;
  fin.read(reinterpret_cast<char*>(&ucGreen), sizeof(unsigned char));
  unsigned char ucBlue = 0;
  fin.read(reinterpret_cast<char*>(&ucBlue), sizeof(unsigned char));

  float fGrayValue = ucRed * 0.2126f + ucGreen * 0.7152f + ucBlue * 0.0722f;
  unsigned char ucGray= static_cast<unsigned char>( fGrayValue ) ); 
  fout.write( &ucGray), sizeof(unsigned char) );
}


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Sat Aug 29, 2015 10:04 pm 

Joined: Fri Aug 22, 2014 3:54 pm
Posts: 17
I've been using a 24BPP BMP image, so I didn't bother checking. I added checking in though since you brought it up.

I'm still slightly confused by your post though. It appears as if you're reading in 3 unsigned char values, (3 bytes total for RGB) and then only writing back the converted value once (1 byte). Am I misunderstanding that? It sounds like the file is being cut in size by a third.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Sun Aug 30, 2015 6:17 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
Celestialkey wrote:
It appears as if you're reading in 3 unsigned char values, (3 bytes total for RGB) and then only writing back the converted value once (1 byte). Am I misunderstanding that? It sounds like the file is being cut in size by a third.


That is exactly what is happening. We only need 1 byte per pixel for the color because the GrayArray2d only stores one byte per "pixel".


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Tue Mar 15, 2016 7:47 pm 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
I'm revisiting this concept in a different project. I'm using you the ShaderEngine's FileHandler - Logger - ExceptionHandler components to create a basic reusable library for just about any kind of project, program etc., I'm taking the idea of the FileHandler's derived classes for the TextFileReader and TextFileWriter and making one for a Generic BinaryFileReader & BinaryFileWriter. Considering that a majority of your MKO files are read as binary I'm using them to build or modify the current system. I specifically using the Array2d model since it is a template type. Now in the videos we have only created a GrayArray2d object by a typedef. In my current project This is what I have so far.

Array2d.h
#ifndef ARRAY2D_H
#define ARRAY2D_H

#include "BaseBinaryData.h"

namespace util {

struct Color3f {
   float red;
   float green;
   float blue;
}; // Color3f

struct Color4f {
   float red;
   float green;
   float blue;
   float alpha;
}; // Color4f

template <typename T>
class Array2d : public BaseBinaryData {
private:
   unsigned      m_width;
   unsigned      m_height;
   std::vector<T>  m_values;

public:
   Array2d( unsigned width, unsigned height, const std::vector<T>& values, const std::string& strId );
   //Array2d( const Array2d& c ); // Default OK
   // Virtual Methods Here

   const unsigned& getHeight() const;
   const unsigned& getWidth() const;

   const unsigned getIndex( unsigned x, unsigned y ) const;

   const T& getValue( unsigned x, unsigned y ) const;
   const T& operator[]( unsigned u ) const;

   //const Color4f& getColor( unsigned x, unsigned y ) const;

private:
   Array2d& operator=( const Array2d& c ); // Not Implemented

   unsigned numValuesPerElement();

}; // Array2d

typedef Array2d<unsigned char> GrayArray2d;
typedef Array2d<Color3f>       RGBArray2d;
typedef Array2d<Color4f>       RGBAArray2d;

#include "Array2d.inl"

} // namespace util

#endif // ARRAY2D_H


Array2d.inl
// ----------------------------------------------------------------------------
// Array2D
template<typename T>
Array2d<T>::Array2d( unsigned width, unsigned height, const std::vector<T>& values, const std::string& strId ) :
BaseBinaryData( strId ),
m_width( width ),
m_height( height ),
m_values( values ) {
   if ( m_values.size() != width * height * numValuesPerElement() ) {
      throw ExceptionHandler( __FUNCTION__ + std::string( " failed. width x height does not equal number of values stored in array" ) );
   }

   /* for ( unsigned h = 0; h < height; ++h ) {
      for( unsigned w = 0; w < width; ++w ) {
         std::cout << unsigned( m_values[w + width*h] ) << " ";
      }
      std::cout << std::endl;
   }*/

} // Array2d

// ----------------------------------------------------------------------------
// getWidth()
template<typename T>
const unsigned& Array2d<T>::getWidth() const {
   return m_width;
} // getWidth

// ----------------------------------------------------------------------------
// getHeight()
template<typename T>
const unsigned& Array2d<T>::getHeight() const {
   return m_height;
} // getHeight

// ----------------------------------------------------------------------------
// getIndex()
template<typename T>
const unsigned Array2d<T>::getIndex( unsigned x, unsigned y ) const {
   if ( x >= m_width || y >= m_height ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << "(" << x << "," << y << ") is out of bounds";
      throw ExceptionHandler( strStream );
   }

   return ( x + m_width*y );
} // getIndex

// ----------------------------------------------------------------------------
// getValue()
template<typename T>
const T& Array2d<T>::getValue( unsigned x, unsigned y ) const {
   return m_values.at( getIndex( x, y ) );
} // getValue

// ----------------------------------------------------------------------------
// operator[]
template<typename T>
const T& Array2d<T>::operator[]( unsigned u ) const {
   return m_values[u];
} // operator[]


Array2d.cpp
#include "stdafx.h"
#include "Array2d.h"

namespace util {

// ----------------------------------------------------------------------------
// numValuesPerElement()
unsigned Array2d<unsigned char>::numValuesPerElement() {
   return 1;
} // numValuesPerElement<unsigned char> GrayArray2d

// ----------------------------------------------------------------------------
// numValuesPerElement()
unsigned Array2d<Color3f>::numValuesPerElement() {
   return 3;
} // numValuesPerElemnent<Color3f> RGBArray2d

// ----------------------------------------------------------------------------
// numValuesPerElement()
unsigned Array2d<Color4f>::numValuesPerElement() {
   return 4;
} // numValuesPerElement<Color4f> RGBAArray2d

} // namespace util


And for my FileReader I have this

BinaryFileReader.h
#ifndef BINARY_FILE_READER_H
#define BINARY_FILE_READER_H

#include "FileHandler.h"

namespace util {

class BinaryFileReader : public FileHandler {
private:
   unsigned int m_uiVersion;

public:
   explicit BinaryFileReader( const std::string& strFilename );
   // virtual ~BinaryFileReader(); // Default OK

   template<typename T>
   T* getBinaryData( const std::string& strId = std::string() );

private:
   BinaryFileReader( const BinaryFileReader& c ); // Not Implemented
   BinaryFileReader& operator=( const BinaryFileReader& c ); // Not Implemented
   
   unsigned loadBinaryHeader();

   template<typename T>
   T* createBinaryData( const std::string& strId, unsigned uType );

}; // BinaryFileReader

#include "BinaryFileReader.inl"

} // namespace util

#endif // BINARY_FILE_READER_H


BinaryFileReader.inl
// ----------------------------------------------------------------------------
// getBinarayData()
template<typename T>
T* BinaryFileReader::getBinaryData( const std::string& strId ) {
   T* pData = createBinaryData<T>( strId, loadBinaryHeader() );
   m_fileStream.seekg( 0, m_fileStream.beg );
   return pData;
} // getBinaryData


BinaryFileReader.cpp
#include "stdafx.h"
#include "BinaryFileReader.h"

// Include The Binary Data Types Header Files Here
#include "Array2d.h"

namespace util {

// This Represents All Types That Can Be Generated: All Derived Types From
// BaseBinaryData Including Any Specific Type That May Have Multiple Configurations
enum BinaryType {
   BT_GRAYSCALE_ARRAY_2D = 0x1,
   BT_RGB_ARRAY_2D,
   BT_RGBA_ARRAY_2D,

   BT_GRAYSCALE_ARRAY_3D,
   BT_RGB_ARRAY_3D,
   BT_RGBA_ARRAY_3D,

   BT_MODEL = 0x16,

}; // BinaryType

// ----------------------------------------------------------------------------
// BinaryFileReader()
BinaryFileReader::BinaryFileReader( const std::string& strFilename ) :
FileHandler( strFilename, true ),
m_uiVersion( 0 ) {
} // BinaryFileReader

// ----------------------------------------------------------------------------
// loadBinaryHeader()
unsigned BinaryFileReader::loadBinaryHeader() {
   // Open File For Reading
   if ( !m_fileStream.is_open() ) {
      m_fileStream.open( m_strFilenameWithPath, std::ios_base::in | std::ios_base::binary );
      if ( !m_fileStream.is_open() ) {
         throwError( __FUNCTION__ + std::string( " can not open file for reading" ) );
      }
   }

   // Get Header Identifer
   const int iStringMaxLength = 20; // Size Of Your Header Description
   char szBinId[iStringMaxLength] = {0};
   m_fileStream.read( szBinId, iStringMaxLength );
   if ( strncmp( szBinId, "Templated Binaries", iStringMaxLength ) != 0 ) {
      throwError( __FUNCTION__ + std::string( " invalid binary file" ) );
   }

   // Get Version Number
   m_fileStream.read( reinterpret_cast<char*>( &m_uiVersion ), sizeof(unsigned int) );
   if ( m_fileStream.fail() || ( m_uiVersion == 0 ) ) {
      throwError( __FUNCTION__ + std::string( " invalid binary file, missing version number" ) );
   }

   // Get Binary Type
   unsigned uType = INVALID_UNSIGNED;
   m_fileStream.read( reinterpret_cast<char*>( &uType ), sizeof(unsigned) );
   if ( m_fileStream.fail() ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary file, missing type";
      throwError( strStream );
   }

   return uType;
} // loadBinaryHeader

// ----------------------------------------------------------------------------
// createBinaryData()
template<>
GrayArray2d* BinaryFileReader::createBinaryData( const std::string& strId, unsigned uType ) {
   if ( uType != BT_GRAYSCALE_ARRAY_2D ) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain GreyArray2d data" ) );
   }

   // Get Size
   unsigned width  = 0;
   unsigned height = 0;
   m_fileStream.read( reinterpret_cast<char*>(&width), sizeof(unsigned) );
   m_fileStream.read( reinterpret_cast<char*>(&height), sizeof(unsigned) );

   const unsigned numElements = width * height;

   if ( m_fileStream.fail() || numElements == 0 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary data file, invalid array size width{" << width << "} height{" << height << "}";
      throwError( strStream );
   }

   std::vector<unsigned char> vValues( numElements, 0 );
   m_fileStream.read( reinterpret_cast<char*>( &vValues[0] ), numElements * sizeof(unsigned char) );
   if ( m_fileStream.fail() ) {
      throwError( __FUNCTION__ + std::string( " invalid binary data file, not enough array elements" ) );
   }

   GrayArray2d* pAsset = new GrayArray2d( width, height, vValues, strId );
   return pAsset;
} // createBinaryData<GrayArray2D>

// ----------------------------------------------------------------------------
// createBinaryData()
template<>
RGBArray2d* BinaryFileReader::createBinaryData( const std::string& strId, unsigned uType ) {
   if ( uType != BT_RGB_ARRAY_2D ) {
      throwError(__FUNCTION__ + std::string(" failed. File does not contain GreyArray2d data" ) );
   }

   // Get Size
   unsigned width = 0;
   unsigned height = 0;
   m_fileStream.read( reinterpret_cast<char*>(&width), sizeof(unsigned) );
   m_fileStream.read( reinterpret_cast<char*>(&height), sizeof(unsigned) );

   const unsigned numElements = width * height * sizeof(Color3f);

   if ( m_fileStream.fail() || numElements == 0 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary data file, invalid array size width{" << width << "} height{" << height << "}";
      throwError( strStream );
   }

   std::vector<unsigned char> vValues( numElements, 0 );
   m_fileStream.read( reinterpret_cast<char*>( &vValues[0] ), numElements * sizeof(unsigned char) );
   if ( m_fileStream.fail() ) {
      throwError(__FUNCTION__ + std::string( " invalid binary data file, not enough array elements") );
   }

   RGBArray2d* pAsset = new RGBArray2d( width, height, vValues, strId );
   return pAsset;
} // createBinaryData<RGBArray2D>

// ----------------------------------------------------------------------------
// createBinaryType()
template<>
RGBAArray2d* BinaryFileReader::createBinaryData( const std::string& strId, unsigned uType ) {
   if (uType != BT_RGBA_ARRAY_2D) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain Array2d data" ) );
   }

   // Get Size
   unsigned width = 0;
   unsigned height = 0;
   m_fileStream.read( reinterpret_cast<char*>(&width), sizeof(unsigned) );
   m_fileStream.read( reinterpret_cast<char*>(&height), sizeof(unsigned) );

   const unsigned numElements = width * height * sizeof(Color4f);

   if ( m_fileStream.fail() || numElements == 0 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary data file, invalid array size width{" << width << "} height{" << height << "}";
      throwError( strStream );
   }

   std::vector<unsigned char> vValues( numElements, 0 );
   m_fileStream.read( reinterpret_cast<char*>(&vValues[0]), numElements * sizeof(unsigned char) );
   if (m_fileStream.fail()) {
      throwError(__FUNCTION__ + std::string( " invalid binary data file, not enough array elements" ) );
   }

   RGBAArray2d* pAsset = new RGBAArray2d( width, height, vValues, strId );
   return pAsset;
} // createBinaryType<RGBAArray2D>

// ----------------------------------------------------------------------------
//

// ----------------------------------------------------------------------------
//

// ----------------------------------------------------------------------------
//

} // namespace util


Most of this code in the BinaryFileReader is the same as the MKOFilereader with very slight modifications. And the Array2d is the basically the same only I added 2 more functions for the numValuesPerElement() based on which type is used. And I created temporary structs in the Array2d.h file for Color3f and Color4f.

Right now they Array2d compiles fine. However when I try to compile the BinaryFileReader it is failing to compile and this is the error message I'm getting:

1>------ Build started: Project: FileParse, Configuration: Debug Win32 ------
1>  BinaryFileReader.cpp
1>c:\users\skilz80\documents\visual studio 2015\projects\fileparse\fileparse\binaryfilereader.cpp(128): error C2664: 'util::Array2d<util::Color3f>::Array2d(const util::Array2d<util::Color3f> &)': cannot convert argument 3 from 'std::vector<unsigned char,std::allocator<_Ty>>' to 'const std::vector<T,std::allocator<_Ty>> &'
1>          with
1>          [
1>              _Ty=unsigned char
1>          ]
1>          and
1>          [
1>              T=util::Color3f,
1>              _Ty=util::Color3f
1>          ]
1>  c:\users\skilz80\documents\visual studio 2015\projects\fileparse\fileparse\binaryfilereader.cpp(128): note: Reason: cannot convert from 'std::vector<unsigned char,std::allocator<_Ty>>' to 'const std::vector<T,std::allocator<_Ty>>'
1>          with
1>          [
1>              _Ty=unsigned char
1>          ]
1>          and
1>          [
1>              T=util::Color3f,
1>              _Ty=util::Color3f
1>          ]
1>  c:\users\skilz80\documents\visual studio 2015\projects\fileparse\fileparse\binaryfilereader.cpp(128): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>c:\users\skilz80\documents\visual studio 2015\projects\fileparse\fileparse\binaryfilereader.cpp(160): error C2664: 'util::Array2d<util::Color4f>::Array2d(const util::Array2d<util::Color4f> &)': cannot convert argument 3 from 'std::vector<unsigned char,std::allocator<_Ty>>' to 'const std::vector<T,std::allocator<_Ty>> &'
1>          with
1>          [
1>              _Ty=unsigned char
1>          ]
1>          and
1>          [
1>              T=util::Color4f,
1>              _Ty=util::Color4f
1>          ]
1>  c:\users\skilz80\documents\visual studio 2015\projects\fileparse\fileparse\binaryfilereader.cpp(160): note: Reason: cannot convert from 'std::vector<unsigned char,std::allocator<_Ty>>' to 'const std::vector<T,std::allocator<_Ty>>'
1>          with
1>          [
1>              _Ty=unsigned char
1>          ]
1>          and
1>          [
1>              T=util::Color4f,
1>              _Ty=util::Color4f
1>          ]
1>  c:\users\skilz80\documents\visual studio 2015\projects\fileparse\fileparse\binaryfilereader.cpp(160): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Any help on what I'm missing would be greatly appreciated. Once I'm able to get this working, then I can apply basically the same thing to another class for Array3d. Then the process of creating any arbitrary binary data type should be quite simple. This is just a current road block for me. I've tried creating multiple constructors etc. But I can not seem to resolve these template errors.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Tue Mar 15, 2016 9:52 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
Can you show me what you have written on line 128 in your binaryfilereader.cpp


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Wed Mar 16, 2016 2:38 am 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
In my editor I have this for line 128 in BinaryFileReader.cpp

RGBArray2d* pAsset = new RGBArray2d( width, height, vValues, strId );


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Wed Mar 16, 2016 6:13 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
How is vValues defined?


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Wed Mar 16, 2016 9:35 am 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
 const std::vector<T>& values


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Wed Mar 16, 2016 9:42 am 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
Last night after some thought I tried this; it compiles and builds, but I have yet to create the files for 2D Arrays with Color3f or Color4f to test them.

   // This May Work
    Color3f colors;
   std::vector<Color3f> vColors;
   for ( unsigned u = 0; u < vValues.size(); u+=3 ) {
      colors.red = vValues[u];
      colors.green = vValues[u+1];
      colors.green = vValues[u+2];
      vColors.push_back( colors );
   }

   RGBArray2d* pAsset = new RGBArray2d( width, height, vColors, strId );
   return pAsset;


and

   // This May Work
   Color4f colors;
   std::vector<Color4f> vColors;
   for (unsigned u = 0; u < vValues.size(); u += 4) {
      colors.red = vValues[u];
      colors.green = vValues[u + 1];
      colors.green = vValues[u + 2];
      colors.alpha = vValues[u + 3];
      vColors.push_back(colors);
   }

   RGBAArray2d* pAsset = new RGBAArray2d( width, height, vColors, strId );
   return pAsset;


The only thing that may be of concern are these lines of code:

const unsigned numElements = width * height * sizeof(Color3f);


and

const unsigned numElements = width * height * sizeof(Color4f);


any thoughts?


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Wed Mar 16, 2016 9:59 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
okay, now you are constructing your array objects correctly I see. Looks good!


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Wed Mar 16, 2016 10:45 am 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
Yeah last night I was stumped for a while; just before I was about to give up and call it a night, I tried that one last method. Before hand I tried to have multiple constructors, I tried to template the structs for Color3f & Color4f etc. and the compiler errors were worse lol. After some thought I then realized that I needed to create a temporary Color3f & Color4f, set their values, then push them into the std::vector.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 33 - GrayArray2d
PostPosted: Wed Mar 16, 2016 8:01 pm 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
After creating my binary files for RGBArray2d and RGBAArray2d I had to adjust the code slightly. There were a couple of previous errors that I had. In my BinaryFileReader::createBinaryData() functions that will return a RGBArray2d* and a RGBAArray2d* object I had an error of assigning the appropriate colors; I made those correction. In the same functions I also had the adjust the calculations for the numElements variable. So for now I have it hard coded as width * height * 3 and width * height * 4 for now. I also had to fix the line m_fileStrem.read() for the last parameter. I have it set as , numElements * sizeof(unsigned char). This does work however within the Array2d class in the cpp file for the numValuesPerElement() I had to set each of these to return 1. The reason for this is even though there would be 12 colors for a RGBArray2d and 16 colors for RGBAArray2d returning 3 & 4 will fail. This is because instead of there being that many unsigned char's stored in the class's vector m_values. What is actually stored in these vectors is either a Color3f or Color4f struct object. So I now have these functions returning 1 if it seems misleading. Now back in the createBinaryData() functions after we read from the file and before we create a pointer to these typedefs I had to create a Color3f & Color4f temporary stack objects and a vector of these temp color objects and go through a for lop for the size of vValue, then increment by how many color elements are in each color object on each iteration of the loop. Saved the values from the vector to the temp Color3f and Color4f objects then push back this temp Color object into the vector. Once this loop is done, instead of passing vValues to the constructor I can now pass the vector of color objects. All works well; and I was able to print out the data to verify these work.

This is basically the same code from the ShaderEngine with very little modification. I only took the classes necessary to compile band build this while stripping out all of the "Window Create & OpenGL Graphics, Sound, GUI etc out." The purpose for this was to create a general generic library that is useful for any type of application with a very good logging, error handling and file handling system. With the concept of having a TextFileReader & TextFileWriter I now have a working BinaryFileReader. The only difference between the two is that since working with Binary Data is more stream lined I decided to go with a Template Approach. This means that the binary objects that you create will be of their own class type. Very similar to Marek's Array2d class. I actually used his class for testing purposes.

Here is the working code between the two classes that I had listed earlier.

Array2d.h
#ifndef ARRAY2D_H
#define ARRAY2D_H

#include "BaseBinaryData.h"

namespace util {

struct Color3f {
   float red;
   float green;
   float blue;
}; // Color3f

struct Color4f {
   float red;
   float green;
   float blue;
   float alpha;
}; // Color4f

template <typename T>
class Array2d : public BaseBinaryData {
private:
   unsigned      m_width;
   unsigned      m_height;
   std::vector<T>  m_values;

public:
   Array2d( unsigned width, unsigned height, const std::vector<T>& values, const std::string& strId );
   //Array2d( const Array2d& c ); // Default OK
   // Virtual Methods Here

   const unsigned& getHeight() const;
   const unsigned& getWidth() const;

   const unsigned getIndex( unsigned x, unsigned y ) const;

   const T& getValue( unsigned x, unsigned y ) const;
   const T& operator[]( unsigned u ) const;

   //const Color4f& getColor( unsigned x, unsigned y ) const;

private:
   Array2d& operator=( const Array2d& c ); // Not Implemented

   unsigned numValuesPerElement();

}; // Array2d

typedef Array2d<unsigned char> GrayArray2d;
typedef Array2d<Color3f> RGBArray2d;
typedef Array2d<Color4f> RGBAArray2d;

#include "Array2d.inl"

} // namespace util

#endif // ARRAY2D_H


Array2d.inl
// ----------------------------------------------------------------------------
// Array2D()
template<typename T>
Array2d<T>::Array2d( unsigned width, unsigned height, const std::vector<T>& values, const std::string& strId ) :
BaseBinaryData( strId ),
m_width( width ),
m_height( height ),
m_values( values ) {
   if ( m_values.size() != width * height * numValuesPerElement() ) {
      throw ExceptionHandler( __FUNCTION__ + std::string( " failed. width x height does not equal number of values stored in array" ) );
   }

   // Will Not Work With Multiple Types.
   /*for ( unsigned h = 0; h < height; ++h ) {
      for( unsigned w = 0; w < width; ++w ) {
         std::cout << unsigned( m_values[w + width*h] ) << " ";
      }
      std::cout << std::endl;
   }*/

} // Array2d

// ----------------------------------------------------------------------------
// getWidth()
template<typename T>
const unsigned& Array2d<T>::getWidth() const {
   return m_width;
} // getWidth

// ----------------------------------------------------------------------------
// getHeight()
template<typename T>
const unsigned& Array2d<T>::getHeight() const {
   return m_height;
} // getHeight

// ----------------------------------------------------------------------------
// getIndex()
template<typename T>
const unsigned Array2d<T>::getIndex( unsigned x, unsigned y ) const {
   if ( x >= m_width || y >= m_height ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << "(" << x << "," << y << ") is out of bounds";
      throw ExceptionHandler( strStream );
   }

   return ( x + m_width*y );
} // getIndex

// ----------------------------------------------------------------------------
// getValue()
template<typename T>
const T& Array2d<T>::getValue( unsigned x, unsigned y ) const {
   return m_values.at( getIndex( x, y ) );
} // getValue

// ----------------------------------------------------------------------------
// operator[]
template<typename T>
const T& Array2d<T>::operator[]( unsigned u ) const {
   return m_values[u];
} // operator[]


Array2d.cpp
#include "stdafx.h"
#include "Array2d.h"

namespace util {

// ----------------------------------------------------------------------------
// numValuesPerElement()
unsigned Array2d<unsigned char>::numValuesPerElement() {
   return 1;
} // numValuesPerElement<unsigned char> GrayArray2d

// ----------------------------------------------------------------------------
// numValuesPerElement()
unsigned Array2d<Color3f>::numValuesPerElement() {
   return 1;
} // numValuesPerElemnent<Color3> RGBArray2d

// ----------------------------------------------------------------------------
// numValuesPerElement()
unsigned Array2d<Color4f>::numValuesPerElement() {
   return 1;
} // numValuesPerElement<Color4> RGBAArray2d

} // namespace util


BinaryFileReader.h
#ifndef BINARY_FILE_READER_H
#define BINARY_FILE_READER_H

#include "FileHandler.h"

namespace util {

class BinaryFileReader : public FileHandler {
private:
   unsigned int m_uiVersion;

public:
   explicit BinaryFileReader( const std::string& strFilename );
   // virtual ~BinaryFileReader(); // Default OK

   template<typename T>
   T* getBinaryData( const std::string& strId = std::string() );

private:
   BinaryFileReader( const BinaryFileReader& c ); // Not Implemented
   BinaryFileReader& operator=( const BinaryFileReader& c ); // Not Implemented
   
   unsigned loadBinaryHeader();

   template<typename T>
   T* createBinaryData( const std::string& strId, unsigned uType );

}; // BinaryFileReader

#include "BinaryFileReader.inl"

} // namespace util

#endif // BINARY_FILE_READER_H


BinaryFileReader.inl
// ----------------------------------------------------------------------------
// getBinarayData()
template<typename T>
T* BinaryFileReader::getBinaryData( const std::string& strId ) {
   T* pData = createBinaryData<T>( strId, loadBinaryHeader() );
   m_fileStream.seekg( 0, m_fileStream.beg );
   return pData;
} // getBinaryData


BinaryFileReader.cpp
#include "stdafx.h"
#include "BinaryFileReader.h"

// Include The Binary Data Types Header Files Here
#include "Array2d.h"

namespace util {

// This Represents All Types That Can Be Generated: All Derived Types From
// BaseBinaryData Including Any Specific Type That May Have Multiple Configurations
enum BinaryType {
   BT_GRAYSCALE_ARRAY_2D = 0x1,
   BT_RGB_ARRAY_2D,
   BT_RGBA_ARRAY_2D,

   BT_GRAYSCALE_ARRAY_3D,
   BT_RGB_ARRAY_3D,
   BT_RGBA_ARRAY_3D,

   BT_MODEL = 0x16,

}; // BinaryType

// ----------------------------------------------------------------------------
// BinaryFileReader()
BinaryFileReader::BinaryFileReader( const std::string& strFilename ) :
FileHandler( strFilename, true ),
m_uiVersion( 0 ) {
} // BinaryFileReader

// ----------------------------------------------------------------------------
// loadBinaryHeader()
unsigned BinaryFileReader::loadBinaryHeader() {
   // Open File For Reading
   if ( !m_fileStream.is_open() ) {
      m_fileStream.open( m_strFilenameWithPath, std::ios_base::in | std::ios_base::binary );
      if ( !m_fileStream.is_open() ) {
         throwError( __FUNCTION__ + std::string( " can not open file for reading" ) );
      }
   }

   // Get Header Identifer
   const int iStringMaxLength = 20; // Size Of Your Header Description
   char szBinId[iStringMaxLength] = {0};
   m_fileStream.read( szBinId, iStringMaxLength );
   if ( strncmp( szBinId, "Templated Binaries", iStringMaxLength ) != 0 ) {
      throwError( __FUNCTION__ + std::string( " invalid binary file" ) );
   }

   // Get Version Number
   m_fileStream.read( reinterpret_cast<char*>( &m_uiVersion ), sizeof(unsigned int) );
   if ( m_fileStream.fail() || ( m_uiVersion == 0 ) ) {
      throwError( __FUNCTION__ + std::string( " invalid binary file, missing version number" ) );
   }

   // Get Binary Type
   unsigned uType = INVALID_UNSIGNED;
   m_fileStream.read( reinterpret_cast<char*>( &uType ), sizeof(unsigned) );
   if ( m_fileStream.fail() ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary file, missing type";
      throwError( strStream );
   }

   return uType;
} // loadBinaryHeader

// ----------------------------------------------------------------------------
// createBinaryData()
template<>
GrayArray2d* BinaryFileReader::createBinaryData( const std::string& strId, unsigned uType ) {
   if ( uType != BT_GRAYSCALE_ARRAY_2D ) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain GreyArray2d data" ) );
   }

   // Get Size
   unsigned width  = 0;
   unsigned height = 0;
   m_fileStream.read( reinterpret_cast<char*>(&width), sizeof(unsigned) );
   m_fileStream.read( reinterpret_cast<char*>(&height), sizeof(unsigned) );

   const unsigned numElements = width * height;

   if ( m_fileStream.fail() || numElements == 0 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary data file, invalid array size width{" << width << "} height{" << height << "}";
      throwError( strStream );
   }

   std::vector<unsigned char> vValues( numElements, 0 );
   m_fileStream.read( reinterpret_cast<char*>( &vValues[0] ), numElements * sizeof(unsigned char) );
   if ( m_fileStream.fail() ) {
      throwError( __FUNCTION__ + std::string( " invalid binary data file, not enough array elements" ) );
   }

   GrayArray2d* pAsset = new GrayArray2d( width, height, vValues, strId );
   return pAsset;
} // createBinaryData<GrayArray2D>

// ----------------------------------------------------------------------------
// createBinaryData()
template<>
RGBArray2d* BinaryFileReader::createBinaryData( const std::string& strId, unsigned uType ) {
   if ( uType != BT_RGB_ARRAY_2D ) {
      throwError(__FUNCTION__ + std::string(" failed. File does not contain RGBArray2d data" ) );
   }

   // Get Size
   unsigned width = 0;
   unsigned height = 0;
   m_fileStream.read( reinterpret_cast<char*>(&width), sizeof(unsigned) );
   m_fileStream.read( reinterpret_cast<char*>(&height), sizeof(unsigned) );

   const unsigned numElements = width * height * 3;

   if ( m_fileStream.fail() || numElements == 0 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary data file, invalid array size width{" << width << "} height{" << height << "}";
      throwError( strStream );
   }

   std::vector<unsigned char> vValues( numElements, 0 );
   m_fileStream.read( reinterpret_cast<char*>( &vValues[0] ), numElements * sizeof(unsigned char) );
   if ( m_fileStream.fail() ) {
      throwError(__FUNCTION__ + std::string( " invalid binary data file, not enough array elements") );
   }

   // This May Work
    Color3f colors;
   std::vector<Color3f> vColors;
   for ( unsigned u = 0; u < vValues.size(); u+=3 ) {
      colors.red   = vValues[u];
      colors.green = vValues[u+1];
      colors.blue  = vValues[u+2];
      vColors.push_back( colors );
   }

   RGBArray2d* pAsset = new RGBArray2d( width, height, vColors, strId );
   return pAsset;
} // createBinaryData<RGBArray2D>

// ----------------------------------------------------------------------------
// createBinaryData()
template<>
RGBAArray2d* BinaryFileReader::createBinaryData( const std::string& strId, unsigned uType ) {
   if (uType != BT_RGBA_ARRAY_2D) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain RGBAArray2d data" ) );
   }

   // Get Size
   unsigned width = 0;
   unsigned height = 0;
   m_fileStream.read( reinterpret_cast<char*>(&width), sizeof(unsigned) );
   m_fileStream.read( reinterpret_cast<char*>(&height), sizeof(unsigned) );

   const unsigned numElements = width * height * 4;

   if ( m_fileStream.fail() || numElements == 0 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " invalid binary data file, invalid array size width{" << width << "} height{" << height << "}";
      throwError( strStream );
   }

   std::vector<unsigned char> vValues( numElements, 0 );
   m_fileStream.read( reinterpret_cast<char*>(&vValues[0]), numElements * sizeof(unsigned char) );
   if (m_fileStream.fail()) {
      throwError(__FUNCTION__ + std::string( " invalid binary data file, not enough array elements" ) );
   }

   // This May Work
   Color4f colors;
   std::vector<Color4f> vColors;
   for (unsigned u = 0; u < vValues.size(); u += 4) {
      colors.red   = vValues[u];
      colors.green = vValues[u + 1];
      colors.blue  = vValues[u + 2];
      colors.alpha = vValues[u + 3];
      vColors.push_back(colors);
   }

   RGBAArray2d* pAsset = new RGBAArray2d( width, height, vColors, strId );
   return pAsset;
} // createBinaryData<RGBAArray2D>

} // namespace util


main.cpp
#include "stdafx.h"

#include "Array2d.h"
#include "BinaryFileReader.h"
#include "Logger.h"
#include "Utility.h"

int main () {
   using namespace util;

   Logger log( "log.txt" );

   BinaryFileReader fileRaw( "Debug/sampleRaw.bdt" );
   std::unique_ptr<GrayArray2d> grayArray2d( fileRaw.getBinaryData<GrayArray2d>() );

   unsigned width = grayArray2d->getWidth();
   unsigned height = grayArray2d->getHeight();

   for ( unsigned y = 0; y < height; y++ ) {
      for ( unsigned x = 0; x < width; x++ ) {
         std::cout << unsigned( grayArray2d->getValue( x, y ) ) << " ";
      }
      std::cout << std::endl;
   }
   std::cout << std::endl;

   BinaryFileReader fileColor( "Debug/sampleColor.bdt" );
   std::unique_ptr<RGBArray2d> colorArray2d( fileColor.getBinaryData<RGBArray2d>() );

   width  = colorArray2d->getWidth();
   height = colorArray2d->getHeight();

   for ( unsigned y = 0; y < height; y++ ) {
      for ( unsigned x = 0; x < width; x++ ) {
         Color3f color = colorArray2d->getValue( x, y );
         std::cout << "{" << static_cast<unsigned>( color.red   ) << ","
                 << static_cast<unsigned>( color.green ) << ","
                  << static_cast<unsigned>( color.blue  ) << "} ";
      }
      std::cout << std::endl;
   }
   std::cout << std::endl;

   BinaryFileReader fileColor3( "Debug/sampleColor3.bdt" );
   std::unique_ptr<RGBAArray2d> colorArray3d( fileColor3.getBinaryData<RGBAArray2d>() );

   width  = colorArray3d->getWidth();
   height = colorArray3d->getHeight();

   for ( unsigned y = 0; y < height; y++ ) {
      for( unsigned x = 0; x < height; x++ ) {
         Color4f color = colorArray3d->getValue( x, y );
         std::cout << "{" << static_cast<unsigned>( color.red   ) << ","
                  << static_cast<unsigned>( color.green ) << ","
                  << static_cast<unsigned>( color.blue  ) << ","
                  << static_cast<unsigned>( color.alpha ) << "} ";
      }
      std::cout << std::endl;
   }
   std::cout << std::endl;

   Utility::pressAnyKeyToQuit();
   return RETURN_OK;
} // main


In my RGBArray2d & RGBArray3d, I have a similar structure as Marek's *.mko files mainly because I was using his Array2d as a test case to use a single class type that is template and can return different types. The only difference is the initial string being stored into the file. But this is how my two files look in binary.

sampleColor.bdt - 2x2 with 3 Color Channel: Colors in order are 1,2,3,4,5,6,7,8,9,10,11,12
54 65 6D 70 C6 61 74 65 64 20 42 69 6E 61 72 69
65 73 00 00 01 00 00 00 02 00 00 00 02 00 00 00
02 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C


sampleColor3.bdt 2x2 with 4 Color Channel: Colors in order are 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
54 65 6D 70 C6 61 74 65 64 20 42 69 6E 61 72 69
65 73 00 00 01 00 00 00 03 00 00 00 02 00 00 00
02 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C
0D 0E 0F 10


And my output for these Array2d Objects:
output:
    Info [2016.03.16 20:49:49:091] Created Logger
    Info [2016.03.16 20:49:49:096] Created bin1
1 2 3
4 5 6

    Info [2016.03.16 20:49:49:101] Created bin2
{1,2,3} {4,5,6}
{7,8,9} {10,11,12}

    Info [2016.03.16 20:49:49:106] Created bin3
{1,2,3,4} {5,6,7,8}
{9,10,11,12} {13,14,15,16}

Press any key to quit


Now for this to compile; it would require other files that are not shown here. It will require the appropriate includes in stdafx.h A constant values and enums defined in stdafx.h. It will also require BaseBinaryData.h & cpp which is basically the same thing as Marek's BaseMko.h & cpp file except for the pure virtual method is stripped out. It will require FileHandler.h & cpp, TextFileReader.h & cpp slightly modified to remove the dependency of the AssetStorage, ShaderManagers, Settings class etc. BlockThread.h & cpp, ExceptionHandler.h & cpp, Logger.h & cpp, Singleton.h & cpp modified to strip out everything except for the Logger. Utility.h, inl & cpp are also required. For these other class objects please refer to Mareks Shader Engine Series VMKs.

Now as for my generic or general BinaryFileWriter class considering that we are working with templates and writing data objects to a file that will have different fields and different data types; what I'm thinking of doing is creating the BinaryFileWriter as an template class that is also an abstract data type. This means you will have to inherit from it. You will have to pass the class type to it and the filename that you would like to either create / write or append to. This hierarchy will be restricted to writing or appending to a file in binary only since we already have a BinaryFileReader, and a TextFileReader & Writer.


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 1 [ 16 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Jump to:  

cron