1// Copyright 2011 Google Inc.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the COPYING file in the root of the source
5// tree. An additional intellectual property rights grant can be found
6// in the file PATENTS. All contributing project authors may
7// be found in the AUTHORS file in the root of the source tree.
8// -----------------------------------------------------------------------------
9//
10// libwebp swig interface definition
11//
12// Author: James Zern (jzern@google.com)
13
14/*
15  Go bindings:
16  $ swig -go \
17         -outdir . \
18         -o libwebp_go_wrap.c libwebp.swig
19
20  Java bindings:
21  $ mkdir -p java/com/google/webp
22  $ swig -java \
23         -package com.google.webp \
24         -outdir java/com/google/webp \
25         -o libwebp_java_wrap.c libwebp.swig
26
27  Python bindings:
28  $ swig -python \
29         -outdir . \
30         -o libwebp_python_wrap.c libwebp.swig
31*/
32
33#ifdef SWIGPYTHON
34%module(package="com.google.webp") libwebp
35#else
36%module libwebp
37#endif  /* SWIGPYTHON */
38
39%include "constraints.i"
40%include "typemaps.i"
41
42#ifdef SWIGGO
43%apply (char* STRING, size_t LENGTH) { (const uint8_t* data, size_t data_size) }
44
45%rename(wrapped_WebPGetInfo) WebPGetInfo(const uint8_t* data, size_t data_size,
46                                         int* width, int* height);
47#endif  /* SWIGGO */
48
49#ifdef SWIGJAVA
50%include "arrays_java.i";
51%include "enums.swg" /*NB: requires JDK-1.5+
52                       See: http://www.swig.org/Doc1.3/Java.html#enumerations */
53
54// map uint8_t* such that a byte[] is used
55%{
56#include "webp/types.h"
57%}
58// from arrays_java.i (signed char)
59JAVA_ARRAYS_DECL(uint8_t, jbyte, Byte, Uint8)
60JAVA_ARRAYS_IMPL(uint8_t, jbyte, Byte, Uint8)
61JAVA_ARRAYS_TYPEMAPS(uint8_t, byte, jbyte, Uint8, "[B")
62%apply uint8_t[] { uint8_t* }
63#endif  /* SWIGJAVA */
64
65#ifdef SWIGPYTHON
66%apply (char* STRING, size_t LENGTH) { (const uint8_t* data, size_t data_size) }
67%typemap(out) uint8_t* {
68  $result = PyString_FromStringAndSize(
69      (const char*)$1,
70      ($1 == NULL) ? 0 : ReturnedBufferSize("$symname", arg3, arg4));
71}
72
73%typemap (in) const uint8_t* rgb (Py_buffer rgb_buffer) {
74  // NB: with Python < 2.6 the old style buffer protocol may be used:
75  // Py_ssize_t unused;
76  // PyObject_AsReadBuffer($input, (const void**)(&$1), &unused);
77  if (!PyObject_CheckBuffer($input)) {
78    SWIG_exception_fail(SWIG_TypeError,
79                        "in method '$symname', argument $argnum"
80                        " does not support the buffer interface");
81  }
82  if (PyObject_GetBuffer($input, &rgb_buffer, PyBUF_SIMPLE)) {
83    SWIG_exception_fail(SWIG_RuntimeError,
84                        "in method '$symname', unable to get buffer view");
85  }
86  $1 = ($1_ltype)rgb_buffer.buf;
87}
88
89%typemap(freearg) const uint8_t* rgb {
90  PyBuffer_Release(&rgb_buffer$argnum);
91}
92
93%define DECODE_AUTODOC(func)
94%feature("autodoc", #func "(uint8_t data) -> (rgb, width, height)") func;
95%enddef
96
97%feature("autodoc", "1");
98DECODE_AUTODOC(WebPDecodeRGB);
99DECODE_AUTODOC(WebPDecodeRGBA);
100DECODE_AUTODOC(WebPDecodeARGB);
101DECODE_AUTODOC(WebPDecodeBGR);
102DECODE_AUTODOC(WebPDecodeBGRA);
103%feature("autodoc", "WebPGetInfo(uint8_t data) -> (width, height)") WebPGetInfo;
104#endif  /* SWIGPYTHON */
105
106//------------------------------------------------------------------------------
107// Decoder specific
108
109%apply int* OUTPUT { int* width, int* height }
110
111int WebPGetDecoderVersion(void);
112int WebPGetInfo(const uint8_t* data, size_t data_size,
113                int* width, int* height);
114
115#if defined(SWIGJAVA) || defined(SWIGPYTHON)
116
117// free the buffer returned by these functions after copying into
118// the native type
119%newobject WebPDecodeRGB;
120%newobject WebPDecodeRGBA;
121%newobject WebPDecodeARGB;
122%newobject WebPDecodeBGR;
123%newobject WebPDecodeBGRA;
124%typemap(newfree) uint8_t* "free($1);"
125
126uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
127                       int* width, int* height);
128uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size,
129                        int* width, int* height);
130uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size,
131                        int* width, int* height);
132uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size,
133                       int* width, int* height);
134uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size,
135                        int* width, int* height);
136
137#endif  /* SWIGJAVA || SWIGPYTHON */
138
139//------------------------------------------------------------------------------
140// Encoder specific
141
142#if defined(SWIGJAVA) || defined(SWIGPYTHON)
143
144int WebPGetEncoderVersion(void);
145
146#endif  /* SWIGJAVA || SWIGPYTHON */
147
148//------------------------------------------------------------------------------
149// Wrapper code additions
150
151%{
152#include "webp/decode.h"
153#include "webp/encode.h"
154%}
155
156#ifdef SWIGJAVA
157%{
158#define FillMeInAsSizeCannotBeDeterminedAutomatically \
159    (result ? (jint)ReturnedBufferSize(__FUNCTION__, arg3, arg4) : 0)
160%}
161#endif  /* SWIGJAVA */
162
163#if defined(SWIGJAVA) || defined(SWIGPYTHON)
164%{
165static size_t ReturnedBufferSize(
166    const char* function, int* width, int* height) {
167  static const struct sizemap {
168    const char* function;
169    int size_multiplier;
170  } size_map[] = {
171#ifdef SWIGJAVA
172    { "Java_com_google_webp_libwebpJNI_WebPDecodeRGB",  3 },
173    { "Java_com_google_webp_libwebpJNI_WebPDecodeRGBA", 4 },
174    { "Java_com_google_webp_libwebpJNI_WebPDecodeARGB", 4 },
175    { "Java_com_google_webp_libwebpJNI_WebPDecodeBGR",  3 },
176    { "Java_com_google_webp_libwebpJNI_WebPDecodeBGRA", 4 },
177    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB",  1 },
178    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR",  1 },
179    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA", 1 },
180    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA", 1 },
181    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB",  1 },
182    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR",  1 },
183    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA", 1 },
184    { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA", 1 },
185#endif
186#ifdef SWIGPYTHON
187    { "WebPDecodeRGB",  3 },
188    { "WebPDecodeRGBA", 4 },
189    { "WebPDecodeARGB", 4 },
190    { "WebPDecodeBGR",  3 },
191    { "WebPDecodeBGRA", 4 },
192    { "wrap_WebPEncodeRGB",  1 },
193    { "wrap_WebPEncodeBGR",  1 },
194    { "wrap_WebPEncodeRGBA", 1 },
195    { "wrap_WebPEncodeBGRA", 1 },
196    { "wrap_WebPEncodeLosslessRGB",  1 },
197    { "wrap_WebPEncodeLosslessBGR",  1 },
198    { "wrap_WebPEncodeLosslessRGBA", 1 },
199    { "wrap_WebPEncodeLosslessBGRA", 1 },
200#endif
201    { NULL, 0 }
202  };
203  const struct sizemap* p;
204  size_t size = 0;
205
206  for (p = size_map; p->function; ++p) {
207    if (!strcmp(function, p->function)) {
208      size = *width * *height * p->size_multiplier;
209      break;
210    }
211  }
212
213  return size;
214}
215%}
216
217%{
218typedef size_t (*WebPEncodeFunction)(const uint8_t* rgb,
219                                     int width, int height, int stride,
220                                     float quality_factor, uint8_t** output);
221typedef size_t (*WebPEncodeLosslessFunction)(const uint8_t* rgb,
222                                             int width, int height, int stride,
223                                             uint8_t** output);
224
225static uint8_t* EncodeLossy(const uint8_t* rgb,
226                            int width, int height, int stride,
227                            float quality_factor,
228                            WebPEncodeFunction encfn,
229                            int* output_size, int* unused) {
230  uint8_t* output = NULL;
231  const size_t image_size =
232      encfn(rgb, width, height, stride, quality_factor, &output);
233  // the values of following two will be interpreted by ReturnedBufferSize()
234  // as 'width' and 'height' in the size calculation.
235  *output_size = image_size;
236  *unused = 1;
237  return image_size ? output : NULL;
238}
239
240static uint8_t* EncodeLossless(const uint8_t* rgb,
241                               int width, int height, int stride,
242                               WebPEncodeLosslessFunction encfn,
243                               int* output_size, int* unused) {
244  uint8_t* output = NULL;
245  const size_t image_size = encfn(rgb, width, height, stride, &output);
246  // the values of the following two will be interpreted by
247  // ReturnedBufferSize() as 'width' and 'height' in the size calculation.
248  *output_size = image_size;
249  *unused = 1;
250  return image_size ? output : NULL;
251}
252%}
253
254#endif  /* SWIGJAVA || SWIGPYTHON */
255
256//------------------------------------------------------------------------------
257// libwebp/encode wrapper functions
258
259#if defined(SWIGJAVA) || defined(SWIGPYTHON)
260
261%apply int* INPUT { int* unused1, int* unused2 }
262%apply int* OUTPUT { int* output_size }
263
264// free the buffer returned by these functions after copying into
265// the native type
266%newobject wrap_WebPEncodeRGB;
267%newobject wrap_WebPEncodeBGR;
268%newobject wrap_WebPEncodeRGBA;
269%newobject wrap_WebPEncodeBGRA;
270%newobject wrap_WebPEncodeLosslessRGB;
271%newobject wrap_WebPEncodeLosslessBGR;
272%newobject wrap_WebPEncodeLosslessRGBA;
273%newobject wrap_WebPEncodeLosslessBGRA;
274
275#ifdef SWIGJAVA
276// There's no reason to call these directly
277%javamethodmodifiers wrap_WebPEncodeRGB "private";
278%javamethodmodifiers wrap_WebPEncodeBGR "private";
279%javamethodmodifiers wrap_WebPEncodeRGBA "private";
280%javamethodmodifiers wrap_WebPEncodeBGRA "private";
281%javamethodmodifiers wrap_WebPEncodeLosslessRGB "private";
282%javamethodmodifiers wrap_WebPEncodeLosslessBGR "private";
283%javamethodmodifiers wrap_WebPEncodeLosslessRGBA "private";
284%javamethodmodifiers wrap_WebPEncodeLosslessBGRA "private";
285#endif  /* SWIGJAVA */
286
287#ifdef SWIGPYTHON
288// This autodoc will serve as a catch-all for wrap_*.
289%feature("autodoc", "private, do not call directly.");
290#endif
291
292%inline %{
293// Changes the return type of WebPEncode* to more closely match Decode*.
294// This also makes it easier to wrap the output buffer in a native type rather
295// than dealing with the return pointer.
296// The additional parameters are to allow reuse of ReturnedBufferSize(),
297// unused2 and output_size will be used in this case.
298#define LOSSY_WRAPPER(FUNC)                                             \
299  static uint8_t* wrap_##FUNC(                                          \
300      const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \
301      int width, int height, int stride, float quality_factor) {        \
302    return EncodeLossy(rgb, width, height, stride, quality_factor,      \
303                       FUNC, output_size, unused2);                     \
304  }                                                                     \
305
306LOSSY_WRAPPER(WebPEncodeRGB)
307LOSSY_WRAPPER(WebPEncodeBGR)
308LOSSY_WRAPPER(WebPEncodeRGBA)
309LOSSY_WRAPPER(WebPEncodeBGRA)
310
311#undef LOSSY_WRAPPER
312
313#define LOSSLESS_WRAPPER(FUNC)                                          \
314  static uint8_t* wrap_##FUNC(                                          \
315      const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \
316      int width, int height, int stride) {                              \
317    return EncodeLossless(rgb, width, height, stride,                   \
318                          FUNC, output_size, unused2);                  \
319  }                                                                     \
320
321LOSSLESS_WRAPPER(WebPEncodeLosslessRGB)
322LOSSLESS_WRAPPER(WebPEncodeLosslessBGR)
323LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA)
324LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA)
325
326#undef LOSSLESS_WRAPPER
327
328%}
329
330#endif  /* SWIGJAVA || SWIGPYTHON */
331
332//------------------------------------------------------------------------------
333// Language specific
334
335#ifdef SWIGGO
336%insert(go_wrapper) %{
337
338// WebPGetInfo has 2 output parameters, provide a version in the more natural
339// go idiom:
340func WebPGetInfo(webp []byte) (ok bool, width int, height int) {
341    w := []int{0}
342    h := []int{0}
343    ok = Wrapped_WebPGetInfo(string(webp), w, h) != 0
344    width = w[0]
345    height = h[0]
346    return
347}
348
349%}
350#endif  /* SWIGGO */
351
352#ifdef SWIGJAVA
353%{
354/* Work around broken gcj jni.h */
355#ifdef __GCJ_JNI_H__
356# undef JNIEXPORT
357# define JNIEXPORT
358# undef JNICALL
359# define JNICALL
360#endif
361%}
362
363%pragma(java) modulecode=%{
364  private static final int UNUSED = 1;
365  private static int outputSize[] = { 0 };
366%}
367
368
369%define CALL_ENCODE_LOSSY_WRAPPER(func)
370%pragma(java) modulecode=%{
371  public static byte[] func(
372      byte[] rgb, int width, int height, int stride, float quality_factor) {
373    return wrap_##func(
374        rgb, UNUSED, UNUSED, outputSize, width, height, stride, quality_factor);
375  }
376%}
377%enddef
378
379%define CALL_ENCODE_LOSSLESS_WRAPPER(func)
380%pragma(java) modulecode=%{
381  public static byte[] func(
382      byte[] rgb, int width, int height, int stride) {
383    return wrap_##func(
384        rgb, UNUSED, UNUSED, outputSize, width, height, stride);
385  }
386%}
387%enddef
388
389CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGB)
390CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGBA)
391CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGR)
392CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGRA)
393CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGB)
394CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA)
395CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGR)
396CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA)
397#endif  /* SWIGJAVA */
398
399#ifdef SWIGPYTHON
400%pythoncode %{
401_UNUSED = 1
402%}
403
404%define CALL_ENCODE_LOSSY_WRAPPER(func)
405%pythoncode %{
406def func(rgb, width, height, stride, quality_factor):
407  """func(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp"""
408  webp = wrap_##func(
409      rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor)
410  if len(webp[0]) == 0:
411    return None
412  return webp[0]
413%}
414%enddef
415
416%define CALL_ENCODE_LOSSLESS_WRAPPER(func)
417%pythoncode %{
418def func(rgb, width, height, stride):
419  """func(uint8_t rgb, int width, int height, int stride) -> lossless_webp"""
420  webp = wrap_##func(rgb, _UNUSED, _UNUSED, width, height, stride)
421  if len(webp[0]) == 0:
422    return None
423  return webp[0]
424%}
425%enddef
426
427CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGB)
428CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGBA)
429CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGR)
430CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGRA)
431CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGB)
432CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA)
433CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGR)
434CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA)
435#endif  /* SWIGPYTHON */
436