Задание № 5702

Студент

Вилейко Иван

Задача

Простой класс Image

Состояние

Завершено

Баллов

6

Дедлайн
28 марта
Назначено

21.04.2024, 09:51

Завершено

31.05.2024, 09:04

Реализовать класс Image для работы с изображениями c применением техники reference counting. Класс представляет собой многоканальный двумерный массив из unsigned char для хранения пикселей изображения.

Справочная информация

Цифровые изображения состоят из пикселей, а пиксели состоят из комбинаций основных цветов. Набор основных цветов называются каналами. Например, RGB изображения состоят из 3-х каналов: R (red), G (green), B (blue), а изображения в градациях серого являются одноканальными.

Постановка задачи

Реализовать основной класс Image и вспомогательный класс Range. public и protected методы классов фиксированы, кроме спецификаторов. Т.е. нельзя менять названия методов, а также типы и количество аргументов. НО в этих методах отсутствуют спецификаторы const и static, которые были удалены намеренно. Их необходимо вернуть на место.

private поля и private методы можно добавлять в класс Image. Класс Range cамодостаточен и не нуждается в дополнительных полях и методах.

//Range.hpp
class Range
{
    int _start, _end;
public:
    Range();
    Range(int _start, int _end);
    int size();
    bool empty();

    int start();
    int end();

    Range all();
};

Класс Range используется для указания полуоткрытого диапазона значений строк или столбцов. Т.е [a,b) = {a <= x < b}.

  • Range() -- конструктор по умолчанию. Инициализация нулями.

  • Range(int _start, int _end) -- конструктор с заданием полуоткрытого диапазона [_start, _end). Если _start < 0 || _start >= _end, то поля инициализируются нулями.

  • int size() -- возвращает размер (длину) диапазона.

  • bool empty() -- возвращает true или false в зависимости от того, является диапазон пустым или нет.

  • int start() -- возращает значение _start.

  • int end() -- возращает значение _end.

  • Range all() -- возвращает специальную переменную Range, которая означает "весь диапазон". Данный метод не зависит от значений полей start и end.

  • int _start - приватное поле класса, содержащее значение инклюзивной левой границы диапазона.

  • int _end - приватное поле класса, содержащее значение исключительной правой границы диапазона.

//Image.hpp
#include "Range.h"

class Image {

public:
    Image();
    Image(int rows, int cols, int channels);
    Image(int rows, int cols, int channels, unsigned char* data);
    Image(const Image& image);
    Image(const Image& image, const Range& rowRange, const Range& colRange);
    virtual ~Image();

    Image& operator=(const Image& image);
    Image operator()(const Range& rowRange, const Range& colRange);

    Image clone();
    void copyTo(Image& image);
    void create(int rows, int cols, int channels);
    bool empty();

    void release();

    Image col(int x);
    Image colRange(const Range& range);

    Image row(int y);
    Image rowRange(const Range& range);

    const unsigned char* data() const;
    unsigned char* data();

    int rows();
    int cols();
    int total();
    int channels();

    unsigned char& at(int index);
    const unsigned char& at(int index) const;

    Image zeros(int rows, int cols, int channels);
    Image values(int rows, int cols, int channels, unsigned char value);

    size_t countRef();
};
  • Image() -- конструктор по умолчанию.
  • Image(int rows, int cols, int channels) -- конструктор с заданием количества строк rows, столбцов cols и каналов channels.
  • Image(int rows, int cols, int channels, unsigned char* data) -- конструктор, который отличается от вышеуказанного дополнительным параметром, указателем на пользовательские данные data. Данный конструктор не выделяет новую память и не копирует данные, а просто использует переданный указатель на данные (пиксели). Эта операция очень эффективна и может использоваться для обработки внешних данных. Внешние данные не освобождаются в деструкторе, поскольку за них ответственен пользователь.
  • Image(const Image& image) -- конструктор копий. Данный конструктор не выделяет новую память, а применяет технику reference counting. Сложность создания копии объекта O(1).
  • Image(const Image& image, const Range& rowRange, const Range& colRange) -- конструктор копий, который отличается от вышеуказанного дополнительными параметрами rowRange и colRange, которые задают прямоугольную область. Дополнительные параметры позволяют создать копию не всего изображения, а только части изображения. Данный конструктор также не выделяет новую память, а применяет технику reference counting. Сложность создания копии объекта O(1). Если range выходит за область изображения, то он обрезается до границы изображения.

  • ~Image() -- деструктор.

  • operator=(const Image& image) -- оператор присваивания. В некотором роде похож на конструктор. Т.е. не выделяет новую память, а применяет технику reference counting. Сложность данной операции O(1).

  • operator()(const Range& rowRange, const Range& colRange) -- выделяет прямоугольное под-изображение. Данный оператор возвращает то изображение, которое находится в заданной (с помощью параметров rowRange и colRange) области. Сложность операции O(1), копирования и выделения новой памяти не требуется. Используется техника reference counting. Если range выходит за область изображения, то он обрезается до границы изображения.

  • clone() -- создает полную копию изображения. Выделяет новую память и производит копирование пикселей. Сложность операции O(n), где n - количество пикселей.

  • copyTo(Image& image) -- метод производит полное копирование изображения в объект image. Сложность операции O(n).

  • create(int rows, int cols, int channels) -- метод задает новые размеры текущего изображения.

  • empty() -- возвращает true или false в зависимости от того, является изображение пустым или нет.

  • release() -- декрементирует счетчик ссылок и в случае необходимости освобождает ресурсы (память).

  • col(int x) -- возвращает новое изображение, которое содержит один столбец по индексу x. Сложность операции O(1). Память не выделяется, используется reference counting. Если x превышает ширину изображения, то метод должен вернуть пустое изображение.

  • colRange(const Range& range) -- возвращает новое изображение, которое содержит диапазон столбцов range. Сложность операции O(1). Память не выделяется, используется reference counting. Если range выходит за область изображения, то он обрезается до границы изображения.

  • row(int y) -- аналог метода col(int x) для строк.

  • rowRange(const Range& range) -- аналог метода colRange(const Range& range) для строк.

  • data() const -- возвращет указатель на константные данные (пиксели).

  • data() -- возвращет указатель на данные (пиксели).

  • rows() -- возвращает общее количество строк в изображении.

  • cols() -- возвращает общее количество столбцов в изображении (без учета каналов).

  • total() -- возвращает общее количество пикселей в изображении.

  • channels() -- возвращает количество каналов в пикселе.

  • at(int index) -- возвращает ссылку на компоненту пикселя изображения (не на весь пиксель, а на часть) по индексу.

  • at(int index) -- возвращает константную ссылку на компоненту пикселя изображения (не на весь пиксель, а на часть) по индексу.

  • zeros(int rows, int cols, int channels) -- создает новое изображение, которое инициализируется нулями.

  • values(int rows, int cols, int channels) -- создает новое изображение, которое инициализируется значением value.

  • countRef() -- возвращает текущее количество ссылок на изображение. Т.е. количество объектов, которые ссылаются на данное изображение. Этот метод нужен для unit test'ов.

Требования

  1. К public методам, классов Range и Image, необходимо добавить спецификаторы static и const. Но только в те места, где это необходимо.
  2. public и protected методы классов фиксированы, кроме спецификаторов. Т.е. нельзя менять названия методов, а также типы и количество аргументов.
  3. Названия header и source файлов следующие: Image.hpp, Image.cpp, Range.hpp, Range.cpp.
  4. Написать unit test'ы для реализованных классов.

Действия