80,353
社区成员
发帖
与我相关
我的任务
分享
#include "png.h"unsigned char *load_png(FILE *file,int &width,int &height)
{
png_byte sig[8];
fread(sig,8,1,file);
if(!png_check_sig(sig,8))
{
fprintf(stderr,"load_png(): wrong signature\n");
return NULL;
}
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
if(!png_ptr)
return NULL;
png_infop info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr)
{
png_destroy_read_struct(&png_ptr,0,0);
return NULL;
}
png_init_io(png_ptr,file);
png_set_sig_bytes(png_ptr,8);
png_read_info(png_ptr,info_ptr);
unsigned long w,h;
int bit_depth,color_type;
png_get_IHDR(png_ptr,info_ptr,&w,&h,&bit_depth,&color_type,0,0,0);
if(bit_depth == 16)
png_set_strip_16(png_ptr);
if(color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
if(bit_depth < 8)
png_set_expand(png_ptr);
if(png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS))
png_set_expand(png_ptr);
if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);
double gamma;
if(png_get_gAMA(png_ptr,info_ptr,&gamma))
png_set_gamma(png_ptr,(double)2.2,gamma);
png_read_update_info(png_ptr,info_ptr);
png_get_IHDR(png_ptr,info_ptr,&w,&h,&bit_depth,&color_type,0,0,0);
png_uint_32 row_bytes = png_get_rowbytes(png_ptr,info_ptr);
png_uint_32 channels = png_get_channels(png_ptr,info_ptr);
png_byte *img = new png_byte[row_bytes * h];
png_byte **row = new png_byte*[h];
for(int i = 0; i < (int)h; i++)
row[i] = img + row_bytes * i;
png_read_image(png_ptr,row);
png_read_end(png_ptr,NULL);
png_destroy_read_struct(&png_ptr,0,0);
delete row;
width = w;
height = h;
unsigned char *data = new unsigned char[width * height * 4];
unsigned char *ptr = data;
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
int k = row_bytes * i + j * channels;
*ptr++ = img[k + 0];
*ptr++ = img[k + 1];
*ptr++ = img[k + 2];
if(channels == 4)
*ptr++ = img[k + 3];
else *ptr++ = 255;
}
}
delete img;
return data;
}
#include "png.h"unsigned char *load_png(FILE *file,int &width,int &height) { png_byte sig[8]; fread(sig,8,1,file); if(!png_check_sig(sig,8)) { fprintf(stderr,"load_png(): wrong signature\n"); return NULL; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); if(!png_ptr) return NULL; png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); return NULL; } png_init_io(png_ptr,file); png_set_sig_bytes(png_ptr,8); png_read_info(png_ptr,info_ptr); unsigned long w,h; int bit_depth,color_type; png_get_IHDR(png_ptr,info_ptr,&w,&h,&bit_depth,&color_type,0,0,0); if(bit_depth == 16) png_set_strip_16(png_ptr); if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if(bit_depth < 8) png_set_expand(png_ptr); if(png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) png_set_expand(png_ptr); if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); double gamma; if(png_get_gAMA(png_ptr,info_ptr,&gamma)) png_set_gamma(png_ptr,(double)2.2,gamma); png_read_update_info(png_ptr,info_ptr); png_get_IHDR(png_ptr,info_ptr,&w,&h,&bit_depth,&color_type,0,0,0); png_uint_32 row_bytes = png_get_rowbytes(png_ptr,info_ptr); png_uint_32 channels = png_get_channels(png_ptr,info_ptr); png_byte *img = new png_byte[row_bytes * h]; png_byte **row = new png_byte*[h]; for(int i = 0; i < (int)h; i++) row[i] = img + row_bytes * i; png_read_image(png_ptr,row); png_read_end(png_ptr,NULL); png_destroy_read_struct(&png_ptr,0,0); delete row; width = w; height = h; unsigned char *data = new unsigned char[width * height * 4]; unsigned char *ptr = data; for(int i = 0; i < height; i++) { for(int j = 0; j < width; j++) { int k = row_bytes * i + j * channels; *ptr++ = img[k + 0]; *ptr++ = img[k + 1]; *ptr++ = img[k + 2]; if(channels == 4) *ptr++ = img[k + 3]; else *ptr++ = 255; } } delete img; return data;}
Previously, I first extra my texture files to /data and then load them from native c++ code. But it's not a good way cause that is a waste to user's space. We can load file directly from APK file.
APK is some like a ZIP file. So we need libzip to help us reading resources from the APK file.
Luckily, I found someone from anddev had packed libzip and libpng for android NDK, you can download it from here.
We need to add libpng and libzip to Application.mk:
APP_ABI := armeabi armeabi-v7a
APP_PROJECT_PATH := $(call my-dir)/project
APP_MODULES := libpng libzip YOU_PROJECT_NAME
Add these to Android.mk
LOCAL_LDLIBS+=-L$(SYSROOT)/usr/lib -ldl
LOCAL_LDLIBS+=-L$(SYSROOT)/usr/lib -lz
Here is a snippet for loading apk file, if it works, it will list all files contained in the apk.
static void loadAPK (const char* apkPath) {
LOGI("Loading APK %s", apkPath);
APKArchive = zip_open(apkPath, 0, NULL);
if (APKArchive == NULL) {
LOGE("Error loading APK");
return;
}
//Just for debug, print APK contents
int numFiles = zip_get_num_files(APKArchive);
for (int i=0; i<numFiles; i++) {
const char* name = zip_get_name(APKArchive, i, 0);
if (name == NULL) {
LOGE("Error reading zip file name at index %i : %s", zip_strerror(APKArchive));
return;
}
LOGI("File %i : %s\n", i, name);
}
}
复制代码
There is something to say about apkPath, it is where your apk is. You can generate it in Java and pass it to native code.
String apkFilePath = null;
ApplicationInfo appInfo = null;
PackageManager packMgmr = this.getPackageManager();
try {
appInfo = packMgmr.getApplicationInfo("com.yourpackage", 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Unable to locate assets, aborting...");
}
apkFilePath = appInfo.sourceDir;
jni.init(apkFilePath);//pass it to NDK
复制代码
Now it's time to load PNGs!
int TexMng::LoadPNG(char* filename,bool _alpha)
{
LOGI("Loading %s",filename);
for(int i=0;i<nTex;++i)
{
if(strcmp(tex_name[i],filename)==0)
{
LOGI("Already Loaded");
return -1;
}
}
if(nTex>=MAX_TEXS)
{
LOGI("Too many textures!");
return -1;
}
file = zip_fopen(APKArchive, filename, 0);
if (!file) {
LOGE("Error opening %s from APK", filename);
return TEXTURE_LOAD_ERROR;
}
//header for testing if it is a png
png_byte header[8];
//read the header
zip_fread(file, header, 8);
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png) {
zip_fclose(file);
LOGE("Not a png file : %s", filename);
return TEXTURE_LOAD_ERROR;
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL);
if (!png_ptr) {
zip_fclose(file);
LOGE("Unable to create png struct : %s", filename);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
LOGE("Unable to create png info : %s", filename);
zip_fclose(file);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
LOGE("Unable to create png end info : %s", filename);
zip_fclose(file);
return (TEXTURE_LOAD_ERROR);
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr))) {
zip_fclose(file);
LOGE("Error during setjmp : %s", filename);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
return (TEXTURE_LOAD_ERROR);
}
//init png reading
//png_init_io(png_ptr, fp);
png_set_read_fn(png_ptr, NULL, png_zip_read);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
// read all the info up to the image data
png_read_info(png_ptr, info_ptr);
//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;
// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
NULL, NULL, NULL);
//update width and height based on png info
tex_w[nTex] = twidth;
tex_h[nTex] = theight;
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Row size in bytes.
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = new png_byte[rowbytes * theight];
if (!image_data) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
LOGE("Unable to allocate image_data while loading %s ", filename);
zip_fclose(file);
return TEXTURE_LOAD_ERROR;
}
//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = new png_bytep[theight];
if (!row_pointers) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
LOGE("Unable to allocate row_pointer while loading %s ", filename);
zip_fclose(file);
return TEXTURE_LOAD_ERROR;
}
// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < theight; ++i)
row_pointers[theight - 1 - i] = image_data + i * rowbytes;
//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);
alpha[nTex]=_alpha;
pixels[nTex]=image_data;
strcpy(tex_name[nTex],filename);
++nTex;
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
//delete[] image_data;
delete[] row_pointers;
zip_fclose(file);
return nTex;
}
复制代码
本文转自:http://androgeek.info/?p=275
$ $NDK/ndk-build
undefined reference to `png_set_longjmp_fn'
/cygdrive/e/DirectX/Android_NDK_JNI/android-ndk-r4b-windows/android-ndk-r4b/build/platforms/android-8/arch-arm/usr/lib/libpng.so
(pngerror.o): In function `png_warning':
pngerror.c:(.text+0x230): undefined reference to `stderr'
(pngerror.o): In function `png_error':
pngerror.c:(.text+0x42c): undefined reference to `stderr'
(pngrutil.o): In function `png_handle_sRGB':
pngrutil.c:(.text+0x32c0): undefined reference to `stderr'
(pngrutil.o): In function `png_handle_cHRM':
pngrutil.c:(.text+0x38cc): undefined reference to `stderr'
(pngrutil.o): In function `png_handle_gAMA':
pngrutil.c:(.text+0x3c14): undefined reference to `stderr'
collect2: ld returned 1 exit status
手上有好些,前一阶段的工作成果.一直没有时间整理出来.
先把cola2d 里面使用的一些基础整理下.
在ndk 下如何读取png到opengl es 的texture了?
其实做法和linux下面没什么区别,我们首先要用到libpng这个开源的库.
从 http://www.libpng.org/pub/png/libpng.html 下载到 libpng-1.2.41这个版本.
然后在android ndk 新建一个libpng的project .
我的android.mk 文件如下.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := png
LOCAL_CFLAGS := -I$(LOCAL_PATH) \
-DPNG_USE_GLOBAL_ARRAYS \
-DPNG_READ_SUPPORTED
LOCAL_CPP_EXTENSION := .cpp
# Note this simple makefile var substitution, you can find even simpler examples in different Android projects
LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.c))
include $(BUILD_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := png
LOCAL_CFLAGS := -I$(LOCAL_PATH) \
-DPNG_USE_GLOBAL_ARRAYS \
-DPNG_READ_SUPPORTED
LOCAL_CPP_EXTENSION := .cpp
# Note this simple makefile var substitution, you can find even simpler examples in different Android projects
LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.c))
include $(BUILD_STATIC_LIBRARY)
这样就可以编译好libpng.a
需要注意的是 如果使用该库,链接时,需要加上-lz 这儿需要带上zlib库 这个库,android ndk 已经自带了.不需要自行编译.
opengl es 如何使用该库读取一个png图片了?
读取png 代码:
unsigned char* Texture::ReadPNG (const char* file, png_uint_32* w, png_uint_32* h)
{
FILE* f;
unsigned char sig[8];
png_structp png_ptr;
png_infop info_ptr;
unsigned char* image_data;
int bit_depth;
int color_type;
unsigned int rowbytes;
png_uint_32 i;
png_bytepp row_pointers;
if ((f = fopen(file, "rb")) == NULL)
return NULL;
fread(sig, sizeof(*sig), sizeof(sig), f);
if (!png_check_sig(sig, sizeof(*sig))) {
fclose(f);
return NULL;
}
if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) {
fclose(f);
return NULL;
}
if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
fclose(f);
return NULL;
}
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return NULL;
}
png_ptr->io_ptr = (png_voidp) f;
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, w, h, &bit_depth, &color_type, NULL, NULL, NULL);
if (color_type & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(png_ptr);
if (bit_depth > <IMG class=wp-smiley alt=8) src="http://www.adevgames.com/wordpress/wp-includes/images/smilies/icon_cool.gif">
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
png_read_update_info(png_ptr, info_ptr);
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
if ((image_data =(unsigned char *) malloc(*h * rowbytes)) == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return NULL;
}
if ((row_pointers =(png_bytepp) malloc(*h * sizeof(png_bytep))) == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
free(image_data);
return NULL;
}
for (i = 0; i < *h; i++)
row_pointers[*h - 1 - i] = image_data + i*rowbytes;
png_read_image(png_ptr, row_pointers);
free(row_pointers);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return image_data;
}
unsigned char* Texture::ReadPNG (const char* file, png_uint_32* w, png_uint_32* h)
{
FILE* f;
unsigned char sig[8];
png_structp png_ptr;
png_infop info_ptr;
unsigned char* image_data;
int bit_depth;
int color_type;
unsigned int rowbytes;
png_uint_32 i;
png_bytepp row_pointers;
if ((f = fopen(file, "rb")) == NULL)
return NULL;
fread(sig, sizeof(*sig), sizeof(sig), f);
if (!png_check_sig(sig, sizeof(*sig))) {
fclose(f);
return NULL;
}
if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) {
fclose(f);
return NULL;
}
if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
fclose(f);
return NULL;
}
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return NULL;
}
png_ptr->io_ptr = (png_voidp) f;
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, w, h, &bit_depth, &color_type, NULL, NULL, NULL);
if (color_type & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(png_ptr);
if (bit_depth >
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
png_read_update_info(png_ptr, info_ptr);
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
if ((image_data =(unsigned char *) malloc(*h * rowbytes)) == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return NULL;
}
if ((row_pointers =(png_bytepp) malloc(*h * sizeof(png_bytep))) == NULL) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
free(image_data);
return NULL;
}
for (i = 0; i < *h; i++)
row_pointers[*h - 1 - i] = image_data + i*rowbytes;
png_read_image(png_ptr, row_pointers);
free(row_pointers);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(f);
return image_data;
}然后使用
下面方法即可读入到texture里面
m_width=imgw;
m_height=imgh;
glGenTextures(1, &m_id);
glBindTexture(GL_TEXTURE_2D, m_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgw, imgh, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
GLint crop[4] = { 0, 0, m_width, m_height };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
m_width=imgw;
m_height=imgh;
glGenTextures(1, &m_id);
glBindTexture(GL_TEXTURE_2D, m_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgw, imgh, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
GLint crop[4] = { 0, 0, m_width, m_height };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
这部分内容和普通opengl es 的开发都没有区别.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/untosil/archive/2010/07/16/5739002.aspx
OpenGL ES
Android support for OpenGL ES, a subset of OpenGL, is exposed both in Java and native API. 2009FLY文摘,正正博客 WWW.2009FLY.COM
All android devices supports version OpenGL ES version 1.0, though some may use a software renderer. Applications which requires (as opposed to may optionally use features from through runtime checks) a higher version must specify so in their AndroidManifest.xml file with the android:glEsVersion attribute on the <uses-feature/> tag, as a 32-bit number with the higher and lower 16 bits representing the major and minor OpenGL version number:
数据技术 Oracle、DBMaker、DB2 2009FLY文摘,正正博客 WWW.2009FLY.COM
<-- require OpenGL ES version 1.0 (default) -->
<uses-feature android:glEsVersion="0x00010000"/>
<-- require OpenGL ES version 1.1 -->
<uses-feature android:glEsVersion="0x00010001"/>
<-- require OpenGL ES version 2.0 -->
<uses-feature android:glEsVersion="0x00020000"/>
网络安全 2009FLY文摘,正正博客 WWW.2009FLY.COM Note that the Android emulator does not support OpenGL ES version 2.x - a physical device is required for testing applications using that version. 网络安全 2009FLY文摘,正正博客 WWW.2009FLY.COM