• Welcome to OS2World OLD-STATIC-BACKUP Forum.
 

News:

This is an old OS2World backup forum for reference only. IT IS READ ONLY!!!

If you need help with OS/2 - eComStation visit http://www.os2world.com/forum

Main Menu

ReSize and convert Images

Started by jep, 2008.04.04, 00:11:31

Previous topic - Next topic

jep

Markes as: Easy
Hello,

here's the updated rexx dll to resize and convert Images.


  • Ensure that you have gbm.dll installed on your computer
    Unpack to a folder
    Add another folder into it and call it "images"
    Open the script and modify it (Important) or you'll end up with one of the images that is 90Mb in size.
    add two images to the folder "images" you just created, one gif and one bmp, both should have the name example before the dot and the extension.
    Run the script and see the result(s)

If you don't modify the script you'll notice that gbm will use all your RAM to do the scaling for the fifth image... it takes a while but should give you the image at the end.

This dll has been written and compiled by me using OpenWatcom 1.7, adjusted to the latest changes Heiko put into gbm and gbmsize.
The dll is based entierly on the code for gbmsize with the exception of a function for conversion to 24 bit pixel depth that has been taken from his rexx dll.
I've also provided string handling through a class to ease comparisons and conversions back and forth.

eville_hn

Hello,

I've read all your discussions about gbmrx (thread Determine Image Size) and to me it looks like having a special dll for operations that could be directly coded in REXX is overkill  ::). It took me about half an hour to hack a function in REXX that does almost the same as your dll. The benefit of having it coded in REXX is that no additional dll is required.

If the resize function is intended only for a one step operation on the same images, it might be OK. But if you plan to run another operation on the resized images afterwards it might be a rather bad idea. Not all output formats are lossless. If you scale a bitmap and write it as JPG image, then read it again for another operation and save it as JPG a second time, the image quality will suffer because JPG is a lossy format, also if quality is set to 100% when saving it!

I have attached the pure REXX version. Maybe some special features are missing but hey, it is REXX, so just add them.

eville

RobertM

Quote from: eville_hn on 2008.04.04, 03:31:14
Hello,

I've read all your discussions about gbmrx (thread Determine Image Size) and to me it looks like having a special dll for operations that could be directly coded in REXX is overkill  ::). It took me about half an hour to hack a function in REXX that does almost the same as your dll. The benefit of having it coded in REXX is that no additional dll is required.

If the resize function is intended only for a one step operation on the same images, it might be OK. But if you plan to run another operation on the resized images afterwards it might be a rather bad idea. Not all output formats are lossless. If you scale a bitmap and write it as JPG image, then read it again for another operation and save it as JPG a second time, the image quality will suffer because JPG is a lossy format, also if quality is set to 100% when saving it!

I have attached the pure REXX version. Maybe some special features are missing but hey, it is REXX, so just add them.

eville


The advantage(s) of having it in a REXX DLL is:


  • The DLL is faster than the interpreted code
  • As you noted, the same DLL can be used to provide added functionality
  • It simplifies the base code, since unlike C, you cannot (easily) have function calls to external REXX functions while maintaining full capabilities
  • Since GBM is being regularly updated, it means that, with no revisions to the REXX code for new formats, simply replacing the DLL with the newest version "updates" the REXX program's capabilities (for instance, being able to determine image sizes of new or variant image formats)
  • It means that (for instance in my case, where we use a lot of web scripts), one does not have to add a whole section of code to each and every REXX cgi script just to read image information... instead, I would load the DLL once on server startup, and then call the functions in it.
  • It increases cgi performance for more reasons than the fact that a C DLL is faster than interpreted code, such as the simple fact that the web server's cgi engine has a bunch less code to load to execute the same tasks (since the DLL is already loaded into memory, making the DLL call method not need to have a few dozen copies loaded, nor require the web server's cgi engine to reload that section of code for every thread it is running that uses that code)

Your points are no less valid.

Thus to clarify, my point is: each method has enticing reasons why some would prefer them. I personally prefer jep's method as most of the coding I do is either (a) for web cgi (and his method is more compact, faster, and easier to code with) and/or (b) I like writing wrapper functions for various things to simplify calling stuff from anywhere - which I find far easier with functions set up all in one DLL and/or (c) as my web server gets quite a decent amount of traffic, I find that 20 or 50 or 100 lines of extra code does indeed impact performance, disk usage, etc (and I like minimizing disk usage as much as possible since SCSI disk drives are kinda expensive).

For standalone apps that just need to query image parameters, having everything in REXX may be better, easier to implement, and would save memory since the code is only loaded with the app, then can be unloaded when the app exits (unlike my scenario, where the REXX DLL needs to be loaded at server start and NEVER unloaded).

So... thanks to both of you.  :)


|
|
Kirk's 5 Year Mission Continues at:
Star Trek New Voyages
|
|


jep

Quote from: eville_hn on 2008.04.04, 03:31:14
Hello,

I've read all your discussions about gbmrx (thread Determine Image Size) and to me it looks like having a special dll for operations that could be directly coded in REXX is overkill  ::). It took me about half an hour to hack a function in REXX that does almost the same as your dll. The benefit of having it coded in REXX is that no additional dll is required.

Quite true and your code is quite complete too, very good.
One may want to add the function "GBM_PaletteDataTo24bpp" so it can operate on many more images and filters?

You need the rexx dll ( gbmrx.dll ) on top of gbm.dll just as rxImgSze.dll would then be the replacement for lazy people. ;)

Quote from: eville_hn on 2008.04.04, 03:31:14
If the resize function is intended only for a one step operation on the same images, it might be OK. But if you plan to run another operation on the resized images afterwards it might be a rather bad idea. Not all output formats are lossless. If you scale a bitmap and write it as JPG image, then read it again for another operation and save it as JPG a second time, the image quality will suffer because JPG is a lossy format, also if quality is set to 100% when saving it!

I have attached the pure REXX version. Maybe some special features are missing but hey, it is REXX, so just add them.

eville
Yes, the greatness of GBM is that it can provide both flexiblity (trough usage of a rexx function) and full freedom to allow sophisticated operations over and over again, something that should be very useful to many users.

The example you provided should be included in the GBM package as it's easy to use and allow flexible operation as well as it's written as a function that make it ideal to cut and paste for other people.

Please do add it!!!
//Jan-Erik

eville_hn

Of course, you can use whatever you think is more suitable for you :) .
But there are some things I'd like to add to your notes.

Quote from: RobertM on 2008.04.04, 03:55:37

The advantage(s) of having it in a REXX DLL is:


  • The DLL is faster than the interpreted code

I don't think so because the DLL is basically doing nothing than forwarding parameters.

Quote from: RobertM on 2008.04.04, 03:55:37
  • As you noted, the same DLL can be used to provide added functionality
  • It simplifies the base code, since unlike C, you cannot (easily) have function calls to external REXX functions while maintaining full capabilities

This is not correct. You can have REXX functions externally. Just put the function code into a separate REXX file and call it exactly as the function name. If the function you want to have externally is called imgReSize, simply name the file imgResize.cmd and put the code into it but skip the function declaration and use exit() instead of return. The REXX interpreter will automatically call the the function when it is not found in the active REXX file. Have a look at the attached example. The package contains both variants.

Quote from: RobertM on 2008.04.04, 03:55:37
  • Since GBM is being regularly updated, it means that, with no revisions to the REXX code for new formats, simply replacing the DLL with the newest version "updates" the REXX program's capabilities (for instance, being able to determine image sizes of new or variant image formats)

In principle this is correct but in the special case that we discuss here it is different. The GBM code for scaling is not part of gbm.dll but part of either gbmrx.dll or jep's dll. This means that if a fix is done for the scaler,both dlls needs to be updated. If the function would be coded in REXX using gbmrx.dll, you would automatically get the fix because gbmrx.dll is always part of the GBM package.

Quote from: RobertM on 2008.04.04, 03:55:37
  • It means that (for instance in my case, where we use a lot of web scripts), one does not have to add a whole section of code to each and every REXX cgi script just to read image information... instead, I would load the DLL once on server startup, and then call the functions in it.

Have a look at the attached example on how this can be done.

Quote from: RobertM on 2008.04.04, 03:55:37
  • It increases cgi performance for more reasons than the fact that a C DLL is faster than interpreted code, such as the simple fact that the web server's cgi engine has a bunch less code to load to execute the same tasks (since the DLL is already loaded into memory, making the DLL call method not need to have a few dozen copies loaded, nor require the web server's cgi engine to reload that section of code for every thread it is running that uses that code)

If the function really has many things to do, you're right. But in this case you won't probably notice any difference. In case you don't know yet, the OS/2 REXX interpreter stores a tokenized version of the program in the extended attributes of the script. Thus running the script again is very fast. This is especially important for  externally located functions.

Quote from: RobertM on 2008.04.04, 03:55:37
Thus to clarify, my point is: each method has enticing reasons why some would prefer them. I personally prefer jep's method as most of the coding I do is either (a) for web cgi (and his method is more compact, faster, and easier to code with) and/or (b) I like writing wrapper functions for various things to simplify calling stuff from anywhere - which I find far easier with functions set up all in one DLL and/or (c) as my web server gets quite a decent amount of traffic, I find that 20 or 50 or 100 lines of extra code does indeed impact performance, disk usage, etc (and I like minimizing disk usage as much as possible since SCSI disk drives are kinda expensive).

Well, if reducing disk accesses is your optimization goal, you should better use a RAM disk or prevent creating temporary files. This is also the big advantage of the gbmrx API design. All transformations on the bitmap can be sequentially done in memory without writing intermediate files.

Quote from: RobertM on 2008.04.04, 03:55:37
For standalone apps that just need to query image parameters, having everything in REXX may be better, easier to implement, and would save memory since the code is only loaded with the app, then can be unloaded when the app exits (unlike my scenario, where the REXX DLL needs to be loaded at server start and NEVER unloaded).

The same mechanism also works with the externally located REXX function. In the attached example (runme_separate.cmd) the dll is loaded and only unloaded at the end of the program.


I hope the examples and the hints are helpful.  :)

eville

RobertM

Quote from: eville_hn on 2008.04.05, 00:52:02
Of course, you can use whatever you think is more suitable for you :) .
But there are some things I'd like to add to your notes.

Quote from: RobertM on 2008.04.04, 03:55:37

The advantage(s) of having it in a REXX DLL is:


  • The DLL is faster than the interpreted code

I don't think so because the DLL is basically doing nothing than forwarding parameters.

By design, compiled DLLs are faster than interpreted code.

Quote from: eville_hn on 2008.04.05, 00:52:02
Quote from: RobertM on 2008.04.04, 03:55:37
  • As you noted, the same DLL can be used to provide added functionality
  • It simplifies the base code, since unlike C, you cannot (easily) have function calls to external REXX functions while maintaining full capabilities

This is not correct. You can have REXX functions externally. Just put the function code into a separate REXX file and call it exactly as the function name. If the function you want to have externally is called imgReSize, simply name the file imgResize.cmd and put the code into it but skip the function declaration and use exit() instead of return. The REXX interpreter will automatically call the the function when it is not found in the active REXX file. Have a look at the attached example. The package contains both variants.

No... it is correct - I emphasized the part I am referring to - such as returning a stem array, or multiple values in different variables... which does not work with an external rexx function without using an additional DLL to add that support.



Quote from: eville_hn on 2008.04.05, 00:52:02

Quote from: RobertM on 2008.04.04, 03:55:37
  • Since GBM is being regularly updated, it means that, with no revisions to the REXX code for new formats, simply replacing the DLL with the newest version "updates" the REXX program's capabilities (for instance, being able to determine image sizes of new or variant image formats)

In principle this is correct but in the special case that we discuss here it is different. The GBM code for scaling is not part of gbm.dll but part of either gbmrx.dll or jep's dll. This means that if a fix is done for the scaler,both dlls needs to be updated. If the function would be coded in REXX using gbmrx.dll, you would automatically get the fix because gbmrx.dll is always part of the GBM package.


True...

Quote from: eville_hn on 2008.04.05, 00:52:02

Quote from: RobertM on 2008.04.04, 03:55:37
  • It means that (for instance in my case, where we use a lot of web scripts), one does not have to add a whole section of code to each and every REXX cgi script just to read image information... instead, I would load the DLL once on server startup, and then call the functions in it.

Have a look at the attached example on how this can be done.

I know ways of doing it... it can even be loaded into macrospace (but havent had too much luck using that for high availability... let's say 500 cgi processes accessing the same function at a time). Or it can be called from disk, meaning one function being called that is not inside the various cgi scripts calling it - but that means 1 function times 500 cgi scripts... it does add up - especially as the machine needs as much disk throughput as possible.


Quote from: eville_hn on 2008.04.05, 00:52:02

Quote from: RobertM on 2008.04.04, 03:55:37
  • It increases cgi performance for more reasons than the fact that a C DLL is faster than interpreted code, such as the simple fact that the web server's cgi engine has a bunch less code to load to execute the same tasks (since the DLL is already loaded into memory, making the DLL call method not need to have a few dozen copies loaded, nor require the web server's cgi engine to reload that section of code for every thread it is running that uses that code)

If the function really has many things to do, you're right. But in this case you won't probably notice any difference. In case you don't know yet, the OS/2 REXX interpreter stores a tokenized version of the program in the extended attributes of the script. Thus running the script again is very fast. This is especially important for  externally located functions.

True (and yes, I know that... even had rare situations where I had to drop the tokenized version to get the script to work properly). Point is, same as above... one DLL loaded once... not one function loaded as many times as the web server needs to access it in a second.


Quote from: eville_hn on 2008.04.05, 00:52:02

Quote from: RobertM on 2008.04.04, 03:55:37
Thus to clarify, my point is: each method has enticing reasons why some would prefer them. I personally prefer jep's method as most of the coding I do is either (a) for web cgi (and his method is more compact, faster, and easier to code with) and/or (b) I like writing wrapper functions for various things to simplify calling stuff from anywhere - which I find far easier with functions set up all in one DLL and/or (c) as my web server gets quite a decent amount of traffic, I find that 20 or 50 or 100 lines of extra code does indeed impact performance, disk usage, etc (and I like minimizing disk usage as much as possible since SCSI disk drives are kinda expensive).

Well, if reducing disk accesses is your optimization goal, you should better use a RAM disk or prevent creating temporary files. This is also the big advantage of the gbmrx API design. All transformations on the bitmap can be sequentially done in memory without writing intermediate files.

Very true... but still faster using a DLL and things on RAM disk than repeatedly calling a function on RAM disk - also reduces memory footprint.

Quote from: eville_hn on 2008.04.05, 00:52:02

Quote from: RobertM on 2008.04.04, 03:55:37
For standalone apps that just need to query image parameters, having everything in REXX may be better, easier to implement, and would save memory since the code is only loaded with the app, then can be unloaded when the app exits (unlike my scenario, where the REXX DLL needs to be loaded at server start and NEVER unloaded).

The same mechanism also works with the externally located REXX function. In the attached example (runme_separate.cmd) the dll is loaded and only unloaded at the end of the program.


I hope the examples and the hints are helpful.  :)

eville


Basically, my intent was to say both methods are equally as valid - I hope you understood that part. And both of your works are outstanding and sure to help many. For web based stuff, I prefer DLLs since often, a single page will result in 50 calls to it.

-Robert


|
|
Kirk's 5 Year Mission Continues at:
Star Trek New Voyages
|
|