[cl-gd-devel] Loading Images from Pointers
Hello. I have so far been using Lisp-Magick for two reasons: On the one hand, I didnt know that GD can stretch images, on the other hand, cl-gd doesnt support reading images from memory. Well, at least according to [1] there is a function which can do this in libgd, but seems like this isnt implemented in cl-gd yet. This is in fact the only thing keeping me from using CL-GD by now. I would like to use it instead of lisp-magick, since lisp-magick seems not to be well-maintained by now, and I already have to use a few of my personal patches to it. Anyway, I am not very familiar with uffi and stuff, I just tried to use cl-gd::def-function, but didnt really suffice. Is there any way of getting this function work with CL-GD? Regards Christoph Senjak [1] http://libgd.org/ImageCreation#gdImageCreateFromPngPtr.28int_size.2C_void_.2...
Hi Christoph, implementing an interface to gdImageCreateFrom.*Ptr shouldn't be hard, but I wonder where you'd get your pointers from? If you could supply some sample code and data, we may be able to help you out. -Hans On Wed, May 19, 2010 at 04:37, Christoph Senjak <christoph.senjak@googlemail.com> wrote:
Hello.
I have so far been using Lisp-Magick for two reasons: On the one hand, I didnt know that GD can stretch images, on the other hand, cl-gd doesnt support reading images from memory. Well, at least according to [1] there is a function which can do this in libgd, but seems like this isnt implemented in cl-gd yet. This is in fact the only thing keeping me from using CL-GD by now. I would like to use it instead of lisp-magick, since lisp-magick seems not to be well-maintained by now, and I already have to use a few of my personal patches to it. Anyway, I am not very familiar with uffi and stuff, I just tried to use cl-gd::def-function, but didnt really suffice.
Is there any way of getting this function work with CL-GD?
Regards Christoph Senjak
[1] http://libgd.org/ImageCreation#gdImageCreateFromPngPtr.28int_size.2C_void_.2...
_______________________________________________ cl-gd-devel site list cl-gd-devel@common-lisp.net http://common-lisp.net/mailman/listinfo/cl-gd-devel
2010/5/19 Hans Hübner <hans.huebner@gmail.com>:
Hi Christoph,
implementing an interface to gdImageCreateFrom.*Ptr shouldn't be hard, but I wonder where you'd get your pointers from? If you could supply some sample code and data, we may be able to help you out.
-Hans
Hello. I am loading the files into an array of (unsigned-byte 8): (defun si (var val) (setf (symbol-value (intern var)) val)) (defun init-file (file) "Load a file into a Variable. Access with |filename| (without .png and path)." (si (pathname-name file) (with-open-file (in file :element-type '(unsigned-byte 8)) (let* ((length (file-length in)) (content (make-array (list length) :element-type '(unsigned-byte 8) :adjustable nil))) (read-sequence content in) content)))) The reason I am doing this is that I dont like to have more external files than necessary, and want them in my core-dump. SDL can load these byte-arrays with (sdl-image:load-image x :image-type :PNG :alpha 1) what it actually does is (defmethod load-image ((source VECTOR) &key color-key alpha (image-type nil) (force nil) (free-rwops $ "Creates and returns a new surface from the image contained in the byte VECTOR in `SOURCE`." (declare (ignore free-rwops)) (load-image (sdl::create-RWops-from-byte-array source) :color-key color-key :color-key-at color-key-at :alpha alpha :image-type image-type :force force :free-rwops t)) where (defun create-RWops-from-byte-array (array) "Creates and returns a new `RWOPS` object from the Lisp array `ARRAY`." (let ((mem-array (cffi:foreign-alloc :unsigned-char :initial-contents array))) (make-instance 'rwops :fp (sdl-cffi::sdl-rw-from-mem mem-array (length array))))) which should be about the same lisp-magick does. Christoph
Hi Christoph, I now understand what you're trying to do. Here is my take on it: - Accessing a byte vector as C vector is compiler specific. A portable solution would allocate some memory using UFFI's interface to malloc, copy the data to that memory buffer using a lisp loop and memory accessor functions, call the required gdCreate* function and finally free the malloced buffer. - When you want to avoid the copying overhead (which in my opinion should only be done if you're dealing with a lot of data), you'll need to find out how you can pin the byte vector so that the garbage collector does not move it while you're in the FFI. Then, you'll need to find out how you can get a pointer to the byte vector in a format that is understood by UFFI. I would first go for the first option and see how that performs (i.e. if it produces a noticeable performance problem). The copies that you'll make are only temporary, so the memory footprint of your application will be roughly identical. GD will make its own private copy of the data anyway. Let us know if that helps. -Hans On Wed, May 19, 2010 at 12:28, Christoph Senjak <christoph.senjak@googlemail.com> wrote:
2010/5/19 Hans Hübner <hans.huebner@gmail.com>:
Hi Christoph,
implementing an interface to gdImageCreateFrom.*Ptr shouldn't be hard, but I wonder where you'd get your pointers from? If you could supply some sample code and data, we may be able to help you out.
-Hans
Hello.
I am loading the files into an array of (unsigned-byte 8):
(defun si (var val) (setf (symbol-value (intern var)) val)) (defun init-file (file) "Load a file into a Variable. Access with |filename| (without .png and path)." (si (pathname-name file) (with-open-file (in file :element-type '(unsigned-byte 8)) (let* ((length (file-length in)) (content (make-array (list length) :element-type '(unsigned-byte 8) :adjustable nil))) (read-sequence content in) content))))
The reason I am doing this is that I dont like to have more external files than necessary, and want them in my core-dump. SDL can load these byte-arrays with
(sdl-image:load-image x :image-type :PNG :alpha 1)
what it actually does is
(defmethod load-image ((source VECTOR) &key color-key alpha (image-type nil) (force nil) (free-rwops $ "Creates and returns a new surface from the image contained in the byte VECTOR in `SOURCE`." (declare (ignore free-rwops)) (load-image (sdl::create-RWops-from-byte-array source) :color-key color-key :color-key-at color-key-at :alpha alpha :image-type image-type :force force :free-rwops t)) where (defun create-RWops-from-byte-array (array) "Creates and returns a new `RWOPS` object from the Lisp array `ARRAY`." (let ((mem-array (cffi:foreign-alloc :unsigned-char :initial-contents array))) (make-instance 'rwops :fp (sdl-cffi::sdl-rw-from-mem mem-array (length array)))))
which should be about the same lisp-magick does.
Christoph
_______________________________________________ cl-gd-devel site list cl-gd-devel@common-lisp.net http://common-lisp.net/mailman/listinfo/cl-gd-devel
I now understand what you're trying to do. Here is my take on it:
- Accessing a byte vector as C vector is compiler specific. A portable solution would allocate some memory using UFFI's interface to malloc, copy the data to that memory buffer using a lisp loop and memory accessor functions, call the required gdCreate* function and finally free the malloced buffer.
cffi:foreign-alloc seems to have an argument :initial-contents, according to what lispbuilder-sdl does. So there should be no need to perform this loop by hand. The main problem I have now is that I get strange error messages about "unknown alien functions" when trying to use def-function (which I found in gd-uffi.lisp). The function is definitely there, but seems like uffi cannot find it or something (I am not familiar with uffi).
On Wed, May 19, 2010 at 4:18 PM, Christoph Senjak <christoph.senjak@googlemail.com> wrote:
The main problem I have now is that I get strange error messages about "unknown alien functions" when trying to use def-function (which I found in gd-uffi.lisp). The function is definitely there, but seems like uffi cannot find it or something (I am not familiar with uffi).
Have you made sure that the version of GD you are using is compatible with the GD docs you pointed to? I haven't looked at GD for quite some time, but judging from the URL in your initial email, current GD seems to use names which are different from the ones used in CL-GD, so if CL-GD works for you otherwise, you probably don't have the newest version of GD. Edi.
Hello.
Have you made sure that the version of GD you are using is compatible with the GD docs you pointed to? I haven't looked at GD for quite some time, but judging from the URL in your initial email, current GD seems to use names which are different from the ones used in CL-GD, so if CL-GD works for you otherwise, you probably don't have the newest version of GD.
CL-GD works (so far), but the page seems not to be up to date, I have the package libgd-xpm-dev from ubuntu, and /usr/include/gd.h contains the line #define GD_VERSION_STRING "2.0.36" which is, according to that site, a prerelease, which I cannot really believe since its in a stable ubuntu release. And it also contains the line BGD_DECLARE(gdImagePtr) gdImageCreateFromGifPtr (int size, void *data); But you are right ... cl-gd is not compatible (I should have done the tests on the same computer I did the other stuff): CL-USER> (cl-gd-test:TEST ) Test 1 failed with the following error: Attempt to call an undefined alien function. Test 2 failed with the following error: Attempt to call an undefined alien function. Test 3 failed with the following error: Attempt to call an undefined alien function. (...) So ... well ... how hard would it be to make it compatible with the new version? Is it just changing a few naming-strings, or more complicated? I have lisp-magick working now, its just not very well maintained, but if cl-gd is outdated, then maybe I will write my own FFI-Binding for GD directly, or keep working with a patched version of lisp-magick (or do the image-processing in CL directly). Regards, Christoph
Christoph, can you please post some code that would allow me to try to reproduce and diagnose the problem in isolation? Make it a single lisp file that assumes cl-gd being loaded, attach it to the message that you send. Thanks. Hans On Wed, May 19, 2010 at 16:18, Christoph Senjak <christoph.senjak@googlemail.com> wrote:
I now understand what you're trying to do. Here is my take on it:
- Accessing a byte vector as C vector is compiler specific. A portable solution would allocate some memory using UFFI's interface to malloc, copy the data to that memory buffer using a lisp loop and memory accessor functions, call the required gdCreate* function and finally free the malloced buffer.
cffi:foreign-alloc seems to have an argument :initial-contents, according to what lispbuilder-sdl does. So there should be no need to perform this loop by hand.
The main problem I have now is that I get strange error messages about "unknown alien functions" when trying to use def-function (which I found in gd-uffi.lisp). The function is definitely there, but seems like uffi cannot find it or something (I am not familiar with uffi).
_______________________________________________ cl-gd-devel site list cl-gd-devel@common-lisp.net http://common-lisp.net/mailman/listinfo/cl-gd-devel
participants (3)
-
Christoph Senjak -
Edi Weitz -
Hans Hübner