LabQ <-> Lab as classes
This commit is contained in:
parent
59513b6869
commit
2e1b8bb9ef
@ -28,6 +28,8 @@
|
||||
* 1/11/09
|
||||
* - gtkdoc
|
||||
* - cleanups
|
||||
* 20/9/12
|
||||
* - redo as a class
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -66,65 +68,91 @@
|
||||
|
||||
#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
|
||||
* 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 );
|
||||
}
|
@ -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 <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
|
||||
* 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 );
|
||||
}
|
@ -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 \
|
||||
|
@ -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, ... )
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
* 2/11/09
|
||||
* - gtkdoc
|
||||
* 20/9/12
|
||||
* redo as a class
|
||||
* - redo as a class
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
Loading…
Reference in New Issue
Block a user