mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@61945 954022d7-b5bf-4e40-9824-e11837661b57
247 lines
9.4 KiB
C
247 lines
9.4 KiB
C
/**
|
||
* 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;
|
||
}
|
||
|