Считать картинку в массив char*
От: cupuyc.  
Дата: 13.02.14 12:57
Оценка: -1 :))
Доброго времени суток.
Пытаюсь считать изображение в массив символов:


    CFile            m_BodyFile;
        size_t            inbuflen = 0;
    long            textSize = 0;
    long            id = 2;
    
    m_BodyFile.Open("H:\\img.jpg", CFile::modeReadWrite);

    inbuflen = m_BodyFile.GetLength();
    m_BodyFile.SeekToBegin();

    char* inbuf = new char [inbuflen+1];
      inbuf[inbuflen]='\0';    

    UINT count = m_BodyFile.Read(inbuf,inbuflen*sizeof(char));


... файл весит 5481 байт, функция Read возвращает значение 5481, однако в inbuf записывается только 4 символа и длина этой строки равна 4. Не могу понять почему функция не считывает весь файл.
Re: Считать картинку в массив char*
От: Nikе Россия  
Дата: 13.02.14 13:05
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>... файл весит 5481 байт, функция Read возвращает значение 5481, однако в inbuf записывается только 4 символа и длина этой строки равна 4. Не могу понять почему функция не считывает весь файл.


Пятым символом в файле идёт 0. Для сишной строки это интерпретируется как конец.

Нельзя бинарные файлы рассматривать как С-строки. Ноль в конце буфера — бесполезен. Используй std::vector.
Нужно разобрать угил.
Re[2]: Считать картинку в массив char*
От: cupuyc.  
Дата: 13.02.14 13:11
Оценка:
Здравствуйте, Nikе, Вы писали:

N>Здравствуйте, cupuyc., Вы писали:


C>>... файл весит 5481 байт, функция Read возвращает значение 5481, однако в inbuf записывается только 4 символа и длина этой строки равна 4. Не могу понять почему функция не считывает весь файл.


N>Пятым символом в файле идёт 0. Для сишной строки это интерпретируется как конец.


N>Нельзя бинарные файлы рассматривать как С-строки. Ноль в конце буфера — бесполезен. Используй std::vector.


спасибо за ответ. А можно код вызова функции Read c вектором?
Re[3]: Считать картинку в массив char*
От: Хреннос  
Дата: 13.02.14 13:14
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>спасибо за ответ. А можно код вызова функции Read c вектором?


Даже я умею:

std::vector<char> inbuf( inbuflen );
UINT count = m_BodyFile.Read( &inbuf[0], inbuflen * sizeof(char) );
Re[4]: Считать картинку в массив char*
От: cupuyc.  
Дата: 13.02.14 13:15
Оценка:
Здравствуйте, Хреннос, Вы писали:

Х>Здравствуйте, cupuyc., Вы писали:


C>>спасибо за ответ. А можно код вызова функции Read c вектором?


Х>Даже я умею:


Х>std::vector<char> inbuf( inbuflen );

Х>UINT count = m_BodyFile.Read( &inbuf[0], inbuflen * sizeof(char) );

спасибо
Re[3]: Считать картинку в массив char*
От: Nikе Россия  
Дата: 13.02.14 13:16
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>спасибо за ответ.


Для этого есть оценки.

C>А можно код вызова функции Read c вектором?


Модифицирую только то что касается вектора:
    CFile            m_BodyFile;
    size_t            inbuflen = 0;
    long            textSize = 0;
    long            id = 2;
    
    m_BodyFile.Open("H:\\img.jpg", CFile::modeReadWrite);

    inbuflen = m_BodyFile.GetLength();
    m_BodyFile.SeekToBegin();

    std::vector<char> inbuf;
    if ( inbuflen > 0 )
    {
        inbuf.resize( inbuflen );

        UINT count = m_BodyFile.Read( &inbuf[0], inbuflen );
        // UINT count = m_BodyFile.Read( inbuf.data(), inbuflen ); для свежих версий С++
        // check
    }
Нужно разобрать угил.
Re[4]: Считать картинку в массив char*
От: Nikе Россия  
Дата: 13.02.14 13:17
Оценка:
Здравствуйте, Хреннос, Вы писали:

Х>std::vector<char> inbuf( inbuflen );

Х>UINT count = m_BodyFile.Read( &inbuf[0], inbuflen * sizeof(char) );

При нулевом размере файла — упадёт.
Зачем делать inbuflen * sizeof(char) — не понятно. Не зачёт
Нужно разобрать угил.
Re: Считать картинку в массив char*
От: uzhas Ниоткуда  
Дата: 13.02.14 13:20
Оценка: 3 (1)
Здравствуйте, cupuyc., Вы писали:


C>однако в inbuf записывается только 4 символа

туда записалось именно столько, сколько вернула функция Read, просто вы плохо проверили, что записано в этой строчке

C> и длина этой строки равна 4

ее длина больше. просто вы остановились на символе с кодом 0. это особенность отображения Си строк. чтобы посмотреть массив в студии, можно ввести в окне Watch такое: "inbuf,40". студия покажет первые 40 байт из строки

успехов
Re[3]: Считать картинку в массив char*
От: Vzhyk  
Дата: 13.02.14 13:24
Оценка:
2/13/2014 4:11 PM, cupuyc. пишет:

> спасибо за ответ. А можно код вызова функции Read c вектором?

http://www.cplusplus.com/
Ну и почитай хотя бы Страуструпа.
Posted via RSDN NNTP Server 2.1 beta
Re: Считать картинку в массив char*
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 13.02.14 13:56
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>Доброго времени суток.


C>... файл весит 5481 байт, функция Read возвращает значение 5481, однако в inbuf записывается только 4 символа и длина этой строки равна 4. Не могу понять почему функция не считывает весь файл.

Там всё считывается, просто ты не правильно интерпретируешь результат. Это потому, что в данном конксте не надо воспринимать char как символ потом, что это байт и значение этого байта могут быть от 0 до 255. Поэтому и работать тебе надо с ним как с байтом.
Убедись, что файл открыт в бинаром режиме, вместо char* inbuf используй std::vector<unsigned char>, ну и вместо CFile я бы использовал std::ifstream ибо нефиг!
Sic luceat lux!
Re: Считать картинку в массив char*
От: flаt  
Дата: 13.02.14 14:02
Оценка: 1 (1) -2
Здравствуйте, cupuyc., Вы писали:

C> m_BodyFile.Open("H:\\img.jpg", CFile::modeReadWrite);

C>... файл весит 5481 байт, функция Read возвращает значение 5481, однако в inbuf записывается только 4 символа и длина этой строки равна 4. Не могу понять почему функция не считывает весь файл.

Выше ответили: "Пятым символом в файле идёт 0."

Поэтому для бинарных файлов CFile::modeRead|CFile::typeBinary.
Re[5]: Считать картинку в массив char*
От: Хреннос  
Дата: 13.02.14 16:30
Оценка:
Здравствуйте, Nikе, Вы писали:

N>Здравствуйте, Хреннос, Вы писали:


Х>>std::vector<char> inbuf( inbuflen );

Х>>UINT count = m_BodyFile.Read( &inbuf[0], inbuflen * sizeof(char) );

N>При нулевом размере файла — упадёт.


Зависит от реализации, в т.ч. и метода Read.
&inbuf[0], скорее всего, не упадет, а если Read реализован оптимально, то при нулевом размере буфера он к переданному указателю обращаться не будет — что есть хорошо.

N>Зачем делать inbuflen * sizeof(char) — не понятно. Не зачёт


Молодец, очень полезное замечание. Возьми сосательную конфетку
Автор: __kot2
Дата: 10.02.14
.
Re[6]: Считать картинку в массив char*
От: Nikе Россия  
Дата: 13.02.14 16:42
Оценка: +1
Здравствуйте, Хреннос, Вы писали:

Х>Зависит от реализации, в т.ч. и метода Read.

Х>&inbuf[0], скорее всего, не упадет

Что значит — скорее всего? Обращаться к невалидному элементу — нельзя.
Нужно разобрать угил.
Re[7]: Считать картинку в массив char*
От: Хреннос  
Дата: 14.02.14 03:55
Оценка: -1
Здравствуйте, Nikе, Вы писали:

N>Здравствуйте, Хреннос, Вы писали:


Х>>Зависит от реализации, в т.ч. и метода Read.

Х>>&inbuf[0], скорее всего, не упадет

N>Что значит — скорее всего? Обращаться к невалидному элементу — нельзя.


Обращаться нельзя, ага. А вот брать адрес — можно.
"Скорее всего" означает ровно то, что означает: в большинстве реализаций std::vector взятие адреса от невалидного элемента не приведет к падению программы. Просто адрес будет левый (возможно, нулевой).
Если обращение по этому адресу не происходит, то и падения не будет (тут зависит от реализации Read).

Я не говорю, что этот код кристально-правильный и так и надо писать в продакшене. Это всего лишь минимальный пример без обработки ошибок. Но вы — молодец, я вами восхищаюсь, заметили потенциальную ошибку и написали.
Re[8]: Считать картинку в массив char*
От: McQwerty Россия  
Дата: 14.02.14 06:45
Оценка:
Здравствуйте, Хреннос, Вы писали:

Х>>>&inbuf[0], скорее всего, не упадет

N>>Что значит — скорее всего? Обращаться к невалидному элементу — нельзя.
Х>"Скорее всего" означает ровно то, что означает: в большинстве реализаций std::vector взятие адреса от невалидного элемента не приведет к падению программы. Просто адрес будет левый (возможно, нулевой).

STLport, например, в отладочной сборке бросит исключение:
  reference operator[](size_type __n) {
    _STLP_VERBOSE_ASSERT(__n < size(), _StlMsg_OUT_OF_BOUNDS)
    return _M_non_dbg_impl[__n];
  }
Re[9]: Считать картинку в массив char*
От: Хреннос  
Дата: 14.02.14 07:24
Оценка:
Здравствуйте, McQwerty, Вы писали:

MQ>STLport, например, в отладочной сборке бросит исключение:


И правильно сделает.

Не считаю нужным снабжать двухстрочный пример обработкой ошибок. Подразумевается, что топикстартер сам ошибки обработает, причем именно так, как надо ему.
Я бы, например, вообще с ошибкой выходил из функции сразу после получения нулевой длины файла — не доходя до создания вектора и чтения в него. Ибо нефиг.
Но вы оба мо-лод-цы.
Re[4]: Считать картинку в массив char*
От: Lorenzo_LAMAS  
Дата: 14.02.14 08:10
Оценка:
Здравствуйте, Vzhyk, Вы писали:

V>2/13/2014 4:11 PM, cupuyc. пишет:


>> спасибо за ответ. А можно код вызова функции Read c вектором?

V>http://www.cplusplus.com/
V>Ну и почитай хотя бы Страуструпа.

в наше время говорить "хотя бы" о книге с довольно-таки мутными (ИМХО) разглагольствованиями на 1200 с чем-то страниц ....
впрочем, какую именно книгу ты имел в виду? а то у него две: очередное издание "Языка программирования" и вот эта http://www.stroustrup.com/programming.html (не знаю, как в переводе ее назвали)
Of course, the code must be complete enough to compile and link.
Re[5]: Считать картинку в массив char*
От: Vzhyk  
Дата: 14.02.14 08:28
Оценка: +1
2/14/2014 11:10 AM, Lorenzo_LAMAS пишет:

> в наше время говорить "хотя бы" о книге с довольно-таки мутными (ИМХО)

> разглагольствованиями на 1200 с чем-то страниц ....
Логично, лучше здесь спросить, нафига читать-то.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Считать картинку в массив char*
От: Lorenzo_LAMAS  
Дата: 14.02.14 08:58
Оценка:
Здравствуйте, Vzhyk, Вы писали:

V>2/14/2014 11:10 AM, Lorenzo_LAMAS пишет:


>> в наше время говорить "хотя бы" о книге с довольно-таки мутными (ИМХО)

>> разглагольствованиями на 1200 с чем-то страниц ....
V>Логично, лучше здесь спросить, нафига читать-то.

как видишь, вполне логично — он спросил, и ему ответили.
читать, конечно, полезно. но если ты не понял, о чем был мой комментарий — мне понравилось твое "хотя бы" в
отношении книги Страуструпа, которая совершенно монструозна и по объему и по манере изложения.
впрочем, конечно, мне неведомо — давно ли ты эту книгу видел и какое издание читал, если читал.
Of course, the code must be complete enough to compile and link.
Re[7]: Считать картинку в массив char*
От: Vzhyk  
Дата: 14.02.14 09:13
Оценка: +1
2/14/2014 11:58 AM, Lorenzo_LAMAS пишет:

> впрочем, конечно, мне неведомо — давно ли ты эту книгу видел и какое

> издание читал, если читал.
До 3-его все. Имхо, самая адекватная была в свое время.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Считать картинку в массив char*
От: Ops Россия  
Дата: 15.02.14 21:57
Оценка: :)
Здравствуйте, Vzhyk, Вы писали:

V>http://www.cplusplus.com/

Не надо это советовать, там ересь встречается.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re: Считать картинку в массив char*
От: smeeld  
Дата: 16.02.14 07:27
Оценка:
Здравствуйте, cupuyc., Вы писали:

Зачем сжатые данные, упакованные в контейнер .jpg тупо
копировать в буфер? Используйте libjpeg для распаковки.
Не знаю как с этим в win, на *nix-ах код будет выглядеть так:

struct _error_mgr {
  struct jpeg_error_mgr pub;

  jmp_buf setjmp_buffer;
};

typedef struct _error_mgr * _error_ptr;



METHODDEF(void)
  _error_exit (j_common_ptr cinfo)
{
  
  _error_ptr er = (_error_ptr) cinfo->err;

 
  (*cinfo->err->output_message) (cinfo);


  longjmp(er->setjmp_buffer, 1);
  }


GLOBAL(int)
read_JPEG_file (char * filename, unsigned char** extbuf)
{
  
  struct _error_mgr jerr;
 
  FILE * infile;
 unsigned char* buf;
  JSAMPARRAY buffer;
  int row_len; 

  int width, height;
  int count=0;



  if ((infile = fopen(filename, "rb")) == NULL) {
    fprintf(stderr, "NOT SUCH FILE %s\n", filename);
    return 0;

  cinfo.err = jpeg_std_error(&jerr.pub);

  jerr.pub.error_exit = _error_exit;

 
  if (setjmp(jerr.setjmp_buffer)) {
    
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    return 0;
  }
 
  jpeg_create_decompress(&cinfo);

  jpeg_stdio_src(&cinfo, infile);

  (void) jpeg_read_header(&cinfo, TRUE);
  

  (void) jpeg_start_decompress(&cinfo);

  height=cinfo.output_height;

  width=cinfo.output_width;

   row_len = width * cinfo.output_components;

  if((buf=(unsigned char*)malloc(sizeof(unsigned char)*height*row_len))==NULL){ printf("FACK\n"); fclose(infile); return -1; };

   buffer = (*cinfo.mem->alloc_sarray)
                ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_len, 1);

  while (cinfo.output_scanline < cinfo.output_height) {
  
 ( void) jpeg_read_scanlines(&cinfo, buffer, 1);

  memcpy(&buf[count], &buffer[0], row_len);

   count+=row_len;
  
   };

  (void) jpeg_finish_decompress(&cinfo);

  jpeg_destroy_decompress(&cinfo);

 fclose(infile);
  
  *extbuf=buf;
  
  return 0;

};


Но и это не всё. Для воспроизводства изображения с Xlib,
мне понадобилось к количеству компоннетов в пикселе- cinfo.output_components, добавлять
четвёртый и инициализировать его 0xff. И переворачивать весь массив так, что первый char компонент из
каждой последовательной тройки ставился на третье место, третий на первое, иначе изображение получалось
в формате BGR, а не RGB, который ожидали функции Xlib-а.
Re[5]: Считать картинку в массив char*
От: Vzhyk  
Дата: 16.02.14 10:00
Оценка:
2/16/2014 12:57 AM, Ops пишет:

> V>http://www.cplusplus.com/

> Не надо это советовать, там ересь встречается.
Не, форум и писатели здесь восхитительны.
Posted via RSDN NNTP Server 2.1 beta
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.