/* Yuk! Have to malloc enough space for the whole image. Interlaced PNG * is not really suitable for large objects ... */ static int png2vips_interlace( Read *read ) { const int rowbytes = IM_IMAGE_SIZEOF_LINE( read->out ); int y; if( !(read->row_pointer = IM_ARRAY( NULL, read->pInfo->height, png_bytep )) ) return( -1 ); if( !(read->data = (png_bytep) im_malloc( NULL, read->pInfo->height * rowbytes )) ) return( -1 ); for( y = 0; y < (int) read->pInfo->height; y++ ) read->row_pointer[y] = read->data + y * rowbytes; if( im_outcheck( read->out ) || im_setupout( read->out ) || setjmp( read->pPng->jmpbuf ) ) return( -1 ); png_read_image( read->pPng, read->row_pointer ); for( y = 0; y < (int) read->pInfo->height; y++ ) if( im_writeline( y, read->out, read->row_pointer[y] ) ) return( -1 ); return( 0 ); }
double *im_dvector(int nl, int nh) { double *v; v = (double *)im_malloc(NULL,(unsigned)(nh - nl + 1) * sizeof(double)); if (v == NULL) return(NULL); else return(v-nl); }
float *im_fvector(int nl, int nh) { float *v; v = (float *)im_malloc(NULL,(unsigned)(nh - nl + 1) * sizeof(float)); if (v == NULL) return(NULL); else return(v-nl); }
static int attach_thumbnail( IMAGE *im, ExifData *ed ) { if( ed->size > 0 ) { char *thumb_copy; thumb_copy = im_malloc( NULL, ed->size ); memcpy( thumb_copy, ed->data, ed->size ); if( im_meta_set_blob( im, "jpeg-thumbnail-data", (im_callback_fn) im_free, thumb_copy, ed->size ) ) { im_free( thumb_copy ); return( -1 ); } } return( 0 ); }
/* Decode base64 back to binary in a malloc'd buffer. NULL on error. */ unsigned char * im__b64_decode( const char *buffer, size_t *data_length ) { const size_t buffer_length = strlen( buffer ); /* Worst case. */ const size_t output_data_length = buffer_length * 3 / 4; unsigned char *data; unsigned char *p; unsigned int bits; int nbits; size_t i; if( output_data_length > 1024 * 1024 ) { /* We shouldn't really be used for large amounts of data. */ im_error( "im__b64_decode", "%s", _( "too much data" ) ); return( NULL ); } if( !(data = im_malloc( NULL, output_data_length )) ) return( NULL ); p = data; bits = 0; nbits = 0; for( i = 0; i < buffer_length; i++ ) { unsigned int val; if( (val = b64_index[(int) buffer[i]]) != XX ) { bits <<= 6; bits |= val; nbits += 6; if( nbits >= 8 ) { *p++ = (bits >> (nbits - 8)) & 0xff; nbits -= 8; } }
/** * im_fav4: * @in: array of 4 input #IMAGE s * @out: output #IMAGE * * Average four identical images. * * Deprecated. */ int im_fav4( IMAGE **in, IMAGE *out) { PEL *result, *buffer, *p1, *p2, *p3, *p4; int x,y; int linebytes, PICY; /* check IMAGEs parameters */ if(im_iocheck(in[1], out)) return(-1); /* BYTE images only! */ if( (in[0]->BandFmt != IM_BANDFMT_CHAR) && (in[0]->BandFmt != IM_BANDFMT_UCHAR)) return(-1); if ( im_cp_desc(out, in[1]) == -1) /* copy image descriptors */ return(-1); if ( im_setupout(out) == -1) return(-1); linebytes = in[0]->Xsize * in[0]->Bands; PICY = in[0]->Ysize; buffer = (PEL*)im_malloc(NULL,linebytes); memset(buffer, 0, linebytes); p1 = (PEL*)in[0]->data; p2 = (PEL*)in[1]->data; p3 = (PEL*)in[2]->data; p4 = (PEL*)in[3]->data; for (y = 0; y < PICY; y++) { result = buffer; /* average 4 pels with rounding, for whole line*/ for (x = 0; x < linebytes; x++) { *result++ = (PEL)((int)((int)*p1++ + (int)*p2++ + (int)*p3++ + (int)*p4++ +2) >> 2); } im_writeline(y,out, buffer); } im_free(buffer); return(0); }
Draw * im__draw_init( Draw *draw, IMAGE *im, PEL *ink ) { if( im_rwcheck( im ) ) return( NULL ); draw->im = im; draw->ink = NULL; draw->lsize = IM_IMAGE_SIZEOF_LINE( im ); draw->psize = IM_IMAGE_SIZEOF_PEL( im ); draw->noclip = FALSE; if( ink ) { if( !(draw->ink = (PEL *) im_malloc( NULL, draw->psize )) ) return( NULL ); memcpy( draw->ink, ink, draw->psize ); } return( draw ); }
/* Noninterlaced images can be read without needing enough RAM for the whole * image. */ static int png2vips_noninterlace( Read *read ) { const int rowbytes = IM_IMAGE_SIZEOF_LINE( read->out ); int y; if( !(read->data = (png_bytep) im_malloc( NULL, rowbytes )) ) return( -1 ); if( im_outcheck( read->out ) || im_setupout( read->out ) || setjmp( read->pPng->jmpbuf ) ) return( -1 ); for( y = 0; y < (int) read->pInfo->height; y++ ) { png_read_row( read->pPng, read->data, NULL ); if( im_writeline( y, read->out, read->data ) ) return( -1 ); } return( 0 ); }
static int buffer_move( im_buffer_t *buffer, Rect *area ) { IMAGE *im = buffer->im; size_t new_bsize; g_assert( buffer->ref_count == 1 ); buffer->area = *area; im_buffer_undone( buffer ); g_assert( !buffer->done ); new_bsize = (size_t) IM_IMAGE_SIZEOF_PEL( im ) * area->width * area->height; if( buffer->bsize < new_bsize ) { buffer->bsize = new_bsize; IM_FREE( buffer->buf ); if( !(buffer->buf = im_malloc( NULL, buffer->bsize )) ) return( -1 ); } return( 0 ); }
/* Make a new buffer. */ im_buffer_t * im_buffer_new( IMAGE *im, Rect *area ) { im_buffer_t *buffer; if( !(buffer = IM_NEW( NULL, im_buffer_t )) ) return( NULL ); buffer->ref_count = 1; buffer->im = im; buffer->area = *area; buffer->done = FALSE; buffer->cache = NULL; buffer->bsize = (size_t) IM_IMAGE_SIZEOF_PEL( im ) * area->width * area->height; if( !(buffer->buf = im_malloc( NULL, buffer->bsize )) ) { im_buffer_unref( buffer ); return( NULL ); } #ifdef DEBUG printf( "** im_buffer_new: left = %d, top = %d, " "width = %d, height = %d (%p)\n", buffer->area.left, buffer->area.top, buffer->area.width, buffer->area.height, buffer ); #endif /*DEBUG*/ #ifdef DEBUG g_mutex_lock( im__global_lock ); im__buffers_all = g_slist_prepend( im__buffers_all, buffer ); printf( "%d buffers in vips\n", g_slist_length( im__buffers_all ) ); g_mutex_unlock( im__global_lock ); #endif /*DEBUG*/ return( buffer ); }
/* Output to a malloc'd buffer, NULL on error. Try to be simple and reliable, * rather than quick. */ char * im__b64_encode( const unsigned char *data, size_t data_length ) { /* Worst case: 1.333 chars per byte, plus 10% for extra carriage * returns and stuff. And the \n\0 at the end. */ const size_t output_data_length = data_length * 44 / 30 + 2; char *buffer; char *p; size_t i; int cursor; if( data_length <= 0 ) { im_error( "im__b64_encode", "%s", _( "too little data" ) ); return( NULL ); } if( output_data_length > 1024 * 1024 ) { /* We shouldn't really be used for large amounts of data. */ im_error( "im__b64_encode", "%s", _( "too much data" ) ); return( NULL ); } if( !(buffer = im_malloc( NULL, output_data_length )) ) return( NULL ); p = buffer; *p++ = '\n'; cursor = 0; for( i = 0; i < data_length; i += 3 ) { size_t remaining = data_length - i; int bits; bits = read24( data + i, remaining ); encode24( p, bits, remaining * 8 ); p += 4; cursor += 4; if( cursor >= 76 ) { *p++ = '\n'; cursor = 0; } } if( cursor > 0 ) *p++ = '\n'; *p++ = '\0'; #ifdef DEBUG { unsigned int total; /* Calculate a very simple checksum for debugging. */ for( total = 0, i = 0; i < data_length; i++ ) total += data[i]; printf( "im__b64_encode: length = %d, checksum 0x%x\n", data_length, total & 0xffff ); } #endif /*DEBUG*/ return( buffer ); }
/* Read a cinfo to a VIPS image. Set invert_pels if the pixel reader needs to * do 255-pel. */ static int read_jpeg_header( struct jpeg_decompress_struct *cinfo, IMAGE *out, gboolean *invert_pels, int shrink ) { jpeg_saved_marker_ptr p; int type; /* Capture app2 sections here for assembly. */ void *app2_data[MAX_APP2_SECTIONS] = { 0 }; int app2_data_length[MAX_APP2_SECTIONS] = { 0 }; int data_length; int i; /* Read JPEG header. libjpeg will set out_color_space sanely for us * for YUV YCCK etc. */ jpeg_read_header( cinfo, TRUE ); cinfo->scale_denom = shrink; cinfo->scale_num = 1; jpeg_calc_output_dimensions( cinfo ); *invert_pels = FALSE; switch( cinfo->out_color_space ) { case JCS_GRAYSCALE: type = IM_TYPE_B_W; break; case JCS_CMYK: type = IM_TYPE_CMYK; /* Photoshop writes CMYK JPEG inverted :-( Maybe this is a * way to spot photoshop CMYK JPGs. */ if( cinfo->saw_Adobe_marker ) *invert_pels = TRUE; break; case JCS_RGB: default: type = IM_TYPE_sRGB; break; } /* Set VIPS header. */ im_initdesc( out, cinfo->output_width, cinfo->output_height, cinfo->output_components, IM_BBITS_BYTE, IM_BANDFMT_UCHAR, IM_CODING_NONE, type, 1.0, 1.0, 0, 0 ); /* Interlaced jpegs need lots of memory to read, so our caller needs * to know. */ (void) im_meta_set_int( out, "jpeg-multiscan", jpeg_has_multiple_scans( cinfo ) ); /* Look for EXIF and ICC profile. */ for( p = cinfo->marker_list; p; p = p->next ) { switch( p->marker ) { case JPEG_APP0 + 1: /* EXIF data. */ #ifdef DEBUG printf( "read_jpeg_header: seen %d bytes of APP1\n", p->data_length ); #endif /*DEBUG*/ if( read_exif( out, p->data, p->data_length ) ) return( -1 ); break; case JPEG_APP0 + 2: /* ICC profile. */ #ifdef DEBUG printf( "read_jpeg_header: seen %d bytes of APP2\n", p->data_length ); #endif /*DEBUG*/ if( p->data_length > 14 && im_isprefix( "ICC_PROFILE", (char *) p->data ) ) { /* cur_marker numbers from 1, according to * spec. */ int cur_marker = p->data[12] - 1; if( cur_marker >= 0 && cur_marker < MAX_APP2_SECTIONS ) { app2_data[cur_marker] = p->data + 14; app2_data_length[cur_marker] = p->data_length - 14; } } break; default: #ifdef DEBUG printf( "read_jpeg_header: seen %d bytes of data\n", p->data_length ); #endif /*DEBUG*/ break; } } /* Assemble ICC sections. */ data_length = 0; for( i = 0; i < MAX_APP2_SECTIONS && app2_data[i]; i++ ) data_length += app2_data_length[i]; if( data_length ) { unsigned char *data; int p; #ifdef DEBUG printf( "read_jpeg_header: assembled %d byte ICC profile\n", data_length ); #endif /*DEBUG*/ if( !(data = im_malloc( NULL, data_length )) ) return( -1 ); p = 0; for( i = 0; i < MAX_APP2_SECTIONS && app2_data[i]; i++ ) { memcpy( data + p, app2_data[i], app2_data_length[i] ); p += app2_data_length[i]; } if( im_meta_set_blob( out, IM_META_ICC_NAME, (im_callback_fn) im_free, data, data_length ) ) { im_free( data ); return( -1 ); } } return( 0 ); }
static int read_exif( IMAGE *im, void *data, int data_length ) { char *data_copy; /* Horrifyingly, some JPEGs have several APP1 sections. We must only * use the first one that starts "Exif.." */ if( ((char *) data)[0] != 'E' || ((char *) data)[1] != 'x' || ((char *) data)[2] != 'i' || ((char *) data)[3] != 'f' ) return( 0 ); if( im_header_get_typeof( im, IM_META_EXIF_NAME ) ) return( 0 ); /* Always attach a copy of the unparsed exif data. */ if( !(data_copy = im_malloc( NULL, data_length )) ) return( -1 ); memcpy( data_copy, data, data_length ); if( im_meta_set_blob( im, IM_META_EXIF_NAME, (im_callback_fn) im_free, data_copy, data_length ) ) { im_free( data_copy ); return( -1 ); } #ifdef HAVE_EXIF { ExifData *ed; if( !(ed = exif_data_new_from_data( data, data_length )) ) return( -1 ); if( ed->size > 0 ) { #ifdef DEBUG_VERBOSE show_tags( ed ); show_values( ed ); #endif /*DEBUG_VERBOSE*/ /* Attach informational fields for what we find. FIXME ... better to have this in the UI layer? Or we could attach non-human-readable tags here (int, double etc) and then move the human stuff to the UI layer? */ exif_data_foreach_content( ed, (ExifDataForeachContentFunc) attach_exif_content, im ); /* Look for resolution fields and use them to set the VIPS * xres/yres fields. */ set_vips_resolution( im, ed ); attach_thumbnail( im, ed ); } exif_data_free( ed ); } #endif /*HAVE_EXIF*/ return( 0 ); }