remove disp stuff, just sRGB now

all the old monitor calibration stuff is gone, we only support sRGB now

im_Lab2disp() etc. have become vips_Lab2sRGB() etc.

compatibility macros keep old code compiling
This commit is contained in:
John Cupitt 2012-09-24 11:23:32 +01:00
parent 2ce7bc9618
commit f8dddf23a9
21 changed files with 435 additions and 504 deletions

View File

@ -2,7 +2,7 @@
- redone im_Lab2XYZ(), im_XYZ2Lab(), im_Lab2LCh(), im_LCh2Lab(), im_UCS2LCh, - redone im_Lab2XYZ(), im_XYZ2Lab(), im_Lab2LCh(), im_LCh2Lab(), im_UCS2LCh,
im_LCh2UCS(), im_XYZ2Yxy(), im_Yxy2XYZ(), im_float2rad(), im_rad2float(), im_LCh2UCS(), im_XYZ2Yxy(), im_Yxy2XYZ(), im_float2rad(), im_rad2float(),
im_Lab2LabQ(), im_LabQ2Lab(), im_Lab2LabS(), im_LabS2Lab(), im_LabQ2LabS(), im_Lab2LabQ(), im_LabQ2Lab(), im_Lab2LabS(), im_LabS2Lab(), im_LabQ2LabS(),
im_LabS2LabQ(), im_LabQ2disp() as classes im_LabS2LabQ(), im_LabQ2disp(), im_XYZ2disp(), im_disp2XYZ() as classes
13/9/12 started 7.30.3 13/9/12 started 7.30.3
- linecache sized itself too large - linecache sized itself too large

View File

@ -96,11 +96,14 @@ vips_LCh2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
void void
vips_col_Ch2ab( float C, float h, float *a, float *b ) vips_col_Ch2ab( float C, float h, float *a, float *b )
{ {
float in[3], out[3]; float in[3];
float out[3];
float *x;
in[1] = C; in[1] = C;
in[2] = h; in[2] = h;
vips_LCh2Lab_line( NULL, (VipsPel *) out, (VipsPel **) &in, 1 ); x = in;
vips_LCh2Lab_line( NULL, (VipsPel *) out, (VipsPel **) &x, 1 );
*a = out[1]; *a = out[1];
*b = out[2]; *b = out[2];
} }

View File

@ -230,17 +230,20 @@ vips_Lab2XYZ( VipsImage *in, VipsImage **out, ... )
void void
vips_col_Lab2XYZ( float L, float a, float b, float *X, float *Y, float *Z ) vips_col_Lab2XYZ( float L, float a, float b, float *X, float *Y, float *Z )
{ {
float in[3], out[3]; float in[3];
float *x;
float out[3];
VipsLab2XYZ Lab2XYZ; VipsLab2XYZ Lab2XYZ;
in[0] = L; in[0] = L;
in[1] = a; in[1] = a;
in[2] = b; in[2] = b;
x = in;
Lab2XYZ.X0 = VIPS_D65_X0; Lab2XYZ.X0 = VIPS_D65_X0;
Lab2XYZ.Y0 = VIPS_D65_Y0; Lab2XYZ.Y0 = VIPS_D65_Y0;
Lab2XYZ.Z0 = VIPS_D65_Z0; Lab2XYZ.Z0 = VIPS_D65_Z0;
vips_Lab2XYZ_line( (VipsColour *) &Lab2XYZ, vips_Lab2XYZ_line( (VipsColour *) &Lab2XYZ,
(VipsPel *) out, (VipsPel **) &in, 1 ); (VipsPel *) out, (VipsPel **) &x, 1 );
*X = out[0]; *X = out[0];
*Y = out[1]; *Y = out[1];
*Z = out[2]; *Z = out[2];

View File

@ -47,6 +47,7 @@
#include <math.h> #include <math.h>
#include <vips/vips.h> #include <vips/vips.h>
#include <vips/internal.h>
#include "colour.h" #include "colour.h"
@ -82,6 +83,23 @@ struct im_col_display {
float d_P; /* 'Picture' (like contrast) */ float d_P; /* 'Picture' (like contrast) */
}; };
/* Structure for holding the lookup tables for XYZ<=>rgb conversion.
* Also holds the luminance to XYZ matrix and the inverse one.
*/
struct im_col_tab_disp {
/*< private >*/
float t_Yr2r[1501]; /* Conversion of Yr to r */
float t_Yg2g[1501]; /* Conversion of Yg to g */
float t_Yb2b[1501]; /* Conversion of Yb to b */
float t_r2Yr[1501]; /* Conversion of r to Yr */
float t_g2Yg[1501]; /* Conversion of g to Yg */
float t_b2Yb[1501]; /* Conversion of b to Yb */
float mat_XYZ2lum[3][3]; /* XYZ to Yr, Yg, Yb matrix */
float mat_lum2XYZ[3][3]; /* Yr, Yg, Yb to XYZ matrix */
float rstep, gstep, bstep;
float ristep, gistep, bistep;
};
/* Do our own indexing of the arrays below to make sure we get efficient mults. /* Do our own indexing of the arrays below to make sure we get efficient mults.
*/ */
#define INDEX( L, A, B ) (L + (A << 6) + (B << 12)) #define INDEX( L, A, B ) (L + (A << 6) + (B << 12))
@ -115,8 +133,9 @@ static VipsPel vips_blue[64 * 64 * 64];
/* Make look_up tables for the Yr,Yb,Yg <=> r,g,b conversions. /* Make look_up tables for the Yr,Yb,Yg <=> r,g,b conversions.
*/ */
static void * static void *
calcul_tables( struct im_col_tab_disp *table ) calcul_tables( void *client )
{ {
struct im_col_tab_disp *table = client;
struct im_col_display *d = &srgb_profile; struct im_col_display *d = &srgb_profile;
int i, j; int i, j;
@ -253,10 +272,11 @@ vips_col_sRGB2XYZ( int r, int g, int b, float *X, float *Y, float *Z )
* contain an approximation of the right colour. * contain an approximation of the right colour.
*/ */
int int
vips_col_XYZ2rgb( float X, float Y, float Z, vips_col_XYZ2sRGB( float X, float Y, float Z,
int *r_ret, int *g_ret, int *b_ret, int *r_ret, int *g_ret, int *b_ret,
int *or_ret ) int *or_ret )
{ {
struct im_col_display *d = &srgb_profile;
struct im_col_tab_disp *table = vips_col_make_tables_RGB(); struct im_col_tab_disp *table = vips_col_make_tables_RGB();
float *mat = &table->mat_XYZ2lum[0][0]; float *mat = &table->mat_XYZ2lum[0][0];
@ -291,24 +311,15 @@ vips_col_XYZ2rgb( float X, float Y, float Z,
* luminosity. * luminosity.
*/ */
Yint = (Yr - d->d_Y0R) / table->rstep; Yint = (Yr - d->d_Y0R) / table->rstep;
if( Yint > 1500 ) { Yint = VIPS_CLIP( 0, Yint, 1500 );
or = 1;
Yint = 1500;
}
r = IM_RINT( table->t_Yr2r[Yint] ); r = IM_RINT( table->t_Yr2r[Yint] );
Yint = (Yg - d->d_Y0G) / table->gstep; Yint = (Yg - d->d_Y0G) / table->gstep;
if( Yint > 1500 ) { Yint = VIPS_CLIP( 0, Yint, 1500 );
or = 1;
Yint = 1500;
}
g = IM_RINT( table->t_Yg2g[Yint] ); g = IM_RINT( table->t_Yg2g[Yint] );
Yint = (Yb - d->d_Y0B) / table->bstep; Yint = (Yb - d->d_Y0B) / table->bstep;
if( Yint > 1500 ) { Yint = VIPS_CLIP( 0, Yint, 1500 );
or = 1;
Yint = 1500;
}
b = IM_RINT( table->t_Yb2b[Yint] ); b = IM_RINT( table->t_Yb2b[Yint] );
*r_ret = r; *r_ret = r;
@ -322,8 +333,8 @@ vips_col_XYZ2rgb( float X, float Y, float Z,
/* Build Lab->disp tables. /* Build Lab->disp tables.
*/ */
static void static void *
build_tables( void ) build_tables( void *client )
{ {
int l, a, b; int l, a, b;
int t; int t;
@ -341,7 +352,7 @@ build_tables( void )
int oflow; int oflow;
vips_col_Lab2XYZ( L, A, B, &X, &Y, &Z ); vips_col_Lab2XYZ( L, A, B, &X, &Y, &Z );
vips_col_XYZ2rgb( X, Y, Z, vips_col_XYZ2sRGB( X, Y, Z,
&rb, &gb, &bb, &oflow ); &rb, &gb, &bb, &oflow );
t = INDEX( l, a, b ); t = INDEX( l, a, b );
@ -351,6 +362,8 @@ build_tables( void )
} }
} }
} }
return( NULL );
} }
static void static void
@ -358,7 +371,7 @@ vips_col_make_tables_LabQ2sRGB( void )
{ {
static GOnce once = G_ONCE_INIT; static GOnce once = G_ONCE_INIT;
(void) g_once( &once, calcul_tables, NULL ); (void) g_once( &once, build_tables, NULL );
} }
/* Process a buffer of data. /* Process a buffer of data.

View File

@ -22,12 +22,12 @@ libcolour_la_SOURCES = \
LabS2LabQ.c \ LabS2LabQ.c \
LabQ2LabS.c \ LabQ2LabS.c \
LabQ2sRGB.c \ LabQ2sRGB.c \
XYZ2sRGB.c \
sRGB2XYZ.c \
im_icc_transform.c \ im_icc_transform.c \
im_lab_morph.c \ im_lab_morph.c \
im_XYZ2disp.c \
im_dE00_fromLab.c \ im_dE00_fromLab.c \
im_dECMC_fromLab.c \ im_dECMC_fromLab.c \
im_dE_fromLab.c \ im_dE_fromLab.c
im_disp2XYZ.c
INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@ INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

View File

@ -172,17 +172,20 @@ vips_XYZ2Lab_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
void void
vips_col_XYZ2Lab( float X, float Y, float Z, float *L, float *a, float *b ) vips_col_XYZ2Lab( float X, float Y, float Z, float *L, float *a, float *b )
{ {
float in[3], out[3]; float in[3];
float out[3];
float *x;
VipsXYZ2Lab XYZ2Lab; VipsXYZ2Lab XYZ2Lab;
in[0] = X; in[0] = X;
in[1] = Y; in[1] = Y;
in[2] = Z; in[2] = Z;
x = in;
XYZ2Lab.X0 = VIPS_D65_X0; XYZ2Lab.X0 = VIPS_D65_X0;
XYZ2Lab.Y0 = VIPS_D65_Y0; XYZ2Lab.Y0 = VIPS_D65_Y0;
XYZ2Lab.Z0 = VIPS_D65_Z0; XYZ2Lab.Z0 = VIPS_D65_Z0;
vips_XYZ2Lab_line( (VipsColour *) &XYZ2Lab, vips_XYZ2Lab_line( (VipsColour *) &XYZ2Lab,
(VipsPel *) out, (VipsPel **) &in, 1 ); (VipsPel *) out, (VipsPel **) &x, 1 );
*L = out[0]; *L = out[0];
*a = out[1]; *a = out[1];
*b = out[2]; *b = out[2];

148
libvips/colour/XYZ2sRGB.c Normal file
View File

@ -0,0 +1,148 @@
/* Turn XYZ files into displayable rgb.
*
* Author: J-P. Laurent
* Modified:
* 15/11/94 JC
* - error message added
* - out->Type set to IM_TYPE_RGB
* - memory leak fixed
* 16/11/94 JC
* - uses im_wrapone()
* 15/2/95 JC
* - oops! now uses PEL, not float for output pointer
* 2/1/96 JC
* - sometimes produced incorrect result at extrema
* - reformatted
* - now uses IM_RINT() and clip()
* 18/9/96 JC
* - some speed-ups ... 3x faster
* - slightly less accurate, but who cares
* - added out-of-mem check for table build
* 21/9/12
* - redone as a class
* - sRGB only, support for other RGBs is now via lcms
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include "colour.h"
typedef VipsColourCode VipsXYZ2sRGB;
typedef VipsColourCodeClass VipsXYZ2sRGBClass;
G_DEFINE_TYPE( VipsXYZ2sRGB, vips_XYZ2sRGB, VIPS_TYPE_COLOUR_CODE );
/* Process a buffer of data.
*/
static void
vips_XYZ2sRGB_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
{
float *p = (float *) in[0];
VipsPel *q = (VipsPel *) out;
int i;
for( i = 0; i < width; i++ ) {
float X = p[0];
float Y = p[1];
float Z = p[2];
int r, g, b;
int or;
vips_col_XYZ2sRGB( X, Y, Z, &r, &g, &b, &or );
p += 3;
q[0] = r;
q[1] = g;
q[2] = b;
q += 3;
}
}
static void
vips_XYZ2sRGB_class_init( VipsXYZ2sRGBClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class );
VipsColourCodeClass *code_class = VIPS_COLOUR_CODE_CLASS( class );
object_class->nickname = "XYZ2sRGB";
object_class->description = _( "convert an XYZ image to sRGB" );
colour_class->process_line = vips_XYZ2sRGB_line;
colour_class->coding = VIPS_CODING_NONE;
colour_class->interpretation = VIPS_INTERPRETATION_sRGB;
colour_class->format = VIPS_FORMAT_UCHAR;
colour_class->bands = 3;
code_class->input_coding = VIPS_CODING_NONE;
code_class->input_bands = 3;
code_class->input_format = VIPS_FORMAT_FLOAT;
}
static void
vips_XYZ2sRGB_init( VipsXYZ2sRGB *XYZ2sRGB )
{
}
/**
* vips_XYZ2sRGB:
* @in: input image
* @out: output image
*
* Convert an XYZ image to sRGB.
*
* See also: im_LabS2LabQ(), im_XYZ2sRGB(), im_rad2float().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_XYZ2sRGB( VipsImage *in, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "XYZ2sRGB", ap, in, out );
va_end( ap );
return( result );
}

View File

@ -389,6 +389,9 @@ vips_colour_operation_init( void )
extern GType vips_Lab2LabS_get_type( void ); extern GType vips_Lab2LabS_get_type( void );
extern GType vips_rad2float_get_type( void ); extern GType vips_rad2float_get_type( void );
extern GType vips_float2rad_get_type( void ); extern GType vips_float2rad_get_type( void );
extern GType vips_LabQ2sRGB_get_type( void );
extern GType vips_XYZ2sRGB_get_type( void );
extern GType vips_sRGB2XYZ_get_type( void );
vips_Lab2XYZ_get_type(); vips_Lab2XYZ_get_type();
vips_XYZ2Lab_get_type(); vips_XYZ2Lab_get_type();
@ -406,4 +409,7 @@ vips_colour_operation_init( void )
vips_Lab2LabS_get_type(); vips_Lab2LabS_get_type();
vips_rad2float_get_type(); vips_rad2float_get_type();
vips_float2rad_get_type(); vips_float2rad_get_type();
vips_LabQ2sRGB_get_type();
vips_XYZ2sRGB_get_type();
vips_sRGB2XYZ_get_type();
} }

View File

@ -294,20 +294,6 @@ im_col_dE00( float L1, float a1, float b1,
/* Quick hack wrappers for common colour functions in the new style. /* Quick hack wrappers for common colour functions in the new style.
*/ */
int
vips_LabQ2disp( VipsImage *in, VipsImage **out,
struct im_col_display *disp, ... )
{
va_list ap;
int result;
va_start( ap, disp );
result = vips_call_split( "im_LabQ2disp", ap, in, out, disp );
va_end( ap );
return( result );
}
int int
vips_argb2rgba( VipsImage *in, VipsImage **out, ... ) vips_argb2rgba( VipsImage *in, VipsImage **out, ... )
{ {
@ -347,21 +333,6 @@ vips_UCS2XYZ( VipsImage *in, VipsImage **out, ... )
return( result ); return( result );
} }
int
vips_XYZ2disp( VipsImage *in, VipsImage **out,
struct im_col_display *disp, ... )
{
va_list ap;
int result;
va_start( ap, disp );
result = vips_call_split( "im_XYZ2disp", ap, in, out, disp );
va_end( ap );
return( result );
}
int int
im__colour_unary( const char *domain, im__colour_unary( const char *domain,
IMAGE *in, IMAGE *out, VipsType type, IMAGE *in, IMAGE *out, VipsType type,

View File

@ -158,53 +158,6 @@ im_XYZ2UCS( IMAGE *in, IMAGE *out )
return( 0 ); return( 0 );
} }
/**
* im_XYZ2sRGB:
* @in: input image
* @out: output image
*
* Convert an image from XYZ to sRGB. The conversion is supposed to be quick
* rather than accurate. Use an ICC profile with im_icc_transform() for more
* precision.
*
* See also: im_icc_transform.
*
* Returns: 0 on success, -1 on error.
*/
int
im_XYZ2sRGB( IMAGE *in, IMAGE *out )
{
if( im_XYZ2disp( in, out, im_col_displays( 7 ) ) )
return( -1 );
out->Type = IM_TYPE_sRGB;
return( 0 );
}
/**
* im_sRGB2XYZ:
* @in: input image
* @out: output image
*
* Convert an image from sRGB to XYZ.
* The conversion is supposed to be quick
* rather than accurate. Use an ICC profile with im_icc_transform() for more
* precision.
*
* See also: im_icc_transform.
*
* Returns: 0 on success, -1 on error.
*/
int
im_sRGB2XYZ( IMAGE *in, IMAGE *out )
{
if( im_disp2XYZ( in, out, im_col_displays( 7 ) ) )
return( -1 );
return( 0 );
}
/** /**
* im_dE_fromXYZ: * im_dE_fromXYZ:
* @in1: first input image * @in1: first input image

View File

@ -1,155 +0,0 @@
/* @(#) Turn XYZ files into displayable rgb.
* @(#)
* @(#) Usage:
* @(#) int im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
* @(#)
* @(#) Returns: -1 on error, else 0
*
* Author: J-P. Laurent
* Modified:
* 15/11/94 JC
* - error message added
* - out->Type set to IM_TYPE_RGB
* - memory leak fixed
* 16/11/94 JC
* - uses im_wrapone()
* 15/2/95 JC
* - oops! now uses PEL, not float for output pointer
* 2/1/96 JC
* - sometimes produced incorrect result at extrema
* - reformatted
* - now uses IM_RINT() and clip()
* 18/9/96 JC
* - some speed-ups ... 3x faster
* - slightly less accurate, but who cares
* - added out-of-mem check for table build
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
/* Process a buffer of data.
*/
void
imb_XYZ2disp( float *p, VipsPel *q, int n, struct im_col_display *d )
{
struct im_col_tab_disp *table = im_col_display_get_table( d );
float rstep = (d->d_YCR - d->d_Y0R) / 1500.0;
float gstep = (d->d_YCG - d->d_Y0G) / 1500.0;
float bstep = (d->d_YCB - d->d_Y0B) / 1500.0;
int x;
for( x = 0; x < n; x++ ) {
float Yr, Yg, Yb;
int i;
int r, g, b;
float X = p[0];
float Y = p[1];
float Z = p[2];
p += 3;
/* Multiply through the matrix to get luminosity values.
*/
Yr = table->mat_XYZ2lum[0][0] * X
+ table->mat_XYZ2lum[0][1] * Y
+ table->mat_XYZ2lum[0][2] * Z;
Yg = table->mat_XYZ2lum[1][0] * X
+ table->mat_XYZ2lum[1][1] * Y
+ table->mat_XYZ2lum[1][2] * Z;
Yb = table->mat_XYZ2lum[2][0] * X
+ table->mat_XYZ2lum[2][1] * Y
+ table->mat_XYZ2lum[2][2] * Z;
/* Clip -ves.
*/
Yr = IM_MAX( Yr, d->d_Y0R );
Yg = IM_MAX( Yg, d->d_Y0G );
Yb = IM_MAX( Yb, d->d_Y0B );
/* Turn luminosity to colour value.
*/
i = IM_MIN( 1500, (Yr - d->d_Y0R) / rstep );
r = table->t_Yr2r[i];
i = IM_MIN( 1500, (Yg - d->d_Y0G) / gstep );
g = table->t_Yg2g[i];
i = IM_MIN( 1500, (Yb - d->d_Y0B) / bstep );
b = table->t_Yb2b[i];
/* Clip output.
*/
r = IM_MIN( r, d->d_Vrwr );
g = IM_MIN( g, d->d_Vrwg );
b = IM_MIN( b, d->d_Vrwb );
q[0] = r;
q[1] = g;
q[2] = b;
q += 3;
}
}
int
im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_XYZ2disp",
"%s", _( "3-band uncoded float only" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->BandFmt = IM_BANDFMT_UCHAR;
out->Type = IM_TYPE_RGB;
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_XYZ2disp, d, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -1,104 +0,0 @@
/* @(#) Turn displayable rgb files to XYZ.
* @(#)
* @(#) Usage:
* @(#) im_disp2XYZ( imagein, imageout, display )
* @(#) IMAGE *imagein, *imageout;
* @(#) struct im_col_display *display;
* @(#)
* @(#) uchar in, float out.
* @(#)
* @(#) Returns: -1 on error, else 0
* Modified:
* 15/11/94 JC
* - memory leak fixed
* - error message added
* 16/11/94 JC
* - partialed
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
/* Convert a buffer.
*/
void
imb_disp2XYZ( VipsPel *p, float *q, int n, struct im_col_display *d )
{
int x;
for( x = 0; x < n; x++ ) {
int r = p[0];
int g = p[1];
int b = p[2];
float X, Y, Z;
p += 3;
im_col_rgb2XYZ( d, r, g, b, &X, &Y, &Z );
q[0] = X;
q[1] = Y;
q[2] = Z;
q += 3;
}
}
int
im_disp2XYZ( IMAGE *in, IMAGE *out, struct im_col_display *d )
{
/* Check input image.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_UCHAR ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_disp2XYZ",
"%s", _( "input not 3-band uncoded char" ) );
return( -1 );
}
/* Prepare the output image
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->BandFmt = IM_BANDFMT_FLOAT;
out->Type = IM_TYPE_XYZ;
/* Do the processing.
*/
if( im_wrapone( in, out,
(im_wrapone_fn) imb_disp2XYZ, d, NULL ) )
return( -1 );
return( 0 );
}

134
libvips/colour/sRGB2XYZ.c Normal file
View File

@ -0,0 +1,134 @@
/* Turn displayable rgb files to XYZ.
*
* Modified:
* 15/11/94 JC
* - memory leak fixed
* - error message added
* 16/11/94 JC
* - partialed
* 21/9/12
* - redone as a class
* - sRGB only, support for other RGBs is now via lcms
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#include "colour.h"
typedef VipsColourCode VipssRGB2XYZ;
typedef VipsColourCodeClass VipssRGB2XYZClass;
G_DEFINE_TYPE( VipssRGB2XYZ, vips_sRGB2XYZ, VIPS_TYPE_COLOUR_CODE );
/* Convert a buffer.
*/
static void
vips_sRGB2XYZ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
{
VipsPel *p = in[0];
float *q = (float *) out;
int i;
for( i = 0; i < width; i++ ) {
int r = p[0];
int g = p[1];
int b = p[2];
float X, Y, Z;
p += 3;
vips_col_sRGB2XYZ( r, g, b, &X, &Y, &Z );
q[0] = X;
q[1] = Y;
q[2] = Z;
q += 3;
}
}
static void
vips_sRGB2XYZ_class_init( VipssRGB2XYZClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsColourClass *colour_class = VIPS_COLOUR_CLASS( class );
VipsColourCodeClass *code_class = VIPS_COLOUR_CODE_CLASS( class );
object_class->nickname = "sRGB2XYZ";
object_class->description = _( "convert an sRGB image to XYZ" );
colour_class->process_line = vips_sRGB2XYZ_line;
colour_class->coding = VIPS_CODING_NONE;
colour_class->interpretation = VIPS_INTERPRETATION_XYZ;
colour_class->format = VIPS_FORMAT_FLOAT;
colour_class->bands = 3;
code_class->input_coding = VIPS_CODING_NONE;
code_class->input_bands = 3;
code_class->input_format = VIPS_FORMAT_UCHAR;
}
static void
vips_sRGB2XYZ_init( VipssRGB2XYZ *sRGB2XYZ )
{
}
/**
* vips_sRGB2XYZ:
* @in: input image
* @out: output image
*
* Convert an sRGB image to XYZ.
*
* See also: im_LabS2LabQ(), im_sRGB2XYZ(), im_rad2float().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_sRGB2XYZ( VipsImage *in, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "sRGB2XYZ", ap, in, out );
va_end( ap );
return( result );
}

View File

@ -57,28 +57,12 @@
*/ */
#define VEC_SEPS " " #define VEC_SEPS " "
/* Init function for input displays. /* Init function for input displays. Just a stub nowadays.
*/ */
static int static int
input_display_init( im_object *obj, char *str ) input_display_init( im_object *obj, char *str )
{ {
struct im_col_display *scr = im_col_display_name( str ); *obj = NULL;
if( !scr ) {
int i;
vips_error( "input_display",
_( "unknown display type \"%s\"" ), str );
vips_error( "input_display", "%s",
_( "display should be one of:\n" ) );
for( i = 0; (scr = im_col_displays( i )); i++ )
vips_error( "input_display",
" '%s'\n", scr->d_name );
return( -1 );
}
*obj = scr;
return( 0 ); return( 0 );
} }
@ -97,7 +81,7 @@ im_type_desc im__input_display = {
*/ */
im_type_desc im__output_display = { im_type_desc im__output_display = {
IM_TYPE_DISPLAY, /* It's a display */ IM_TYPE_DISPLAY, /* It's a display */
sizeof( struct im_col_display ),/* Memory to allocate */ sizeof( void * ), /* Memory to allocate */
IM_TYPE_OUTPUT, /* Output object */ IM_TYPE_OUTPUT, /* Output object */
NULL, /* Init function */ NULL, /* Init function */
NULL /* Destroy function */ NULL /* Destroy function */
@ -739,62 +723,6 @@ im__dmsprint( im_object obj )
return( 0 ); return( 0 );
} }
static char *decode_dtype( enum im_col_disp_type type )
{
switch( type ) {
case DISP_BARCO:
return( "DISP_BARCO" );
case DISP_DUMB:
return( "DISP_DUMB" );
default:
return( "<unknown display type>" );
}
}
/* Print display stuff.
*/
int
im__displayprint( im_object obj )
{
struct im_col_display *scr = (struct im_col_display *) obj;
printf( "im_col_display:\n" );
printf( "\td_name: %s\n", scr->d_name );
printf( "\td_type: %s\n", decode_dtype( scr->d_type ) );
printf( "\td_mat:\n" );
printf( "\t\t %g %g %g\n",
scr->d_mat[0][0], scr->d_mat[0][1], scr->d_mat[0][2] );
printf( "\t\t %g %g %g\n",
scr->d_mat[1][0], scr->d_mat[1][1], scr->d_mat[1][2] );
printf( "\t\t %g %g %g\n",
scr->d_mat[2][0], scr->d_mat[2][1], scr->d_mat[2][2] );
printf( "\td_YCW: %g\n", scr->d_YCW );
printf( "\td_xCW: %g\n", scr->d_xCW );
printf( "\td_yCW: %g\n", scr->d_yCW );
printf( "\td_YCR: %g\n", scr->d_YCR );
printf( "\td_YCG: %g\n", scr->d_YCG );
printf( "\td_YCB: %g\n", scr->d_YCB );
printf( "\td_Vrwr: %d\n", scr->d_Vrwr );
printf( "\td_Vrwg: %d\n", scr->d_Vrwg );
printf( "\td_Vrwb: %d\n", scr->d_Vrwb );
printf( "\td_Y0R: %g\n", scr->d_Y0R );
printf( "\td_Y0G: %g\n", scr->d_Y0G );
printf( "\td_Y0B: %g\n", scr->d_Y0B );
printf( "\td_gammaR: %g\n", scr->d_gammaR );
printf( "\td_gammaG: %g\n", scr->d_gammaG );
printf( "\td_gammaB: %g\n", scr->d_gammaB );
printf( "\td_B: %g\n", scr->d_B );
printf( "\td_P: %g\n", scr->d_P );
return( 0 );
}
/* GValue /* GValue
*/ */

View File

@ -2508,3 +2508,51 @@ im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d )
return( 0 ); return( 0 );
} }
int
im_sRGB2XYZ( IMAGE *in, IMAGE *out )
{
VipsImage *x;
if( vips_sRGB2XYZ( in, &x, NULL ) )
return( -1 );
if( im_copy( x, out ) ) {
g_object_unref( x );
return( -1 );
}
g_object_unref( x );
return( 0 );
}
int
im_XYZ2sRGB( IMAGE *in, IMAGE *out )
{
VipsImage *x;
if( vips_XYZ2sRGB( in, &x, NULL ) )
return( -1 );
if( im_copy( x, out ) ) {
g_object_unref( x );
return( -1 );
}
g_object_unref( x );
return( 0 );
}
int
im_LabQ2sRGB( IMAGE *in, IMAGE *out )
{
VipsImage *x;
if( vips_LabQ2sRGB( in, &x, NULL ) )
return( -1 );
if( im_copy( x, out ) ) {
g_object_unref( x );
return( -1 );
}
g_object_unref( x );
return( 0 );
}

View File

@ -1116,7 +1116,7 @@ vips_foreign_convert_saveable( VipsForeignSave *save )
if( in->Coding == VIPS_CODING_LABQ ) { if( in->Coding == VIPS_CODING_LABQ ) {
VipsImage *out; VipsImage *out;
if( vips_LabQ2disp( in, &out, im_col_displays( 7 ), NULL ) ) { if( vips_LabQ2sRGB( in, &out, NULL ) ) {
g_object_unref( in ); g_object_unref( in );
return( -1 ); return( -1 );
} }
@ -1300,7 +1300,7 @@ vips_foreign_convert_saveable( VipsForeignSave *save )
in->Type == VIPS_INTERPRETATION_LAB ) { in->Type == VIPS_INTERPRETATION_LAB ) {
VipsImage *out; VipsImage *out;
if( vips_XYZ2disp( in, &out, im_col_displays( 7 ), NULL ) ) { if( vips_XYZ2sRGB( in, &out, NULL ) ) {
g_object_unref( in ); g_object_unref( in );
return( -1 ); return( -1 );
} }

View File

@ -120,6 +120,8 @@ int vips_XYZ2Lab( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_XYZ2sRGB( VipsImage *in, VipsImage **out, ... ) int vips_XYZ2sRGB( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_sRGB2XYZ( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_LCh2UCS( VipsImage *in, VipsImage **out, ... ) int vips_LCh2UCS( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_UCS2LCh( VipsImage *in, VipsImage **out, ... ) int vips_UCS2LCh( VipsImage *in, VipsImage **out, ... )
@ -174,8 +176,6 @@ int im_UCS2XYZ( VipsImage *in, VipsImage *out );
int im_UCS2Lab( VipsImage *in, VipsImage *out ); int im_UCS2Lab( VipsImage *in, VipsImage *out );
int im_Lab2UCS( VipsImage *in, VipsImage *out ); int im_Lab2UCS( VipsImage *in, VipsImage *out );
int im_XYZ2UCS( VipsImage *in, VipsImage *out ); int im_XYZ2UCS( VipsImage *in, VipsImage *out );
int im_sRGB2XYZ( VipsImage *in, VipsImage *out );
int im_XYZ2sRGB( VipsImage *in, VipsImage *out );
int im_dECMC_fromLab( VipsImage *in1, VipsImage *in2, VipsImage *out ); int im_dECMC_fromLab( VipsImage *in1, VipsImage *in2, VipsImage *out );
int im_dE00_fromLab( VipsImage *in1, VipsImage *in2, VipsImage *out ); int im_dE00_fromLab( VipsImage *in1, VipsImage *in2, VipsImage *out );

View File

@ -109,27 +109,27 @@ typedef enum {
/** /**
* VipsInterpretation: * VipsInterpretation:
* @VIPS_INTERPREATION_MULTIBAND: generic many-band image * @VIPS_INTERPRETATION_MULTIBAND: generic many-band image
* @VIPS_INTERPREATION_B_W: some kind of single-band image * @VIPS_INTERPRETATION_B_W: some kind of single-band image
* @VIPS_INTERPREATION_HISTOGRAM: a 1D image such as a histogram or lookup table * @VIPS_INTERPRETATION_HISTOGRAM: a 1D image, eg. histogram or lookup table
* @VIPS_INTERPREATION_FOURIER: image is in fourier space * @VIPS_INTERPRETATION_FOURIER: image is in fourier space
* @VIPS_INTERPREATION_XYZ: the first three bands are CIE XYZ * @VIPS_INTERPRETATION_XYZ: the first three bands are CIE XYZ
* @VIPS_INTERPREATION_LAB: pixels are in CIE Lab space * @VIPS_INTERPRETATION_LAB: pixels are in CIE Lab space
* @VIPS_INTERPREATION_CMYK: the first four bands are in CMYK space * @VIPS_INTERPRETATION_CMYK: the first four bands are in CMYK space
* @VIPS_INTERPREATION_LABQ: implies #VIPS_CODING_LABQ * @VIPS_INTERPRETATION_LABQ: implies #VIPS_CODING_LABQ
* @VIPS_INTERPREATION_RGB: generic RGB space * @VIPS_INTERPRETATION_RGB: generic RGB space
* @VIPS_INTERPREATION_UCS: a uniform colourspace based on CMC * @VIPS_INTERPRETATION_UCS: a uniform colourspace based on CMC
* @VIPS_INTERPREATION_LCH: pixels are in CIE LCh space * @VIPS_INTERPRETATION_LCH: pixels are in CIE LCh space
* @VIPS_INTERPREATION_LABS: CIE LAB coded as three signed 16-bit values * @VIPS_INTERPRETATION_LABS: CIE LAB coded as three signed 16-bit values
* @VIPS_INTERPREATION_sRGB: pixels are sRGB * @VIPS_INTERPRETATION_sRGB: pixels are sRGB
* @VIPS_INTERPREATION_YXY: pixels are CIE Yxy * @VIPS_INTERPRETATION_YXY: pixels are CIE Yxy
* @VIPS_INTERPREATION_RGB16: generic 16-bit RGB * @VIPS_INTERPRETATION_RGB16: generic 16-bit RGB
* @VIPS_INTERPREATION_GREY16: generic 16-bit mono * @VIPS_INTERPRETATION_GREY16: generic 16-bit mono
* @VIPS_INTERPREATION_ARRAY: an array * @VIPS_INTERPRETATION_ARRAY: an array
* *
* How the values in an image should be interpreted. For example, a * How the values in an image should be interpreted. For example, a
* three-band float image of type #VIPS_INTERPREATION_LAB should have its pixels * three-band float image of type #VIPS_INTERPRETATION_LAB should have its
* interpreted as coordinates in CIE Lab space. * pixels interpreted as coordinates in CIE Lab space.
* *
* These values are set by operations as hints to user-interfaces built on top * These values are set by operations as hints to user-interfaces built on top
* of VIPS to help them show images to the user in a meaningful way. * of VIPS to help them show images to the user in a meaningful way.
@ -143,7 +143,6 @@ typedef enum {
VIPS_INTERPRETATION_MULTIBAND = 0, VIPS_INTERPRETATION_MULTIBAND = 0,
VIPS_INTERPRETATION_B_W = 1, VIPS_INTERPRETATION_B_W = 1,
VIPS_INTERPRETATION_HISTOGRAM = 10, VIPS_INTERPRETATION_HISTOGRAM = 10,
VIPS_INTERPRETATION_FOURIER = 24,
VIPS_INTERPRETATION_XYZ = 12, VIPS_INTERPRETATION_XYZ = 12,
VIPS_INTERPRETATION_LAB = 13, VIPS_INTERPRETATION_LAB = 13,
VIPS_INTERPRETATION_CMYK = 15, VIPS_INTERPRETATION_CMYK = 15,
@ -154,6 +153,7 @@ typedef enum {
VIPS_INTERPRETATION_LABS = 21, VIPS_INTERPRETATION_LABS = 21,
VIPS_INTERPRETATION_sRGB = 22, VIPS_INTERPRETATION_sRGB = 22,
VIPS_INTERPRETATION_YXY = 23, VIPS_INTERPRETATION_YXY = 23,
VIPS_INTERPRETATION_FOURIER = 24,
VIPS_INTERPRETATION_RGB16 = 25, VIPS_INTERPRETATION_RGB16 = 25,
VIPS_INTERPRETATION_GREY16 = 26, VIPS_INTERPRETATION_GREY16 = 26,
VIPS_INTERPRETATION_ARRAY = 27 VIPS_INTERPRETATION_ARRAY = 27

View File

@ -730,6 +730,25 @@ int im_Lab2LabS( VipsImage *in, VipsImage *out );
int im_LabS2Lab( VipsImage *in, VipsImage *out ); int im_LabS2Lab( 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_LabQ2sRGB( VipsImage *in, VipsImage *out );
int im_XYZ2sRGB( IMAGE *in, IMAGE *out );
int im_sRGB2XYZ( IMAGE *in, IMAGE *out );
struct im_col_display;
#define im_col_displays(S) (NULL)
#define im_LabQ2disp_build_table(A, B) (NULL)
#define im_LabQ2disp_table(A, B, C) (im_LabQ2disp(A, B, C))
int im_Lab2disp( IMAGE *in, IMAGE *out, struct im_col_display *disp );
int im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *disp );
int im_dE_fromdisp( IMAGE *, IMAGE *, IMAGE *, struct im_col_display * );
int im_dECMC_fromdisp( IMAGE *, IMAGE *, IMAGE *, struct im_col_display * );
#define im_disp2XYZ(A, B, C) (im_sRGB2XYZ(A, B))
#define im_XYZ2disp(A, B, C) (im_XYZ2sRGB(A, B))
#define im_LabQ2disp(A, B, C) (im_LabQ2sRGB(A, B))
/* ruby-vips uses this /* ruby-vips uses this
*/ */

View File

@ -423,7 +423,6 @@ vips_interpretation_get_type( void )
{VIPS_INTERPRETATION_MULTIBAND, "VIPS_INTERPRETATION_MULTIBAND", "multiband"}, {VIPS_INTERPRETATION_MULTIBAND, "VIPS_INTERPRETATION_MULTIBAND", "multiband"},
{VIPS_INTERPRETATION_B_W, "VIPS_INTERPRETATION_B_W", "b-w"}, {VIPS_INTERPRETATION_B_W, "VIPS_INTERPRETATION_B_W", "b-w"},
{VIPS_INTERPRETATION_HISTOGRAM, "VIPS_INTERPRETATION_HISTOGRAM", "histogram"}, {VIPS_INTERPRETATION_HISTOGRAM, "VIPS_INTERPRETATION_HISTOGRAM", "histogram"},
{VIPS_INTERPRETATION_FOURIER, "VIPS_INTERPRETATION_FOURIER", "fourier"},
{VIPS_INTERPRETATION_XYZ, "VIPS_INTERPRETATION_XYZ", "xyz"}, {VIPS_INTERPRETATION_XYZ, "VIPS_INTERPRETATION_XYZ", "xyz"},
{VIPS_INTERPRETATION_LAB, "VIPS_INTERPRETATION_LAB", "lab"}, {VIPS_INTERPRETATION_LAB, "VIPS_INTERPRETATION_LAB", "lab"},
{VIPS_INTERPRETATION_CMYK, "VIPS_INTERPRETATION_CMYK", "cmyk"}, {VIPS_INTERPRETATION_CMYK, "VIPS_INTERPRETATION_CMYK", "cmyk"},
@ -434,6 +433,7 @@ vips_interpretation_get_type( void )
{VIPS_INTERPRETATION_LABS, "VIPS_INTERPRETATION_LABS", "labs"}, {VIPS_INTERPRETATION_LABS, "VIPS_INTERPRETATION_LABS", "labs"},
{VIPS_INTERPRETATION_sRGB, "VIPS_INTERPRETATION_sRGB", "srgb"}, {VIPS_INTERPRETATION_sRGB, "VIPS_INTERPRETATION_sRGB", "srgb"},
{VIPS_INTERPRETATION_YXY, "VIPS_INTERPRETATION_YXY", "yxy"}, {VIPS_INTERPRETATION_YXY, "VIPS_INTERPRETATION_YXY", "yxy"},
{VIPS_INTERPRETATION_FOURIER, "VIPS_INTERPRETATION_FOURIER", "fourier"},
{VIPS_INTERPRETATION_RGB16, "VIPS_INTERPRETATION_RGB16", "rgb16"}, {VIPS_INTERPRETATION_RGB16, "VIPS_INTERPRETATION_RGB16", "rgb16"},
{VIPS_INTERPRETATION_GREY16, "VIPS_INTERPRETATION_GREY16", "grey16"}, {VIPS_INTERPRETATION_GREY16, "VIPS_INTERPRETATION_GREY16", "grey16"},
{VIPS_INTERPRETATION_ARRAY, "VIPS_INTERPRETATION_ARRAY", "array"}, {VIPS_INTERPRETATION_ARRAY, "VIPS_INTERPRETATION_ARRAY", "array"},

View File

@ -52,28 +52,13 @@ VIPS_NAMESPACE_START
static void static void
free_display( im_col_display *d ) free_display( im_col_display *d )
{ {
if( d->d_name )
im_free( d->d_name );
im_free( d );
} }
// Dupe an im_col_display // Dupe an im_col_display
static im_col_display * static im_col_display *
dup_display( im_col_display *in ) throw( VError ) dup_display( im_col_display *in ) throw( VError )
{ {
im_col_display *out; return( in );
if( !(out = IM_NEW( NULL, im_col_display )) )
verror();
*out = *in;
if( in->d_name )
if( !(out->d_name = strdup( in->d_name )) ) {
free_display( out );
verror( "out of memory" );
}
return( out );
} }
// Remove lut // Remove lut
@ -109,9 +94,6 @@ void VDisplay::refblock::wready() throw( VError )
// Check that luts are up-to-date // Check that luts are up-to-date
void VDisplay::refblock::cluts() throw( VError ) void VDisplay::refblock::cluts() throw( VError )
{ {
if( !luts )
if( !(luts = im_col_make_tables_RGB( NULL, disp )) )
verror();
} }
VDisplay::~VDisplay() VDisplay::~VDisplay()
@ -140,30 +122,9 @@ VDisplay &VDisplay::operator=( const VDisplay &a )
VDisplay::VDisplay( const char *name ) throw( VError ) VDisplay::VDisplay( const char *name ) throw( VError )
{ {
// Search for a matching name in the VIPS colour list
im_col_display *scr = im_col_display_name( name );
if( !scr ) {
VError err;
err.app( "VDisplay error: " );
err.app( "unknown display type \"" ).app( name ).app( "\"\n" );
err.app( "display should be one of:" );
for( int i = 0; (scr = im_col_displays( i )); i++ ) {
err.app( " \"" );
err.app( im_col_displays( i )->d_name );
err.app( "\"" );
}
err.app( "\n" );
throw( err );
}
// Install display // Install display
ref = new refblock; ref = new refblock;
ref->disp = scr; ref->disp = NULL;
} }
VDisplay::VDisplay() VDisplay::VDisplay()