| /* @(#) Turn Lab 32bit packed format into displayable rgb. Fast, but very |
| * @(#) inaccurate: for display only! |
| * @(#) |
| * @(#) Usage: |
| * @(#) int im_LabQ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d ) |
| * @(#) |
| * @(#) Returns: -1 on error, else 0 |
| * |
| * 5/11/97 Steve Perry |
| * - adapted from old ip code |
| * 7/11/97 JC |
| * - small tidies, added to VIPS |
| * - LUT build split into separate function |
| */ |
| |
| /* |
| |
| 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 <assert.h> |
| |
| #include <vips/vips.h> |
| |
| #ifdef WITH_DMALLOC |
| #include <dmalloc.h> |
| #endif /*WITH_DMALLOC*/ |
| |
| /* Hold a display characterisation, and a set of tables |
| * computed from that. |
| */ |
| typedef struct { |
| struct im_col_display *disp; |
| PEL red[ 64 * 64 * 64 ]; |
| PEL green[ 64 * 64 * 64 ]; |
| PEL blue[ 64 * 64 * 64 ]; |
| } CalibrateInfo; |
| |
| /* Do our own indexing of the arrays, to make sure we get efficient mults. |
| */ |
| #define index( L, A, B ) (L + (A << 6) + (B << 12)) |
| |
| /* Process a buffer of data. |
| */ |
| static void |
| imb_LabQ2disp( PEL *p, PEL *q, int n, CalibrateInfo *cal ) |
| { |
| int x, t; |
| |
| /* Current error. |
| */ |
| int le = 0; |
| int ae = 0; |
| int be = 0; |
| |
| for( x = 0; x < n; x++ ) { |
| /* Get colour, add in error from previous pixel. |
| */ |
| int L = p[0] + le; |
| int A = (signed char) p[1] + ae; |
| int B = (signed char) p[2] + be; |
| p += 4; |
| |
| /* Look out for overflow. |
| */ |
| L = IM_MIN( 255, L ); |
| A = IM_MIN( 127, A ); |
| B = IM_MIN( 127, B ); |
| |
| /* Find new quant error. This will always be +ve. |
| */ |
| le = L & 3; |
| ae = A & 3; |
| be = B & 3; |
| |
| /* Scale to 0-63. |
| */ |
| L = (L >> 2) & 63; |
| A = (A >> 2) & 63; |
| B = (B >> 2) & 63; |
| |
| /* Convert to RGB. |
| */ |
| t = index( L, A, B ); |
| q[0] = cal->red[t]; |
| q[1] = cal->green[t]; |
| q[2] = cal->blue[t]; |
| q += 3; |
| } |
| } |
| |
| /* Build Lab->disp tables. |
| */ |
| void * |
| im_LabQ2disp_build_table( IMAGE *out, struct im_col_display *d ) |
| { |
| CalibrateInfo *cal; |
| int l, a, b; |
| int t; |
| |
| if( !(cal = IM_NEW( out, CalibrateInfo )) ) |
| return( NULL ); |
| cal->disp = d; |
| |
| /* Build our tables. |
| */ |
| for( l = 0; l < 64; l++ ) { |
| for( a = 0; a < 64; a++ ) { |
| for( b = 0; b < 64; b++ ) { |
| /* Scale to lab space. |
| */ |
| float L = (l << 2) * (100.0/256.0); |
| float A = (signed char) (a << 2); |
| float B = (signed char) (b << 2); |
| float X, Y, Z; |
| int rb, gb, bb; |
| int oflow; |
| |
| /* Convert to XYZ. |
| */ |
| im_col_Lab2XYZ( L, A, B, &X, &Y, &Z ); |
| |
| /* Convert to display. |
| */ |
| im_col_XYZ2rgb( cal->disp, |
| X, Y, Z, &rb, &gb, &bb, &oflow ); |
| |
| /* Save RGB. |
| */ |
| t = index( l, a, b ); |
| cal->red[t] = rb; |
| cal->green[t] = gb; |
| cal->blue[t] = bb; |
| } |
| } |
| } |
| |
| return( (void *) cal ); |
| } |
| |
| int |
| im_LabQ2disp_table( IMAGE *in, IMAGE *out, void *table ) |
| { |
| CalibrateInfo *cal = (CalibrateInfo *) table; |
| |
| if( im_check_coding_labq( "im_LabQ2disp", in ) ) |
| return( -1 ); |
| |
| if( im_cp_desc( out, in ) ) |
| return( -1 ); |
| out->Bands = 3; |
| out->BandFmt = IM_BANDFMT_UCHAR; |
| out->Coding = IM_CODING_NONE; |
| out->Type = IM_TYPE_RGB; |
| |
| if( im_wrapone( in, out, (im_wrapone_fn) imb_LabQ2disp, cal, NULL ) ) |
| return( -1 ); |
| |
| return( 0 ); |
| } |
| |
| int |
| im_LabQ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d ) |
| { |
| void *table; |
| |
| if( !(table = im_LabQ2disp_build_table( out, d )) || |
| im_LabQ2disp_table( in, out, table ) ) |
| return( -1 ); |
| |
| return( 0 ); |
| } |