devilimagereader.cpp 10.4 KB
Newer Older
schultezub's avatar
schultezub committed
1 2 3 4
// ================================================================================================
// 
// This file is part of the CAMPVis Software Framework.
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
schultezub's avatar
schultezub committed
6 7
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
8 9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
schultezub's avatar
schultezub committed
11 12
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
// 
13 14 15 16
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
schultezub's avatar
schultezub committed
17
// 
18 19 20 21
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
schultezub's avatar
schultezub committed
22 23 24 25 26 27 28 29
// 
// ================================================================================================

#include "devilimagereader.h"


#include <IL/il.h>
#include <cstring>
Hossain Mahmud's avatar
Hossain Mahmud committed
30
#include <vector>
schultezub's avatar
schultezub committed
31

32 33 34 35
#include "cgt/logmanager.h"
#include "cgt/filesystem.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
schultezub's avatar
schultezub committed
36

37 38
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
39
#include "core/datastructures/renderdata.h"
40
#include "core/datastructures/genericimagerepresentationlocal.h"
schultezub's avatar
schultezub committed
41

schultezub's avatar
schultezub committed
42
#include "core/tools/quadrenderer.h"
Hossain Mahmud's avatar
Hossain Mahmud committed
43 44
#include "core/tools/stringutils.h"
#include "core/tools/mapping.h"
schultezub's avatar
schultezub committed
45

schultezub's avatar
schultezub committed
46 47 48 49

namespace campvis {
    const std::string DevilImageReader::loggerCat_ = "CAMPVis.modules.io.DevilImageReader";

50
    GenericOption<std::string> importOptions[3] = {
51
        GenericOption<std::string>("rt", "Render Target"),
Hossain Mahmud's avatar
Hossain Mahmud committed
52 53
        GenericOption<std::string>("localIntensity", "Local Intensity Image"),
        GenericOption<std::string>("localIntensity3", "Local Intensity Image RGB")
54 55
    };

56 57
    DevilImageReader::DevilImageReader()
        : AbstractImageReader()
58
        , p_importType("ImportType", "Import Type", importOptions, 3)
Hossain Mahmud's avatar
Hossain Mahmud committed
59
        , p_importSimilar("ImportSimilar", "Import All Similar Files", false)
60
        , _shader(nullptr)
schultezub's avatar
schultezub committed
61
    {
62 63 64 65
        this->_ext.push_back("bmp");
        this->_ext.push_back("jpg");
        this->_ext.push_back("png");
        this->_ext.push_back("tif");
Hossain Mahmud's avatar
Hossain Mahmud committed
66 67
        this->p_targetImageID.setValue("DevilImageReader.output");

68 69 70
        addProperty(p_url);
        addProperty(p_targetImageID);
        addProperty(p_importType);
Hossain Mahmud's avatar
Hossain Mahmud committed
71
        addProperty(p_importSimilar);
schultezub's avatar
schultezub committed
72 73 74 75 76
    }

    DevilImageReader::~DevilImageReader() {
    }

schultezub's avatar
schultezub committed
77
    void DevilImageReader::init() {
78
        AbstractImageReader::init();
79
        _shader = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "#define NO_DEPTH\n");
schultezub's avatar
schultezub committed
80 81 82
    }

    void DevilImageReader::deinit() {
83
        AbstractImageReader::deinit();
schultezub's avatar
schultezub committed
84 85 86
        ShdrMgr.dispose(_shader);
    }

87
    void DevilImageReader::updateResult(DataContainer& data) {
88
        const std::string& url = p_url.getValue();
89 90 91
        std::string directory = cgt::FileSystem::dirName(url);
        std::string base = cgt::FileSystem::baseName(url);
        std::string ext = cgt::FileSystem::fileExtension(url);
Hossain Mahmud's avatar
Hossain Mahmud committed
92

93 94 95 96 97
        // check whether we open an image series
        size_t suffixPos = base.find_last_not_of("0123456789");
        if (suffixPos != std::string::npos)
            ++suffixPos;
        size_t suffixLength = (suffixPos == std::string::npos) ? 0 : base.length() - suffixPos;
Hossain Mahmud's avatar
Hossain Mahmud committed
98

99 100 101 102 103 104 105 106 107
        // assemble the list of files to read
        std::vector<std::string> files;
        if (suffixLength == 0 || !p_importSimilar.getValue()) {
            files.push_back(url);
        }
        else {
            std::string prefix = base.substr(0, suffixPos);
            int index = StringUtils::fromString<int>(base.substr(suffixPos));

108
            while (cgt::FileSystem::fileExists(directory + "/" + prefix + StringUtils::toString(index, suffixLength, '0') + "." + ext)) {
109 110
                files.push_back(directory + "/" + prefix + StringUtils::toString(index, suffixLength, '0') + "." + ext);
                ++index;
111
            }
112 113
        }

114 115
        if (files.empty())
            return;
116

117
        cgt::ivec3 imageSize(0, 0, static_cast<int>(files.size()));
118 119 120 121 122 123 124 125 126
        uint8_t* buffer = nullptr;

        ILint devilFormat = 0;
        if (p_importType.getOptionValue() == "localIntensity") 
            devilFormat = IL_LUMINANCE;
        else if (p_importType.getOptionValue() == "localIntensity3") 
            devilFormat = IL_RGB;
        else if (p_importType.getOptionValue() == "rt") 
            devilFormat = IL_RGBA;
127

128
        ILint devilDataType = 0;
129
        WeaklyTypedPointer::BaseType campvisDataType = WeaklyTypedPointer::UINT8;
130 131 132 133 134 135 136 137 138 139 140 141 142 143
        size_t numChannels = 1;

        // start reading
        for (size_t i = 0; i < files.size(); ++i) {
            // prepare DevIL
            ILuint img;
            ilGenImages(1, &img);
            ilBindImage(img);

            // try load file
            if (! ilLoadImage(files[i].c_str())) {
                LERROR("Could not load image: " << files[i]);
                delete [] buffer;
                return;
144
            }
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

            // prepare buffer and perform dimensions check
            if (i == 0) {
                imageSize.x = ilGetInteger(IL_IMAGE_WIDTH);
                imageSize.y = ilGetInteger(IL_IMAGE_HEIGHT);

                if (devilFormat == 0)
                    devilFormat = ilGetInteger(IL_IMAGE_FORMAT);

                switch (ilGetInteger(IL_IMAGE_TYPE)) {
                    case IL_UNSIGNED_BYTE:
                        devilDataType = IL_UNSIGNED_BYTE;
                        campvisDataType = WeaklyTypedPointer::UINT8;
                        break;
                    case IL_BYTE:
                        devilDataType = IL_BYTE;
                        campvisDataType = WeaklyTypedPointer::INT8;
                        break;
                    case IL_UNSIGNED_SHORT:
                        devilDataType = IL_UNSIGNED_SHORT;
                        campvisDataType = WeaklyTypedPointer::UINT16;
                        break;
                    case IL_SHORT:
                        devilDataType = IL_SHORT;
                        campvisDataType = WeaklyTypedPointer::INT16;
                        break;
                    case IL_UNSIGNED_INT:
                        devilDataType = IL_UNSIGNED_INT;
                        campvisDataType = WeaklyTypedPointer::UINT32;
Hossain Mahmud's avatar
Hossain Mahmud committed
174
                        break;
175 176 177 178 179 180 181 182 183 184 185
                    case IL_INT:
                        devilDataType = IL_INT;
                        campvisDataType = WeaklyTypedPointer::INT32;
                        break;
                    case IL_FLOAT:
                        devilDataType = IL_FLOAT;
                        campvisDataType = WeaklyTypedPointer::FLOAT;
                        break;
                    default:
                        LERROR("unsupported data type: " << ilGetInteger(IL_IMAGE_TYPE) << " (" << files[i] << ")");
                        return;
186
                }
Hossain Mahmud's avatar
Hossain Mahmud committed
187

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
                switch (devilFormat) {
                    case IL_LUMINANCE:
                        numChannels = 1;
                        break;
                    case IL_LUMINANCE_ALPHA:
                        numChannels = 2;
                        break;
                    case IL_RGB:
                        numChannels = 3;
                        break;
                    case IL_RGBA:
                        numChannels = 4;
                        break;
                    default:
                        LERROR("unsupported image format: " << devilFormat << " (" << files[i] << ")");
                        return;
                }
205
                buffer = new uint8_t[cgt::hmul(imageSize) * WeaklyTypedPointer::numBytes(campvisDataType, numChannels)];
206 207 208 209 210 211 212 213 214 215 216 217 218
            }
            else {
                if (imageSize.x != ilGetInteger(IL_IMAGE_WIDTH)) {
                    LERROR("Could not load images: widths do not match!");
                    delete [] buffer;
                    return;
                }
                if (imageSize.y != ilGetInteger(IL_IMAGE_HEIGHT)) {
                    LERROR("Could not load images: heights do not match!");
                    delete [] buffer;
                    return;
                }
            }
Hossain Mahmud's avatar
Hossain Mahmud committed
219

220 221 222 223 224 225 226
            // get data from image and transform to single intensity image:
            ilCopyPixels(0, 0, 0, imageSize.x, imageSize.y, 1, devilFormat, devilDataType, buffer + (WeaklyTypedPointer::numBytes(campvisDataType, numChannels) * i * imageSize.x * imageSize.y));
            ILint err = ilGetError();
            if (err != IL_NO_ERROR) {
                LERROR("Error during conversion: " << iluErrorString(err));
                delete [] buffer;
                return;
Hossain Mahmud's avatar
Hossain Mahmud committed
227
            }
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

            ilDeleteImage(img);
        }

        size_t dimensionality = 3;
        if (imageSize.z == 1)
            dimensionality = 2;
        if (imageSize.y == 1)
            dimensionality = 1;


        ImageData* id = new ImageData(dimensionality, imageSize, numChannels);
        WeaklyTypedPointer wtp(campvisDataType, numChannels, buffer);
        ImageRepresentationLocal::create(id, wtp);
        //id->setMappingInformation(ImageMappingInformation(imageSize, p_imageOffset.getValue(), p_voxelSize.getValue()));

        if (p_importType.getOptionValue() == "rt") {
            RenderData* rd = new RenderData();
            rd->addColorTexture(id);

            // create fake depth image
249
            // TODO: think of a better solution to this...
250
            ImageData* idDepth = new ImageData(dimensionality, imageSize, 1);
251
            float* ptr = new float[cgt::hmul(imageSize)];
252
            memset(ptr, 0, cgt::hmul(imageSize) * sizeof(float));
253 254 255 256 257
            WeaklyTypedPointer wtpDepth(campvisDataType, 1, ptr);
            ImageRepresentationLocal::create(idDepth, wtpDepth);
            rd->setDepthTexture(idDepth);

            data.addData(p_targetImageID.getValue(), rd);
schultezub's avatar
schultezub committed
258
        }
schultezub's avatar
schultezub committed
259
        else {
260
            data.addData(p_targetImageID.getValue(), id);
schultezub's avatar
schultezub committed
261 262 263
        }
    }
}