File: image_utils.cpp

package info (click to toggle)
satdump 1.2.2%2Bgb79af48-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 81,648 kB
  • sloc: cpp: 276,768; ansic: 164,598; lisp: 1,219; sh: 283; xml: 106; makefile: 7
file content (131 lines) | stat: -rw-r--r-- 4,778 bytes parent folder | download | duplicates (2)
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
#include "image_utils.h"
#include "core/exception.h"

namespace image
{
    Image make_manyimg_composite(int count_width, int count_height, int img_cnt, std::function<Image(int cnt)> get_img_func)
    {
        Image first_img = get_img_func(0);
        int img_w = first_img.width();
        int img_h = first_img.height();

        Image image_all(first_img.depth(), img_w * count_width, img_h * count_height, first_img.channels());

        first_img.clear();

        for (int row = 0; row < count_height; row++)
        {
            for (int column = 0; column < count_width; column++)
            {
                if (row * count_width + column >= img_cnt)
                    return image_all;

                image_all.draw_image(0, get_img_func(row * count_width + column), img_w * column, img_h * row);
            }
        }

        return image_all;
    }

    Image blend_images(std::vector<Image> &images)
    {
        if(images.size() == 0)
            throw satdump_exception("No images passed!");

        size_t width = images[0].width();
        size_t height = images[0].height();
        int channels = images[0].channels();
        bool are_rgba = channels == 4;

        for (Image &this_img : images)
        {
            if(this_img.depth() != 16)
                throw satdump_exception("blend_images must be the same bit depth, and 16");
            width = std::min(width, this_img.width());
            height = std::min(height, this_img.height());
            are_rgba &= this_img.channels() == 4;
        }

        Image img_b(16, width, height, channels);

        for (int c = 0; c < channels; c++)
        {
            if (are_rgba)
            {
                for (size_t i = 0; i < height * width; i++)
                {
                    if (c == 3)
                    {
                        double final_alpha = 0.0;
                        for (Image &this_img : images)
                            final_alpha = std::max(final_alpha, this_img.getf(3, i));
                        img_b.setf(c, i, final_alpha);
                    }
                    else
                    {
                        float num_layers = 0.0f;
                        double final_val = 0.0;
                        for (Image &this_img : images)
                        {
                            final_val += this_img.getf(c, i) * this_img.getf(3, i);
                            num_layers += this_img.getf(3, i);
                        }

                        img_b.setf(c, i, final_val / num_layers);
                    }
                }
            }
            else
            {
                for (size_t i = 0; i < height * width; i++)
                {
                    size_t num_layers = images.size();
                    double final_val = 0.0f;
                    for (Image& this_img : images)
                    {
                        float layer_val = this_img.getf(c, i);
                        if (layer_val == 0)
                            num_layers--;
                        else
                            final_val += layer_val;
                    }

                    img_b.setf(c, i, final_val / num_layers);
                }
            }
        }
        return img_b;
    }

    image::Image merge_images_opacity(image::Image &img1, image::Image &img2, float op)
    {
        if (img1.depth() != img2.depth() || img1.depth() != 16 || img2.depth() != 16)
            throw satdump_exception("merge_images_opacity must be the same bit depth, and 16");

        const size_t width = std::min<int>(img1.width(), img2.width());
        const size_t height = std::min<int>(img1.height(), img2.height());
        const int64_t size = width * height;
        const int channels_1 = img1.channels();
        const int channels_2 = img2.channels();
        const int color_channels = std::min(3, channels_1);
        image::Image ret(16, width, height, channels_1);

#pragma omp parallel for
        for (int64_t i = 0; i < size; i++)
        {
            float alpha_1 = channels_1 == 4 ? (float)img1.get(3, i) / 65535.0f : 1.0f;
            float alpha_2 = (channels_2 == 4 ? (float)img2.get(3, i) / 65535.0f : 1.0f) * op;
            float ret_alpha = alpha_2 + alpha_1 * (1.0f - alpha_2);
            for (int j = 0; j < color_channels; j++)
                ret.set(j, i, ((alpha_2 * ((float)img2.get(j, i) / 65535.0f) + alpha_1 * ((float)img1.get(j, i) / 65535.0f) * (1.0f - alpha_2)) / ret_alpha) * 65535.0f);

            if (channels_1 == 4)
                ret.set(3, i, ret_alpha * 65535.0f);
            else
                for (int j = 0; j < color_channels; j++)
                    ret.set(j, i, (float)ret.get(j, i) * ret_alpha);
        }

        return ret;
    }
}