Nightpoison Ответов: 2

Как сохранить 2d массив в новый массив...(beaglebone black)


Я работаю с bmp-изображениями, которые я передаю 2d-массиву по ссылке на функцию, которая открывает bmp и сохраняет его с помощью структуры. Когда функция завершается, у меня есть ссылка на адрес. Я могу добавить его в новый массив для хранения открытого bmp, но поскольку это ссылка, все местоположения нового массива имеют одну и ту же ссылку.

видеть https://www.codeproject.com/Questions/5248639/Why-is-my-array-index-values-all-the-same в качестве ссылки на мою первоначальную проблему.

Поэтому мне нужно снять ссылку и вставить только значения 2d-массива. Как мне это сделать?

typedef struct pixel {
	uint8_t r;
	uint8_t g;
	uint8_t b;

} pixel;

//image_names = name of all images which have been sorted
//num_images = total number of images
//IMG_Y = 360
//IMG_X = 640

pixel** img;
struct pixel** images[num_images];

// Allocate image structure which will be used to load images
img = (pixel**)malloc (IMG_Y * sizeof (pixel*));
for (i = 0; i < IMG_Y; i++) 
{
		img[i] = (pixel*)malloc (IMG_X * sizeof (pixel));
}

for (i = 0; i < num_images; i++)
{
	// Open image and ensure it's successful. 
	if (open_bmp (*(image_names + i), img) == EXIT_FAILURE) 
    {
		return EXIT_FAILURE;
	}

	images[i] = img;
	}
}

int open_bmp (char * file_name, pixel** img) {
	// Variable declarations
	long offset = 0;
	unsigned char buff[100];
	int x = 0, y = 0;
	FILE *f = fopen (file_name, "rb"); // open file in binary mode

	// Read pixel data
	fseek (f, offset, SEEK_SET); // go to beginning of pixel data
	while ((fread (&buff, 3, 1, f) >= 1) && y < IMG_Y) // while not EOF (or done with image), read next pixel
	{
		img[y][x].r = buff[2];
		img[y][x].g = buff[1];
		img[y][x].b = buff[0];

		x++; // read next column
		if (x >= IMG_X) { // finished reading row, go to next row
			y++;
			x = 0;
		}
	}

	if (PRINTBMPDATA) {
		for (y = 0; y < IMG_Y; y++) {
			for (x = 0; x < IMG_X; x++) {
				printf ("%02x%02x%02x ", img[y][x].b, img[y][x].g, img[y][x].r);
			}
			printf ("\n");
		}
		printf ("\n");
	}

	// Close image file now that we have copied it to the img structure
	if (fclose (f)) {
		printf ("Unable to close image file\n");
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}


Что я уже пробовал:

То, что я пытался сделать, было де-референцией. Который вставил только одно значение 0.

images[i] = **img
в результате получился всего лишь 1D массив

Затем я подумал, что должен попытаться передать 3D-массив, изменить open_bmp() и просто сделать то же самое, что я делаю сейчас, но при переходе к open_bmp() заполнить уровни 2 и 3. вот изменения, которые я сделал.
pixel*** img;

	// Allocate image structure which will be used to load images
	img = (pixel***)malloc (num_images * sizeof (pixel**));
	for(i = 0; i < num_images; i++)
	{

		img[i] = (pixel**)malloc (IMG_Y * sizeof (pixel*));
		for (k = 0; k < IMG_Y; i++)
			img[i][k] = (pixel*)malloc (IMG_X * sizeof (pixel));
	}

for (i = 0; i < num_images; i++)
	{
	// Open image and ensure it's successful. Inefficent to load file everytime but fine at BeagleBone's low effective video framerates
		if (open_bmp (*(image_names + i), img, i) == EXIT_FAILURE) {
			return EXIT_FAILURE;
		}
	}

int open_bmp (char * file_name, pixel*** img, int idx) {

	printf ("Index: %d\n", idx);
	// Variable declarations
	long offset = 0;
	unsigned char buff[100];
	int x = 0, y = 0;
	FILE *f = fopen (file_name, "rb"); // open file in binary mode

	// Read pixel data
	fseek (f, offset, SEEK_SET); // go to beginning of pixel data
	while ((fread (&buff, 3, 1, f) >= 1) && y < IMG_Y) // while not EOF (or done with image), read next pixel
	{
		img[idx][y][x].r = buff[2];
		img[idx][y][x].g = buff[1];
		img[idx][y][x].b = buff[0];

		x++; // read next column
		if (x >= IMG_X) { // finished reading row, go to next row
			y++;
			x = 0;
		}
	}

	if (PRINTBMPDATA) {
		for (y = 0; y < IMG_Y; y++) {
			for (x = 0; x < IMG_X; x++) {
				printf ("%02x%02x%02x ", img[idx][y][x].b, img[idx][y][x].g, img[idx][y][x].r);
			}
			printf ("\n");
		}
		printf ("\n");
	}

	// Close image file now that we have copied it to the img structure
	if (fclose (f)) {
		printf ("Unable to close image file\n");
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}
хотя я написал тестовый пример, и он отлично работает, я нашел много ссылок, утверждающих, что 3d+ массивы-это плохая идея в этом смысле. Другая проблема заключается в том, что сама программа не выполняется.

2 Ответов

Рейтинг:
0

Richard MacCutchan

Я не уверен, что понимаю вашу проблему, но вы неправильно обрабатываете файл. Растровый файл - это не простой 2d массив пикселей; см. Хранилище растровых изображений - приложения для Windows | Microsoft Docs[^В зависимости от того, что вы пытаетесь сделать, все, что вам нужно для чтения файла, - это выделить буфер достаточно большой, чтобы содержать все содержимое, и прочитать файл непосредственно в этот буфер. Затем вы можете сохранить адрес этого буфера в простом массиве или наборе структур. Затем вы можете обрабатывать фактические растровые данные в памяти в соответствии с требованиями вашего приложения.


Рейтинг:
0

CPallini

Я покажу вам, как распределять (и освобождать) память.
Следующий код загружает данные из фиксированного размера (36x64x3 байты) файлы 'image' с именем 'img00.bmp', 'img01.bmp', ..
Затем выводит содержимое пикселя (числа) на консоль.
Наконец, очищает память и выходит.
Вы можете использовать его в качестве отправной точки (если ваши изображения не имеют одинакового размера, то вам следует создать структуру изображения, содержащую ширину и высоту изображения вместе с фактическими данными пикселей).

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


typedef struct pixel
{
  uint8_t r;
  uint8_t g;
  uint8_t b;
} pixel;

#define IMG_Y  36
#define IMG_X  64

int open_bmp (pixel *** images, int image_no);
void dump_image( pixel ** image );

int main()
{
  size_t num_images;
  printf("please enter the number of images:\n");
  if ( scanf("%lu", &num_images ) != 1 || num_images > 16)
  {
    fprintf(stderr, "invalid input\n");
    return -1;
  }

  struct pixel ** images[num_images];

  // allocate memory
  for (size_t n=0; n<num_images; ++n)
  {
    images[n] = (pixel ** ) malloc (IMG_Y * sizeof( pixel * ));
    assert(images[n]); 
    for (size_t y = 0; y<IMG_Y; ++y)
    {
      images[n][y] = (pixel *) malloc( IMG_X * sizeof( pixel));
      assert(images[n][y]);
    }
    assert( ! open_bmp(  images, n )  );
  }

  // show the content of the images
  for (size_t n=0; n<num_images; ++n)
    dump_image(images[n]);

  // cleanup
  for (size_t n=0; n<num_images; ++n)
  { 
    for (size_t y = 0; y<IMG_Y; ++y)
      free( images[n][y] );
    free(images[n]);
  }
}

int open_bmp (pixel *** images, int image_no)
{

  char filename[] = "imgNN.bmp";
  sprintf(filename, "img%02d.bmp", image_no);
  FILE * fp = fopen(filename, "rb");
  if ( ! fp ) return -1;

  pixel ** image = images[image_no];

  for (size_t y = 0; y < IMG_Y; ++y)
  {
    pixel * row = image[y];
    for ( size_t x = 0; x < IMG_X; ++x)
    {
      uint8_t buf[3];
      if ( fread( &buf, 3, 1, fp ) != 1 )
        return -2;
      row[x].r = buf[2];
      row[x].g = buf[1];
      row[x].b = buf[0];
    }
  }
  fclose(fp);
  return 0;
}

void dump_image( pixel ** image )
{
  for (size_t y = 0; y < IMG_Y; ++y)
  {
    pixel * row = image[y];
    for ( size_t x = 0; x < IMG_X; ++x)
    {
      printf("{%03d, %03d, %03d}, ", row[x].r, row[x].g, row[x].b);
    }
    printf("\n");
  }
}