I am currently working on a simple image class in c++ which uses FreeImage internally to load and parse the image files. Anyways I am not really sure about how to implement my pixel array as generic, simple and safe as possible. For instance the class is supposed to handle different channel counts. Since for now I simply want to decide which pixel format to use based on the file type and pixel information freeImage gives me, the exact decisions have to be made at runtime, when actually loading the image. I think the only way to deal with this is to have a pointer to some abstract "Pixels" baseclass in the image class definition, and then allocate the correct format on the heap like this (basically a factory pattern):
//pseudo code
class Image{
template<class T, class TNumChannels>
struct Pixel
{
T v[TNumChannels];
};
class BasePixelArray{...};
class RGBPixelArray :
public std::vector<Pixel<uint8, 3> >,
public BasePixelArray
{
...
};
private:
BasePixelArray * m_pixelPtr;
public:
void loadImage(const std::string & _bla)
{
//parse and decide what pixelformat to use, i.e
m_pixelPtr = static_cast<BasePixelArray*>(new RGBPixelArray);
//fill array
....
}
};
i don't think this is ideal at all since I would like to avoid allocating from the heap , but since it has to be done at runtime I could not really think of anything else, so I was wondering if anybody of you guys might have a better idea!
Thanks
If you know all dimensions of image beforehand and if it's a large image (actually, it should be relatively small image), you can make it compile-time allocation on stack. If you don't know those details or you want to allocate large image, then allocation on heap is the only solution.
For more inspiration, you may want to take a look at the image and any_image models from Boost.GIL library.
You didn't mention your platform, but from the Windows perspective, here's my advice:
Stack, but keep in mind that the default user stack size is 1MB, which can be changed if you control the thread creation using _beginthreadex().
Heap, probably the most common choice
Use ::VirtualAlloc directly if you alloc/dealloc either very large buffers, or alloc/dealloc very frequently
Related
Background Info
I am writing a graph-drawing program. I have encountered a problem with templates and inheritance, and I do not know how to proceed. I do not know how I should design my code to enable me to do what I am trying to do. (Explanation below.)
Target
I have a template class, which represents "data". It looks something like the following:
template<typename T>
class GraphData
{
std::vector<T> data_x;
std::vector<T> data_y; // x and y should be held in separate vectors
}
This class is part of an inheritance hierarchy involving several classes.
The hierarchy looks something like this... (Sorry this is from my notes, awful diagram.)
Explanation
There is a base class. No real reason to have it right now, but I anticipate using it later.
Base_Legend adds functionality for legend drawing. New members added include a std::string, and Get/Set functions.
Base_Drawable adds a pure abstract = 0 member. void Draw(...). This is to force overloading in all inherited objects which are drawable.
GraphData_Generic adds functionality for adding/removing data points to a set of vectors. These are pure abstract methods, and must be overridden by any data classes which inherit.
GraphData and HistogramData are 2 data types which have implementations of the functions from GraphData_Generic. (No implementation of Draw().)
GraphData_GenericDrawable doesn't do anything. It is to be used as a base class pointer, so that a vector of these objects can be used as data (add/remove data points) and can be draw (using void Draw()). This class also can be used to call the Get()/Set() methods for the std::string to be used in the legend.
Finally, at the bottom are GraphData_Drawable and HistogramData_Drawable which overload the void Draw() function. This code specifies exactly how the data should be drawn, depending on whether we have a Histogram or general set of data points.
Problem
Currently, I am using template types. The type of data for the datapoints / histogram bin values is specified by using a template.
For example, one can have a HistogramData<double, HistogramData_Drawable<double>, HistogramData_Drawable<int>, etc... Similarly, one can have GraphData<double>, GraphData<float>, GraphData_Drawable`, etc...
So hopefully it should be fairly obvious what's going on here without me uploading my ~ 10000 lines of code...
Right, so, in addition I have some class Graph, which contains a std::vector<GraphData_Generic_Drawable*>, hence the use of the base class pointer, as suggested above.
BUT! One has to decide what type of data should be used as the underlying type. I MUST choose either std::vector<GraphData_Generic_Drawable<double>*> or std::vector<GraphData_Generic_Drawable<float>*>.
This isn't useful, for obvious reasons! (I could choose double and force the user to convert all values manually, but that's just an easy way out which creates more work later on.)
A (very) ugly solution would be to have a std::vector<> for each possible type... int long unsigned long long double float unsigned char... etc...
Obviously this is going to be hideous and essentially repeat loads of code..
So, I intend to implement an AddData method which adds data to that vector, and I also currently have the following method:
// In class Graph
void DrawAll()
{
for(std::vector<GraphData_Drawable*>::iterator it = m_data.begin(); it != m_data.end(); ++ it)
(*iterator)->Draw(arguments);
} // Draw function takes arguments including a canvas to draw to, but this isn't directly relevant to the question
Which iterates over the vector and calls Draw for each set of data in there.
How to fix it?
My current thoughts are something along the lines of; I need to implement some sort of interface for an underlying data class, which retrieves values independent of the underlying type. But this is only a very vague initial idea and I'm not really sure how I would go about implementing this, hence the question... I'm not sure this is even what I should be doing...
If this isn't clear ask me a question and I'll update this with more details.
I am using a dll which code I cannot change. I have a public interface that exposes a class Surface that I am using.
The code of the dll contains something similar to this:
static Texture staticTexture[MAXTEXTURECOUNT];
static Texture *staticTextureCurrent = NULL;
static Texture *staticGetTextureById(int id);
class Texture
{
public:
int _id;
...
void *_dib;
...
};
void Surface::DrawSetTexture(int id)
{
Texture *texture = staticGetTextureById(id);
staticTextureCurrent = texture;
}
The Texture class is not exposed in any way by the public header files. I need to access the memory that is being pointed to by Texture::_dib. Ideally I would want to be able to call staticGetTextureById from anywhere, but the memory is what I am after.
I do however know more or less how the Texture class looks like.
I already tried to see if I can recover the Texture pointer by fiddling with the cpu registers after a call to DrawSetTexture, but that didn't work out at all.
Any ideas how to retrieve this pointer? I would be glad about any solution no matter how hacky as long as it doesn't crash and works somewhat reliably. I need a faster way to draw to that memory then with what I am given.
From my understanding, classes operate similarly to structs in C in terms of how they're set up. So, perhaps by doing ptrToClassObject+offset it might just work. There's a way to get the offset of the class members, I just don't know anything about how that's set up.
Issue about Storeing unknown Data in a Class
How can I provide a class in C++ which is able to store any number of variables each of any type? From inside and outside of the class I would like to read, add, modify and delete these data.
So what I am looking for is maybe a list where the datatypes can vary.
Example how the Usage could look like
Class Object();
Object->Storage->Create("position", "float"); // create
Object->Storage->Write("position", 42.0f); // write
int Result = Object->Storage->Read("position"); // read
Object->Storage->Delete("position"); // delete
How to do that or why to do it in another Way
My question is if there is a common approach for this problem and what a good solution is. If my thoughts were not correct and there is another technique or place to store data for my aim (next paragraph) please tell me.
Optional Background Information and Context
The reason behind this need is that I am writing a kind of component based game engine. There are Components and Systems. A System could be the title menu or a world level and I can add as many Components to it as I wish. Every game tick, the System calls a specified method over all of its Components. Components are e.g. Physics, Terrain, Draw, Characters, Sound, ... The mentioned unknown data structure is what a Component should be able to store in its System. The Component is nearly static and its state depends on the storage it uses. This Storage system is (together with the event manager) used to communicate between Components.
Edit:
By researches I figured out that what I want is called Data Centered or Data Oriented in software design. Now I have a starting point to do more research on this topic. Thank you Michael Anderson for your answer, probably I will use that.
You probably want to use boost::any for this kind of thing.
Your code will look like this:
std::map<std::string,boost::any> object;
object["position"] = 42.0f;
//This will throw if the type is wrong
int Result = boost::any_cast<float>(object["position"]);
object.erase("position");
Does the Standard Template Library (STL) - more specifically, the use of a map - not work for your needs?
http://en.cppreference.com/w/cpp/container/map
You can use the map to hold values which are either:
1) a "CustomObject", which is a union of all possible variable / object types.
2) a pointer to the actual objects / variables.
I have a problem with the SLMATH library. Not sure if anyone uses it or has used it before? Anyway, the issue is that when I compile with SSE optimisation enabled (in VS 2010), I obviously have to provide a container that has the correct byte alignment for SSE type objects. This is OK because there's a little class in SLMATH that's an aligned vector; it aligns the vector allocation on an 8 byte boundary (i.e. I do not use std::vector<>).
Now the problem is that it appears any structure or class that contains something like slm::mat4 must also be aligned on such a boundary too, before it's put into a collection. So, for example, I used an aligned vector to create an array of slm::mat4, but if I create a class called Mesh, and Mesh contains an slm::mat4 and I want to put Mesh into a std::vector, well, I get strange memory errors whilst debugging.
So given the documentation is very sparse indeed, can anyone who's used this library tell me what, precisely, I have to do to use it with SSE optimisation? I mean I don't like the idea of having to use aligned vectors absolutely everywhere in place of std::vector just in case an slm:: component ends up being encapsulated into a class or structure somehow.
Alternatively, a fast vector/matrix/graphics math library as good as SLMATH would be great if there's on around.
Thanks for any advice you can offer.
Edit 1: Simple repro-case not using SLMATH illustrates the problem:
#include <vector>
class Item
{
public:
__declspec(align(8))
struct {
float a, b, c, d;
} Aligned;
};
int main()
{
// Error - won't compile.
std::vector<Item> myItems;
}
Robin
It might work if you when you declare your variable to use __declspec(align) on your variable declarations, or to wrap them within a struct that declares itself to be aligned properly. I have not used the library in question, but it seems that this might be the issue you are facing.
The reference for the align option can be found here.
Right now my gui is abstract and basically has a Bitmap class which holds a void* to the native bitmap type. The way it works is I have an abstract bitmap loader which returns a void pointer to the image data given a path string. the loader is a static pointer in the Bitmap data type and is set by the user for whatever backend used. The Graphics class is abstract and a pointer to it is asked for by the Gui class. When the backend for the Graphics class draws an image it does something like this:
void Allegro5GraphicsManager::drawImage( const Bitmap &bmp,
const Point &position,
const Point ®ionStart,
const Dimension ®ionSize,
const float &opacity /*= 1.0f*/ )
{
al_draw_tinted_bitmap_region((ALLEGRO_BITMAP*)bmp.getBitmap(),
al_map_rgba_f(opacity,opacity,opacity,opacity),
regionStart.getX(),regionStart.getY(),
regionSize.getWidth(),regionSize.getHeight(),
position.getX() + getOffset().getX(),position.getY() + getOffset().getY(), 0);
}
So as you can see it mearly type casts the void* to what it needs.
The problem is I hear void*s are not a good idea in C++.
The other solution I thought of is for something like Allegro5Bitmap which would inherit from Bitmap.
The problem I had with this method was that the user would then have to plaster Allegro5Bitmap all over their code. And this defeats the concept of my API which is for all code written to be portable to other backends like sdl, etc, by simply initializing the Gui class with sdl manager pointers.
What could I do?
Thanks
No, this is bad design. void* is what you definitely want to get rid of in C++.
It is not fully clear to me what problem you are trying to solve. Is it only about abstracting I/O of images or also drawing of them?
the typical solution to the I/O problem is to have ImageReader/ImageWriter abstract classes. Then their implementations are based on image type or I/O backend. These classes are basically factories for Image objects.
What you are handling in your code afterwards is still a generic Image (btw. you know that a "bitmap" actually is a black+white image?).
Note: Even if you need to have different types of Image objects (derivations), the factory is the typical pattern to resolve your issue while staying generic in your other code. You obtain an Image object from the factory, that in fact is an AllegroImage or whatever other type. You only call the base class methods on the Image so you don't care.