• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 17270491352

27 Aug 2025 02:57PM UTC coverage: 65.333%. Remained the same
17270491352

push

github

paulmthompson
Merge branch 'main' of https://github.com/paulmthompson/WhiskerToolbox

352 of 628 new or added lines in 92 files covered. (56.05%)

357 existing lines in 24 files now uncovered.

26429 of 40453 relevant lines covered (65.33%)

1119.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.26
/src/DataManager/IO/OpenCV/OpenCVFormatLoader.cpp
1
#include "OpenCVFormatLoader.hpp"
2

3
#include "Mask_Data_Image.hpp"
4
#include "Masks/Mask_Data.hpp"
5

6
#include <iostream>
7

8
LoadResult OpenCVFormatLoader::load(std::string const& filepath, 
1✔
9
                                   IODataType dataType, 
10
                                   nlohmann::json const& config, 
11
                                   DataFactory* factory) const {
12
    if (!factory) {
1✔
13
        return LoadResult("DataFactory is null");
×
14
    }
15

16
    switch (dataType) {
1✔
17
        case IODataType::Mask:
1✔
18
            return loadMaskDataImage(filepath, config, factory);
1✔
19
            
20
        default:
×
21
            return LoadResult("OpenCV loader does not support data type: " + std::to_string(static_cast<int>(dataType)));
×
22
    }
23
}
24

25
bool OpenCVFormatLoader::supportsFormat(std::string const& format, IODataType dataType) const {
16✔
26
    // Support image format for MaskData
27
    if (format == "image" && dataType == IODataType::Mask) {
16✔
28
        return true;
4✔
29
    }
30
    
31
    return false;
12✔
32
}
33

34
LoadResult OpenCVFormatLoader::save(std::string const& filepath, 
×
35
                                    IODataType dataType, 
36
                                    nlohmann::json const& config, 
37
                                    void const* data) const {
38
    if (dataType != IODataType::Mask) {
×
39
        return LoadResult("OpenCVFormatLoader only supports saving MaskData");
×
40
    }
41
    
42
    if (!data) {
×
43
        return LoadResult("Data pointer is null");
×
44
    }
45
    
46
    try {
47
        // Cast void pointer back to MaskData
48
        auto const* mask_data = static_cast<MaskData const*>(data);
×
49
        
50
        // Convert JSON config to ImageMaskSaverOptions
51
        ImageMaskSaverOptions save_opts;
×
52
        save_opts.parent_dir = config.value("parent_dir", ".");
×
53
        save_opts.image_format = config.value("image_format", "PNG");
×
54
        save_opts.filename_prefix = config.value("filename_prefix", "");
×
55
        save_opts.frame_number_padding = config.value("frame_number_padding", 4);
×
56
        save_opts.image_width = config.value("image_width", 640);
×
57
        save_opts.image_height = config.value("image_height", 480);
×
58
        save_opts.background_value = config.value("background_value", 0);
×
59
        save_opts.mask_value = config.value("mask_value", 255);
×
60
        save_opts.overwrite_existing = config.value("overwrite_existing", false);
×
61
        
62
        // Call the existing save function
63
        ::save(mask_data, save_opts);
×
64
        
65
        // Return success
NEW
66
        LoadResult result;
×
NEW
67
        result.success = true;
×
NEW
68
        return result;
×
69
        
70
    } catch (std::exception const& e) {
×
71
        return LoadResult("OpenCVFormatLoader save failed: " + std::string(e.what()));
×
UNCOV
72
    }
×
73
}
74

75
std::string OpenCVFormatLoader::getLoaderName() const {
92✔
76
    return "OpenCVFormatLoader";
276✔
77
}
78

79
LoadResult OpenCVFormatLoader::loadMaskDataImage(std::string const& filepath, 
1✔
80
                                                nlohmann::json const& config, 
81
                                                DataFactory* factory) const {
82
    try {
83
        // Configure image loading parameters
84
        ImageMaskLoaderOptions load_opts;
1✔
85
        load_opts.directory_path = filepath;  // filepath is actually directory path for images
1✔
86
        
87
        // Extract configuration with defaults
88
        if (config.contains("file_pattern")) {
1✔
89
            load_opts.file_pattern = config["file_pattern"];
1✔
90
        }
91
        if (config.contains("filename_prefix")) {
1✔
92
            load_opts.filename_prefix = config["filename_prefix"];
1✔
93
        }
94
        if (config.contains("frame_number_padding")) {
1✔
95
            load_opts.frame_number_padding = config["frame_number_padding"];
1✔
96
        }
97
        if (config.contains("threshold_value")) {
1✔
98
            load_opts.threshold_value = config["threshold_value"];
1✔
99
        }
100
        if (config.contains("invert_mask")) {
1✔
101
            load_opts.invert_mask = config["invert_mask"];
1✔
102
        }
103
        
104
        // Load using existing image loading functionality
105
        auto loaded_mask_data = ::load(load_opts);
1✔
106
        if (!loaded_mask_data) {
1✔
UNCOV
107
            return LoadResult("Failed to load image MaskData from: " + filepath);
×
108
        }
109
        
110
        // Convert to factory-created object
111
        // First extract the data from the loaded MaskData
112
        std::map<TimeFrameIndex, std::vector<Mask2D>> mask_map;
1✔
113
        for (auto const& time : loaded_mask_data->getTimesWithData()) {
4✔
114
            mask_map[time] = loaded_mask_data->getAtTime(time);
3✔
115
        }
116
        
117
        // Create new MaskData using factory
118
        auto mask_data_variant = factory->createMaskData();
1✔
119
        
120
        // Apply the loaded data to the factory-created object
121
        if (std::holds_alternative<std::shared_ptr<MaskData>>(mask_data_variant)) {
1✔
122
            auto new_mask_data = std::get<std::shared_ptr<MaskData>>(mask_data_variant);
1✔
123
            
124
            // Copy masks to the new object
125
            for (auto const& [time, masks] : mask_map) {
4✔
126
                for (auto const& mask : masks) {
6✔
127
                    new_mask_data->addAtTime(time, mask, false);
3✔
128
                }
129
            }
130
            
131
            // Apply image size from the loaded data
132
            ImageSize image_size = loaded_mask_data->getImageSize();
1✔
133
            if (image_size.width > 0 && image_size.height > 0) {
1✔
UNCOV
134
                new_mask_data->setImageSize(image_size);
×
135
            }
136
            
137
            // Apply image size override from config if specified
138
            if (config.contains("image_width") && config.contains("image_height")) {
1✔
UNCOV
139
                int width = config["image_width"];
×
UNCOV
140
                int height = config["image_height"];
×
UNCOV
141
                new_mask_data->setImageSize(ImageSize(width, height));
×
142
            }
143
            
144
            // Notify observers once at the end
145
            new_mask_data->notifyObservers();
1✔
146
            
147
            return LoadResult(std::move(mask_data_variant));
1✔
148
        } else {
1✔
UNCOV
149
            return LoadResult("Factory did not create MaskData object");
×
150
        }
151
        
152
    } catch (std::exception const& e) {
1✔
UNCOV
153
        return LoadResult("OpenCV image loading failed: " + std::string(e.what()));
×
UNCOV
154
    }
×
155
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc