Множество притяжений корней метода Ньютона
Существующие файлы:
Какого файла не хватает — догадаетесь сами: это несложно,
ежели «pozor» достаточно хорошо впитан.
Краткое содержание части лекции про запись PNG-файла
Оглавленьице:
Вместо введения
Давайте смотреть на main.c.
Идею того, что картинка — это прямоугольник
с целыми координатами точек (пикселов; pixel —
picture element) и к каждой точке приписано дополнительное
свойство — цвет, вам нужно как-то дополнительно объяснить
или это понятно?
Если нужно — пишите письма: автор будет жечь напалмом
(не так,
конечно:
албанско-бобруйские
коннотации
Б-го
противны?).
Цвет кодируется тройкой интенсивностей базовых
(в модели RGB:
red,
green,
blue) цветов;
амплитуда каждой компоненты преставляет
из себя целое число от нуля до 255, умещаясь, таким образом,
в один байт.
А цвет точки, тогда, умещается в 3 байта,
которые состоят из 24 битов; такой цвет, поэтому называется
3x8=24-битным
(иногда).
Герменевтика горизонтального
Поскольку картинка — это прямоугольник с цветными точками,
то его можно представлять ещё и как совокупность строчек (rows);
их количество равно высоте картинки, а каждая строчка уже состоит
из горизонтально расположенных пикселов.
Их в каждой строке столько, какова ширина картинки.
Поэтому строчка является массивом пикселов, каждый пиксел —
тройка байтов (red, green, blue), следовательно, графически оно (массив этот)
выглядит так:
| R1 | G1 | B1 | R2 | G2 | B2 | ... | Rn | Gn | Bn |
каждая ячейка — байт.
Индексы — номер байта.
Что такое «R», «G»
и «B?
Это, наверное, что-то с космосом связано.
И вот, в main(), мы как раз сначала распределяем память
под массив указателей на строки, а дальше — под каждую
из строк.
До этого, конечно, инициализируя ширину и высоту.
Для компактного хранения всех данных, относящихся к картинке,
мы используем структуру pngdata, которую вводим сами же,
в newton.h,
struct pngdata {
int width, height;
png_bytep *rows;
};
png_bytep — это тип данных, который нам предоставляет
libpng,
сами мы его, поэтому, не определяем: он приходит из png.h.
Землемерное
Чтобы в такой «геометрической» конструкции дойти
до отдельного пиксела с координатами (x, y), надо
сделать так:
png_byte *bp = pp->rows[x] + 3 * y;
и bp будет указывать на байт Ry.
Поэтому bp[0] — это Ry,
bp[1] — Gy,
bp[2] — By и, скажем,
simple_image() устроено так, как оно и устроено
(«Ото /не путать с ОТО/ ты объяснил,
так объяснил, графоманец;
тушите свет!»):
void
simple_image(struct pngdata *pp) {
unsigned int x, y;
for (x = 0; x < pp->height; x++)
for (y = 0; y < pp->width; y++) {
png_byte *bp = pp->rows[x] + 3 * y;
bp[0] = (x * y) % 256;
bp[1] = y % 256;
bp[2] = sin(x * x + y * y) * 256;
}
}
На этом с заполнением данных картинки — всё,
объяснение закончено.
Das ist fantastisch! А теперь — десерт.
Переходим к записи нарисованного в файл.
За это отвечает отдельная функция — png_write(),
в которую я (Он?) выделил всё, что необходимо
для записи:
- открытие выходного файла (с помощью fopen());
- создание базовой структуры png_struct с помощью png_create_write_struct():
она содержит совершенно общие настройки, касающиеся конфигурации алгоритмов
записи PNG-файла;
- создание структуры png_info, несущей информацию именно о нашем файле
и его обработке: функциям его записи/чтения, обработки
ошибок и т. п.;
- разделение на две структуры делается потому, что их (структур)
задачи почти ортогональны: мы можем использовать одну и ту же png_struct
для разных png_info, поэтому тратить память на, скажем, содержание
данных png_struct внутри (разных) png_info — не всегда разумно;
- потом, с помощью png_init_io(), мы связываем распределённый png_info
с полученным нами (с помощью fopen()) 'FILE *': функция записи
по-умолчанию как раз работает с потоками из stdio.h, которые
и описываются 'FILE *'; (Керниган и Ритчи из меня, конечно,
такой — тесносплетённые в единого; интересно — целого?)
- у многих файлов (не только формата PNG,
но и других)
есть заголовок,
описывающий метаданные (данные о данных ;?)
и сами данные; так вот,
png_set_IHDR() прямо и заполняет эти самые метаданные; ей как раз
мы и передаём размеры картинки, характеристики цветности
(PNG_COLOR_TYPE_RGB), чередования элементов картинки (PNG_INTERLACE_NONE,
см. прогрессивное)
и кое-чего остального (поищите «png_set_IHDR»
в TFM /локальная копия/
и непременно обрящите оное; вы считаете,
что верно — «об-ре-тё-те»? Так точно!
Однако, насяльника, whatever…);
- дальше мы записываем заголовок — png_write_info() и данные —
png_write_image(); далее — завершаем процесс записи — png_write_end().
Обратите внимание: семь
(прописью: Se7en)
пунктов.
К чему бы Это?
Соответственно, после каждого движения в png_write() мы проверям,
получилось ли оно, и используем goto (к _bailout)
для обработки ошибок, которая совершенно стандартна
(если мы правильно инициализируем сначала переменные, конечно).
Это — один из случаев, когда
goto
не против структурности (локальная копия),
а за неё.
Как мне кажется, конечно.