pike.git / src / modules / _Image_JPEG / image_jpeg.c

version» Context lines:

pike.git/src/modules/_Image_JPEG/image_jpeg.c:1:   /*   || 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 "global.h" -  +    #include "config.h"      #if !defined(HAVE_LIBJPEG)   #undef HAVE_JPEGLIB_H   #endif    -  + #include "pike_compiler.h" + #include "pike_macros.h" + #include "object.h" + #include "constants.h" + #include "interpret.h" + #include "svalue.h" + #include "threads.h" + #include "array.h" + #include "mapping.h" + #include "pike_error.h" + #include "stralloc.h" + #include "builtin_functions.h" + #include "module_support.h" + #include "operators.h" + #include "pike_types.h" +    #ifdef HAVE_JPEGLIB_H    - #include <stdio.h> -  +    /* NOTE: INT32 and INT16 are redefined by <jmorecfg.h>. */   #define XMD_H /* Avoid INT16 / INT32 being redefined */      /* FAR is defined by windef.h and jmorecfg.h */   #ifdef FAR   #undef FAR   #endif      #ifdef HAVE_JCONFIG_H_HAVE_BOOLEAN - #ifdef HAVE_WINDOWS_H - #include <windows.h> +    #ifdef HAVE_WTYPES_H   /* jconfig.h has probably been compiled without WIN32_LEAN_AND_MEAN...    * So we need this one to get the boolean typedef.    */   #include <wtypes.h>   #endif   #endif - #endif +       #include <jpeglib.h>   #include "transupp.h" /* Support routines for jpeg transformations */      #endif /* HAVE_JPEGLIB_H */      /* jpeglib defines EXTERN for some reason.    * This is not good, since it confuses compilation.h.    */   #ifdef EXTERN   #undef EXTERN   #endif    - #include "pike_macros.h" - #include "object.h" - #include "constants.h" - #include "interpret.h" - #include "svalue.h" - #include "threads.h" - #include "array.h" - #include "mapping.h" - #include "pike_error.h" - #include "stralloc.h" - #include "threads.h" - #include "builtin_functions.h" - #include "module_support.h" - #include "operators.h" -  +    #define sp Pike_sp      #ifdef HAVE_JPEGLIB_H      #include "../Image/image.h"      #ifdef DYNAMIC_MODULE   static struct program *image_program;   #else   extern struct program *image_program;
pike.git/src/modules/_Image_JPEG/image_jpeg.c:191: Inside #if defined(HAVE_JPEGLIB_H)
   struct my_decompress_struct *mds=    (struct my_decompress_struct*)cinfo;    struct my_marker *mm;    char *d;       length=jpeg_getc(cinfo)<<8;    length|=jpeg_getc(cinfo);    length-=2;    length &= 0xffff;    -  mm=(struct my_marker*)xalloc(sizeof(struct my_marker)+length); +  mm=xalloc(sizeof(struct my_marker)+length);    mm->id=cinfo->unread_marker;    mm->len=length;    mm->next=mds->first_marker;    mds->first_marker=mm;       d = (char *)mm->data;    while (length--) *(d++)=(char)jpeg_getc(cinfo);       if (mm->id==JPEG_APP0+14)    examine_app14(cinfo,mm->data,mm->len);
pike.git/src/modules/_Image_JPEG/image_jpeg.c:235:    dm->pub.next_output_byte=(JOCTET*)dm->buf;   }      static boolean my_empty_output_buffer(struct jpeg_compress_struct *cinfo)   {    struct my_destination_mgr *dm=(struct my_destination_mgr *)cinfo->dest;    size_t pos;    char *new;       pos=dm->len; /* foo! dm->len-dm->pub.free_in_buffer; */ -  new=(char*)realloc(dm->buf,dm->len+BUF_INCREMENT); +  new=realloc(dm->buf,dm->len+BUF_INCREMENT);    if (!new) return FALSE;       dm->buf = new;    dm->len += BUF_INCREMENT; -  dm->pub.free_in_buffer = DO_NOT_WARN(dm->len - pos); +  dm->pub.free_in_buffer = dm->len - pos;    dm->pub.next_output_byte = (JOCTET*)new + pos;       return TRUE;   }      static void my_term_destination(struct jpeg_compress_struct *UNUSED(cinfo))   {    /* don't do anything */   }   
pike.git/src/modules/_Image_JPEG/image_jpeg.c:417:       v=low_mapping_string_lookup(map->u.mapping,what);       if (!v) return 0;    else if (TYPEOF(*v) != T_MAPPING)    Pike_error("Image.JPEG.encode: illegal value of option marker;"    " expected mapping\n");    md=v->u.mapping->data;    NEW_MAPPING_LOOP(md)    { -  if (TYPEOF(k->ind) != T_INT || TYPEOF(k->val) != T_STRING || -  k->val.u.string->size_shift) -  Pike_error("Image.JPEG.encode: illegal value of option " -  "marker; expected mapping(int:8 bit string)\n"); +  if (TYPEOF(k->ind) == T_INT) { +  if (TYPEOF(k->val) == T_STRING && !k->val.u.string->size_shift) {    jpeg_write_marker(cinfo, k->ind.u.integer,    (const unsigned char *)k->val.u.string->str,    k->val.u.string->len); -  +  continue; +  } else if (TYPEOF(k->val) == T_ARRAY) { +  struct array *a = k->val.u.array; +  INT32 i; +  for (i = 0; i < a->size; i++) { +  struct pike_string *str = ITEM(a)[i].u.string; +  if (TYPEOF(ITEM(a)[i]) != T_STRING || str->size_shift) +  goto fail; +  jpeg_write_marker(cinfo, k->ind.u.integer, +  STR0(str), str->len);    } -  +  continue; +  } +  } +  fail: +  Pike_error("Image.JPEG.encode: illegal value of option marker; " +  "expected mapping(int:string(8bit)|array(string(8bit)))\n"); +  }       return 1;   }      static int parameter_comment(struct svalue *map,struct pike_string *what,    struct jpeg_compress_struct *cinfo)   {    struct svalue *v;       v=low_mapping_string_lookup(map->u.mapping,what);
pike.git/src/modules/_Image_JPEG/image_jpeg.c:459:   {    struct jpeg_source_mgr pub;    struct pike_string *str;   };      static void my_init_source(struct jpeg_decompress_struct *cinfo)   {    struct my_source_mgr *sm = (struct my_source_mgr *)cinfo->src;       sm->pub.next_input_byte = (JOCTET*)sm->str->str; -  sm->pub.bytes_in_buffer = DO_NOT_WARN(sm->str->len); +  sm->pub.bytes_in_buffer = sm->str->len;   }      static boolean my_fill_input_buffer(struct jpeg_decompress_struct *cinfo)   {    static const unsigned char my_eoi[2]={0xff,JPEG_EOI};       struct my_source_mgr *sm=(struct my_source_mgr *)cinfo->src;       sm->pub.next_input_byte=my_eoi;    sm->pub.bytes_in_buffer=2;
pike.git/src/modules/_Image_JPEG/image_jpeg.c:648:    *! @member int "x_density"    *! @member int "y_density"    *! Density of image.    *! @member string "comment"    *! Comment to be written in the JPEG file. Must not be a wide string.    *! @member int(0..1) "baseline"    *! Force baseline output. Useful for quality<25.    *! Default is off for quality<25.    *! @member mapping(int:array(array(int))) "quant_tables"    *! Tune quantisation tables manually. -  *! @member mapping(int:string) "marker" +  *! @member mapping(int:string(8bit)|array(string(8bit))) "marker"    *! Application and comment markers;    *! the integer should be one of @[Marker.COM], @[Marker.APP0],    *! @[Marker.APP1], ..., @[Marker.APP15]. The string is up to the application;    *! most notable are Adobe and Photoshop markers.    *! @member int "transform"    *! Lossless image transformation. Has only effect when supplying a    *! JPEG file as indata.    *! @int    *! @value FLIP_H    *! Flip image horizontally
pike.git/src/modules/_Image_JPEG/image_jpeg.c:697:    struct my_decompress_struct mds;       unsigned char *tmp = NULL;    INT32 y;    rgb_group *s;    JSAMPROW row_pointer[8];       if (args<1    || (TYPEOF(sp[-args]) != T_OBJECT && TYPEOF(sp[-args]) != T_STRING)    || (TYPEOF(sp[-args]) == T_OBJECT && -  !(img=(struct image*) get_storage(sp[-args].u.object,image_program))) +  !(img= get_storage(sp[-args].u.object,image_program)))    || (args>1 && TYPEOF(sp[1-args]) != T_MAPPING))    Pike_error("Image.JPEG.encode: Illegal arguments\n");       if (img) {    /* Compression from Image.Image object */    if (!img->img)    Pike_error("Image.JPEG.encode: Given image is empty.\n");       tmp=malloc(img->xsize*3*8);    if (!tmp)
pike.git/src/modules/_Image_JPEG/image_jpeg.c:976:    *! @endint    *! @member int "x_density"    *! @member int "y_density"    *! Density of image.    *! @member int(0..1) "adobe_marker"    *! If the file has an Adobe marker.    *! @member mapping(int:array(array(int))) "quant_tables"    *! JPEG quant tables.    *! @member int(0..100) "quality"    *! JPEG quality guess. +  *! @member mapping(int(0..255):string(8bit)|array(string(8bit))) "marker" +  *! Mapping from application and comment markers to their values.    *! @endmapping    */      enum { IMG_DECODE_MUCH,IMG_DECODE_IMAGE,IMG_DECODE_HEADER };      static void img_jpeg_decode(INT32 args,int mode)   {    struct jpeg_error_mgr errmgr;    struct my_source_mgr srcmgr;    struct my_decompress_struct mds;       struct object *o=NULL;    struct image *img=NULL;       unsigned char *tmp,*s;    INT32 y;    rgb_group *d;    JSAMPROW row_pointer[8];    -  int n=0,m; +  int n=0;       if (args<1    || TYPEOF(sp[-args]) != T_STRING    || (args>1 && TYPEOF(sp[1-args]) != T_MAPPING))    Pike_error("Image.JPEG.decode: Illegal arguments\n");       /* init jpeg library objects */       init_src(sp[-args].u.string, &errmgr, &srcmgr, &mds);   
pike.git/src/modules/_Image_JPEG/image_jpeg.c:1047:    if (parameter_int(sp+1-args,param_scale_denom,&p)    &&parameter_int(sp+1-args,param_scale_num,&q))    mds.cinfo.scale_num=q,    mds.cinfo.scale_denom=p;       parameter_qt_d(sp+1-args,param_quant_tables,&mds.cinfo);    }       if (mode!=IMG_DECODE_IMAGE)    { +  struct mapping *markers; +  int got_comment = 0; +     /* standard header info */    -  push_text("type"); n++; -  push_text("image/jpeg"); +  ref_push_string(literal_type_string); n++; +  push_static_text("image/jpeg");    -  push_text("xsize"); n++; +  push_static_text("xsize"); n++;    push_int(mds.cinfo.image_width);    -  push_text("ysize"); n++; +  push_static_text("ysize"); n++;    push_int(mds.cinfo.image_height);    -  push_text("xdpi"); n++; -  push_text("ydpi"); n++; +  push_static_text("xdpi"); n++; +  push_static_text("ydpi"); n++;    switch (mds.cinfo.density_unit)    {    default:    pop_n_elems(2); n-=2;    break;    case 1:    push_float( mds.cinfo.X_density );    stack_swap();    push_float( mds.cinfo.Y_density );    break;    case 2: -  push_float( DO_NOT_WARN((FLOAT_TYPE)(mds.cinfo.X_density/2.54)) ); +  push_float( (FLOAT_TYPE)(mds.cinfo.X_density/2.54) );    stack_swap(); -  push_float( DO_NOT_WARN((FLOAT_TYPE)(mds.cinfo.Y_density/2.54)) ); +  push_float( (FLOAT_TYPE)(mds.cinfo.Y_density/2.54) );    break;    }       /* JPEG special header */    -  push_text("num_components"); n++; +  push_static_text("num_components"); n++;    push_int(mds.cinfo.num_components);    -  push_text("color_space"); n++; +  push_static_text("color_space"); n++;    switch (mds.cinfo.jpeg_color_space)    { -  case JCS_UNKNOWN: push_text("UNKNOWN"); break; -  case JCS_GRAYSCALE: push_text("GRAYSCALE"); break; -  case JCS_RGB: push_text("RGB"); break; -  case JCS_YCbCr: push_text("YUV"); break; -  case JCS_CMYK: push_text("CMYK"); break; -  case JCS_YCCK: push_text("YCCK"); break; -  default: push_text("?"); break; +  case JCS_UNKNOWN: push_static_text("UNKNOWN"); break; +  case JCS_GRAYSCALE: push_static_text("GRAYSCALE"); break; +  case JCS_RGB: push_static_text("RGB"); break; +  case JCS_YCbCr: push_static_text("YUV"); break; +  case JCS_CMYK: push_static_text("CMYK"); break; +  case JCS_YCCK: push_static_text("YCCK"); break; +  default: push_static_text("?"); break;    }    -  push_text("density_unit"); n++; +  push_static_text("density_unit"); n++;    push_int(mds.cinfo.density_unit);    -  push_text("x_density"); n++; +  push_static_text("x_density"); n++;    push_int(mds.cinfo.X_density);    -  push_text("y_density"); n++; +  push_static_text("y_density"); n++;    push_int(mds.cinfo.Y_density);    -  push_text("adobe_marker"); n++; +  push_static_text("adobe_marker"); n++;    push_int(mds.cinfo.saw_Adobe_marker);       ref_push_string(param_marker); n++; -  m=0; +  push_mapping(markers = allocate_mapping(mds.first_marker?10:0));    while (mds.first_marker)    {    struct my_marker *mm=mds.first_marker; -  +  struct svalue *val;    push_int(mm->id); -  +  if ((val = low_mapping_lookup(markers, Pike_sp-1))) { +  if (TYPEOF(*val) == T_STRING) { +  /* Both values are strings. */ +  ref_push_string(val->u.string); +  push_string(make_shared_binary_string((char *)mm->data, +  mm->len)); +  f_aggregate(2); +  } else { +  struct array *old = val->u.array; +  struct array *new; +  push_string(make_shared_binary_string((char *)mm->data, +  mm->len)); +  +  /* Make sure not to free the old array in place +  * on realloc, as that would invalidate the mapping. +  */ +  add_ref(old); +  +  new = append_array(old, Pike_sp-1); +  pop_stack(); +  if (new == old) { +  /* Array modified in place. +  * No need to reassign it. +  * Remove the extra reference from above. +  */ +  free_array(old); +  goto next_marker; +  } +  /* The reference we added to old has migrated to new. +  * Pass it along to the stack. +  */ +  push_array(new); +  } +  } else {    push_string(make_shared_binary_string((char *)mm->data, mm->len)); -  m++; -  mds.first_marker=mm->next; -  free(mm); +     } -  f_aggregate_mapping(m*2); -  -  if (m) -  { -  stack_dup(); -  push_int(JPEG_COM); -  f_index(2); -  if (TYPEOF(sp[-1]) == T_STRING) -  { -  ref_push_string(param_comment); n++; +  mapping_insert(markers, Pike_sp-2, Pike_sp-1); +  if ((mm->id == JPEG_COM) && !got_comment) { +  /* First comment - Add the comment to the main mapping too. */    stack_swap(); -  +  pop_stack(); /* Zap mm->id from the stack. */ +  ref_push_string(param_comment); +  stack_swap(); /* And replace it with "comment". */ +  n++; /* One more element for the main mapping. */ +  got_comment = 1; +  } else { +  pop_n_elems(2);    } -  else -  pop_stack(); +  next_marker: +  mds.first_marker=mm->next; +  free(mm);    }    }       while (mds.first_marker)    {    struct my_marker *mm=mds.first_marker;    mds.first_marker=mm->next;    free(mm);    }       if (mode!=IMG_DECODE_HEADER)    {    int bytes_per_pixel;       jpeg_start_decompress(&mds.cinfo);    bytes_per_pixel = mds.cinfo.output_components;       o=clone_object(image_program,0); -  img=(struct image*)get_storage(o,image_program); +  img=get_storage(o,image_program);    if (!img) Pike_error("image no image? foo?\n"); /* should never happen */    img->img=malloc(bytes_per_pixel *    mds.cinfo.output_width*mds.cinfo.output_height);    if (!img->img)    {    jpeg_destroy((struct jpeg_common_struct*)&mds.cinfo);    free_object(o);    Pike_error("Image.JPEG.decode: out of memory\n");    }    img->xsize=mds.cinfo.output_width;
pike.git/src/modules/_Image_JPEG/image_jpeg.c:1221:    y-=n;    }    THREADS_DISALLOW();       free(tmp);       if (mode!=IMG_DECODE_IMAGE)    {    int i,m,j;    -  push_text("quant_tables"); +  push_static_text("quant_tables");    for (i=m=0; i<NUM_QUANT_TBLS; i++)    {    if (mds.cinfo.quant_tbl_ptrs[i])    {    push_int(i);    for (j=0; j<DCTSIZE2; j++)    {    push_int(mds.cinfo.quant_tbl_ptrs[i]->quantval[j]);    if (!((j+1)%DCTSIZE))    f_aggregate(DCTSIZE);
pike.git/src/modules/_Image_JPEG/image_jpeg.c:1252:    int q=mds.cinfo.quant_tbl_ptrs[0]->quantval[4*DCTSIZE+4];    int a=0,b=100,c,w;    while (b>a)    {    c=(b+a)/2;    w=reverse_quality[c];    if (w==q) break;    else if (w>q) a=++c;    else b=c;    } -  push_text("quality"); +  push_static_text("quality");    push_int(c);    n++;    }    }       jpeg_finish_decompress(&mds.cinfo);    }    jpeg_destroy_decompress(&mds.cinfo);       if (mode==IMG_DECODE_IMAGE)    {    pop_n_elems(args);    push_object(o);    return;    }    else if (mode==IMG_DECODE_MUCH)    { -  push_text("image"); +  push_static_text("image");    push_object(o);    n++;    }       f_aggregate_mapping(n*2);    while (args--)    {    stack_swap();    pop_stack();    }
pike.git/src/modules/_Image_JPEG/image_jpeg.c:1333:    cinfo.dest=(struct jpeg_destination_mgr*)&destmgr;       cinfo.image_width=17;    cinfo.image_height=17;    cinfo.input_components=3;    cinfo.in_color_space=JCS_RGB;       if (args)    {    INT_TYPE q; -  get_all_args("Image.JPEG.quant_tables",args,"%i",&q); +  get_all_args(NULL,args,"%i",&q);    jpeg_set_quality(&cinfo,q,0);    }       for (i=m=0; i<NUM_QUANT_TBLS; i++)    {    if (cinfo.quant_tbl_ptrs[i])    {    push_int(i);    for (j=0; j<DCTSIZE2; j++)    {
pike.git/src/modules/_Image_JPEG/image_jpeg.c:1494:    free_string(param_scale_num);    free_string(param_grayscale);    free_string(param_marker);    free_string(param_comment);    free_string(param_transform);   }      PIKE_MODULE_INIT   {   #ifdef HAVE_JPEGLIB_H - #ifdef DYNAMIC_MODULE + #ifndef FAKE_DYNAMIC_LOAD    image_program = PIKE_MODULE_IMPORT(Image, image_program);    if(!image_program) {    yyerror("Could not load Image module.");    return;    }   #endif /* DYNAMIC_MODULE */      #define tOptions tMap(tStr,tOr3( \    tInt, \    tStr, \