对于 3D 矩阵,我通常会将它们转换为 VRML3D 并使用 ParallelGraphics/Cortona3D 来查看它们。
否则,您需要对矩阵进行某种投影或“切片”才能查看所有矩阵。
这是一个将 3D 矩阵转储到 PNG 文件的 C 实现。编译
gcc -W -Wall -o bin2png bin2png.c -lpng
代码:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <png.h>
static png_structp png_ptr;
static png_infop info_ptr;
/**
|<--- W ---->|
+------------+ -
| 18 19 20| |
+-------------+ | |
| 9 10 11 | | |
+-------------+ |23| +--> H
| 0 1 2 | | | |
| |14 | | |
| | |26| |
| 3 4 5 | |--+ + -
| |17 | /
| |---+ +--> D
| 6 7 8 | /
+-------------+ +
@param matrix a 3D matrix. Element [i,j,k] is A[H*(D*k + j) + i]
@param W width
@param H height
@param D depth
@param WW width in W-sized chunks of target image
@param HH height in H-sized chunks of target image
@param filename output filename in PNG format
Output image:
|<----- WW = 2 --->|
+------------------+ -
| 0 1 2 9 10 11| |
| 3 4 5 12 13 14| |
| 6 7 8 15 16 17| HH = 2
| 18 19 20 | |
| 21 22 23 blank | |
| 24 25 26 | |
+------------------+ -
NOTE: W*WW and H*HH may not exceed 32760.
Return:
0 success
-1 cannot create PNG structure (write)
-2 cannot create PNG structure (info)
-3 out of memory
-4 cannot create output file
*/
int matrix3D_to_png(uint8_t *matrix, size_t W, size_t H, size_t D, size_t WW, size_t HH, char *filename)
{
FILE *fp;
png_color palette[16];
png_byte transparencies[16];
uint32_t y;
size_t x;
uint8_t *row;
if( !(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) )
return -1;
if( !(info_ptr = png_create_info_struct(png_ptr)) || setjmp(png_jmpbuf(png_ptr)) ){
/* If we get here, libpng had a problem writing */
png_destroy_write_struct(&png_ptr, &info_ptr);
return -2;
}
if (NULL == (row = malloc(WW*W + 7)))
{
return -3;
}
/* Create 16-color palette for representation */
#define SETPAL(i,r,g,b,a) \
palette[i].red = r; palette[i].green = g; palette[i].blue = b; transparencies[i] = 255-a;
// We will draw the matrix in red if points are nonzero, black if zero; outside the matrix
// we use transparent white.
#define INDEX_IF_ZERO 0
#define INDEX_IF_NONZERO 3
#define INDEX_IF_BLANK 15
SETPAL(0, 0, 0, 0, 0); // Black
SETPAL(1, 255, 255, 255, 0); // Opaque white
SETPAL(2, 192, 192, 192, 0); // Light gray
SETPAL(3, 255, 0, 0, 0); // Red
SETPAL(4, 0, 255, 0, 0); // Green
SETPAL(5, 0, 0, 255, 0);// Blue
SETPAL(6, 255, 0, 0, 128); // Halftransparent red
SETPAL(7, 0, 255, 0, 128); // green
SETPAL(8, 0, 0, 255, 128); // blue
SETPAL(9, 255, 0, 0, 0); // red again :-)
SETPAL(10, 0, 255, 0, 0);
SETPAL(11, 0, 0, 255, 0);
SETPAL(12, 255, 0, 0, 0);
SETPAL(13, 0, 255, 0, 0);
SETPAL(14, 0, 0, 255, 0);
SETPAL(15, 255, 255, 255, 255); // Transparent white
/* End palette */
/* Create filename */
if (NULL == (fp = fopen(filename, "w")))
{
fprintf(stderr, "cannot open output '%s': %s\n", filename, strerror(errno));
return -4;
}
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, W*WW, H*HH, 8, PNG_COLOR_TYPE_PALETTE,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_set_PLTE(png_ptr, info_ptr, palette, 16);
png_set_tRNS(png_ptr, info_ptr, transparencies, 16, NULL);
png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
png_write_info(png_ptr, info_ptr);
for (y = 0; y < H*HH; y++)
{
size_t mx = y/H;
mx = (mx*H*WW + (y%H))*W;
for (x = 0; x < WW; x++)
{
if (mx+x*H >= H*D)
memset(row+x*W, INDEX_IF_BLANK, W);
else
{
size_t ii;
for (ii = 0; ii < W; ii++)
row[x*W+ii] = (matrix[mx+x*W*H+ii]) ? INDEX_IF_NONZERO : INDEX_IF_ZERO;
}
}
png_write_row(png_ptr, row);
}
png_write_end(png_ptr, NULL /*info_ptr*/);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
free(row);
return 0;
}
int main(int argc, char **argv)
{
FILE *fp;
uint8_t *matrix;
size_t W, H, D, WW, HH, i;
if (8 != argc)
{
fprintf(stderr, "Syntax: %s input output.png width height depth TileX TileY\n", *argv);
return EXIT_FAILURE;
}
W = atol(argv[3]);
H = atol(argv[4]);
D = atol(argv[5]);
WW = atol(argv[6]);
HH = atol(argv[7]);
if ((W * WW > 32767)||(H * HH) > 32767)
{
fprintf(stderr, "Output image would be too large\n");
return EXIT_FAILURE;
}
if (WW*HH < D)
{
fprintf(stderr, "WARNING: matrix does not fit into output image\n");
}
if (WW*HH > D*2)
{
fprintf(stderr, "WARNING: output image is far larger than input matrix\n");
}
if (NULL == (fp = fopen(argv[1], "r")))
{
fprintf(stderr, "Input file not found\n");
return EXIT_FAILURE;
}
if (NULL == (matrix = malloc(W*H*D)))
{
fprintf(stderr, "Out of memory: matrix too large\n");
return EXIT_FAILURE;
}
for (i = 0; i < D; i++)
{
int ret;
if ((int)H != (ret = fread(matrix + W*H*i, W, H, fp)))
{
fprintf(stderr, "Read error at plane %d (reading %d rows of %d elements, expecting %d, got %d)\n",
(int)i, (int)W, (int)H, (int)H, ret);
fclose(fp);
return EXIT_FAILURE;
}
}
if (matrix3D_to_png(matrix, W, H, D, WW, HH, argv[2]))
{
fprintf(stderr, "Error in creating output PNG '%s'\n", argv[2]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}