• 字符图像


    字符图像

             ——《C++沉思录》第9章 一个课堂练习的分析(上)

             设计一个字符图像,用字符代替像素,实现的基本操作有加边框、将两个图像横排、竖排等。然后再对其进行一些扩展:横排下边对齐、竖排右边对齐、将重载运算符封装、去边框处理等。

             具体细节详见代码和注释。

    // 字符图像
    #include <iostream>
    #include <assert.h>
    using namespace std;
    
    // 图像类
    class Picture
    {
    private:
        int   height; //
        int   width;  //
        char* data;   // 可用string代替
    
        int   isframe; // 标示是否有边框,其值表示边框数
    
    private:
        void copyblock(int, int, const Picture&); // 块拷贝
        void copyblock2(int, int, const Picture&, int, int, int, int); // 块拷贝第二版
    
        char& position(int, int);
        char  position(int, int) const;
    
        void clear(int, int, int, int); // 将矩形内的字符清空为空格
    
        void init(int, int); // 初始化
    
        static int max(int, int);
    
    public:
        Picture();
        Picture(const char* const*, int);
        Picture(const Picture&);
        ~Picture();
    
        Picture& operator = (const Picture&);
    
        // 友元
        friend ostream& operator << (ostream&, const Picture&);
    
        // 添加边框
        friend Picture frame(const Picture&);
        // 去边框
        friend Picture removeframe(const Picture&);
        // 竖排,左边并齐
        friend Picture operator & (const Picture&, const Picture&);
        // 竖排,右边并齐
        friend Picture operator + (const Picture&, const Picture&);
        // 横排,上边并齐
        friend Picture operator | (const Picture&, const Picture&);
        // 横排,下边并齐
        friend Picture operator * (const Picture&, const Picture&);
    };
    
    int Picture::max(int m, int n)
    {
        return m > n ? m : n;
    }
    
    char& Picture::position(int row, int col) 
    {
        return data[row * width + col];
    }
    
    char Picture::position(int row, int col) const
    {
        return data[row * width + col];
    }
    
    void Picture::init(int h, int w)
    {
        height = h;
        width  = w;
        data   = new char[height * width];
    
        isframe = 0;
    }
    
    // 可以用memset函数填充空格,避免clear以及补充空格操作
    void Picture::clear(int r1, int c1, int r2, int c2)
    {
        for (int r = r1; r < r2; ++r)
        {
            for (int c = c1; c < c2; ++c)
            {
                position(r, c) = ' ';
            }
        }
    }
    
    // 将图像p从(0,0)拷贝到(row,col)起始的区域
    void Picture::copyblock(int row, int col, const Picture& p)
    {
        for (int i = 0; i < p.height; ++i)
        {
            for (int j = 0; j < p.width; ++j)
            {
                position(i + row, j + col) = p.position(i, j);
            }
        }
    }
    
    // copyblock实现的功能是将p拷贝到自身,p是从第一个字符开始拷贝的
    // 这里我们实现一个可以指定p的起始字符位置
    void Picture::copyblock2(int row, int col, const Picture& p, int prow, int pcol, int h, int w)
    {
        for (int i = 0; i < h; ++i)
        {
            for (int j = 0; j < w; ++j)
            {
                position(row + i, col + j) = p.position(prow + i, pcol + j);
            }
        }
    }
    
    Picture::Picture() : height(0), width(0), data(0), isframe(0) {}
    
    Picture::Picture(const char* const* array, int n)
    {
        int w = 0;
        int i = 0;
    
        for (i = 0; i < n; ++i)
        {
            w = Picture::max(w, strlen(array[i]));
        }
    
        init(n, w);
    
        for (i = 0; i < n; ++i)
        {
            const char* src = array[i];
            int len = strlen(src);
    
            int j = 0;
            while (j < len)
            {
                position(i, j) = src[j];
                ++j;
            }
            
            while (j < width)
            {
                position(i, j) = ' ';
                ++j;
            }
        }
    }
    
    Picture::Picture(const Picture& p) : height(p.height), width(p.width), data(new char[p.height * p.width]), isframe(p.isframe)
    {
        copyblock(0, 0, p);
    }
    
    Picture::~Picture()
    {
        delete [] data;
    }
    
    Picture& Picture::operator = (const Picture& p)
    {
        if (this != &p)
        {
            delete [] data;
            init(p.height, p.width);
    
            isframe = p.isframe;
    
            copyblock(0, 0, p);
        }
    
        return *this;
    }
    
    ostream& operator << (ostream& o, const Picture& p)
    {
        for (int i = 0; i < p.height; ++i)
        {
            for (int j = 0; j < p.width; ++j)
            {
                o << p.position(i, j);
            }
            o << endl;
        }
        return o;
    }
    
    Picture frame(const Picture& p)
    {
        Picture r;
    
        r.init(p.height + 2, p.width + 2);
        r.isframe = p.isframe + 1;
    
        // 将左右边放上'|'字符
        for (int i = 1; i < r.height - 1; ++i)
        {
            r.position(i, 0) = '|';
            r.position(i, r.width - 1) = '|';
        }
    
        // 将上下边放上'-'字符
        for (int i = 1; i < r.width - 1; ++i)
        {
            r.position(0, i) = '-';
            r.position(r.height - 1, i) = '-';
        }
    
        // 将四个角放上'+'字符
        r.position(0, 0) = '+';
        r.position(0, r.width - 1) = '+';
        r.position(r.height - 1, 0) = '+';
        r.position(r.height - 1, r.width - 1) = '+';
    
        r.copyblock(1, 1, p);
    
        return r;
    }
    
    Picture removeframe(const Picture& p)
    {
        if (p.isframe == 0)
        {
            return p;
        }
        Picture r;
    
        assert(p.height >= 2 && p.width >= 2);
    
        r.init(p.height - 2, p.width - 2);
        r.isframe = p.isframe - 1;
    
        r.copyblock2(0, 0, p, 1, 1, r.height, r.width);
    
        return r;
    }
    
    // 竖排,左边并齐
    Picture operator & (const Picture& p, const Picture& q)
    {
        Picture r;
    
        r.init(p.height + q.height, Picture::max(p.width, q.width));
    
        // 将多余的矩形空间置为空格
        r.clear(0, p.width, p.height, r.width);
        r.clear(p.height, q.width, r.height, r.width);
    
        r.copyblock(0, 0, p);
        r.copyblock(p.height, 0, q);
    
        return r;
    }
    
    // 竖排,右边并齐
    Picture operator + (const Picture& p, const Picture& q)
    {
        Picture r;
    
        r.init(p.height + q.height, Picture::max(p.width, q.width));
    
        // 将多余的矩形置为空格
        r.clear(0, 0, p.height, r.width - p.width);
        r.clear(p.height, 0, r.height, r.width - q.width);
    
        r.copyblock(0, r.width - p.width, p);
        r.copyblock(p.height, r.width - q.width, q);
    
        return r;
    }
    
    // 对竖排封装
    Picture vcatleft(const Picture& p, const Picture& q)
    {
        return p & q;
    }
    
    Picture vcatright(const Picture& p, const Picture& q)
    {
        return p + q;
    }
    
    // 横排,上边并齐
    Picture operator | (const Picture& p, const Picture& q)
    {
        Picture r;
        r.init(Picture::max(p.height, q.height), p.width + q.width);
    
        r.clear(p.height, 0, r.height, p.width);
        r.clear(q.height, p.width, r.height, r.width);
    
        r.copyblock(0, 0, p);
        r.copyblock(0, p.width, q);
    
        return r;
    }
    
    // 横排,下边并齐
    Picture operator * (const Picture& p, const Picture& q)
    {
        Picture r;
        r.init(Picture::max(p.height, q.height), p.width + q.width);
    
        r.clear(0, 0, r.height - p.height, p.width);
        r.clear(0, p.width, r.height - q.height, r.width);
    
        r.copyblock(r.height - p.height, 0, p);
        r.copyblock(r.height - q.height, p.width, q);
    
        return r;
    }
    
    // 对横排封装
    Picture hcatabove(const Picture& p, const Picture& q)
    {
        return p | q;
    }
    
    Picture hcatbelow(const Picture& p, const Picture& q)
    {
        return p * q;
    }
    
    // 测试
    int main()
    {
        char* init[] = {"Paris", "in the", "Sprint"};
    
        // 新建图像
        Picture p(init, 3);
        cout << p << endl;
    
        // 加边框
        Picture q = frame(p);
        cout << q << endl;
    
        // 去边框
        Picture r = removeframe(q);
        cout << r << endl;
    
        // 再去边框
        Picture s = removeframe(r);
        cout << s << endl;
    
        // 再加边框
        Picture t = frame(q);
        cout << t << endl;
    
        // 去边框1
        Picture u1 = removeframe(t);
        cout << u1 << endl;
        // 去边框2
        Picture u2 = removeframe(u1);
        cout << u2 << endl;
        // 去边框3
        Picture u3 = removeframe(u2);
        cout << u3 << endl;
    
    
        // 横排,上边并齐
        Picture v1 = p | q;
        cout << v1 << endl;
        Picture v3 = q | p;
        cout << v3 << endl;
        
        // 横排,下边并齐
        Picture v2 = p * q;
        cout << v2 << endl;
        Picture v4 = q * p;
        cout << v4 << endl;
    
    
        // 竖排,左边并齐
        Picture w1 = p & q;
        cout << w1 << endl;
        Picture w3 = q & p;
        cout << w3 << endl;
    
        // 竖排,下边并齐
        Picture w2 = p + q;
        cout << w2 << endl;
        Picture w4 = q + p;
        cout << w4 << endl;
    
        // 组合
        Picture x = frame(q & v1);
        cout << x << endl;
    
    
        return 0;
    }

             以上是对图像的表象进行的处理,没涉及图像深层结构。图像处理是一门很有意思的学科。

  • 相关阅读:
    在嵌入式设备中实现webrtc的第三种方式①
    海思dv300cv500交叉编译webrtc
    Windows编译运行webrtc全过程
    如何使用C#调用C++类虚函数(即动态内存调用)
    使用Windows的Linux子系统搭建嵌入式开发环境
    Spring进阶教程之在ApplicationContext初始化完成后重定义Bean
    Java与邮件系统交互之使用Socket验证邮箱是否存在
    旧博客内容 & 洛谷日报(转载)
    多项式不全家桶
    NOIP2020游记
  • 原文地址:https://www.cnblogs.com/unixfy/p/3462846.html
Copyright © 2020-2023  润新知