Короткие примеры C++ кода-1 Кувшинов Д



Download 326,03 Kb.
bet21/23
Sana21.03.2020
Hajmi326,03 Kb.
#42712
1   ...   15   16   17   18   19   20   21   22   23
Bog'liq
Короткие примеры C

using Color = std::uint32_t;
/// Тип "координата". Синоним 32-битного беззнакового целого.

using Coordinate = std::uint32_t;

/// Тип "точка". Имеет две координаты.

struct Point

{

Coordinate x, y;

/// Создать точку в начале координат.

Point()

: x(0), y(0) {}

/// Создать точку с заданными координатами.

Point(Coordinate x, Coordinate y)

: x(x), y(y) {}

};

/// Тип "размеры" (прямоугольной области). Два размера: ширина и высота.

struct Extents

{

Coordinate width, height;

/// Создать область нулевых размеров.

Extents()

: width(0), height(0) {}

/// Создать область с заданными шириной и высотой.

Extents(Coordinate width, Coordinate height)

: width(width), height(height) {}
/// Вычислить площадь области.

std::size_t area() const { return std::size_t(width) * height; }

/// Проверить, выходят ли координаты точки за пределы области.

bool contains(Point point) const

{

return point.x < width && point.y < height;

}

};

/// Тип "картинка". Управляет массивом пикселей.

class Picture

{

Color *pixels; // упакованный двумерный массив

Extents extents;
/// Выделить память и выполнить копирование данных из другой картинки.

void copy_other(const Picture &other)

{

const auto area = extents.area();

pixels = new Color[area];

std::memcpy(pixels, other.pixels, area);

}
/// Удостовериться, что координаты точки корректны.

void assert_point(Point point) const

{

assert(extents.contains(point));

}
public:

/// Освободить занимаемую память.

void clear()

{

delete[] pixels;

pixels = nullptr;

extents = Extents();

}
/// Обменять содержимое двух объектов.

void swap(Picture &other)

{

std::swap(pixels, other.pixels);

std::swap(extents, other.extents);

}
/// Завершить существование объекта картинки.

~Picture() { clear(); }



/// Создать пустую картинку.

Picture()

: pixels(nullptr) {}
/// Создать картинку заданных размеров с неопределённым содержимым.

explicit Picture(Extents extents)

: pixels(nullptr), extents(extents)

{

pixels = new Color[extents.area()];

}
/// Создать копию картинки.

Picture(const Picture &other)

: pixels(nullptr), extents(other.extents)

{

copy_other(other);

}
/// Скопировать картинку присваиванием.

Picture& operator=(const Picture &other)

{

return *this = Picture(other);

}
/// Переместить картинку, не копируя данные.

Picture(Picture &&other)

: pixels(other.pixels), extents(other.extents)

{

other.pixels = nullptr;

other.extents = Extents();

}
/// Переместить картинку при присваивании, не копируя данные.

Picture& operator=(Picture &&other)

{

assert(this != &other);

clear();

swap(other);

return *this;

}
/// Получить размеры картинки.

const Extents& size() const { return extents; }
/// Получить указатель на пиксели.

const Color* data() const { return pixels; }

Color* data() { return pixels; }
/// Обратиться к одному пикселю по его координатам.

const Color& operator()(Point point) const

{

assert_point(point);

return pixels[point.x + extents.width * point.y];

}
Color& operator()(Point point)

{

assert_point(point);

return pixels[point.x + extents.width * point.y];

}

};

/// Получить значение цвета в формате BGRX для заданных значений трёх каналов модели RGB.

inline Color bgrx(unsigned red, unsigned green, unsigned blue)

{

return (blue & 0xFF) | ((green & 0xFF) << 8) | ((red & 0xFF) << 16);

}

/// Закрасить картинку целиком одним цветом.

void fill(Picture &picture, Color color)

{

const auto pixels = picture.size().area();

const auto data = picture.data();

for (std::size_t i = 0; i < pixels; ++i)

data[i] = color;

}

/// Заливка связной области.

/// Рекурсия заменена на стек+цикл = поиск в глубину по соседним пикселям.

void flood_fill(Picture &picture, Point start, Color color)

{

const auto target_color = picture(start);

std::stack
points;


points.push(start);

do

{

start = points.top();

points.pop();

if (picture.size().contains(start) && picture(start) == target_color)

{

picture(start) = color;

points.emplace(start.x - 1, start.y);

points.emplace(start.x + 1, start.y);

points.emplace(start.x, start.y - 1);

points.emplace(start.x, start.y + 1);

}

} while (!points.empty());

}

/// Обвести фрагменты заданного цвета (what) контуром заданной толщины (в пикселях).

/// Алгоритм основан на ограниченном поиске в ширину.

void make_outline(Picture &picture, Color what, Color outline, unsigned width)

{

struct Pos

{

Point pos;

Color* ptr;

unsigned distance;

Pos(Coordinate x, Coordinate y, Color *ptr, unsigned d)

: pos(x, y), ptr(ptr), distance(d) {}

};
std::queue
positions;


const auto data = picture.data();

const auto pw = picture.size().width,

ph = picture.size().height;



// Сканируем картинку в поисках пикселей цвета what и

// добавляем их координаты в очередь со значением distances == 0.

for (Coordinate row = 0, i = 0; row < ph; ++row)

for (Coordinate col = 0; col < pw; ++col, ++i)

if (data[i] == what)

positions.emplace(col, row, data + i, 0);
// Выполняем ограниченный по дальности поиск в ширину, используя накопленную очередь.

while (!positions.empty())

{

const auto &cur = positions.front();

const auto x = cur.pos.x, y = cur.pos.y;

const auto ptr = cur.ptr;

auto distance = cur.distance;

positions.pop();
if (*ptr != what)

*ptr = outline;
if (++distance < width)

{

if (x != 0)

positions.emplace(x - 1, y, ptr - 1, distance);

if (x != pw - 1)

positions.emplace(x + 1, y, ptr + 1, distance);

if (y != 0)

positions.emplace(x, y - 1, ptr - pw, distance);

if (y != ph - 1)

positions.emplace(x, y + 1, ptr + pw, distance);

}

}

}

// Загрузка и сохранение простого варианта BMP.

// По данным https://en.wikipedia.org/wiki/BMP_file_format
/// Follows minimalistic BITMAPINFOHEADER structure.

#if defined(_MSC_VER) // Компилируем MSVC?

#pragma pack(push) // Сохранить текущее значение упаковки структур.

#pragma pack(1) // Нестандартное расширение MSVC: упакованная структура.

struct

#else

struct __attribute__((packed)) // Нестандартное расширение GCC: упакованная структура.

#endif

Bmp_header

{

// BMP header

char b = 'B', m = 'M';

std::uint32_t file_size = 54; // == data_offset + pixels size in bytes

std::uint16_t reserved1 = 0, reserved2 = 0;

std::uint32_t data_offset = 54; // this header size in bytes
// DIB header (BITMAPINFOHEADER)

std::uint32_t header_size = 40;

std::int32_t bitmap_width = 0, bitmap_height = 0;

std::uint16_t color_planes = 1;

std::uint16_t bpp = 32; // bits per pixel

std::uint32_t compression_method = 0; // 0 = none (BGRX), 3 = XBGR

std::uint32_t image_size = 0;

std::uint32_t x_dpi = 96, y_dpi = 96; // actually ignored

std::uint32_t palette_size = 0;

std::uint32_t important_colors = 0;
/// Конструктор по умолчанию (пустая картинка).

Bmp_header() = default;

/// Конструктор на основе картинки.

explicit Bmp_header(const Picture &picture)

{

bitmap_width = picture.size().width;

bitmap_height = picture.size().height;

file_size = 54 + picture.size().area() * sizeof(Color); // возможно переполнение

}
/// Проверка заголовка на корректность (ограничено возможностями данной реализации).

bool is_valid() const

{

return b == 'B' && m == 'M' &&

data_offset >= 54 && header_size >= 40 &&

bitmap_width != 0 && bitmap_height != 0 && color_planes == 1 &&

bpp == 32 && (compression_method == 0 || compression_method == 3);

// other values ignored

}

};

#if defined(_MSC_VER)

#pragma pack(pop) // Восстановить предыдущее значение упаковки структур.

#endif

// Вспомогательные функции, выполняющие насилие над системой типов

// (конверсия произвольного указателя в указатель на char/const char).

inline char* to_byte_ptr(void *ptr) { return (char*)ptr; }

inline const char* to_byte_ptr(const void *ptr) { return (const char*)ptr; }
/// Преобразование формата пикселя.

inline Color xbgr_to_bgrx(Color color)

{

return (color << 24) | (color >> 8);

}

/// Прочитать BMP из потока (фиксированный формат: 32 бита на пиксель, нет сжатия).

/// Поток должен быть открыт в двоичном режиме.

std::istream& read_bmp_32bpp(std::istream &is, Picture &picture)

{

// Считать заголовок из файла.

Bmp_header header;

is.read(to_byte_ptr(&header), header.data_offset);

if (!is || !header.is_valid())

{

is.setstate(std::ios::failbit);

return is;

}
// Создать картинку нужных размеров.

picture = Picture(Extents(header.bitmap_width, header.bitmap_height));

// Пропустить заданное число байт после заголовка.

is.ignore(header.data_offset - sizeof(header));
// Считать пиксели.

is.read(to_byte_ptr(picture.data()), picture.size().area() * sizeof(Color));
// Если "метод компрессии" == 3 (RGBA, результат работы GIMP), обратить порядок байт.

if (header.compression_method == 3)

{

const auto data = picture.data();

const auto sz = picture.size().area();

for (std::size_t i = 0; i < sz; ++i)

data[i] = xbgr_to_bgrx(data[i]);

}
// Вернуть результирующую картинку.

return is;

}

/// Записать BMP в двоичный поток.

std::ostream& write_bmp_32bpp(std::ostream &os, const Picture &picture)

{

// Построить и записать в файл соответствующий картинке заголовок.

Bmp_header header(picture);

os.write(to_byte_ptr(&header), header.data_offset);
// Записать пиксели.

os.write(to_byte_ptr(picture.data()), picture.size().area() * sizeof(Color));

return os;

}

///////////////////////////////////////////////////////////////////////////////

// Тестирование

#include
int main()

{

using namespace std;

// Test 1.

fstream bmp("100x50orange.bmp", ios::binary | ios::out | ios::trunc);

Picture picture(Extents(100, 50));

fill(picture, bgrx(255, 144, 0));

write_bmp_32bpp(bmp, picture);

bmp.close();
// Test 2.

picture.clear();

bmp.open("input.bmp", ios::binary | ios::in);

read_bmp_32bpp(bmp, picture);

bmp.close();
// Заливка белым из центра.

flood_fill(picture,

Point(picture.size().width / 2, picture.size().height / 2),

0xFFFFFFFF);
bmp.open("flood_fill.bmp", ios::binary | ios::out | ios::trunc);

write_bmp_32bpp(bmp, picture);

bmp.close();
// Test 3.

picture.clear();

bmp.open("input.bmp", ios::binary | ios::in);

read_bmp_32bpp(bmp, picture);

bmp.close();
// Белый контур вокруг чёрных пикселей.

make_outline(picture, bgrx(0, 0, 0), bgrx(255, 255, 255), 4);

bmp.open("outline.bmp", ios::binary | ios::out | ios::trunc);

write_bmp_32bpp(bmp, picture);

bmp.close();

Download 326,03 Kb.

Do'stlaringiz bilan baham:
1   ...   15   16   17   18   19   20   21   22   23




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish