Понадобилось при порте генерить текстурку из jpeg файла. Решил поделиться самой либой, чтоб без проблем смогли её сбилдить в своём проекте, а так же небольшим примерчиком того, как считать пикчу из assets.
С самой либой особых проблем нету (с билдом). Но если кто не работал плотно с .mk файлами, то можете использовать готовое. Проблема именно со считыванием из файла и самим использованием библиотеки. Так как по умолчанию все стримы, как обычно, используют FILE, а у нас пикча лежит в assets. Поэтому делюсь методом, как прочитать картинку из assets папки с помощью AAssetManager’а.
static void _JpegError(j_common_ptr cInfo){ char pszMessage[JMSG_LENGTH_MAX]; (*cInfo->err->format_message)(cInfo, pszMessage); LOGE("Jpeg Lib","error! %s", pszMessage); } static uint32_t make8888(int red, int green, int blue, int alpha){ //LOGD("[%i;%i;%i]",red,green,blue); return (uint32_t)( ((alpha << 24) & 0xff000000) | ((blue << 16) & 0x00ff0000) | ((green << 8) & 0x0000ff00) | ( red & 0x000000ff) ); } GLuint loadTextureFromJPEG(const char* filename, int &width, int &height){ AAsset* pAsset = NULL; struct jpeg_decompress_struct cInfo; struct jpeg_error_mgr jError; cInfo.err = jpeg_std_error(&jError); // register error handler 1 jError.error_exit = _JpegError; // register error handler 2 jpeg_create_decompress(&cInfo); // create a decompresser // load from asset pAsset = AAssetManager_open(mgr, filename, AASSET_MODE_UNKNOWN); if (!pAsset) { LOGD("!pAsset"); return NULL; } unsigned char* ucharRawData = (unsigned char*)AAsset_getBuffer(pAsset); long myAssetLength = (long)AAsset_getLength(pAsset); // the jpeg_stdio_src alternative func, which is also included in IJG's lib. jpeg_mem_src(&cInfo, ucharRawData, myAssetLength); uint32_t* pTexUint; int yy; int pixelSize, lineSize; char* lpbtBits; JSAMPLE tmp; int rectHeight, rectWidth; jpeg_read_header(&cInfo, TRUE); // read header jpeg_start_decompress(&cInfo); // start decompression //LOGD("cInfo %i - %i",cInfo.output_width,cInfo.output_height); width = cInfo.output_width; height = height = cInfo.output_height; pixelSize = cInfo.output_components; lineSize = width * pixelSize; pTexUint = (uint32_t*)calloc(sizeof(uint32_t), width * height); if (pTexUint == NULL){ AAsset_close(pAsset); return NULL; } JSAMPLE* pSample = (JSAMPLE*)calloc(sizeof(JSAMPLE), lineSize + 10); if (!pSample){ LOGE("Jpeg Lib","cannot alloc pSample"); if (pTexUint) free(pTexUint); AAsset_close(pAsset); return NULL; //error } JSAMPROW buffer[1]; buffer[0] = pSample; uint32_t* pPixelsUint = pTexUint; yy = 0; while(cInfo.output_scanline < cInfo.output_height){ if(yy >= cInfo.output_height) break; jpeg_read_scanlines(&cInfo, buffer, 1); int xx; int x3; for(xx = 0, x3 = 0; xx < width; xx++, x3 += 3) pPixelsUint[xx] = make8888(buffer[0][x3], buffer[0][x3 + 1], buffer[0][x3 + 2], 0xff); pPixelsUint = (uint32_t*)pPixelsUint + width; yy++; } //LOGD("sizeof(*pPixelsUint) = %i", sizeof(*pPixelsUint)); GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pTexUint); jpeg_finish_decompress(&cInfo); jpeg_destroy_decompress(&cInfo); if (pSample) free(pSample); AAsset_close(pAsset); //free(pTexUint); return texture; //return (unsigned char*)pTexUint; }
В общем, метод считывает картинку и сразу генерирует текстурку. Можно потом сразу использовать в OpenGL.
Исходники можно на гитхабе качнуть.