我稍微更改了您的程序,以一种我在这里用于其他事情的方式,我将把它留在这里作为对您的案例有用的示例,以及测试数据
图像数据结构
typedef struct
{
uint32_t _limit;
uint32_t _imgC; // argc
Record** _imgV; // argv
} ImageData;
-
ImageData 这里是一个动态结构体,容量为_limitRecord 数据结构体。
-
imgC是实际使用的记录数
-
Record** 是指向 Record 结构的指针数组的指针,该结构的长度为 1、2、4 或 8 字节像素数据。这样它就可以同时保存任意数量的任意大小的像素数据
- 这与
main() 中的argc/argv 对完全相同
Record 结构
typedef void Data;
typedef struct
{
uint8_t _id; // 1,2,4 or 8
uint32_t _NumPix; // argc
Data* _data; // argv
} Record; // one record of image data
-
_id 是像素数据长度
-
_NumPix 是像素的总数,正如您所介绍的那样
- 这里的东西和你的程序不同:像素数据在这里分配,是一个
_id * _NumPix字节的区域,像素数据按顺序排列,就像在我的位图构建程序中我改用你的数据一样; )
- 像素数据在此处以
_id 组的形式打包并根据需要解包,只使用void* 指针。
例子
我使用了随机数据和一个“工厂”函数,它构建并返回随机 1-2-4 或 8 字节图像
像素工厂函数
Record* getImage()
{
const uint8_t len[4] = { 1,2,4,8 };
Record* one = (Record*)malloc(sizeof(Record));
one->_id = len[rand() % 4];
one->_NumPix = 1 + rand() % 8;
// now builds the pixels with random values under 255
// here the actual size of EACH record is computed
uint32_t total = one->_NumPix * one->_id;
void* p = (Data**)malloc(total);
uint8_t value = rand() % 255;
// here you get the actual pixel data
memset(p, value, total);
one->_data = (Data**)p;
return one;
};
程序逻辑
#define _BLOCK_SIZE_ 50
#define _IMAGES_ 5
#define _SEED_ 201001
-
图像内存分配在_BLOCK_SIZE_Record*指针块中。在数据采集阶段结束时,阵列被修剪到确切使用的大小。
-
创建数组时,最终未使用的数据为free(),因此ImageData 仅包含与图像数据对应的记录。
-
程序然后显示一些随机记录,这次形成ImageData 数组,以便我们可以将其与构建阶段显示的数据进行比较。
输出示例
DumpImage(Sample 0): 8 8-pixels images [64 bytes]:
0: EC EC EC EC EC EC EC EC
1: EC EC EC EC EC EC EC EC
2: EC EC EC EC EC EC EC EC
3: EC EC EC EC EC EC EC EC
4: EC EC EC EC EC EC EC EC
5: EC EC EC EC EC EC EC EC
6: EC EC EC EC EC EC EC EC
7: EC EC EC EC EC EC EC EC
DumpImage(Sample 1): 4 2-pixels images [8 bytes]:
0: 02 02
1: 02 02
2: 02 02
3: 02 02
DumpImage(Sample 2): 3 2-pixels images [6 bytes]:
0: DC DC
1: DC DC
2: DC DC
DumpImage(Sample 3): 5 2-pixels images [10 bytes]:
0: 75 75
1: 75 75
2: 75 75
3: 75 75
4: 75 75
DumpImage(Sample 4): 7 4-pixels images [28 bytes]:
0: 54 54 54 54
1: 54 54 54 54
2: 54 54 54 54
3: 54 54 54 54
4: 54 54 54 54
5: 54 54 54 54
6: 54 54 54 54
5 Test images loaded
now shows 2 random images from list
DumpImage(From Array: image 3): 5 2-pixels images [10 bytes]:
0: 75 75
1: 75 75
2: 75 75
3: 75 75
4: 75 75
DumpImage(From Array: image 0): 8 8-pixels images [64 bytes]:
0: EC EC EC EC EC EC EC EC
1: EC EC EC EC EC EC EC EC
2: EC EC EC EC EC EC EC EC
3: EC EC EC EC EC EC EC EC
4: EC EC EC EC EC EC EC EC
5: EC EC EC EC EC EC EC EC
6: EC EC EC EC EC EC EC EC
7: EC EC EC EC EC EC EC EC
50 pointers allocated
5 arguments read
45 pointers to free
Block size trimmed for a total of 5 pointers
Image array is ready for use
示例程序到此结束。我没有移植内存的释放,这是微不足道的,并且没有使用数据写任何内容,因为我对此一无所知:)
我也没有做太多测试。请不要在此处进行宗教讨论:是的,我在结构字段的开头使用了下划线。我只使用了现在在这里运行的 Microsoft 编译器 CL 16.7.4。
我将此处的数字设置为 5 条记录,以便发布所有输出数据。但是由于内存中只包含数据,而元数据只有几个词,因此可以运行数千条记录。而且速度很快。
对于大型数据集,最好将 BLOCK_SIZE 更改为更大的数字
示例代码
#define _BLOCK_SIZE_ 50
#define _IMAGES_ 5
#define _SEED_ 201001
#include <math.h>
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
typedef void Data;
typedef struct
{
uint8_t _id; // 1,2,4 or 8
uint32_t _NumPix; // argc
Data* _data; // argv
} Record; // one record of image data
typedef struct
{
uint32_t _limit;
uint32_t _imgC; // argc
Record** _imgV; // argv
} ImageData;
int dumpImage(const char*,Record*);
Record* getImage();
int main(void)
{
srand(_SEED_);
char message[30];
ImageData image;
image._imgC = 0;
image._limit = _BLOCK_SIZE_;
image._imgV = (Record**)malloc( image._limit * sizeof(Record*) );
Record* sandbox;
for (int i = 0; i < _IMAGES_; i += 1)
{
// gets an image and a Record to hold it
sprintf(message, "Sample %d", i);
sandbox = getImage(); // gets a random image
dumpImage(message, sandbox);
Record* target = (Record*)malloc(sizeof(Record)); // new one
target->_id = sandbox->_id;
target->_NumPix = sandbox->_NumPix;
uint32_t total = sandbox->_NumPix * sandbox->_id;
target->_data = (void*)malloc(total);
memcpy(target->_data, sandbox->_data, total);
image._imgV[image._imgC] = target;
// expands the block if there is no space left
if (image._imgC >= image._limit)
{ // block is full
image._limit += _BLOCK_SIZE_;
char* new_block = realloc(image._imgV, (image._limit * sizeof(char*)));
printf("Block extended for a total of %d pointers\n", image._limit);
image._imgV = (Record**)new_block;
}; // if()
image._imgC += 1;
}; // for
printf("\n\n%d Test images loaded\n", image._imgC);
printf("now shows %d random images from list\n\n\n", _IMAGES_ / 2 );
for (int i = 0; i < _IMAGES_ / 2; i += 1)
{
int j = rand() % _IMAGES_;
sprintf(message, "From Array: image %d", j);
sandbox = getImage(); // gets a random image
dumpImage(message,image._imgV[j]);
}; // for()
// now trims the end of the block
// allocated: _limit
// used: argc
printf("\t%d pointers allocated\n", image._limit);
printf("\t%d arguments read\n", image._imgC);
if (image._limit == image._imgC)
printf("\tNothing to free()\n");
else
{
printf("\t%d pointers to free\n", image._limit - image._imgC);
char* new_size = realloc(image._imgV, (image._imgC * sizeof(char*)));
printf("\tBlock size trimmed for a total of %d pointers\n", image._imgC);
image._imgV = (Record**)new_size;
};
printf("\tImage array is ready for use\n");
return 0;
}; // main()
int dumpImage(const char* msg, Record* img)
{
/*
uint8_t _id; // len
uint32_t _NumPix; // argc
Data** _data; // argv
*/
uint32_t total = img->_NumPix * img->_id;
uint8_t* p = (void*)img->_data;
printf("DumpImage(%s): %d %d-pixels images [%d bytes]:\n\n", msg, img->_NumPix, img->_id, total);
for (uint32_t i = 0; i < img->_NumPix; i += 1)
{
printf("%6d: ", i);
for (int j = 0; j < img->_id; j++)
printf("%02X ", *p);
printf("\n");
}; // for()
printf("\n");
return total;
};
//
// Image factory: build random "images"
// id is 1 to 4, NumPix is 1 to 100,
// data is NumPix Pixels with id bytes
//
/*
uint8_t _id; // len
uint32_t _NumPix; // argc
Data** _data; // argv
*/
Record* getImage()
{
const uint8_t len[4] = { 1,2,4,8 };
Record* one = (Record*)malloc(sizeof(Record));
one->_id = len[rand() % 4];
one->_NumPix = 1 + rand() % 8;
// now builds the pixels with random values under 255
uint32_t total = one->_NumPix * one->_id;
void* p = (Data**)malloc(total);
uint8_t value = rand() % 255;
memset(p, value, total);
one->_data = (Data**)p;
return one;
};