Как сохранить и получить UIImages, используя «imageWithData», поддерживая правильный формат изображения? - PullRequest
0 голосов
/ 12 декабря 2018

Я работаю над созданием и хранением 3D-моделей OpenGL ES1 и хочу включить файлы изображений для использования в качестве текстур в тот же файл, что и данные 3D-модели.У меня проблемы с загрузкой данных изображения в удобном формате.Я использую UIImageJPEGRepresentation, чтобы преобразовать данные изображения и сохранить их в NSData.Затем я добавляю его к объекту NSMutableData вместе со всеми трехмерными данными и записываю в файл.Кажется, что данные пишутся и читаются без ошибок, но у меня возникают проблемы при попытке использовать данные изображения для создания «CGImageRef», который я использую для генерации данных текстуры для 3D-модели.Данные изображения, похоже, находятся в нераспознанном формате после загрузки из файла, поскольку при попытке создать «CGImageRef» возникает ошибка «CGContextDrawImage: неверный контекст 0x0.» Я подозреваю, что данные изображения получаются смещеннымикаким-то образом, вызывая его отклонение при попытке создать «CGImageRef». Я ценю любую помощь. Я в этом тупике. Все размеры данных и смещения складываются и выглядят нормально. Сохранения и загрузки происходят без ошибок.данные изображения кажутся немного ненадежными, но я не знаю почему.

Вот мой код:

//======================================================
- (BOOL)save3DFile: (NSString *)filePath {


  // load TEST IMAGE into UIIMAGE
  UIImage *image = [UIImage imageNamed:@“testImage.jpg"];

  // convert image to JPEG encoded NSDATA
  NSData *imageData = UIImageJPEGRepresentation(image,1.0);

  // Save length of imageData to global "imDataLen" to use later in “load3DFile”
  imDataLen = [imageData length];

  // TEST: this works fine for CGImageRef creation in “loadTexture” 
  // traceView.image=[UIImage imageWithData:[imageData subdataWithRange:NSMakeRange(0, imageDataLen)]];  
  // [self loadTexture];

  // TEST: this also works fine for CGImageRef creation in “loadTexture” 
  // traceView.image=[UIImage imageWithData:txImData];
  // [self loadTexture];

  fvoh.fileVersion  = FVO_VERSION;
  fvoh.obVertDatLen = obVertDatLen;
  fvoh.obFaceDatLen = obFaceDatLen;
  fvoh.obNormDatLen = obNormDatLen;
  fvoh.obTextDatLen = obTextDatLen;
  fvoh.obCompCount  = obCompCount;
  fvoh.obVertCount  = obVertCount;
  fvoh.obElemCount  = obElemCount;
  fvoh.obElemSize   = obElemSize;
  fvoh.obElemType   = obElemType;

  NSMutableData *obSvData;
  obSvData=[NSMutableData dataWithBytes:&fvoh length:(sizeof(fvoh))];
  [obSvData appendBytes:obElem   length:obFaceDatLen];
  [obSvData appendBytes:mvElem   length:obVertDatLen];
  [obSvData appendBytes:mvNorm   length:obNormDatLen];
  [obSvData appendBytes:obText   length:obTextDatLen];
  [obSvData appendBytes:&ds      length:(sizeof(ds))];

  // next, we append image data, and write all data to a file
  // seems to work fine, no errors, at this point
  [obSvData appendBytes: imageData length:[imageData length]];  

  BOOL success=[obSvData writeToFile: filePath atomically:YES];
  return success; 
}
//======================================================
- (void) load3DFile:(NSString *)filePath {

  NSData *fvoData;
  NSUInteger offSet,fiLen,fhLen,dsLen;
  [[FileList sharedFileList] setCurrFile:(NSString *)filePath];

  fvoData=[NSData dataWithContentsOfFile:filePath];
  fiLen=[fvoData length];
  fhLen=sizeof(fvoh);
  dsLen=sizeof(ds);

  memcpy(&fvoh,[fvoData bytes],fhLen);offSet=fhLen;

  //+++++++++++++++++++++++++++++++
  obVertDatLen = fvoh.obVertDatLen;
  obFaceDatLen = fvoh.obFaceDatLen;
  obNormDatLen = fvoh.obNormDatLen;
  obTextDatLen = fvoh.obTextDatLen;
  obCompCount  = fvoh.obCompCount;
  obVertCount  = fvoh.obVertCount;
  obElemCount  = fvoh.obElemCount;
  obElemSize   = fvoh.obElemSize;
  obElemType   = fvoh.obElemType;
  //+++++++++++++++++++++++++++++++

  memcpy(obElem, [fvoData bytes]+offSet,obFaceDatLen);offSet+=obFaceDatLen;
  memcpy(mvElem, [fvoData bytes]+offSet,obVertDatLen);offSet+=obVertDatLen;
  memcpy(mvNorm, [fvoData bytes]+offSet,obNormDatLen);offSet+=obNormDatLen;
  memcpy(obText, [fvoData bytes]+offSet,obTextDatLen);offSet+=obTextDatLen;
  memcpy(&ds,    [fvoData bytes]+offSet,dsLen);offSet+=dsLen;

  // the following seem to read the data into “imageData” just fine, no errors
  // NSData *imageData = [fvoData subdataWithRange:NSMakeRange(offSet, imDataLen)];
  // NSData *imageData = [fvoData subdataWithRange:NSMakeRange((fiLen-imDataLen), imDataLen)];
  // NSData *imageData = [NSData dataWithBytes:[fvoData bytes]+offSet length: imDataLen];
  NSData *imageData = [NSData dataWithBytes:[fvoData bytes]+(fiLen-imDataLen) length: imDataLen];

  // but the contents of imageData seem to end up in an unexpected format, causing error: 
  // “CGContextDrawImage: invalid context 0x0.” during CGImageRef creation in “loadTexture”

  traceView.image=[UIImage imageWithData:imageData];
  [self loadTexture];
}
//======================================================
- (void)loadTexture {

  CGImageRef image=[traceView.image].CGImage;
  CGContextRef texContext;GLubyte* bytes=nil;GLsizei width,height;

  if(image){
      width=(GLsizei)CGImageGetWidth(image);
      height=(GLsizei)CGImageGetHeight(image);
      bytes=(GLubyte*) calloc(width*height*4,sizeof(GLubyte));
      texContext=CGBitmapContextCreate(bytes,width,height,8,width*4,CGImageGetColorSpace(image),
      kCGImageAlphaPremultipliedLast);
      CGContextDrawImage(texContext,CGRectMake(0.0,0.0,(CGFloat)width,(CGFloat)height),image);
      CGContextRelease(texContext);
  }

  if(bytes){
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
      glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,bytes);
      free(bytes);
  }
}
//======================================================

1 Ответ

0 голосов
/ 19 декабря 2018

Мне не удалось получить ответы на этот вопрос.Я наконец наткнулся на ответ сам.Когда я выполняю код save3DFile, вместо добавления данных изображения в NSMutableData * obSvData, используя 'appendBytes', как показано ниже:

[obSvData appendBytes: imageData length:[imageData length]];

Я вместо этого использую 'appendData', как показано здесь:

[obSvData appendData: imageData];

, где imageData ранее был заполнен содержимым UIImage и преобразован в формат JPEG следующим образом:

NSData *imageData = UIImageJPEGRepresentation(image,1.0);

См. Полный список кода выше для контекста.В любом случае, использование 'appendData' вместо 'appendBytes' полностью изменило ситуацию и позволило мне сохранить данные изображения в том же файле вместе со всеми другими данными 3D-модели (вершины, индексы, нормали и т. Д.), Перезагрузив всеэти данные без проблем, и успешно создавать 3D-модели с текстурами из одного файла.

...