Понадобилось при порте генерить текстурку из 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.
Исходники можно на гитхабе качнуть.