summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorTeruaki Kawashima <teru@rockbox.org>2010-11-21 13:47:56 +0000
committerTeruaki Kawashima <teru@rockbox.org>2010-11-21 13:47:56 +0000
commite5b1a7d4237a9006b6c49c9c1c13b292ca4ecf7c (patch)
treef0b9dd1cba0a4ee70afd8b6da64a05286f76c380 /apps
parenteef21cb18ae4bc7cdf83830554a848e0c733a73d (diff)
downloadrockbox-e5b1a7d4237a9006b6c49c9c1c13b292ca4ecf7c.tar.gz
rockbox-e5b1a7d4237a9006b6c49c9c1c13b292ca4ecf7c.tar.bz2
rockbox-e5b1a7d4237a9006b6c49c9c1c13b292ca4ecf7c.zip
FS#6321: Universal Image Viewer
This unifies jpeg viewer, png viewer, and bmp viewer to one plugin, image viewer, so that you can navigate through different image formats. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28626 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/imageviewer/SOURCES2
-rw-r--r--apps/plugins/imageviewer/bmp/SOURCES1
-rw-r--r--apps/plugins/imageviewer/bmp/bmp.c47
-rw-r--r--apps/plugins/imageviewer/bmp/bmp.make14
-rw-r--r--apps/plugins/imageviewer/bmp/bmp_ui.c5
-rw-r--r--apps/plugins/imageviewer/image_decoder.c130
-rw-r--r--apps/plugins/imageviewer/image_decoder.h46
-rw-r--r--apps/plugins/imageviewer/imageviewer.c219
-rw-r--r--apps/plugins/imageviewer/imageviewer.h104
-rw-r--r--apps/plugins/imageviewer/imageviewer.make45
-rw-r--r--apps/plugins/imageviewer/jpeg/SOURCES1
-rw-r--r--apps/plugins/imageviewer/jpeg/jpeg.c52
-rw-r--r--apps/plugins/imageviewer/jpeg/jpeg.make14
-rw-r--r--apps/plugins/imageviewer/jpeg/jpeg_ui.c5
-rw-r--r--apps/plugins/imageviewer/png/SOURCES1
-rw-r--r--apps/plugins/imageviewer/png/png.c55
-rw-r--r--apps/plugins/imageviewer/png/png.make13
-rw-r--r--apps/plugins/imageviewer/png/png_ui.c5
-rw-r--r--apps/plugins/plugin.lds3
-rw-r--r--apps/plugins/viewers.config10
21 files changed, 547 insertions, 226 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 1d9aa8aee0..983e52c88a 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -35,6 +35,7 @@ frotz,viewers
goban,games
greyscale,demos
helloworld,demos
+imageviewer,viewers
invadrox,games
iriver_flash,apps
iriverify,viewers
diff --git a/apps/plugins/imageviewer/SOURCES b/apps/plugins/imageviewer/SOURCES
new file mode 100644
index 0000000000..610087bf82
--- /dev/null
+++ b/apps/plugins/imageviewer/SOURCES
@@ -0,0 +1,2 @@
+imageviewer.c
+image_decoder.c
diff --git a/apps/plugins/imageviewer/bmp/SOURCES b/apps/plugins/imageviewer/bmp/SOURCES
index a50d245846..29297c9ec2 100644
--- a/apps/plugins/imageviewer/bmp/SOURCES
+++ b/apps/plugins/imageviewer/bmp/SOURCES
@@ -1,2 +1 @@
-bmp_ui.c
bmp.c
diff --git a/apps/plugins/imageviewer/bmp/bmp.c b/apps/plugins/imageviewer/bmp/bmp.c
index 6d33575f98..b7efbb7e2c 100644
--- a/apps/plugins/imageviewer/bmp/bmp.c
+++ b/apps/plugins/imageviewer/bmp/bmp.c
@@ -65,18 +65,13 @@ struct bitmap bmp;
/************************* Implementation ***************************/
-bool img_ext(const char *ext)
-{
- if (!ext)
- return false;
- if (!rb->strcasecmp(ext,".bmp"))
- return true;
- else
- return false;
-}
+#if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED)
+/* hack: fix error "undefined reference to `_grey_info'". */
+GREY_INFO_STRUCT
+#endif /* USEGSLIB */
-void draw_image_rect(struct image_info *info,
- int x, int y, int width, int height)
+static void draw_image_rect(struct image_info *info,
+ int x, int y, int width, int height)
{
struct t_disp* pdisp = (struct t_disp*)info->data;
#ifdef HAVE_LCD_COLOR
@@ -95,7 +90,7 @@ void draw_image_rect(struct image_info *info,
#endif
}
-int img_mem(int ds)
+static int img_mem(int ds)
{
#ifndef USEGSLIB
return (bmp.width/ds) * (bmp.height/ds) * sizeof (fb_data);
@@ -104,8 +99,8 @@ int img_mem(int ds)
#endif
}
-int load_image(char *filename, struct image_info *info,
- unsigned char *buf, ssize_t *buf_size)
+static int load_image(char *filename, struct image_info *info,
+ unsigned char *buf, ssize_t *buf_size)
{
int w, h; /* used to center output */
long time; /* measured ticks */
@@ -147,7 +142,7 @@ int load_image(char *filename, struct image_info *info,
}
#endif
#ifdef USE_PLUG_BUF
- if (!plug_buf)
+ if (!iv->plug_buf)
#endif
{
while (size > *buf_size && bmp.width >= 2 && bmp.height >= 2 && ds < 8)
@@ -174,7 +169,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OUTOFMEM;
}
- if (!running_slideshow)
+ if (!iv->running_slideshow)
{
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_putsf(0, 1, "loading %dx%d%s",
@@ -204,7 +199,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_ERROR;
}
- if (!running_slideshow)
+ if (!iv->running_slideshow)
{
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@@ -212,7 +207,7 @@ int load_image(char *filename, struct image_info *info,
rb->lcd_update();
}
#ifdef DISK_SPINDOWN
- else if (immediate_ata_off)
+ else if(iv->immediate_ata_off)
{
/* running slideshow and time is long enough: power down disk */
rb->storage_sleep();
@@ -223,7 +218,7 @@ int load_image(char *filename, struct image_info *info,
buf_images = buf_root = buf + size;
buf_images_size = root_size = *buf_size - size;
- if (!running_slideshow)
+ if (!iv->running_slideshow)
{
rb->lcd_putsf(0, 2, "image %dx%d", bmp.width, bmp.height);
rb->lcd_update();
@@ -235,7 +230,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OK;
}
-int get_image(struct image_info *info, int ds)
+static int get_image(struct image_info *info, int ds)
{
struct t_disp* p_disp = &disp[ds]; /* short cut */
@@ -270,7 +265,7 @@ int get_image(struct image_info *info, int ds)
buf_images += size;
buf_images_size -= size;
- if (!running_slideshow)
+ if (!iv->running_slideshow)
{
rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
rb->lcd_update();
@@ -294,3 +289,13 @@ int get_image(struct image_info *info, int ds)
return PLUGIN_OK;
}
+
+const struct image_decoder image_decoder = {
+ true,
+ img_mem,
+ load_image,
+ get_image,
+ draw_image_rect,
+};
+
+IMGDEC_HEADER
diff --git a/apps/plugins/imageviewer/bmp/bmp.make b/apps/plugins/imageviewer/bmp/bmp.make
index 0582ba3eb3..0947dd6166 100644
--- a/apps/plugins/imageviewer/bmp/bmp.make
+++ b/apps/plugins/imageviewer/bmp/bmp.make
@@ -10,12 +10,18 @@
BMPSRCDIR := $(IMGVSRCDIR)/bmp
BMPBUILDDIR := $(IMGVBUILDDIR)/bmp
-ROCKS += $(BMPBUILDDIR)/bmp.rock
-
BMP_SRC := $(call preprocess, $(BMPSRCDIR)/SOURCES)
BMP_OBJ := $(call c2obj, $(BMP_SRC))
-# add source files to OTHER_SRC to get automatic dependencies
OTHER_SRC += $(BMP_SRC)
-$(BMPBUILDDIR)/bmp.rock: $(BMP_OBJ)
+ROCKS += $(BMPBUILDDIR)/bmp.ovl
+
+$(BMPBUILDDIR)/bmp.refmap: $(BMP_OBJ)
+$(BMPBUILDDIR)/bmp.link: $(PLUGIN_LDS) $(BMPBUILDDIR)/bmp.refmap
+$(BMPBUILDDIR)/bmp.ovl: $(BMP_OBJ)
+
+# special pattern rule for compiling image decoder with extra flags
+$(BMPBUILDDIR)/%.o: $(BMPSRCDIR)/%.c $(BMPSRCDIR)/bmp.make
+ $(SILENT)mkdir -p $(dir $@)
+ $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(IMGDECFLAGS) -c $< -o $@
diff --git a/apps/plugins/imageviewer/bmp/bmp_ui.c b/apps/plugins/imageviewer/bmp/bmp_ui.c
deleted file mode 100644
index 8ff3e0c880..0000000000
--- a/apps/plugins/imageviewer/bmp/bmp_ui.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#define BMP_VIEWER
-#define MENU_TITLE "BMP Menu"
-#define UNSCALED_IS_AVAILABLE 1
-
-#include "../imageviewer.c"
diff --git a/apps/plugins/imageviewer/image_decoder.c b/apps/plugins/imageviewer/image_decoder.c
new file mode 100644
index 0000000000..b4fa27e425
--- /dev/null
+++ b/apps/plugins/imageviewer/image_decoder.c
@@ -0,0 +1,130 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * load image decoder.
+ *
+ * This program 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 Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "plugin.h"
+#include "imageviewer.h"
+#include "image_decoder.h"
+
+static const char *decoder_names[MAX_IMAGE_TYPES] = {
+ "bmp",
+ "jpeg",
+ "png",
+};
+
+/* check file type by extention */
+enum image_type get_image_type(const char *name)
+{
+ static const struct {
+ char *ext;
+ enum image_type type;
+ } ext_list[] = {
+ { ".bmp", IMAGE_BMP },
+ { ".jpg", IMAGE_JPEG },
+ { ".jpe", IMAGE_JPEG },
+ { ".jpeg", IMAGE_JPEG },
+ { ".png", IMAGE_PNG },
+ };
+
+ const char *ext = rb->strrchr(name, '.');
+ int i;
+ if (!ext)
+ return IMAGE_UNKNOWN;
+
+ for (i = 0; i < (int)ARRAYLEN(ext_list); i++)
+ {
+ if (!rb->strcasecmp(ext, ext_list[i].ext))
+ return ext_list[i].type;
+ }
+ return IMAGE_UNKNOWN;
+}
+
+static void *decoder_handle = NULL;
+const struct image_decoder *load_decoder(struct loader_info *loader_info)
+{
+ const char *name;
+ char filename[MAX_PATH];
+ struct imgdec_header *hdr;
+ struct lc_header *lc_hdr;
+
+ if (loader_info->type < 0 || loader_info->type >= MAX_IMAGE_TYPES)
+ {
+ rb->splashf(2*HZ, "Unknown type: %d", loader_info->type);
+ goto error;
+ }
+
+ release_decoder();
+
+ name = decoder_names[loader_info->type];
+ rb->snprintf(filename, MAX_PATH, VIEWERS_DIR "/%s.ovl", name);
+
+ /* load decoder to the buffer. */
+ decoder_handle = rb->lc_open(filename, loader_info->buffer, loader_info->size);
+ if (!decoder_handle)
+ {
+ rb->splashf(2*HZ, "Can't open %s", filename);
+ goto error;
+ }
+
+ hdr = rb->lc_get_header(decoder_handle);
+ if (!hdr)
+ {
+ rb->splash(2*HZ, "Can't get header");
+ goto error_close;
+ }
+ lc_hdr = &hdr->lc_hdr;
+
+ if (lc_hdr->magic != PLUGIN_MAGIC || lc_hdr->target_id != TARGET_ID)
+ {
+ rb->splashf(2*HZ, "%s decoder: Incompatible model.", name);
+ goto error_close;
+ }
+
+ if (lc_hdr->api_version != IMGDEC_API_VERSION)
+ {
+ rb->splashf(2*HZ, "%s decoder: Incompatible version.", name);
+ goto error_close;
+ }
+
+ *(hdr->api) = rb;
+ *(hdr->img_api) = loader_info->iv;
+
+ /* set remaining buffer size to loader_info. decoder will
+ * be loaded to the end of the buffer, so fix size only. */
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+ loader_info->size = lc_hdr->load_addr - loader_info->buffer;
+#endif
+
+ return hdr->decoder;
+
+error_close:
+ release_decoder();
+error:
+ return NULL;
+}
+
+void release_decoder(void)
+{
+ if (decoder_handle != NULL)
+ {
+ rb->lc_close(decoder_handle);
+ decoder_handle = NULL;
+ }
+}
diff --git a/apps/plugins/imageviewer/image_decoder.h b/apps/plugins/imageviewer/image_decoder.h
new file mode 100644
index 0000000000..93608b1b9a
--- /dev/null
+++ b/apps/plugins/imageviewer/image_decoder.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * load image decoder.
+ *
+ * This program 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 Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _IMAGE_DECODER_H
+#define _IMAGE_DECODER_H
+
+#include "imageviewer.h"
+
+enum image_type {
+ IMAGE_UNKNOWN = -1,
+ IMAGE_BMP = 0,
+ IMAGE_JPEG,
+ IMAGE_PNG,
+ MAX_IMAGE_TYPES
+};
+
+struct loader_info {
+ enum image_type type;
+ const struct imgdec_api *iv;
+ unsigned char* buffer;
+ size_t size;
+};
+
+enum image_type get_image_type(const char *name);
+const struct image_decoder *load_decoder(struct loader_info *loader_info);
+void release_decoder(void);
+
+#endif /* _IMAGE_DECODER_H */
diff --git a/apps/plugins/imageviewer/imageviewer.c b/apps/plugins/imageviewer/imageviewer.c
index e3c72ae291..01b9f31be1 100644
--- a/apps/plugins/imageviewer/imageviewer.c
+++ b/apps/plugins/imageviewer/imageviewer.c
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * user intereface of image viewers (jpeg, png, etc.)
+ * user intereface of image viewer
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,11 +19,16 @@
*
****************************************************************************/
+/*
+ * TODO:
+ * - check magick value in file header to determine image type.
+ */
#include "plugin.h"
#include <lib/playback_control.h>
#include <lib/helper.h>
#include <lib/configfile.h>
#include "imageviewer.h"
+#include "image_decoder.h"
@@ -38,16 +43,6 @@ GREY_INFO_STRUCT
/******************************* Globals ***********************************/
-bool slideshow_enabled = false; /* run slideshow */
-bool running_slideshow = false; /* loading image because of slideshow */
-#ifdef DISK_SPINDOWN
-bool immediate_ata_off = false; /* power down disk after loading */
-#endif
-#ifdef USE_PLUG_BUF
-/* are we using the plugin buffer or the audio buffer? */
-bool plug_buf = true;
-#endif
-
/* Persistent configuration */
#define IMGVIEW_CONFIGFILE "imageviewer.cfg"
#define IMGVIEW_SETTINGS_MINVERSION 1
@@ -63,8 +58,7 @@ bool plug_buf = true;
#include "jpeg/yuv2rgb.h"
#endif
-/* jpeg use this */
-struct imgview_settings settings =
+static struct imgview_settings settings =
{
#ifdef HAVE_LCD_COLOR
COLOURMODE_COLOUR,
@@ -86,17 +80,39 @@ static struct configdata config[] =
{ .int_p = &settings.ss_timeout }, "Slideshow Time", NULL },
};
+static void cb_progress(int current, int total);
+
+static struct imgdec_api iv_api = {
+ .settings = &settings,
+ .slideshow_enabled = false,
+ .running_slideshow = false,
+#ifdef DISK_SPINDOWN
+ .immediate_ata_off = false,
+#endif
+#ifdef USE_PLUG_BUF
+ .plug_buf = true,
+#endif
+
+ .cb_progress = cb_progress,
+
+#ifdef USEGSLIB
+ .gray_bitmap_part = myxlcd_ub_(gray_bitmap_part),
+#endif
+};
+
/**************** begin Application ********************/
/************************* Globals ***************************/
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
+#ifdef HAVE_LCD_COLOR
static fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when
DITHER_DIFFUSION is set */
#endif
-/* my memory pool (from the mp3 buffer) */
+/* buffer to load image decoder */
+static unsigned char* decoder_buf;
+static size_t decoder_buf_size;
/* the remaining free part of the buffer for loaded+resized images */
static unsigned char* buf;
static size_t buf_size;
@@ -106,11 +122,14 @@ static struct image_info image_info;
/* the current full file name */
static char np_file[MAX_PATH];
-static int curfile = 0, direction = DIR_NEXT, entries = 0;
+static int curfile = -1, direction = DIR_NEXT, entries = 0;
/* list of the supported image files */
static char **file_pt;
+static const struct image_decoder *imgdec = NULL;
+static enum image_type image_type = IMAGE_UNKNOWN;
+
/************************* Implementation ***************************/
/* Read directory contents for scrolling. */
@@ -130,7 +149,7 @@ static void get_pic_list(void)
for (i = 0; i < tree->filesindir && buf_size > sizeof(char**); i++)
{
if (!(dircache[i].attr & ATTR_DIRECTORY)
- && img_ext(rb->strrchr(dircache[i].name,'.')))
+ && get_image_type(dircache[i].name) != IMAGE_UNKNOWN)
{
file_pt[entries] = dircache[i].name;
/* Set Selected File. */
@@ -187,11 +206,11 @@ static void cleanup(void *parameter)
#endif
}
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
+#ifdef HAVE_LCD_COLOR
static bool set_option_grayscale(void)
{
bool gray = settings.jpeg_colour_mode == COLOURMODE_GRAY;
- rb->set_bool("Grayscale", &gray);
+ rb->set_bool("Grayscale (Jpeg)", &gray);
settings.jpeg_colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR;
return false;
}
@@ -204,14 +223,14 @@ static bool set_option_dithering(void)
[DITHER_DIFFUSION] = { "Diffusion", -1 },
};
- rb->set_option("Dithering", &settings.jpeg_dither_mode, INT,
+ rb->set_option("Dithering (Jpeg)", &settings.jpeg_dither_mode, INT,
dithering, DITHER_NUM_MODES, NULL);
return false;
}
-MENUITEM_FUNCTION(grayscale_item, 0, "Greyscale",
+MENUITEM_FUNCTION(grayscale_item, 0, "Greyscale (Jpeg)",
set_option_grayscale, NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(dithering_item, 0, "Dithering",
+MENUITEM_FUNCTION(dithering_item, 0, "Dithering (Jpeg)",
set_option_dithering, NULL, NULL, Icon_NOICON);
MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON,
&grayscale_item, &dithering_item);
@@ -220,7 +239,7 @@ static void display_options(void)
{
rb->do_menu(&display_menu, NULL, NULL, false);
}
-#endif /* defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) */
+#endif /* HAVE_LCD_COLOR */
static int show_menu(void) /* return 1 to quit */
{
@@ -234,19 +253,19 @@ static int show_menu(void) /* return 1 to quit */
#ifdef USE_PLUG_BUF
MIID_SHOW_PLAYBACK_MENU,
#endif
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
+#ifdef HAVE_LCD_COLOR
MIID_DISPLAY_OPTIONS,
#endif
MIID_QUIT,
};
- MENUITEM_STRINGLIST(menu, MENU_TITLE, NULL,
+ MENUITEM_STRINGLIST(menu, "Image Viewer Menu", NULL,
"Return", "Toggle Slideshow Mode",
"Change Slideshow Time",
#ifdef USE_PLUG_BUF
"Show Playback Menu",
#endif
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
+#ifdef HAVE_LCD_COLOR
"Display Options",
#endif
"Quit");
@@ -263,7 +282,7 @@ static int show_menu(void) /* return 1 to quit */
case MIID_RETURN:
break;
case MIID_TOGGLE_SS_MODE:
- rb->set_option("Toggle Slideshow", &slideshow_enabled, BOOL,
+ rb->set_option("Toggle Slideshow", &iv_api.slideshow_enabled, BOOL,
slideshow , 2, NULL);
break;
case MIID_CHANGE_SS_MODE:
@@ -274,7 +293,7 @@ static int show_menu(void) /* return 1 to quit */
#ifdef USE_PLUG_BUF
case MIID_SHOW_PLAYBACK_MENU:
- if (plug_buf)
+ if (iv_api.plug_buf)
{
playback_control(NULL);
}
@@ -284,7 +303,7 @@ static int show_menu(void) /* return 1 to quit */
}
break;
#endif
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
+#ifdef HAVE_LCD_COLOR
case MIID_DISPLAY_OPTIONS:
display_options();
break;
@@ -296,10 +315,10 @@ static int show_menu(void) /* return 1 to quit */
#ifdef DISK_SPINDOWN
/* change ata spindown time based on slideshow time setting */
- immediate_ata_off = false;
+ iv_api.immediate_ata_off = false;
rb->storage_spindown(rb->global_settings->disk_spindown);
- if (slideshow_enabled)
+ if (iv_api.slideshow_enabled)
{
if(settings.ss_timeout < 10)
{
@@ -309,7 +328,7 @@ static int show_menu(void) /* return 1 to quit */
else if (!rb->mp3_is_playing())
{
/* slideshow times > 10s and not playing: ata_off after load */
- immediate_ata_off = true;
+ iv_api.immediate_ata_off = true;
}
}
#endif
@@ -344,7 +363,7 @@ static int ask_and_get_audio_buffer(const char *filename)
switch(button)
{
case IMGVIEW_ZOOM_IN:
- plug_buf = false;
+ iv_api.plug_buf = false;
buf = rb->plugin_get_audio_buffer(&buf_size);
/*try again this file, now using the audio buffer */
return PLUGIN_OTHER;
@@ -382,15 +401,15 @@ static int ask_and_get_audio_buffer(const char *filename)
#endif /* USE_PLUG_BUF */
/* callback updating a progress meter while image decoding */
-void cb_progress(int current, int total)
+static void cb_progress(int current, int total)
{
rb->yield(); /* be nice to the other threads */
#ifndef USEGSLIB
/* in slideshow mode, keep gui interference to a minimum */
- const int size = (!running_slideshow ? 8 : 4);
+ const int size = (!iv_api.running_slideshow ? 8 : 4);
#else
const int size = 8;
- if(!running_slideshow)
+ if(!iv_api.running_slideshow)
#endif
{
rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],
@@ -414,7 +433,8 @@ static void pan_view_right(struct image_info *info)
{
mylcd_ub_scroll_left(move); /* scroll left */
info->x += move;
- draw_image_rect(info, LCD_WIDTH - move, 0, move, info->height-info->y);
+ imgdec->draw_image_rect(info, LCD_WIDTH - move, 0,
+ move, info->height-info->y);
mylcd_ub_update();
}
}
@@ -430,7 +450,7 @@ static void pan_view_left(struct image_info *info)
{
mylcd_ub_scroll_right(move); /* scroll right */
info->x -= move;
- draw_image_rect(info, 0, 0, move, info->height-info->y);
+ imgdec->draw_image_rect(info, 0, 0, move, info->height-info->y);
mylcd_ub_update();
}
}
@@ -446,15 +466,16 @@ static void pan_view_up(struct image_info *info)
{
mylcd_ub_scroll_down(move); /* scroll down */
info->y -= move;
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
- if (settings.jpeg_dither_mode == DITHER_DIFFUSION)
+#ifdef HAVE_LCD_COLOR
+ if (image_type == IMAGE_JPEG
+ && settings.jpeg_dither_mode == DITHER_DIFFUSION)
{
/* Draw over the band at the top of the last update
caused by lack of error history on line zero. */
move = MIN(move + 1, info->y + info->height);
}
#endif
- draw_image_rect(info, 0, 0, info->width-info->x, move);
+ imgdec->draw_image_rect(info, 0, 0, info->width-info->x, move);
mylcd_ub_update();
}
}
@@ -470,8 +491,9 @@ static void pan_view_down(struct image_info *info)
{
mylcd_ub_scroll_up(move); /* scroll up */
info->y += move;
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
- if (settings.jpeg_dither_mode == DITHER_DIFFUSION)
+#ifdef HAVE_LCD_COLOR
+ if (image_type == IMAGE_JPEG
+ && settings.jpeg_dither_mode == DITHER_DIFFUSION)
{
/* Save the line that was on the last line of the display
and draw one extra line above then recover the line with
@@ -484,10 +506,12 @@ static void pan_view_down(struct image_info *info)
}
#endif
- draw_image_rect(info, 0, LCD_HEIGHT - move, info->width-info->x, move);
+ imgdec->draw_image_rect(info, 0, LCD_HEIGHT - move,
+ info->width-info->x, move);
-#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER)
- if (settings.jpeg_dither_mode == DITHER_DIFFUSION)
+#ifdef HAVE_LCD_COLOR
+ if (image_type == IMAGE_JPEG
+ && settings.jpeg_dither_mode == DITHER_DIFFUSION)
{
/* Cover the first row drawn with previous image data. */
rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
@@ -507,12 +531,12 @@ static int scroll_bmp(struct image_info *info)
while (true)
{
- if (slideshow_enabled)
+ if (iv_api.slideshow_enabled)
button = rb->button_get_w_tmo(settings.ss_timeout * HZ);
else
button = rb->button_get(true);
- running_slideshow = false;
+ iv_api.running_slideshow = false;
switch(button)
{
@@ -543,16 +567,16 @@ static int scroll_bmp(struct image_info *info)
break;
case BUTTON_NONE:
- if (slideshow_enabled && entries > 1)
+ if (iv_api.slideshow_enabled && entries > 1)
{
- running_slideshow = true;
+ iv_api.running_slideshow = true;
return change_filename(DIR_NEXT);
}
break;
#ifdef IMGVIEW_SLIDE_SHOW
case IMGVIEW_SLIDE_SHOW:
- slideshow_enabled = !slideshow_enabled;
+ iv_api.slideshow_enabled = !iv_api.slideshow_enabled;
break;
#endif
@@ -605,7 +629,7 @@ static int scroll_bmp(struct image_info *info)
#ifdef USEGSLIB
grey_show(true); /* switch on greyscale overlay */
#else
- draw_image_rect(info, 0, 0,
+ imgdec->draw_image_rect(info, 0, 0,
info->width-info->x, info->height-info->y);
mylcd_ub_update();
#endif
@@ -637,10 +661,10 @@ static int min_downscale(int bufsize)
{
int downscale = 8;
- if (img_mem(8) > bufsize)
+ if (imgdec->img_mem(8) > bufsize)
return 0; /* error, too large, even 1:8 doesn't fit */
- while (downscale > 1 && img_mem(downscale/2) <= bufsize)
+ while (downscale > 1 && imgdec->img_mem(downscale/2) <= bufsize)
downscale /= 2;
return downscale;
@@ -697,18 +721,39 @@ static int load_and_show(char* filename, struct image_info *info)
rb->lcd_clear_display();
+ status = get_image_type(filename);
+ if (image_type != status) /* type of image is changed, load decoder. */
+ {
+ struct loader_info loader_info = {
+ status, &iv_api, decoder_buf, decoder_buf_size,
+ };
+ image_type = status;
+ imgdec = load_decoder(&loader_info);
+ if (imgdec == NULL)
+ {
+ /* something is wrong */
+ return PLUGIN_ERROR;
+ }
+#ifdef USE_PLUG_BUF
+ if(iv_api.plug_buf)
+ {
+ buf = loader_info.buffer;
+ buf_size = loader_info.size;
+ }
+#endif
+ }
rb->memset(info, 0, sizeof(*info));
remaining = buf_size;
if (rb->button_get(false) == IMGVIEW_MENU)
status = PLUGIN_ABORT;
else
- status = load_image(filename, info, buf, &remaining);
+ status = imgdec->load_image(filename, info, buf, &remaining);
if (status == PLUGIN_OUTOFMEM)
{
#ifdef USE_PLUG_BUF
- if(plug_buf)
+ if(iv_api.plug_buf)
{
return ask_and_get_audio_buffer(filename);
}
@@ -734,13 +779,14 @@ static int load_and_show(char* filename, struct image_info *info)
ds_min = min_downscale(remaining); /* check memory constraint */
if (ds_min == 0)
{
-#if UNSCALED_IS_AVAILABLE
- /* Can not resize the image but original one is available, so use it. */
- ds_min = ds_max = 1;
-#else
- /* not enough memory to decode image. */
+ if (imgdec->unscaled_avail)
+ {
+ /* Can not resize the image but original one is available, so use it. */
+ ds_min = ds_max = 1;
+ }
+ else
#ifdef USE_PLUG_BUF
- if(plug_buf)
+ if (iv_api.plug_buf)
{
return ask_and_get_audio_buffer(filename);
}
@@ -751,7 +797,6 @@ static int load_and_show(char* filename, struct image_info *info)
file_pt[curfile] = NULL;
return change_filename(direction);
}
-#endif
}
else if (ds_max < ds_min)
ds_max = ds_min;
@@ -762,7 +807,7 @@ static int load_and_show(char* filename, struct image_info *info)
do /* loop the image prepare and decoding when zoomed */
{
- status = get_image(info, ds); /* decode or fetch from cache */
+ status = imgdec->get_image(info, ds); /* decode or fetch from cache */
if (status == PLUGIN_ERROR)
{
file_pt[curfile] = NULL;
@@ -771,14 +816,14 @@ static int load_and_show(char* filename, struct image_info *info)
set_view(info, cx, cy);
- if(!running_slideshow)
+ if(!iv_api.running_slideshow)
{
rb->lcd_putsf(0, 3, "showing %dx%d", info->width, info->height);
rb->lcd_update();
}
mylcd_ub_clear_display();
- draw_image_rect(info, 0, 0,
+ imgdec->draw_image_rect(info, 0, 0,
info->width-info->x, info->height-info->y);
mylcd_ub_update();
@@ -794,18 +839,10 @@ static int load_and_show(char* filename, struct image_info *info)
status = scroll_bmp(info);
if (status == ZOOM_IN)
{
-#if UNSCALED_IS_AVAILABLE
- if (ds > 1)
-#else
- if (ds > ds_min)
-#endif
+ if (ds > ds_min || (imgdec->unscaled_avail && ds > 1))
{
-#if UNSCALED_IS_AVAILABLE
/* if 1/1 is always available, jump ds from ds_min to 1. */
int zoom = (ds == ds_min)? ds_min: 2;
-#else
- const int zoom = 2;
-#endif
ds /= zoom; /* reduce downscaling to zoom in */
get_view(info, &cx, &cy);
cx *= zoom; /* prepare the position in the new image */
@@ -819,12 +856,8 @@ static int load_and_show(char* filename, struct image_info *info)
{
if (ds < ds_max)
{
-#if UNSCALED_IS_AVAILABLE
/* if ds is 1 and ds_min is > 1, jump ds to ds_min. */
int zoom = (ds < ds_min)? ds_min: 2;
-#else
- const int zoom = 2;
-#endif
ds *= zoom; /* increase downscaling to zoom out */
get_view(info, &cx, &cy);
cx /= zoom; /* prepare the position in the new image */
@@ -859,25 +892,24 @@ enum plugin_status plugin_start(const void* parameter)
if(!parameter) return PLUGIN_ERROR;
+ rb->strcpy(np_file, parameter);
+ if (get_image_type(np_file) == IMAGE_UNKNOWN)
+ {
+ rb->splash(HZ*2, "Unsupported file");
+ return PLUGIN_ERROR;
+ }
+
#ifdef USE_PLUG_BUF
buf = rb->plugin_get_buffer(&buf_size);
#else
+ decoder_buf = rb->plugin_get_buffer(&decoder_buf_size);
buf = rb->plugin_get_audio_buffer(&buf_size);
#endif
- rb->strcpy(np_file, parameter);
get_pic_list();
if(!entries) return PLUGIN_ERROR;
-#ifdef USE_PLUG_BUF
- if(!rb->audio_status())
- {
- plug_buf = false;
- buf = rb->plugin_get_audio_buffer(&buf_size);
- }
-#endif
-
#ifdef USEGSLIB
if (!grey_init(buf, buf_size, GREY_ON_COP,
LCD_WIDTH, LCD_HEIGHT, &greysize))
@@ -889,6 +921,16 @@ enum plugin_status plugin_start(const void* parameter)
buf_size -= greysize;
#endif
+#ifdef USE_PLUG_BUF
+ decoder_buf = buf;
+ decoder_buf_size = buf_size;
+ if(!rb->audio_status())
+ {
+ iv_api.plug_buf = false;
+ buf = rb->plugin_get_audio_buffer(&buf_size);
+ }
+#endif
+
/* should be ok to just load settings since the plugin itself has
just been loaded from disk and the drive should be spinning */
configfile_load(IMGVIEW_CONFIGFILE, config,
@@ -908,6 +950,7 @@ enum plugin_status plugin_start(const void* parameter)
{
condition = load_and_show(np_file, &image_info);
} while (condition >= PLUGIN_OTHER);
+ release_decoder();
if (rb->memcmp(&settings, &old_settings, sizeof (settings)))
{
diff --git a/apps/plugins/imageviewer/imageviewer.h b/apps/plugins/imageviewer/imageviewer.h
index da2bbfe45c..8e838def08 100644
--- a/apps/plugins/imageviewer/imageviewer.h
+++ b/apps/plugins/imageviewer/imageviewer.h
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * user intereface of image viewers (jpeg, png, etc.)
+ * user intereface of image viewer.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,8 +19,8 @@
*
****************************************************************************/
-#ifndef _IMGVIEW_IMGVIEW_H
-#define _IMGVIEW_IMGVIEW_H
+#ifndef _IMAGE_VIEWER_H
+#define _IMAGE_VIEWER_H
#include "plugin.h"
@@ -384,6 +384,13 @@
#include <lib/mylcd.h>
+#if defined(USEGSLIB) && defined(IMGDEC)
+#undef mylcd_ub_
+#undef myxlcd_ub_
+#define mylcd_ub_(fn) iv->fn
+#define myxlcd_ub_(fn) iv->fn
+#endif
+
/* Min memory allowing us to use the plugin buffer
* and thus not stopping the music
* *Very* rough estimation:
@@ -413,7 +420,6 @@ enum {
/* Settings. jpeg needs these */
struct imgview_settings
{
- /* include all settings for varias decoders as using same setting file. */
#ifdef HAVE_LCD_COLOR
int jpeg_colour_mode;
int jpeg_dither_mode;
@@ -421,7 +427,7 @@ struct imgview_settings
int ss_timeout;
};
-/* structure passed to decoder. */
+/* structure passed to image decoder. */
struct image_info {
int x_size, y_size; /* set size of loaded image in load_image(). */
int width, height; /* set size of resized image in get_image(). */
@@ -429,34 +435,78 @@ struct image_info {
void *data; /* use freely in decoder. not touched in ui. */
};
-/* callback updating a progress meter while image decoding */
-extern void cb_progress(int current, int total);
-
-extern struct imgview_settings settings;
-extern bool slideshow_enabled;
-extern bool running_slideshow;
+struct imgdec_api {
+ const struct imgview_settings *settings;
+ bool slideshow_enabled; /* run slideshow */
+ bool running_slideshow; /* loading image because of slideshw */
#ifdef DISK_SPINDOWN
-extern bool immediate_ata_off;
+ bool immediate_ata_off; /* power down disk after loading */
#endif
#ifdef USE_PLUG_BUF
-extern bool plug_buf;
+ bool plug_buf; /* are we using the plugin buffer or the audio buffer? */
#endif
+ /* callback updating a progress meter while image decoding */
+ void (*cb_progress)(int current, int total);
+
+#ifdef USEGSLIB
+ void (*gray_bitmap_part)(const unsigned char *src, int src_x, int src_y,
+ int stride, int x, int y, int width, int height);
+#endif
+};
+
/* functions need to be implemented in each image decoders. */
-/* return true if ext is supported by the decoder. */
-extern bool img_ext(const char *ext);
-/* return needed size of buffer to store downscaled image by ds */
-extern int img_mem(int ds);
-/* load image from filename. set width and height of info properly. also, set
- * buf_size to remaining size of buf after load image. it is used to caluclate
- * min downscale. */
-extern int load_image(char *filename, struct image_info *info,
+struct image_decoder {
+ /* if unscaled image can be always displayed when there isn't enough memory
+ * for resized image. e.g. when using native format to store image. */
+ const bool unscaled_avail;
+
+ /* return needed size of buffer to store downscaled image by ds */
+ int (*img_mem)(int ds);
+ /* load image from filename. set width and height of info properly. also, set
+ * buf_size to remaining size of buf after load image. it is used to caluclate
+ * min downscale. */
+ int (*load_image)(char *filename, struct image_info *info,
unsigned char *buf, ssize_t *buf_size);
-/* downscale loaded image by ds. note that buf to store reszied image is not
- * provided. return PLUGIN_ERROR for error. ui will skip to next image. */
-extern int get_image(struct image_info *info, int ds);
-/* draw part of image */
-extern void draw_image_rect(struct image_info *info,
+ /* downscale loaded image by ds. note that buf to store reszied image is not
+ * provided. return PLUGIN_ERROR for error. ui will skip to next image. */
+ int (*get_image)(struct image_info *info, int ds);
+ /* draw part of image */
+ void (*draw_image_rect)(struct image_info *info,
int x, int y, int width, int height);
+};
+
+#define IMGDEC_API_VERSION (PLUGIN_API_VERSION << 4 | 0)
+
+/* image decoder header */
+struct imgdec_header {
+ struct lc_header lc_hdr; /* must be the first */
+ const struct image_decoder *decoder;
+ const struct plugin_api **api;
+ const struct imgdec_api **img_api;
+};
+
+#ifdef IMGDEC
+extern const struct imgdec_api *iv;
+extern const struct image_decoder image_decoder;
+
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+#define IMGDEC_HEADER \
+ const struct plugin_api *rb DATA_ATTR; \
+ const struct imgdec_api *iv DATA_ATTR; \
+ const struct imgdec_header __header \
+ __attribute__ ((section (".header")))= { \
+ { PLUGIN_MAGIC, TARGET_ID, IMGDEC_API_VERSION, \
+ plugin_start_addr, plugin_end_addr }, &image_decoder, &rb, &iv };
+#else /* PLATFORM_HOSTED */
+#define IMGDEC_HEADER \
+ const struct plugin_api *rb DATA_ATTR; \
+ const struct imgdec_api *iv DATA_ATTR; \
+ const struct imgdec_header __header \
+ __attribute__((visibility("default"))) = { \
+ { PLUGIN_MAGIC, TARGET_ID, IMGDEC_API_VERSION, \
+ NULL, NULL }, &image_decoder, &rb, &iv };
+#endif /* CONFIG_PLATFORM */
+#endif
-#endif /* _IMGVIEW_IMGVIEW_H */
+#endif /* _IMAGE_VIEWER_H */
diff --git a/apps/plugins/imageviewer/imageviewer.make b/apps/plugins/imageviewer/imageviewer.make
index 76af8d24e5..d06bbfd571 100644
--- a/apps/plugins/imageviewer/imageviewer.make
+++ b/apps/plugins/imageviewer/imageviewer.make
@@ -10,7 +10,50 @@
IMGVSRCDIR := $(APPSDIR)/plugins/imageviewer
IMGVBUILDDIR := $(BUILDDIR)/apps/plugins/imageviewer
-# include actual viewer's make file
+ROCKS += $(IMGVBUILDDIR)/imageviewer.rock
+
+IMGV_SRC := $(call preprocess, $(IMGVSRCDIR)/SOURCES)
+IMGV_OBJ := $(call c2obj, $(IMGV_SRC))
+
+# add source files to OTHER_SRC to get automatic dependencies
+OTHER_SRC += $(IMGV_SRC)
+
+$(IMGVBUILDDIR)/imageviewer.rock: $(IMGV_OBJ)
+
+IMGDECFLAGS = $(PLUGINFLAGS) -DIMGDEC
+
+# include decoder's make from each subdir
IMGVSUBDIRS := $(call preprocess, $(IMGVSRCDIR)/SUBDIRS)
$(foreach dir,$(IMGVSUBDIRS),$(eval include $(dir)/$(notdir $(dir)).make))
+IMGDECLDFLAGS = -T$(PLUGINLINK_LDS) -Wl,--gc-sections -Wl,-Map,$(IMGVBUILDDIR)/$*.refmap
+
+ifndef APP_TYPE
+ IMGDEC_OUTLDS = $(IMGVBUILDDIR)/%.link
+ IMGDEC_OVLFLAGS = -T$(IMGVBUILDDIR)/$*.link -Wl,--gc-sections -Wl,-Map,$(IMGVBUILDDIR)/$*.map
+else
+ IMGDEC_OVLFLAGS = $(PLUGINLDFLAGS)
+endif
+
+$(IMGVBUILDDIR)/%.ovl: $(IMGDEC_OUTLDS)
+ $(call PRINTS,LD $(@F))$(CC) $(IMGDECFLAGS) -o $(IMGVBUILDDIR)/$*.elf \
+ $(filter-out $(PLUGIN_CRT0),$(filter %.o, $^)) \
+ $(filter %.a, $+) \
+ -lgcc $(IMGDEC_OVLFLAGS)
+ifdef APP_TYPE
+ $(SILENT)cp $(IMGVBUILDDIR)/$*.elf $@
+else
+ $(SILENT)$(OC) -O binary $(IMGVBUILDDIR)/$*.elf $@
+endif
+
+# rule to create reference map for image decoder
+$(IMGVBUILDDIR)/%.refmap: $(APPSDIR)/plugin.h $(IMGVSRCDIR)/imageviewer.h $(PLUGINLINK_LDS) $(PLUGINLIB) $(PLUGINBITMAPLIB)
+ $(call PRINTS,LD $(@F))$(CC) $(IMGDECFLAGS) -o /dev/null \
+ $(filter %.o, $^) \
+ $(filter %.a, $+) \
+ -lgcc $(IMGDECLDFLAGS)
+
+$(IMGVBUILDDIR)/%.link: $(PLUGIN_LDS) $(IMGVBUILDDIR)/%.refmap
+ $(call PRINTS,PP $(@F))$(call preprocess2file,$<,$@,-DIMGVDECODER_OFFSET=$(shell \
+ $(TOOLSDIR)/ovl_offset.pl $(IMGVBUILDDIR)/$*.refmap))
+
diff --git a/apps/plugins/imageviewer/jpeg/SOURCES b/apps/plugins/imageviewer/jpeg/SOURCES
index 8e80722a5a..c3524001e2 100644
--- a/apps/plugins/imageviewer/jpeg/SOURCES
+++ b/apps/plugins/imageviewer/jpeg/SOURCES
@@ -1,4 +1,3 @@
-jpeg_ui.c
jpeg.c
jpeg_decoder.c
#ifdef HAVE_LCD_COLOR
diff --git a/apps/plugins/imageviewer/jpeg/jpeg.c b/apps/plugins/imageviewer/jpeg/jpeg.c
index 5f69cc7f51..511a7054e1 100644
--- a/apps/plugins/imageviewer/jpeg/jpeg.c
+++ b/apps/plugins/imageviewer/jpeg/jpeg.c
@@ -69,20 +69,8 @@ static struct jpeg jpg; /* too large for stack */
/************************* Implementation ***************************/
-bool img_ext(const char *ext)
-{
- if(!ext)
- return false;
- if(!rb->strcasecmp(ext,".jpg") ||
- !rb->strcasecmp(ext,".jpe") ||
- !rb->strcasecmp(ext,".jpeg"))
- return true;
- else
- return false;
-}
-
-void draw_image_rect(struct image_info *info,
- int x, int y, int width, int height)
+static void draw_image_rect(struct image_info *info,
+ int x, int y, int width, int height)
{
struct t_disp* pdisp = (struct t_disp*)info->data;
#ifdef HAVE_LCD_COLOR
@@ -92,7 +80,7 @@ void draw_image_rect(struct image_info *info,
x + MAX(0, (LCD_WIDTH - info->width) / 2),
y + MAX(0, (LCD_HEIGHT - info->height) / 2),
width, height,
- settings.jpeg_colour_mode, settings.jpeg_dither_mode);
+ iv->settings->jpeg_colour_mode, iv->settings->jpeg_dither_mode);
#else
mylcd_ub_gray_bitmap_part(
pdisp->bitmap[0], info->x + x, info->y + y, pdisp->stride,
@@ -102,7 +90,7 @@ void draw_image_rect(struct image_info *info,
#endif
}
-int img_mem(int ds)
+static int img_mem(int ds)
{
int size;
struct jpeg *p_jpg = &jpg;
@@ -121,8 +109,8 @@ int img_mem(int ds)
return size;
}
-int load_image(char *filename, struct image_info *info,
- unsigned char *buf, ssize_t *buf_size)
+static int load_image(char *filename, struct image_info *info,
+ unsigned char *buf, ssize_t *buf_size)
{
int fd;
int filesize;
@@ -154,7 +142,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OUTOFMEM;
}
- if(!running_slideshow)
+ if(!iv->running_slideshow)
{
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_putsf(0, 1, "loading %d bytes", filesize);
@@ -164,13 +152,13 @@ int load_image(char *filename, struct image_info *info,
rb->read(fd, buf_jpeg, filesize);
rb->close(fd);
- if(!running_slideshow)
+ if(!iv->running_slideshow)
{
rb->lcd_puts(0, 2, "decoding markers");
rb->lcd_update();
}
#ifdef DISK_SPINDOWN
- else if(immediate_ata_off)
+ else if(iv->immediate_ata_off)
{
/* running slideshow and time is long enough: power down disk */
rb->storage_sleep();
@@ -190,7 +178,7 @@ int load_image(char *filename, struct image_info *info,
default_huff_tbl(p_jpg); /* use default */
build_lut(p_jpg); /* derive Huffman and other lookup-tables */
- if(!running_slideshow)
+ if(!iv->running_slideshow)
{
rb->lcd_putsf(0, 2, "image %dx%d", p_jpg->x_size, p_jpg->y_size);
rb->lcd_update();
@@ -202,7 +190,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OK;
}
-int get_image(struct image_info *info, int ds)
+static int get_image(struct image_info *info, int ds)
{
int w, h; /* used to center output */
int size; /* decompressed image size */
@@ -262,7 +250,7 @@ int get_image(struct image_info *info, int ds)
buf_images += size;
buf_images_size -= size;
- if(!running_slideshow)
+ if(!iv->running_slideshow)
{
rb->lcd_putsf(0, 3, "decoding %d*%d", info->width, info->height);
rb->lcd_update();
@@ -275,10 +263,10 @@ int get_image(struct image_info *info, int ds)
time = *rb->current_tick;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true);
- status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progress);
+ status = jpeg_decode(p_jpg, p_disp->bitmap, ds, iv->cb_progress);
rb->cpu_boost(false);
#else
- status = jpeg_decode(p_jpg, p_disp->bitmap, ds, cb_progress);
+ status = jpeg_decode(p_jpg, p_disp->bitmap, ds, iv->cb_progress);
#endif
if (status)
{
@@ -287,7 +275,7 @@ int get_image(struct image_info *info, int ds)
}
time = *rb->current_tick - time;
- if(!running_slideshow)
+ if(!iv->running_slideshow)
{
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@@ -297,3 +285,13 @@ int get_image(struct image_info *info, int ds)
return PLUGIN_OK;
}
+
+const struct image_decoder image_decoder = {
+ false,
+ img_mem,
+ load_image,
+ get_image,
+ draw_image_rect,
+};
+
+IMGDEC_HEADER
diff --git a/apps/plugins/imageviewer/jpeg/jpeg.make b/apps/plugins/imageviewer/jpeg/jpeg.make
index caf37fc74c..dd7addca56 100644
--- a/apps/plugins/imageviewer/jpeg/jpeg.make
+++ b/apps/plugins/imageviewer/jpeg/jpeg.make
@@ -10,12 +10,18 @@
JPEGSRCDIR := $(IMGVSRCDIR)/jpeg
JPEGBUILDDIR := $(IMGVBUILDDIR)/jpeg
-ROCKS += $(JPEGBUILDDIR)/jpeg.rock
-
JPEG_SRC := $(call preprocess, $(JPEGSRCDIR)/SOURCES)
JPEG_OBJ := $(call c2obj, $(JPEG_SRC))
-# add source files to OTHER_SRC to get automatic dependencies
OTHER_SRC += $(JPEG_SRC)
-$(JPEGBUILDDIR)/jpeg.rock: $(JPEG_OBJ)
+ROCKS += $(JPEGBUILDDIR)/jpeg.ovl
+
+$(JPEGBUILDDIR)/jpeg.refmap: $(JPEG_OBJ)
+$(JPEGBUILDDIR)/jpeg.link: $(PLUGIN_LDS) $(JPEGBUILDDIR)/jpeg.refmap
+$(JPEGBUILDDIR)/jpeg.ovl: $(JPEG_OBJ)
+
+# special pattern rule for compiling image decoder with extra flags
+$(JPEGBUILDDIR)/%.o: $(JPEGSRCDIR)/%.c $(JPEGSRCDIR)/jpeg.make
+ $(SILENT)mkdir -p $(dir $@)
+ $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(IMGDECFLAGS) -c $< -o $@
diff --git a/apps/plugins/imageviewer/jpeg/jpeg_ui.c b/apps/plugins/imageviewer/jpeg/jpeg_ui.c
deleted file mode 100644
index e7f57c699f..0000000000
--- a/apps/plugins/imageviewer/jpeg/jpeg_ui.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#define JPEG_VIEWER
-#define MENU_TITLE "Jpeg Menu"
-#define UNSCALED_IS_AVAILABLE 0
-
-#include "../imageviewer.c"
diff --git a/apps/plugins/imageviewer/png/SOURCES b/apps/plugins/imageviewer/png/SOURCES
index 8c278b02b9..978150db78 100644
--- a/apps/plugins/imageviewer/png/SOURCES
+++ b/apps/plugins/imageviewer/png/SOURCES
@@ -3,4 +3,3 @@ tinflate.c
tinfzlib.c
png_decoder.c
png.c
-png_ui.c
diff --git a/apps/plugins/imageviewer/png/png.c b/apps/plugins/imageviewer/png/png.c
index 956cad37d8..10404b7c30 100644
--- a/apps/plugins/imageviewer/png/png.c
+++ b/apps/plugins/imageviewer/png/png.c
@@ -50,18 +50,13 @@ static unsigned char *disp_buf;
#define resize_bitmap grey_resize_bitmap
#endif
-bool img_ext(const char *ext)
-{
- if (!ext)
- return false;
- if (!rb->strcasecmp(ext,".png"))
- return true;
- else
- return false;
-}
+#if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED)
+/* hack: fix error "undefined reference to `_grey_info'". */
+GREY_INFO_STRUCT
+#endif /* USEGSLIB */
-void draw_image_rect(struct image_info *info,
- int x, int y, int width, int height)
+static void draw_image_rect(struct image_info *info,
+ int x, int y, int width, int height)
{
unsigned char **pdisp = (unsigned char **)info->data;
@@ -80,7 +75,7 @@ void draw_image_rect(struct image_info *info,
#endif
}
-int img_mem(int ds)
+static int img_mem(int ds)
{
LodePNG_Decoder *p_decoder = &decoder;
@@ -93,8 +88,8 @@ int img_mem(int ds)
#endif
}
-int load_image(char *filename, struct image_info *info,
- unsigned char *buf, ssize_t *buf_size)
+static int load_image(char *filename, struct image_info *info,
+ unsigned char *buf, ssize_t *buf_size)
{
int fd;
long time = 0; /* measured ticks */
@@ -122,7 +117,7 @@ int load_image(char *filename, struct image_info *info,
DEBUGF("reading file '%s'\n", filename);
- if (!running_slideshow) {
+ if (!iv->running_slideshow) {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_update();
}
@@ -132,7 +127,7 @@ int load_image(char *filename, struct image_info *info,
rb->close(fd);
} else {
- if (!running_slideshow) {
+ if (!iv->running_slideshow) {
rb->lcd_putsf(0, 1, "loading %zu bytes", file_size);
rb->lcd_update();
}
@@ -142,12 +137,12 @@ int load_image(char *filename, struct image_info *info,
rb->read(fd, image, file_size);
rb->close(fd);
- if (!running_slideshow) {
+ if (!iv->running_slideshow) {
rb->lcd_puts(0, 2, "decoding image");
rb->lcd_update();
}
#ifdef DISK_SPINDOWN
- else if (immediate_ata_off) {
+ else if (iv->immediate_ata_off) {
/* running slideshow and time is long enough: power down disk */
rb->storage_sleep();
}
@@ -167,7 +162,7 @@ int load_image(char *filename, struct image_info *info,
if (!p_decoder->error) {
- if (!running_slideshow) {
+ if (!iv->running_slideshow) {
rb->lcd_putsf(0, 2, "image %dx%d",
p_decoder->infoPng.width,
p_decoder->infoPng.height);
@@ -181,16 +176,16 @@ int load_image(char *filename, struct image_info *info,
time = *rb->current_tick;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true);
- LodePNG_decode(p_decoder, image, file_size, cb_progress);
+ LodePNG_decode(p_decoder, image, file_size, iv->cb_progress);
rb->cpu_boost(false);
#else
- LodePNG_decode(p_decoder, image, file_size, cb_progress);
+ LodePNG_decode(p_decoder, image, file_size, iv->cb_progress);
#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
time = *rb->current_tick - time;
}
}
- if (!running_slideshow && !p_decoder->error)
+ if (!iv->running_slideshow && !p_decoder->error)
{
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@@ -200,7 +195,7 @@ int load_image(char *filename, struct image_info *info,
if (p_decoder->error) {
#ifdef USE_PLUG_BUF
- if (plug_buf && (p_decoder->error == FILE_TOO_LARGE ||
+ if (iv->plug_buf && (p_decoder->error == FILE_TOO_LARGE ||
p_decoder->error == OUT_OF_MEMORY ||
p_decoder->error == TINF_DATA_ERROR))
return PLUGIN_OUTOFMEM;
@@ -244,7 +239,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OK;
}
-int get_image(struct image_info *info, int ds)
+static int get_image(struct image_info *info, int ds)
{
unsigned char **p_disp = &disp[ds]; /* short cut */
LodePNG_Decoder *p_decoder = &decoder;
@@ -261,7 +256,7 @@ int get_image(struct image_info *info, int ds)
/* assign image buffer */
if (ds > 1) {
- if (!running_slideshow)
+ if (!iv->running_slideshow)
{
rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
rb->lcd_update();
@@ -303,3 +298,13 @@ int get_image(struct image_info *info, int ds)
return PLUGIN_OK;
}
+
+const struct image_decoder image_decoder = {
+ true,
+ img_mem,
+ load_image,
+ get_image,
+ draw_image_rect,
+};
+
+IMGDEC_HEADER
diff --git a/apps/plugins/imageviewer/png/png.make b/apps/plugins/imageviewer/png/png.make
index 0a7106d2a9..dee89acb71 100644
--- a/apps/plugins/imageviewer/png/png.make
+++ b/apps/plugins/imageviewer/png/png.make
@@ -10,18 +10,19 @@
PNGSRCDIR := $(IMGVSRCDIR)/png
PNGBUILDDIR := $(IMGVBUILDDIR)/png
-ROCKS += $(PNGBUILDDIR)/png.rock
-
PNG_SRC := $(call preprocess, $(PNGSRCDIR)/SOURCES)
PNG_OBJ := $(call c2obj, $(PNG_SRC))
-# add source files to OTHER_SRC to get automatic dependencies
OTHER_SRC += $(PNG_SRC)
-# Use -O3 for png plugin : it gives a bigger file but very good performances
-PNGFLAGS = $(PLUGINFLAGS) -Os
+ROCKS += $(PNGBUILDDIR)/png.ovl
-$(PNGBUILDDIR)/png.rock: $(PNG_OBJ)
+$(PNGBUILDDIR)/png.refmap: $(PNG_OBJ)
+$(PNGBUILDDIR)/png.link: $(PNG_OBJ) $(PNGBUILDDIR)/png.refmap
+$(PNGBUILDDIR)/png.ovl: $(PNG_OBJ)
+
+# Use -O3 for png plugin : it gives a bigger file but very good performances
+PNGFLAGS = $(IMGDECFLAGS) -Os
# Compile PNG plugin with extra flags (adapted from ZXBox)
$(PNGBUILDDIR)/%.o: $(PNGSRCDIR)/%.c $(PNGSRCDIR)/png.make
diff --git a/apps/plugins/imageviewer/png/png_ui.c b/apps/plugins/imageviewer/png/png_ui.c
deleted file mode 100644
index 5dbf526ba1..0000000000
--- a/apps/plugins/imageviewer/png/png_ui.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#define PNG_VIEWER
-#define MENU_TITLE "Png Menu"
-#define UNSCALED_IS_AVAILABLE 1
-
-#include "../imageviewer.c"
diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds
index 2f11bd1235..f4bd64df35 100644
--- a/apps/plugins/plugin.lds
+++ b/apps/plugins/plugin.lds
@@ -181,6 +181,9 @@ OUTPUT_FORMAT(elf32-littlemips)
#elif defined OVERLAY_OFFSET
#define THIS_LENGTH (DRAMSIZE - OVERLAY_OFFSET)
#define THIS_ORIGIN (DRAMORIG + OVERLAY_OFFSET)
+#elif defined IMGVDECODER_OFFSET
+#define THIS_LENGTH (PLUGIN_LENGTH - IMGVDECODER_OFFSET)
+#define THIS_ORIGIN (PLUGIN_ORIGIN + IMGVDECODER_OFFSET)
#else /* plugin */
#define THIS_LENGTH PLUGIN_LENGTH
#define THIS_ORIGIN PLUGIN_ORIGIN
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index aa8b51b478..e0ebdbb496 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -13,11 +13,11 @@ ch8,viewers/chip8,0
txt,viewers/text_viewer,1
nfo,viewers/text_viewer,1
txt,apps/text_editor,2
-bmp,viewers/bmp,2
-jpg,viewers/jpeg,2
-jpe,viewers/jpeg,2
-jpeg,viewers/jpeg,2
-png,viewers/png,2
+bmp,viewers/imageviewer,2
+jpg,viewers/imageviewer,2
+jpe,viewers/imageviewer,2
+jpeg,viewers/imageviewer,2
+png,viewers/imageviewer,2
ucl,viewers/rockbox_flash,3
rvf,viewers/video,4
mp3,viewers/vbrfix,5