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); } }
static void psd_channel_mixer_proc(psd_uint layer_info_data, psd_int * red, psd_int * green, psd_int * blue) { psd_layer_channel_mixer * data = (psd_layer_channel_mixer *)layer_info_data; psd_int dst_red, dst_green, dst_blue, src_red, src_green, src_blue, gray; src_red = *red; src_green = *green; src_blue = *blue; if(data->monochrome == psd_true) { gray = 0; gray += src_red * data->red_cyan[0] / 100; gray += src_green * data->green_magenta[0] / 100; gray += src_blue * data->blue_yellow[0] / 100; gray += data->constant[0] * 255 / 100; gray = PSD_CONSTRAIN(gray, 0, 255); *red = gray; *green = gray; *blue = gray; } else { if(data->red_cyan[0] != 100 || data->green_magenta[0] != 0 || data->blue_yellow[0] != 0 || data->constant[0] != 0) { dst_red = 0; dst_red += src_red * data->red_cyan[0] / 100; dst_red += src_green * data->green_magenta[0] / 100; dst_red += src_blue * data->blue_yellow[0] / 100; dst_red += data->constant[0] * 255 / 100; *red = PSD_CONSTRAIN(dst_red, 0, 255); } if(data->green_magenta[1] != 100 || data->red_cyan[1] != 0 || data->blue_yellow[1] != 0 || data->constant[1] != 0) { dst_green = 0; dst_green += src_green * data->green_magenta[1] / 100; dst_green += src_red * data->red_cyan[1] / 100; dst_green += src_blue * data->blue_yellow[1] / 100; dst_green += data->constant[1] * 255 / 100; *green = PSD_CONSTRAIN(dst_green, 0, 255); } if(data->blue_yellow[2] != 100 || data->red_cyan[2] != 0 || data->green_magenta[2] != 0 || data->constant[2] != 0) { dst_blue = 0; dst_blue += src_blue * data->blue_yellow[2] / 100; dst_blue += src_red * data->red_cyan[2] / 100; dst_blue += src_green * data->green_magenta[2] / 100; dst_blue += data->constant[2] * 255 / 100; *blue = PSD_CONSTRAIN(dst_blue, 0, 255); } } }
void psd_adjustment_blend_rgb(psd_context * context, psd_layer_record * layer, psd_rect * dst_rect, psd_uchar * red_lookup_table, psd_uchar * green_lookup_table, psd_uchar * blue_lookup_table, psd_bool preserve_luminosity) { psd_int i, j, width, height; psd_int dst_red, dst_green, dst_blue, dst_alpha, src_red, src_green, src_blue; psd_argb_color *src_data, * dst_data, src_color; psd_int dst_luminosity, src_luminosity, value; width = psd_rect_width(dst_rect); height = psd_rect_height(dst_rect); for(i = 0; i < height; i ++) { src_data = context->blending_image_data + (dst_rect->top + i) * context->width + dst_rect->left; dst_data = layer->image_data + (dst_rect->top + i) * layer->width + dst_rect->left; for(j = 0; j < width; j ++, src_data ++, dst_data ++) { src_color = *src_data; dst_alpha = PSD_GET_ALPHA_COMPONENT(src_color); src_red = PSD_GET_RED_COMPONENT(src_color); src_green = PSD_GET_GREEN_COMPONENT(src_color); src_blue = PSD_GET_BLUE_COMPONENT(src_color); dst_red = red_lookup_table[src_red]; dst_green = green_lookup_table[src_green]; dst_blue = blue_lookup_table[src_blue]; if(preserve_luminosity == psd_true) { src_luminosity = psd_rgb_get_brightness(src_red, src_green, src_blue); dst_luminosity = psd_rgb_get_brightness(dst_red, dst_green, dst_blue); value = dst_red * src_luminosity / dst_luminosity; src_red = PSD_CONSTRAIN(value, 0, 255); value = dst_green * src_luminosity / dst_luminosity; src_green = PSD_CONSTRAIN(value, 0, 255); value = dst_blue * src_luminosity / dst_luminosity; src_blue = PSD_CONSTRAIN(value, 0, 255); } *dst_data = PSD_ARGB_TO_COLOR(dst_alpha, dst_red, dst_green, dst_blue); } } }
psd_bool psd_layer_blend_levels(psd_context * context, psd_layer_record * layer, psd_rect * dst_rect) { psd_int i, j, range, floor, value; psd_float gamma; psd_layer_levels * data = NULL; psd_uchar input_table[256], output_table[256]; if(context->color_mode != psd_color_mode_rgb && context->color_mode != psd_color_mode_grayscale) return psd_false; for(i = 0; i < layer->layer_info_count; i ++) { if(layer->layer_info_type[i] == psd_layer_info_type_levels) { data = (psd_layer_levels *)layer->layer_info_data[i]; break; } } if(data == NULL) return psd_false; if(layer->adjustment_valid == psd_true) { for(i = 0; i < 3; i ++) { for(j = 0; j < 256; j ++) data->lookup_table[i][j] = j; } for(i = 0; i < 4; i ++) { if(data->record[i].input_floor != 0 || data->record[i].input_ceiling != 255 || data->record[i].output_floor != 0 || data->record[i].output_ceiling != 255 || data->record[i].gamma != 1.0) { if(layer->adjustment_valid == psd_true) { if(data->record[i].input_floor != 0 || data->record[i].input_ceiling != 255 || data->record[i].gamma != 1.0) { range = data->record[i].input_ceiling - data->record[i].input_floor; floor = data->record[i].input_floor; if(data->record[i].gamma != 1.0) { gamma = 1 / data->record[i].gamma; for(j = 0; j < 256; j ++) { value = (psd_int)(pow((psd_float)(j - floor) / range, gamma) * 255 + 0.5); input_table[j] = PSD_CONSTRAIN(value, 0, 255); } } else { for(j = 0; j < 256; j ++) { value = (psd_int)((j - floor) * 255.0 / range); input_table[j] = PSD_CONSTRAIN(value, 0, 255); } } } else { for(j = 0; j < 256; j ++) input_table[j] = j; } if(data->record[i].output_floor != 0 || data->record[i].output_ceiling != 255) { range = data->record[i].output_ceiling - data->record[i].output_floor; floor = data->record[i].output_floor; for(j = 0; j < 256; j ++) { output_table[j] = (j * range + 128) / 255 + floor; } } else { for(j = 0; j < 256; j ++) output_table[j] = j; } if(i == 0) { for(j = 0; j < 256; j ++) { data->lookup_table[0][j] = data->lookup_table[1][j] = data->lookup_table[2][j] = output_table[input_table[j]]; } } else { for(j = 0; j < 256; j ++) data->lookup_table[i - 1][j] = output_table[input_table[data->lookup_table[i - 1][j]]]; } } } if(context->color_mode == psd_color_mode_grayscale) break; } } psd_adjustment_blend_rgb(context, layer, dst_rect, data->lookup_table[0], data->lookup_table[1], data->lookup_table[2], psd_false); layer->adjustment_valid = psd_false; return psd_true; }