Android NDK: использование libjpeg для создания текстур

Понадобилось при порте генерить текстурку из 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 1jError.error_exit = _JpegError; // register error handler 2jpeg_create_decompress(&cInfo); // create a decompresser// load from assetpAsset = 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 headerjpeg_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.

Исходники можно на гитхабе качнуть.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *