Beispiel #1
0
/**
 * im_lab_morph:
 * @in: input image
 * @out: output image
 * @mask: cast correction table
 * @L_offset: L adjustment
 * @L_scale: L adjustment
 * @a_scale: a scale
 * @b_scale: b scale
 *
 * Morph an image in CIELAB colour space. Useful for certain types of gamut
 * mapping, or correction of greyscales on some printers.
 *
 * We perform three adjustments:
 * 	
 * <itemizedlist>
 *   <listitem>
 *     <para>
 *       <emphasis>cast</emphasis>
 *
 * Pass in @mask containing CIELAB readings for a neutral greyscale. For
 * example:
 *
 * <tgroup cols='3' align='left' colsep='1' rowsep='1'>
 *   <tbody>
 *     <row>
 *       <entry>3</entry>
 *       <entry>4</entry>
 *     </row>
 *     <row>
 *       <entry>14.23</entry>
 *       <entry>4.8</entry>
 *       <entry>-3.95</entry>
 *     </row>
 *     <row>
 *       <entry>18.74</entry>
 *       <entry>2.76</entry>
 *       <entry>-2.62</entry>
 *     </row>
 *     <row>
 *       <entry>23.46</entry>
 *       <entry>1.4</entry>
 *       <entry>-1.95</entry>
 *     </row>
 *     <row>
 *       <entry>27.53</entry>
 *       <entry>1.76</entry>
 *       <entry>-2.01</entry>
 *     </row>
 *   </tbody>
 * </tgroup>
 *
 * Interpolation from this makes cast corrector. The top and tail are
 * interpolated towards [0, 0, 0] and [100, 0, 0], intermediate values are 
 * interpolated along straight lines fitted between the specified points. 
 * Rows may be in any order (ie. they need not be sorted on L*).
 *
 * Each pixel is displaced in a/b by the amount specified for that L in the
 * table.
 *     </para>
 *   </listitem>
 *   <listitem>
 *     <para>
 *       <emphasis>L*</emphasis>
 *	
 * Pass in scale and offset for L. L' = (L + offset) * scale.
 *     </para>
 *   </listitem>
 *   <listitem>
 *     <para>
 *       <emphasis>saturation</emphasis>
 *
 * scale a and b by these amounts, eg. 1.5 increases saturation. 
 *     </para>
 *   </listitem>
 * </itemizedlist>
 *
 * Find the top two by generating and printing a greyscale. Find the bottom
 * by printing a Macbeth and looking at a/b spread
 *
 * Returns: 0 on success, -1 on error.
 */
int
im_lab_morph( IMAGE *in, IMAGE *out,
	DOUBLEMASK *mask, 
	double L_offset, double L_scale, 
	double a_scale, double b_scale )
{
	Params *parm;

        /* Recurse for coded images.
         */
	if( in->Coding == IM_CODING_LABQ ) {
		IMAGE *t[2];

		if( im_open_local_array( out, t, 2, "im_lab_morph", "p" ) ||
			im_LabQ2Lab( in, t[0] ) ||
			im_lab_morph( t[0], t[1], 
				mask, L_offset, L_scale, a_scale, b_scale ) ||
			im_Lab2LabQ( t[1], out ) )
			return( -1 );

		return( 0 );
	}

	if( !(parm = IM_NEW( out, Params )) ||
		morph_init( parm,
			in, out, L_scale, L_offset, mask, a_scale, b_scale ) ) 
		return( -1 );

	return( im__colour_unary( "im_lab_morph", in, out, IM_TYPE_LAB,
		(im_wrapone_fn) morph_buffer, parm, NULL ) );
}
Beispiel #2
0
static int
morph_vec( im_object *argv )
{
	im_mask_object *mo = argv[2];
	double L_offset = *((double *) argv[3]);
	double L_scale = *((double *) argv[4]);
	double a_scale = *((double *) argv[5]);
	double b_scale = *((double *) argv[6]);

        return( im_lab_morph( argv[0], argv[1], 
		mo->mask, L_offset, L_scale, a_scale, b_scale ) );
}
Beispiel #3
0
/* Morph an image.
 */
int
im_lab_morph( IMAGE *in, IMAGE *out,
	DOUBLEMASK *mask, 
	double L_offset, double L_scale, 
	double a_scale, double b_scale )
{
	Params *parm;

        /* Recurse for coded images.
         */
	if( in->Coding == IM_CODING_LABQ ) {
		IMAGE *t1 = im_open_local( out, "im_lab_morph:1", "p" );
		IMAGE *t2 = im_open_local( out, "im_lab_morph:2", "p" );

		if( !t1 || !t2 ||
			im_LabQ2Lab( in, t1 ) ||
			im_lab_morph( t1, t2, 
				mask, L_offset, L_scale, a_scale, b_scale ) ||
			im_Lab2LabQ( t2, out ) )
			return( -1 );

		return( 0 );
	}

        if( in->Coding != IM_CODING_NONE ) {
		im_errormsg( "im_lab_morph: must be uncoded or IM_CODING_LABQ" ); 
		return( -1 );
	}
	if( in->BandFmt != IM_BANDFMT_FLOAT && in->BandFmt != IM_BANDFMT_DOUBLE ) {
		im_errormsg( "im_lab_morph: must be uncoded float or double" );
		return( -1 );
	}
	if( in->Bands != 3 ) {
		im_errormsg( "im_lab_morph: must be 3 bands" ); 
		return( -1 );
	}

	if( !(parm = IM_NEW( out, Params )) ||
		morph_init( parm,
			in, out, L_scale, L_offset, mask, a_scale, b_scale ) ) 
		return( -1 );

	if( im_cp_desc( out, in ) )
		return( -1 );
	out->Type = IM_TYPE_LAB;

	if( im_wrapone( in, out, 
		(im_wrapone_fn) morph_buffer, parm, NULL ) )
		return( -1 );

        return( 0 );
}
Beispiel #4
0
VALUE
img_lab_morph(VALUE obj, VALUE mask, VALUE l_offset, VALUE l_scale,
	VALUE a_scale, VALUE b_scale)
{
    DOUBLEMASK *dmask;

	GetImg(obj, data, im);
	OutImg(obj, new, data_new, im_new);

    mask_arg2mask(mask, NULL, &dmask);

	if( im_lab_morph(im, im_new, dmask, NUM2DBL(l_offset),
		NUM2DBL(l_scale), NUM2DBL(a_scale), NUM2DBL(b_scale)) )
		vips_lib_error();

    return new;
}