LINUX.ORG.RU

Как прочитать тга файл?

 


0

1

Использую такой код,но он не дочитавается до конца похоже, обязательно нужен буфер из чаров

FILE *f = fopen("Screen.tga", "r");
char* buffer =new char[10240000];
    if (f != NULL)
    {
        int countfile = 0;
        while ((buffer[countfile++] = getc(f)) != EOF)
            ;
        fclose(f);
    }



Последнее исправление: cetjs2 (всего исправлений: 3)
        // ...
        int c;
        while ((c = getc(f)) != EOF)
            buffer[countfile++] = c;
        // ...

А вообще лучше узнать размер файла, выделить буфер и считать файл за один вызов.

xaizek ★★★★★
()

while ((buffer[countfile++] = getc(f)) != EOF)

У тебя будет рак яичек. Мало того, что этот однострочник сам по себе отвратителен, так еще и является причиной твоей проблемы.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)

char* buffer =new char[10240000];

Ты С++ учил по книге 80-х годов прошлого века? О RAII слышал? std::vector?

Begemoth ★★★★★
()

fopen_s(&f, «Screen.tga», «r»);

while ((buffer[countfile++] = getc(f)) != EOF)

Это код на конкурс самого забагованного и дырявого софта?

Begemoth ★★★★★
()
Последнее исправление: Begemoth (всего исправлений: 1)

«r»

Если ты ничего не менял, то это открывает файл в текстовом режиме, что может изменить байты, которые ты читаешь из файла. Например, производится преобразование \r\n в \n.

i-rinat ★★★★★
()
Ответ на: комментарий от bad_master

K&R - это С, а вот это:

new char[10240000];

С++, они не могли про это писать. С учётом, что у тебя Visual C++, а не какая-то окаменелось где есть только компилятор С, стоит всё-таки почитать книги по современному С++ (https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list).

Begemoth ★★★★★
()

Ну что-то такое будет для чтения, разбор уж сам, а вообще если нет цели поупражняться, то лучше поискать готовую библиотеку

//...
typedef struct tga_image_header
{
	uint8_t  id;
	uint8_t  color_map_type;
	uint8_t  image_type;
	uint8_t  color_map_specs[5];
	uint16_t offset_x;
	uint16_t offset_y;
	uint16_t image_width;
	uint16_t image_height;
	uint8_t  image_depth;
	uint8_t  image_descriptor;
} tga_image_header;

//...
//const char * filename = ...
FILE * image = fopen(filename, "r");
tga_image_header tih;
fread(&tih, sizeof(tga_image_header), 1, image);

uint8_t bytes_per_pixel = tih.image_depth >> 3;

uint8_t *raw_data = (uint8_t*)malloc(
		tih.image_width * 
		tih.image_height* 
		bytes_per_pixel * sizeof(uint8_t));

fread(raw_data, sizeof(uint8_t),
	tih.image_width * 
	tih.image_height * 
	bytes_per_pixel, image);
//...
AKonia ★★
()
Ответ на: комментарий от Begemoth

В двоичном тоже не хочет до конца файла считывать

bad_master
() автор топика

char* buffer =new char[10240000];

  1. Что будет если файл больше?
  2. Кто будет освобождать этот буфер?

Ну и, как выше уже сказали, либо пиши на C и используй malloc()/free(), либо пиши на C++ и используй std::vector.

    while ((buffer[countfile++] = getc(f)) != EOF)
  1. getc() возвращает не unsigned char, а int. И сделано это специально, чтобы можно было вернуть EOF, который в unsigned char не влезет. У тебя int преобразуется в char, а затем char сравнивается с EOF. Тут то всё и ломается.
  2. Побайтовое чтение - очень медленное. Лучше читать блоками.
im-0
()

По совету что надо читать в int,а не в char сделал чтение таким образом

    FILE* f=fopen("Screen.tga", "rb");
    if (f != NULL)
    {
        int countfile = -1;
        int c;
        while ((c = getc(f)) != EOF)
            buffer[++countfile] = c;
        fclose(f);
        std::cout << countfile;
    }
bad_master
() автор топика
Последнее исправление: bad_master (всего исправлений: 1)
Ответ на: комментарий от bad_master

Тогда ваш вопрос вводит в заблуждение, т.к. разницы между файлами как де факто двоичными последовательностями нет, вы же указали уточнение о формате файла, что наводит на мысль о необходимости его разбора, короче: пишите вопросы настолько точно, насколько это необходимо.

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 1)
Ответ на: комментарий от bad_master

Странные советы вам конечно дают, если вам просто считать файл целиком в двоичном виде, то вот это если средствами сишки:

	FILE * input = fopen("картинка.tga", "rb");
	fseek(input, 0, SEEK_END); // Ставим в конец
	int size = ftell(input); // узнаём смещение в конце = размер файла
	fseek(input, 0, SEEK_SET); // Ставим на начало
	char data[size];
	fread(data, size, 1, input);
AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 3)
Ответ на: комментарий от AKonia

int size = ftell(input); // узнаём смещение в конце = размер файла

Что будет, если файл изменится между получением размера и чтением?

char data[size];

Stack overflow. Нельзя так делать, если железобетонно не гарантируется, что у size есть верхняя граница, и что она достаточно мала, чтобы на стеке хватило места.

im-0
()
Последнее исправление: im-0 (всего исправлений: 1)
Ответ на: комментарий от im-0
  1. А что сразу не предрались к отсутствию проверки input на 0 ? Плюс я не помню, чтобы ТС просил «устойчивость при изменении файла в любое время, очень важное и необходимое в 0,1% случаев»
  2. Суть не в SO, а в том, что я хотел акцентировать внимание на выделение пямяти и уместить в меньшее количество знаков… ну если это нужно объяснять, печально….
AKonia ★★
()
Ответ на: комментарий от AKonia

На сколько я понимаю, это так не работает

Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state.

Стандарт, внизу 267 страницы.

То есть, если это бинарь, а tga – бинарь, fseek(file, 0, SEEK_END) перейдёт к первому попавшемуся \0.

com
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.