Анализ основных полей заголовка
Для построения рисунка надо знать его ширину, высоту и размер строки в файле. Следует подчеркнуть, что ширина рисунка и размер строки в файле являются разными величинами и их значения чаще всего не совпадают.
Будем считать, что в разделе данных задачи описаны переменные:
iwidth dw 0; количество точек в строке рисунка iheight dw 0; количество строк в рисунке fwidth dw 0; количество байтов в строке в файле rmndr dw 0; количество дополнительных байтов в строке файла bitcnt db 0; количество разрядов в коде точки
Первые четыре переменные мы использовали в основной части книги при описаниях построения различных рисунков. Пятая переменная нужна для временного хранения размера кода точки, чтобы не выбирать его каждый раз из заголовка файла. При описании переменные очищаются, их конкретные значения определяются в процессе обработки заголовка. В нем явно указаны значения только трех переменных, а fwidth и rmndr приходится вычислять.
Описание следующего шага
Расположение полей, содержащих значения для переменных iwidth, iheight и bitcnt, зависит от того, какому формату соответствует заголовок – Windows или OS/2. Напомним, что эти форматы различаются размером информационной части заголовка, указанным в поле bisize или bcsize (его смещение ОЕb).
Шаг 3.
Выбираем содержимое полей заголовка biwidth, biHeight и biBitCnt с учетом значения, указанного в поле bisize, и сохраняем выбранные величины в переменных iwidth, iheight и bitcnt. В заключение проверяем значение bitcnt, и если оно равно ish (24), то обработка заголовка закончена, и выполнение подпрограммы Bitmap завершается. В соответствии со стандартом BMP поле biBitCnt может содержать значения 1, 4, 8 или ish. Последнее значение соответствует полноцветным рисункам, не использующим палитру цветов, поэтому никакие манипуляции с палитрой не требуются, что и позволяет просто завершить подпрограмму.
Полученные на этом шаге величины содержат исчерпывающую исходную информацию и позволяют вычислить все, что нужно для построения рисунка. В конце раздела А.2.1 говорилось, что при работе с ВМР-файлами доверять можно только этим величинам. Значения, содержащиеся в других полях заголовка, могут быть ошибочными.
Программная реализация описанного шага показана в примере А.3, который является продолжением примера А.2.
Пример А.3. Формирование исходных значений основных переменных.
Part 2: mov ax, fs: [si+12h] ax = biwidth, формат Windows и OS/2 mov bx, fs: [si+16h] bx = biHeight, формат Windows mov ex, fs: [si+ ICh] ex = biBitCnt, формат Windows cmp byte ptr fs: [si+01 ]h), 28h; заголовок формата Windows? je @F › да, переходим на запись значений mov bx, fs: [si+14h] bx = biHeight, формат OS/2 mov ex, fs: [si+18h] сх = biBitCnt, формат OS/2 Э @: mov iwidth, ax iwidth = biwidth mov f width, ax fwidth = biwidth mov iheight, bx iheight = biHeight mov bitcnt, cl bitcnt = biBitCnt cmp cl, 18h cl = 18h? jne Part_3 › нет, переход на продолжение ret возврат из подпрограммы
При выполнении примера А.З переменным iwidth и fwidth присваиваются одинаковые значения, но в общем случае они различаются. Поэтому цель дальнейших шагов – уточнить значение fwidth.
Здесь уместно напомнить, что в стандарте PCX значение переменной fwidth хранится в заголовке файла и вычислять его не надо.
Наиболее простой способ определения значения fwidth следующий. В соответствии со стандартом в полях заголовка хранятся размер файла и адрес начала образа рисунка. Размер образа рисунка в байтах равен разности указанных величин. При делении этой разности на количество строк получается размер строки в байтах.
К сожалению, этот способ на практике не применим. Проверка достаточно большого количества файлов показала, что поле bfsize (его смешение 02) в котором должен находиться размер файла в байтах, может содержать ошибочное значение или нуль. Размер файла можно определить программно, но для этого придется обращаться к DOS со специальными запросами.
Следующие 4 шага. Мы опишем более простой способ, основанный на том что адрес начала строки в файле должен быть кратен четырем. Поэтому если количество точек в строке рисунка не кратно четырем, то при записи в файл после каждой строки добавляется необходимое количество байтов, содержимое которых не определено. При построении образа рисунка эти байты не используются, их просто пропускают. Таким образом, одна из причин различия значений переменных iwidth и fwidth связана с возможным наличием дополнительных байтов в строке файла. Кроме того, вследствие упаковки точек 2- и 16-цветных рисунков, строка в файле будет в 2 или в 8 раз короче строки рисунка (без учета дополнительных байтов).