summaryrefslogtreecommitdiff
path: root/vaa3d_wrapper/loadV3dFFMpeg.cpp
blob: 90a6dbc3925b999c9e2dd8d5bf1e38696a772ad1 (plain)
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
136
137
138
139
140
141
142
143
#include "loadV3dFFMpeg.h"
#include "FFMpegVideo.h"
#include <iostream>

#ifdef USE_FFMPEG

using namespace std;

bool saveStackFFMpeg(const char * file_name, const My4DImage& img, enum CodecID codec_id)
{
    try {
        Image4DProxy<My4DImage> proxy(const_cast<My4DImage*>(&img));
        double default_irange = 1.0; // assumes data range is 0-255.0
        if (proxy.su > 1) {
            default_irange = 1.0 / 16.0; // 0-4096, like our microscope images
        }
        std::vector<double> imin(proxy.sc, 0.0);
        std::vector<double> irange2(proxy.sc, default_irange);
        // rescale if converting from 16 bit to 8 bit
        if (proxy.su > 1) {
            if (img.p_vmin && img.p_vmax)
                proxy.set_minmax(img.p_vmin, img.p_vmax);
            if (proxy.has_minmax()) {
                for (int c = 0; c < proxy.sc; ++c) {
                    imin[c] = proxy.vmin[c];
                    irange2[c] = 255.0 / (proxy.vmax[c] - proxy.vmin[c]);
                }
            }
        }
        FFMpegEncoder encoder(file_name, proxy.sx, proxy.sy, codec_id);
        for (int z = 0; z < proxy.sz; ++z) {
            for (int y = 0; y < proxy.sy; ++y) {
                for (int x = 0; x < proxy.sx; ++x) {
                    for (int c = 0; c < 3; ++c) {
                        int ic = c;
                        if (c >= proxy.sc) ic = 0; // single channel volume to gray RGB movie
                        double val = proxy.value_at(x, y, z, ic);
                        val = (val - imin[ic]) * irange2[ic]; // rescale to range 0-255
                        encoder.setPixelIntensity(x, y, c, (int)val);
                    }
                }
            }
            encoder.write_frame();
        }
        return true;
    } catch (...) {}

    return false;
}

bool loadStackFFMpeg(const char* fileName, Image4DSimple& img)
{
    return loadStackFFMpeg(QUrl::fromLocalFile(fileName), img);
}

bool loadStackFFMpeg(QUrl url, Image4DSimple& img)
{
    try {
        FFMpegVideo video(url);
        if (! video.isOpen)
            return false;
        int sx = video.getWidth();
        int sy = video.getHeight();
        int sz = video.getNumberOfFrames();
        int sc = video.getNumberOfChannels();
        // cout << "Number of frames = " << sz << endl;

        img.createBlankImage(sx, sy, sz, sc, 1); // 1 byte = 8 bits per value
        Image4DProxy<Image4DSimple> proxy(&img);

        int frameCount = 0;
        for (int z = 0; z < sz; ++z)
        {
            video.fetchFrame(z);
            int z = frameCount;
            frameCount++;
            for(int c = 0; c < sc; ++c) {
                for (int y = 0; y < sy; ++y) {
                    for (int x = 0; x < sx; ++x) {
                        proxy.put_at(x, y, z, c,
                                     video.getPixelIntensity(x, y, (FFMpegVideo::Channel)c)
                                     );
                    }
                }
            }
        }
        cout << "Number of frames found = " << frameCount << endl;

        return true;

    } catch(...) {}

    return false;
}

bool loadStackFFMpegAsGray(const char* fileName, Image4DSimple& img)
{
    loadStackFFMpegAsGray(QUrl::fromLocalFile(fileName), img);
}

bool loadStackFFMpegAsGray(QUrl url, Image4DSimple& img)
{
    try {
        FFMpegVideo video(url);
        int sx = video.getWidth();
        int sy = video.getHeight();
        int sz = video.getNumberOfFrames();
        int sc = video.getNumberOfChannels();
        // cout << "Number of frames = " << sz << endl;

        img.createBlankImage(sx, sy, sz, 1, 1); // 1 byte = 8 bits per value
        Image4DProxy<Image4DSimple> proxy(&img);

        int frameCount = 0;
        for (int z = 0; z < sz; ++z)
        {
            video.fetchFrame(z);
            int z = frameCount;
            frameCount++;
            for (int y = 0; y < sy; ++y) {
                for (int x = 0; x < sx; ++x) {
                    // Use average of R,G,B as gray value
                    int val = 0;
                    for(int c = 0; c < sc; ++c) {
                        val += video.getPixelIntensity(x, y, (FFMpegVideo::Channel)c);
                    }
                    val /= sc; // average of rgb
                    proxy.put_at(x, y, z, 0, val);
                }
            }
        }
        // cout << "Number of frames found = " << frameCount << endl;

        return true;

    } catch(...) {}

    return false;
}

#endif // USE_FFMPEG