Jump to content
Foersom

Delphi by Example: Images and Graphics

Recommended Posts

Quote

A TImage object (an object of a TImage class) can be used to display an image file like a JPEG or PNG file. However with the TImage object it is NOT possible to edit the image, draw graphics and change pixels. To work with the graphics and pixels of the image it must be moved to a TBitmap object.

Do you know what the reason might be for that design decision?

Share this post


Link to post
1 hour ago, Joseph MItzen said:

Do you know what the reason might be for that design decision?

I do not know why. I found that the BMP method was the simplest way to make it work.

Share this post


Link to post
54 minutes ago, Joseph MItzen said:

Do you know what the reason might be for that design decision?

BMP, PNG, JPEG, GIF etc. are encoding formats. The sole purpose of TPNGImage, TJPEGImage and TGIFImage is to read, write and display these formats. Their internal representation is optimized to handle the features of the file format. They are not optimized to handle image manipulation.


TBitmap on the other hand implements the BMP encoding and is internally represented as a native Windows DIB or DDB. TBitmap can wrap these with a TCanvas and thus provide access to most of the functionality of the GDI through the canvas.
Additionally almost all other formats can convert to and from TBitmap so there's no reason why all the other formats should duplicate the functionality in TBitmap/TCanvas/GDI. They would just have to convert to/from TBitmap internally to do so anyway.

 

Btw, using TCanvas.Pixels is extremely slow but fine for learning and very minor drawing tasks. For anything serious you have to mess with the raw DIB data directly - or use something like Graphics32 which does that for you. When you're using Pixels to manipulate the whole bitmap then the optimizations in the code become pretty pointless and only obfuscates the algorithm.

  • Like 1

Share this post


Link to post
34 minutes ago, Anders Melander said:

Additionally almost all other formats can convert to and from TBitmap so there's no reason why all the other formats should duplicate the functionality in TBitmap/TCanvas/GDI.

Why not have just one image type that can read/write multiple formats? Or at least have TJPEGImage, etc. descend from TBitmap rather than TGraphic?

Share this post


Link to post
27 minutes ago, Joseph MItzen said:

Why not have just one image type that can read/write multiple formats?

Monolithic design... Pick up any book on software design and it will explain why that is not a good idea. I'm not going to do it here.

 

32 minutes ago, Joseph MItzen said:

Or at least have TJPEGImage, etc. descend from TBitmap rather than TGraphic?

Unnecessary coupling. The above book will explain that too, but ask instead: Why should it?

 

Make a toolbox of individual tools that does as little as possible as good as possible and then assemble them into something larger. A swiss army knife is good to have if you're stranded on a deserted island. Besides that it's only good for impressing your 7 year old friends.

 

Anyway, we're hijacking Foersom's thread. I'm outta here.

Share this post


Link to post
12 minutes ago, Anders Melander said:

Monolithic design... Pick up any book on software design and it will explain why that is not a good idea. I'm not going to do it here.

 

Unnecessary coupling. The above book will explain that too, but ask instead: Why should it?

 

Having lots of methods that all do the same thing with a slight twist isn't a good idea. In normal development, you make that one function and supply a parameter. For instance, you don't want one function that returns squares of a number, another for cubes, etc. You have one power function that takes a parameter that raises a number to the specified power.

 

I'm also not clear about the coupling. Classic OOP would, for instance, create a deck of cards class and then inherit from that to produce a blackjack game and a poker class would similarly inherit from the deck class. In the VCL, TJpegImage, TPNGImage, etc. are all inheriting from the TGraphic base class. If they all inherited from the TImage class instead you wouldn't need to do any converting to load and alter an image.

 

In fact, this is how many popular image libraries across languages work. ImageMagick, one of the most popular open source image editing libraries, has a ReadImage method that takes a file name and returns an ImageMagick Image object. One function to load any image type, one object type returned to work with.

 

Pillow is the most popular library in Python. One image type, "image".  Further:


 

Quote

 

The Python Imaging Library supports a wide variety of image file formats. To read files from disk, use the open() function in the Image module. You don’t have to know the file format to open a file. The library automatically determines the format based on the contents of the file.

To save a file, use the save() method of the Image class. When saving files, the name becomes important. Unless you specify the format, the library uses the filename extension to discover which file storage format to use.

 

Same idea as ImageMagick. It's the VCL inheritance scheme that seems rather ad hoc and unusual.

Share this post


Link to post
17 minutes ago, Joseph MItzen said:

Classic OOP would, for instance, create a deck of cards class and then inherit from that to produce a blackjack game

Nope. A deck is model, data, state and maybe presentation. The game is logic.

A game is not a deck. A game uses a deck. Really basic OOP since we're going there.

 

18 minutes ago, Joseph MItzen said:

n the VCL, TJpegImage, TPNGImage, etc. are all inheriting from the TGraphic base class. If they all inherited from the TImage class instead

Why stop there?

What about layers, filters, transformations, scanner and cloud support. Yes, let's add SOAP, REST, FTP and Kermit support in case need to transfer these images between systems.

Why do we need different classes at all? We could just create a single class that does EVERYTHING.

 

6 minutes ago, Joseph MItzen said:

It's the VCL inheritance scheme that seems rather ad hoc and unusual.

You're confusing high level ease of use with low level architecture. The difference between the VCL and f.ex. ImageMagic is that one of them has it and the other doesn't. I'm guessing you've never read through the ImageMagick source code since you use it as a reference. I have. It's written in C. That might give you an idea of the inheritance scheme it uses... No?

 

There's really no point in me trying to explain my point further since our reference frames are obviously worlds apart. Good night and good luck.

  • Like 1

Share this post


Link to post
2 hours ago, Anders Melander said:

What about layers, filters, transformations, scanner and cloud support. Yes, let's add SOAP, REST, FTP and Kermit support in case need to transfer these images between systems. 

Why do we need different classes at all? We could just create a single class that does EVERYTHING.

You really don't want to have an honest discussion, do you? You seemed to come into it with some sort of chip on your shoulder.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×