Design suggestions for an Image class hierarchy - c++

I need some design suggestions for an Image class hierarchy.
Currently, I have 2 types of images (one is a standard image, the second doesn't contain standard image data).
Sometimes I want the object to allocate the memory for the image data, and other times I just want it to point to it.
The problem arises when I want to give TypeA images specific functionality.
If TypeA images inherit from Image, I will have to duplicate the functionality of the Allocated vs. non-Allocated Image.
I'm sure there is a better way to do this, I remember some elegant solutions with mixins during university, but can't find a way to use that here.
My current design looks like:
class Image
{
public:
Image(int width, int height, int bpp);
virtual ~Image() {};
// getters
template <typename T>
T* ptr() { return reinterpret_cast<T*>(m_imageData); } // T depends on bpp
protected:
// metadata
char* m_imageData;
};
class AllocImage : public Image
{
public:
AllocImage(int width, int height, int bpp, DataType dataType) :
Image(width, height, bpp, dataType)
{
m_imageData = new char[m_dataSize];
}
~AllocImage()
{
delete m_imageData;
}
};
class ImageHolder : public Image
{
public:
ImageHolder(int width, int height, int bpp, DataType m_dataType);
void setPtr(const void* ptr);
};
class AllocatedImageTypeA : public AllocImage
{
public:
// Type A specific methods
};
class NonAllocatedImageTypeA : public ImageHolder
{
public:
// duplicated Type A specific methods
};

If all the differences are constrained to how the image is held (allocated or not), you could use the policy model.
The short explanation is that you would pass a policy object to the image, where the policy describes whether you need to deallocate the image or not, how to access it, etc., basically anything that relates to the differences that arise from how the image data is held (allocated vs. pointed). Then all your access to the image will be through the policy.
For example, instead of writing
delete image;
You would write:
policy.del(image);
Where policy.del can be a delegate to delete or a no-op, depending on the actual type of the policy (that is in line with what the image requires)

Why so many types? If the difference is only in allocation, then simply create multiple constructors, one which takes a pointer to a pre-allocated data holder, one that doesn't and does the allocation internally. You could also use dependency injection to get the variations in behaviour / functionality.

I had a similar case.
Let's make something clear. Your class hierarchy its not based if an image is allocated or not, but, each class will have some features.
You may want to have a very specialized class that allocates images, another that references, and, warp that class with another of the same hierarchy, with similar features.
The following example, explains the idea of wraping one class, with another class,
from the same inheritance, that seems to apply to your questio.
Disclaimer: Please ignore, some minor bugs or non relevant syntax errors:
// generic base class for my image library:
/* abstract */ class GenericImage
{
public:
int width;
int height;
public:
/* constructor */ GenericImage() ;
/* destructor */ ~GenericImage() ;
/* constructor */ GenericImage(int newwidth, int newheight);
}; // class GenericImage
// in charge of allocating or deallocating an image
class AllocatedImage: GenericImage
{
public:
/* constructor */ AllocatedImage() ;
/* destructor */ ~AllocatedImage() ;
/* constructor */ AllocatedImage(int newwidth, int newheight);
/* constructor */ AllocatedImage(char* filename);
}; // class AllocatedImage
// access an image, but doesn't allocate or deallocate
class ContainedImage: GenericImage
{
public:
/* constructor */ ContainedImage() ;
/* destructor */ ~ContainedImage() ;
/* constructor */ ContainedImage(int newwidth, int newheight);
}; // class AllocatedImage
// real working class, will allocate other objects,
// of same hierarchy
class WrapperImage: GenericImage
{
public:
GenericImage* RealImage;
public:
/* constructor */ GenericImage() ;
/* destructor */ ~GenericImage() ;
void AllocateImage(AllocatedImage* newimage);
void HoldImage(ContainedImage* newimage);
}; // class AllocatedImage
Suggestions:
Its good idea, to have a constructor without parameters, specially if you are designing a class hierarchy, instead of a single class.
I know its a quick example, but, you may want to move all code to body file.
Cheers.

Related

How to declare a class member that may be one of two classes

I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?
You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();

Access to a method of Object C in an Object B both created by Object A

I think the problem is quite basic and there was the same Question for sure somewhere here but i wasn't able to find.
So here is the Problem. Top has access to MyCircle and calls the SetSize function. But MyCircle has no access to MyRect.
I am able to access MyRect if i am providing a pointer to MyRect within the Constructor of MyCircle, but i think there should be another way. Maybe i just got it wrong at all :( Thanks for your help.
in the
class Top{
public:
Rect myRect;
Circle myCircle;
void Run();
};
class Rect{
public:
int size;
};
class Circle{
public:
int size;
void SetSize(int buffer);
};
void Circle::SetSize(int buffer){
myRect.Size = buffer;
}
void Top:Run(){
myCircle.SetSize(10);
}
Don't pass a rectangle to a circle class, the circle should have no knowledge about the rectangle (or vice versa).
Instead make a function in Top using both the circle and rect and act on that.
I don't know exactly what you want to do, but suppose you want to set the sizes equally. Than make e.g. a SetSize method in Top setting the sizes for both the circle and rectangle:
e.g.
class Top{
public:
Rect myRect;
Circle myCircle;
void Run();
void SetSize(int size)
}
where SetSize is implemented as:
myRect.SetSize(size);
myCircle.size = size;
It's always better to put code handling multiple derived objects in the base class instead of in one of the children. If there will be too much (or unrelated) functionality in the base class, create a different class (like SizeHandler).
btw, it's better not to use public properties but always get/set methods.

Child classes that share Parent class member

I have an awkward question. I think it's impossible but I need to know for sure. It's a bit of an odd request, but I need my child classes to share the SAME Pixels vector from the parent class.
Basically, I want to create an instance of Image class. That Image class will hold Pixels for both Bitmap and Png Class so that if I need to convert from Bitmap To PNG and Vice-versa, they use the same vector rather than me creating both Bitmap and PNG classes.
class Image
{
private:
std::vector<RGB> Pixels;
};
class Bitmap : Image
{
public:
Bitmap() : Image() {};
};
class Png : Image
{
public:
Png() : Image() {};
};
Such that when I do:
int main()
{
Image Img();
Img.GetBitmapPixels(); //This
Img.GetPngPixels(); //And this, return the same Pixels Vector.
Bitmap Foo = Img.ToPng();
Png Moo = Img.ToBitmap();
//Such that both Foo and Moo have the exact same underlying Pixels Vector.
}
Currently my classes look like:
class Bitmap
{
private:
std::vector<RGB> Pixels;
public:
Bitmap();
std::vector<RGB> GetPixels() {return Pixels;}
void SetPixels(std::vector<RGB> Pixels) {this->Pixels = Pixels;}
};
class Png
{
private:
std::vector<RGB> Pixels;
public:
Png();
std::vector<RGB> GetPixels() {return Pixels;}
void SetPixels(std::vector<RGB> Pixels) {this->Pixels = Pixels;}
};
And to convert from one to the other, I have to do:
int main()
{
Bitmap Bmp();
Png PNG();
PNG.SetPixels(BMP.GetPixels); //BMP has to COPY PNG's Pixels and vice-versa..
}
It's kind of a stupid question. I just don't want to copy pixels. I just want to be able to convert between the two classes without any copying as both classes hold an std::vector Pixels member and the data is aligned the same.
I guess I'm trying to be able to do: PNG.SaveAsBitmap(...); Or BMP.SaveAsPNG(...); without creating a new instance of the other.
How can I avoid copying/creating and making a new instance of the other class I'm converting to? Can I have classes that inherit from eachother?
I may be oversimplyfying this. How are you loading your data? If it is the same for each image type could you have a load in the image class and just overload the Translation functions. I am not an expert on image data but could you do something similiar to:
public Image
{
private Pixels data;
public void GetPixels();
public virtual Pixels ToFormat(FormatEnum format);
}
public Bitmap:Image
{
public override Pixels ToFormat(FormatEnum format)
{
switch(format){
case FormatEnum.Bitmap:return data;break;
case FormatEnum.Png:return doSomethingElse();break;
}
}
}
int main()
{
Image Img();
Img.GetPixels();
Bitmap Foo = Img.ToFormat(Format.BitMap);
Png Moo = Img.ToFormat(Format.Png);
}
Since they share a parent as a common factor, you can elect to use pointers (this is considered a shallow copy), but this is usually not wise a deep copy is usually better. Perhaps you can create two functions one to create a shallow copy and one for a deep copy. Since a Bitmap and a Png are separate entities (they are siblings). Perhaps you should allow BMP to be the parent of png?
You may also elect to decouple the encoding altogether for saving purposes and just deal with the raw image data.

What's a good safe way to initialise memory for types I don't yet know about?

I started thinking about this after receiving an answer for this question. This is a bit tricky to explain, but I'll do my best.
I'm building a small(ish) 2D game engine. There are certain requirements that I need to satisfy, since this engine has to "work" with existing code that others have written for a different engine. Some change to existing code is inevitable, but I want to minimise it.
Users of my engine need to define entities called "gadgets". These are basically structs containing shapes and other state variables. These "gadgets" fall into classes, e.g. they may decide to define an icon gadget or a button gadget - or whatever.
They will also define a message handler for that class of gadgets.
E.g.
typedef struct
{
shape shapelist[5];
int num_options;
}interface;
static void interface_message_handler( interface * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
....
}
}
Users have already given me the corresponding message handler function and also the number of bytes in a interface object. And they can then ask the engine to create new instances of their gadgets via IDs e.g:
engine->CreateNewGadget( interface_gadget_class_ID, welcome_interface_ID );
where interface_gadget_class_ID is the ID for that class of gadgets and welcome_interface_ID is the instance ID. At some point during CreateNewGadget I need to a) allocate memory to hold a new gadget and then call the gadget class's message handler on it, with a NEW_MSG so that it can initialize itself.
The problem is, if all I'm doing is allocating memory - that memory is uninitialized (and that means all the struct members are uninitialized - so if interface contains a vector, for example, then I'm going to get some wierd results if the message handler does anything with it ).
To avoid wierd results caused by doing stuff to unintialized memory, I really need to call a constructor for that memory as well before passing it to the gadget's message handler function.
e.g in the case of interface:
pfunc(new (memory) interface);
But my question is, if I have no knowledge of the types that users are creating, how can I do that?
// We create a typedef that refers to a function pointer
// which is a function that returns an interface pointer
typedef interface * (*GadgetFactory)(void);
// we'll actually create these functions by using this template function
// Different version of this function will produce different classes.
template<typename T>
interface * create_object()
{
return new T;
}
// This function takes care of setting everything up.
template<typename T>
void RegisterGadgetType(int gadget_type_id)
{
// Get outselves a copy of a pointer to the function that will make the object
GadgetFactory factory = create_object<T>;
// store factory somewhere
}
interface * CreateGadget(int gadget_type_id)
{
// get factory
GadgetFactory factory;
// factory will give me the actual object type I need.
return (*factory)();
}
RegisterGadgetType<S>(2);
CreateGadget(2);
as i see it, you always know because interface_gadget_class_ID defines the type to create.
you create a base c++ class: (corresponds to class interface in your example). this base class contains all of data members which are used by every interface subclass (that is, every gadget).
the base class also declares all methods common to every gadget. example: each gadget is able to receive a call handleMessage. handleMessage is pure virtual, because this method is the subclasses' role to fulfill.
then you extend/subclass to support the stuff you have to do with each gadget's specialization. at this point, you add the members and methods specific to each gadget subclass.
CreateNewGadget serves as a factory for all your subclasses, where the arguments determine which class you will create.
from there, c++ will handle construction/destruction, allocation sizes, etc..
if you're allowing plugins with their own factories in your engine, then you'll need another level, where third parties register their custom types and inherit from your base(s).
here's a simple layout of the interfaces (in non-compiled pseudo code):
namespace MONGadgets {
class t_interface {
protected:
t_interface(/* ... */);
public:
virtual ~t_interface();
/* each subclass must override handleMessage */
virtual t_result handleMessage(const t_message& message) = 0;
};
namespace InterfaceSubclasses {
class t_gadget1 : public t_interface {
public:
t_gadget1(const welcome_interface_ID& welcome);
virtual ~t_gadget1();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget1\n";
}
/* gadget1 has no specific instance variables or methods to declare */
};
class t_gadget2 : public t_interface {
public:
t_gadget2(const welcome_interface_ID& welcome);
virtual ~t_gadget2();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget2\n";
}
private:
/* here is an example of a method specific to gadget2: */
void drawShape(const unsigned& idx);
private:
/* here is gadget2's unique data: */
shape shapelist[5];
int num_options;
};
namespace ClassID {
enum { Gadget1 = 1, Gadget2 = 2 };
}
}
/* replaced by virtual t_result t_interface::handleMessage(const t_message&)
- static void interface_message_handler( interface * myself, message * msg );
*/
class t_gadget_factory {
public:
t_interface* CreateNewGadget(const interface_gadget_class_ID& classID, const welcome_interface_ID& welcome) {
switch (classID) {
case InterfaceSubclasses::ClassID::Gadget1 :
return new InterfaceSubclasses::gadget1(welcome);
case InterfaceSubclasses::ClassID::Gadget2 :
return new InterfaceSubclasses::gadget2(welcome);
/* ... */
}
}
};
}
Example code (ignoring my other suggestion, about factories and virtual functions):
typedef struct
{
shape shapelist[5];
int num_options;
} interface;
static void interface_message_handler( void * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface *self = new (myself) interface;
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
case OTHER_MSG:
{
interface *self = static_cast<interface*>(myself);
...
}
break;
....
}
}
Then your CreateNewGadget code does:
void *ptr = malloc(some_amount);
msg newmsg;
newmsg.type = NEW_MSG;
// other fields
some_message_handler(ptr, &msg);
// now we have an initialized object, that we can add to our tree or whatever.
The less horrible version is more like this:
struct gadgetinterface {
virtual ~gadgetinterface() {}
virtual void handle_message(msg *) = 0;
};
struct mygadget : gadgetinterface {
void handle_message(msg *m) {
// no need for NEW_MSG, just do other messages
}
};
gadgetinterface *mygadget_factory(some parameters) {
// use some parameters, either passed to constructor or afterwards
return new mygadget();
}
Then we register a pointer to mygadget_factory with the gadget manager, and CreateNewGadget does this:
gadgetinterface *some_factory(some parameters); // that's it!
Where some_factory is the function pointer that was registered, so in the case of this gadget type, it points to mygadget_factory.

Accessing an object from a different class - Design

I have three classes, TImageProcessingEngine, TImage and TProcessing
TImageProcessingEngine is the one which i am using to expose all my methods to the world.
TImage is the one i plan to use generic image read and image write functions.
TProcessing contains methods that will perform imaging operations.
class TImageProcessingEngine
{
public:
TImage* mpImageProcessingEngine;
};
class TImage
{
public:
int ReadImage();
int WriteImage();
private:
//a two dimensional array holding the pixel values
tImageMatrix* mpImageMatrix;
};
class TProcessing
{
public:
int ConvertToBinary();
int ConvertToGrayScale();
};
My question is how do i access the object mpImageMatrix in class TProcessing? So that my calling application can use the following
TImageProcessingEngine* vEngine = new TImageProcessingEngine;
//Converts an input gray scsale image to binary image
vEngine->ReadImage().ConvertToBinary();
//Write the converted image to disk
vEngine->WriteImage();
delete vEngine;
vEngine = NULL;
//During this whole processing internally,
//the image is read in to `mpImageMatrix`
//and will also be holding the binarised image data,
//till writing the image to disk.
Or Do you recommend any other approach to my class design?
I would certainly recommend a different implementation, but let's check the design first.
I don't really understand the added value of TImageProcessingEngine, it doesn't bring any functionality.
My advice would be quite simple in fact:
Image class, to hold the values
Processing class (interface), to apply operations
Encoder and Decoder classes (interfaces), to read and write to different formats
It does make sense for the Processing class to have access to the images internal only if you can get efficiency from it (which is likely), in this case you can simply makes Processing friend and having it unpack the values for its derived
class Image
{
public:
Image();
void Accept(Processing& p);
void Encode(Encoder& e) const; // Image is not modified by encoding
void Decode(Decoder& d); // This actually resets the image content
private:
friend class Processing;
size_t mHeight;
size_t mWidth;
std::vector<Pixel> mPixels; // 2D array of Pixels
};
class Processing
{
public:
void apply(Image& image)
{
this->applyImpl(image.mHeight, image.mWidth, image.mPixels);
}
private:
virtual void applyImpl(size_t h, size_t w, std::vector<Pixel>& pixels) = 0;
};
Encoder and Decoder follow the same principle.
Note how I never needed an explicit pointer, and the guaranteed correctness that results from it.
First off, based on your provided code there are no ReadImage() & WriteImage() functions in the TImageProcessingEngine class, so the later code where you use such functionality is flawed.
As for the solution, you can make a getter function for the tImageMatrix pointer like this:
tImageMatrix* GetImageMatrix() { return mpImageMatrix; }
Then just pass that pointer (or a pointer to the whole TImage instance) to the TProcessing function you want to call.
Why you want to have a separate TProcessing process, when it specifically has functions just accessing mpImageMatrix;
In OOP, you have to bind the data members and it's operations..
So, IMO, remove your TProcessing class and have both the functions within TImage..
Your TImage will be like,
class TImage
{
public:
int ReadImage();
int WriteImage();
int ConvertToBinary();
int ConvertToGrayScale();
private:
//a two dimensional array holding the pixel values
tImageMatrix* mpImageMatrix;
};
You could create an accessor TImage class:
byte * pixelAt(unsigned x, unsigned y);