DavidMStraub / Pillow-PGF

A Pillow Plugin to load PGF files
0 stars 0 forks source link

Implementation of decoder #1

Open DavidMStraub opened 3 years ago

DavidMStraub commented 3 years ago

Continuation of the discussion at https://sourceforge.net/p/libpgf/feature-requests/4/.

kauai68 commented 3 years ago

Hi David. My GitHub user name is kauai68. In meantime I wrote a C wrapper for the C++ library libpgf.

DavidMStraub commented 3 years ago

Great! I added you to the repo.

kauai68 commented 3 years ago

Thanks. It works well. Could you please delete the ".vs" folder. It pushed accidently because I forgot to update gitignore.

DavidMStraub commented 3 years ago

Thanks! I am now trying to understand how to marry the C extension with the Python plugin module. My first issue is that I don't manage to compile pgf_decode.c.

I get:

pillow_pgf/pgf_decode.c:49:22: error: unknown type name ‘Imaging’

If I add #include "Imaging.h", I get

pillow_pgf/pgf_decode.c:52:37: error: expected ‘)’ before ‘-’ token
DavidMStraub commented 3 years ago

@kauai68 thanks for the updated code. I still cannot compile it, I feel like I am missing something obvious. What I am trying to do is to get

python3 setup.py build

to work. At the moment, it throws, among other things


pillow_pgf/pgf_decode.c:52:37: error: expected ‘)’ before ‘->’ token
   52 |  struct CPGFFileStream *stream(state->fd); // needs Wrapper.lib
      |                                     ^~
      |                                     )
pillow_pgf/pgf_decode.c:57:2: error: ‘try’ undeclared (first use in this function)
   57 |  try {
      |  ^~~
``
DavidMStraub commented 3 years ago

I added a Github workflow now which executes this build command, so we can check after every commit if/why it is failing, see e.g. here: https://github.com/DavidMStraub/Pillow-PGF/runs/1778396969

kauai68 commented 3 years ago

Sorry, it took a bit longer, because my SSD crashed and I had to copy all data to another computer. I've updated setup.py. It includes a path to the source code of Pillow. I've added a small library project to build pgf_decode.c and fixed the bugs in the c code. I'm still unsure if we need a C version of libpgf or if we just can use the C++ version.

You might need to modify the parameters of the Extension:

The next step would be to glue the python part with the C part. I don't really understand where I should store the read raw image bytes (= destination buffer) and where I can get the needed number of bytes of an image row (= stride) in the destination buffer.

DavidMStraub commented 3 years ago

Oh, that sounds bad :boom:

I still can't compile because I'm missing clibpgf, could you provide me with an instruction "for dummies" how to link it properly? :hand_over_mouth:

Concerning the inputs/outputs: my idea was to actually not use a pure C plugin, but to wrap the C functions into a Python plugin. The PGFImageFile._open method in __init__.py processes the header and sets the tile property. It's last compent, called args, can be chosen to be anything the decoder needs; I put in the header content, but it could also contain the stride, for instance. These arguments are then used as function arguments to the pgf_decode.decode function, which is defined in pgf_decode.c (its Python signature is (buffer, *args)).

I think part of the mismatch in the current code is that I was following "Writing Your Own File Decoder in Python" in the Pillow docs and thought of calling a C function in the (Python) decoder method, while you were following "Writing Your Own File Decoder in C". If it's possible to do it entirely in C that's of course great, but I didn't undertand how to register the plugin etc. and how to build when having this as a standalone package (rather than as part of Pillow itself).

kauai68 commented 3 years ago

Ok, let's do it in your way. I've modified setup.py so it creates a C wrapper for the already existing libpgf.lib (you need to copy your linux library of libpgf.lib to the folder libpgf).

Then in decoder.py you need to import the built extension libpgf (I renamed pgf_decode to libpgf). At the moment it doesn't work.

In decode() in libpgf.c I will decode a PGF image. In args I need the following information:

kauai68 commented 3 years ago

Since we are working on different platforms a local file called localsettings would be useful. It should include several local information needed in setup.py.

DavidMStraub commented 3 years ago

OK!

Concerning the platform-dependent stuff, I would just do it directly in setup.py:

import sys

if sys.platform == "win32":
    # ...

Even for Pillow itself they do it like this.

kauai68 commented 3 years ago

OK, that's perfect for me. -------- Ursprüngliche Nachricht --------Von: David Straub notifications@github.comDatum: So., 7. Feb. 2021, 18:08An: DavidMStraub/Pillow-PGF Pillow-PGF@noreply.github.comCc: kauai68 stamm@xeraina.ch, Mention mention@noreply.github.comBetreff: Re: [DavidMStraub/Pillow-PGF] Implementation of decoder (#1) OK! Concerning the platform-dependent stuff, I would just do it directly in setup.py: import sys

if sys.platform == "win32":

...

Even for Pillow itself they do it like this.

—You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub, or unsubscribe.

kauai68 commented 3 years ago

A short update:

DavidMStraub commented 3 years ago

Cool, that's great progress! I'll take a look tomorrow and see if I can get any further.

kauai68 commented 3 years ago

Ok, I've found the line where the C decoder is called in Python: On line 242 in ImageFile.py.

status, err_code = decoder.decode(b"")

Now I see that an exception is thrown because my decoder tries to write at address 1.

The problem with the access violation is solved and now a black image is returned, means I write my image data to the wrong buffer.

kauai68 commented 3 years ago

Bingo! I can read a PGF image in RGB mode and show it and save it as BMP! The first version of the plugin is working! The next few days I will spend in the mountains for skiing. When I come back I will finish the decoder for a few other image modes.

DavidMStraub commented 3 years ago

Great! Can you please push your code, so I can improve the Python part, add unit tests etc.?

Enjoy skiing!

kauai68 commented 3 years ago

Should I copy the whole Pillow project tree with all my modifications to this folder or only the modified and added files?

DavidMStraub commented 3 years ago

Not sure I understand, did you actually implement it by modifying the Pillow source code itself rather than using the code in this repository? In that case I would suggest to create a fork of Pillow and upload your changes there. Then we can see whether it's possible to abstract this into a standalone package or whether it makes more sense to make a pull request to Pillow directly.

kauai68 commented 3 years ago

Yes, I implement it by modifying the Pillow source code itself. I've created a branch pillow-clone and copied the whole Pillow source to the folder Pillow

DavidMStraub commented 3 years ago

Sorry, I'm confused because it's really hard to see from you branch what you actually changed. Are you only using what's inside the Pillow directory and you copied everything there?

kauai68 commented 3 years ago

Ok, I try to clarify my changes:

  1. Pillow/winbuild/build_prepare.py: added block libpgf to download and build PGF library source code from sourceforge. In future it needs some modifications because we need a C library of PGF instead of the provided C++ library
  2. manual step: build C library of PGF using the built C++ library and the source code in clibpgf (outside of the Pillow folder); this step is already programmed in your setup.py as the extension step
  3. Pillow/setup.py: lines 95, 96, 278, 705-709, 746-748, 829
  4. Pillow/src/decode.c: 925-961 (it contains the interface between python and C, python args are parsed and C objects initialized)
  5. Pillow/src/libImaging/PgfDecode.c and Pgf.h: PGF decoder (calls functions in clibpgf)
  6. Pillow/src/PIL/PgfImagePlugin.py: python part of the PGF decoder plugin (similar to your python code you have written first)
  7. Pillow/src/PIL/init.py: line 117
  8. Pillow/src/_imaging.c: lines 3909-3910, 3935-3936, 4022-4024, 4145-4151
  9. Pillow/Tests/test_file_pgf.py

Please let me know if something is missing.