Использование SDL_image и SDL_RWops с LibZip для загрузки png из zip на поверхность, но не распознает png - PullRequest
1 голос
/ 06 апреля 2020

Соответствующий код:

  zip_stat_t filestat;
  uint64_t filetotal = 0;
  SDL_RWops* rwop = SDL_AllocRW();

//bunch of code that's not relevant to the matter goes here

  std::vector<char> rwbuffer(filestat.size);
  rwop = SDL_RWFromMem(rwbuffer.data(), filestat.size);
  while(filetotal < filestat.size)
  {
    char buffer[256];
    int64_t length;
    //read the file into the buffer
    length = zip_fread(file, buffer, 256);
    if (length == -1)
    {
      u_error(std::cerr, CC_ERROR_ZIP, "zip_fread");
      zip_fclose(file);
      SDL_FreeRW(rwop);
      return false;
    }
    //write the buffer into the rwop stream
    if ( (uint16_t)length != SDL_RWwrite(rwop, buffer, 1, (size_t)length) )
    {
      u_error(std::cerr, CC_ERROR_SDL, "SDL_RWwrite");
      zip_fclose(file);
      SDL_FreeRW(rwop);
      return false;
    }
    //Increment the count so that the loop ends
    filetotal += length;
  }
  zip_fclose(file);
  //Put it onto a surface
  SDL_Surface* surf_load = IMG_Load_RW(rwop, 0);
  if(surf_load == NULL)
  {
    u_error(std::cerr, CC_ERROR_IMAGE, "IMG_Load_RW");
    SDL_FreeRW(rwop);
    u_cleanup(surf_load);
    return false;
  }

//...

Я выгрузил содержимое векторного rwbuffer с помощью отладчика, и это допустимый png, но IMG_Load_RW по-прежнему выдает ошибку «Неподдерживаемый формат изображения». У меня установлен libpng, и IMG_Init, кажется, работает нормально, поэтому библиотека SDL_image должна работать. Очевидно, что libzip дает мне правильные данные. Я очень смущен тем, почему я получаю ошибку.

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Я понял это. В конце моего while l oop для чтения данных значение поиска для потока RWops находится в конце файла, и IMG_LoadPNG_RW не сбрасывает его, поэтому мне нужно вручную SDL_RWseek (rwop, 0, RW_SEEK_SET ); через некоторое время l oop заканчивается для чтения данных png.

  //Return the seek pointer of the RWop to the beginning so that the file can be read
  SDL_RWseek(rwop,0,RW_SEEK_SET);
  //Put it onto a surface
  SDL_Surface* surf_load = IMG_Load_RW(rwop, 0);
  if(surf_load == NULL)
  {
    u_error(std::cerr, CC_ERROR_IMAGE, "IMG_Load_RW");
    SDL_FreeRW(rwop);
    u_cleanup(surf_load);
    return false;
  }
0 голосов
/ 06 апреля 2020

Если вы позвоните SDL_FreeRW(rwop); до IMG_Load_RW(rwop, 0);, то из памяти ничего не получите.

Если не проблема freeRW, используйте:

IMG_LoadPNG_RW instread IMG_Load_RW также IMG_isPNG может пригодиться для проверки.

По-другому, похоже, у вас ошибка с корреляцией версий между SDL и SDL_Image. Если вы используете SDL2, то также используйте SDL2_image lib.

ОБНОВЛЕНО

  zip_stat_t filestat;
  uint64_t filetotal = 0;
  SDL_RWops* rwop = SDL_AllocRW();

//bunch of code that's not relevant to the matter goes here

  std::vector<char> rwbuffer(filestat.size);
  rwop = SDL_RWFromMem(rwbuffer.data(), filestat.size);
  while(filetotal < filestat.size)
  {
    char buffer[256];
    int64_t length;
    //read the file into the buffer
    length = zip_fread(file, buffer, 256);
    if (length == -1)
    {
      u_error(std::cerr, CC_ERROR_ZIP, "zip_fread");
      zip_fclose(file);
      SDL_FreeRW(rwop);
      return false;
    }
    //write the buffer into the rwop stream
    if ( (uint16_t)length != SDL_RWwrite(rwop, buffer, 1, (size_t)length) )
    {
      u_error(std::cerr, CC_ERROR_SDL, "SDL_RWwrite");
      zip_fclose(file);
      SDL_FreeRW(rwop);
      return false;
    }
    //Increment the count so that the loop ends
    filetotal += length;
  }
  zip_fclose(file);
  //Put it onto a surface
  SDL_Surface* surf_load = IMG_LoadPNG_RW(rwop, 0);
  if(surf_load == NULL)
  {
    u_error(std::cerr, CC_ERROR_IMAGE, "IMG_Load_RW");
    SDL_FreeRW(rwop);
    u_cleanup(surf_load);
    return false;
  }
...