NativeActivityでのlibpngを使った画像表示

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
ひよこ
記事: 25
登録日時: 13年前

NativeActivityでのlibpngを使った画像表示

#1

投稿記事 by ひよこ » 10年前

おひさしぶりです、ひよこです。最近NDKを勉強してます。
NativeActivityでのlibpngを使った画像表示なのですが、
Android NDKのNativeActivityに
http://d.hatena.ne.jp/hecomi/20130226/1361886948
を参考に組み込んでいたのですが
エラーが出て進めません。C++の標準ライブラリ?が読めてない感じなのですがどうすればいいでしょうか?

環境はeclipse adt-bundle-windows-x86-20130522、NDK android-ndk-r8e

プロジェクトをコピーしたのを圧縮したのを添付します。
よろしくお願いします。

エラー
説明 リソース パス ロケーション 型
Symbol 'height_' could not be resolved image.cpp /NativeActivity/jni 行 12 Semantic Error
Symbol 'width_' could not be resolved image.cpp /NativeActivity/jni 行 12 Semantic Error
Symbol 'color_type_' could not be resolved image.cpp /NativeActivity/jni 行 13 Semantic Error
Symbol 'bit_depth_' could not be resolved image.cpp /NativeActivity/jni 行 13 Semantic Error
Type 'std::string' could not be resolved image.cpp /NativeActivity/jni 行 10 Semantic Error
Member declaration not found image.cpp /NativeActivity/jni 行 10 Semantic Error
Symbol 'data_' could not be resolved image.cpp /NativeActivity/jni 行 11 Semantic Error
Symbol 'file_name_' could not be resolved image.cpp /NativeActivity/jni 行 11 Semantic Error
Symbol 'std' could not be resolved main.cpp /NativeActivity/jni 行 18 Semantic Error
Method 'c_str' could not be resolved image.cpp /NativeActivity/jni 行 18 Semantic Error
Method 'c_str' could not be resolved image.cpp /NativeActivity/jni 行 16 Semantic Error
Invalid arguments '
Candidates are:
void glGetShaderInfoLog(unsigned int, int, int *, char *)
' main.cpp /NativeActivity/jni 行 75 Semantic Error
Type 'std::string' could not be resolved main.cpp /NativeActivity/jni 行 74 Semantic Error
Type 'std::string' could not be resolved main.cpp /NativeActivity/jni 行 102 Semantic Error
Type 'std::string' could not be resolved image.h /NativeActivity/jni 行 15 Semantic Error
Symbol 'compression_type_' could not be resolved image.cpp /NativeActivity/jni 行 14 Semantic Error
Type 'std::string' could not be resolved image.h /NativeActivity/jni 行 7 Semantic Error
Symbol 'interlace_type_' could not be resolved image.cpp /NativeActivity/jni 行 13 Semantic Error
Method 'c_str' could not be resolved main.cpp /NativeActivity/jni 行 76 Semantic Error
Method 'c_str' could not be resolved main.cpp /NativeActivity/jni 行 104 Semantic Error
Symbol 'filter_method_' could not be resolved image.cpp /NativeActivity/jni 行 14 Semantic Error
Invalid arguments '
Candidates are:
void glGetProgramInfoLog(unsigned int, int, int *, char *)
' main.cpp /NativeActivity/jni 行 103 Semantic Error
Invalid arguments '
Candidates are:
__sFILE * fopen(const char *, const char *)
' image.cpp /NativeActivity/jni 行 16 Semantic Error

コード:

#include <string>

#include <EGL/egl.h>
#include <GLES/gl.h>
#include <GLES2/gl2.h>

#include <android/log.h>
#include <android_native_app_glue.h>

#include <image.h>

#define LOG_TAG ("gles2ndtest")
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,  LOG_TAG, __VA_ARGS__))
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,  LOG_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))

using namespace std;

struct engine
{
	android_app* app;
	EGLDisplay display;
	EGLSurface surface;
	EGLContext context;
};

const char* vertex_shader =
	"attribute vec4 position;\n"
	"attribute vec2 texcoord;\n"
	"varying vec2 texcoordVarying;\n"
	"void main() {\n"
		"gl_Position = position;\n"
		"texcoordVarying = texcoord;\n"
	"}\n";

const char* fragment_shader =
	"precision mediump float;\n"
	"varying vec2 texcoordVarying;\n"
	"uniform sampler2D texture;\n"
	"void main() {\n"
		"gl_FragColor = texture2D(texture, texcoordVarying);\n"
	"}\n";

const float vertices[] = {
	-1.0f,  1.0f, 0.0f,
	-1.0f, -1.0f, 0.0f,
	 1.0f,  1.0f, 0.0f,
	 1.0f, -1.0f, 0.0f
};

const float texcoords[] = {
	0.0f, 0.0f,
	0.0f, 1.0f,
	1.0f, 0.0f,
	1.0f, 1.0f
};

GLuint program, position, texcoord;
GLuint textures[1];

GLuint load_shader(GLenum shader_type, const char* source)
{
	GLuint shader = glCreateShader(shader_type);
	if (shader) {
		glShaderSource(shader, 1, &source, 0);
		glCompileShader(shader);
		GLint compiled = 0;
		glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
		if (!compiled) {
			GLint length = 0;
			glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
			if (length) {
				std::string log(static_cast<size_t>(length), ' ');
				glGetShaderInfoLog(shader, length, 0, &log[0]);
				LOGE("Could not compile shader %d:\n%s\n", shader_type, log.c_str());
				glDeleteShader(shader);
				shader = 0;
			}
		}
	}
	return shader;
}

GLuint create_program(const char* vertex_source, const char* fragment_source)
{
    GLuint vertex_shader = load_shader(GL_VERTEX_SHADER, vertex_source);
	if (vertex_shader == 0) return 0;
    GLuint pixel_shader  = load_shader(GL_FRAGMENT_SHADER, fragment_source);
	if (pixel_shader  == 0) return 0;

    GLuint program = glCreateProgram();
	glAttachShader(program, vertex_shader);
	glAttachShader(program, pixel_shader);
	glLinkProgram(program);
	GLint link_status = GL_FALSE;
	glGetProgramiv(program, GL_LINK_STATUS, &link_status);
	if (link_status != GL_TRUE) {
		GLint length = 0;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
		if (length) {
				std::string log(static_cast<size_t>(length), ' ');
			glGetProgramInfoLog(program, length, 0, &log[0]);
			LOGE("Could not link program:\n%s\n", log.c_str());
		}
		glDeleteProgram(program);
		program = 0;
	}
    return program;
}

void load_png()
{
    program = create_program(vertex_shader, fragment_shader);
	if (program == 0) return;
	glUseProgram(program);

	position = glGetAttribLocation(program, "position");
	glEnableVertexAttribArray(position);

	texcoord = glGetAttribLocation(program, "texcoord");
	glEnableVertexAttribArray(texcoord);

	textures[0] = glGetUniformLocation(program, "texture");
	glGenTextures(1, textures);
	glBindTexture(GL_TEXTURE_2D, textures[0]);

	PNG png("/sdcard/tmp/hoge.png");
	LOGD("Image: alpha:%d width:%dpx height%dpx",
			png.has_alpha(), png.get_width(), png.get_height());

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, png.has_alpha() ? GL_RGBA : GL_RGB,
			png.get_width(), png.get_height(),
			0, png.has_alpha() ? GL_RGBA : GL_RGB,
			GL_UNSIGNED_BYTE, png.get_data());
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

int init(engine* e)
{
	const EGLint attribs[] = {
		EGL_BLUE_SIZE,       8,
		EGL_GREEN_SIZE,      8,
		EGL_RED_SIZE,        8,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_NONE
	};
	const EGLint context_attribs[] = {
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};

	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	eglInitialize(display, 0, 0);

	EGLConfig config;
	EGLint num_configs;
	eglChooseConfig(display, attribs, &config, 1, &num_configs);

	EGLint format;
	eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
	ANativeWindow_setBuffersGeometry(e->app->window, 0, 0, format);

	EGLSurface surface = eglCreateWindowSurface(display, config, e->app->window, 0);
	EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribs);

	if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
		return -1;
	}

	EGLint w, h;
	eglQuerySurface(display, surface, EGL_WIDTH,  &w);
	eglQuerySurface(display, surface, EGL_HEIGHT, &h);

	e->display = display;
	e->surface = surface;
	e->context = context;

	glViewport(0, 0, w, h);
}

void draw(engine* e)
{
	glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	LOGD("glBindTexture");
	glBindTexture(GL_TEXTURE_2D, textures[0]);
	LOGD("glVertexAttribPointer");
    glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
	LOGD("glVertexAttribPointer");
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, vertices);
	LOGD("glDrawArra");
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	eglSwapBuffers(e->display, e->surface);
}

void android_main(android_app* state)
{
	app_dummy();

	engine e;
	state->userData = &e;
	state->onAppCmd = [](android_app* app, int32_t cmd) {
		auto e = static_cast<engine*>(app->userData);
		switch (cmd) {
			case APP_CMD_INIT_WINDOW:
				init(e);
				load_png();
				draw(e);
				break;
		}
	};
	e.app = state;

	while (1) {
		int ident, events;
		android_poll_source* source;
		while ((ident=ALooper_pollAll(0, 0, &events, (void**)&source)) >= 0) {
			if (source != 0) {
				source->process(state, source);
			}
			if (state->destroyRequested != 0) {
				if (e.display != EGL_NO_DISPLAY) {
					eglMakeCurrent(e.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
					if (e.context != EGL_NO_CONTEXT) {
						eglDestroyContext(e.display, e.context);
					}
					if (e.surface != EGL_NO_SURFACE) {
						eglDestroySurface(e.display, e.surface);
					}
					eglTerminate(e.display);
				}
				e.display = EGL_NO_DISPLAY;
				e.context = EGL_NO_CONTEXT;
				e.surface = EGL_NO_SURFACE;
				return;
			}
		}
	}
}
image.h

コード:

#include <string>
#include <png.h>

class PNG
{
public:
	PNG(const std::string& file_name);
	~PNG();
	unsigned int get_width();	// 画像の横幅を取得
	unsigned int get_height();	// 画像の縦幅を取得
	bool has_alpha();			// RGBA/RGB --> true/false
	unsigned char* get_data();			// 画像データ

private:
	const std::string file_name_;
	unsigned char* data_;
	png_uint_32 width_, height_;
	int bit_depth_, color_type_, interlace_type_;
	int compression_type_, filter_method_;
};
image.cpp

コード:

#include <image.h>
#include <android/log.h>

#define LOG_TAG ("PNG")
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,  LOG_TAG, __VA_ARGS__))
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,  LOG_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))

PNG::PNG(const std::string& file_name) :
	file_name_(file_name), data_(0),
	width_(0), height_(0),
	bit_depth_(0), color_type_(0), interlace_type_(0),
	compression_type_(0), filter_method_(0)
{
	FILE* fp = fopen(file_name_.c_str(), "rb");
	if (fp == 0) {
		LOGE("%s is not found.", file_name_.c_str());
		fclose(fp);
		return;
	}

	png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (png == 0) {
		LOGE("png_create_read_struct error.");
		fclose(fp);
		return;
	}

	png_infop info = png_create_info_struct(png);
	if (info == 0) {
		LOGE("png_create_info_struct error.");
		png_destroy_read_struct(&png, 0, 0);
		fclose(fp);
		return;
	}

	if (setjmp(png_jmpbuf(png))) {
		LOGE("png_jmpbuf error.");
		png_destroy_read_struct(&png, &info, 0);
		fclose(fp);
		return;
	}

	png_init_io(png, fp);

	unsigned int sig_bytes = 0;
	png_set_sig_bytes(png, sig_bytes);

	png_read_png(png, info, (PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND), 0);
	png_get_IHDR(png, info, &width_, &height_, &bit_depth_, &color_type_, &interlace_type_, &compression_type_, &filter_method_);

	unsigned int row_bytes = png_get_rowbytes(png, info);
	if (data_ != 0) {
		delete[] data_;
	}
	data_ = new unsigned char[row_bytes * height_];

	png_bytepp rows = png_get_rows(png, info);
	for (int i = 0; i < height_; ++i) {
		memcpy(data_ + (row_bytes * i), rows[i], row_bytes);
	}

	png_destroy_read_struct(&png, &info, 0);
}

PNG::~PNG()
{
	if (data_) delete[] data_;
}

unsigned int PNG::get_width()
{
	return width_;
}

unsigned int PNG::get_height()
{
	return height_;
}

unsigned char* PNG::get_data()
{
	return data_;
}

bool PNG::has_alpha()
{
	if (color_type_ == PNG_COLOR_TYPE_RGBA) {
		return true;
	}
	return false;
}
Android.mk

コード:

TOP_LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

#libpngのMakeFikeを読み込む
include $(TOP_LOCAL_PATH)/libpng/src/Android.mk

LOCAL_PATH := $(TOP_LOCAL_PATH)
include $(CLEAR_VARS)

LOCAL_MODULE     := native-activity
LOCAL_CFLAGS     := -std=c++11 #コンパイルオプション
LOCAL_SRC_FILES  := $(wildcard *.cpp) #ソースコードはcpp全部
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libpng/src/. #libpngのソースコード全部インクルード
LOCAL_LDLIBS     := -lz -llog -landroid -lEGL -lGLESv1_CM -lGLESv2
LOCAL_STATIC_LIBRARIES := android_native_app_glue libpng

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)
Application.mk

コード:

APP_PLATFORM := android-10
APP_OPTIM    := debug
APP_ABI      := armeabi armeabi-v7a
APP_STL      := gnustl_static
添付ファイル
NativeActivity.zip
プロジェクト
(1.51 MiB) ダウンロード数: 172 回

“C言語何でも質問掲示板” へ戻る