lib/mnit: expand images to the nearest power of 2 for OpenGL ES 1.0
authorAlexis Laferrière <alexis.laf@xymus.net>
Sun, 22 Feb 2015 17:55:49 +0000 (12:55 -0500)
committerAlexis Laferrière <alexis.laf@xymus.net>
Mon, 20 Apr 2015 17:00:09 +0000 (13:00 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

lib/mnit/opengles1.nit
lib/mnit_android/android_assets.nit
lib/mnit_linux/linux_opengles1.nit

index def8598..24a904b 100644 (file)
@@ -55,7 +55,9 @@ 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" `{
@@ -79,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;
@@ -93,8 +97,8 @@ 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) {
                        PRINT_ERROR("error loading image after malloc: %i", mnit_opengles_error_code);
@@ -112,7 +116,7 @@ in "C" `{
                        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) {
@@ -454,10 +458,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 );
     `}
index 8f61c90..d1ee104 100644 (file)
@@ -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; i<height; i++)
                        row_pointers[i] = (png_byte*) malloc(row_bytes);
@@ -188,11 +196,11 @@ redef class Opengles1Image
                png_read_image(png_ptr, row_pointers);
 
                for (i = 0; i < height; i++)
-                       memcpy(pixels + (row_bytes*i),
-                                       row_pointers[i], row_bytes);
+                       memcpy(pixels + (row_bytes_pow2*i), row_pointers[i], row_bytes);
 
-               recv = mnit_opengles_load_image((const uint_least32_t *)pixels, width, height, has_alpha);
                LOGW("OK");
+               recv = mnit_opengles_load_image((const uint_least32_t *)pixels,
+                       width, height, width_pow2, height_pow2, has_alpha);
 
        close_png_ptr:
                if (info_ptr != NULL)
@@ -213,3 +221,13 @@ redef class Opengles1Image
                return recv;
        `}
 end
+
+redef universal Int
+       # The first power of `exp` greater or equal to `self`
+       private fun next_pow(exp: Int): Int
+       do
+               var p = 0
+               while p < self do p = p*exp
+               return p
+       end
+end
index 106bc07..084abcc 100644 (file)
@@ -78,7 +78,9 @@ end
 
 redef extern class Opengles1Image
        new from_sdl_image( sdl_image: SDLImage ) is extern `{
-               return mnit_opengles_load_image( sdl_image->pixels, 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;
                }