I want to write a program that controls the Linux command "mogrify"
in a search loop so that I get photos reduced to a certain size for a
home page. As it is, whether I use % reduction of specify the size in
pixels, the final size in Mb varies quite a bit, apparently at random,
from one photo to the next.
A program that calls the command, then the directory command into a
pipe, and reads the size, in a loop, would make sure that I get the
size I want.
I know (at least I believe) that invoking system commands is not
standard Fortran but can it be done? I work under Suse Linux 12.1
and have Intel Fortran 90/95 installed. The Fortran part would be easy,
it's only the system commands that I don't know how to do.
> I know (at least I believe) that invoking system commands is not
> standard Fortran but can it be done? I work under Suse Linux 12.1
> and have Intel Fortran 90/95 installed. The Fortran part would be easy,
> it's only the system commands that I don't know how to do.
Intel Fortran has three library routines that can do this - there are minor differences among them, so look at the documentation to see which is most appropriate for you: SYSTEM, SYSTEMQQ, RUNQQ. For best results, add USE IFPORT to the procedure calling these.
Fortran 2008 defines an intrinsic EXECUTE_COMMAND_LINE. Intel Fortran does not yet support this.
-- Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH
Dieter Britz <dieterhansbr...@gmail.com> wrote:
> I want to write a program that controls the Linux command "mogrify"
> in a search loop so that I get photos reduced to a certain size for a
> home page. As it is, whether I use % reduction of specify the size in
> pixels, the final size in Mb varies quite a bit, apparently at random,
> from one photo to the next.
The size of JPEG files can vary a lot, depending on the detail
needed to represent it, and, usually, on a parameter telling
how hard it should (lossy) compress.
> A program that calls the command, then the directory command into a
> pipe, and reads the size, in a loop, would make sure that I get the
> size I want.
Executing the command is usually not so hard. Reading a pipe
from Fortran, though, isn't so easy. On some, you can use
INQUIRE to get a file size, though. You could also redirect
directory listing output to a file, and then read the file.
> I know (at least I believe) that invoking system commands is not
> standard Fortran but can it be done? I work under Suse Linux 12.1
> and have Intel Fortran 90/95 installed. The Fortran part would be easy,
> it's only the system commands that I don't know how to do.
Most linux systems supply the C popen() and pclose() functions.
I believe that they are not supposed to be supported by C
interoperability, but you might be able to use them. It would,
though, be easier to do in C if that was the goal.
> I want to write a program that controls the Linux command "mogrify"
> in a search loop so that I get photos reduced to a certain size for a
> home page. As it is, whether I use % reduction of specify the size in
> pixels, the final size in Mb varies quite a bit, apparently at random,
> from one photo to the next.
> A program that calls the command, then the directory command into a
> pipe, and reads the size, in a loop, would make sure that I get the
> size I want.
> I know (at least I believe) that invoking system commands is not
> standard Fortran but can it be done? I work under Suse Linux 12.1
> and have Intel Fortran 90/95 installed. The Fortran part would be easy,
> it's only the system commands that I don't know how to do.
All Linux Fortran compilers (as back as g77) support the Fortran System Calls that used to be known as 3f from the appendix in the Unix manual. G95 and gfortran give access to them in the form of intrinsic, while Intel requires the USE of ifport module (that provides the interface).
If what you want to use is not provided as intrinsic (or by the module) you could write either a C wrap (requires essentially only an underscore ) or use the iso binding to C provided by the newer Fortran standards.
Essentially, you can do anything in the dynamic area by having one program
construct command code of the executing O/S, to be executed as a 'daughter
program' (if this is the easiest way to solve the problem), or else produce
some form of output to control a second program to executed the task. After
whch the parent program is handed back control to decide what to do next.
I have a long-time habit of writing most general-purpose programs, so that
they generate and output decision tables, constucted from the user's input
instructions (spoken or typed) to be used by a second-level program that
accomplishes the needed task.
As I've noted before, this is how a CPU operates: it uses microcoded tables
to actually manipulate the current contents of registers in executing a
'machine code' instruction.
Dieter Britz <dieterhansbr...@gmail.com> wrote:
> I want to write a program that controls the Linux command "mogrify"
> in a search loop so that I get photos reduced to a certain size for a
> home page. As it is, whether I use % reduction of specify the size in
> pixels, the final size in Mb varies quite a bit, apparently at random,
> from one photo to the next.
> A program that calls the command, then the directory command into a
> pipe, and reads the size, in a loop, would make sure that I get the
> size I want.
> I know (at least I believe) that invoking system commands is not
> standard Fortran but can it be done? I work under Suse Linux 12.1
> and have Intel Fortran 90/95 installed. The Fortran part would be easy,
> it's only the system commands that I don't know how to do.
Dieter,
I'm guessing that the error is in your understanding. I tried it and
there was nothing approximate about it.
My picture that I tested it on came from Wikipedia:
Dieter Britz <dieterhansbr...@gmail.com> wrote:
> I want to write a program that controls the Linux command "mogrify"
> in a search loop so that I get photos reduced to a certain size for a
> home page. As it is, whether I use % reduction of specify the size in
> pixels, the final size in Mb varies quite a bit, apparently at random,
> from one photo to the next.
> A program that calls the command, then the directory command into a
> pipe, and reads the size, in a loop, would make sure that I get the
> size I want.
> I know (at least I believe) that invoking system commands is not
> standard Fortran but can it be done? I work under Suse Linux 12.1
> and have Intel Fortran 90/95 installed. The Fortran part would be easy,
> it's only the system commands that I don't know how to do.
Dieter,
I read your post more carefully, and I see something. Perhaps *I*
misunderstood. It seems you are trying for a target size not in pixel
width and height, but in Mb. Yes?
Are your pictures compressed? Jpeg (and some other formats) is a
compressed format. You can choose your compression. In mogrify I
think it is called "-quality".
For a webpage isn't the size of the picture in pixels more important
than the number of Megabytes that comprise it?
On Mon, 13 Aug 2012 12:06:39 -0400, Steve Lionel wrote:
> On 8/13/2012 11:43 AM, Dieter Britz wrote:
>> I know (at least I believe) that invoking system commands is not
>> standard Fortran but can it be done? I work under Suse Linux 12.1 and
>> have Intel Fortran 90/95 installed. The Fortran part would be easy,
>> it's only the system commands that I don't know how to do.
> Intel Fortran has three library routines that can do this - there are
> minor differences among them, so look at the documentation to see which
> is most appropriate for you: SYSTEM, SYSTEMQQ, RUNQQ. For best results,
> add USE IFPORT to the procedure calling these.
> Fortran 2008 defines an intrinsic EXECUTE_COMMAND_LINE. Intel Fortran
> does not yet support this.
I have now tried this, and struck some strange problems. Here is
the little program, which I will expand to do the job:
program MOG
use IFPORT
! implicit none
character(len=80) :: SYSTEMQQ
character(len=80) :: lsline, inputfile, command
integer :: size
src/mog.f90(4): error #6401: The attributes of this name conflict with those made accessible by a USE statement. [SYSTEMQQ]
character(len=80) :: SYSTEMQQ
-----------------------^
src/mog.f90(12): error #6054: A CHARACTER data type is required in this context. [SYSTEMQQ]
lsline = SYSTEMQQ (command)
-----------^
compilation aborted for src/mog.f90 (code 1)
When I deactivate the declaration of SYSTEMQQ and activate the
commented lines using liline, it works, strangely enough. This
was an accident, me typing "liline" instead of the intended
"lsline"
So, how do I use this? I declare the output line lsline as
character(len=80), and I assume SYSTEMQQ must be type character
as well, but what length? The manual on SYSTEMQQ doesn't tell
me how I should declare it in the example.
In some versions of my attempts, I get a message like
sh: $'\001': command not found
(e.g. when I cpomment out the USE statement).
What does this mean? I run the thing with the shell script,
> On Mon, 13 Aug 2012 12:06:39 -0400, Steve Lionel wrote:
>> On 8/13/2012 11:43 AM, Dieter Britz wrote:
>>> I know (at least I believe) that invoking system commands is not
>>> standard Fortran but can it be done? I work under Suse Linux 12.1 and
>>> have Intel Fortran 90/95 installed. The Fortran part would be easy,
>>> it's only the system commands that I don't know how to do.
>> Intel Fortran has three library routines that can do this - there are
>> minor differences among them, so look at the documentation to see which
>> is most appropriate for you: SYSTEM, SYSTEMQQ, RUNQQ. For best results,
>> add USE IFPORT to the procedure calling these.
>> Fortran 2008 defines an intrinsic EXECUTE_COMMAND_LINE. Intel Fortran
>> does not yet support this.
> I have now tried this, and struck some strange problems. Here is
> the little program, which I will expand to do the job:
> src/mog.f90(4): error #6401: The attributes of this name conflict with
> those made accessible by a USE statement. [SYSTEMQQ]
> character(len=80) :: SYSTEMQQ
> -----------------------^
> src/mog.f90(12): error #6054: A CHARACTER data type is required in this
> context. [SYSTEMQQ]
> lsline = SYSTEMQQ (command)
> -----------^
> compilation aborted for src/mog.f90 (code 1)
> When I deactivate the declaration of SYSTEMQQ and activate the
> commented lines using liline, it works, strangely enough. This
> was an accident, me typing "liline" instead of the intended
> "lsline"
> So, how do I use this? I declare the output line lsline as
> character(len=80), and I assume SYSTEMQQ must be type character
> as well, but what length? The manual on SYSTEMQQ doesn't tell
> me how I should declare it in the example.
> In some versions of my attempts, I get a message like
> sh: $'\001': command not found
> (e.g. when I cpomment out the USE statement).
> What does this mean? I run the thing with the shell script,
> On Mon, 13 Aug 2012 12:06:39 -0400, Steve Lionel wrote:
...
>> Intel Fortran has three library routines that can do this - there are
>> minor differences among them, so look at the documentation to see which
>> is most appropriate for you: SYSTEM, SYSTEMQQ, RUNQQ. For best results,
>> add USE IFPORT to the procedure calling these.
...
> I have now tried this, and struck some strange problems. Here is
> the little program, which I will expand to do the job:
> program MOG
> use IFPORT
> ! implicit none
> character(len=80) :: SYSTEMQQ
...
> So, how do I use this? I declare the output line lsline as
> character(len=80), and I assume SYSTEMQQ must be type character
> as well, but what length? The manual on SYSTEMQQ doesn't tell
> me how I should declare it in the example.
...
Well, that's not exactly true; from the CVF manual (which I presume Intel follows pretty doggone closely :) ) --
> SYSTEMQQ
> Run-Time Function: Executes a system command by passing a command string to the operating system's command interpreter.
> Module: USE DFLIB
> Syntax
> result = SYSTEMQQ (commandline)
> commandline
> (Input) Character*(*). Command to be passed to the operating system.
> Results:
> The result is of type LOGICAL(4). The result is .TRUE. if successful; otherwise, .FALSE..
program MOG
use IFPORT
implicit none
! trash this; the USE takes care of the declarations needed for the
!function --character(len=80) :: SYSTEMQQ
character(len=80) :: inputfile, command
integer :: size
! add the following per the documentation--SYSTEMQQ returns a flag
logical :: result
Now, unfortunately, SYSTEMQQ will _NOT_ return the results of the system command passed to the shell; you'll have to use redirection of the output to a file and parse the file or some other ruse.
I don't know what they distribute on Linux platform; on Windows there is a set of modules that have pre-built interfaces to a large portion of the system API. I'd suggest looking there and see about calling them directly instead since your into system-dependent stuff anyway.
Jan Gerrit Kootstra <jan.ger...@kootstra.org.uk> wrote:
> Op 03-09-12 17:27, Dieter Britz schreef:
> > src/mog.f90(4): error #6401: The attributes of this name conflict with
> > those made accessible by a USE statement. [SYSTEMQQ]
> > character(len=80) :: SYSTEMQQ
> A function should not be declared as a "variable".
> That is where you go wrong.
Well.... no.
First off, he did not declare it as a variable. In fact, there isn't an
explicit way to do any such thing as declare something to be a variable.
This is occasionally a source of confusions. The closest thing to
declaring something as a variable is declaring it to have attributes
that only a variable can have. There are several such attributes, but
this example did *NOT* illustrate any of those.
In particular, the declaration
character(len=80) :: SYSTEMQQ
does not declare systemqq to be a variable. It declares it to have type
character and a length type parameter of 80. That's all. There are
things other than variables that can have those properties. At least 2
off the top of my head, and I suppose I might have forgotten something
else. With no information other than just that line, it could still be a
parameter or a function.
It is possible that you aren't used to pre-f90 style function usage.
Before f90, not only was it allowed to declare the type of your
functions in any scope that used them, it was required unless you relied
on implicit typing. As of f90, some people (myself included) moved more
towards putting procedures in modules in most cases, and using interface
bodies in most of the rest, so I don't much use the pre-f90 style
function declarations any more, but they are still perfectly fine
(except for functions that require explicit interfaces for some reason).
In short, the function declaration that Dieter showed was a perfectly
fine function declaration; that was not where he went wrong. The
above-quoted error message tells a different story. While I haven't used
systemqq myself, I'd lay (very high) odds that it is declared in the
IFPORT module that Dieter used. Trying to redeclare something that is
declared in a module that you use is not legal and is much more the
direction to look for his problem.
-- Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
> Jan Gerrit Kootstra<jan.ger...@kootstra.org.uk> wrote:
>> Op 03-09-12 17:27, Dieter Britz schreef:
>>> src/mog.f90(4): error #6401: The attributes of this name conflict with
>>> those made accessible by a USE statement. [SYSTEMQQ]
>>> character(len=80) :: SYSTEMQQ
>> A function should not be declared as a "variable".
>> That is where you go wrong.
> Well.... no.
> First off, he did not declare it as a variable. In fact, there isn't an
> explicit way to do any such thing as declare something to be a variable.
> This is occasionally a source of confusions. The closest thing to
> declaring something as a variable is declaring it to have attributes
> that only a variable can have. There are several such attributes, but
> this example did *NOT* illustrate any of those.
> In particular, the declaration
> character(len=80) :: SYSTEMQQ
> does not declare systemqq to be a variable. It declares it to have type
> character and a length type parameter of 80. That's all. There are
> things other than variables that can have those properties. At least 2
> off the top of my head, and I suppose I might have forgotten something
> else. With no information other than just that line, it could still be a
> parameter or a function.
> It is possible that you aren't used to pre-f90 style function usage.
> Before f90, not only was it allowed to declare the type of your
> functions in any scope that used them, it was required unless you relied
> on implicit typing. As of f90, some people (myself included) moved more
> towards putting procedures in modules in most cases, and using interface
> bodies in most of the rest, so I don't much use the pre-f90 style
> function declarations any more, but they are still perfectly fine
> (except for functions that require explicit interfaces for some reason).
> In short, the function declaration that Dieter showed was a perfectly
> fine function declaration; that was not where he went wrong. The
> above-quoted error message tells a different story. While I haven't used
> systemqq myself, I'd lay (very high) odds that it is declared in the
> IFPORT module that Dieter used. Trying to redeclare something that is
> declared in a module that you use is not legal and is much more the
> direction to look for his problem.
Richard,
I come from f77.
Whether or not it is in a module, I am use to declare the function's type in the function declaration line, not in the variable/parameter block.
suggests SYSTEMQQ to be a function of type logical*4
so this is where Dieter may have gone wrong. The redeclaration as you refer to.
I never learned anything about the f90+ style of programming, I only us module for it was shown to me by my PhD studies in CFD tutor but due to work in a complete other field never had the time to learn at the in and outs of f90 programming.
Jan Gerrit Kootstra <jan.ger...@kootstra.org.uk> wrote:
> I come from f77.
> Whether or not it is in a module, I am use to declare the function's > type in the function declaration line, not in the variable/parameter block.
You have to do it in the function statement and *ALSO* in whatever scope
uses it. That was the only option (other than implicit typing) in f77.
The routine that uses it doesn't get to "see" the function statement.
That is the essense of separate compilation, which f77 was designed
around.
If you aren't familliar with this (though I find it a little hard to
imagine doing much f77 code without already having run into it),
I suggest trying the following f77 (except for the lower case - I just
can't bring myself to type in all caps) code.
program p
x = 1.0
write (*,*) f(x)
end
character*80 function f(x)
f = 'hello world.'
end
I just tried it in gfortran. I got an output of 0.0000000, followed
by a segmentation fault. Any guess why? (That's a rhetorical question; I
know why).
If I make the "obvious" addition, it prints the expected output and
terminates normally.
By the way, there is no such concept in the language as a
"variable/parameter block". There is the specification part (I think
that's the term, but no tim to check it at the moment), and then there
is the execution part. Almost all explicit specifications go into the
specification part. Yes, that includes dclarations of function types.
> suggests SYSTEMQQ to be a function of type logical*4
Ah. So that was another problem.
> so this is where Dieter may have gone wrong. The redeclaration as you
> refer to.
Still no. Declaring it *AT ALL* in his subroutine is a redeclaration,
and thus is illegal. Apparently he also got the type incorrect, but
that's a separate error. Even if he got the type correct, it is illegal
to declare it twice, which his code essentially did - once in the used
module and once in his source code.
It isn't exactly the same thing because of the module involvement, but
try adding the declaration
character*80 f
in th emain program of the above f77 code. And add it twice; yes
duplicate the line. Adding it once makes the code run correctly. Adding
it twice gives me the compilation error message
character*80 f
1
Error: Symbol 'f' at (1) already has basic type of CHARACTER
That's about as close as I can get in f77 to the same kind of error.
Note that there is nothing wrong with the declarations of f - just that
there are 2 of them.
-- Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
>> does not declare systemqq to be a variable. It declares it to have type
>> character and a length type parameter of 80. That's all. ...
>> It is possible that you aren't used to pre-f90 style function usage.
>> Before f90, not only was it allowed to declare the type of your
>> functions in any scope that used them, it was required unless you relied
>> on implicit typing. As of f90, some people (myself included) moved more
>> towards putting procedures in modules in most cases, and using interface
>> bodies in most of the rest, so I don't much use the pre-f90 style
>> function declarations any more, but they are still perfectly fine
>> (except for functions that require explicit interfaces for some reason).
>> In short, the function declaration that Dieter showed was a perfectly
>> fine function declaration; that was not where he went wrong. ...
...
> I come from f77.
> Whether or not it is in a module, I am use to declare the function's
> type in the function declaration line, not in the variable/parameter block.
...
That still only declares the type for the declaration of the function itself--it would still be missing the declaration in the calling/referencing procedure (or main program in this case). If the function is not consistent with implicit typing (as also is true in this case) then there will be a mismatch between the function as declared and the calling routine's view of it (again, w/o modules or an explicit interface otherwise supplied).
So, as Richard points out, F77 or no, declaring the function type somewhere else other than in the definition line of the function is still needed (and _especially_ in F77 as there is no other way).
> suggests SYSTEMQQ to be a function of type logical*4
Yes, see my other followup to OP...and it also doesn't do what OP was hoping for it to do... :(
On Sat, 18 Aug 2012 05:36:35 +0000, Joe Rosevear wrote:
> Dieter Britz <dieterhansbr...@gmail.com> wrote:
>> I want to write a program that controls the Linux command "mogrify"
>> in a search loop so that I get photos reduced to a certain size for a
>> home page. As it is, whether I use % reduction of specify the size in
>> pixels, the final size in Mb varies quite a bit, apparently at random,
>> from one photo to the next.
>> A program that calls the command, then the directory command into a
>> pipe, and reads the size, in a loop, would make sure that I get the
>> size I want.
>> I know (at least I believe) that invoking system commands is not
>> standard Fortran but can it be done? I work under Suse Linux 12.1 and
>> have Intel Fortran 90/95 installed. The Fortran part would be easy,
>> it's only the system commands that I don't know how to do.
> Dieter,
> I read your post more carefully, and I see something. Perhaps *I*
> misunderstood. It seems you are trying for a target size not in pixel
> width and height, but in Mb. Yes?
> Are your pictures compressed? Jpeg (and some other formats) is a
> compressed format. You can choose your compression. In mogrify I think
> it is called "-quality".
> For a webpage isn't the size of the picture in pixels more important
> than the number of Megabytes that comprise it?
> I'm not getting it.
> -Joe
You are no doubt right, but I want the picture to appear on
people's screen reasonably fast, and I decided that files of
about 400 kb are a good compromise between this and picture
quality. Hence my plan for this program.
On Mon, 13 Aug 2012 15:43:57 +0000, Dieter Britz wrote:
> I want to write a program that controls the Linux command "mogrify"
> in a search loop so that I get photos reduced to a certain size for a
> home page. As it is, whether I use % reduction of specify the size in
> pixels, the final size in Mb varies quite a bit, apparently at random,
> from one photo to the next.
[...]
I now got this going, thanks to a few suggestions from this ng. The
program is now
program MOG
use IFPORT
implicit none
character(len=80) :: inputfile, command, line
logical :: com
integer :: L, size
print '(" File name?")'
read (*,'(a)') inputfile
L = LEN_TRIM (inputfile)
command = "ls -s " // inputfile(1:L) // " > pipe"
print '(a)', "Command = " // command
com = SYSTEMQQ (command)
print '(" Reading from the pipe:")'
OPEN (1, file="pipe", status="old")
read (1,'(a)') line
print '(a)', line
read (line,*) size
print '(" Size in blocks:", i6)', size
CLOSE (1)
command = "rm pipe"
com = SYSTEMQQ(command)
end program MOG
There is a file called pic.jpg, 34475 in size, and I get this
output:
File name?
Command = ls -s pic.jpg > pipe Reading from the pipe:
36 pic.jpg Size in blocks: 36
So now I can build this into the binary search for a file of
a wanted length. Interesting, a change form my normal Fortran
programming.