§ Как устроен формат
Этот формат переводится как Portable Pixel Map и настолько прост, что даже BMP кажется сложным.Первые строки в файле PPM пишутся так:
P6 # Здесь может быть комментарий 640 400 255
- Здесь P6 означает "магическое число формата". После P6 ставится символ \n переноса строки. Тут может быть не только P6, но и P3. Этот формат можно посмотреть тут.
- Комментариев может быть сколько угодно, они начинаются с #
- Сразу после комментария идет размер по ширине и высоте
- 255 означает что далее идет RGB последовательность
§ Код для записи файла
В data находятся числа в формате int, причем blue-компонента находится в младшем байте. Альфа-канал не записывается.int write_ppm(const char* filename, int width, int height, int data[]) { FILE* fp = fopen(filename, "wb"); char buf[256]; if (fp) { sprintf(buf, "P6\n# G++ HELLO WORLD\n%d %d\n255\n", width, height); fputs(buf, fp); for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { int cl = data[y*width+x]; buf[0] = cl>>16; buf[1] = cl>>8; buf[2] = cl; fwrite(buf, 1, 3, fp); } fclose(fp); } }Тестовый код для записи в файл
int main(int argc, char* argv[]) { int data[640*480]; for (int y = 0; y < 480; y++) for (int x = 0; x < 640; x++) { data[640*y + x] = x*y; } write_ppm("file.ppm", 640, 480, data); return 0; }
§ Код для чтения из PPM
Чтение из файла, создание новой области памяти и заполнить значениями RGB.unsigned char* loadppm(const char* fn) { char buf[512]; unsigned char* pixels; FILE* fp = fopen(name, "rb"); if (fp) { fgets(buf, 512, fp); do { fgets(buf, 512, fp); } while (buf[0] == '#'); // Попробовать распарсить данные W x H sscanf(buf, "%d %d", &width, &height); // Другой формат. Дочитать if (width && !height) { fgets(buf, 512, fp); sscanf(buf, "%d", &height); } // Прочесть число 255 fgets(buf, 512, fp); // Выделить память pixels = (unsigned char*) malloc(3 * width * height); fread(pixels, 3, width * height, fp); fclose(fp); } return pixels; }