Сначала давайте отложим часть вашего вопроса в формате TIFF. Основная проблема заключается в том, что вам нужно выяснить, как организовать пиксельные данные в памяти, прежде чем вы сможете сохранить окончательное изображение в любой тип изображения.
Я приведу свой собственный простой пример, чтобы проиллюстрировать, как должны быть организованы эти данные пикселей.
Допустим, мы хотим объединить 9 изображений в таблицу 3х3.
Каждое изображение будет 3х3 пикселя и 8-битным моно (1 канал).
Это делает этот пример красивым и простым с 9 байтами на изображение, и каждое изображение имеет шаг 3 байта на строку.
Объединенное изображение будет 9x9 пикселей, всего 81 байт.
Эти изображения называются A, B, C ... I
A0
- это байт 0 данных пикселей для A, A1
- это байт 1 и т. Д. *
Эти изображения будут организованы в таблицу 3х3, например:
ABC
DEF
GHI
Тогда окончательный макет данных должен выглядеть следующим образом:
byte[] pixelData = [
A0,A1,A2,B0,B1,B2,C0,C1,C2,
A3,A4,A5,B3,B4,B5,C3,C4,C5,
A6,A7,A8,B6,B7,B8,C6,C7,C8,
D0,D1,D2,E0,E1,E2,F0,F1,F2,
D3,D4,D5,E3,E4,E5,F3,F4,F5,
D6,D7,D8,E6,E7,E8,F6,F7,F8,
G0,G1,G2,H0,H1,H2,I0,I1,I2,
G3,G4,G5,H3,H4,H5,I3,I4,I5,
G6,G7,G8,H6,H7,H8,I6,I7,I8
];
Приведенный выше массив пикселей можно записать в любой файл изображения. Включая TIFF.
Обратите внимание на массив выше:
Когда вы выполняете итерацию по этому массиву с индексом от 0 до 80, вы будете перемещаться назад и вперед между тремя изображениями, которые находятся в одной строке, до тех пор, пока вы полностью не достигнете следующей строки, где следующие 3 изображения из этой строки посещаются в одном и том же шаблон.
Чтобы добиться такой раскладки памяти, вы можете использовать несколько подходов.
- Файлы TIFF поддерживают разбиение большого изображения на плитки одинакового размера. Это может быть использовано для достижения того, о чем вы просите, записав каждое изображение в отдельную плитку с помощью библиотеки libTIFF. Существует ограничение, что каждая плитка TIFF должна иметь размеры, кратные 16.
- Класс
Graphics
в System.Drawing
можно использовать для создания одного большого пустого изображения, а затем вы можете нарисовать каждое вспомогательное изображение в большом изображении в любой желаемой позиции. (Это самый простой способ получить то, что вы хотите, но он может быть медленным.)
- Делаем это вручную с помощью цикла:
// For the example I have given above, in pseudo C# code
int composite_stride = image_stride * 3; // 3 is the number of images per row
int composite_size = composite_stride * image_height * 3 // 3 is the number of images per column
byte[] composite_pixels = new byte[composite_size];
// Loop over each image you want to combine
// We need some way to know which row/column the image is from, let that be assigned to table_row and table_col
// We are also assuming all images have the same width and height
foreach (image in table)
{
int comp_x = table_col * image.width;
int comp_y = table_row * image.height;
for (int y=0; y<image.height; y++)
{
// Calculate the array index that the current row starts at
int comp_row_start = comp_y * composite_stride;
for (int x=0; x<image.width; x++)
{
// Calculate the array index in the composite image to write to, and the source image index to copy from
int comp_index = comp_row_start + ((comp_x + x) * image.bytes_per_pixel);
int img_index = (y * image.stride) + (x * image.bytes_per_pixel);
composite_pixels[pixel_index] = image.pixels[img_index];
}
}
}