From 8b07f39d6f706931689cef4a0aaa126a346cf336 Mon Sep 17 00:00:00 2001
From: twinaphex <libretro@gmail.com>
Date: Tue, 10 May 2016 07:54:47 +0200
Subject: [PATCH] Create tasks/task_image.c

---
 Makefile.common            |   1 +
 griffin/griffin.c          |   1 +
 tasks/task_file_transfer.c | 409 +------------------------------------
 tasks/task_image.c         | 403 ++++++++++++++++++++++++++++++++++++
 tasks/tasks_internal.h     |  45 ++++
 5 files changed, 454 insertions(+), 405 deletions(-)
 create mode 100644 tasks/task_image.c

diff --git a/Makefile.common b/Makefile.common
index 9d184e89f8..ab4df5e620 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -127,6 +127,7 @@ OBJ += frontend/frontend.o \
        tasks/tasks_internal.o \
        tasks/task_content.o \
        tasks/task_file_transfer.o \
+       tasks/task_image.o \
        content.o \
        libretro-common/encodings/encoding_utf.o \
        libretro-common/lists/file_list.o \
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 8c0d1ab72f..4bd73571bf 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -802,6 +802,7 @@ NETPLAY
 DATA RUNLOOP
 ============================================================ */
 #include "../tasks/task_content.c"
+#include "../tasks/image.c"
 #include "../tasks/task_file_transfer.c"
 #ifdef HAVE_ZLIB
 #include "../tasks/task_decompress.c"
diff --git a/tasks/task_file_transfer.c b/tasks/task_file_transfer.c
index 34db03a599..5b7c4ce5c5 100644
--- a/tasks/task_file_transfer.c
+++ b/tasks/task_file_transfer.c
@@ -17,373 +17,15 @@
 #include <errno.h>
 #include <file/nbio.h>
 #include <formats/image.h>
-#include <formats/rpng.h>
 #include <compat/strl.h>
 #include <retro_assert.h>
 #include <retro_miscellaneous.h>
-#include <queues/message_queue.h>
 #include <lists/string_list.h>
 #include <rhash.h>
 
 #include "tasks_internal.h"
 #include "../verbosity.h"
 
-#define CB_MENU_WALLPAPER     0xb476e505U
-#define CB_MENU_THUMBNAIL     0x82f93a21U
-
-enum nbio_image_status_enum
-{
-   NBIO_IMAGE_STATUS_POLL = 0,
-   NBIO_IMAGE_STATUS_TRANSFER,
-   NBIO_IMAGE_STATUS_TRANSFER_PARSE,
-   NBIO_IMAGE_STATUS_PROCESS_TRANSFER,
-   NBIO_IMAGE_STATUS_PROCESS_TRANSFER_PARSE,
-   NBIO_IMAGE_STATUS_TRANSFER_PARSE_FREE
-};
-
-enum nbio_status_enum
-{
-   NBIO_STATUS_POLL = 0,
-   NBIO_STATUS_TRANSFER,
-   NBIO_STATUS_TRANSFER_PARSE,
-   NBIO_STATUS_TRANSFER_PARSE_FREE
-};
-
-typedef struct nbio_image_handle
-{
-   struct texture_image ti;
-   bool is_blocking;
-   bool is_blocking_on_processing;
-   bool is_finished;
-   transfer_cb_t  cb;
-#ifdef HAVE_RPNG
-   rpng_t *handle;
-#endif
-   unsigned processing_pos_increment;
-   unsigned pos_increment;
-   uint64_t frame_count;
-   int processing_final_state;
-   unsigned status;
-} nbio_image_handle_t;
-
-typedef struct nbio_handle
-{
-   nbio_image_handle_t image;
-   bool is_finished;
-   transfer_cb_t  cb;
-   struct nbio_t *handle;
-   unsigned pos_increment;
-   uint64_t frame_count;
-   msg_queue_t *msg_queue;
-   unsigned status;
-} nbio_handle_t;
-
-
-#ifdef HAVE_MENU
-#include "../menu/menu_driver.h"
-
-static void rarch_task_file_load_handler(retro_task_t *task);
-
-static int cb_image_menu_upload_generic(void *data, size_t len)
-{
-   nbio_handle_t *nbio = (nbio_handle_t*)data;
-   unsigned r_shift, g_shift, b_shift, a_shift;
-
-   if (!nbio)
-      return -1;
-
-   if (nbio->image.processing_final_state == IMAGE_PROCESS_ERROR ||
-         nbio->image.processing_final_state == IMAGE_PROCESS_ERROR_END)
-      return -1;
-
-   video_texture_image_set_color_shifts(&r_shift, &g_shift, &b_shift,
-         &a_shift);
-
-   video_texture_image_color_convert(r_shift, g_shift, b_shift,
-         a_shift, &nbio->image.ti);
-
-   nbio->image.is_blocking_on_processing         = false;
-   nbio->image.is_blocking                       = true;
-   nbio->image.is_finished                       = true;
-   nbio->is_finished                             = true;
-
-   return 0;
-}
-
-#ifdef HAVE_RPNG
-static int cb_image_menu_generic_rpng(nbio_handle_t *nbio)
-{
-   unsigned width = 0, height = 0;
-   int retval;
-   if (!nbio)
-      return -1;
-
-   if (!rpng_is_valid(nbio->image.handle))
-      return -1;
-
-   retval = rpng_nbio_load_image_argb_process(nbio->image.handle,
-         &nbio->image.ti.pixels, &width, &height);
-
-   nbio->image.ti.width  = width;
-   nbio->image.ti.height = height;
-
-   if (retval == IMAGE_PROCESS_ERROR)
-      return -1;
-   if (retval == IMAGE_PROCESS_ERROR_END)
-      return -1;
-
-   nbio->image.is_blocking_on_processing         = true;
-   nbio->image.is_finished                       = false;
-
-   return 0;
-}
-
-static int cb_image_menu_wallpaper_rpng(void *data, size_t len)
-{
-   nbio_handle_t *nbio = (nbio_handle_t*)data; 
-
-   if (cb_image_menu_generic_rpng(nbio) != 0)
-      return -1;
-
-   nbio->image.cb = &cb_image_menu_upload_generic;
-
-   return 0;
-}
-
-static int cb_image_menu_thumbnail(void *data, size_t len)
-{
-   nbio_handle_t *nbio = (nbio_handle_t*)data; 
-
-   if (cb_image_menu_generic_rpng(nbio) != 0)
-      return -1;
-
-   nbio->image.cb = &cb_image_menu_upload_generic;
-
-   return 0;
-}
-
-static int rarch_main_data_image_iterate_transfer(nbio_handle_t *nbio)
-{
-   unsigned i;
-
-   if (!nbio)
-      return -1;
-
-   if (nbio->image.is_finished)
-      return 0;
-
-   for (i = 0; i < nbio->image.pos_increment; i++)
-   {
-      /* TODO/FIXME - add JPEG equivalents as well */
-      if (!rpng_nbio_load_image_argb_iterate(nbio->image.handle))
-         goto error;
-   }
-
-   nbio->image.frame_count++;
-   return 0;
-
-error:
-   return -1;
-}
-
-static int rarch_main_data_image_iterate_process_transfer(nbio_handle_t *nbio)
-{
-   unsigned i, width = 0, height = 0;
-   int retval = 0;
-
-   if (!nbio)
-      return -1;
-
-   for (i = 0; i < nbio->image.processing_pos_increment; i++)
-   {
-      /* TODO/FIXME -add JPEG equivalents as well */
-      retval = rpng_nbio_load_image_argb_process(nbio->image.handle,
-            &nbio->image.ti.pixels, &width, &height);
-
-      nbio->image.ti.width  = width;
-      nbio->image.ti.height = height;
-
-      if (retval != IMAGE_PROCESS_NEXT)
-         break;
-   }
-
-   if (retval == IMAGE_PROCESS_NEXT)
-      return 0;
-
-   nbio->image.processing_final_state = retval;
-   return -1;
-}
-
-static int rarch_main_data_image_iterate_process_transfer_parse(
-      nbio_handle_t *nbio)
-{
-   if (nbio->image.handle && nbio->image.cb)
-   {
-      size_t len = 0;
-      nbio->image.cb(nbio, len);
-   }
-
-   return 0;
-}
-
-static int rarch_main_data_image_iterate_transfer_parse(nbio_handle_t *nbio)
-{
-   if (nbio->image.handle && nbio->image.cb)
-   {
-      size_t len = 0;
-      nbio->image.cb(nbio, len);
-   }
-
-   return 0;
-}
-
-static int cb_nbio_default(void *data, size_t len)
-{
-   nbio_handle_t *nbio = (nbio_handle_t*)data;
-
-   if (!data)
-      return -1;
-
-   (void)len;
-
-   nbio->is_finished   = true;
-
-   return 0;
-}
-
-static int cb_nbio_generic_rpng(nbio_handle_t *nbio, size_t *len)
-{
-   void *ptr           = NULL;
-
-   if (!nbio->image.handle)
-   {
-      nbio->image.cb = NULL;
-      return -1;
-   }
-
-   ptr = nbio_get_ptr(nbio->handle, len);
-
-   if (!ptr)
-   {
-      rpng_nbio_load_image_free(nbio->image.handle);
-      nbio->image.handle = NULL;
-      nbio->image.cb     = NULL;
-
-      return -1;
-   }
-
-   rpng_set_buf_ptr(nbio->image.handle, (uint8_t*)ptr);
-   nbio->image.pos_increment            = (*len / 2) ? (*len / 2) : 1;
-   nbio->image.processing_pos_increment = (*len / 4) ?  (*len / 4) : 1;
-
-   if (!rpng_nbio_load_image_argb_start(nbio->image.handle))
-   {
-      rpng_nbio_load_image_free(nbio->image.handle);
-      return -1;
-   }
-
-   nbio->image.is_blocking   = false;
-   nbio->image.is_finished   = false;
-   nbio->is_finished         = true;
-
-   return 0;
-}
-
-static int cb_nbio_image_menu_wallpaper_rpng(void *data, size_t len)
-{
-   nbio_handle_t *nbio = (nbio_handle_t*)data; 
-
-   if (!nbio || !data)
-      return -1;
-   
-   nbio->image.handle = rpng_alloc();
-   nbio->image.cb     = &cb_image_menu_wallpaper_rpng;
-
-   return cb_nbio_generic_rpng(nbio, &len);
-}
-
-static int cb_nbio_image_menu_thumbnail_rpng(void *data, size_t len)
-{
-   nbio_handle_t *nbio = (nbio_handle_t*)data; 
-
-   if (!nbio || !data)
-      return -1;
-   
-   nbio->image.handle = rpng_alloc();
-   nbio->image.cb     = &cb_image_menu_thumbnail;
-
-   return cb_nbio_generic_rpng(nbio, &len);
-}
-#endif
-#endif
-
-bool rarch_task_push_image_load(const char *fullpath,
-      const char *type, retro_task_callback_t cb, void *user_data)
-{
-#if defined(HAVE_RPNG) && defined(HAVE_MENU)
-   nbio_handle_t *nbio          = NULL;
-   retro_task_t *t              = NULL;
-   uint32_t cb_type_hash        = 0;
-   struct nbio_t* handle        = NULL;
-
-   cb_type_hash = djb2_calculate(type);
-
-   handle = nbio_open(fullpath, NBIO_READ);
-
-   if (!handle)
-   {
-      RARCH_ERR("[image load] Failed to open '%s': %s.\n",
-            fullpath, strerror(errno));
-      return false;
-   }
-
-   nbio = (nbio_handle_t*)calloc(1, sizeof(*nbio));
-
-   if (!nbio)
-      return false;
-
-   nbio->handle       = handle;
-   nbio->is_finished  = false;
-   nbio->cb           = &cb_nbio_default;
-   nbio->status       = NBIO_STATUS_TRANSFER;
-   nbio->image.status = NBIO_IMAGE_STATUS_TRANSFER;
-
-   if (strstr(fullpath, ".png"))
-   {
-#ifdef HAVE_RPNG
-      if (cb_type_hash == CB_MENU_WALLPAPER)
-         nbio->cb = &cb_nbio_image_menu_wallpaper_rpng;
-      else if (cb_type_hash == CB_MENU_THUMBNAIL)
-         nbio->cb = &cb_nbio_image_menu_thumbnail_rpng;
-#endif
-   }
-   else if (strstr(fullpath, ".jpeg") || strstr(fullpath, ".jpg"))
-   {
-      /* TODO/FIXME */
-   }
-
-   nbio_begin_read(handle);
-
-   t = (retro_task_t*)calloc(1, sizeof(*t));
-
-   if (!t)
-   {
-      free(nbio);
-      return false;
-   }
-
-   t->state = nbio;
-   t->handler = rarch_task_file_load_handler;
-   t->callback = cb;
-   t->user_data = user_data;
-
-   task_queue_ctl(TASK_QUEUE_CTL_PUSH, t);
-#endif
-   return true;
-}
-
-/* Guarded for RPNG/menu use but good for generic reuse */
-#if defined(HAVE_RPNG) && defined(HAVE_MENU)
 static int rarch_main_data_nbio_iterate_transfer(nbio_handle_t *nbio)
 {
    size_t i;
@@ -420,10 +62,9 @@ static int rarch_main_data_nbio_iterate_parse(nbio_handle_t *nbio)
    return 0;
 }
 
-static void rarch_task_file_load_handler(retro_task_t *task)
+void rarch_task_file_load_handler(retro_task_t *task)
 {
    nbio_handle_t         *nbio  = (nbio_handle_t*)task->state;
-   nbio_image_handle_t   *image = nbio    ? &nbio->image   : NULL;
 
    switch (nbio->status)
    {
@@ -443,43 +84,8 @@ static void rarch_task_file_load_handler(retro_task_t *task)
 
    if (nbio->image.handle)
    {
-      switch (image->status)
-      {
-         case NBIO_IMAGE_STATUS_PROCESS_TRANSFER:
-            if (rarch_main_data_image_iterate_process_transfer(nbio) == -1)
-               image->status = NBIO_IMAGE_STATUS_PROCESS_TRANSFER_PARSE;
-            break;
-         case NBIO_IMAGE_STATUS_TRANSFER_PARSE:
-            rarch_main_data_image_iterate_transfer_parse(nbio);
-            if (image->is_blocking_on_processing)
-               image->status = NBIO_IMAGE_STATUS_PROCESS_TRANSFER;
-            break;
-         case NBIO_IMAGE_STATUS_TRANSFER:
-            if (!image->is_blocking)
-               if (rarch_main_data_image_iterate_transfer(nbio) == -1)
-                  image->status = NBIO_IMAGE_STATUS_TRANSFER_PARSE;
-            break;
-         case NBIO_IMAGE_STATUS_PROCESS_TRANSFER_PARSE:
-            rarch_main_data_image_iterate_process_transfer_parse(nbio);
-            if (!image->is_finished)
-               break;
-         case NBIO_IMAGE_STATUS_TRANSFER_PARSE_FREE:
-         case NBIO_IMAGE_STATUS_POLL:
-         default:
-            break;
-      }
-
-      if (     nbio->is_finished 
-            && nbio->image.is_finished 
-            && !task->cancelled)
-      {
-         task->task_data = malloc(sizeof(nbio->image.ti));
-
-         if (task->task_data)
-            memcpy(task->task_data, &nbio->image.ti, sizeof(nbio->image.ti));
-
+      if (!rarch_task_image_load_handler(task))
          goto task_finished;
-      }
    }
    else
       if (nbio->is_finished)
@@ -497,14 +103,8 @@ static void rarch_task_file_load_handler(retro_task_t *task)
 task_finished:
    task->finished = true;
 
-   if (image->handle)
-   {
-      /* TODO/FIXME - add JPEG equivalents as well */
-      rpng_nbio_load_image_free(image->handle);
-
-      image->handle                 = NULL;
-      image->frame_count            = 0;
-   }
+   if (nbio->image.handle != NULL)
+      rarch_task_image_load_free(task);
 
    nbio_free(nbio->handle);
    nbio->handle      = NULL;
@@ -512,4 +112,3 @@ task_finished:
    nbio->frame_count = 0;
    free(nbio);
 }
-#endif
diff --git a/tasks/task_image.c b/tasks/task_image.c
new file mode 100644
index 0000000000..3b2eb8ce98
--- /dev/null
+++ b/tasks/task_image.c
@@ -0,0 +1,403 @@
+/*  RetroArch - A frontend for libretro.
+ *  Copyright (C) 2011-2016 - Daniel De Matteis
+ *
+ *  RetroArch is free software: you can redistribute it and/or modify it under the terms
+ *  of the GNU General Public License as published by the Free Software Found-
+ *  ation, either version 3 of the License, or (at your option) any later version.
+ *
+ *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  PURPOSE.  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with RetroArch.
+ *  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <file/nbio.h>
+#include <formats/image.h>
+#include <compat/strl.h>
+#include <retro_assert.h>
+#include <retro_miscellaneous.h>
+#include <lists/string_list.h>
+#include <rhash.h>
+#ifdef HAVE_RPNG
+#include <formats/rpng.h>
+#endif
+
+#ifdef HAVE_MENU
+#include "../menu/menu_driver.h"
+#endif
+
+#include "tasks_internal.h"
+#include "../verbosity.h"
+
+enum nbio_image_status_enum
+{
+   NBIO_IMAGE_STATUS_POLL = 0,
+   NBIO_IMAGE_STATUS_TRANSFER,
+   NBIO_IMAGE_STATUS_TRANSFER_PARSE,
+   NBIO_IMAGE_STATUS_PROCESS_TRANSFER,
+   NBIO_IMAGE_STATUS_PROCESS_TRANSFER_PARSE,
+   NBIO_IMAGE_STATUS_TRANSFER_PARSE_FREE
+};
+
+static int cb_image_menu_upload_generic(void *data, size_t len)
+{
+   nbio_handle_t *nbio = (nbio_handle_t*)data;
+   unsigned r_shift, g_shift, b_shift, a_shift;
+
+   if (!nbio)
+      return -1;
+
+   if (nbio->image.processing_final_state == IMAGE_PROCESS_ERROR ||
+         nbio->image.processing_final_state == IMAGE_PROCESS_ERROR_END)
+      return -1;
+
+   video_texture_image_set_color_shifts(&r_shift, &g_shift, &b_shift,
+         &a_shift);
+
+   video_texture_image_color_convert(r_shift, g_shift, b_shift,
+         a_shift, &nbio->image.ti);
+
+   nbio->image.is_blocking_on_processing         = false;
+   nbio->image.is_blocking                       = true;
+   nbio->image.is_finished                       = true;
+   nbio->is_finished                             = true;
+
+   return 0;
+}
+
+static int rarch_main_data_image_iterate_process_transfer_parse(
+      nbio_handle_t *nbio)
+{
+   if (nbio->image.handle && nbio->image.cb)
+   {
+      size_t len = 0;
+      nbio->image.cb(nbio, len);
+   }
+
+   return 0;
+}
+
+static int rarch_main_data_image_iterate_transfer_parse(nbio_handle_t *nbio)
+{
+   if (nbio->image.handle && nbio->image.cb)
+   {
+      size_t len = 0;
+      nbio->image.cb(nbio, len);
+   }
+
+   return 0;
+}
+
+static int cb_nbio_default(void *data, size_t len)
+{
+   nbio_handle_t *nbio = (nbio_handle_t*)data;
+
+   if (!data)
+      return -1;
+
+   (void)len;
+
+   nbio->is_finished   = true;
+
+   return 0;
+}
+
+#ifdef HAVE_RPNG
+static int cb_image_menu_generic_rpng(nbio_handle_t *nbio)
+{
+   unsigned width = 0, height = 0;
+   int retval;
+   if (!nbio)
+      return -1;
+
+   if (!rpng_is_valid(nbio->image.handle))
+      return -1;
+
+   retval = rpng_nbio_load_image_argb_process(nbio->image.handle,
+         &nbio->image.ti.pixels, &width, &height);
+
+   nbio->image.ti.width  = width;
+   nbio->image.ti.height = height;
+
+   if (retval == IMAGE_PROCESS_ERROR)
+      return -1;
+   if (retval == IMAGE_PROCESS_ERROR_END)
+      return -1;
+
+   nbio->image.is_blocking_on_processing         = true;
+   nbio->image.is_finished                       = false;
+
+   return 0;
+}
+
+static int cb_image_menu_wallpaper_rpng(void *data, size_t len)
+{
+   nbio_handle_t *nbio = (nbio_handle_t*)data; 
+
+   if (cb_image_menu_generic_rpng(nbio) != 0)
+      return -1;
+
+   nbio->image.cb = &cb_image_menu_upload_generic;
+
+   return 0;
+}
+
+static int cb_image_menu_thumbnail(void *data, size_t len)
+{
+   nbio_handle_t *nbio = (nbio_handle_t*)data; 
+
+   if (cb_image_menu_generic_rpng(nbio) != 0)
+      return -1;
+
+   nbio->image.cb = &cb_image_menu_upload_generic;
+
+   return 0;
+}
+
+static int rarch_main_data_image_iterate_transfer(nbio_handle_t *nbio)
+{
+   unsigned i;
+
+   if (!nbio)
+      return -1;
+
+   if (nbio->image.is_finished)
+      return 0;
+
+   for (i = 0; i < nbio->image.pos_increment; i++)
+   {
+      /* TODO/FIXME - add JPEG equivalents as well */
+      if (!rpng_nbio_load_image_argb_iterate(nbio->image.handle))
+         goto error;
+   }
+
+   nbio->image.frame_count++;
+   return 0;
+
+error:
+   return -1;
+}
+
+static int rarch_main_data_image_iterate_process_transfer(nbio_handle_t *nbio)
+{
+   unsigned i, width = 0, height = 0;
+   int retval = 0;
+
+   if (!nbio)
+      return -1;
+
+   for (i = 0; i < nbio->image.processing_pos_increment; i++)
+   {
+      /* TODO/FIXME -add JPEG equivalents as well */
+      retval = rpng_nbio_load_image_argb_process(nbio->image.handle,
+            &nbio->image.ti.pixels, &width, &height);
+
+      nbio->image.ti.width  = width;
+      nbio->image.ti.height = height;
+
+      if (retval != IMAGE_PROCESS_NEXT)
+         break;
+   }
+
+   if (retval == IMAGE_PROCESS_NEXT)
+      return 0;
+
+   nbio->image.processing_final_state = retval;
+   return -1;
+}
+
+static int cb_nbio_generic_rpng(nbio_handle_t *nbio, size_t *len)
+{
+   void *ptr           = NULL;
+
+   if (!nbio->image.handle)
+   {
+      nbio->image.cb = NULL;
+      return -1;
+   }
+
+   ptr = nbio_get_ptr(nbio->handle, len);
+
+   if (!ptr)
+   {
+      rpng_nbio_load_image_free(nbio->image.handle);
+      nbio->image.handle = NULL;
+      nbio->image.cb     = NULL;
+
+      return -1;
+   }
+
+   rpng_set_buf_ptr(nbio->image.handle, (uint8_t*)ptr);
+   nbio->image.pos_increment            = (*len / 2) ? (*len / 2) : 1;
+   nbio->image.processing_pos_increment = (*len / 4) ?  (*len / 4) : 1;
+
+   if (!rpng_nbio_load_image_argb_start(nbio->image.handle))
+   {
+      rpng_nbio_load_image_free(nbio->image.handle);
+      return -1;
+   }
+
+   nbio->image.is_blocking   = false;
+   nbio->image.is_finished   = false;
+   nbio->is_finished         = true;
+
+   return 0;
+}
+
+static int cb_nbio_image_menu_wallpaper_rpng(void *data, size_t len)
+{
+   nbio_handle_t *nbio = (nbio_handle_t*)data; 
+
+   if (!nbio || !data)
+      return -1;
+   
+   nbio->image.handle = rpng_alloc();
+   nbio->image.cb     = &cb_image_menu_wallpaper_rpng;
+
+   return cb_nbio_generic_rpng(nbio, &len);
+}
+
+static int cb_nbio_image_menu_thumbnail_rpng(void *data, size_t len)
+{
+   nbio_handle_t *nbio = (nbio_handle_t*)data; 
+
+   if (!nbio || !data)
+      return -1;
+   
+   nbio->image.handle = rpng_alloc();
+   nbio->image.cb     = &cb_image_menu_thumbnail;
+
+   return cb_nbio_generic_rpng(nbio, &len);
+}
+#endif
+
+bool rarch_task_image_load_handler(retro_task_t *task)
+{
+   nbio_handle_t       *nbio  = (nbio_handle_t*)task->state;
+   nbio_image_handle_t *image = nbio ? &nbio->image : NULL;
+
+   switch (image->status)
+   {
+      case NBIO_IMAGE_STATUS_PROCESS_TRANSFER:
+         if (rarch_main_data_image_iterate_process_transfer(nbio) == -1)
+            image->status = NBIO_IMAGE_STATUS_PROCESS_TRANSFER_PARSE;
+         break;
+      case NBIO_IMAGE_STATUS_TRANSFER_PARSE:
+         rarch_main_data_image_iterate_transfer_parse(nbio);
+         if (image->is_blocking_on_processing)
+            image->status = NBIO_IMAGE_STATUS_PROCESS_TRANSFER;
+         break;
+      case NBIO_IMAGE_STATUS_TRANSFER:
+         if (!image->is_blocking)
+            if (rarch_main_data_image_iterate_transfer(nbio) == -1)
+               image->status = NBIO_IMAGE_STATUS_TRANSFER_PARSE;
+         break;
+      case NBIO_IMAGE_STATUS_PROCESS_TRANSFER_PARSE:
+         rarch_main_data_image_iterate_process_transfer_parse(nbio);
+         if (!image->is_finished)
+            break;
+      case NBIO_IMAGE_STATUS_TRANSFER_PARSE_FREE:
+      case NBIO_IMAGE_STATUS_POLL:
+      default:
+         break;
+   }
+
+   if (     nbio->is_finished 
+         && nbio->image.is_finished 
+         && !task->cancelled)
+   {
+      task->task_data = malloc(sizeof(nbio->image.ti));
+
+      if (task->task_data)
+         memcpy(task->task_data, &nbio->image.ti, sizeof(nbio->image.ti));
+
+      return false;
+   }
+
+   return true;
+}
+
+bool rarch_task_push_image_load(const char *fullpath,
+      const char *type, retro_task_callback_t cb, void *user_data)
+{
+#if defined(HAVE_RPNG) && defined(HAVE_MENU)
+   nbio_handle_t *nbio          = NULL;
+   retro_task_t *t              = NULL;
+   uint32_t cb_type_hash        = 0;
+   struct nbio_t* handle        = NULL;
+
+   cb_type_hash = djb2_calculate(type);
+
+   handle = nbio_open(fullpath, NBIO_READ);
+
+   if (!handle)
+   {
+      RARCH_ERR("[image load] Failed to open '%s': %s.\n",
+            fullpath, strerror(errno));
+      return false;
+   }
+
+   nbio = (nbio_handle_t*)calloc(1, sizeof(*nbio));
+
+   if (!nbio)
+      return false;
+
+   nbio->handle       = handle;
+   nbio->is_finished  = false;
+   nbio->cb           = &cb_nbio_default;
+   nbio->status       = NBIO_STATUS_TRANSFER;
+   nbio->image.status = NBIO_IMAGE_STATUS_TRANSFER;
+
+   if (strstr(fullpath, ".png"))
+   {
+#ifdef HAVE_RPNG
+      if (cb_type_hash == CB_MENU_WALLPAPER)
+         nbio->cb = &cb_nbio_image_menu_wallpaper_rpng;
+      else if (cb_type_hash == CB_MENU_THUMBNAIL)
+         nbio->cb = &cb_nbio_image_menu_thumbnail_rpng;
+#endif
+   }
+   else if (strstr(fullpath, ".jpeg") || strstr(fullpath, ".jpg"))
+   {
+      /* TODO/FIXME */
+   }
+
+   nbio_begin_read(handle);
+
+   t = (retro_task_t*)calloc(1, sizeof(*t));
+
+   if (!t)
+   {
+      free(nbio);
+      return false;
+   }
+
+   t->state     = nbio;
+   t->handler   = rarch_task_file_load_handler;
+   t->callback  = cb;
+   t->user_data = user_data;
+
+   task_queue_ctl(TASK_QUEUE_CTL_PUSH, t);
+#endif
+   return true;
+}
+
+void rarch_task_image_load_free(retro_task_t *task)
+{
+   nbio_handle_t       *nbio  = (nbio_handle_t*)task->state;
+   nbio_image_handle_t *image = nbio ? &nbio->image : NULL;
+
+#ifdef HAVE_RPNG
+   /* TODO/FIXME - add JPEG equivalents as well */
+   rpng_nbio_load_image_free(image->handle);
+#endif
+
+   image->handle                 = NULL;
+   image->frame_count            = 0;
+}
diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h
index 44562f2bad..897ce2fc2f 100644
--- a/tasks/tasks_internal.h
+++ b/tasks/tasks_internal.h
@@ -19,6 +19,7 @@
 #include <stdint.h>
 #include <boolean.h>
 
+#include <queues/message_queue.h>
 #include <queues/task_queue.h>
 
 #include "../core_type.h"
@@ -28,6 +29,17 @@
 extern "C" {
 #endif
 
+#define CB_MENU_WALLPAPER     0xb476e505U
+#define CB_MENU_THUMBNAIL     0x82f93a21U
+
+enum nbio_status_enum
+{
+   NBIO_STATUS_POLL = 0,
+   NBIO_STATUS_TRANSFER,
+   NBIO_STATUS_TRANSFER_PARSE,
+   NBIO_STATUS_TRANSFER_PARSE_FREE
+};
+
 #ifdef HAVE_NETWORKING
 typedef struct {
     char *data;
@@ -40,6 +52,33 @@ typedef struct http_transfer_info
    int progress;
 } http_transfer_info_t;
 
+typedef struct nbio_image_handle
+{
+   struct texture_image ti;
+   bool is_blocking;
+   bool is_blocking_on_processing;
+   bool is_finished;
+   transfer_cb_t  cb;
+   void *handle;
+   unsigned processing_pos_increment;
+   unsigned pos_increment;
+   uint64_t frame_count;
+   int processing_final_state;
+   unsigned status;
+} nbio_image_handle_t;
+
+typedef struct nbio_handle
+{
+   nbio_image_handle_t image;
+   bool is_finished;
+   transfer_cb_t  cb;
+   struct nbio_t *handle;
+   unsigned pos_increment;
+   uint64_t frame_count;
+   msg_queue_t *msg_queue;
+   unsigned status;
+} nbio_handle_t;
+
 void *rarch_task_push_http_transfer(const char *url, const char *type,
       retro_task_callback_t cb, void *userdata);
 
@@ -71,6 +110,8 @@ int detect_psp_game(const char *track_path, char *game_id);
 
 bool rarch_task_check_decompress(const char *source_file);
 
+bool rarch_task_image_load_handler(retro_task_t *task);
+
 bool rarch_task_push_decompress(
       const char *source_file,
       const char *target_dir,
@@ -88,6 +129,10 @@ bool rarch_task_push_content_load_default(
       retro_task_callback_t cb,
       void *user_data);
 
+void rarch_task_image_load_free(retro_task_t *task);
+
+void rarch_task_file_load_handler(retro_task_t *task);;
+
 #ifdef __cplusplus
 }
 #endif