-
Notifications
You must be signed in to change notification settings - Fork 184
Reading and writing common image formats, ppm, tiff, jpeg, png #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
If we only do PPM, that can be easily done in pure Fortran. For almost all the other formats we would have to depend on a 3rd party library. It feels like supporting all the formats might be a better fit for a separate library from But since PPM can be supported easily in pure Fortran, it would allow codes to export and import images by using some external tool to convert to and from PPM first, which seems like it might be valuable enough to include in |
PPM is good enough for start! I agree on the advantage of pure Fortran implementation. We can adopt your implementations, they're good. I also have a P3 writer (same as P6, but ascii). |
Perfect, let's do it. Yes, we can support both ascii and binary PPM and a few related formats. |
What module would this belong to? I'm happy to prepare a PR with loadppm and saveppm implementations for P3 and P6 formats -- basically take your code and add P3 implementations. Other formats may be implemented later if desired. How should we handle choosing a format? For
We could also have a thin wrapper and specify it with the format argument: subroutine saveppm(filename, img, format)
...
if (format == 'P3') then
call saveppm_p3(filename, img)
else if (format == 'P6') then
call saveppm_p3(filename, img)
else
call error_stop()
end if
end subroutine saveppm |
Let's use Regarding the API, I agree with your choice. I would further make the P.S. Isn't |
I don't think Fortran has reserved words. I like the idea of P6 as default. |
For some applications I had in the past a graymap PPM (P2 or P5) would have sufficed. Specifically, I could use a ppm as a porosity map in a Lattice Boltzmann simulation. Since these only require a rank 2 array (i and j image coordinates) vs a rank 3 array (i, j, and rgb) it would be easy to support these too. |
FYI: pure Fortran gif (even animated) library here: https://github.com/jacobwilliams/FGIF |
@jacobwilliams this is great! It might not be that difficult to provide pure Fortran readers / writers to other image formats also. |
IMHO this is easily implemented as part of the ecosystem with iso_c_binding to currently existing libraries. There is no need complicating stuff by making competing solutions in stdlib (even for ppm). And one would need unsigned types to make it work in any decent way. |
Often there is a compelling case to write something in Fortran so that the community can contribute and fix it, but for certain cases, especially file formats, if there is a widely used existing library that stdlib can provide a Fortran interface for then that reduces complexity and reduces maintenance burden, while ensuring a higher quality of implementation. In this particular case we should be pragmatic and include implementations only where:
|
@gronki Can you list C library candidates? I know of stb and libpng. What do you have in mind? We should absolutely weigh-out the complexity of pure Fortran vs. C-interop implementations. In case of ppm, the pure Fortran implementation is so simple that I can't imagine a similar Fortran-C interface would be any simpler. I may be wrong though. Involving any external C library would add the complexity of a dependency. While I'm not against external dependencies in stdlib (Python has them), I think we should consider them as a last resort. |
But is reading and writing ppm's worth the burden of the maintenance? Don't get me wrong but it's not a serious image format. PPM is short for "i don't feel like googling libpng manual". I see no value of having a ppm implementation but maybe my opinion is isolated. I have never heard about stb before. I personally used libgdal, libpng and cfitsio in my field (from Fortran). All of them mature, stable and insanely easy to use by iso_c_binding (or even to wrap in a derived type). (edit: Actually, cfitsio has a f77 interface included.) I think it would be nice to have a stable and up-to-date bindings as a part of the ecosystem (whether they make it into stdlib or not) but I see absolutely no need to put any effort in implementing a worse version of what is already done. One a side note, I feel that not having certain bindings for popular format handling libraries is the actual problem we are trying to solve here. Fortran does have PNG or JPG handling. But it takes too much effort (one has to write their own binding rather than have a ready-to-use interface such as C or Python). |
@milancurcic Exactly how I feel. Well said.
This is very true. But in the case where an external library already does it---and does it well---and adding a roll-your-own implementation in the standard library adds unacceptable complexity, then I think a choice should be made about either:
Elon Musk recently said something like this when talking about SpaceX Starship:
Obviously we want convenience and utility in a standard library but it needs to be provided in a sustainable way. (And, yes, I know Musk is a bit mad, but he has some moments of wisdom/genius.) |
I agree! It seems to me that any format that would need compression like zlib would fall into one of these two categories. (if we need to include zlib as a dependency, this lowers the bar to entry to an external image library as a dependency as well). @gronki Let's focus on PNG and libpng -- do you have example interfaces that we can look at? Would you like to contribute them to stdlib? |
The idea of PPM is that they made the format simple enough so that anybody can easily read and write it from any language. Then you can use external tools to convert it to more common formats. The cost of any dependency should not be underestimated. For example, I would suggest to make such dependencies optional, at least initially. Not every (future) user of stdlib wants to use images, and having them require to install 10 libraries for the 10 image formats that we will support (but they don't need), that I think is not worth it. |
I would suggest to avoid non-optional dependencies as much as possible, except if there are installed on several OSes per default (or are very common and expected to be already installed). |
I also agree that we shouldn't re-implement rock solid libs written in other languages (I was also thinking of something like But, also keep in mind that this is a volunteer project. If somebody wants to spend their time writing the world's most amazing Fortran PPM interface, I have absolutely no objection to them doing that. :) |
Looks like we are all in agreement on the following:
Let me know if you all agree with the above, and if you think this will satisfy everybody. |
was designed as a simple self-contained vector library for PPM files for use in a graphics class. The Fortran-based GIF utilities mentioned previously worked great in conjunction with it for making simple GIF and animated GIF examples. PPM is very good (of course) for programs that are basically manipulating pixels; this could use some polish and needs a higher-level axis routine added, and prettier fonts but if anyone ones something in self-contained Fortran to start with feel free to take a look. In a batch environment the venerable NetPBM and ImageMagik filters worked seamlessly to convert the PPM files to just about any image file format around. With command-level packages like that the PPM format was basically just as good for single-image graphics files as any other, and easiest to convert to other formats. It is a bit verbose so it was almost always converted to something else on the spot. We actually let the programs write multiple images sequentially to a single file and then split them with a post-processor to make multi-plot formats like Adobe PDF. The main irritation with PPM files is they are only designed to represent one frame. It was designed to be compatible (Originally) with the VOGLE/M_graph library, which supports a lot of vector output formats but very little pixel-level graphics; so anyone that used VOGLE in the past |
The C GdkPixbuf library can save files in "jpeg", "png", "tiff", "ico" or "bmp": See my Discourse post for a Fortran example: |
I think Portable pixmaps would be valuable. I used a portable graymap (P2) in a recent Discourse thread. Now I doubt a Fortran-lang Netpbm module would ever be standardized, but it's just nice to have something light-weight you can drop in to a project, without having to install any libraries. Here is a very basic example, with the image given as an array of characters: !> Save as plain Portable GrayMap (use .pgm extension)
subroutine save_pgm(filename,icode,ngray)
character(len=*), intent(in) :: filename
character(1), intent(in) :: icode(:,:)
integer, intent(in) :: ngray
! number of gray values
integer :: i, j, unit
open(newunit=unit,file=filename,status='unknown')
! a description of the format is available at
! https://en.wikipedia.org/wiki/Netpbm
! header part
write(unit,'(A)') 'P2'
write(unit,'(I0,1X,I0)') size(icode,1), size(icode,2)
write(unit,'(I0)') ngray
! pixel data, gray values
do j = 1, size(icode,2)
write(unit,'(*(A1,:,1X))') (icode(i,j), i = 1, size(icode,1))
end do
close(unit)
end subroutine I would note that the "official" library for reading and writing Netpbm files is |
There's also stb_image. |
That's a nice find for C programmers. There is also PNM in C++ (similar single source file concept). But what we really want is something Fortran-friendly. Implementation issues aside, as has been said times and times before it's mainly about having a community-approved interface. Having a quick and simple way to export images can be very handy for developing and demonstrating PDE solvers. Here's an example in C++ where the authors included a BMP writer, directly in their single source file heat-equation solver: When I first learned Fortran, I wanted to read a gray image in BMP format as the initial conditions for a fluid simulation. All I could find where uncomplete snippets on comp.lang.fortran (https://groups.google.com/g/comp.lang.fortran/c/bvrvFLCT-uc/m/fU9jQTR8u8oJ). Implementing something from this like scratch was just not something I was capable of at the time. In Python or Matlab on the other hand it might have been as simple as |
I've started making bindings to stb and an image container for my own use. The project is still in a rough stage currently. Can currently save images as PNG, BMP, TGA and can read a bunch of formats. |
Yes, the ppm, pbm style is super nice, because it is text only, easy to write, easy to read. And you can use other software to convert to/from png or other formats. We definitely need this as part of stdlib. |
Here is an example implementation of loading and saving ppm: https://github.com/certik/fortran-utils/blob/b43bd24cd421509a5bc6d3b9c3eeae8ce856ed88/src/ppm.f90. The advantage of the ppm format is that it is simple to write such readers and writers. Then one can use external tools (such as
pnmtopng
) to convert to more common formats. So perhapstiff
,jpeg
andpng
are not initially needed andppm
might be enough to allow to work with images in Fortran.Prior art:
The text was updated successfully, but these errors were encountered: