diff --git a/libvips/colour/im_Lab2LabQ.c b/libvips/colour/Lab2LabQ.c similarity index 56% rename from libvips/colour/im_Lab2LabQ.c rename to libvips/colour/Lab2LabQ.c index 66d2139c..7d081d74 100644 --- a/libvips/colour/im_Lab2LabQ.c +++ b/libvips/colour/Lab2LabQ.c @@ -28,6 +28,8 @@ * 1/11/09 * - gtkdoc * - cleanups + * 20/9/12 + * - redo as a class */ /* @@ -66,65 +68,91 @@ #include +#include "colour.h" + +typedef VipsColourCode VipsLab2LabQ; +typedef VipsColourCodeClass VipsLab2LabQClass; + +G_DEFINE_TYPE( VipsLab2LabQ, vips_Lab2LabQ, VIPS_TYPE_COLOUR_CODE ); + /* @(#) convert float Lab to packed Lab32 format 10 11 11 bits * works only on buffers, not IMAGEs * Copyright 1993 K.Martinez * Modified: 3/5/93, 16/6/93 */ -void -imb_Lab2LabQ( float *inp, unsigned char *outbuf, int n ) +static void +vips_Lab2LabQ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) { - float *f, fval; - int lsbs, intv; - int Xc; - unsigned char *out; + float *p = (float *) in[0]; - out = outbuf; - f = inp; - for( Xc = 0; Xc < n; Xc++) { - /* Scale L up to 10 bits. Add 0.5 rather than call IM_RINT for - * speed. This will not round negatives correctly! But this - * does not matter, since L is >0. L*=100.0 -> 1023. + float fval; + int lsbs; + int intv; + int i; + + for( i = 0; i < width; i++) { + /* Scale L up to 10 bits. Add 0.5 rather than call VIPS_RINT + * for speed. This will not round negatives correctly! But + * this does not matter, since L is >0. L*=100.0 -> 1023. */ - intv = 10.23 * f[0] + 0.5; /* scale L up to 10 bits */ - if( intv > 1023 ) - intv = 1023; - if( intv < 0 ) - intv = 0; + intv = 10.23 * p[0] + 0.5; /* scale L up to 10 bits */ + intv = VIPS_CLIP( 0, intv, 1023 ); lsbs = (intv & 0x3) << 6; /* 00000011 -> 11000000 */ out[0] = (intv >> 2); /* drop bot 2 bits and store */ - fval = 8.0 * f[1]; /* do a */ - intv = IM_RINT( fval ); - if( intv > 1023 ) - intv = 1023; - else if( intv < -1024 ) - intv = -1024; - - /* Break into bits. - */ + fval = 8.0 * p[1]; /* do a */ + intv = VIPS_RINT( fval ); + intv = VIPS_CLIP( -1024, intv, 1023 ); lsbs |= (intv & 0x7) << 3; /* 00000111 -> 00111000 */ out[1] = (intv >> 3); /* drop bot 3 bits & store */ - fval = 8.0 * f[2]; /* do b */ - intv = IM_RINT( fval ); - if( intv > 1023 ) - intv = 1023; - else if( intv < -1024 ) - intv = -1024; - + fval = 8.0 * p[2]; /* do b */ + intv = VIPS_RINT( fval ); + intv = VIPS_CLIP( -1024, intv, 1023 ); lsbs |= (intv & 0x7); out[2] = (intv >> 3); out[3] = lsbs; /* store lsb band */ - f += 3; + p += 3; out += 4; } } +void +vips__Lab2LabQ_vec( VipsPel *out, float *in, int width ) +{ + vips_Lab2LabQ_line( NULL, out, (VipsPel **) &in, width ); +} + +static void +vips_Lab2LabQ_class_init( VipsLab2LabQClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + VipsColourCodeClass *code_class = VIPS_COLOUR_CODE_CLASS( class ); + + object_class->nickname = "Lab2LabQ"; + object_class->description = _( "transform float Lab to LabQ coding" ); + + colour_class->process_line = vips_Lab2LabQ_line; + colour_class->coding = VIPS_CODING_LABQ; + colour_class->interpretation = VIPS_INTERPRETATION_LABQ; + colour_class->format = VIPS_FORMAT_UCHAR; + colour_class->bands = 4; + + code_class->input_coding = VIPS_CODING_NONE; + code_class->input_format = VIPS_FORMAT_FLOAT; + code_class->input_bands = 3; +} + +static void +vips_Lab2LabQ_init( VipsLab2LabQ *Lab2LabQ ) +{ +} + /** - * im_Lab2LabQ: + * vips_Lab2LabQ: * @in: input image * @out: output image * @@ -135,26 +163,14 @@ imb_Lab2LabQ( float *inp, unsigned char *outbuf, int n ) * Returns: 0 on success, -1 on error. */ int -im_Lab2LabQ( IMAGE *in, IMAGE *out ) +vips_Lab2LabQ( VipsImage *in, VipsImage **out, ... ) { - IMAGE *t[1]; + va_list ap; + int result; - if( im_check_uncoded( "im_Lab2LabQ", in ) || - im_check_bands( "im_Lab2LabQ", in, 3 ) || - im_open_local_array( out, t, 1, "im_Lab2LabQ", "p" ) || - im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ) - return( -1 ); + va_start( ap, out ); + result = vips_call_split( "Lab2LabQ", ap, in, out ); + va_end( ap ); - if( im_cp_desc( out, t[0] ) ) - return( -1 ); - out->Bands = 4; - out->Type = IM_TYPE_LABQ; - out->BandFmt = IM_BANDFMT_UCHAR; - out->Coding = IM_CODING_LABQ; - - if( im_wrapone( t[0], out, - (im_wrapone_fn) imb_Lab2LabQ, NULL, NULL ) ) - return( -1 ); - - return( 0 ); + return( result ); } diff --git a/libvips/colour/im_LabQ2Lab.c b/libvips/colour/LabQ2Lab.c similarity index 55% rename from libvips/colour/im_LabQ2Lab.c rename to libvips/colour/LabQ2Lab.c index 674704e9..827f31d1 100644 --- a/libvips/colour/im_LabQ2Lab.c +++ b/libvips/colour/LabQ2Lab.c @@ -16,6 +16,8 @@ * - L* = 100.0 now handled correctly * 2/11/09 * - gtkdoc + * 20/9/12 + * - redo as a class */ /* @@ -53,6 +55,13 @@ #include +#include "colour.h" + +typedef VipsColourCode VipsLabQ2Lab; +typedef VipsColourCodeClass VipsLabQ2LabClass; + +G_DEFINE_TYPE( VipsLabQ2Lab, vips_LabQ2Lab, VIPS_TYPE_COLOUR_CODE ); + /* imb_LabQ2Lab: CONVERT n pels from packed 32bit Lab to float values * in a buffer * ARGS: VipsPel *inp pointer to first byte of Lab32 buffer @@ -60,47 +69,76 @@ * int n number of pels to process * (C) K.Martinez 2/5/93 */ -void -imb_LabQ2Lab( VipsPel *inp, float *outbuf, int n ) +static void +vips_LabQ2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width ) { - signed char *b; /* to read input bytes */ + signed char *p = (signed char *) in[0]; + float *q = (float *) out; + int l; int lsbs; /* for lsbs byte */ - int c; /* counter */ - float *out; + int i; /* counter */ /* Read input with a signed pointer to get signed ab easily. */ - b = (signed char *) inp; - out = outbuf; - for( c = 0; c < n; c++ ) { + for( i = 0; i < width; i++ ) { /* Get extra bits. */ - lsbs = ((unsigned char *) b)[3]; + lsbs = ((unsigned char *) p)[3]; /* Build L. */ - l = ((unsigned char *)b)[0]; + l = ((unsigned char *)p)[0]; l = (l << 2) | (lsbs >> 6); - out[0] = (float) l * (100.0 / 1023.0); + q[0] = (float) l * (100.0 / 1023.0); /* Build a. */ - l = (b[1] << 3) | ((lsbs >> 3) & 0x7); - out[1] = (float) l * 0.125; + l = (p[1] << 3) | ((lsbs >> 3) & 0x7); + q[1] = (float) l * 0.125; /* And b. */ - l = (b[2] << 3) | (lsbs & 0x7); - out[2] = (float) l * 0.125; + l = (p[2] << 3) | (lsbs & 0x7); + q[2] = (float) l * 0.125; - b += 4; - out += 3; + p += 4; + q += 3; } } +void +vips__LabQ2Lab_vec( float *out, VipsPel *in, int width ) +{ + vips_LabQ2Lab_line( NULL, (VipsPel *) out, &in, width ); +} + +static void +vips_LabQ2Lab_class_init( VipsLabQ2LabClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class ); + VipsColourCodeClass *code_class = VIPS_COLOUR_CODE_CLASS( class ); + + object_class->nickname = "LabQ2Lab"; + object_class->description = _( "unpack a LabQ image to float Lab" ); + + colour_class->process_line = vips_LabQ2Lab_line; + colour_class->coding = VIPS_CODING_NONE; + colour_class->interpretation = VIPS_INTERPRETATION_LAB; + colour_class->format = VIPS_FORMAT_FLOAT; + colour_class->bands = 3; + + code_class->input_coding = VIPS_CODING_LABQ; +} + +static void +vips_LabQ2Lab_init( VipsLabQ2Lab *LabQ2Lab ) +{ +} + /** - * im_LabQ2Lab: + * vips_LabQ2Lab: * @in: input image * @out: output image * @@ -111,21 +149,14 @@ imb_LabQ2Lab( VipsPel *inp, float *outbuf, int n ) * Returns: 0 on success, -1 on error. */ int -im_LabQ2Lab( IMAGE *in, IMAGE *out ) +vips_LabQ2Lab( VipsImage *in, VipsImage **out, ... ) { - if( im_check_coding_labq( "im_LabQ2Lab", in ) ) - return( -1 ); + va_list ap; + int result; - if( im_cp_desc( out, in ) ) - return( -1 ); - out->Bands = 3; - out->Type = IM_TYPE_LAB; - out->BandFmt = IM_BANDFMT_FLOAT; - out->Coding = IM_CODING_NONE; + va_start( ap, out ); + result = vips_call_split( "LabQ2Lab", ap, in, out ); + va_end( ap ); - if( im_wrapone( in, out, - (im_wrapone_fn) imb_LabQ2Lab, NULL, NULL ) ) - return( -1 ); - - return( 0 ); + return( result ); } diff --git a/libvips/colour/Makefile.am b/libvips/colour/Makefile.am index 2323cc1f..8aedb450 100644 --- a/libvips/colour/Makefile.am +++ b/libvips/colour/Makefile.am @@ -16,10 +16,10 @@ libcolour_la_SOURCES = \ Yxy2XYZ.c \ float2rad.c \ rad2float.c \ + Lab2LabQ.c \ + LabQ2Lab.c \ im_icc_transform.c \ - im_Lab2LabQ.c \ im_Lab2LabS.c \ - im_LabQ2Lab.c \ im_LabQ2LabS.c \ im_LabQ2disp.c \ im_LabS2LabQ.c \ diff --git a/libvips/colour/colour_funcs.c b/libvips/colour/colour_funcs.c index f34bc77f..bd71777b 100644 --- a/libvips/colour/colour_funcs.c +++ b/libvips/colour/colour_funcs.c @@ -334,32 +334,6 @@ vips_LabS2LabQ( VipsImage *in, VipsImage **out, ... ) return( result ); } -int -vips_LabQ2Lab( VipsImage *in, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "im_LabQ2Lab", ap, in, out ); - va_end( ap ); - - return( result ); -} - -int -vips_Lab2LabQ( VipsImage *in, VipsImage **out, ... ) -{ - va_list ap; - int result; - - va_start( ap, out ); - result = vips_call_split( "im_Lab2LabQ", ap, in, out ); - va_end( ap ); - - return( result ); -} - int vips_Yxy2Lab( VipsImage *in, VipsImage **out, ... ) { diff --git a/libvips/colour/float2rad.c b/libvips/colour/float2rad.c index 5e92acb4..90b4d8c3 100644 --- a/libvips/colour/float2rad.c +++ b/libvips/colour/float2rad.c @@ -5,7 +5,7 @@ * 2/11/09 * - gtkdoc * 20/9/12 - * redo as a class + * - redo as a class */ /* diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 9e0086b0..fab13a61 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -2355,3 +2355,35 @@ im_rad2float( IMAGE *in, IMAGE *out ) return( 0 ); } + +int +im_Lab2LabQ( IMAGE *in, IMAGE *out ) +{ + VipsImage *x; + + if( vips_Lab2LabQ( in, &x, NULL ) ) + return( -1 ); + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} + +int +im_LabQ2Lab( IMAGE *in, IMAGE *out ) +{ + VipsImage *x; + + if( vips_LabQ2Lab( in, &x, NULL ) ) + return( -1 ); + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} diff --git a/libvips/include/vips/colour.h b/libvips/include/vips/colour.h index 55a58857..a90f39df 100644 --- a/libvips/include/vips/colour.h +++ b/libvips/include/vips/colour.h @@ -164,9 +164,7 @@ float im_col_dE00( float L1, float a1, float b1, float L2, float a2, float b2 ); int im_LabQ2XYZ( VipsImage *in, VipsImage *out ); -int im_Lab2LabQ( VipsImage *in, VipsImage *out ); int im_Lab2LabS( VipsImage *in, VipsImage *out ); -int im_LabQ2Lab( VipsImage *in, VipsImage *out ); int im_LabQ2LabS( VipsImage *in, VipsImage *out ); int im_LabS2LabQ( VipsImage *in, VipsImage *out ); int im_LabS2Lab( VipsImage *in, VipsImage *out ); diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 57197a1f..f6392301 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -236,11 +236,12 @@ typedef struct { } im_colour_temperature; void imb_XYZ2Lab( float *, float *, int, im_colour_temperature * ); -void imb_LabQ2Lab( VipsPel *, float *, int ); -void imb_Lab2LabQ( float *, VipsPel *, int ); void imb_LabS2Lab( signed short *, float *, int ); void imb_Lab2LabS( float *, signed short *, int n ); +void vips__Lab2LabQ_vec( VipsPel *out, float *in, int width ); +void vips__LabQ2Lab_vec( float *out, VipsPel *in, int width ); + void im_copy_dmask_matrix( DOUBLEMASK *mask, double **matrix ); void im_copy_matrix_dmask( double **matrix, DOUBLEMASK *mask ); diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index af4ec8bc..05938b3c 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -724,6 +724,8 @@ int im_XYZ2Yxy( VipsImage *in, VipsImage *out ); int im_Yxy2XYZ( VipsImage *in, VipsImage *out ); int im_float2rad( VipsImage *in, VipsImage *out ); int im_rad2float( VipsImage *in, VipsImage *out ); +int im_Lab2LabQ( VipsImage *in, VipsImage *out ); +int im_LabQ2Lab( VipsImage *in, VipsImage *out ); /* ruby-vips uses this */ diff --git a/libvips/inplace/im_draw_mask.c b/libvips/inplace/im_draw_mask.c index fd230b2f..0c862789 100644 --- a/libvips/inplace/im_draw_mask.c +++ b/libvips/inplace/im_draw_mask.c @@ -180,7 +180,7 @@ mask_draw_labq( Mask *mask ) mask->image_clip.width * 3, float )) ) return( -1 ); - imb_LabQ2Lab( DRAW( mask )->ink, ink_buffer, 1 ); + vips__LabQ2Lab_vec( ink_buffer, DRAW( mask )->ink, 1 ); for( y = 0; y < mask->image_clip.height; y++ ) { VipsPel *to = IM_IMAGE_ADDR( DRAW( mask )->im, @@ -188,9 +188,9 @@ mask_draw_labq( Mask *mask ) VipsPel *mask_line = IM_IMAGE_ADDR( mask->mask_im, mask->mask_clip.left, y + mask->mask_clip.top ); - imb_LabQ2Lab( to, lab_buffer, mask->image_clip.width ); + vips__LabQ2Lab_vec( lab_buffer, to, mask->image_clip.width ); DBLEND( float, lab_buffer, ink_buffer ); - imb_Lab2LabQ( lab_buffer, to, mask->image_clip.width ); + vips__Lab2LabQ_vec( to, lab_buffer, mask->image_clip.width ); } im_free( lab_buffer ); diff --git a/libvips/mosaicing/im_lrmerge.c b/libvips/mosaicing/im_lrmerge.c index 61f8495c..3baa8b82 100644 --- a/libvips/mosaicing/im_lrmerge.c +++ b/libvips/mosaicing/im_lrmerge.c @@ -662,8 +662,8 @@ lr_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg ) /* Unpack two bits we want. */ - imb_LabQ2Lab( pr, r, oreg->width ); - imb_LabQ2Lab( ps, s, oreg->width ); + vips__LabQ2Lab_vec( r, pr, oreg->width ); + vips__LabQ2Lab_vec( s, ps, oreg->width ); /* Blend as floats. */ @@ -671,7 +671,7 @@ lr_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg ) /* Re-pack to output buffer. */ - imb_Lab2LabQ( inf->merge, q, oreg->width ); + vips__Lab2LabQ_vec( q, inf->merge, oreg->width ); } return( 0 ); diff --git a/libvips/mosaicing/im_tbmerge.c b/libvips/mosaicing/im_tbmerge.c index f1f43008..2547e0eb 100644 --- a/libvips/mosaicing/im_tbmerge.c +++ b/libvips/mosaicing/im_tbmerge.c @@ -593,8 +593,8 @@ tb_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg ) /* Unpack two bits we want. */ - imb_LabQ2Lab( pr, r, oreg->width ); - imb_LabQ2Lab( ps, s, oreg->width ); + vips__LabQ2Lab_vec( r, pr, oreg->width ); + vips__LabQ2Lab_vec( s, ps, oreg->width ); /* Blend as floats. */ @@ -602,7 +602,7 @@ tb_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg ) /* Re-pack to output buffer. */ - imb_Lab2LabQ( inf->merge, q, oreg->width ); + vips__Lab2LabQ_vec( q, inf->merge, oreg->width ); } return( 0 );