Files
core/DesktopEditor/cximage/libpsd/hue_saturation.c
Elen.Subbotina e89cf2f58f .....
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@61945 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-20 23:54:34 +03:00

247 lines
9.4 KiB
C
Raw Permalink Blame History

/**
* libpsd - Photoshop file formats (*.psd) decode library
* Copyright (C) 2004-2007 Graphest Software.
*
* libpsd is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library 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 General Public License for more details.
*
* You should have received a copy of the GNU Library 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
*
* $Id: hue_saturation.c, created by Patrick in 2006.05.22, libpsd@graphest.com Exp $
*/
#include "libpsd.h"
#include "psd_system.h"
#include "psd_stream.h"
#include "psd_color.h"
#include "psd_rect.h"
#include "psd_math.h"
typedef void psd_adjustment_blend_proc(psd_uint layer_info_data, psd_int * red, psd_int * green, psd_int * blue);
extern void psd_adjustment_blend_color(psd_context * context, psd_layer_record * layer, psd_rect * dst_rect,
psd_adjustment_blend_proc * blend_proc, psd_uint layer_info_data);
// New Hue/saturation, Photoshop 5.0
psd_status psd_get_layer_hue_saturation(psd_context * context, psd_layer_record * layer)
{
psd_layer_hue_saturation * data;
psd_int i, j;
layer->layer_info_type[layer->layer_info_count] = psd_layer_info_type_new_hue_saturation;
layer->layer_type = psd_layer_type_hue_saturation;
data = (psd_layer_hue_saturation *)psd_malloc(sizeof(psd_layer_hue_saturation));
if(data == NULL)
return psd_status_malloc_failed;
memset(data, 0, sizeof(psd_layer_hue_saturation));
layer->layer_info_data[layer->layer_info_count] = (psd_uint)data;
layer->layer_info_count ++;
// Version ( = 2)
if(psd_stream_get_short(context) != 2)
return psd_status_hue_saturation_unsupport_version;
// 0 = Use settings for hue-adjustment; 1 = Use settings for colorization.
data->hue_or_colorization = psd_stream_get_char(context);
// Padding byte; must be present but is ignored by Photoshop.
psd_stream_get_char(context);
// Colorization.
// Photoshop 5.0: The actual values are stored for the new version. Hue is -
// 180...180, Saturation is 0...100, and Lightness is -100...100.
// Photoshop 4.0: Three psd_short integers Hue, Saturation, and Lightness
// from <20>C100...100. The user interface represents hue as <20>C180...180,
// saturation as 0...100, and Lightness as -100...1000, as the traditional
// HSB color wheel, with red = 0.
data->colorization_hue = psd_stream_get_short(context);
data->colorization_saturation = psd_stream_get_short(context);
data->colorization_lightness = psd_stream_get_short(context);
// Master hue, saturation and lightness values.
data->master_hue = psd_stream_get_short(context);
data->master_saturation = psd_stream_get_short(context);
data->master_lightness = psd_stream_get_short(context);
// 6 sets of the following 14 bytes (4 range values followed by 3 settings values)
for(i = 0; i < 6; i ++)
{
//For RGB and CMYK, those values apply to each of the six hextants in
// the HSB color wheel: those image pixels nearest to red, yellow, green,
// cyan, blue, or magenta. These numbers appear in the user interface
// from <20>C60...60, however the slider will reflect each of the possible 201
// values from <20>C100...100.
for(j = 0; j < 4; j ++)
data->range_values[i][j] = psd_stream_get_short(context);
// For Lab, the first four of the six values are applied to image pixels in the
// four Lab color quadrants, yellow, green, blue, and magenta. The other
// two values are ignored ( = 0). The values appear in the user interface
// from <20>C90 to 90.
for(j = 0; j < 3; j ++)
data->setting_values[i][j] = psd_stream_get_short(context);
}
layer->adjustment_valid = psd_true;
return psd_status_done;
}
psd_static void psd_hue_saturation_proc(psd_uint layer_info_data, psd_int * red, psd_int * green, psd_int * blue)
{
psd_layer_hue_saturation * data = (psd_layer_hue_saturation *)layer_info_data;
psd_int src_hue, src_saturation, src_lightness;
psd_int dst_hue, dst_saturation, dst_lightness;
psd_int i, opacity;
psd_rgb_to_inthsb(*red, *green, *blue, &src_hue, &src_saturation, &src_lightness);
dst_hue = data->master_hue;
dst_saturation = data->master_saturation;
dst_lightness = data->master_lightness;
for(i = 0; i < 6; i ++)
{
opacity = data->lookup_table[i][src_hue];
if(opacity > 0)
{
dst_hue += data->setting_values[i][0] * opacity / 255;
dst_saturation += data->setting_values[i][1] * opacity / 255;
dst_lightness += data->setting_values[i][2] * opacity / 255;
}
}
if(dst_hue != 0 || dst_saturation != 0 || dst_lightness != 0)
{
dst_hue = (src_hue + dst_hue + 2160) % 360;
dst_saturation = src_saturation + src_saturation * PSD_CONSTRAIN(dst_saturation, -100, 100) / 100;
dst_saturation = PSD_CONSTRAIN(dst_saturation, 0, 255);
dst_lightness = src_lightness + src_lightness * PSD_CONSTRAIN(dst_lightness, -100, 100) / 100;
dst_lightness = PSD_CONSTRAIN(dst_lightness, 0, 255);
psd_inthsb_to_rgb(dst_hue, dst_saturation, dst_lightness, red, green, blue);
}
}
psd_bool psd_layer_blend_hue_saturation(psd_context * context, psd_layer_record * layer, psd_rect * dst_rect)
{
psd_uint layer_info_data;
psd_layer_hue_saturation * data = NULL;
psd_int i, j, increase, range_value[4];
for(i = 0; i < layer->layer_info_count; i ++)
{
if(layer->layer_info_type[i] == psd_layer_info_type_new_hue_saturation)
{
layer_info_data = layer->layer_info_data[i];
data = (psd_layer_hue_saturation *)layer_info_data;
break;
}
}
if(data == NULL)
return psd_false;
if(layer->adjustment_valid == psd_true)
{
for(i = 0; i < 6; i ++)
{
if(data->setting_values[i][0] != 0 || data->setting_values[i][1] != 0 ||
data->setting_values[i][2] != 0)
{
if(data->range_values[i][0] > data->range_values[i][1] ||
data->range_values[i][1] > data->range_values[i][2] ||
data->range_values[i][2] > data->range_values[i][3])
{
increase = 0;
range_value[0] = data->range_values[i][0];
if(data->range_values[i][0] > data->range_values[i][1])
increase = 360;
range_value[1] = data->range_values[i][1] + increase;
if(data->range_values[i][1] > data->range_values[i][2] && increase == 0)
increase = 360;
range_value[2] = data->range_values[i][2] + increase;
if(data->range_values[i][2] > data->range_values[i][3] && increase == 0)
increase = 360;
range_value[3] = data->range_values[i][3] + increase;
for(j = 0; j < 360; j ++)
{
if(j >= range_value[0] && j < range_value[3])
{
if(j >= range_value[1] && j < range_value[2])
data->lookup_table[i][j] = 255;
else if(j < range_value[1] && range_value[1] > range_value[0])
data->lookup_table[i][j] = 255 * (j - range_value[0]) / (range_value[1] - range_value[0]);
else if(j >= range_value[2] && range_value[3] > range_value[2])
data->lookup_table[i][j] = 255 * (range_value[3] - j) / (range_value[3] - range_value[2]);
else
data->lookup_table[i][j] = 0;
}
else if(j + 360 >= range_value[0] && j + 360 < range_value[3])
{
if(j + 360 >= range_value[1] && j + 360 < range_value[2])
data->lookup_table[i][j] = 255;
else if(j + 360 < range_value[1] && range_value[1] > range_value[0])
data->lookup_table[i][j] = 255 * (j + 360 - range_value[0]) / (range_value[1] - range_value[0]);
else if(j + 360 >= range_value[2] && range_value[3] > range_value[2])
data->lookup_table[i][j] = 255 * (range_value[3] - (j + 360)) / (range_value[3] - range_value[2]);
else
data->lookup_table[i][j] = 0;
}
else
{
data->lookup_table[i][j] = 0;
}
}
}
else
{
for(j = 0; j < 360; j ++)
{
if(j >= data->range_values[i][0] && j < data->range_values[i][3])
{
if(j >= data->range_values[i][1] && j < data->range_values[i][2])
data->lookup_table[i][j] = 255;
else if(j < data->range_values[i][1] && data->range_values[i][1] > data->range_values[i][0])
data->lookup_table[i][j] = 255 * (j - data->range_values[i][0]) / (data->range_values[i][1] - data->range_values[i][0]);
else if(j >= data->range_values[i][2] && data->range_values[i][3] > data->range_values[i][2])
data->lookup_table[i][j] = 255 * (data->range_values[i][3] - j) / (data->range_values[i][3] - data->range_values[i][2]);
else
data->lookup_table[i][j] = 0;
}
else
{
data->lookup_table[i][j] = 0;
}
}
}
}
else
{
memset(data->lookup_table[i], 0, 360);
}
}
}
psd_adjustment_blend_color(context, layer, dst_rect, psd_hue_saturation_proc, layer_info_data);
layer->adjustment_valid = psd_false;
return psd_true;
}