File size: 4,699 Bytes
2c51ce3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
 * ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ๊ธฐ๋Šฅ์„ ์œ„ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ
 * ์ด๋ฏธ์ง€ ํ•„ํ„ฐ ์ ์šฉ, ๊ด€๋ฆฌ์— ๊ด€๋ จ๋œ ๋ชจ๋“  ํ•จ์ˆ˜๋ฅผ ํฌํ•จ
 */

// ํ•„ํ„ฐ ๊ธฐ๋ณธ๊ฐ’
const DEFAULT_FILTERS = {
    temperature: 0,
    brightness: 100,
    contrast: 100,
    saturation: 100
};

/**
 * ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์— ํ•„ํ„ฐ ์ ์šฉ
 * @param {ImageData} imageData - ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ
 * @param {Object} filters - ํ•„ํ„ฐ ์„ค์ • (temperature, brightness, contrast, saturation)
 * @returns {ImageData} - ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋œ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ
 */
function applyFilters(imageData, filters) {
    const {temperature, brightness, contrast, saturation} = filters;
    
    const data = imageData.data;
    
    // ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์˜ ๊ฐ ํ”ฝ์…€์— ํ•„ํ„ฐ ์ ์šฉ
    for (let i = 0; i < data.length; i += 4) {
        // RGB ๊ฐ’ ์ถ”์ถœ
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];
        
        // ์ƒ‰์˜จ๋„ ์ ์šฉ (๋นจ๊ฐ„์ƒ‰/ํŒŒ๋ž€์ƒ‰ ์กฐ์ •)
        if (temperature !== 0) {
            const tempValue = temperature / 5; // ํšจ๊ณผ ๊ฐ•๋„ ์กฐ์ •
            if (tempValue > 0) {
                // ๋”ฐ๋œปํ•œ ์ƒ‰์กฐ (๋” ๋นจ๊ฐ›๊ฒŒ)
                r = Math.min(255, r + tempValue);
                b = Math.max(0, b - tempValue / 2);
            } else {
                // ์ฐจ๊ฐ€์šด ์ƒ‰์กฐ (๋” ํŒŒ๋ž—๊ฒŒ)
                r = Math.max(0, r + tempValue);
                b = Math.min(255, b - tempValue * 1.5);
            }
        }
        
        // ๋ฐ๊ธฐ ์ ์šฉ (๋ชจ๋“  ์ƒ‰์ƒ ์ฑ„๋„์— ๊ท ์ผํ•˜๊ฒŒ ์ ์šฉ)
        const brightnessMultiplier = brightness / 100;
        r = Math.min(255, r * brightnessMultiplier);
        g = Math.min(255, g * brightnessMultiplier);
        b = Math.min(255, b * brightnessMultiplier);
        
        // ๋Œ€๋น„ ์ ์šฉ
        const contrastFactor = (contrast / 100);
        r = Math.min(255, Math.max(0, (r - 128) * contrastFactor + 128));
        g = Math.min(255, Math.max(0, (g - 128) * contrastFactor + 128));
        b = Math.min(255, Math.max(0, (b - 128) * contrastFactor + 128));
        
        // ์ฑ„๋„ ์ ์šฉ
        const avg = (r + g + b) / 3;
        const saturationMultiplier = saturation / 100;
        r = Math.min(255, Math.max(0, avg + (r - avg) * saturationMultiplier));
        g = Math.min(255, Math.max(0, avg + (g - avg) * saturationMultiplier));
        b = Math.min(255, Math.max(0, avg + (b - avg) * saturationMultiplier));
        
        // ๊ฐ’ ๋‹ค์‹œ ์ €์žฅ
        data[i] = Math.round(r);
        data[i + 1] = Math.round(g);
        data[i + 2] = Math.round(b);
    }
    
    return imageData;
}

/**
 * ์ด๋ฏธ์ง€์— ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•˜์—ฌ ์ƒˆ ์บ”๋ฒ„์Šค์— ๊ทธ๋ฆฌ๊ธฐ
 * @param {HTMLImageElement} image - ์›๋ณธ ์ด๋ฏธ์ง€
 * @param {Object} filters - ํ•„ํ„ฐ ์„ค์ •
 * @returns {HTMLCanvasElement} - ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋œ ์ด๋ฏธ์ง€๊ฐ€ ๊ทธ๋ ค์ง„ ์บ”๋ฒ„์Šค
 */
function createFilteredCanvas(image, filters) {
    if (!image) return null;
    
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = image.width;
    tempCanvas.height = image.height;
    const tempCtx = tempCanvas.getContext('2d');
    
    // ์›๋ณธ ์ด๋ฏธ์ง€ ๊ทธ๋ฆฌ๊ธฐ
    tempCtx.drawImage(image, 0, 0);
    
    // ํ•„ํ„ฐ ์ ์šฉ
    const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
    const filteredData = applyFilters(imageData, filters);
    tempCtx.putImageData(filteredData, 0, 0);
    
    return tempCanvas;
}

/**
 * ์„ ํƒ๋œ ๋ ˆ์ด์–ด์—๋งŒ ํ•„ํ„ฐ ์ ์šฉ
 * @param {Array} overlays - ๋ ˆ์ด์–ด ๋ฐฐ์—ด
 * @param {number} activeOverlayIndex - ํ˜„์žฌ ํ™œ์„ฑ ๋ ˆ์ด์–ด ์ธ๋ฑ์Šค
 * @param {Object} filterValues - ์ ์šฉํ•  ํ•„ํ„ฐ ๊ฐ’
 */
function applyFilterToLayer(overlays, activeOverlayIndex, filterValues) {
    if (activeOverlayIndex >= 0 && activeOverlayIndex < overlays.length) {
        // ํ˜„์žฌ ์„ ํƒ๋œ ๋ ˆ์ด์–ด์—๋งŒ ํ•„ํ„ฐ ์ ์šฉ
        overlays[activeOverlayIndex].filters = { ...filterValues };
    }
}

/**
 * ํ•„ํ„ฐ ์ดˆ๊ธฐํ™”
 * @param {Array} overlays - ๋ ˆ์ด์–ด ๋ฐฐ์—ด
 * @param {number} activeOverlayIndex - ํ˜„์žฌ ํ™œ์„ฑ ๋ ˆ์ด์–ด ์ธ๋ฑ์Šค
 * @returns {Object} - ์ดˆ๊ธฐํ™”๋œ ํ•„ํ„ฐ ๊ฐ’
 */
function resetFilters(overlays, activeOverlayIndex) {
    // ํ˜„์žฌ ๋ ˆ์ด์–ด์˜ ํ•„ํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”
    if (activeOverlayIndex >= 0 && activeOverlayIndex < overlays.length) {
        overlays[activeOverlayIndex].filters = { ...DEFAULT_FILTERS };
    }
    
    // ์ดˆ๊ธฐ ํ•„ํ„ฐ ๊ฐ’ ๋ฐ˜ํ™˜
    return { ...DEFAULT_FILTERS };
}

// filter.js์˜ ํ•จ์ˆ˜๋ฅผ ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ „์—ญ์œผ๋กœ ๋…ธ์ถœ
window.ImageFilters = {
    applyFilters,
    createFilteredCanvas,
    applyFilterToLayer,
    resetFilters,
    DEFAULT_FILTERS
};