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
#pragma once

#include <cassert>
#include <vector>
#include <string>
#include <sys/stat.h>
#include "matlab_utils.h"


class MyImage
{
private:
	std::vector<BYTE> pixels;
    int w, h, comp;

public:
    MyImage():w(0),h(0),comp(0) {}
    ~MyImage() { }

	/*MyImage(const std::string &filename, int ncomp=4):w(0), h(0),comp(0)
	{
        // not implemented
    }*/

	MyImage(const std::string &filename) :w(0), h(0), comp(0)		//read image
	{
		const std::string tempname("mytempval4c");
		matlabEval(tempname + std::string("= uint8(imread('") + filename + std::string("'));"), false);
		matlabEval((tempname + std::string("= permute(") + tempname + std::string(",[3,1,2]);")), false);
		mxArray *m = getMatEngine().getVariable(tempname);
		if (!m) {
			printf("read image failed!\n");
			return;
		}
		const mwSize* ImageSize = mxGetDimensions(m);
		comp = ImageSize[0];
		w = ImageSize[1];
		h = ImageSize[2];
		const BYTE *data = (BYTE*)mxGetData(m);
		pixels = std::vector<BYTE>(data, data + comp * w*h);
		mxDestroyArray(m);
		getMatEngine().eval("clear " + tempname + ";");
	}


    MyImage(BYTE* data, int ww, int hh, int pitch, int ncomp = 3) :w(ww), h(hh), comp(ncomp)
    {
        assert(pitch >= ww * 3);
		if (pitch == w*comp) pixels = std::vector<BYTE>(data, data + pitch*h);
		else {
			pixels.resize(w*comp*h);
			for (int i = 0; i < h; i++) std::copy_n(data + pitch*i, pitch, pixels.data() + i*w*comp);
		}
	}

	void img_malloc(int ww, int hh, int ncomp = 3)
	{
		w = ww;
		h = hh;
		comp = ncomp;
		pixels.resize(w * h * comp);
	}

    static int alignment() { return 1; }  // OpenGL only supports 1,2,4,8, do not use 8, it is buggy

    inline bool empty() const { return pixels.empty(); }

	inline BYTE* data() { return pixels.data(); }
	inline const BYTE* data() const { return pixels.data(); }
	inline int width() const { return w; }
	inline int height() const { return h; }
	inline int dim() const { return comp; }
	inline int pitch() const { return w*comp; }


    MyImage resizeCanvas(int ww, int hh)
    {
		std::vector<BYTE> data(ww*comp*hh, 255);
		for (int i = 0; i < h; i++)
			std::copy_n(pixels.data() + i*w*comp, w*comp, data.data() + i*ww*comp);
 
		return MyImage(data.data(), ww, hh, ww*comp, comp);   
	}


    inline void write(const std::string &filename, bool vflip=true) const {
        // not implemented
		mxArray* m;
		mwSize dims[3] = {comp, w, h};
		m = mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL);
		UINT8* mdat = (UINT8 *)mxGetData(m);
		std::memcpy(mdat, pixels.data(), comp * w * h * sizeof(UINT8));
		const std::string tempname("mytempval4c");
		getMatEngine().putVariable(tempname, m);
		matlabEval((tempname + std::string("= permute(") + tempname + std::string(",[3,2,1]);")), false);
		matlabEval(std::string("imwrite(") + tempname + std::string(",'") + filename + std::string("');"));
		mxDestroyArray(m);
		matlabEval("clear " + tempname + ";");
		
	}

	inline std::vector<BYTE> bits(int align=1) const
	{
        const int pitch = (w * comp + align - 1) / align*align;

		std::vector<BYTE> data(pitch*h);
		for(int i=0; i<h; i++)
			std::copy_n(pixels.data()+i*w*comp, w*comp, data.data()+i*pitch);

		return data;
	}
};