LabQ <-> Lab as classes

This commit is contained in:
John Cupitt 2012-09-20 21:21:08 +01:00
parent 59513b6869
commit 2e1b8bb9ef
12 changed files with 182 additions and 128 deletions

View File

@ -28,6 +28,8 @@
* 1/11/09 * 1/11/09
* - gtkdoc * - gtkdoc
* - cleanups * - cleanups
* 20/9/12
* - redo as a class
*/ */
/* /*
@ -66,65 +68,91 @@
#include <vips/vips.h> #include <vips/vips.h>
#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 /* @(#) convert float Lab to packed Lab32 format 10 11 11 bits
* works only on buffers, not IMAGEs * works only on buffers, not IMAGEs
* Copyright 1993 K.Martinez * Copyright 1993 K.Martinez
* Modified: 3/5/93, 16/6/93 * Modified: 3/5/93, 16/6/93
*/ */
void static void
imb_Lab2LabQ( float *inp, unsigned char *outbuf, int n ) vips_Lab2LabQ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
{ {
float *f, fval; float *p = (float *) in[0];
int lsbs, intv;
int Xc;
unsigned char *out;
out = outbuf; float fval;
f = inp; int lsbs;
for( Xc = 0; Xc < n; Xc++) { int intv;
/* Scale L up to 10 bits. Add 0.5 rather than call IM_RINT for int i;
* speed. This will not round negatives correctly! But this
* does not matter, since L is >0. L*=100.0 -> 1023. 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 */ intv = 10.23 * p[0] + 0.5; /* scale L up to 10 bits */
if( intv > 1023 ) intv = VIPS_CLIP( 0, intv, 1023 );
intv = 1023;
if( intv < 0 )
intv = 0;
lsbs = (intv & 0x3) << 6; /* 00000011 -> 11000000 */ lsbs = (intv & 0x3) << 6; /* 00000011 -> 11000000 */
out[0] = (intv >> 2); /* drop bot 2 bits and store */ out[0] = (intv >> 2); /* drop bot 2 bits and store */
fval = 8.0 * f[1]; /* do a */ fval = 8.0 * p[1]; /* do a */
intv = IM_RINT( fval ); intv = VIPS_RINT( fval );
if( intv > 1023 ) intv = VIPS_CLIP( -1024, intv, 1023 );
intv = 1023;
else if( intv < -1024 )
intv = -1024;
/* Break into bits.
*/
lsbs |= (intv & 0x7) << 3; /* 00000111 -> 00111000 */ lsbs |= (intv & 0x7) << 3; /* 00000111 -> 00111000 */
out[1] = (intv >> 3); /* drop bot 3 bits & store */ out[1] = (intv >> 3); /* drop bot 3 bits & store */
fval = 8.0 * f[2]; /* do b */ fval = 8.0 * p[2]; /* do b */
intv = IM_RINT( fval ); intv = VIPS_RINT( fval );
if( intv > 1023 ) intv = VIPS_CLIP( -1024, intv, 1023 );
intv = 1023;
else if( intv < -1024 )
intv = -1024;
lsbs |= (intv & 0x7); lsbs |= (intv & 0x7);
out[2] = (intv >> 3); out[2] = (intv >> 3);
out[3] = lsbs; /* store lsb band */ out[3] = lsbs; /* store lsb band */
f += 3; p += 3;
out += 4; 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 * @in: input image
* @out: output image * @out: output image
* *
@ -135,26 +163,14 @@ imb_Lab2LabQ( float *inp, unsigned char *outbuf, int n )
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.
*/ */
int 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 ) || va_start( ap, out );
im_check_bands( "im_Lab2LabQ", in, 3 ) || result = vips_call_split( "Lab2LabQ", ap, in, out );
im_open_local_array( out, t, 1, "im_Lab2LabQ", "p" ) || va_end( ap );
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) )
return( -1 );
if( im_cp_desc( out, t[0] ) ) return( result );
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 );
} }

View File

@ -16,6 +16,8 @@
* - L* = 100.0 now handled correctly * - L* = 100.0 now handled correctly
* 2/11/09 * 2/11/09
* - gtkdoc * - gtkdoc
* 20/9/12
* - redo as a class
*/ */
/* /*
@ -53,6 +55,13 @@
#include <vips/vips.h> #include <vips/vips.h>
#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 /* imb_LabQ2Lab: CONVERT n pels from packed 32bit Lab to float values
* in a buffer * in a buffer
* ARGS: VipsPel *inp pointer to first byte of Lab32 buffer * ARGS: VipsPel *inp pointer to first byte of Lab32 buffer
@ -60,47 +69,76 @@
* int n number of pels to process * int n number of pels to process
* (C) K.Martinez 2/5/93 * (C) K.Martinez 2/5/93
*/ */
void static void
imb_LabQ2Lab( VipsPel *inp, float *outbuf, int n ) 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 l;
int lsbs; /* for lsbs byte */ int lsbs; /* for lsbs byte */
int c; /* counter */ int i; /* counter */
float *out;
/* Read input with a signed pointer to get signed ab easily. /* Read input with a signed pointer to get signed ab easily.
*/ */
b = (signed char *) inp; for( i = 0; i < width; i++ ) {
out = outbuf;
for( c = 0; c < n; c++ ) {
/* Get extra bits. /* Get extra bits.
*/ */
lsbs = ((unsigned char *) b)[3]; lsbs = ((unsigned char *) p)[3];
/* Build L. /* Build L.
*/ */
l = ((unsigned char *)b)[0]; l = ((unsigned char *)p)[0];
l = (l << 2) | (lsbs >> 6); l = (l << 2) | (lsbs >> 6);
out[0] = (float) l * (100.0 / 1023.0); q[0] = (float) l * (100.0 / 1023.0);
/* Build a. /* Build a.
*/ */
l = (b[1] << 3) | ((lsbs >> 3) & 0x7); l = (p[1] << 3) | ((lsbs >> 3) & 0x7);
out[1] = (float) l * 0.125; q[1] = (float) l * 0.125;
/* And b. /* And b.
*/ */
l = (b[2] << 3) | (lsbs & 0x7); l = (p[2] << 3) | (lsbs & 0x7);
out[2] = (float) l * 0.125; q[2] = (float) l * 0.125;
b += 4; p += 4;
out += 3; 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 * @in: input image
* @out: output image * @out: output image
* *
@ -111,21 +149,14 @@ imb_LabQ2Lab( VipsPel *inp, float *outbuf, int n )
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.
*/ */
int int
im_LabQ2Lab( IMAGE *in, IMAGE *out ) vips_LabQ2Lab( VipsImage *in, VipsImage **out, ... )
{ {
if( im_check_coding_labq( "im_LabQ2Lab", in ) ) va_list ap;
return( -1 ); int result;
if( im_cp_desc( out, in ) ) va_start( ap, out );
return( -1 ); result = vips_call_split( "LabQ2Lab", ap, in, out );
out->Bands = 3; va_end( ap );
out->Type = IM_TYPE_LAB;
out->BandFmt = IM_BANDFMT_FLOAT;
out->Coding = IM_CODING_NONE;
if( im_wrapone( in, out, return( result );
(im_wrapone_fn) imb_LabQ2Lab, NULL, NULL ) )
return( -1 );
return( 0 );
} }

View File

@ -16,10 +16,10 @@ libcolour_la_SOURCES = \
Yxy2XYZ.c \ Yxy2XYZ.c \
float2rad.c \ float2rad.c \
rad2float.c \ rad2float.c \
Lab2LabQ.c \
LabQ2Lab.c \
im_icc_transform.c \ im_icc_transform.c \
im_Lab2LabQ.c \
im_Lab2LabS.c \ im_Lab2LabS.c \
im_LabQ2Lab.c \
im_LabQ2LabS.c \ im_LabQ2LabS.c \
im_LabQ2disp.c \ im_LabQ2disp.c \
im_LabS2LabQ.c \ im_LabS2LabQ.c \

View File

@ -334,32 +334,6 @@ vips_LabS2LabQ( VipsImage *in, VipsImage **out, ... )
return( result ); 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 int
vips_Yxy2Lab( VipsImage *in, VipsImage **out, ... ) vips_Yxy2Lab( VipsImage *in, VipsImage **out, ... )
{ {

View File

@ -5,7 +5,7 @@
* 2/11/09 * 2/11/09
* - gtkdoc * - gtkdoc
* 20/9/12 * 20/9/12
* redo as a class * - redo as a class
*/ */
/* /*

View File

@ -2355,3 +2355,35 @@ im_rad2float( IMAGE *in, IMAGE *out )
return( 0 ); 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 );
}

View File

@ -164,9 +164,7 @@ float im_col_dE00(
float L1, float a1, float b1, float L2, float a2, float b2 ); float L1, float a1, float b1, float L2, float a2, float b2 );
int im_LabQ2XYZ( VipsImage *in, VipsImage *out ); int im_LabQ2XYZ( VipsImage *in, VipsImage *out );
int im_Lab2LabQ( VipsImage *in, VipsImage *out );
int im_Lab2LabS( 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_LabQ2LabS( VipsImage *in, VipsImage *out );
int im_LabS2LabQ( VipsImage *in, VipsImage *out ); int im_LabS2LabQ( VipsImage *in, VipsImage *out );
int im_LabS2Lab( VipsImage *in, VipsImage *out ); int im_LabS2Lab( VipsImage *in, VipsImage *out );

View File

@ -236,11 +236,12 @@ typedef struct {
} im_colour_temperature; } im_colour_temperature;
void imb_XYZ2Lab( float *, float *, int, 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_LabS2Lab( signed short *, float *, int );
void imb_Lab2LabS( float *, signed short *, int n ); 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_dmask_matrix( DOUBLEMASK *mask, double **matrix );
void im_copy_matrix_dmask( double **matrix, DOUBLEMASK *mask ); void im_copy_matrix_dmask( double **matrix, DOUBLEMASK *mask );

View File

@ -724,6 +724,8 @@ int im_XYZ2Yxy( VipsImage *in, VipsImage *out );
int im_Yxy2XYZ( VipsImage *in, VipsImage *out ); int im_Yxy2XYZ( VipsImage *in, VipsImage *out );
int im_float2rad( VipsImage *in, VipsImage *out ); int im_float2rad( VipsImage *in, VipsImage *out );
int im_rad2float( 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 /* ruby-vips uses this
*/ */

View File

@ -180,7 +180,7 @@ mask_draw_labq( Mask *mask )
mask->image_clip.width * 3, float )) ) mask->image_clip.width * 3, float )) )
return( -1 ); 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++ ) { for( y = 0; y < mask->image_clip.height; y++ ) {
VipsPel *to = IM_IMAGE_ADDR( DRAW( mask )->im, 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, VipsPel *mask_line = IM_IMAGE_ADDR( mask->mask_im,
mask->mask_clip.left, y + mask->mask_clip.top ); 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 ); 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 ); im_free( lab_buffer );

View File

@ -662,8 +662,8 @@ lr_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
/* Unpack two bits we want. /* Unpack two bits we want.
*/ */
imb_LabQ2Lab( pr, r, oreg->width ); vips__LabQ2Lab_vec( r, pr, oreg->width );
imb_LabQ2Lab( ps, s, oreg->width ); vips__LabQ2Lab_vec( s, ps, oreg->width );
/* Blend as floats. /* Blend as floats.
*/ */
@ -671,7 +671,7 @@ lr_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
/* Re-pack to output buffer. /* Re-pack to output buffer.
*/ */
imb_Lab2LabQ( inf->merge, q, oreg->width ); vips__Lab2LabQ_vec( q, inf->merge, oreg->width );
} }
return( 0 ); return( 0 );

View File

@ -593,8 +593,8 @@ tb_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
/* Unpack two bits we want. /* Unpack two bits we want.
*/ */
imb_LabQ2Lab( pr, r, oreg->width ); vips__LabQ2Lab_vec( r, pr, oreg->width );
imb_LabQ2Lab( ps, s, oreg->width ); vips__LabQ2Lab_vec( s, ps, oreg->width );
/* Blend as floats. /* Blend as floats.
*/ */
@ -602,7 +602,7 @@ tb_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
/* Re-pack to output buffer. /* Re-pack to output buffer.
*/ */
imb_Lab2LabQ( inf->merge, q, oreg->width ); vips__Lab2LabQ_vec( q, inf->merge, oreg->width );
} }
return( 0 ); return( 0 );