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
This commit is contained in:
Teruaki Kawashima 2010-11-21 13:47:56 +00:00
parent eef21cb18a
commit e5b1a7d423
26 changed files with 582 additions and 478 deletions

View file

@ -35,6 +35,7 @@ frotz,viewers
goban,games goban,games
greyscale,demos greyscale,demos
helloworld,demos helloworld,demos
imageviewer,viewers
invadrox,games invadrox,games
iriver_flash,apps iriver_flash,apps
iriverify,viewers iriverify,viewers

View file

@ -0,0 +1,2 @@
imageviewer.c
image_decoder.c

View file

@ -1,2 +1 @@
bmp_ui.c
bmp.c bmp.c

View file

@ -65,17 +65,12 @@ struct bitmap bmp;
/************************* Implementation ***************************/ /************************* Implementation ***************************/
bool img_ext(const char *ext) #if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED)
{ /* hack: fix error "undefined reference to `_grey_info'". */
if (!ext) GREY_INFO_STRUCT
return false; #endif /* USEGSLIB */
if (!rb->strcasecmp(ext,".bmp"))
return true;
else
return false;
}
void draw_image_rect(struct image_info *info, static void draw_image_rect(struct image_info *info,
int x, int y, int width, int height) int x, int y, int width, int height)
{ {
struct t_disp* pdisp = (struct t_disp*)info->data; struct t_disp* pdisp = (struct t_disp*)info->data;
@ -95,7 +90,7 @@ void draw_image_rect(struct image_info *info,
#endif #endif
} }
int img_mem(int ds) static int img_mem(int ds)
{ {
#ifndef USEGSLIB #ifndef USEGSLIB
return (bmp.width/ds) * (bmp.height/ds) * sizeof (fb_data); return (bmp.width/ds) * (bmp.height/ds) * sizeof (fb_data);
@ -104,7 +99,7 @@ int img_mem(int ds)
#endif #endif
} }
int load_image(char *filename, struct image_info *info, static int load_image(char *filename, struct image_info *info,
unsigned char *buf, ssize_t *buf_size) unsigned char *buf, ssize_t *buf_size)
{ {
int w, h; /* used to center output */ int w, h; /* used to center output */
@ -147,7 +142,7 @@ int load_image(char *filename, struct image_info *info,
} }
#endif #endif
#ifdef USE_PLUG_BUF #ifdef USE_PLUG_BUF
if (!plug_buf) if (!iv->plug_buf)
#endif #endif
{ {
while (size > *buf_size && bmp.width >= 2 && bmp.height >= 2 && ds < 8) 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; return PLUGIN_OUTOFMEM;
} }
if (!running_slideshow) if (!iv->running_slideshow)
{ {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_putsf(0, 1, "loading %dx%d%s", 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; return PLUGIN_ERROR;
} }
if (!running_slideshow) if (!iv->running_slideshow)
{ {
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ 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(); rb->lcd_update();
} }
#ifdef DISK_SPINDOWN #ifdef DISK_SPINDOWN
else if (immediate_ata_off) else if(iv->immediate_ata_off)
{ {
/* running slideshow and time is long enough: power down disk */ /* running slideshow and time is long enough: power down disk */
rb->storage_sleep(); rb->storage_sleep();
@ -223,7 +218,7 @@ int load_image(char *filename, struct image_info *info,
buf_images = buf_root = buf + size; buf_images = buf_root = buf + size;
buf_images_size = root_size = *buf_size - 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_putsf(0, 2, "image %dx%d", bmp.width, bmp.height);
rb->lcd_update(); rb->lcd_update();
@ -235,7 +230,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OK; 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 */ 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;
buf_images_size -= 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_putsf(0, 3, "resizing %d*%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();
@ -294,3 +289,13 @@ int get_image(struct image_info *info, int ds)
return PLUGIN_OK; return PLUGIN_OK;
} }
const struct image_decoder image_decoder = {
true,
img_mem,
load_image,
get_image,
draw_image_rect,
};
IMGDEC_HEADER

View file

@ -10,12 +10,18 @@
BMPSRCDIR := $(IMGVSRCDIR)/bmp BMPSRCDIR := $(IMGVSRCDIR)/bmp
BMPBUILDDIR := $(IMGVBUILDDIR)/bmp BMPBUILDDIR := $(IMGVBUILDDIR)/bmp
ROCKS += $(BMPBUILDDIR)/bmp.rock
BMP_SRC := $(call preprocess, $(BMPSRCDIR)/SOURCES) BMP_SRC := $(call preprocess, $(BMPSRCDIR)/SOURCES)
BMP_OBJ := $(call c2obj, $(BMP_SRC)) BMP_OBJ := $(call c2obj, $(BMP_SRC))
# add source files to OTHER_SRC to get automatic dependencies
OTHER_SRC += $(BMP_SRC) 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 $@

View file

@ -1,5 +0,0 @@
#define BMP_VIEWER
#define MENU_TITLE "BMP Menu"
#define UNSCALED_IS_AVAILABLE 1
#include "../imageviewer.c"

View file

@ -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;
}
}

View file

@ -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 */

View file

@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/ * \/ \/ \/ \/ \/
* $Id$ * $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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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 "plugin.h"
#include <lib/playback_control.h> #include <lib/playback_control.h>
#include <lib/helper.h> #include <lib/helper.h>
#include <lib/configfile.h> #include <lib/configfile.h>
#include "imageviewer.h" #include "imageviewer.h"
#include "image_decoder.h"
@ -38,16 +43,6 @@ GREY_INFO_STRUCT
/******************************* Globals ***********************************/ /******************************* 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 */ /* Persistent configuration */
#define IMGVIEW_CONFIGFILE "imageviewer.cfg" #define IMGVIEW_CONFIGFILE "imageviewer.cfg"
#define IMGVIEW_SETTINGS_MINVERSION 1 #define IMGVIEW_SETTINGS_MINVERSION 1
@ -63,8 +58,7 @@ bool plug_buf = true;
#include "jpeg/yuv2rgb.h" #include "jpeg/yuv2rgb.h"
#endif #endif
/* jpeg use this */ static struct imgview_settings settings =
struct imgview_settings settings =
{ {
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
COLOURMODE_COLOUR, COLOURMODE_COLOUR,
@ -86,17 +80,39 @@ static struct configdata config[] =
{ .int_p = &settings.ss_timeout }, "Slideshow Time", NULL }, { .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 ********************/ /**************** begin Application ********************/
/************************* Globals ***************************/ /************************* 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 static fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when
DITHER_DIFFUSION is set */ DITHER_DIFFUSION is set */
#endif #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 */ /* the remaining free part of the buffer for loaded+resized images */
static unsigned char* buf; static unsigned char* buf;
static size_t buf_size; static size_t buf_size;
@ -106,11 +122,14 @@ static struct image_info image_info;
/* the current full file name */ /* the current full file name */
static char np_file[MAX_PATH]; 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 */ /* list of the supported image files */
static char **file_pt; static char **file_pt;
static const struct image_decoder *imgdec = NULL;
static enum image_type image_type = IMAGE_UNKNOWN;
/************************* Implementation ***************************/ /************************* Implementation ***************************/
/* Read directory contents for scrolling. */ /* 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++) for (i = 0; i < tree->filesindir && buf_size > sizeof(char**); i++)
{ {
if (!(dircache[i].attr & ATTR_DIRECTORY) 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; file_pt[entries] = dircache[i].name;
/* Set Selected File. */ /* Set Selected File. */
@ -187,11 +206,11 @@ static void cleanup(void *parameter)
#endif #endif
} }
#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) #ifdef HAVE_LCD_COLOR
static bool set_option_grayscale(void) static bool set_option_grayscale(void)
{ {
bool gray = settings.jpeg_colour_mode == COLOURMODE_GRAY; 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; settings.jpeg_colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR;
return false; return false;
} }
@ -204,14 +223,14 @@ static bool set_option_dithering(void)
[DITHER_DIFFUSION] = { "Diffusion", -1 }, [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); dithering, DITHER_NUM_MODES, NULL);
return false; return false;
} }
MENUITEM_FUNCTION(grayscale_item, 0, "Greyscale", MENUITEM_FUNCTION(grayscale_item, 0, "Greyscale (Jpeg)",
set_option_grayscale, NULL, NULL, Icon_NOICON); 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); set_option_dithering, NULL, NULL, Icon_NOICON);
MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON, MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON,
&grayscale_item, &dithering_item); &grayscale_item, &dithering_item);
@ -220,7 +239,7 @@ static void display_options(void)
{ {
rb->do_menu(&display_menu, NULL, NULL, false); 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 */ 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 #ifdef USE_PLUG_BUF
MIID_SHOW_PLAYBACK_MENU, MIID_SHOW_PLAYBACK_MENU,
#endif #endif
#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) #ifdef HAVE_LCD_COLOR
MIID_DISPLAY_OPTIONS, MIID_DISPLAY_OPTIONS,
#endif #endif
MIID_QUIT, MIID_QUIT,
}; };
MENUITEM_STRINGLIST(menu, MENU_TITLE, NULL, MENUITEM_STRINGLIST(menu, "Image Viewer Menu", NULL,
"Return", "Toggle Slideshow Mode", "Return", "Toggle Slideshow Mode",
"Change Slideshow Time", "Change Slideshow Time",
#ifdef USE_PLUG_BUF #ifdef USE_PLUG_BUF
"Show Playback Menu", "Show Playback Menu",
#endif #endif
#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) #ifdef HAVE_LCD_COLOR
"Display Options", "Display Options",
#endif #endif
"Quit"); "Quit");
@ -263,7 +282,7 @@ static int show_menu(void) /* return 1 to quit */
case MIID_RETURN: case MIID_RETURN:
break; break;
case MIID_TOGGLE_SS_MODE: 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); slideshow , 2, NULL);
break; break;
case MIID_CHANGE_SS_MODE: case MIID_CHANGE_SS_MODE:
@ -274,7 +293,7 @@ static int show_menu(void) /* return 1 to quit */
#ifdef USE_PLUG_BUF #ifdef USE_PLUG_BUF
case MIID_SHOW_PLAYBACK_MENU: case MIID_SHOW_PLAYBACK_MENU:
if (plug_buf) if (iv_api.plug_buf)
{ {
playback_control(NULL); playback_control(NULL);
} }
@ -284,7 +303,7 @@ static int show_menu(void) /* return 1 to quit */
} }
break; break;
#endif #endif
#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) #ifdef HAVE_LCD_COLOR
case MIID_DISPLAY_OPTIONS: case MIID_DISPLAY_OPTIONS:
display_options(); display_options();
break; break;
@ -296,10 +315,10 @@ static int show_menu(void) /* return 1 to quit */
#ifdef DISK_SPINDOWN #ifdef DISK_SPINDOWN
/* change ata spindown time based on slideshow time setting */ /* 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); rb->storage_spindown(rb->global_settings->disk_spindown);
if (slideshow_enabled) if (iv_api.slideshow_enabled)
{ {
if(settings.ss_timeout < 10) if(settings.ss_timeout < 10)
{ {
@ -309,7 +328,7 @@ static int show_menu(void) /* return 1 to quit */
else if (!rb->mp3_is_playing()) else if (!rb->mp3_is_playing())
{ {
/* slideshow times > 10s and not playing: ata_off after load */ /* slideshow times > 10s and not playing: ata_off after load */
immediate_ata_off = true; iv_api.immediate_ata_off = true;
} }
} }
#endif #endif
@ -344,7 +363,7 @@ static int ask_and_get_audio_buffer(const char *filename)
switch(button) switch(button)
{ {
case IMGVIEW_ZOOM_IN: case IMGVIEW_ZOOM_IN:
plug_buf = false; iv_api.plug_buf = false;
buf = rb->plugin_get_audio_buffer(&buf_size); buf = rb->plugin_get_audio_buffer(&buf_size);
/*try again this file, now using the audio buffer */ /*try again this file, now using the audio buffer */
return PLUGIN_OTHER; return PLUGIN_OTHER;
@ -382,15 +401,15 @@ static int ask_and_get_audio_buffer(const char *filename)
#endif /* USE_PLUG_BUF */ #endif /* USE_PLUG_BUF */
/* callback updating a progress meter while image decoding */ /* 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 */ rb->yield(); /* be nice to the other threads */
#ifndef USEGSLIB #ifndef USEGSLIB
/* in slideshow mode, keep gui interference to a minimum */ /* 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 #else
const int size = 8; const int size = 8;
if(!running_slideshow) if(!iv_api.running_slideshow)
#endif #endif
{ {
rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], 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 */ mylcd_ub_scroll_left(move); /* scroll left */
info->x += move; 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(); mylcd_ub_update();
} }
} }
@ -430,7 +450,7 @@ static void pan_view_left(struct image_info *info)
{ {
mylcd_ub_scroll_right(move); /* scroll right */ mylcd_ub_scroll_right(move); /* scroll right */
info->x -= move; 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(); mylcd_ub_update();
} }
} }
@ -446,15 +466,16 @@ static void pan_view_up(struct image_info *info)
{ {
mylcd_ub_scroll_down(move); /* scroll down */ mylcd_ub_scroll_down(move); /* scroll down */
info->y -= move; info->y -= move;
#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) #ifdef HAVE_LCD_COLOR
if (settings.jpeg_dither_mode == DITHER_DIFFUSION) if (image_type == IMAGE_JPEG
&& settings.jpeg_dither_mode == DITHER_DIFFUSION)
{ {
/* Draw over the band at the top of the last update /* Draw over the band at the top of the last update
caused by lack of error history on line zero. */ caused by lack of error history on line zero. */
move = MIN(move + 1, info->y + info->height); move = MIN(move + 1, info->y + info->height);
} }
#endif #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(); mylcd_ub_update();
} }
} }
@ -470,8 +491,9 @@ static void pan_view_down(struct image_info *info)
{ {
mylcd_ub_scroll_up(move); /* scroll up */ mylcd_ub_scroll_up(move); /* scroll up */
info->y += move; info->y += move;
#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) #ifdef HAVE_LCD_COLOR
if (settings.jpeg_dither_mode == DITHER_DIFFUSION) if (image_type == IMAGE_JPEG
&& settings.jpeg_dither_mode == DITHER_DIFFUSION)
{ {
/* Save the line that was on the last line of the display /* Save the line that was on the last line of the display
and draw one extra line above then recover the line with 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 #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) #ifdef HAVE_LCD_COLOR
if (settings.jpeg_dither_mode == DITHER_DIFFUSION) if (image_type == IMAGE_JPEG
&& settings.jpeg_dither_mode == DITHER_DIFFUSION)
{ {
/* Cover the first row drawn with previous image data. */ /* Cover the first row drawn with previous image data. */
rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH,
@ -507,12 +531,12 @@ static int scroll_bmp(struct image_info *info)
while (true) while (true)
{ {
if (slideshow_enabled) if (iv_api.slideshow_enabled)
button = rb->button_get_w_tmo(settings.ss_timeout * HZ); button = rb->button_get_w_tmo(settings.ss_timeout * HZ);
else else
button = rb->button_get(true); button = rb->button_get(true);
running_slideshow = false; iv_api.running_slideshow = false;
switch(button) switch(button)
{ {
@ -543,16 +567,16 @@ static int scroll_bmp(struct image_info *info)
break; break;
case BUTTON_NONE: 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); return change_filename(DIR_NEXT);
} }
break; break;
#ifdef IMGVIEW_SLIDE_SHOW #ifdef IMGVIEW_SLIDE_SHOW
case IMGVIEW_SLIDE_SHOW: case IMGVIEW_SLIDE_SHOW:
slideshow_enabled = !slideshow_enabled; iv_api.slideshow_enabled = !iv_api.slideshow_enabled;
break; break;
#endif #endif
@ -605,7 +629,7 @@ static int scroll_bmp(struct image_info *info)
#ifdef USEGSLIB #ifdef USEGSLIB
grey_show(true); /* switch on greyscale overlay */ grey_show(true); /* switch on greyscale overlay */
#else #else
draw_image_rect(info, 0, 0, imgdec->draw_image_rect(info, 0, 0,
info->width-info->x, info->height-info->y); info->width-info->x, info->height-info->y);
mylcd_ub_update(); mylcd_ub_update();
#endif #endif
@ -637,10 +661,10 @@ static int min_downscale(int bufsize)
{ {
int downscale = 8; 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 */ 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; downscale /= 2;
return downscale; return downscale;
@ -697,18 +721,39 @@ static int load_and_show(char* filename, struct image_info *info)
rb->lcd_clear_display(); 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)); rb->memset(info, 0, sizeof(*info));
remaining = buf_size; remaining = buf_size;
if (rb->button_get(false) == IMGVIEW_MENU) if (rb->button_get(false) == IMGVIEW_MENU)
status = PLUGIN_ABORT; status = PLUGIN_ABORT;
else else
status = load_image(filename, info, buf, &remaining); status = imgdec->load_image(filename, info, buf, &remaining);
if (status == PLUGIN_OUTOFMEM) if (status == PLUGIN_OUTOFMEM)
{ {
#ifdef USE_PLUG_BUF #ifdef USE_PLUG_BUF
if(plug_buf) if(iv_api.plug_buf)
{ {
return ask_and_get_audio_buffer(filename); 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 */ ds_min = min_downscale(remaining); /* check memory constraint */
if (ds_min == 0) if (ds_min == 0)
{ {
#if UNSCALED_IS_AVAILABLE if (imgdec->unscaled_avail)
{
/* Can not resize the image but original one is available, so use it. */ /* Can not resize the image but original one is available, so use it. */
ds_min = ds_max = 1; ds_min = ds_max = 1;
#else }
/* not enough memory to decode image. */ else
#ifdef USE_PLUG_BUF #ifdef USE_PLUG_BUF
if(plug_buf) if (iv_api.plug_buf)
{ {
return ask_and_get_audio_buffer(filename); 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; file_pt[curfile] = NULL;
return change_filename(direction); return change_filename(direction);
} }
#endif
} }
else if (ds_max < ds_min) else if (ds_max < ds_min)
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 */ 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) if (status == PLUGIN_ERROR)
{ {
file_pt[curfile] = NULL; file_pt[curfile] = NULL;
@ -771,14 +816,14 @@ static int load_and_show(char* filename, struct image_info *info)
set_view(info, cx, cy); 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_putsf(0, 3, "showing %dx%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();
} }
mylcd_ub_clear_display(); 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); info->width-info->x, info->height-info->y);
mylcd_ub_update(); mylcd_ub_update();
@ -794,18 +839,10 @@ static int load_and_show(char* filename, struct image_info *info)
status = scroll_bmp(info); status = scroll_bmp(info);
if (status == ZOOM_IN) if (status == ZOOM_IN)
{ {
#if UNSCALED_IS_AVAILABLE if (ds > ds_min || (imgdec->unscaled_avail && ds > 1))
if (ds > 1)
#else
if (ds > ds_min)
#endif
{ {
#if UNSCALED_IS_AVAILABLE
/* if 1/1 is always available, jump ds from ds_min to 1. */ /* if 1/1 is always available, jump ds from ds_min to 1. */
int zoom = (ds == ds_min)? ds_min: 2; int zoom = (ds == ds_min)? ds_min: 2;
#else
const int zoom = 2;
#endif
ds /= zoom; /* reduce downscaling to zoom in */ ds /= zoom; /* reduce downscaling to zoom in */
get_view(info, &cx, &cy); get_view(info, &cx, &cy);
cx *= zoom; /* prepare the position in the new image */ 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 (ds < ds_max)
{ {
#if UNSCALED_IS_AVAILABLE
/* if ds is 1 and ds_min is > 1, jump ds to ds_min. */ /* if ds is 1 and ds_min is > 1, jump ds to ds_min. */
int zoom = (ds < ds_min)? ds_min: 2; int zoom = (ds < ds_min)? ds_min: 2;
#else
const int zoom = 2;
#endif
ds *= zoom; /* increase downscaling to zoom out */ ds *= zoom; /* increase downscaling to zoom out */
get_view(info, &cx, &cy); get_view(info, &cx, &cy);
cx /= zoom; /* prepare the position in the new image */ 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; 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 #ifdef USE_PLUG_BUF
buf = rb->plugin_get_buffer(&buf_size); buf = rb->plugin_get_buffer(&buf_size);
#else #else
decoder_buf = rb->plugin_get_buffer(&decoder_buf_size);
buf = rb->plugin_get_audio_buffer(&buf_size); buf = rb->plugin_get_audio_buffer(&buf_size);
#endif #endif
rb->strcpy(np_file, parameter);
get_pic_list(); get_pic_list();
if(!entries) return PLUGIN_ERROR; 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 #ifdef USEGSLIB
if (!grey_init(buf, buf_size, GREY_ON_COP, if (!grey_init(buf, buf_size, GREY_ON_COP,
LCD_WIDTH, LCD_HEIGHT, &greysize)) LCD_WIDTH, LCD_HEIGHT, &greysize))
@ -889,6 +921,16 @@ enum plugin_status plugin_start(const void* parameter)
buf_size -= greysize; buf_size -= greysize;
#endif #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 /* should be ok to just load settings since the plugin itself has
just been loaded from disk and the drive should be spinning */ just been loaded from disk and the drive should be spinning */
configfile_load(IMGVIEW_CONFIGFILE, config, 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); condition = load_and_show(np_file, &image_info);
} while (condition >= PLUGIN_OTHER); } while (condition >= PLUGIN_OTHER);
release_decoder();
if (rb->memcmp(&settings, &old_settings, sizeof (settings))) if (rb->memcmp(&settings, &old_settings, sizeof (settings)))
{ {

View file

@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/ * \/ \/ \/ \/ \/
* $Id$ * $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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -19,8 +19,8 @@
* *
****************************************************************************/ ****************************************************************************/
#ifndef _IMGVIEW_IMGVIEW_H #ifndef _IMAGE_VIEWER_H
#define _IMGVIEW_IMGVIEW_H #define _IMAGE_VIEWER_H
#include "plugin.h" #include "plugin.h"
@ -384,6 +384,13 @@
#include <lib/mylcd.h> #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 /* Min memory allowing us to use the plugin buffer
* and thus not stopping the music * and thus not stopping the music
* *Very* rough estimation: * *Very* rough estimation:
@ -413,7 +420,6 @@ enum {
/* Settings. jpeg needs these */ /* Settings. jpeg needs these */
struct imgview_settings struct imgview_settings
{ {
/* include all settings for varias decoders as using same setting file. */
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
int jpeg_colour_mode; int jpeg_colour_mode;
int jpeg_dither_mode; int jpeg_dither_mode;
@ -421,7 +427,7 @@ struct imgview_settings
int ss_timeout; int ss_timeout;
}; };
/* structure passed to decoder. */ /* structure passed to image decoder. */
struct image_info { struct image_info {
int x_size, y_size; /* set size of loaded image in load_image(). */ int x_size, y_size; /* set size of loaded image in load_image(). */
int width, height; /* set size of resized image in get_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. */ void *data; /* use freely in decoder. not touched in ui. */
}; };
/* callback updating a progress meter while image decoding */ struct imgdec_api {
extern void cb_progress(int current, int total); const struct imgview_settings *settings;
bool slideshow_enabled; /* run slideshow */
extern struct imgview_settings settings; bool running_slideshow; /* loading image because of slideshw */
extern bool slideshow_enabled;
extern bool running_slideshow;
#ifdef DISK_SPINDOWN #ifdef DISK_SPINDOWN
extern bool immediate_ata_off; bool immediate_ata_off; /* power down disk after loading */
#endif #endif
#ifdef USE_PLUG_BUF #ifdef USE_PLUG_BUF
extern bool plug_buf; bool plug_buf; /* are we using the plugin buffer or the audio buffer? */
#endif #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. */ /* functions need to be implemented in each image decoders. */
/* return true if ext is supported by the decoder. */ struct image_decoder {
extern bool img_ext(const char *ext); /* if unscaled image can be always displayed when there isn't enough memory
/* return needed size of buffer to store downscaled image by ds */ * for resized image. e.g. when using native format to store image. */
extern int img_mem(int ds); const bool unscaled_avail;
/* load image from filename. set width and height of info properly. also, set
/* 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 * buf_size to remaining size of buf after load image. it is used to caluclate
* min downscale. */ * min downscale. */
extern int load_image(char *filename, struct image_info *info, int (*load_image)(char *filename, struct image_info *info,
unsigned char *buf, ssize_t *buf_size); unsigned char *buf, ssize_t *buf_size);
/* downscale loaded image by ds. note that buf to store reszied image is not /* 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. */ * provided. return PLUGIN_ERROR for error. ui will skip to next image. */
extern int get_image(struct image_info *info, int ds); int (*get_image)(struct image_info *info, int ds);
/* draw part of image */ /* draw part of image */
extern void draw_image_rect(struct image_info *info, void (*draw_image_rect)(struct image_info *info,
int x, int y, int width, int height); int x, int y, int width, int height);
};
#endif /* _IMGVIEW_IMGVIEW_H */ #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 /* _IMAGE_VIEWER_H */

View file

@ -10,7 +10,50 @@
IMGVSRCDIR := $(APPSDIR)/plugins/imageviewer IMGVSRCDIR := $(APPSDIR)/plugins/imageviewer
IMGVBUILDDIR := $(BUILDDIR)/apps/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) IMGVSUBDIRS := $(call preprocess, $(IMGVSRCDIR)/SUBDIRS)
$(foreach dir,$(IMGVSUBDIRS),$(eval include $(dir)/$(notdir $(dir)).make)) $(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))

View file

@ -1,4 +1,3 @@
jpeg_ui.c
jpeg.c jpeg.c
jpeg_decoder.c jpeg_decoder.c
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR

View file

@ -69,19 +69,7 @@ static struct jpeg jpg; /* too large for stack */
/************************* Implementation ***************************/ /************************* Implementation ***************************/
bool img_ext(const char *ext) static void draw_image_rect(struct image_info *info,
{
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) int x, int y, int width, int height)
{ {
struct t_disp* pdisp = (struct t_disp*)info->data; struct t_disp* pdisp = (struct t_disp*)info->data;
@ -92,7 +80,7 @@ void draw_image_rect(struct image_info *info,
x + MAX(0, (LCD_WIDTH - info->width) / 2), x + MAX(0, (LCD_WIDTH - info->width) / 2),
y + MAX(0, (LCD_HEIGHT - info->height) / 2), y + MAX(0, (LCD_HEIGHT - info->height) / 2),
width, height, width, height,
settings.jpeg_colour_mode, settings.jpeg_dither_mode); iv->settings->jpeg_colour_mode, iv->settings->jpeg_dither_mode);
#else #else
mylcd_ub_gray_bitmap_part( mylcd_ub_gray_bitmap_part(
pdisp->bitmap[0], info->x + x, info->y + y, pdisp->stride, pdisp->bitmap[0], info->x + x, info->y + y, pdisp->stride,
@ -102,7 +90,7 @@ void draw_image_rect(struct image_info *info,
#endif #endif
} }
int img_mem(int ds) static int img_mem(int ds)
{ {
int size; int size;
struct jpeg *p_jpg = &jpg; struct jpeg *p_jpg = &jpg;
@ -121,7 +109,7 @@ int img_mem(int ds)
return size; return size;
} }
int load_image(char *filename, struct image_info *info, static int load_image(char *filename, struct image_info *info,
unsigned char *buf, ssize_t *buf_size) unsigned char *buf, ssize_t *buf_size)
{ {
int fd; int fd;
@ -154,7 +142,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OUTOFMEM; return PLUGIN_OUTOFMEM;
} }
if(!running_slideshow) if(!iv->running_slideshow)
{ {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_putsf(0, 1, "loading %d bytes", filesize); 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->read(fd, buf_jpeg, filesize);
rb->close(fd); rb->close(fd);
if(!running_slideshow) if(!iv->running_slideshow)
{ {
rb->lcd_puts(0, 2, "decoding markers"); rb->lcd_puts(0, 2, "decoding markers");
rb->lcd_update(); rb->lcd_update();
} }
#ifdef DISK_SPINDOWN #ifdef DISK_SPINDOWN
else if(immediate_ata_off) else if(iv->immediate_ata_off)
{ {
/* running slideshow and time is long enough: power down disk */ /* running slideshow and time is long enough: power down disk */
rb->storage_sleep(); rb->storage_sleep();
@ -190,7 +178,7 @@ int load_image(char *filename, struct image_info *info,
default_huff_tbl(p_jpg); /* use default */ default_huff_tbl(p_jpg); /* use default */
build_lut(p_jpg); /* derive Huffman and other lookup-tables */ 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_putsf(0, 2, "image %dx%d", p_jpg->x_size, p_jpg->y_size);
rb->lcd_update(); rb->lcd_update();
@ -202,7 +190,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OK; 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 w, h; /* used to center output */
int size; /* decompressed image size */ int size; /* decompressed image size */
@ -262,7 +250,7 @@ int get_image(struct image_info *info, int ds)
buf_images += size; buf_images += size;
buf_images_size -= 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_putsf(0, 3, "decoding %d*%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();
@ -275,10 +263,10 @@ int get_image(struct image_info *info, int ds)
time = *rb->current_tick; time = *rb->current_tick;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true); 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); rb->cpu_boost(false);
#else #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 #endif
if (status) if (status)
{ {
@ -287,7 +275,7 @@ int get_image(struct image_info *info, int ds)
} }
time = *rb->current_tick - time; 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->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ 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; return PLUGIN_OK;
} }
const struct image_decoder image_decoder = {
false,
img_mem,
load_image,
get_image,
draw_image_rect,
};
IMGDEC_HEADER

View file

@ -10,12 +10,18 @@
JPEGSRCDIR := $(IMGVSRCDIR)/jpeg JPEGSRCDIR := $(IMGVSRCDIR)/jpeg
JPEGBUILDDIR := $(IMGVBUILDDIR)/jpeg JPEGBUILDDIR := $(IMGVBUILDDIR)/jpeg
ROCKS += $(JPEGBUILDDIR)/jpeg.rock
JPEG_SRC := $(call preprocess, $(JPEGSRCDIR)/SOURCES) JPEG_SRC := $(call preprocess, $(JPEGSRCDIR)/SOURCES)
JPEG_OBJ := $(call c2obj, $(JPEG_SRC)) JPEG_OBJ := $(call c2obj, $(JPEG_SRC))
# add source files to OTHER_SRC to get automatic dependencies
OTHER_SRC += $(JPEG_SRC) 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 $@

View file

@ -1,5 +0,0 @@
#define JPEG_VIEWER
#define MENU_TITLE "Jpeg Menu"
#define UNSCALED_IS_AVAILABLE 0
#include "../imageviewer.c"

View file

@ -3,4 +3,3 @@ tinflate.c
tinfzlib.c tinfzlib.c
png_decoder.c png_decoder.c
png.c png.c
png_ui.c

View file

@ -50,17 +50,12 @@ static unsigned char *disp_buf;
#define resize_bitmap grey_resize_bitmap #define resize_bitmap grey_resize_bitmap
#endif #endif
bool img_ext(const char *ext) #if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED)
{ /* hack: fix error "undefined reference to `_grey_info'". */
if (!ext) GREY_INFO_STRUCT
return false; #endif /* USEGSLIB */
if (!rb->strcasecmp(ext,".png"))
return true;
else
return false;
}
void draw_image_rect(struct image_info *info, static void draw_image_rect(struct image_info *info,
int x, int y, int width, int height) int x, int y, int width, int height)
{ {
unsigned char **pdisp = (unsigned char **)info->data; unsigned char **pdisp = (unsigned char **)info->data;
@ -80,7 +75,7 @@ void draw_image_rect(struct image_info *info,
#endif #endif
} }
int img_mem(int ds) static int img_mem(int ds)
{ {
LodePNG_Decoder *p_decoder = &decoder; LodePNG_Decoder *p_decoder = &decoder;
@ -93,7 +88,7 @@ int img_mem(int ds)
#endif #endif
} }
int load_image(char *filename, struct image_info *info, static int load_image(char *filename, struct image_info *info,
unsigned char *buf, ssize_t *buf_size) unsigned char *buf, ssize_t *buf_size)
{ {
int fd; int fd;
@ -122,7 +117,7 @@ int load_image(char *filename, struct image_info *info,
DEBUGF("reading file '%s'\n", filename); DEBUGF("reading file '%s'\n", filename);
if (!running_slideshow) { if (!iv->running_slideshow) {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_update(); rb->lcd_update();
} }
@ -132,7 +127,7 @@ int load_image(char *filename, struct image_info *info,
rb->close(fd); rb->close(fd);
} else { } else {
if (!running_slideshow) { if (!iv->running_slideshow) {
rb->lcd_putsf(0, 1, "loading %zu bytes", file_size); rb->lcd_putsf(0, 1, "loading %zu bytes", file_size);
rb->lcd_update(); rb->lcd_update();
} }
@ -142,12 +137,12 @@ int load_image(char *filename, struct image_info *info,
rb->read(fd, image, file_size); rb->read(fd, image, file_size);
rb->close(fd); rb->close(fd);
if (!running_slideshow) { if (!iv->running_slideshow) {
rb->lcd_puts(0, 2, "decoding image"); rb->lcd_puts(0, 2, "decoding image");
rb->lcd_update(); rb->lcd_update();
} }
#ifdef DISK_SPINDOWN #ifdef DISK_SPINDOWN
else if (immediate_ata_off) { else if (iv->immediate_ata_off) {
/* running slideshow and time is long enough: power down disk */ /* running slideshow and time is long enough: power down disk */
rb->storage_sleep(); rb->storage_sleep();
} }
@ -167,7 +162,7 @@ int load_image(char *filename, struct image_info *info,
if (!p_decoder->error) { if (!p_decoder->error) {
if (!running_slideshow) { if (!iv->running_slideshow) {
rb->lcd_putsf(0, 2, "image %dx%d", rb->lcd_putsf(0, 2, "image %dx%d",
p_decoder->infoPng.width, p_decoder->infoPng.width,
p_decoder->infoPng.height); p_decoder->infoPng.height);
@ -181,16 +176,16 @@ int load_image(char *filename, struct image_info *info,
time = *rb->current_tick; time = *rb->current_tick;
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true); 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); rb->cpu_boost(false);
#else #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*/ #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
time = *rb->current_tick - time; 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->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ 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) { if (p_decoder->error) {
#ifdef USE_PLUG_BUF #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 == OUT_OF_MEMORY ||
p_decoder->error == TINF_DATA_ERROR)) p_decoder->error == TINF_DATA_ERROR))
return PLUGIN_OUTOFMEM; return PLUGIN_OUTOFMEM;
@ -244,7 +239,7 @@ int load_image(char *filename, struct image_info *info,
return PLUGIN_OK; 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 */ unsigned char **p_disp = &disp[ds]; /* short cut */
LodePNG_Decoder *p_decoder = &decoder; LodePNG_Decoder *p_decoder = &decoder;
@ -261,7 +256,7 @@ int get_image(struct image_info *info, int ds)
/* assign image buffer */ /* assign image buffer */
if (ds > 1) { if (ds > 1) {
if (!running_slideshow) if (!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height); rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();
@ -303,3 +298,13 @@ int get_image(struct image_info *info, int ds)
return PLUGIN_OK; return PLUGIN_OK;
} }
const struct image_decoder image_decoder = {
true,
img_mem,
load_image,
get_image,
draw_image_rect,
};
IMGDEC_HEADER

View file

@ -10,18 +10,19 @@
PNGSRCDIR := $(IMGVSRCDIR)/png PNGSRCDIR := $(IMGVSRCDIR)/png
PNGBUILDDIR := $(IMGVBUILDDIR)/png PNGBUILDDIR := $(IMGVBUILDDIR)/png
ROCKS += $(PNGBUILDDIR)/png.rock
PNG_SRC := $(call preprocess, $(PNGSRCDIR)/SOURCES) PNG_SRC := $(call preprocess, $(PNGSRCDIR)/SOURCES)
PNG_OBJ := $(call c2obj, $(PNG_SRC)) PNG_OBJ := $(call c2obj, $(PNG_SRC))
# add source files to OTHER_SRC to get automatic dependencies
OTHER_SRC += $(PNG_SRC) OTHER_SRC += $(PNG_SRC)
# Use -O3 for png plugin : it gives a bigger file but very good performances ROCKS += $(PNGBUILDDIR)/png.ovl
PNGFLAGS = $(PLUGINFLAGS) -Os
$(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) # Compile PNG plugin with extra flags (adapted from ZXBox)
$(PNGBUILDDIR)/%.o: $(PNGSRCDIR)/%.c $(PNGSRCDIR)/png.make $(PNGBUILDDIR)/%.o: $(PNGSRCDIR)/%.c $(PNGSRCDIR)/png.make

View file

@ -1,5 +0,0 @@
#define PNG_VIEWER
#define MENU_TITLE "Png Menu"
#define UNSCALED_IS_AVAILABLE 1
#include "../imageviewer.c"

View file

@ -181,6 +181,9 @@ OUTPUT_FORMAT(elf32-littlemips)
#elif defined OVERLAY_OFFSET #elif defined OVERLAY_OFFSET
#define THIS_LENGTH (DRAMSIZE - OVERLAY_OFFSET) #define THIS_LENGTH (DRAMSIZE - OVERLAY_OFFSET)
#define THIS_ORIGIN (DRAMORIG + 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 */ #else /* plugin */
#define THIS_LENGTH PLUGIN_LENGTH #define THIS_LENGTH PLUGIN_LENGTH
#define THIS_ORIGIN PLUGIN_ORIGIN #define THIS_ORIGIN PLUGIN_ORIGIN

View file

@ -13,11 +13,11 @@ ch8,viewers/chip8,0
txt,viewers/text_viewer,1 txt,viewers/text_viewer,1
nfo,viewers/text_viewer,1 nfo,viewers/text_viewer,1
txt,apps/text_editor,2 txt,apps/text_editor,2
bmp,viewers/bmp,2 bmp,viewers/imageviewer,2
jpg,viewers/jpeg,2 jpg,viewers/imageviewer,2
jpe,viewers/jpeg,2 jpe,viewers/imageviewer,2
jpeg,viewers/jpeg,2 jpeg,viewers/imageviewer,2
png,viewers/png,2 png,viewers/imageviewer,2
ucl,viewers/rockbox_flash,3 ucl,viewers/rockbox_flash,3
rvf,viewers/video,4 rvf,viewers/video,4
mp3,viewers/vbrfix,5 mp3,viewers/vbrfix,5

View file

@ -1,115 +0,0 @@
% $Id$ %
\subsection{BMP viewer}
This plugin opens \fname{.bmp} files from the \setting{File Browser} to display them\nopt{lcd_color}{ using Rockbox's greyscale library}.
\opt{swcodec}{
\par
\note{
When an audio file is playing the size of the image is limited as
the decoding process needs to share memory with audio tracks. To be able to
view a bigger file you may need to stop playback.}
}
\nopt{large_plugin_buffer}{%
\note{This plugin will cause playback to stop.}%
}%
\begin{btnmap}
\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD%
,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD%
,MROBE100_PAD,PBELL_VIBE500_PAD}
{\ButtonUp\ / \ButtonDown}%
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu\ / \ButtonPlay}%
\opt{IRIVER_H10_PAD}{\ButtonScrollUp\ / \ButtonScrollDown} %
\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD%
,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD%
,MROBE100_PAD,IPOD_4G_PAD,IPOD_3G_PAD,IRIVER_H10_PAD,PBELL_VIBE500_PAD}
{/ \ButtonLeft\ / \ButtonRight}
\opt{COWON_D2_PAD}{}
\opt{HAVEREMOTEKEYMAP}{& }
& Move around in zoomed in image\\
\opt{RECORDER_PAD}{\ButtonPlay}
\opt{ONDIO_PAD,COWON_D2_PAD}{\ButtonMenu}
\opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD%
,SANSA_FUZE_PAD,SANSA_C200_PAD,MROBE100_PAD}{\ButtonSelect}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollFwd}
\opt{IRIVER_H10_PAD}{\ButtonPlay}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolUp}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonUp}
\opt{HAVEREMOTEKEYMAP}{& }
& Zoom in\\
\opt{RECORDER_PAD}{\ButtonOn}
\opt{ONDIO_PAD}{\ButtonMenu+\ButtonDown}
\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollBack}
\opt{IAUDIO_X5_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD}{Long \ButtonSelect}
\opt{IRIVER_H10_PAD}{Long \ButtonPlay}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolDown}
\opt{MROBE100_PAD}{\ButtonPlay}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonDown}
\opt{HAVEREMOTEKEYMAP}{& }
& Zoom out\\
\opt{RECORDER_PAD}{\ButtonFThree}
\opt{ONDIO_PAD}{\ButtonMenu+\ButtonRight}
\opt{IRIVER_H100_PAD}{\ButtonOn}
\opt{IRIVER_H300_PAD}{\ButtonRec}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonRight}
\opt{IAUDIO_X5_PAD}{\ButtonPlay}
\opt{IRIVER_H10_PAD}{\ButtonFF}
\opt{SANSA_E200_PAD,SANSA_FUZE_PAD}{\ButtonScrollFwd}
\opt{SANSA_C200_PAD}{\ButtonVolUp}
\opt{GIGABEAT_PAD}{\ButtonA+\ButtonRight}
\opt{GIGABEAT_S_PAD}{\ButtonNext}
\opt{MROBE100_PAD}{\ButtonDisplay+\ButtonRight}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonRight}
\opt{HAVEREMOTEKEYMAP}{& }
& Next bmp in directory\\
\opt{RECORDER_PAD}{\ButtonFTwo}
\opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft}
\opt{IRIVER_H100_PAD,IAUDIO_X5_PAD}{\ButtonRec}
\opt{IRIVER_H300_PAD}{\ButtonOn}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonLeft}
\opt{IRIVER_H10_PAD}{\ButtonRew}
\opt{SANSA_E200_PAD,SANSA_FUZE_PAD}{\ButtonScrollBack}
\opt{SANSA_C200_PAD}{\ButtonVolDown}
\opt{GIGABEAT_PAD}{\ButtonA+\ButtonLeft}
\opt{GIGABEAT_S_PAD}{\ButtonPrev}
\opt{MROBE100_PAD}{\ButtonDisplay+\ButtonLeft}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonLeft}
\opt{HAVEREMOTEKEYMAP}{& }
& Previous bmp in directory\\
\opt{SANSA_E200_PAD,SANSA_C200_PAD}{%currently only defined for the sansa pads
\ButtonRec
\opt{HAVEREMOTEKEYMAP}{& }
& Toggle slide show mode\\
}
\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonMenu}
\opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD,SANSA_C200_PAD}{\ButtonPower}
\opt{SANSA_FUZE_PAD}{Long \ButtonHome}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,PBELL_VIBE500_PAD}{\ButtonMenu}
\opt{COWON_D2_PAD}{\ButtonPower}
\opt{HAVEREMOTEKEYMAP}{&
\opt{IRIVER_RC_H100_PAD}{\ButtonRCStop}
}
& Show menu / Abort \\
\opt{IPOD_4G_PAD,IPOD_3G_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,PBELL_VIBE500_PAD}{
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonPlay}
\opt{GIGABEAT_PAD,MROBE100_PAD}{\ButtonPower}
\opt{GIGABEAT_S_PAD}{\ButtonBack}
\opt{PBELL_VIBE500_PAD}{\ButtonCancel}
\opt{HAVEREMOTEKEYMAP}{& }
& Quit the viewer \\
}
\end{btnmap}
The menu has the following entries.
\begin{description}
\item[Return.] Returns you to the image
\item[Toggle Slideshow Mode.] Enables or disables the slideshow mode.
\item[Change Slideshow Timeout.] You can set the timeout for the slideshow
between 1 second and 20 seconds.
\opt{large_plugin_buffer}{
\item[Show Playback Menu.] From the playback menu you can control the
playback of the currently loaded playlist and change the volume of your \dap.
}
\item[Quit.] Quits the viewer and returns to the \setting{File Browser}.
\end{description}

View file

@ -1,7 +1,18 @@
% $Id$ % % $Id$ %
\subsection{JPEG viewer} \subsection{Image Viewer}
This plugin opens \fname{.jpeg} files from the \setting{File Browser} to display them\nopt{lcd_color}{ using Rockbox's greyscale library}. This plugin opens image files from the \setting{File Browser} to display them\nopt{lcd_color}{ using Rockbox's greyscale library}. Supported formats are as follows.
\opt{swcodec}{
\begin{table}
\begin{rbtabular}{.60\textwidth}{llX}%
{\textbf{Format}& \textbf{File-extension(s)}}%
{}{}
BMP & \fname{.bmp} \\
JPEG & \fname{.jpg, .jpe, .jpeg} \\
PNG & \fname{.png} \\
\end{rbtabular}
\end{table}
\opt{large_plugin_buffer}{
\par \par
\note{ \note{
When an audio file is playing the size of the image is limited as When an audio file is playing the size of the image is limited as
@ -23,17 +34,18 @@ view a bigger file you may need to stop playback.}
,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD% ,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD%
,MROBE100_PAD,IPOD_4G_PAD,IPOD_3G_PAD,IRIVER_H10_PAD,PBELL_VIBE500_PAD} ,MROBE100_PAD,IPOD_4G_PAD,IPOD_3G_PAD,IRIVER_H10_PAD,PBELL_VIBE500_PAD}
{/ \ButtonLeft\ / \ButtonRight} {/ \ButtonLeft\ / \ButtonRight}
\opt{COWON_D2_PAD}{} \opt{touchscreen}{\TouchTopMiddle{} / \TouchBottomMiddle{}/ \TouchMidLeft{} / \TouchMidRight}
\opt{HAVEREMOTEKEYMAP}{& } \opt{HAVEREMOTEKEYMAP}{& }
& Move around in zoomed in image\\ & Move around in zoomed in image\\
\opt{RECORDER_PAD}{\ButtonPlay} \opt{RECORDER_PAD}{\ButtonPlay}
\opt{ONDIO_PAD,COWON_D2_PAD}{\ButtonMenu} \opt{ONDIO_PAD}{\ButtonMenu}
\opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD% \opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD%
,SANSA_FUZE_PAD,SANSA_C200_PAD,MROBE100_PAD}{\ButtonSelect} ,SANSA_FUZE_PAD,SANSA_C200_PAD,MROBE100_PAD}{\ButtonSelect}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollFwd} \opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollFwd}
\opt{IRIVER_H10_PAD}{\ButtonPlay} \opt{IRIVER_H10_PAD}{\ButtonPlay}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolUp} \opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolUp}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonUp} \opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonUp}
\opt{touchscreen}{\TouchTopRight}
\opt{HAVEREMOTEKEYMAP}{& } \opt{HAVEREMOTEKEYMAP}{& }
& Zoom in\\ & Zoom in\\
\opt{RECORDER_PAD}{\ButtonOn} \opt{RECORDER_PAD}{\ButtonOn}
@ -45,6 +57,7 @@ view a bigger file you may need to stop playback.}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolDown} \opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolDown}
\opt{MROBE100_PAD}{\ButtonPlay} \opt{MROBE100_PAD}{\ButtonPlay}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonDown} \opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonDown}
\opt{touchscreen}{\TouchTopLeft}
\opt{HAVEREMOTEKEYMAP}{& } \opt{HAVEREMOTEKEYMAP}{& }
& Zoom out\\ & Zoom out\\
\opt{RECORDER_PAD}{\ButtonFThree} \opt{RECORDER_PAD}{\ButtonFThree}
@ -60,8 +73,9 @@ view a bigger file you may need to stop playback.}
\opt{GIGABEAT_S_PAD}{\ButtonNext} \opt{GIGABEAT_S_PAD}{\ButtonNext}
\opt{MROBE100_PAD}{\ButtonDisplay+\ButtonRight} \opt{MROBE100_PAD}{\ButtonDisplay+\ButtonRight}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonRight} \opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonRight}
\opt{touchscreen}{\TouchBottomRight}
\opt{HAVEREMOTEKEYMAP}{& } \opt{HAVEREMOTEKEYMAP}{& }
& Next jpeg in directory\\ & Next image in directory\\
\opt{RECORDER_PAD}{\ButtonFTwo} \opt{RECORDER_PAD}{\ButtonFTwo}
\opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft} \opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft}
\opt{IRIVER_H100_PAD,IAUDIO_X5_PAD}{\ButtonRec} \opt{IRIVER_H100_PAD,IAUDIO_X5_PAD}{\ButtonRec}
@ -74,8 +88,9 @@ view a bigger file you may need to stop playback.}
\opt{GIGABEAT_S_PAD}{\ButtonPrev} \opt{GIGABEAT_S_PAD}{\ButtonPrev}
\opt{MROBE100_PAD}{\ButtonDisplay+\ButtonLeft} \opt{MROBE100_PAD}{\ButtonDisplay+\ButtonLeft}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonLeft} \opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonLeft}
\opt{touchscreen}{\TouchBottomLeft}
\opt{HAVEREMOTEKEYMAP}{& } \opt{HAVEREMOTEKEYMAP}{& }
& Previous jpeg in directory\\ & Previous image in directory\\
\opt{SANSA_E200_PAD,SANSA_C200_PAD}{%currently only defined for the sansa pads \opt{SANSA_E200_PAD,SANSA_C200_PAD}{%currently only defined for the sansa pads
\ButtonRec \ButtonRec
\opt{HAVEREMOTEKEYMAP}{& } \opt{HAVEREMOTEKEYMAP}{& }
@ -86,7 +101,7 @@ view a bigger file you may need to stop playback.}
\opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD,SANSA_C200_PAD}{\ButtonPower} \opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD,SANSA_C200_PAD}{\ButtonPower}
\opt{SANSA_FUZE_PAD}{Long \ButtonHome} \opt{SANSA_FUZE_PAD}{Long \ButtonHome}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,PBELL_VIBE500_PAD}{\ButtonMenu} \opt{GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,PBELL_VIBE500_PAD}{\ButtonMenu}
\opt{COWON_D2_PAD}{\ButtonPower} \opt{touchscreen}{\TouchCenter}
\opt{HAVEREMOTEKEYMAP}{& \opt{HAVEREMOTEKEYMAP}{&
\opt{IRIVER_RC_H100_PAD}{\ButtonRCStop} \opt{IRIVER_RC_H100_PAD}{\ButtonRCStop}
} }
@ -114,7 +129,8 @@ playback of the currently loaded playlist and change the volume of your \dap.
\opt{lcd_color}{ \opt{lcd_color}{
\item[Display Options.] From this menu you can force the viewer to render the \item[Display Options.] From this menu you can force the viewer to render the
image in greyscale using the \setting{Greyscale} option or set the method of image in greyscale using the \setting{Greyscale} option or set the method of
dithering used in the \setting{Dithering} submenu. dithering used in the \setting{Dithering} submenu. These settings only take affect
for JPEG images.
} }
\item[Quit.] Quits the viewer and returns to the \setting{File Browser}. \item[Quit.] Quits the viewer and returns to the \setting{File Browser}.
\end{description} \end{description}

View file

@ -137,11 +137,10 @@ option from the \setting{Context Menu} (see \reference{ref:Contextmenu}).}
\begin{rbtabular}{.92\textwidth}{Xlc}% \begin{rbtabular}{.92\textwidth}{Xlc}%
{\textbf{Viewer Plugin}& \textbf{Associated filetype(s)} & \textbf{Context Menu only}}% {\textbf{Viewer Plugin}& \textbf{Associated filetype(s)} & \textbf{Context Menu only}}%
{}{} {}{}
BMP Viewer & \fname{.bmp} & \\
Shortcuts & \fname{.link} & \\ Shortcuts & \fname{.link} & \\
Chip-8 Emulator & \fname{.ch8} & \\ Chip-8 Emulator & \fname{.ch8} & \\
Frotz & \fname{.z1 - .z8} & \\ Frotz & \fname{.z1 - .z8} & \\
JPEG Viewer & \fname{.jpg, .jpeg} & \\ Image Viewer & \fname{.bmp, .jpg, .jpeg, .png} & \\
Lua scripting language& \fname{.lua} & \\ Lua scripting language& \fname{.lua} & \\
\opt{swcodec}{\nopt{lowmem}{ \opt{swcodec}{\nopt{lowmem}{
Midiplay & \fname{.mid, .midi} & \\ Midiplay & \fname{.mid, .midi} & \\
@ -152,9 +151,6 @@ option from the \setting{Context Menu} (see \reference{ref:Contextmenu}).}
Movie Player & \fname{.rvf} & \\ Movie Player & \fname{.rvf} & \\
} }
} }
\opt{lcd_bitmap}{
PNG viewer & \fname{.png} & \\
}
\opt{lcd_color}{ \opt{lcd_color}{
PPM viewer & \fname{.ppm} & \\ PPM viewer & \fname{.ppm} & \\
} }
@ -177,13 +173,11 @@ option from the \setting{Context Menu} (see \reference{ref:Contextmenu}).}
{\input{plugins/shortcuts.tex}} {\input{plugins/shortcuts.tex}}
\opt{lcd_bitmap}{\input{plugins/bmpviewer.tex}}
\opt{lcd_bitmap}{\input{plugins/chip8emulator.tex}} \opt{lcd_bitmap}{\input{plugins/chip8emulator.tex}}
\opt{lcd_bitmap}{\input{plugins/frotz.tex}} \opt{lcd_bitmap}{\input{plugins/frotz.tex}}
\opt{lcd_bitmap}{\input{plugins/jpegviewer.tex}} \opt{lcd_bitmap}{\input{plugins/imageviewer.tex}}
\opt{large_plugin_buffer}{\input{plugins/lua.tex}} \opt{large_plugin_buffer}{\input{plugins/lua.tex}}
@ -193,8 +187,6 @@ option from the \setting{Context Menu} (see \reference{ref:Contextmenu}).}
\opt{lcd_bitmap}{\opt{swcodec}{\nopt{lowmem}{\input{plugins/mpegplayer.tex}}}} \opt{lcd_bitmap}{\opt{swcodec}{\nopt{lowmem}{\input{plugins/mpegplayer.tex}}}}
\opt{lcd_bitmap}{\input{plugins/pngviewer.tex}}
\opt{lcd_color}{\input{plugins/ppmviewer.tex}} \opt{lcd_color}{\input{plugins/ppmviewer.tex}}
\opt{archosrecorder,archosfmrecorder,ondio}{\input{plugins/rockbox_flash.tex}} \opt{archosrecorder,archosfmrecorder,ondio}{\input{plugins/rockbox_flash.tex}}

View file

@ -1,113 +0,0 @@
% $Id$ %
\subsection{PNG viewer}
This plugin opens \fname{.png} files from the \setting{File Browser} to
display them.
\opt{swcodec}{
\note{When an audio file is playing the size of the image is limited as
the decoding process needs to share memory with audio tracks. To be able to
view a bigger file you may need to stop playback.\\}
}
\nopt{large_plugin_buffer}{%
\note{This plugin will cause playback to stop.}%
}%
\begin{btnmap}
\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD%
,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD%
,MROBE100_PAD,PBELL_VIBE500_PAD}
{\ButtonUp\ / \ButtonDown}%
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu\ / \ButtonPlay}%
\opt{IRIVER_H10_PAD}{\ButtonScrollUp\ / \ButtonScrollDown} %
\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD%
,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD%
,MROBE100_PAD,IPOD_4G_PAD,IPOD_3G_PAD,IRIVER_H10_PAD,PBELL_VIBE500_PAD}
{/ \ButtonLeft\ / \ButtonRight}
\opt{HAVEREMOTEKEYMAP}{& }
& Move around in zoomed in image\\
\opt{RECORDER_PAD}{\ButtonPlay}
\opt{ONDIO_PAD}{\ButtonMenu}
\opt{IRIVER_H100_PAD,IRIVER_H300_PAD,IAUDIO_X5_PAD,SANSA_E200_PAD%
,SANSA_FUZE_PAD,SANSA_C200_PAD,MROBE100_PAD}{\ButtonSelect}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollFwd}
\opt{IRIVER_H10_PAD}{\ButtonPlay}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolUp}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonUp}
\opt{HAVEREMOTEKEYMAP}{& }
& Zoom in\\
\opt{RECORDER_PAD}{\ButtonOn}
\opt{ONDIO_PAD}{\ButtonMenu+\ButtonDown}
\opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonScrollBack}
\opt{IAUDIO_X5_PAD,SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD}{Long \ButtonSelect}
\opt{IRIVER_H10_PAD}{Long \ButtonPlay}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD}{\ButtonVolDown}
\opt{MROBE100_PAD}{\ButtonPlay}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonDown}
\opt{HAVEREMOTEKEYMAP}{& }
& Zoom out\\
\opt{RECORDER_PAD}{\ButtonFThree}
\opt{ONDIO_PAD}{\ButtonMenu+\ButtonRight}
\opt{IRIVER_H100_PAD}{\ButtonOn}
\opt{IRIVER_H300_PAD}{\ButtonRec}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonRight}
\opt{IAUDIO_X5_PAD}{\ButtonPlay}
\opt{IRIVER_H10_PAD}{\ButtonFF}
\opt{SANSA_E200_PAD,SANSA_FUZE_PAD}{\ButtonScrollFwd}
\opt{SANSA_C200_PAD}{\ButtonVolUp}
\opt{GIGABEAT_PAD}{\ButtonA+\ButtonRight}
\opt{GIGABEAT_S_PAD}{\ButtonNext}
\opt{MROBE100_PAD}{\ButtonDisplay+\ButtonRight}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonRight}
\opt{HAVEREMOTEKEYMAP}{& }
& Next png in directory\\
\opt{RECORDER_PAD}{\ButtonFTwo}
\opt{ONDIO_PAD}{\ButtonMenu+\ButtonLeft}
\opt{IRIVER_H100_PAD,IAUDIO_X5_PAD}{\ButtonRec}
\opt{IRIVER_H300_PAD}{\ButtonOn}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonLeft}
\opt{IRIVER_H10_PAD}{\ButtonRew}
\opt{SANSA_E200_PAD,SANSA_FUZE_PAD}{\ButtonScrollBack}
\opt{SANSA_C200_PAD}{\ButtonVolDown}
\opt{GIGABEAT_PAD}{\ButtonA+\ButtonLeft}
\opt{GIGABEAT_S_PAD}{\ButtonPrev}
\opt{MROBE100_PAD}{\ButtonDisplay+\ButtonLeft}
\opt{PBELL_VIBE500_PAD}{\ButtonRec+\ButtonLeft}
\opt{HAVEREMOTEKEYMAP}{& }
& Previous png in directory\\
\opt{SANSA_E200_PAD,SANSA_C200_PAD}{%currently only defined for the sansa pads
\ButtonRec
\opt{HAVEREMOTEKEYMAP}{& }
& Toggle slide show mode\\
}
\opt{RECORDER_PAD,ONDIO_PAD,IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonOff}
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonMenu}
\opt{IAUDIO_X5_PAD,IRIVER_H10_PAD,SANSA_E200_PAD,SANSA_C200_PAD}{\ButtonPower}
\opt{SANSA_FUZE_PAD}{Long \ButtonHome}
\opt{GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,PBELL_VIBE500_PAD}{\ButtonMenu}
\opt{HAVEREMOTEKEYMAP}{&
\opt{IRIVER_RC_H100_PAD}{\ButtonRCStop}
}
& Show menu / Abort while decoding \\
\opt{IPOD_4G_PAD,IPOD_3G_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD%
,PBELL_VIBE500_PAD}{%
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonSelect+\ButtonPlay}
\opt{GIGABEAT_PAD,MROBE100_PAD}{\ButtonPower}
\opt{GIGABEAT_S_PAD}{\ButtonBack}
\opt{PBELL_VIBE500_PAD}{\ButtonCancel}
\opt{HAVEREMOTEKEYMAP}{& }
& Quit the viewer \\
}
\end{btnmap}
The menu has the following entries.
\begin{description}
\item[Return.] Returns you to the image
\item[Toggle Slideshow Mode.] Enables or disables the slideshow mode.
\item[Change Slideshow Timeout.] You can set the timeout for the slideshow
between 1 second and 20 seconds.
\opt{large_plugin_buffer}{
\item[Show Playback Menu.] From the playback menu you can control the
playback of the currently loaded playlist and change the volume of your \dap.
}
\item[Quit.] Quits the viewer and returns to the \setting{File Browser}.
\end{description}

View file

@ -470,8 +470,11 @@ STOP
find(find_copyfile(qr/\.(rock|ovl|lua)/, abs_path("$temp_dir/rocks/")), 'apps/plugins'); find(find_copyfile(qr/\.(rock|ovl|lua)/, abs_path("$temp_dir/rocks/")), 'apps/plugins');
open VIEWERS, "$ROOT/apps/plugins/viewers.config" or # exclude entries for the image file types not supported by the imageviewer for the target.
die "can't open viewers.config"; my $viewers = "$ROOT/apps/plugins/viewers.config";
my $c="cat $viewers | gcc $cppdef -I. -I$firmdir/export -E -P -include config.h -";
open VIEWERS, "$c|" or die "can't open viewers.config";
my @viewers = <VIEWERS>; my @viewers = <VIEWERS>;
close VIEWERS; close VIEWERS;