Я изо всех сил пытаюсь пикселизировать изображение, состоящее из значений RGB, хранящихся в двоичном (P6) файле PPM. Шаги по пикселизации изображения следующие:
- Считайте двоичные данные и сохраните их в одномерном массиве.
- Перебирать данные, хранящиеся в этом массиве, в ячейках размера «c» (строка x столбцов). Эта переменная 'c' может быть изменена пользователем, но для этой программы в настоящее время установлено значение
int c = 4;
, что означает, что она выполняет итерацию по пиксельным данным в блоках размером4 x 4
. - Теперь найдите среднее значение цвета в каждой из этих ячеек размером 'c'.
- Выведите каждое среднее значение цвета в новый выходной файл PPM
Каждый двоичный файл PPM начинается с заголовка в следующем формате, состоящего из «магического числа», за которым следуют ширина, высота и, наконец, максимальное значение цвета 255. Комментарии заголовка игнорируются. Пример заголовка показывает изображение PPM формата P6 (следовательно, это двоичный файл), шириной 16, высотой 16 и максимальным значением цвета 255:
P6
16
16
255
Где я борюсь:
- Я не уверен, как найти среднее значение RGB для каждой ячейки и затем вывести его в новый поток данных. Я нашел способ сделать это при линейном чтении данных (т.е. не считывая их в массив (или буфер)), разделив общее количество цветов в этой ячейке на количество итераций цикла, но это оказалось неверным.
- Упорядочены ли вложенные циклы for таким образом, чтобы изменить ориентацию выходного изображения, например. он поворачивает его на 180 градусов и т. д.? Я изо всех сил пытаюсь определить это при чтении необработанных двоичных данных.
Моя попытка:
#define _CRT_SECURE_NO_WARNINGS //preprocessor requirement
#include <stdio.h> //library for I/O functions
#include <stdlib.h> //library for general functions
#define magic_size 10 //macro for PPM character found within header
typedef struct {
int t_r, t_g, t_b; //Struct to hold RGB pixel data
} Pixel;
int main()
{
char magic_number[magic_size]; //variable for PPM format
int width = 0, height = 0, max_col = 0; //imagine dimensions
int c = 4; //mosaic parameter
/* INPUT FILE HANDLING */
FILE *inputFile;
inputFile = fopen("Sheffield512x512.ppm", "r");
//input file error handling
if (inputFile == NULL)
{
printf(stderr, "ERROR: file cannot be opened");
getchar(); //prevent cmd premature closure
exit(1); //exit program cleanly
}
/* OUTPUT FILE HANDLING */
FILE *outputFile;
outputFile = fopen("mosaic.ppm", "w");
//output file error handling
if (outputFile == NULL)
{
printf(stderr, "ERROR: cannot write to file");
getchar(); //prevent cmd premature closure
exit(1); //exit program cleanly
}
// Scan the header (these variables are used later on)
fscanf(inputFile, "%s\n%d\n%d\n%d", &magic_number, &width, &height, &max_col);
// Error handling. Program only supports binary files (i.e. of P6 format)
if (magic_number[1] != '6')
{
printf("Only Binary images supported!\n");
getchar(); //prevent cmd premature closure
return;
}
// Raw 1 dimensional store of pixel data
Pixel *data = malloc(width*height * sizeof(Pixel));
//2D index to access pixel data
Pixel **pixels = malloc(height * sizeof(Pixel*));
// Read the binary file data
size_t r = fread(data, width*height, sizeof(unsigned char), inputFile);
// Build a 1-dimensional index for the binary data
for (unsigned int i = 0; i < height; ++i)
{
pixels[i] = data + (i * width);
}
// Close the input file
fclose(inputFile);
/* BEGIN PIXELATION PROCESS */
// Print the OUTPUT file header
fprintf(outputFile, "%s\n%d\n%d\n%d", magic_number, width, height, max_col);
//loop condition variables
int cw_x = ceil((double)(width / (float)c));
int cw_y = ceil((double)(height / (float)c));
//iterate through 2d array in cells of size c
for (int c_x = 0; c_x < cw_x; c_x += 1)
{
for (int c_y = 0; c_y < cw_y; c_y += 1)
{
//iterate within the cells
for (int _x = 0; _x < c; _x++)
{
int x = c_x * c + _x;
//bounds checking
if (x < width)
{
for (int _y = 0; _y < c; _y++)
{
int y = c_y * c + _y;
//bounds checking
if (y < height)
{
//write data to the output FILE stream
fwrite(data, width*height, sizeof(unsigned char), outputFile);
}
}
}
}
}
}
//close the output file
fclose(outputFile);
return 0;
}
fread(data, width*height, sizeof(unsigned char), ..)
вы не читаете достаточно, потому что вы должны читать значения RGB, которые являются вашимиPixel
s. - person Paul Ogilvie   schedule 11.05.2019sizeof(Pixel)
может быть больше, чем RGB, потому что компилятор может дополнить структуру. Перед объявлениемPixel
используйте#pragma pack (push n)
сn
размером целых чисел в файле / формате, а затем#pragma pop
. - person Paul Ogilvie   schedule 11.05.2019pixels
. Убери это. - person Paul Ogilvie   schedule 11.05.2019fwrite(data, width*height, ..
, конечно, всегда будет записывать первые байты изображения. - person Paul Ogilvie   schedule 11.05.2019