From: Jean Privat Date: Wed, 22 Apr 2015 06:46:03 +0000 (+0700) Subject: Merge: Small clean up and improvements to MNit from WBTW X-Git-Tag: v0.7.4~10 X-Git-Url: http://nitlanguage.org?hp=d6f787716470460c5cd3db30734bbe48a55a9ded Merge: Small clean up and improvements to MNit from WBTW The new OpenGL parameters affect the display of images for a better pixelated look: * When zoomed out, the image is smoother, the color values are interpolated from the nearest source pixels. * When zoomed in, the image is displayed pixelated. You may recognize the `Int::next_pow` method, `inkscape_tools` use something similar for the same purpose. Actually, with this PR, `inkscape_tools` may not need it anymore and produce smaller PNG files. Pull-Request: #1284 Reviewed-by: Jean Privat Reviewed-by: Romain Chanoir --- diff --git a/lib/mnit/opengles1.nit b/lib/mnit/opengles1.nit index eb1061b..b11d8dd 100644 --- a/lib/mnit/opengles1.nit +++ b/lib/mnit/opengles1.nit @@ -55,17 +55,12 @@ in "C header" `{ GLenum mnit_opengles_error_code; - struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha ); + struct mnit_opengles_Texture *mnit_opengles_load_image( + const uint_least32_t *pixels, int width, int height, + int width_pow2, int height_pow2, int has_alpha); `} in "C" `{ - #define LOGW(...) ((void)fprintf(stderr, "# warn: %s (%i)\n", __VA_ARGS__)) - #ifdef DEBUG - #define LOGI(...) ((void)fprintf(stderr, "# info: %s (%i)\n", __VA_ARGS__)) - #else - #define LOGI(...) (void)0 - #endif - extern NativeWindowType mnit_window; extern EGLNativeDisplayType mnit_native_display; @@ -86,7 +81,9 @@ in "C" `{ {1.0f, 0.0f} }; - struct mnit_opengles_Texture *mnit_opengles_load_image( const uint_least32_t *pixels, int width, int height, int has_alpha ) + struct mnit_opengles_Texture *mnit_opengles_load_image( + const uint_least32_t *pixels, int width, int height, + int width_pow2, int height_pow2, int has_alpha) { struct mnit_opengles_Texture *image = malloc(sizeof(struct mnit_opengles_Texture)); int format = has_alpha? GL_RGBA: GL_RGB; @@ -100,36 +97,37 @@ in "C" `{ image->src_xo = 0; image->src_yo = 0; - image->src_xi = 1.0; - image->src_yi = 1.0; + image->src_xi = ((float)width)/width_pow2; + image->src_yi = ((float)height)/height_pow2; if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error loading image after malloc", mnit_opengles_error_code); + PRINT_ERROR("error loading image after malloc: %i", mnit_opengles_error_code); } glGenTextures(1, &image->texture); if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error loading image after glGenTextures", mnit_opengles_error_code); + PRINT_ERROR("error loading image after glGenTextures: %i", mnit_opengles_error_code); } glBindTexture(GL_TEXTURE_2D, image->texture); if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error loading image glBindTexture", mnit_opengles_error_code); + PRINT_ERROR("error loading image glBindTexture: %i", mnit_opengles_error_code); } - glTexImage2D( GL_TEXTURE_2D, 0, format, width, height, + glTexImage2D( GL_TEXTURE_2D, 0, format, width_pow2, height_pow2, 0, format, GL_UNSIGNED_BYTE, (GLvoid*)pixels); if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error loading image after glTexImage2D", mnit_opengles_error_code); + PRINT_ERROR("error loading image after glTexImage2D: %i", mnit_opengles_error_code); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error loading image after gtTexParameter", mnit_opengles_error_code); + PRINT_ERROR("error loading image after gtTexParameter: %i", mnit_opengles_error_code); } return image; @@ -162,27 +160,27 @@ class Opengles1Display EGLDisplay display = eglGetDisplay(mnit_native_display); if ( display == EGL_NO_DISPLAY) { - LOGW("Unable to eglGetDisplay", 0); + PRINT_ERROR("Unable to eglGetDisplay"); return -1; } if ( eglInitialize(display, 0, 0) == EGL_FALSE) { - LOGW("Unable to eglInitialize", 0); + PRINT_ERROR("Unable to eglInitialize"); return -1; } if ( eglChooseConfig(display, attribs, &config, 1, &numConfigs) == EGL_FALSE) { - LOGW("Unable to eglChooseConfig", 0); + PRINT_ERROR("Unable to eglChooseConfig"); return -1; } if ( numConfigs == 0 ) { - LOGW("No configs available for egl", 0); + PRINT_ERROR("No configs available for egl"); return -1; } if ( eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format) == EGL_FALSE) { - LOGW("Unable to eglGetConfigAttrib", 0); + PRINT_ERROR("Unable to eglGetConfigAttrib"); return -1; } @@ -193,7 +191,7 @@ class Opengles1Display context = eglCreateContext(display, config, NULL, NULL); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { - LOGW("Unable to eglMakeCurrent", 0); + PRINT_ERROR("Unable to eglMakeCurrent"); return -1; } @@ -207,11 +205,6 @@ class Opengles1Display mnit_width = w; mnit_height = h; - LOGI("surface", (int)surface); - LOGI("display", (int)display); - LOGI("width", w); - LOGI("height", h); - glViewport(0, 0, mnit_width, mnit_height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -304,7 +297,7 @@ class Opengles1Display glDisable(GL_TEXTURE_2D); if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error drawing", mnit_opengles_error_code); + PRINT_ERROR("error drawing: %i", mnit_opengles_error_code); } `} @@ -354,7 +347,7 @@ class Opengles1Display glDisable(GL_TEXTURE_2D); if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error drawing", mnit_opengles_error_code); + PRINT_ERROR("error drawing: %i", mnit_opengles_error_code); } `} @@ -409,7 +402,7 @@ class Opengles1Display glDisable(GL_TEXTURE_2D); if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) { - LOGW("error drawing", mnit_opengles_error_code); + PRINT_ERROR("error drawing: %i", mnit_opengles_error_code); } `} @@ -466,10 +459,12 @@ extern class Opengles1Image in "C" `{struct mnit_opengles_Texture *`} image->scale = recv->scale; image->blended = recv->blended; - image->src_xo = ((float)x)/recv->width; - image->src_yo = ((float)y)/recv->height; - image->src_xi = ((float)x+w)/recv->width; - image->src_yi = ((float)y+h)/recv->height; + float r_dx = recv->src_xi - recv->src_xo; + float r_dy = recv->src_yi - recv->src_yo; + image->src_xo = recv->src_xo + ((float)x)/recv->width*r_dx; + image->src_yo = recv->src_yo + ((float)y)/recv->height*r_dy; + image->src_xi = recv->src_xo + ((float)x+w)/recv->width*r_dx; + image->src_yi = recv->src_yo + ((float)y+h)/recv->height*r_dy; return Opengles1Image_as_Image( image ); `} diff --git a/lib/mnit_android/android_assets.nit b/lib/mnit_android/android_assets.nit index 8f61c90..1720c57 100644 --- a/lib/mnit_android/android_assets.nit +++ b/lib/mnit_android/android_assets.nit @@ -86,7 +86,7 @@ redef class App var a = load_asset_from_apk(path) if a != null then if path.file_extension == "png" then - var png = new Opengles1Image.from_android_asset(a) + var png = new Opengles1Image.from_android_asset(a) a.close return png else if path.file_extension == "txt" then @@ -118,7 +118,7 @@ end redef class Opengles1Image # Read a png from a zipped stream - new from_android_asset(asset: AndroidAsset) is extern `{ + new from_android_asset(asset: AndroidAsset) import Int.next_pow `{ struct mnit_opengles_Texture *recv = NULL; png_structp png_ptr = NULL; @@ -133,13 +133,16 @@ redef class Opengles1Image unsigned char *pixels = NULL; unsigned int i; + png_uint_32 width_pow2, height_pow2; + unsigned int row_bytes_pow2; + unsigned char sig[8]; int sig_read = AAsset_read(asset, sig, 8); if (png_sig_cmp(sig, 0, sig_read)) { LOGW("invalide png signature"); return NULL; } - + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { LOGW("png_create_read_struct failed"); @@ -176,11 +179,16 @@ redef class Opengles1Image png_read_update_info(png_ptr, info_ptr); } - LOGW("w: %i, h: %i", width, height); + width_pow2 = Int_next_pow(width, 2); + height_pow2 = Int_next_pow(height, 2); + + LOGW("Loading image of w: %i, h: %i, w2: %d, h2: %d", + width, height, width_pow2, height_pow2); row_bytes = png_get_rowbytes(png_ptr, info_ptr); - pixels = malloc(row_bytes * height); - row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); + row_bytes_pow2 = row_bytes * width_pow2 / width; + pixels = malloc(row_bytes_pow2 * height_pow2); + row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height_pow2); for (i=0; ipixels, sdl_image->w, sdl_image->h, sdl_image->format->Amask ); + return mnit_opengles_load_image( sdl_image->pixels, + sdl_image->w, sdl_image->h, + sdl_image->w, sdl_image->h, sdl_image->format->Amask ); `} # using sdl @@ -91,7 +93,9 @@ redef extern class Opengles1Image fprintf(stderr, "SDL failed to load image <%s>: %s\n", String_to_cstring(path), IMG_GetError()); return NULL; } else { - opengles_image = mnit_opengles_load_image( sdl_image->pixels, sdl_image->w, sdl_image->h, sdl_image->format->Amask ); + opengles_image = mnit_opengles_load_image( sdl_image->pixels, + sdl_image->w, sdl_image->h, + sdl_image->w, sdl_image->h, sdl_image->format->Amask ); SDL_FreeSurface(sdl_image); return opengles_image; }