pike.git / src / post_modules / _Image_WebP / image_webp.cmod

version» Context lines:

pike.git/src/post_modules/_Image_WebP/image_webp.cmod:1: + /* -*- c -*- + || This file is part of Pike. For copyright information see COPYRIGHT. + || Pike is distributed under GPL, LGPL and MPL. See the file COPYING + || for more information. + */ +    #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"   #include "svalue.h"   #include "threads.h"   #include "array.h"   #include "builtin_functions.h"   #include "mapping.h"   #include "pike_error.h" - #include "threads.h" +    #include "operators.h"   #include "module_support.h"   #include "modules/Image/image.h"   #include "config.h"      #ifdef HAVE_LIBWEBP   DECLARATIONS      /* #define DEFAULT_CMOD_STORAGE static*/   #define true 1
pike.git/src/post_modules/_Image_WebP/image_webp.cmod:52:    }       next_size = (uint64_t)w->size + data_size;       if (next_size > w->max_size)    {    uint8_t* new_mem;    size_t next_max_size = 2ULL * w->max_size;    if (next_max_size < next_size) next_max_size = next_size;    if (next_max_size < 8192ULL) next_max_size = 8192ULL; -  new_mem = (uint8_t*)xalloc(next_max_size); +  new_mem = xalloc(next_max_size);    if (w->size > 0) {    memcpy(new_mem, w->mem, w->size);    }    free(w->mem);    w->mem = new_mem;    w->max_size = (size_t)next_max_size;    }    if (data_size > 0) {    memcpy(w->mem + w->size, data, data_size);    w->size += data_size;
pike.git/src/post_modules/_Image_WebP/image_webp.cmod:75:   }   #endif         typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int);         typedef struct object object;   typedef struct program program;    + static program *img_program; +    static program *image_program()   { -  static program *ip; -  if( !ip ) +  if( !img_program )    { -  push_text("Image.Image"); +  push_static_text("Image.Image");    SAFE_APPLY_MASTER("resolv",1); -  ip = Pike_sp[-1].u.program; +  img_program = Pike_sp[-1].u.program;    Pike_sp--;    } -  return ip; +  return img_program;   }      static object *allocate_image(int w, int h )   {    push_int(w);    push_int(h);    return clone_object(image_program(),2);   }      static inline int image_width( object *img )
pike.git/src/post_modules/_Image_WebP/image_webp.cmod:191:    *output = (uint8_t*)"Unknown error\n";    break;    }    return 0;    }    *output = wrt.mem;    return wrt.size;   }       - PIKEFUN object decode( string data ) - { -  apply( Pike_fp->current_object, "_decode", 1 ); -  push_text( "image" ); -  f_index(2); - } + /*! @module Image +  *! +  *! @module WebP +  *! +  *! WebP is a truecolor image format with alpha channel support +  *! currently developed by Google. +  *! +  *! This module supports decoding and encoding of lossy and lossless +  *! WebP images with and without alpha channels using the libwebp library. +  *! +  *! WebP images are generally smaller than the same quality JPEG or +  *! PNG image, but takes longer to encode and decode, and support in +  *! various applications is less common. +  *! +  */    - PIKEFUN mapping(string:object) _decode( string data ) + /*! @decl mapping _decode( string data ) +  *! +  *! Decode a WebP image. +  *! +  *! @returns +  *! @mapping +  *! @member Image.Image "alpha" +  *! @member Image.Image "image" +  *! @member string "format" +  *! @member int(1..16384) "width" +  *! @member int(1..16384) "height" +  *! @endmapping +  */ +  + /*! @decl Image.Image decode( string data ) +  *! +  *! Decode a WebP image, like @[_decode]. +  *! @returns +  *! The decoded image or an error +  */ +  + PIKEFUN mapping(string:object(Image.Image)|string) _decode( string data )   {    int width, height, npix;    uint8_t *ip, *rp, *ap;    object *i = NULL, *a = NULL;    WebPBitstreamFeatures features;    uint8_t *res = WebPDecodeRGBA( (uint8_t*)data->str, data->len,    &width, &height );    WebPGetFeatures( (uint8_t*)data->str, data->len, &features );       if( !res )
pike.git/src/post_modules/_Image_WebP/image_webp.cmod:231:    ip = image_ptr( i );       while( npix-- )    {    uint8_t av;    *(ip++) = *(rp++); // R    *(ip++) = *(rp++); // G    *(ip++) = *(rp++); // B    av = *(rp++);    -  if( av && ap ) +  if( ap )    {    *(ap++) = av; // A    *(ap++) = av;    *(ap++) = av;    }    }    free( res );    -  push_text( "image" ); push_object( i ); -  push_text( "alpha" ); +  pop_n_elems(args); +  +  push_static_text( "image" ); push_object( i ); +  push_static_text( "img" ); ref_push_object( i ); +  push_static_text( "alpha" );    if( a )    push_object( a );    else    push_undefined( ); -  push_text("format"); push_text("WebP"); -  push_text( "xsize" ); push_int( width ); -  push_text( "ysize" ); push_int( height ); -  f_aggregate_mapping( 10 ); +  push_static_text("format"); push_text("image/webp"); +  push_static_text( "xsize" ); push_int( width ); +  push_static_text( "ysize" ); push_int( height ); +  f_aggregate_mapping( 12 );   }    - #ifndef TYPEOF - #define TYPEOF(X) (X).type - #endif + PIKEFUN object(Image.Image) decode( string data ) + { +  struct mapping *m; +  struct svalue *p;    -  +  apply(Pike_fp->current_object, "_decode", args); +  +  m = Pike_sp[-1].u.mapping; +  +  if( TYPEOF(Pike_sp[-1]) != PIKE_T_MAPPING ) +  Pike_error("Decoding failed\n"); +  +  p = simple_mapping_string_lookup(m,"image"); +  +  if( !p || TYPEOF(*p) != PIKE_T_OBJECT ) +  Pike_error("Decoding failed\n"); +  +  ref_push_object( p->u.object ); +  stack_unlink(1); + } +    static int parameter_int(struct mapping *map, const char *what, int def )   {    struct svalue *v = simple_mapping_string_lookup(map,what);    if (v && TYPEOF(*v) == PIKE_T_INT) return v->u.integer;    return def;   }      static double parameter_float(struct mapping *map, const char *what,    double def )   {
pike.git/src/post_modules/_Image_WebP/image_webp.cmod:283:   }      static object *parameter_obj(struct mapping *map, const char *what )   {    struct svalue *v = simple_mapping_string_lookup(map,what);    if( v && TYPEOF(*v) == PIKE_T_OBJECT )    return v->u.object;    return NULL;   }    - PIKEFUN string encode( object i, -  mapping(string:int|float|object)|void options ) +  + /*! @decl string encode( Image.Image image, mapping(string:int|float|Image.Image)|void options ) +  *! +  *! Encode an image using the WebP format. +  *! +  *! The image to encode has to be at most 16384 pixels in any direction. +  *! +  *! Commonly used options: +  *! +  *! @mapping +  *! @member Image.Image "alpha" +  *! If present, the alpha channel for the image will be the green +  *! component of this image. Has to be the same size as the @[image] +  *! @member int "preset" +  *! Initialization for the encoding options. +  *! One of PRESET_DEFAULT, PRESET_PICTURE, PRESET_PHOTO +  *! PRESET_DRAWING, PRESET_ICON and PRESET_TEXT +  *! @member bool "lossless" +  *! If set, do lossless encoding. +  *! @member float "quality" +  *! Between 0 and 99. If quality is 100+, lossless encoding with +  *! quality 70 will be used. +  *! @endmapping +  *! +  *! Additionally these advanced options are also supported: +  *! +  *! @mapping +  *! @member int "image_hint" +  *! One of HINT_DEFAULT, HINT_PICTURE, HINT_PHOTO and HINT_GRAPH. +  *! Only used in lossless mode +  *! @member int "target_size" +  *! If non zero, sets the desired filesize, in bytes. Takes +  *! precedence over quality. +  *! @member int "target_PSNR" +  *! if non-zero, specifies the minimal distortion to try to +  *! achieve. Takes precedence over target_size. +  *! @member int(1..4) "segments" +  *! maximum number of segments to use. +  *! @member int(0..100) "sns_strength" +  *! Spatial Noise Shaping. 0=off, 100=maximum. +  *! @member int(0..100) "filter_strength" +  *! 0=off +  *! @member int(0..7) "filter_sharpness" +  *! 0=off +  *! @member int(0..1) "filter_type" +  *! For the type, 0=simple, 1=strong. +  *! @member bool autofilter +  *! If true, automatically adjust the filter strengths +  *! @member int(0..1) "alpha_compression" +  *! Select alpha channel encoding format. Currently supported are 0: No alpha and 1: WebP lossless +  *! @member int(0..2) "alpha_filtering" +  *! Select alpha filtering method. 0: none, 1: fast, 2: best. Default if 1. +  *! @member int(0..100) "alpha_quality" +  *! Select the base image quality for the alpha channel. +  *! @member int(1..10) "pass" +  *! The number of entropy analysis passes. Defaults to 1. +  *! @member bool "show_compressed" +  *! +  *! @member bool "preprocessing" +  *! If true, do preprocessing (segment-smooth) +  *! @member int(0..3) "partitions" +  *! log2(number of token partitions). Default is set to 0 for easier +  *! progressive decoding. +  *! @member int(0..100) "partition_limit" +  *! quality degradation allowed to fit the 512k limit on prediction +  *! modes coding (0: no degradation, 100: maximum possible +  *! degradation). +  *! @member bool "emulate_jpeg_size" +  *! If true, try to map the quality setting to generate similar sizes +  *! when compared to jpeg. +  *! @member int "thread_level" +  *! The maximum number of extra threads to use. Defaults to 0 +  *! @member bool "low_memory" +  *! Decrease memory usage at the cost of encoding speed +  *! @endmapping +  *! +  *! @returns +  *! Always returns the encoded image as a string or throws an error. +  *! +  */ + PIKEFUN string(0..255) encode( object(Image.Image) i, +  mapping(string:int|float|object(Image.Image))|void options )   {    unsigned char *result = NULL;    size_t size;    object *a;    int width = image_width( i );    int height = image_height( i );    unsigned char *iptr = image_ptr( i );    unsigned char *rgba = NULL;    Importer importer = WebPPictureImportRGB;    WebPConfig config;
pike.git/src/post_modules/_Image_WebP/image_webp.cmod:372:    if( config.quality >= 100 )    {    config.quality = 70;    config.lossless = true;    }   #endif    }    else    {    a = 0; -  WebPConfigInit( &config ); +  if( !WebPConfigInit( &config ) ) +  Pike_error("Failed to initialize config.\n");    }       if( a )    {    unsigned char *aptr = image_ptr( a );    int num = width*height;    unsigned char *dst;    importer = WebPPictureImportRGBA;       if( !aptr )    Pike_error("Alpha channels is not an image object\n");   #if WEBP_ENCODER_ABI_VERSION < 0x0201    else    Pike_error("Alpha channels are not supported by your libwebp.\n");   #endif    if( image_width( a ) != width || image_height( a ) != height )    Pike_error("The alpha channel does not have the same size as the image\n");    -  dst = rgba = (unsigned char*)xalloc( num * 4 ); +  dst = rgba = xalloc( num * 4 );       while( num-- )    {    *(dst++) = *(iptr++); // r    *(dst++) = *(iptr++); // g    *(dst++) = *(iptr++); // b    *(dst++) = *(aptr); // a    aptr += 3;    }    }
pike.git/src/post_modules/_Image_WebP/image_webp.cmod:415:       if( rgba ) free( rgba );       if( size == 0 )    Pike_error( (const char *)result );       push_string( make_shared_binary_string( (const char *)result, size ) );    free( result );   }    + EXIT { +  if (img_program) { +  free_program(img_program); +  img_program = NULL; +  } + }    -  + /* + *! @decl constant PRESET_DEFAULT + *! @decl constant PRESET_PICTURE + *! @decl constant PRESET_PHOTO + *! @decl constant PRESET_DRAWING + *! @decl constant PRESET_ICON + *! @decl constant PRESET_TREXT + *! Constants used to select the default values for the various encoding options in @[encode]. + *! + *! @decl constant HINT_DEFAULT + *! @decl constant HINT_PICTURE + *! @decl constant HINT_PHOTO + *! @decl constant HINT_GRAPH + *! Constants used to give hints to the lossless encoder when using @[encode]. + *! (selected automatically when using a hint.) + */ +    EXTRA {   #define CONST(X) add_integer_constant( #X, WEBP_##X, 0 );    CONST(PRESET_DEFAULT);    CONST(PRESET_PICTURE);    CONST(PRESET_PHOTO);    CONST(PRESET_DRAWING);    CONST(PRESET_ICON);    CONST(PRESET_TEXT);      #if WEBP_ENCODER_ABI_VERSION > 0x0200    CONST(HINT_DEFAULT);    CONST(HINT_PICTURE);    CONST(HINT_PHOTO);    CONST(HINT_GRAPH);   #endif   #undef CONST   }   #endif /* HAVE_LIBVPX */ -  +  + /*! @endmodule +  *! +  *! @endmodule +  */