Я написал программу для вывода символов на рисунок (см. ниже). Но прошу ответить на два вопроса. Имеется массив:
// в массиве font[] битовые маски символов, по 10 байт на символ
const unsigned char font[] =
"\x7F\x7F\x63\x5D\x7D\x7B\x73\x7F\x73\x7F" // (<?>) 0 == (негатив <?>)
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ( )
"\x0C\x0C\x0C\x0C\x0C\x0C\x00\x0C\x0C\x00" // (!)
....
"\x14\x00\x1C\x22\x22\x3E\x20\x20\x1C\x00" // (ё)
"\x4C\x48\x4B\x4B\x68\x5B\x48\x48\x48\x00"; // (№)
const int N=(sizeof(font)-1)/10;
Вопрос-1Принцип работы программы: байты входного текста в кодировке Win-1251 легко преобразуются в индексы массива font, по которым лежат битовые маски соответствующих символов. Но по замыслу массив font можно урезать снизу, если нужны не все символы. Например нужны только цифры, или только цифры и английские буквы (ASC-II). Чтобы исключить возможный выход за край массива font, я ввёл проверку, если индекс больше, чем доступное число символов, то рисует знак вопроса: const int N=(sizeof(font)-1)/10;
....
// c -текущий символ
if(c<128) k = (c-31)*10; // ASC-II
....
// k -индекс массива font[]
if(k>=N*10) k = 0; // <?> массив font[] укорочен снизу
Чтобы определить N -число символов в массиве, я вычитаю единицу (sizeof(font)-1), т. е. беру длину массива без конечного нуля, а то из-за этого лишнего байта проходят дефекты, когда в последней строке массива не 10, а 9 байт. Правда, выхода за край массива нет, т. к. этот конечный нулевой байт тоже элемент массива, но я хочу, чтобы программа такие дефекты браковала и выводила знак вопроса. Вопрос: Всегда ли, при любой ли кодировке исходного текста программы, Си-строка оканчивается одним-единственным нулевым байтом, а не двумя или тремя байтами сообразно кодировке? (это я о массиве font) В ASC-II 0x00 = NOP. А в UTF-16 0x0000 = NOP. Вопрос-2Вообще, существуют ли Си-компиляторы, способные принимать для компиляции текст программы в кодировках, несовместимых с ASC-II ? Мой компилятор GCC не принимает текст программы в кодировке UTF-16, она несовместима с ASC-II. А в UTF-8 принимает, она совместима. Примечание. Массив font хоть и похож на байтовый массив, но это всё же одна большая Си-строка, строковая константа, оконченная нулевым байтом. Я не сразу сообразил, и хорошо, что опробовал укороченную до 9-ти байт строку в массиве, а то так ничего и не заметил бы. Рис. 1. Win-1251. Рис. 2. UTF-8. Кодировки терминала -- Полная программа.
// /home/test/SI/SI/font8/font8_d.c
// cd /home/test/SI/SI/font8/
// gcc font8_d.c -o font8_d.cgi -Wall -Werror -O3
// ./font8_d.cgi
// Запустите программу и введите строку с терминала. Появится рисунок,
// на котором есть три тестовые строки, они есть в функции main(), и
// ещё четвёртая строка, которую ввели с терминала
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int wr_bmp_24_RGB(FILE *fp, const char *pic, int w, int h);
// в массиве font[] битовые маски символов, по 10 байт на символ
const unsigned char font[] =
"\x7F\x7F\x63\x5D\x7D\x7B\x73\x7F\x73\x7F" // (<?>) 0 == (негатив <?>)
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // ( )
"\x0C\x0C\x0C\x0C\x0C\x0C\x00\x0C\x0C\x00" // (!)
"\x14\x14\x14\x00\x00\x00\x00\x00\x00\x00" // (")
"\x00\x12\x12\x3F\x12\x3F\x12\x12\x00\x00" // (#)
"\x00\x08\x1C\x2A\x18\x0C\x2A\x1C\x08\x00" // ($)
"\x00\x00\x31\x32\x04\x08\x13\x23\x00\x00" // (%)
"\x00\x10\x28\x28\x10\x2A\x24\x24\x1A\x00" // (&)
"\x08\x08\x08\x00\x00\x00\x00\x00\x00\x00" // (')
"\x00\x04\x08\x08\x08\x08\x08\x08\x04\x00" // (()
"\x00\x10\x08\x08\x08\x08\x08\x08\x10\x00" // ()) 10
"\x00\x00\x12\x0C\x3F\x0C\x12\x00\x00\x00" // (*)
"\x00\x00\x08\x08\x3E\x08\x08\x00\x00\x00" // (+)
"\x00\x00\x00\x00\x00\x00\x00\x0C\x04\x08" // (,)
"\x00\x00\x00\x00\x3F\x00\x00\x00\x00\x00" // (-)
"\x00\x00\x00\x00\x00\x00\x00\x0C\x0C\x00" // (.)
"\x02\x02\x04\x04\x08\x08\x10\x10\x20\x20" // (/)
"\x00\x1E\x21\x23\x25\x29\x31\x21\x1E\x00" // (0)
"\x00\x04\x0C\x14\x04\x04\x04\x04\x04\x00" // (1)
"\x00\x1E\x21\x21\x02\x04\x08\x10\x3F\x00" // (2)
"\x00\x1E\x21\x02\x0E\x01\x01\x21\x1E\x00" // (3) 20
"\x00\x0E\x0A\x12\x12\x22\x3F\x02\x02\x00" // (4)
"\x00\x3F\x20\x2E\x31\x01\x01\x21\x1E\x00" // (5)
"\x00\x1E\x21\x20\x3E\x21\x21\x21\x1E\x00" // (6)
"\x00\x3F\x01\x02\x04\x08\x08\x08\x08\x00" // (7)
"\x00\x1E\x21\x21\x1E\x21\x21\x21\x1E\x00" // (8)
"\x00\x1E\x21\x21\x21\x1F\x01\x01\x1E\x00" // (9)
"\x00\x0C\x0C\x00\x00\x00\x0C\x0C\x00\x00" // (:)
"\x00\x0C\x0C\x00\x00\x00\x00\x0C\x04\x08" // (;)
"\x00\x02\x04\x08\x10\x08\x04\x02\x00\x00" // (<)
"\x00\x00\x00\x3F\x00\x3F\x00\x00\x00\x00" // (=) 30
"\x00\x10\x08\x04\x02\x04\x08\x10\x00\x00" // (>)
"\x00\x1E\x21\x01\x02\x04\x0C\x00\x0C\x00" // (?)
"\x00\x1C\x22\x4D\x55\x55\x5E\x20\x1C\x00" // (@)
"\x00\x0C\x12\x21\x21\x3F\x21\x21\x21\x00" // (A)
"\x00\x3E\x21\x21\x3E\x21\x21\x21\x3E\x00" // (B)
"\x00\x1E\x21\x20\x20\x20\x20\x21\x1E\x00" // (C)
"\x00\x3C\x22\x21\x21\x21\x21\x22\x3C\x00" // (D)
"\x00\x3F\x20\x20\x3E\x20\x20\x20\x3F\x00" // (E)
"\x00\x3F\x20\x20\x20\x3E\x20\x20\x20\x00" // (F)
"\x00\x1E\x21\x20\x20\x27\x21\x23\x1D\x00" // (G) 40
"\x00\x21\x21\x21\x3F\x21\x21\x21\x21\x00" // (H)
"\x00\x1C\x08\x08\x08\x08\x08\x08\x1C\x00" // (I)
"\x00\x1E\x02\x02\x02\x02\x02\x22\x1C\x00" // (J)
"\x00\x22\x24\x28\x30\x28\x24\x22\x21\x00" // (K)
"\x00\x20\x20\x20\x20\x20\x20\x20\x3F\x00" // (L)
"\x00\x41\x41\x63\x55\x49\x41\x41\x41\x00" // (M)
"\x00\x21\x21\x31\x29\x25\x23\x21\x21\x00" // (N)
"\x00\x1E\x21\x21\x21\x21\x21\x21\x1E\x00" // (O)
"\x00\x3E\x21\x21\x21\x3E\x20\x20\x20\x00" // (P)
"\x00\x1E\x21\x21\x21\x21\x25\x22\x1D\x00" // (Q) 50
"\x00\x3E\x21\x21\x3E\x28\x24\x22\x21\x00" // (R)
"\x00\x1C\x22\x20\x1C\x02\x02\x22\x1C\x00" // (S)
"\x00\x3E\x08\x08\x08\x08\x08\x08\x08\x00" // (T)
"\x00\x21\x21\x21\x21\x21\x21\x21\x1E\x00" // (U)
"\x00\x41\x41\x22\x22\x14\x14\x08\x08\x00" // (V)
"\x00\x41\x41\x41\x41\x2A\x2A\x14\x14\x00" // (W)
"\x00\x21\x12\x12\x0C\x0C\x12\x12\x21\x00" // (X)
"\x00\x41\x22\x22\x14\x08\x08\x08\x08\x00" // (Y)
"\x00\x3F\x02\x04\x08\x10\x20\x40\x7E\x00" // (Z)
"\x00\x0C\x08\x08\x08\x08\x08\x08\x0C\x00" // ([) 60
"\x20\x20\x10\x10\x08\x08\x04\x04\x02\x02" // (\)
"\x00\x18\x08\x08\x08\x08\x08\x08\x18\x00" // (])
"\x08\x14\x22\x00\x00\x00\x00\x00\x00\x00" // (^)
"\x00\x00\x00\x00\x00\x00\x00\x00\x7F\x00" // (_)
"\x10\x08\x04\x00\x00\x00\x00\x00\x00\x00" // (`)
"\x00\x00\x1C\x02\x1E\x22\x22\x22\x1D\x00" // (a)
"\x20\x20\x20\x3C\x22\x22\x22\x22\x3C\x00" // (b)
"\x00\x00\x1C\x22\x20\x20\x20\x22\x1C\x00" // (c)
"\x02\x02\x02\x1E\x22\x22\x22\x22\x1E\x00" // (d)
"\x00\x00\x1C\x22\x22\x3E\x20\x20\x1C\x00" // (e) 70
"\x06\x08\x08\x3E\x08\x08\x08\x08\x08\x00" // (f)
"\x00\x00\x1E\x22\x22\x22\x22\x1E\x02\x3C" // (g)
"\x20\x20\x20\x2C\x32\x22\x22\x22\x22\x00" // (h)
"\x00\x08\x00\x38\x08\x08\x08\x08\x3E\x00" // (i)
"\x00\x04\x00\x1C\x04\x04\x04\x04\x04\x18" // (j)
"\x20\x20\x22\x24\x28\x30\x28\x24\x22\x00" // (k)
"\x38\x08\x08\x08\x08\x08\x08\x08\x06\x00" // (l)
"\x00\x00\x76\x49\x49\x49\x49\x49\x49\x00" // (m)
"\x00\x00\x3C\x22\x22\x22\x22\x22\x22\x00" // (n)
"\x00\x00\x1E\x21\x21\x21\x21\x21\x1E\x00" // (o) 80
"\x00\x00\x1E\x11\x11\x11\x11\x1E\x10\x10" // (p)
"\x00\x00\x1E\x22\x22\x22\x22\x1E\x02\x03" // (q)
"\x00\x00\x2E\x30\x20\x20\x20\x20\x20\x00" // (r)
"\x00\x00\x1E\x20\x20\x1C\x02\x02\x3C\x00" // (s)
"\x08\x08\x3E\x08\x08\x08\x08\x08\x06\x00" // (t)
"\x00\x00\x22\x22\x22\x22\x22\x22\x1D\x00" // (u)
"\x00\x00\x22\x22\x22\x14\x14\x08\x08\x00" // (v)
"\x00\x00\x22\x22\x22\x2A\x2A\x14\x14\x00" // (w)
"\x00\x00\x21\x12\x0C\x0C\x0C\x12\x21\x00" // (x)
"\x00\x00\x21\x21\x12\x12\x0C\x0C\x08\x30" // (y) 90
"\x00\x00\x3E\x02\x04\x08\x10\x20\x3E\x00" // (z)
"\x04\x08\x08\x08\x10\x08\x08\x08\x04\x00" // ({)
"\x00\x08\x08\x08\x08\x08\x08\x08\x08\x00" // (|)
"\x10\x08\x08\x08\x04\x08\x08\x08\x10\x00" // (})
"\x00\x00\x00\x00\x19\x26\x00\x00\x00\x00" // (~)
"\x7F\x7F\x63\x5D\x7D\x7B\x73\x7F\x73\x7F" // (_)====== <?>
"\x00\x0C\x12\x21\x21\x3F\x21\x21\x21\x00" // (А)
"\x00\x3E\x20\x20\x3E\x21\x21\x21\x3E\x00" // (Б)
"\x00\x3E\x21\x21\x3E\x21\x21\x21\x3E\x00" // (В)
"\x00\x3E\x20\x20\x20\x20\x20\x20\x20\x00" // (Г)100
"\x00\x0E\x12\x22\x22\x22\x22\x22\x7F\x41" // (Д)
"\x00\x3F\x20\x20\x3E\x20\x20\x20\x3F\x00" // (Е)
"\x00\x49\x49\x2A\x1C\x1C\x2A\x49\x49\x00" // (Ж)
"\x00\x1C\x22\x02\x0C\x02\x02\x22\x1C\x00" // (З)
"\x00\x21\x21\x21\x23\x25\x29\x31\x21\x00" // (И)
"\x04\x29\x21\x21\x23\x25\x29\x31\x21\x00" // (Й)
"\x00\x22\x24\x28\x30\x28\x24\x22\x21\x00" // (К)
"\x00\x03\x05\x09\x11\x21\x21\x21\x21\x00" // (Л)
"\x00\x41\x41\x63\x55\x49\x41\x41\x41\x00" // (М)
"\x00\x21\x21\x21\x3F\x21\x21\x21\x21\x00" // (Н)110
"\x00\x1E\x21\x21\x21\x21\x21\x21\x1E\x00" // (О)
"\x00\x3F\x21\x21\x21\x21\x21\x21\x21\x00" // (П)
"\x00\x1E\x11\x11\x11\x11\x1E\x10\x10\x00" // (Р)
"\x00\x1E\x21\x20\x20\x20\x20\x21\x1E\x00" // (С)
"\x00\x3E\x08\x08\x08\x08\x08\x08\x08\x00" // (Т)
"\x00\x22\x22\x22\x22\x1E\x02\x22\x1C\x00" // (У)
"\x00\x3E\x49\x49\x49\x3E\x08\x08\x08\x00" // (Ф)
"\x00\x21\x12\x12\x0C\x0C\x12\x12\x21\x00" // (Х)
"\x00\x22\x22\x22\x22\x22\x22\x22\x3F\x01" // (Ц)
"\x00\x22\x22\x22\x22\x1E\x02\x02\x02\x00" // (Ч)120
"\x00\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x3E\x00" // (Ш)
"\x00\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x3F\x01" // (Щ)
"\x00\x38\x08\x08\x0E\x09\x09\x09\x0E\x00" // (Ъ)
"\x00\x21\x21\x21\x39\x25\x25\x25\x39\x00" // (Ы)
"\x00\x20\x20\x20\x3C\x22\x22\x22\x3C\x00" // (Ь)
"\x00\x1E\x21\x01\x0F\x01\x01\x21\x1E\x00" // (Э)
"\x00\x26\x29\x29\x39\x29\x29\x29\x26\x00" // (Ю)
"\x00\x1F\x21\x21\x21\x1F\x09\x11\x21\x00" // (Я)
"\x00\x00\x1C\x02\x1E\x22\x22\x22\x1D\x00" // (а)
"\x02\x1C\x20\x3E\x21\x21\x21\x21\x1E\x00" // (б)130
"\x00\x00\x3C\x22\x22\x3C\x22\x22\x3C\x00" // (в)
"\x00\x00\x3E\x22\x20\x20\x20\x20\x20\x00" // (г)
"\x00\x00\x0E\x12\x12\x12\x12\x12\x3F\x21" // (д)
"\x00\x00\x1C\x22\x22\x3E\x20\x20\x1C\x00" // (е)
"\x00\x00\x49\x49\x2A\x1C\x2A\x49\x49\x00" // (ж)
"\x00\x00\x1C\x22\x02\x0C\x02\x22\x1C\x00" // (з)
"\x00\x00\x22\x22\x26\x2A\x32\x22\x22\x00" // (и)
"\x04\x08\x22\x22\x26\x2A\x32\x22\x22\x00" // (й)
"\x00\x00\x22\x24\x28\x30\x28\x24\x22\x00" // (к)
"\x00\x00\x1E\x22\x22\x22\x22\x22\x62\x00" // (л)140
"\x00\x00\x22\x22\x36\x2A\x2A\x22\x22\x00" // (м)
"\x00\x00\x22\x22\x22\x3E\x22\x22\x22\x00" // (н)
"\x00\x00\x1E\x21\x21\x21\x21\x21\x1E\x00" // (о)
"\x00\x00\x3E\x22\x22\x22\x22\x22\x22\x00" // (п)
"\x00\x00\x1E\x11\x11\x11\x1E\x10\x10\x10" // (р)
"\x00\x00\x1C\x22\x20\x20\x20\x22\x1C\x00" // (с)
"\x00\x00\x3E\x08\x08\x08\x08\x08\x08\x00" // (т)
"\x00\x00\x22\x22\x22\x22\x1E\x02\x02\x1C" // (у)
"\x00\x00\x08\x3E\x49\x49\x49\x3E\x08\x00" // (ф)
"\x00\x00\x21\x12\x0C\x0C\x0C\x12\x21\x00" // (х)150
"\x00\x00\x24\x24\x24\x24\x24\x24\x3E\x02" // (ц)
"\x00\x00\x22\x22\x22\x1E\x02\x02\x02\x00" // (ч)
"\x00\x00\x2A\x2A\x2A\x2A\x2A\x2A\x3E\x00" // (ш)
"\x00\x00\x2A\x2A\x2A\x2A\x2A\x2A\x3F\x01" // (щ)
"\x00\x00\x70\x10\x1E\x11\x11\x11\x1E\x00" // (ъ)
"\x00\x00\x41\x41\x79\x45\x45\x45\x79\x00" // (ы)
"\x00\x00\x20\x20\x3C\x22\x22\x22\x3C\x00" // (ь)
"\x00\x00\x3C\x02\x02\x1E\x02\x02\x3C\x00" // (э)
"\x00\x00\x26\x29\x29\x39\x29\x29\x26\x00" // (ю)
"\x00\x00\x1E\x22\x22\x1E\x22\x22\x22\x00" // (я)160
"\x12\x00\x3F\x20\x20\x3E\x20\x20\x3F\x00" // (Ё)
"\x14\x00\x1C\x22\x22\x3E\x20\x20\x1C\x00" // (ё)
"\x4C\x48\x4B\x4B\x68\x5B\x48\x48\x48\x00"; // (№)
// N -число символов в масиве font.
// (sizeof(font)-1) вычитаю концевой ноль.
const int N=(sizeof(font)-1)/10;
//--------- set_pixel --------------
void set_pixel(char *p, int r, int g, int b)
{
*p++ = r; *p++ = g; *p++ = b;
return;
}
//------------ plot -----------
// простые (не жирные) точки
int plot(char *pic, int w, int h, int x, int y,
int r, int g, int b)
{
int k;
if(x<0 || y<0 || x >= (w-0) || y >= (h-0)) return(-1);
k = y*3*w + 3*x;
set_pixel(pic + k, r, g, b);
return(0);
}
//--------------- print_sym -------------
// напечатать один символ. знакоместо 8x10 пикселей
// k -индекс массива font[], по которому лежат битовые маски символа
int print_sym(char *pic, int w, int h, int x, int y, int k,
const unsigned char *font)
{
int x0=x, i, j, n, maska;
for(i=y+10; y<i; y++, k++){ // развёртка знакоместа по вертикали
n = font[k] ; // n -это байт, строка из 8-ми пикселей
maska = 128;
for(x=x0, j=x+8; x<j; x++){ // развёртка по горизонтали
if((n & maska) != 0){
plot(pic, w, h, x, y, 0, 0, 0); // точки символа
}
else{
plot(pic, w, h, x, y, 200, 255, 255); // фон строки
}
maska = maska >> 1;
}
}
return(0);
}
//--------------- print_str ------------
// напечатать строку или многострочный текст, кодировка Win-1251.
// pic -RGB-буфер, 3 байта на пиксель.
// w и h ширина и высота рисунка.
int print_str(char *pic, int w, int h, int x, int y,
const char *str)
{
int i, j, k, c=0, n, y0=y, x0=x, fl;
fl=0; // флаг 1 -символ (c) ещё не обработан, 0 -символ обработан
n=0;
for(i=0;; i++){ // последовательные строки текста
y = y0 + i*11;
if(y>(h-11)) break; // упор в нижний край
for(j=0;; j++){ // последовательно печатать символы
x=x0 + j*8;
if(fl==0){ c = str[n++]&255; fl=1;} // c -текущий символ
if(c==0) break; // конец строки, на выход
if(c==10) break; // (\n) новая срока
if(c < 32){ fl=0; continue;} // непечатные символы
if(x>(w-8)) break; // упор в край, новая строка
else if(c<128) k = (c-31)*10; // ASC-II
else if(c==168) k = 161*10; // Ё
else if(c==184) k = 162*10; // ё
else if(c==185) k = 163*10; // №
else if(c>191) k = (c-31-64)*10; // русские
else k = 0; // <?> символа нет в массиве font[]
if(k>=N*10) k = 0; // <?> массив font[] укорочен снизу
print_sym(pic, w, h, x, y, k, font);
fl=0; // символ напечатан, сбрасываю флаг
}
if(c==0) break;
if(c==10) fl=0; // если по (\n), то обнуляю флаг, а если по
// упору в край, то не обнуляю, символ ещё
// не напечатан.
}
return(0);
}
//----------- main -----------
int main()
{
int i, w=260, h=260;
char *pic=NULL;
FILE *fp=NULL;
const char *f="out.bmp";
//===ТЕСТ строка в кодировке программы
const char str1[] =
"в чащах юга жил бы цитрус?\n"
"да, но фальшивый экземпляр!";
//===ТЕСТ та же строка, что и str1, кодировка windows-1251
const char str2[] =
"\xE2\x20\xF7\xE0\xF9\xE0\xF5\x20\xFE\xE3\xE0\x20\xE6\xE8"
"\xEB\x20\xE1\xFB\x20\xF6\xE8\xF2\xF0\xF3\xF1\x3F\x0A\xE4"
"\xE0\x2C\x20\xED\xEE\x20\xF4\xE0\xEB\xFC\xF8\xE8\xE2\xFB"
"\xE9\x20\xFD\xEA\xE7\xE5\xEC\xEF\xEB\xFF\xF0\x21";
//===ТЕСТ строка в кодировке программы
const char str3[] =
"The quick brown fox jumps over the lazy dog.";
//===ТЕСТ str4[] строка в кодировке, которую даёт терминал,
// ввести произвольную строку с терминала
char *p, str4[600], buf[600];
//=== Ввод строки с терминала ===
printf("N=%d; input string:\n", N); // N -число символов
printf("> "); fflush(stdout);
p = fgets(buf, sizeof(buf), stdin);
if(p==NULL) exit(0);
/*
Для ввода с терминала многострочного текста оформляйте
переносы строк так: \n, а чтобы \n без переноса - так: \\n.
Пример (кому надо - разберутся):
Stroka1\nStroka2\nStroka3\nА это \\n без переноса. \x0A\x0B
*/
for(i=0; *p != 0; p++, i++){
if(*p=='\\'){
if( *(p+1)=='n') { str4[i]=0x0A; p++; continue;}
if( *(p+1)=='\\'){ str4[i]=0x5C; p++; continue;}
}
str4[i]=*p;
}
str4[i]=0;
//===конец ввода===
fp=fopen(f, "w"); // выходной bmp-файл
if(fp==NULL){ printf("fp=fopen(%s)=NULL\n", f); exit(0);}
pic = (char*)malloc(w*h*3); // RGB-буфер рисунка
if(pic==NULL){ printf("pic = (char*)malloc()=NULL\n"); exit(0);}
memset(pic, 255, 3*w*h);
print_str(pic, w, h, 4, 3, str1);
print_str(pic, w, h, 4, 33, str2);
print_str(pic, w, h, 4, 63, str3);
print_str(pic, w, h, 0, 98, "str=");
print_str(pic, w, h, 32, 98, str4);
if(wr_bmp_24_RGB(fp, pic, w, h) < 0){
printf("wr_bmp_24_RGB() < 0\n");
}
exit(0);
}
//--------------- wr_bmp_24_RGB ----------
// записать RGB-буфер в BMP-файл
int wr_bmp_24_RGB(FILE *fp, const char *pic, int w, int h)
{
char hdr[54];
int i, j, dl, pad, w1;
const char *p1;
w1=3*w;
if(w1%4) pad = 4 - w1%4;
else pad=0;
dl = (w1 + pad)*h + 54;
memset(hdr, 0, sizeof(hdr));
hdr[0]='B'; hdr[1]='M';
hdr[2]=dl; hdr[3]=(dl>>8); hdr[4]=(dl>>16); hdr[5]=(dl>>24);
hdr[10]=54; hdr[14]=40;
hdr[18]=w; hdr[19]=(w>>8); hdr[20]=(w>>16); hdr[21]=(w>>24);
hdr[22]=h; hdr[23]=(h>>8); hdr[24]=(h>>16); hdr[25]=(h>>24);
hdr[26]=1; hdr[28]=24;
if(fwrite(hdr, 54, 1, fp) != 1) return(-1);
p1=pic + w1*h;
for(i=0; i<h; i++){
p1 -= w1;
for(j=0; j<w; j++){
if(fputc(*(p1+2), fp) < 0) return(-1);
if(fputc(*(p1+1), fp) < 0) return(-1);
if(fputc(*(p1), fp) < 0) return(-1);
p1 += 3;
}
p1 -= w1;
if(pad>0) if(fwrite("\0\0\0", pad, 1, fp) != 1) return(-1);
}
return(0);
}
|