Object Oriented Bitmap

Started by
22 comments, last by Gladiator 21 years, 7 months ago
I''ve already done that and even though there are some nice classes out there, they don''t take into consideration other objects they have contact to (like my bitmap has contact with directdraw manager and vice versa). Also, I''d like to hear some ideas from people not just plain code.

Thanks though



-G|aD-
Advertisement
Paintings don''t paint themselves. Artists paint paintings.

So my images don''t have a ''draw'' function. My renderer has a draw function and you pass it the image.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]
That's all I'm asking for guys. That's an excellent idea and great new info to me.

Kylotian, your reply has raised a few questions in me. How would the renderer know what to draw and which method to use (bmp, jpg, gif, etc.)

Let's say I have this:


    class IImage  {protected:   int m_iWidth;   int m_iHeight;public:   IImage( ) : m_iWidth(0), m_iHeight(0) { };   virtual ~IImage( );  };class CBitmap : public IImage  {  DirectDrawSurface pSurface;public:  BOOL load( std::string strFileName ) {...};  void release( void ) {...};  };class CDirectDraw  {public:  void drawImage( const IImage &srcImage ); // **  };    


Ok, how do I make DDraw manager recognize which type of image it has to draw? Can you help me with some code snippets of the class interfaces and important implementation details?

I'm thinking of having a draw() method for each IImage derived class, make the method private, and define it as a friend to the DDraw manager. This way the manager will call the according method but it will still be private in the image object.

Please give me more suggestions/ideas/code snippets!

Thanks!

[edited by - Gladiator on September 10, 2002 9:22:23 PM]
What your failing to understand, that it doesnt matter what the image format is... once loaded into memeory they are all *bitmaps*... or just a raw array of pixel info...

if you want to keep with your class for each image type, what it should be used for is loading and saving of the data.

so your CJPG class will know how to load a JPG file and convert it into a bitmap in memory, or however else you require image data in memory.

CBitmap will do the same as CJPG, but it will convert the BMP fileformat into a bitmap in memory.

then you just need a public method/variable that is a handle to your pixels in memory, (in windows either a HDC/HBITMAP).

then your rasterizer (your CDirectDraw) will have a Draw function, that when called, will call/grab the handle to the image data from your CImage classes... and from that handle it can call the API draw methods to put that image on the screen.
shadwdrake, Thanks for the reply.

I understand what you are saying and the way that works. I guess I''m too deep into this OO thing and I''m having a hard time trying to make the classes as abstract as possible.

More replies please

I''m a newbie when it comes to object oriented design and architecture so anything that you say in that area is most likely new to me and will help me learn more.

Thanks!



-G|aD-
I would design such an image loader like this:
CImageLoader  virtual bool CanLoad() = 0  virtual bool LoadImage() = 0CImageServer  RegisterLoader()  UnregisterLoader()  CImage *NewImage()  CImage *LoadImage()CImage  Width()  Height()  Format()CBitmapImageLoder : CImageLoader  bool CanLoad()  CImage *LoadImage()CJPGImageLoader : CImageLoader  bool CanLoad()  CImage *LoadImage() 


You''ve got an CImageServer which manages image creation (either from file or a new image). Registered to the CImageServer are any number of CImageLoader-derived classes which are used to load various image formats from file.
Additional loaders can be added at any time, even after the library has been compiled by simply using the CImageServer::RegisterLoader() method.

CImage is then created by those loader, but does itself not know a thing about which file format it was loaded from. Why duplicate Width(), Height() and all that when it has nothing to do with the file on disc ?

I would strongly suggest not to put a Load() method into the image and not to derive CImage itself for different image formats, because you will be copy&pasting lots of code resulting in poor design.


You can find an object oriented C++ image loading library at http://www.paintlib.de

-Markus-
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
Markus, that''s the type of thing I want to see more often :-)

Your design is very enlightening and I''m getting lots of ideas at this moment. THANKS!

What books should I look into to configure my mindset to think in terms of objects and not functions (i.e. object oriented programming) when designing a program? Markus? Anyone else?

Thanks to all who replied. Keep the replies pouring in...



-G|aD-
quote:Original post by Gladiator
What books should I look into to configure my mindset to think in terms of objects and not functions (i.e. object oriented programming) when designing a program?

This is what scares me. There are times when functions are the more appropriate solution. What you want is to think in terms of the appropriate technology, not exclusively one or another.

Anyway, I''d have an Image class and a number of Load<Format>Image methods at global scope (not a part of the class).
class Image{public:  void allocate( unsigned long w, unsigned long h );  void set_fmt( ImageFormatDescriptor fmt );  // whatever private:  unsigned long * bits;  unsigned long width, height;}; bool LoadBMPImage( const std::string & filename, Image & img ){  // obtain BMP file dimensions (w, h)  // obtain image format (fmt)  img.allocate( width, height );  img.set_format( fmt );   // and so forth  return true;} 

You could also switch up the Load* interfaces so that they can be used as Image img = LoadBMPImage( "image.bmp" ); This clearly separates an image''s definition from implementations of algorithms that operate on the image, either loading, drawing, copying or otherwise manipulating it. Save class members for alterations of/access to intrinsic properties, allowing you to add more "external" operations without modifying the class definition.
Oluyseyi, I've had plenty of experience with functions and I know when they are appropriate. I'm trying to learn OOP now, and the whole point behind the project I'm currently working on is to get some design concepts into my programming so I know WHEN it is appropriate and HOW to design an object. Right now I don't know neither of the two in OOP, and only in modular which is not what I'm going after at this moment.

Edit: By the way, thanks for the design idea but as I said global functions are out of the question for this project

[edited by - Gladiator on September 11, 2002 2:34:02 AM]
quote:Original post by Gladiator
[...]
I''m currently working on is to get some design concepts into my programming so I know WHEN it is appropriate and HOW to design an object
[...]
Edit: By the way, thanks for the design idea but as I said global functions are out of the question for this project
You said you wanted to learn when it''s appropriate to use objects and when not. Well, here''s a situation when objects are not the best solution

I used to be pretty strict about not using globals, but now I have to rephrase myself: Most things that don''t have a state , should be globally accessible. By globally accessible, I mean you should put it within a namespace or within a singleton (search Google for singleton design pattern). Maybe as a static member function occasionally..

Loading images is (usually) a stateless operation and should be possible anywhere in your project. So Oluseyi''s design was good, but I prefer the Image img = LoadBMPImage( "image.bmp" ); way

This topic is closed to new replies.

Advertisement