From 02ab59df62ed1470b2fc7fe6348cc33c341e2408 Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 19 Apr 2020 13:31:21 +0200 Subject: [PATCH 01/11] feat: initial commit --- projects/recalbox-fbv/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 projects/recalbox-fbv/README.md diff --git a/projects/recalbox-fbv/README.md b/projects/recalbox-fbv/README.md new file mode 100644 index 0000000000..f9c8065455 --- /dev/null +++ b/projects/recalbox-fbv/README.md @@ -0,0 +1 @@ +fbv -- GitLab From f30e281a033599c09352dbdba1db9adfa59c92c3 Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 19 Apr 2020 16:09:06 +0200 Subject: [PATCH 02/11] chore: initial import --- projects/recalbox-fbv/.gitignore | 1 + projects/recalbox-fbv/.idea/.gitignore | 8 + projects/recalbox-fbv/.idea/fbv.iml | 2 + .../inspectionProfiles/Project_Default.xml | 8 + projects/recalbox-fbv/.idea/misc.xml | 7 + projects/recalbox-fbv/.idea/modules.xml | 8 + projects/recalbox-fbv/.idea/vcs.xml | 6 + projects/recalbox-fbv/CMakeLists.txt | 22 + projects/recalbox-fbv/COPYING | 5 + projects/recalbox-fbv/ChangeLog | 33 + projects/recalbox-fbv/Make.conf | 2 + projects/recalbox-fbv/Makefile | 36 ++ projects/recalbox-fbv/README.md | 50 +- projects/recalbox-fbv/TODO | 23 + projects/recalbox-fbv/VERSION | 1 + projects/recalbox-fbv/bmp.c | 235 +++++++ projects/recalbox-fbv/config.h | 6 + projects/recalbox-fbv/configure | 176 ++++++ projects/recalbox-fbv/fb_display.c | 355 +++++++++++ projects/recalbox-fbv/fbv.1 | 58 ++ projects/recalbox-fbv/fbv.h | 61 ++ projects/recalbox-fbv/gif.c | 226 +++++++ projects/recalbox-fbv/jpeg.c | 144 +++++ projects/recalbox-fbv/main.c | 592 ++++++++++++++++++ projects/recalbox-fbv/mkrelease | 17 + projects/recalbox-fbv/png.c | 175 ++++++ projects/recalbox-fbv/transforms.c | 181 ++++++ 27 files changed, 2437 insertions(+), 1 deletion(-) create mode 100644 projects/recalbox-fbv/.gitignore create mode 100644 projects/recalbox-fbv/.idea/.gitignore create mode 100644 projects/recalbox-fbv/.idea/fbv.iml create mode 100644 projects/recalbox-fbv/.idea/inspectionProfiles/Project_Default.xml create mode 100644 projects/recalbox-fbv/.idea/misc.xml create mode 100644 projects/recalbox-fbv/.idea/modules.xml create mode 100644 projects/recalbox-fbv/.idea/vcs.xml create mode 100644 projects/recalbox-fbv/CMakeLists.txt create mode 100644 projects/recalbox-fbv/COPYING create mode 100644 projects/recalbox-fbv/ChangeLog create mode 100644 projects/recalbox-fbv/Make.conf create mode 100644 projects/recalbox-fbv/Makefile create mode 100644 projects/recalbox-fbv/TODO create mode 100644 projects/recalbox-fbv/VERSION create mode 100644 projects/recalbox-fbv/bmp.c create mode 100644 projects/recalbox-fbv/config.h create mode 100755 projects/recalbox-fbv/configure create mode 100644 projects/recalbox-fbv/fb_display.c create mode 100644 projects/recalbox-fbv/fbv.1 create mode 100644 projects/recalbox-fbv/fbv.h create mode 100644 projects/recalbox-fbv/gif.c create mode 100644 projects/recalbox-fbv/jpeg.c create mode 100644 projects/recalbox-fbv/main.c create mode 100755 projects/recalbox-fbv/mkrelease create mode 100644 projects/recalbox-fbv/png.c create mode 100644 projects/recalbox-fbv/transforms.c diff --git a/projects/recalbox-fbv/.gitignore b/projects/recalbox-fbv/.gitignore new file mode 100644 index 0000000000..bf797c5fe7 --- /dev/null +++ b/projects/recalbox-fbv/.gitignore @@ -0,0 +1 @@ +cmake-build-debug \ No newline at end of file diff --git a/projects/recalbox-fbv/.idea/.gitignore b/projects/recalbox-fbv/.idea/.gitignore new file mode 100644 index 0000000000..73f69e0958 --- /dev/null +++ b/projects/recalbox-fbv/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/projects/recalbox-fbv/.idea/fbv.iml b/projects/recalbox-fbv/.idea/fbv.iml new file mode 100644 index 0000000000..f08604bb65 --- /dev/null +++ b/projects/recalbox-fbv/.idea/fbv.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/projects/recalbox-fbv/.idea/inspectionProfiles/Project_Default.xml b/projects/recalbox-fbv/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000..1ac5b580d4 --- /dev/null +++ b/projects/recalbox-fbv/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/projects/recalbox-fbv/.idea/misc.xml b/projects/recalbox-fbv/.idea/misc.xml new file mode 100644 index 0000000000..8822db8f1c --- /dev/null +++ b/projects/recalbox-fbv/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/projects/recalbox-fbv/.idea/modules.xml b/projects/recalbox-fbv/.idea/modules.xml new file mode 100644 index 0000000000..23361f90e8 --- /dev/null +++ b/projects/recalbox-fbv/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/projects/recalbox-fbv/.idea/vcs.xml b/projects/recalbox-fbv/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/projects/recalbox-fbv/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/projects/recalbox-fbv/CMakeLists.txt b/projects/recalbox-fbv/CMakeLists.txt new file mode 100644 index 0000000000..8d5476f295 --- /dev/null +++ b/projects/recalbox-fbv/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 2.8) +project(fbv C) + +set(CMAKE_C_STANDARD 11) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g3") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") + +include_directories(.) + +add_executable(fbv + bmp.c + fb_display.c + fbv.h + gif.c + jpeg.c + main.c + png.c + transforms.c) + +target_link_libraries(fbv gif png jpeg) diff --git a/projects/recalbox-fbv/COPYING b/projects/recalbox-fbv/COPYING new file mode 100644 index 0000000000..42a1b9318c --- /dev/null +++ b/projects/recalbox-fbv/COPYING @@ -0,0 +1,5 @@ +The package is licensed under the GPL license, version 2. + +It was to large to include it here (bigger than the whole source). + +Obtain your copy from http://www.gnu.org diff --git a/projects/recalbox-fbv/ChangeLog b/projects/recalbox-fbv/ChangeLog new file mode 100644 index 0000000000..a4cc0916f9 --- /dev/null +++ b/projects/recalbox-fbv/ChangeLog @@ -0,0 +1,33 @@ +0.99 2003-08-24 Mateusz Golicz mtg@elsat.net.pl + * fixes in transparent and interlaced GIF & PNG support + * support for using the alpha channel + * docs update + +0.98 2002-12-05 Nat Ersoz nat.ersoz@myrio.com + * fbv now supports the "stride" feature (it works (hopefully) + well when a device supports a line length longer than + the viewable graphics display) + +0.96 2002-01-15 Tomasz Sterna smoku@jaszczur.org + + * BMP files support + (RLE compression and 16bpp not supported yet) + +0.95 2001-08-09 Tomasz Sterna smoku@jaszczur.org + + * dropped autotools + * added tgt-like configure script + +0.94b 2001-02-19 Marcin Zieba piaskowy@irc.pl + + * adding automake support + * manual page + + 2001-02-18 Marcin Zieba piaskowy@irc.pl + + * main.c: added long options support, fixed? segv. Checked, if user supplied filename. + +-0.93b 2000-11-23 Tomasz 'smoku' Sterna + Mateusz 'mteg' Golicz + + * added this entry just to be fair, they did it all. diff --git a/projects/recalbox-fbv/Make.conf b/projects/recalbox-fbv/Make.conf new file mode 100644 index 0000000000..a420de7ea7 --- /dev/null +++ b/projects/recalbox-fbv/Make.conf @@ -0,0 +1,2 @@ +error: + @echo Please run ./configure first... diff --git a/projects/recalbox-fbv/Makefile b/projects/recalbox-fbv/Makefile new file mode 100644 index 0000000000..f3b3da4fd2 --- /dev/null +++ b/projects/recalbox-fbv/Makefile @@ -0,0 +1,36 @@ +# +# Makefile +# +# Makefile for fbv + +include Make.conf + +CC = gcc +CFLAGS = -O2 -Wall -D_GNU_SOURCE + +SOURCES = main.c jpeg.c gif.c png.c bmp.c fb_display.c transforms.c +OBJECTS = ${SOURCES:.c=.o} + +OUT = fbv +#LIBS = -lungif -L/usr/X11R6/lib -ljpeg -lpng + +all: $(OUT) + @echo Build DONE. + +$(OUT): $(OBJECTS) + $(CC) $(LDFLAGS) -o $(OUT) $(OBJECTS) $(LIBS) + +clean: + rm -f $(OBJECTS) *~ $$$$~* *.bak core config.log $(OUT) + +distclean: clean + @echo -e "error:\n\t@echo Please run ./configure first..." >Make.conf + rm -f $(OUT) config.h + +install: $(OUT) + cp $(OUT) $(DESTDIR)$(bindir) + gzip -9c $(OUT).1 > $(DESTDIR)$(mandir)/man1/$(OUT).1.gz + +uninstall: $(DESTDIR)$(bindir)/$(OUT) + rm -f $(DESTDIR)$(bindir)/$(OUT) + rm -f $(DESTDIR)$(mandir)/man1/$(OUT).1.gz diff --git a/projects/recalbox-fbv/README.md b/projects/recalbox-fbv/README.md index f9c8065455..f64cac3558 100644 --- a/projects/recalbox-fbv/README.md +++ b/projects/recalbox-fbv/README.md @@ -1 +1,49 @@ -fbv +1. OVERVIEW + fbv (FrameBuffer Viewer) is a simple program to view pictures on + a linux framebuffer device. In 2000, when fbv was created, there + were no other situable programs performing the same task, so the + authors decided to follow the rule: 'If you need a tool - write + it yourself!' :-) + +2. REQUIREMENTS + - Linux, configured to provide the framebuffer device interface + (/dev/fb0 or /dev/fb/0) + - libungif for GIF support + - libjpeg for JPEG support + - libpng for PNG support + +3. INSTALLATION + - unpack the archive (you've propably already done it) + - run ./configure + - type: make + - type: make install + - enjoy... + +4. USAGE + Just run fbv without any arguments, and a short help message + will appear... + +5. AUTHORS + Tomasz 'smoku' Sterna + Mateusz 'mteg' Golicz + + Feel free to send any comments, patches, bugfixes, suggestions, etc. The + authors are not native english speakers, and they are aware of the fact + that their english is far from perfect. Because of that, reports on + grammar and vocabulary mistakes in this file are also welcome. + +6. BUGS & TODO + - the code is really awfully formated and requires some fixes... + - the english in messages is not the best at all :-) + +7. ACKNOWLEDGEMENTS + - the fbset authors: some code in fb_display.c is based on it... + - Nat Ersoz - for his suggestions and bugfixes + - Mauro Meneghin - for the transparent GIF support + - Marcin 'Piaskowy' Zieba - for his minor bugfixes + - Mariusz 'Ma-rYu-sH' Witkowski - for his suggestions on alpha + channel support and testing + +8. LICENSE + The package is licensed under the GNU GPL license, version 2. + Obtain your copy at http://www.gnu.org. diff --git a/projects/recalbox-fbv/TODO b/projects/recalbox-fbv/TODO new file mode 100644 index 0000000000..5f4ac0d761 --- /dev/null +++ b/projects/recalbox-fbv/TODO @@ -0,0 +1,23 @@ +switching off cursor (it's flashing in upper-left corner) => done +support for multiple files =>done + +command-line switches: +no-clear => done +interpolate-resize => done +fast-resize =>done +slideshow =>done + +keymaps: (needed) ++ zoom in +- zoom out + * "fit to screen" zoom => done as a command line option + next picture => done +<- previous picture => done +cursors panning => done + + +'more normal' configure script :))))))) => DONE + + +make it compile and work on Sparc - I need it ;) - added by piaskowy@irc.pl + diff --git a/projects/recalbox-fbv/VERSION b/projects/recalbox-fbv/VERSION new file mode 100644 index 0000000000..d74244a170 --- /dev/null +++ b/projects/recalbox-fbv/VERSION @@ -0,0 +1 @@ +1.0b diff --git a/projects/recalbox-fbv/bmp.c b/projects/recalbox-fbv/bmp.c new file mode 100644 index 0000000000..7c77d89703 --- /dev/null +++ b/projects/recalbox-fbv/bmp.c @@ -0,0 +1,235 @@ +/* + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2002 Tomasz Sterna + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "config.h" +#ifdef FBV_SUPPORT_BMP +#include "fbv.h" +#include +#include +#include +#include + +#define BMP_TORASTER_OFFSET 10 +#define BMP_SIZE_OFFSET 18 +#define BMP_BPP_OFFSET 28 +#define BMP_RLE_OFFSET 30 +#define BMP_COLOR_OFFSET 54 + +#define fill4B(a) ( ( 4 - ( (a) % 4 ) ) & 0x03) + +struct color { + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +int fh_bmp_id(char *name) +{ + int fd; + char id[2]; + + fd = open(name, O_RDONLY); + if (fd == -1) { + return(0); + } + + read(fd, id, 2); + close(fd); + if ( id[0]=='B' && id[1]=='M' ) { + return(1); + } + return(0); +} + +void fetch_pallete(int fd, struct color pallete[], int count) +{ + unsigned char buff[4]; + int i; + + lseek(fd, BMP_COLOR_OFFSET, SEEK_SET); + for (i=0; i>4; + buff[2] = buff[0] & 0x0f; + *wr_buffer++ = pallete[buff[1]].red; + *wr_buffer++ = pallete[buff[1]].green; + *wr_buffer++ = pallete[buff[1]].blue; + *wr_buffer++ = pallete[buff[2]].red; + *wr_buffer++ = pallete[buff[2]].green; + *wr_buffer++ = pallete[buff[2]].blue; + } + if (x%2) { + read(fd, buff, 1); + buff[1] = buff[0]>>4; + *wr_buffer++ = pallete[buff[1]].red; + *wr_buffer++ = pallete[buff[1]].green; + *wr_buffer++ = pallete[buff[1]].blue; + } + if (skip) { + read(fd, buff, skip); + } + wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ + } + break; + case 8: /* 8bit palletized */ + skip = fill4B(x); + fetch_pallete(fd, pallete, 256); + lseek(fd, raster, SEEK_SET); + for (i=0; i&2 +Usage: ./configure [options] +Options: [defaults in brackets after descriptions] + +If a long option shows an argument as mandatory, then it is mandatory +for the equivalent short option also. Similarly for optional arguments. + +General: + --help print this message + --libs=LIBS additional libraries required (try -lX11 for ungif, -lz for PNG) + +Directory and file names: + --prefix=PREFIX install files in PREFIX [/usr/local] + --bindir=DIR binary executable in DIR [PREFIX/lib] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + +Features and packages: + --without-libungif disable libungif support even if found + --without-libjpeg disable libjpeg support even if found + --without-libpng disable libpng support even if found + --without-bmp disable bmp support +EOF +} + +# get options +TEMP=$(getopt -o h \ +--long help,\ +prefix:,srcdir:,bindir:,\ +infodir:,mandir:,\ +without-libungif,without-libjpeg,without-libpng,without-bmp,libs: \ +-n "$BASENAME" -- "$@") + +if [ $? != 0 ] ; then help ; exit 1 ; fi +# +eval set -- "$TEMP" + +# process options +while true ; do + case "$1" in + -h|--help) help ; exit 0 ;; + --libs) libs="$2"; shift 2 ;; + --prefix) prefix="$2" ; shift 2 ;; + --srcdir) srcdir="$2" ; shift 2 ;; + --bindir) bindir="$2" ; shift 2 ;; + --infodir) infodir="$2" ; shift 2 ;; + --mandir) mandir="$2" ; shift 2 ;; + --without-libungif) ungif="disabled" ; shift ;; + --without-libjpeg) jpeg="disabled" ; shift ;; + --without-libpng) png="disabled" ; shift ;; + --without-bmp) bmp="disabled" ; shift ;; + + --) shift ; break ;; + *) help ; exit 1 ;; + esac +done + +[ -z "$prefix" ] && prefix="/usr/local" +[ -z "$bindir" ] && bindir="${prefix}/bin" +[ -z "$mandir" ] && mandir="${prefix}/man" +[ -z "$infodir" ] && infodir="${prefix}/info" + +cat << EOF | tee ./config.log >Make.conf +prefix = $prefix +bindir = $bindir +mandir = $mandir +infodir = $infodir +EOF + +# tests +rm -f \$\$~test \$\$~test.c +cat > \$\$~test.c << EOF +main() +{ +} +EOF +### +echo -n "checking for libungif presence... " +if [ "$ungif" != "disabled" ]; then +xdir="/usr/X11R6" +ungif="no" +echo "libungif check" >>./config.log +echo " 1st:" >>./config.log +cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lungif $libs +if [ -e \$\$~test ]; then + libs="-lungif $libs" ; ungif="yes" +else + echo " 2nd: -lX11 -L$xdir/lib" >>./config.log + cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lungif -lX11 -L$xdir/lib $libs + if [ -e \$\$~test ]; then + libs="-lungif -lX11 -L$xdir/lib $libs" ; ungif="yes" + fi +fi +rm -f \$\$~test +fi +echo $ungif +echo "libungif: $ungif" >> ./config.log +### +echo -n "checking for libjpeg presence... " +if [ "$jpeg" != "disabled" ]; then +jpeg="no" +cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -ljpeg $libs +if [ -e \$\$~test ]; then + libs="-ljpeg $libs" ; jpeg="yes" +fi +fi +echo $jpeg +echo "libjpeg: $jpeg" >> ./config.log +### +echo -n "checking for libpng presence... " +if [ "$png" != "disabled" ]; then +png="no" +cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lpng $libs +if [ -e \$\$~test ]; then + libs="-lpng $libs" ; png="yes" +fi +fi +echo $png +echo "libpng: $png" >> ./config.log +### +echo -n "building with bmp support... " +if [ "$bmp" != "disabled" ]; then +bmp="yes" +fi +echo $bmp +echo "bmp: $bmp" >> ./config.log +### +rm -f \$\$~test \$\$~test.c +### +echo -n "checking for DEFAULT_FRAMEBUFFER... " +if [ -n "$FRAMEBUFFER" ]; then + dfb="$FRAMEBUFFER" +else + dfb="/dev/fb0" +fi +echo $dfb +echo "fb: $dfb" >> ./config.log +# +echo >>Make.conf +echo "LIBS = $libs" | tee -a ./config.log >>Make.conf +echo "#define IDSTRING \"fbv "`cat VERSION`", s-tech\"" | tee -a ./config.log >config.h +echo "#define DEFAULT_FRAMEBUFFER \"$dfb\"" | tee -a ./config.log >>config.h +[ "$ungif" != "disabled" ] && echo "#define FBV_SUPPORT_GIF" | tee -a ./config.log >>config.h +[ "$jpeg" != "disabled" ] && echo "#define FBV_SUPPORT_JPEG" | tee -a ./config.log >>config.h +[ "$png" != "disabled" ] && echo "#define FBV_SUPPORT_PNG" | tee -a ./config.log >>config.h +[ "$bmp" != "disabled" ] && echo "#define FBV_SUPPORT_BMP" | tee -a ./config.log >>config.h +echo "installation dir: $bindir" +echo "manuals dir: $mandir" + +exit 0 +## EOF diff --git a/projects/recalbox-fbv/fb_display.c b/projects/recalbox-fbv/fb_display.c new file mode 100644 index 0000000000..02e579e2c9 --- /dev/null +++ b/projects/recalbox-fbv/fb_display.c @@ -0,0 +1,355 @@ +/*` + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2000 Tomasz Sterna + Copyright (C) 2003 Mateusz Golicz + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +/* Public Use Functions: + * + * extern void fb_display(unsigned char *rgbbuff, + * int x_size, int y_size, + * int x_pan, int y_pan, + * int x_offs, int y_offs); + * + * extern void getCurrentRes(int *x,int *y); + * + */ + +unsigned short red[256], green[256], blue[256]; +struct fb_cmap map332 = {0, 256, red, green, blue, NULL}; +unsigned short red_b[256], green_b[256], blue_b[256]; +struct fb_cmap map_back = {0, 256, red_b, green_b, blue_b, NULL}; + + +int openFB(const char *name); +void closeFB(int fh); +void getVarScreenInfo(int fh, struct fb_var_screeninfo *var); +void setVarScreenInfo(int fh, struct fb_var_screeninfo *var); +void getFixScreenInfo(int fh, struct fb_fix_screeninfo *fix); +void set332map(int fh); +void* convertRGB2FB(int fh, unsigned char *rgbbuff, unsigned long count, int bpp, int *cpp); +void blit2FB(int fh, void *fbbuff, unsigned char *alpha, + unsigned int pic_xs, unsigned int pic_ys, + unsigned int scr_xs, unsigned int scr_ys, + unsigned int xp, unsigned int yp, + unsigned int xoffs, unsigned int yoffs, + int cpp); + +void fb_display(unsigned char *rgbbuff, unsigned char * alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs) +{ + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + unsigned short *fbbuff = NULL; + int fh = -1, bp = 0; + unsigned long x_stride; + + /* get the framebuffer device handle */ + fh = openFB(NULL); + + /* read current video mode */ + getVarScreenInfo(fh, &var); + getFixScreenInfo(fh, &fix); + + x_stride = (fix.line_length * 8) / var.bits_per_pixel; + + /* correct panning */ + if(x_pan > x_size - x_stride) x_pan = 0; + if(y_pan > y_size - var.yres) y_pan = 0; + /* correct offset */ + if(x_offs + x_size > x_stride) x_offs = 0; + if(y_offs + y_size > var.yres) y_offs = 0; + + /* blit buffer 2 fb */ + fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp); +#if 0 + blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres, x_pan, y_pan, x_offs, y_offs, bp); +#else + blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres_virtual, x_pan, y_pan, x_offs, y_offs + var.yoffset, bp); +#endif + free(fbbuff); + + /* close device */ + closeFB(fh); +} + +void getCurrentRes(int *x, int *y) +{ + struct fb_var_screeninfo var; + int fh = -1; + fh = openFB(NULL); + getVarScreenInfo(fh, &var); + *x = var.xres; + *y = var.yres; + closeFB(fh); +} + +int openFB(const char *name) +{ + int fh; + char *dev; + + if(name == NULL){ + dev = getenv("FRAMEBUFFER"); + if(dev) name = dev; + else name = DEFAULT_FRAMEBUFFER; + } + + if ((fh = open(name, O_RDWR)) == -1){ + fprintf(stderr, "open %s: %s\n", name, strerror(errno)); + exit(1); + } + return fh; +} + +void closeFB(int fh) +{ + close(fh); +} + +void getVarScreenInfo(int fh, struct fb_var_screeninfo *var) +{ + if (ioctl(fh, FBIOGET_VSCREENINFO, var)){ + fprintf(stderr, "ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + exit(1); + } +} + +void setVarScreenInfo(int fh, struct fb_var_screeninfo *var) +{ + if (ioctl(fh, FBIOPUT_VSCREENINFO, var)){ + fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); + exit(1); + } +} + +void getFixScreenInfo(int fh, struct fb_fix_screeninfo *fix) +{ + if (ioctl(fh, FBIOGET_FSCREENINFO, fix)){ + fprintf(stderr, "ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + exit(1); + } +} + +void make332map(struct fb_cmap *map) +{ + int rs, gs, bs, i; + int r = 8, g = 8, b = 4; + + map->red = red; + map->green = green; + map->blue = blue; + + rs = 256 / (r - 1); + gs = 256 / (g - 1); + bs = 256 / (b - 1); + + for (i = 0; i < 256; i++) { + map->red[i] = (rs * ((i / (g * b)) % r)) * 255; + map->green[i] = (gs * ((i / b) % g)) * 255; + map->blue[i] = (bs * ((i) % b)) * 255; + } +} + +void set8map(int fh, struct fb_cmap *map) +{ + if (ioctl(fh, FBIOPUTCMAP, map) < 0) { + fprintf(stderr, "Error putting colormap"); + exit(1); + } +} + +void get8map(int fh, struct fb_cmap *map) +{ + if (ioctl(fh, FBIOGETCMAP, map) < 0) { + fprintf(stderr, "Error getting colormap"); + exit(1); + } +} + +void set332map(int fh) +{ + make332map(&map332); + set8map(fh, &map332); +} + +void blit2FB(int fh, void *fbbuff, unsigned char *alpha, + unsigned int pic_xs, unsigned int pic_ys, + unsigned int scr_xs, unsigned int scr_ys, + unsigned int xp, unsigned int yp, + unsigned int xoffs, unsigned int yoffs, + int cpp) +{ + int i, xc, yc; + unsigned char *fb; + + unsigned char *fbptr; + unsigned char *imptr; + + xc = (pic_xs > scr_xs) ? scr_xs : pic_xs; + yc = (pic_ys > scr_ys) ? scr_ys : pic_ys; + + fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); + + if(fb == MAP_FAILED) + { + perror("mmap"); + return; + } + + if(cpp == 1) + { + get8map(fh, &map_back); + set332map(fh); + } + + fbptr = fb + (yoffs * scr_xs + xoffs) * cpp; + imptr = fbbuff + (yp * pic_xs + xp) * cpp; + + if(alpha) + { + unsigned char * alphaptr; + int from, to, x; + + alphaptr = alpha + (yp * pic_xs + xp); + + for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp, alphaptr += pic_xs) + { + for(x = 0; x 0x80) from = v; + } + else + { + if(alphaptr[v] < 0x80) + { + to = v; + break; + } + } + } + if(from == -1) + break; + + if(to == -1) to = xc; + + memcpy(fbptr + (from * cpp), imptr + (from * cpp), (to - from - 1) * cpp); + x += to - from - 1; + } + } + } + else + for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp) + memcpy(fbptr, imptr, xc * cpp); + + if(cpp == 1) + set8map(fh, &map_back); + + munmap(fb, scr_xs * scr_ys * cpp); +} + +inline static unsigned char make8color(unsigned char r, unsigned char g, unsigned char b) +{ + return ( + (((r >> 5) & 7) << 5) | + (((g >> 5) & 7) << 2) | + ((b >> 6) & 3) ); +} + +inline static unsigned short make15color(unsigned char r, unsigned char g, unsigned char b) +{ + return ( + (((r >> 3) & 31) << 10) | + (((g >> 3) & 31) << 5) | + ((b >> 3) & 31) ); +} + +inline static unsigned short make16color(unsigned char r, unsigned char g, unsigned char b) +{ + return ( + (((r >> 3) & 31) << 11) | + (((g >> 2) & 63) << 5) | + ((b >> 3) & 31) ); +} + +void* convertRGB2FB(int fh, unsigned char *rgbbuff, unsigned long count, int bpp, int *cpp) +{ + unsigned long i; + void *fbbuff = NULL; + u_int8_t *c_fbbuff; + u_int16_t *s_fbbuff; + u_int32_t *i_fbbuff; + + switch(bpp) + { + case 8: + *cpp = 1; + c_fbbuff = (unsigned char *) malloc(count * sizeof(unsigned char)); + for(i = 0; i < count; i++) + c_fbbuff[i] = make8color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]); + fbbuff = (void *) c_fbbuff; + break; + case 15: + *cpp = 2; + s_fbbuff = (unsigned short *) malloc(count * sizeof(unsigned short)); + for(i = 0; i < count ; i++) + s_fbbuff[i] = make15color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]); + fbbuff = (void *) s_fbbuff; + break; + case 16: + *cpp = 2; + s_fbbuff = (unsigned short *) malloc(count * sizeof(unsigned short)); + for(i = 0; i < count ; i++) + s_fbbuff[i] = make16color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]); + fbbuff = (void *) s_fbbuff; + break; + case 24: + case 32: + *cpp = 4; + i_fbbuff = (unsigned int *) malloc(count * sizeof(unsigned int)); + for(i = 0; i < count ; i++) + i_fbbuff[i] = ((rgbbuff[i*3] << 16) & 0xFF0000) | + ((rgbbuff[i*3+1] << 8) & 0xFF00) | + (rgbbuff[i*3+2] & 0xFF); + fbbuff = (void *) i_fbbuff; + break; + default: + fprintf(stderr, "Unsupported video mode! You've got: %dbpp\n", bpp); + exit(1); + } + return fbbuff; +} diff --git a/projects/recalbox-fbv/fbv.1 b/projects/recalbox-fbv/fbv.1 new file mode 100644 index 0000000000..b7e0bb30fb --- /dev/null +++ b/projects/recalbox-fbv/fbv.1 @@ -0,0 +1,58 @@ +.TH fbv 1 "2001-02-18" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +FrameBuffer Viewer +.SH SYNOPSIS +\fBfbv\fP [options] image1 image2 image3 ... +.SH DESCRIPTION +This is a simple program to view pictures on a framebuffer console. +.PP +.nh +.SH OPTIONS +.TP +.BR "\fB--help\fP" , \fB-h\fP +help +.TP +.BR \fB--alpha\fP , \fB-a\fP +Respect alpha channel (if applicable) +.TP +.BR \fB--noclear\fP , \fB-c\fP +Do not clear the screen before/after displaying image +.TP +.BR \fB--unhide\fP , \fB-u\fP +Do not hide/show cursor before/after displaying image +.TP +.BR \fB--noinfo\fP , \fB-i\fP +Do not show image information +.TP +.BR \fB--stretch\fP , \fB-f\fP +Strech (using simple resize) the image to fit onto screen if necessary +.TP +.BR \fB--colorstretch\fP , \fB-k\fP +Strech (using color average resize) the image to fit onto screen if necessary +.TP +.BR \fB--delay\fP , "\fB-s\fP \fI\fP" +Slideshow, wait 'delay' tenths of a second before displaying each image + +.BR + Use a,d,w and x to scroll the image + + + +.SH AUTHOR +Tomasz 'smoku' Sterna +.br +Mateusz 'mteg' Golicz +.br +Marcin 'Piaskowy' Zieba +.br + diff --git a/projects/recalbox-fbv/fbv.h b/projects/recalbox-fbv/fbv.h new file mode 100644 index 0000000000..1bf53faba9 --- /dev/null +++ b/projects/recalbox-fbv/fbv.h @@ -0,0 +1,61 @@ +/* + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2000, 2001, 2003 Mateusz Golicz + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define FH_ERROR_OK 0 +#define FH_ERROR_FILE 1 /* read/access error */ +#define FH_ERROR_FORMAT 2 /* file format error */ + +void fb_display(unsigned char *rgbbuff, unsigned char * alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs); +void getCurrentRes(int *x, int *y); + +int fh_bmp_id(char *name); +int fh_bmp_load(char *name,unsigned char *buffer, unsigned char **alpha, int x,int y); +int fh_bmp_getsize(char *name,int *x,int *y); + +int fh_jpeg_id(char *name); +int fh_jpeg_load(char *name,unsigned char *buffer, unsigned char **alpha, int x,int y); +int fh_jpeg_getsize(char *name,int *x,int *y); + +int fh_png_id(char *name); +int fh_png_load(char *name,unsigned char *buffer, unsigned char **alpha, int x,int y); +int fh_png_getsize(char *name,int *x,int *y); + +int fh_gif_id(char *name); +int fh_gif_load(char *name,unsigned char *buffer, unsigned char **alpha, int x,int y); +int fh_gif_getsize(char *name,int *x,int *y); + +struct image +{ + int width, height; + unsigned char *rgb; + unsigned char *alpha; + int do_free; +}; + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif +unsigned char * simple_resize(unsigned char * orgin,int ox,int oy,int dx,int dy); +unsigned char * alpha_resize(unsigned char * alpha,int ox,int oy,int dx,int dy); +unsigned char * color_average_resize(unsigned char * orgin,int ox,int oy,int dx,int dy); +unsigned char * rotate(unsigned char *i, int ox, int oy, int rot); +unsigned char * alpha_rotate(unsigned char *i, int ox, int oy, int rot); diff --git a/projects/recalbox-fbv/gif.c b/projects/recalbox-fbv/gif.c new file mode 100644 index 0000000000..1eed1ac4f4 --- /dev/null +++ b/projects/recalbox-fbv/gif.c @@ -0,0 +1,226 @@ +/* + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2000, 2001, 2003 Mateusz Golicz + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "config.h" + +#ifdef FBV_SUPPORT_GIF + + #include "fbv.h" + #include + //#include + //#include + #include + //#include + #include + //#include + #include + #include + #include + + #define min(a, b) ((a) < (b) ? (a) : (b)) + #define gflush do { return(FH_ERROR_FILE); } while(false) + #define grflush do { DGifCloseFile(gft, NULL); return(FH_ERROR_FORMAT); } while(false) + #define mgrflush do { free(lb); free(slb); DGifCloseFile(gft, NULL); return(FH_ERROR_FORMAT); } while(false) + //#define agflush return(FH_ERROR_FORMAT); + //#define agrflush { DGifCloseFile(gft); return(FH_ERROR_FORMAT); } + + +int fh_gif_id(char* name) +{ + char id[4]; + int fd = open(name, O_RDONLY); + if (fd == -1) return (0); + read(fd, id, 4); + close(fd); + if (id[0] == 'G' && id[1] == 'I' && id[2] == 'F') return (1); + return (0); +} + +void +m_rend_gif_decodecolormap(const unsigned char* cmb, unsigned char* rgbb, ColorMapObject* cm, int s, int l, int transparency) +{ + (void)s; + (void)transparency; + for (int i = 0; i < l; i++) + { + GifColorType* cmentry = &cm->Colors[cmb[i]]; + *(rgbb++) = cmentry->Red; + *(rgbb++) = cmentry->Green; + *(rgbb++) = cmentry->Blue; + } +} + + +/* Thanks goes here to Mauro Meneghin, who implemented interlaced GIF files support */ + +int fh_gif_load(char* name, unsigned char* buffer, unsigned char** alpha, int x, int y) +{ + (void)x; + (void)y; + int in_nextrow[4] = { 8, 8, 4, 2 }; //interlaced jump to the row current+in_nextrow + int in_beginrow[4] = { 0, 4, 2, 1 }; //begin pass j from that row number + int transparency = -1; //-1 means not transparency present + int ibxs = 0; + GifByteType* extension = NULL; + int extcode = 0; + + GifFileType* gft = DGifOpenFileName(name, NULL); + if (gft == NULL) + { + printf("err5\n"); + gflush; + } ////////// + GifRecordType rt = UNDEFINED_RECORD_TYPE; + do + { + if (DGifGetRecordType(gft, &rt) == GIF_ERROR) + grflush; + switch (rt) + { + case IMAGE_DESC_RECORD_TYPE: + if (DGifGetImageDesc(gft) == GIF_ERROR) + grflush; + int px = gft->Image.Width; + int py = gft->Image.Height; + char* lb = (char*) malloc(px * 3); + char* slb = (char*) malloc(px); + // printf("reading...\n"); + if (lb != NULL && slb != NULL) + { + unsigned char* alphaptr = NULL; + + ColorMapObject* cmap = (gft->Image.ColorMap ? gft->Image.ColorMap : gft->SColorMap); + int cmaps = cmap->ColorCount; + + ibxs = ibxs * 3; + char* fbptr = (char*) buffer; + + if (transparency != -1) + { + alphaptr = malloc(px * py); + *alpha = alphaptr; + } + + if (!(gft->Image.Interlace)) + { + for (int i = 0; i < py; i++, fbptr += px * 3) + { + if (DGifGetLine(gft, (GifPixelType*) slb, px) == GIF_ERROR) + mgrflush; + m_rend_gif_decodecolormap((unsigned char*) slb, (unsigned char*) lb, cmap, cmaps, px, transparency); + memcpy(fbptr, lb, px * 3); + if (alphaptr) + for (int j = 0; j < px; j++) *(alphaptr++) = (((unsigned char*) slb)[j] == transparency) ? 0x00 : 0xff; + } + } + else + { + unsigned char* aptr = NULL; + + for (int j = 0; j < 4; j++) + { + if (alphaptr) + aptr = alphaptr + (in_beginrow[j] * px); + + fbptr = (char*) buffer + (in_beginrow[j] * px * 3); + + for (int i = in_beginrow[j]; + i < py; i += in_nextrow[j], fbptr += px * 3 * in_nextrow[j], aptr += px * in_nextrow[j]) + { + if (DGifGetLine(gft, (GifPixelType*) slb, px) == GIF_ERROR) + mgrflush; ///////////// + m_rend_gif_decodecolormap((unsigned char*) slb, (unsigned char*) lb, cmap, cmaps, px, transparency); + memcpy(fbptr, lb, px * 3); + if (alphaptr) + for (int k = 0; k < px; k++) aptr[k] = (((unsigned char*) slb)[k] == transparency) ? 0x00 : 0xff; + } + } + } + } + if (lb) free(lb); + if (slb) free(slb); + break; + case EXTENSION_RECORD_TYPE: + if (DGifGetExtension(gft, &extcode, &extension) == GIF_ERROR) + grflush; ////////// + if (extcode == 0xf9) //look image transparency in graph ctr extension + { + if (extension[1] & 1) + { + transparency = extension[4]; + + } + // tran_off=(int)*extension; + // transparency=(int)*(extension+tran_off); + // printf("transparency: %d\n", transparency); + } + while (extension != NULL) + { + if (DGifGetExtensionNext(gft, &extension) == GIF_ERROR) + grflush; + } + break; + default: break; + } + } while (rt != TERMINATE_RECORD_TYPE); + DGifCloseFile(gft, NULL); + return (FH_ERROR_OK); +} + + +int fh_gif_getsize(char* name, int* x, int* y) +{ + GifByteType* extension = NULL; + int extcode = 0; + + GifFileType* gft = DGifOpenFileName(name, NULL); + if (gft == NULL) gflush; + GifRecordType rt = UNDEFINED_RECORD_TYPE; + do + { + if (DGifGetRecordType(gft, &rt) == GIF_ERROR) + grflush; + switch (rt) + { + case IMAGE_DESC_RECORD_TYPE: + + if (DGifGetImageDesc(gft) == GIF_ERROR) + grflush; + int px = gft->Image.Width; + int py = gft->Image.Height; + *x = px; + *y = py; + DGifCloseFile(gft, NULL); + return (FH_ERROR_OK); + case EXTENSION_RECORD_TYPE: + if (DGifGetExtension(gft, &extcode, &extension) == GIF_ERROR) + grflush; + while (extension != NULL) + { + if (DGifGetExtensionNext(gft, &extension) == GIF_ERROR) + grflush; + } + break; + default: break; + } + } while (rt != TERMINATE_RECORD_TYPE); + DGifCloseFile(gft, NULL); + return (FH_ERROR_FORMAT); +} + +#endif diff --git a/projects/recalbox-fbv/jpeg.c b/projects/recalbox-fbv/jpeg.c new file mode 100644 index 0000000000..4b253af7d5 --- /dev/null +++ b/projects/recalbox-fbv/jpeg.c @@ -0,0 +1,144 @@ +/* + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2000, 2001, 2003 Mateusz Golicz + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "config.h" + +#ifdef FBV_SUPPORT_JPEG + + #include +//#include +//#include + #include + #include + #include + #include + #include + #include "fbv.h" + +struct r_jpeg_error_mgr +{ + struct jpeg_error_mgr pub; + jmp_buf envbuffer; +}; + + +int fh_jpeg_id(char* name) +{ + unsigned char id[10]; + int fd = open(name, O_RDONLY); + if (fd == -1) return (0); + read(fd, id, 10); + close(fd); + if (id[6] == 'J' && id[7] == 'F' && id[8] == 'I' && id[9] == 'F') return (1); + if (id[0] == 0xff && id[1] == 0xd8 && id[2] == 0xff) return (1); + return (0); +} + + +void jpeg_cb_error_exit(j_common_ptr cinfo) +{ + struct r_jpeg_error_mgr* mptr = (struct r_jpeg_error_mgr*) cinfo->err; + (*cinfo->err->output_message)(cinfo); + longjmp(mptr->envbuffer, 1); +} + +int fh_jpeg_load(char* filename, unsigned char* buffer, unsigned char** alpha, int x, int y) +{ + (void)alpha; + (void)x; + (void)y; + struct jpeg_decompress_struct cinfo; + struct r_jpeg_error_mgr emgr; + + struct jpeg_decompress_struct* ciptr = &cinfo; + FILE* fh = NULL; + if (!(fh = fopen(filename, "rb"))) return (FH_ERROR_FILE); + ciptr->err = jpeg_std_error(&emgr.pub); + emgr.pub.error_exit = jpeg_cb_error_exit; + if (setjmp(emgr.envbuffer) == 1) + { + // FATAL ERROR - Free the object and return... + jpeg_destroy_decompress(ciptr); + fclose(fh); + return (FH_ERROR_FORMAT); + } + + jpeg_create_decompress(ciptr); + jpeg_stdio_src(ciptr, fh); + jpeg_read_header(ciptr, TRUE); + ciptr->out_color_space = JCS_RGB; + jpeg_start_decompress(ciptr); + + int px = ciptr->output_width; + //int py = ciptr->output_height; + int c = ciptr->output_components; + + + if (c == 3) + { + JSAMPLE* lb = (*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, c * px); + unsigned char* bp = buffer; + while (ciptr->output_scanline < ciptr->output_height) + { + jpeg_read_scanlines(ciptr, &lb, 1); + memcpy(bp, lb, px * c); + bp += px * c; + } + + } + jpeg_finish_decompress(ciptr); + jpeg_destroy_decompress(ciptr); + fclose(fh); + return (FH_ERROR_OK); +} + +int fh_jpeg_getsize(char* filename, int* x, int* y) +{ + struct jpeg_decompress_struct cinfo; + struct r_jpeg_error_mgr emgr; + + struct jpeg_decompress_struct* ciptr = &cinfo; + FILE* fh = NULL; + if (!(fh = fopen(filename, "rb"))) return (FH_ERROR_FILE); + + ciptr->err = jpeg_std_error(&emgr.pub); + emgr.pub.error_exit = jpeg_cb_error_exit; + if (setjmp(emgr.envbuffer) == 1) + { + // FATAL ERROR - Free the object and return... + jpeg_destroy_decompress(ciptr); + fclose(fh); + return (FH_ERROR_FORMAT); + } + + jpeg_create_decompress(ciptr); + jpeg_stdio_src(ciptr, fh); + jpeg_read_header(ciptr, TRUE); + ciptr->out_color_space = JCS_RGB; + jpeg_start_decompress(ciptr); + int px = ciptr->output_width; + int py = ciptr->output_height; + //int c = ciptr->output_components; + *x = px; + *y = py; + jpeg_destroy_decompress(ciptr); + fclose(fh); + return (FH_ERROR_OK); +} + +#endif diff --git a/projects/recalbox-fbv/main.c b/projects/recalbox-fbv/main.c new file mode 100644 index 0000000000..fae1df3bef --- /dev/null +++ b/projects/recalbox-fbv/main.c @@ -0,0 +1,592 @@ +/* + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2000, 2001, 2003, 2004 Mateusz 'mteg' Golicz + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "fbv.h" + +#define PAN_STEPPING 20 + +static int opt_clear = 1, + opt_alpha = 0, + opt_hide_cursor = 1, + opt_image_info = 1, + opt_stretch = 0, + opt_delay = 0, + opt_enlarge = 0, + opt_ignore_aspect = 0, + opt_loop = 0; + +void setup_console(int t) +{ + struct termios our_termios; + static struct termios old_termios; + + if(t) + { + tcgetattr(0, &old_termios); + memcpy(&our_termios, &old_termios, sizeof(struct termios)); + our_termios.c_lflag &= ~(ECHO | ICANON); + tcsetattr(0, TCSANOW, &our_termios); + } + else + tcsetattr(0, TCSANOW, &old_termios); + +} + +static inline void do_rotate(struct image *i, int rot) +{ + if(rot) + { + unsigned char *image = NULL, *alpha = NULL; + + image = rotate(i->rgb, i->width, i->height, rot); + if(i->alpha) + alpha = alpha_rotate(i->alpha, i->width, i->height, rot); + if(i->do_free) + { + free(i->alpha); + free(i->rgb); + } + + i->rgb = image; + i->alpha = alpha; + i->do_free = 1; + + if(rot & 1) + { + int t = i->width; + i->width = i->height; + i->height = t; + } + } +} + + +static inline void do_enlarge(struct image *i, int screen_width, int screen_height, int ignoreaspect) +{ + if(((i->width > screen_width) || (i->height > screen_height)) && (!ignoreaspect)) + return; + if((i->width < screen_width) || (i->height < screen_height)) + { + int xsize = i->width, ysize = i->height; + unsigned char * image = NULL, * alpha = NULL; + + if(ignoreaspect) + { + if(i->width < screen_width) + xsize = screen_width; + if(i->height < screen_height) + ysize = screen_height; + + goto have_sizes; + } + + if((i->height * screen_width / i->width) <= screen_height) + { + xsize = screen_width; + ysize = i->height * screen_width / i->width; + goto have_sizes; + } + + if((i->width * screen_height / i->height) <= screen_width) + { + xsize = i->width * screen_height / i->height; + ysize = screen_height; + goto have_sizes; + } + return; +have_sizes: + image = simple_resize(i->rgb, i->width, i->height, xsize, ysize); + if(i->alpha) + alpha = alpha_resize(i->alpha, i->width, i->height, xsize, ysize); + + if(i->do_free) + { + free(i->alpha); + free(i->rgb); + } + + i->rgb = image; + i->alpha = alpha; + i->do_free = 1; + i->width = xsize; + i->height = ysize; + } +} + + +static inline void do_fit_to_screen(struct image *i, int screen_width, int screen_height, int ignoreaspect, int cal) +{ + if((i->width > screen_width) || (i->height > screen_height)) + { + unsigned char * new_image = NULL, * new_alpha = NULL; + int nx_size = i->width, ny_size = i->height; + + if(ignoreaspect) + { + if(i->width > screen_width) + nx_size = screen_width; + if(i->height > screen_height) + ny_size = screen_height; + } + else + { + if((i->height * screen_width / i->width) <= screen_height) + { + nx_size = screen_width; + ny_size = i->height * screen_width / i->width; + } + else + { + nx_size = i->width * screen_height / i->height; + ny_size = screen_height; + } + } + + if(cal) + new_image = color_average_resize(i->rgb, i->width, i->height, nx_size, ny_size); + else + new_image = simple_resize(i->rgb, i->width, i->height, nx_size, ny_size); + + if(i->alpha) + new_alpha = alpha_resize(i->alpha, i->width, i->height, nx_size, ny_size); + + if(i->do_free) + { + free(i->alpha); + free(i->rgb); + } + + i->rgb = new_image; + i->alpha = new_alpha; + i->do_free = 1; + i->width = nx_size; + i->height = ny_size; + } +} + + +int show_image(char *filename) +{ + int (*load)(char *, unsigned char *, unsigned char **, int, int) = NULL; + + unsigned char * image = NULL; + unsigned char * alpha = NULL; + + int x_size = 0, y_size = 0, screen_width = 0, screen_height = 0; + int x_pan = 0, y_pan = 0, x_offs = 0, y_offs = 0, refresh = 1, ret = 1; + int delay = opt_delay, retransform = 1; + + int transform_stretch = opt_stretch, transform_enlarge = opt_enlarge, transform_cal = (opt_stretch == 2), + transform_iaspect = opt_ignore_aspect, transform_rotation = 0; + + struct image i; + +#ifdef FBV_SUPPORT_GIF + if(fh_gif_id(filename)) + if(fh_gif_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + { + load = fh_gif_load; + goto identified; + } +#endif + +#ifdef FBV_SUPPORT_PNG + if(fh_png_id(filename)) + if(fh_png_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + { + load = fh_png_load; + goto identified; + } +#endif + +#ifdef FBV_SUPPORT_JPEG + if(fh_jpeg_id(filename)) + if(fh_jpeg_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + { + load = fh_jpeg_load; + goto identified; + } +#endif + +#ifdef FBV_SUPPORT_BMP + if(fh_bmp_id(filename)) + if(fh_bmp_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + { + load = fh_bmp_load; + goto identified; + } +#endif + fprintf(stderr, "%s: Unable to access file or file format unknown.\n", filename); + return(1); + +identified: + + if(!(image = (unsigned char*) malloc(x_size * y_size * 3))) + { + fprintf(stderr, "%s: Out of memory.\n", filename); + goto error_mem; + } + + if(load(filename, image, &alpha, x_size, y_size) != FH_ERROR_OK) + { + fprintf(stderr, "%s: Image data is corrupt?\n", filename); + goto error_mem; + } + + if(!opt_alpha) + { + free(alpha); + alpha = NULL; + } + + + + getCurrentRes(&screen_width, &screen_height); + i.do_free = 0; + while(1) + { + if(retransform) + { + if(i.do_free) + { + free(i.rgb); + free(i.alpha); + } + i.width = x_size; + i.height = y_size; + i.rgb = image; + i.alpha = alpha; + i.do_free = 0; + + + if(transform_rotation) + do_rotate(&i, transform_rotation); + + if(transform_stretch) + do_fit_to_screen(&i, screen_width, screen_height, transform_iaspect, transform_cal); + + if(transform_enlarge) + do_enlarge(&i, screen_width, screen_height, transform_iaspect); + + x_pan = y_pan = 0; + refresh = 1; retransform = 0; + if(opt_clear) + { + printf("\033[H\033[J"); + fflush(stdout); + } + if(opt_image_info) + printf("fbv - The Framebuffer Viewer\n%s\n%d x %d\n", filename, x_size, y_size); + } + if(refresh) + { + if(i.width < screen_width) + x_offs = (screen_width - i.width) / 2; + else + x_offs = 0; + + if(i.height < screen_height) + y_offs = (screen_height - i.height) / 2; + else + y_offs = 0; + + fb_display(i.rgb, i.alpha, i.width, i.height, x_pan, y_pan, x_offs, y_offs); + refresh = 0; + } + if(delay) + { + struct timeval tv; + fd_set fds; + tv.tv_sec = delay / 10; + tv.tv_usec = (delay % 10) * 100000; + FD_ZERO(&fds); + FD_SET(0, &fds); + + if(select(1, &fds, NULL, NULL, &tv) <= 0) + break; + delay = 0; + } + + int c = getchar(); + switch(c) + { + case EOF: + case 'q': + ret = 0; + goto done; + case ' ': + case 10: + case 13: + case '>': + case '.': + goto done; + case '<': case ',': + ret = -1; + goto done; + case 'r': + refresh = 1; + break; + case 'a': case 'D': + if(x_pan == 0) break; + x_pan -= i.width / PAN_STEPPING; + if(x_pan < 0) x_pan = 0; + refresh = 1; + break; + case 'd': case 'C': + if(x_offs) break; + if(x_pan >= (i.width - screen_width)) break; + x_pan += i.width / PAN_STEPPING; + if(x_pan > (i.width - screen_width)) x_pan = i.width - screen_width; + refresh = 1; + break; + case 'w': case 'A': + if(y_pan == 0) break; + y_pan -= i.height / PAN_STEPPING; + if(y_pan < 0) y_pan = 0; + refresh = 1; + break; + case 'x': case 'B': + if(y_offs) break; + if(y_pan >= (i.height - screen_height)) break; + y_pan += i.height / PAN_STEPPING; + if(y_pan > (i.height - screen_height)) y_pan = i.height - screen_height; + refresh = 1; + break; + case 'f': + transform_stretch = !transform_stretch; + retransform = 1; + break; + case 'e': + transform_enlarge = !transform_enlarge; + retransform = 1; + break; + case 'k': + transform_cal = !transform_cal; + retransform = 1; + break; + case 'i': + transform_iaspect = !transform_iaspect; + retransform = 1; + break; + case 'p': + transform_cal = 0; + transform_iaspect = 0; + transform_enlarge = 0; + transform_stretch = 0; + retransform = 1; + break; + case 'n': + transform_rotation -= 1; + if(transform_rotation < 0) + transform_rotation += 4; + retransform = 1; + break; + case 'm': + transform_rotation += 1; + if(transform_rotation > 3) + transform_rotation -= 4; + retransform = 1; + break; + default: + break; + } + + } + +done: + if(opt_clear) + { + printf("\033[H\033[J"); + fflush(stdout); + } + +error_mem: + free(image); + free(alpha); + if(i.do_free) + { + free(i.rgb); + free(i.alpha); + } + return(ret); + +} + +void help(char *name) +{ + printf("Usage: %s [options] image1 image2 image3 ...\n\n" + "Available options:\n" + " --help | -h : Show this help\n" + " --alpha | -a : Use the alpha channel (if applicable)\n" + " --dontclear | -c : Do not clear the screen before and after displaying the image\n" + " --donthide | -u : Do not hide the cursor before and after displaying the image\n" + " --noinfo | -i : Supress image information\n" + " --stretch | -f : Strech (using a simple resizing routine) the image to fit onto screen if necessary\n" + " --colorstretch| -k : Strech (using a 'color average' resizing routine) the image to fit onto screen if necessary\n" + " --enlarge | -e : Enlarge the image to fit the whole screen if necessary\n" + " --ignore-aspect| -r : Ignore the image aspect while resizing\n" + " --delay | -s : Slideshow, 'delay' is the slideshow delay in tenths of seconds.\n\n" + " --loop | -l : Loop after displaying all images\n" + "Keys:\n" + " r : Redraw the image\n" + " a, d, w, x : Pan the image\n" + " f : Toggle resizing on/off\n" + " k : Toggle resizing quality\n" + " e : Toggle enlarging on/off\n" + " i : Toggle respecting the image aspect on/off\n" + " n : Rotate the image 90 degrees left\n" + " m : Rotate the image 90 degrees right\n" + " p : Disable all transformations\n" + "Copyright (C) 2000 - 2004 Mateusz Golicz, Tomasz Sterna.\n", name); +} + +void sighandler(int s) +{ + if(opt_hide_cursor) + { + printf("\033[?25h"); + fflush(stdout); + } + setup_console(0); + _exit(128 + s); + +} + +int main(int argc, char **argv) +{ + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"noclear", no_argument, 0, 'c'}, + {"alpha", no_argument, 0, 'a'}, + {"unhide", no_argument, 0, 'u'}, + {"noinfo", no_argument, 0, 'i'}, + {"stretch", no_argument, 0, 'f'}, + {"colorstrech", no_argument, 0, 'k'}, + {"delay", required_argument, 0, 's'}, + {"enlarge", no_argument, 0, 'e'}, + {"ignore-aspect", no_argument, 0, 'r'}, + {"loop", no_argument, 0, 'l'}, + {0, 0, 0, 0} + }; + + if(argc < 2) + { + help(argv[0]); + fprintf(stderr, "Error: Required argument missing.\n"); + return(1); + } + + for(int c; (c = getopt_long_only(argc, argv, "hcauifks:er", long_options, NULL)) != EOF; ) + { + switch(c) + { + case 'a': + opt_alpha = 1; + break; + case 'c': + opt_clear = 0; + break; + case 's': + opt_delay = (int)strtol(optarg, NULL, 10); + break; + case 'u': + opt_hide_cursor = 0; + break; + case 'h': + help(argv[0]); + return(0); + case 'i': + opt_image_info = 0; + break; + case 'f': + opt_stretch = 1; + break; + case 'k': + opt_stretch = 2; + break; + case 'e': + opt_enlarge = 1; + break; + case 'r': + opt_ignore_aspect = 1; + break; + case 'l': + opt_loop = 1; + break; + default: + break; + } + } + + + if(!argv[optind]) + { + fprintf(stderr, "Required argument missing! Consult %s -h.\n", argv[0]); + return(1); + } + + signal(SIGHUP, sighandler); + signal(SIGINT, sighandler); + signal(SIGQUIT, sighandler); + signal(SIGSEGV, sighandler); + signal(SIGTERM, sighandler); + signal(SIGABRT, sighandler); + + if(opt_hide_cursor) + { + printf("\033[?25l"); + fflush(stdout); + } + + setup_console(1); + + do + { + for (int i = optind; argv[i];) + { + int r = show_image(argv[i]); + + if (!r) break; + + i += r; + if (i < optind) + i = optind; + } + } while(opt_loop != 0); + + setup_console(0); + + if(opt_hide_cursor) + { + printf("\033[?25h"); + fflush(stdout); + } + return(0); +} diff --git a/projects/recalbox-fbv/mkrelease b/projects/recalbox-fbv/mkrelease new file mode 100755 index 0000000000..d5a246a5a9 --- /dev/null +++ b/projects/recalbox-fbv/mkrelease @@ -0,0 +1,17 @@ +#!/bin/bash + +make distclean + +NAME="fbv-`cat VERSION`" +OLDDIR="`pwd`" + +rm -fr fbv-*.tar.gz +cd .. +mv $OLDDIR $NAME + +tar -zcvf $NAME.tar.gz $NAME/ + +mv $NAME $OLDDIR +mv $NAME.tar.gz $OLDDIR + +cd $OLDDIR diff --git a/projects/recalbox-fbv/png.c b/projects/recalbox-fbv/png.c new file mode 100644 index 0000000000..6a169732c1 --- /dev/null +++ b/projects/recalbox-fbv/png.c @@ -0,0 +1,175 @@ +/* + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2000, 2001, 2003 Mateusz Golicz + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "config.h" + +#ifdef FBV_SUPPORT_PNG + + #include + #include "fbv.h" + #include + #include + #include + #include + + //#define PNG_BYTES_TO_CHECK 4 + #ifndef min + #define min(x,y) ((x) < (y) ? (x) : (y)) + #endif + +int fh_png_id(char* name) +{ + char id[4]; + int fd = open(name, O_RDONLY); + if (fd == -1) return (0); + read(fd, id, 4); + close(fd); + if (id[1] == 'P' && id[2] == 'N' && id[3] == 'G') return (1); + return (0); +} + +int fh_png_load(char* name, unsigned char* buffer, unsigned char** alpha, int x, int y) +{ + (void)x; + (void)y; + png_bytep rptr[2]; + FILE* fh = NULL; + + if (!(fh = fopen(name, "rb"))) return (FH_ERROR_FILE); + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) return (FH_ERROR_FORMAT); + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(fh); + return (FH_ERROR_FORMAT); + } + //rp = 0; + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + //if (rp) free(rp); + fclose(fh); + return (FH_ERROR_FORMAT); + } + + png_init_io(png_ptr, fh); + + png_read_info(png_ptr, info_ptr); + png_uint_32 width = 0, height = 0; + int bit_depth = 0, color_type = 0, interlace_type = 0; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); + if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); + if (bit_depth < 8) png_set_packing(png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); + int trans = 0; + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + { + trans = 1; + png_set_tRNS_to_alpha(png_ptr); + } + + if (bit_depth == 16) png_set_strip_16(png_ptr); + int number_passes = png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGB_ALPHA || trans) + { + unsigned char* alpha_buffer = (unsigned char*) malloc(width * height); + unsigned char* aptr = NULL; + + unsigned char* rp = (unsigned char*) malloc(width * 4); + rptr[0] = (png_bytep) rp; + + *alpha = alpha_buffer; + + for (int pass = 0; pass < number_passes; pass++) + { + unsigned char* fbptr = buffer; + aptr = alpha_buffer; + + for (int i = 0; i < height; i++) + { + unsigned char* trp = rp; + + png_read_rows(png_ptr, rptr, NULL, 1); + + for (int n = 0; n < width; n++, fbptr += 3, trp += 4) + { + memcpy(fbptr, trp, 3); + *(aptr++) = trp[3]; + } + } + } + free(rp); + } + else + { + for (int pass = 0; pass < number_passes; pass++) + { + unsigned char* fbptr = buffer; + for (int i = 0; i < height; i++, fbptr += width * 3) + { + rptr[0] = (png_bytep) fbptr; + png_read_rows(png_ptr, rptr, NULL, 1); + } + } + } + png_read_end(png_ptr, info_ptr); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + fclose(fh); + return (FH_ERROR_OK); +} + +int fh_png_getsize(char* name, int* x, int* y) +{ + FILE* fh = NULL; + if (!(fh = fopen(name, "rb"))) return (FH_ERROR_FILE); + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) return (FH_ERROR_FORMAT); + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(fh); + return (FH_ERROR_FORMAT); + } + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + fclose(fh); + return (FH_ERROR_FORMAT); + } + + png_init_io(png_ptr, fh); + png_read_info(png_ptr, info_ptr); + png_uint_32 width = 0, height = 0; + int bit_depth = 0, color_type = 0, interlace_type = 0; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + *x = width; + *y = height; + fclose(fh); + return (FH_ERROR_OK); +} + +#endif diff --git a/projects/recalbox-fbv/transforms.c b/projects/recalbox-fbv/transforms.c new file mode 100644 index 0000000000..e73d70d530 --- /dev/null +++ b/projects/recalbox-fbv/transforms.c @@ -0,0 +1,181 @@ +/* + fbv -- simple image viewer for the linux framebuffer + Copyright (C) 2000, 2001, 2003 Mateusz Golicz + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include +#include +#include + +unsigned char* simple_resize(unsigned char* orgin, int ox, int oy, int dx, int dy) +{ + unsigned char* cr = (unsigned char*) malloc(dx * dy * 3); + assert(cr); + unsigned char* l = cr; + + for (int j = 0; j < dy; j++, l += dx * 3) + { + unsigned char* p = orgin + (j * oy / dy * ox * 3); + for (int i = 0, k = 0; i < dx; i++, k += 3) + { + int ip = i * ox / dx * 3; + l[k] = p[ip]; + l[k + 1] = p[ip + 1]; + l[k + 2] = p[ip + 2]; + } + } + return (cr); +} + +unsigned char* alpha_resize(unsigned char* alpha, int ox, int oy, int dx, int dy) +{ + unsigned char* cr = (unsigned char*) malloc(dx * dy); + unsigned char* l = cr; + + for (int j = 0; j < dy; j++, l += dx) + { + unsigned char* p = alpha + (j * oy / dy * ox); + for (int i = 0, k = 0; i < dx; i++) + l[k++] = p[i * ox / dx]; + } + + return (cr); +} + +unsigned char* color_average_resize(unsigned char* orgin, int ox, int oy, int dx, int dy) +{ + unsigned char* cr = (unsigned char*) malloc(dx * dy * 3); + assert(cr); + unsigned char* p = cr; + + for (int j = 0; j < dy; j++) + { + for (int i = 0; i < dx; i++, p += 3) + { + int xa = i * ox / dx; + int ya = j * oy / dy; + int xb = (i + 1) * ox / dx; + if (xb >= ox) xb = ox - 1; + int yb = (j + 1) * oy / dy; + if (yb >= oy) yb = oy - 1; + int r = 0, g = 0, b =0, sq = 0; + for (int l = ya; l <= yb; l++) + { + unsigned char* q = orgin + ((l * ox + xa) * 3); + for (int k = xa; k <= xb; k++, q += 3, sq++) + { + r += q[0]; + g += q[1]; + b += q[2]; + } + } + p[0] = r / sq; + p[1] = g / sq; + p[2] = b / sq; + } + } + return (cr); +} + +unsigned char* rotate(unsigned char* i, int ox, int oy, int rot) +{ + unsigned char* n = (unsigned char*) malloc(ox * oy * 3), * p = NULL; + assert(n); + + switch (rot) + { + case 1: /* 90 deg right */ + p = n + (oy - 1) * 3; + for (int y = 0; y < oy; y++, p -= 3) + { + unsigned char* r = p; + for (int x = 0; x < ox; x++, r += oy * 3) + { + r[0] = *(i++); + r[1] = *(i++); + r[2] = *(i++); + } + } + break; + case 2: /* 180 deg */ + i += ox * oy * 3; + p = n; + for (int y = ox * oy; y > 0; y--) + { + i -= 3; + p[0] = i[0]; + p[1] = i[1]; + p[2] = i[2]; + p += 3; + } + break; + case 3: /* 90 deg left */ + p = n; + for (int y = 0; y < oy; y++, p += 3) + { + unsigned char* r = p + ((ox * 3) * oy); + for (int x = 0; x < ox; x++) + { + r -= oy * 3; + r[0] = *(i++); + r[1] = *(i++); + r[2] = *(i++); + } + } + break; + default: break; + } + return (n); +} + +unsigned char* alpha_rotate(unsigned char* i, int ox, int oy, int rot) +{ + unsigned char* n = (unsigned char*) malloc(ox * oy), * p = NULL; + assert(n); + + switch (rot) + { + case 1: /* 90 deg right */ + p = n + (oy - 1); + for (int y = 0; y < oy; y++, p--) + { + unsigned char* r = p; + for (int x = 0; x < ox; x++, r += oy) + *r = *(i++); + } + break; + case 2: /* 180 deg */ + i += ox * oy; + p = n; + for (int y = ox * oy; y > 0; y--) + *(p++) = *(i--); + break; + case 3: /* 90 deg left */ + p = n; + for (int y = 0; y < oy; y++, p++) + { + unsigned char* r = p + (ox * oy); + for (int x = 0; x < ox; x++) + { + r -= oy; + *r = *(i++); + } + } + break; + default: break; + } + return (n); +} -- GitLab From f126bbd82741d165636aabd3609e1ed90e7958e1 Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 26 Jul 2020 12:22:17 +0200 Subject: [PATCH 03/11] fix(args): fix missing short option -l --- projects/recalbox-fbv/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/recalbox-fbv/main.c b/projects/recalbox-fbv/main.c index fae1df3bef..54b6a0ff3b 100644 --- a/projects/recalbox-fbv/main.c +++ b/projects/recalbox-fbv/main.c @@ -503,7 +503,7 @@ int main(int argc, char **argv) return(1); } - for(int c; (c = getopt_long_only(argc, argv, "hcauifks:er", long_options, NULL)) != EOF; ) + for(int c; (c = getopt_long_only(argc, argv, "hcauifks:erl", long_options, NULL)) != EOF; ) { switch(c) { -- GitLab From 64f06463baac43ad0ca1fbce80b8bc2771d958d4 Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 26 Jul 2020 13:27:44 +0200 Subject: [PATCH 04/11] chore(build): apply buildroot patches and reformat --- projects/recalbox-fbv/configure | 11 +- projects/recalbox-fbv/fb_display.c | 552 ++++++++++++++++------------- 2 files changed, 308 insertions(+), 255 deletions(-) diff --git a/projects/recalbox-fbv/configure b/projects/recalbox-fbv/configure index 73b8fbabe8..762a2f270a 100755 --- a/projects/recalbox-fbv/configure +++ b/projects/recalbox-fbv/configure @@ -80,6 +80,7 @@ while true ; do esac done +[ -z "$CC" ] && CC=cc [ -z "$prefix" ] && prefix="/usr/local" [ -z "$bindir" ] && bindir="${prefix}/bin" [ -z "$mandir" ] && mandir="${prefix}/man" @@ -106,12 +107,12 @@ xdir="/usr/X11R6" ungif="no" echo "libungif check" >>./config.log echo " 1st:" >>./config.log -cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lungif $libs +$CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lgif $libs if [ -e \$\$~test ]; then - libs="-lungif $libs" ; ungif="yes" + libs="-lgif $libs" ; ungif="yes" else echo " 2nd: -lX11 -L$xdir/lib" >>./config.log - cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lungif -lX11 -L$xdir/lib $libs + $CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lungif -lX11 -L$xdir/lib $libs if [ -e \$\$~test ]; then libs="-lungif -lX11 -L$xdir/lib $libs" ; ungif="yes" fi @@ -124,7 +125,7 @@ echo "libungif: $ungif" >> ./config.log echo -n "checking for libjpeg presence... " if [ "$jpeg" != "disabled" ]; then jpeg="no" -cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -ljpeg $libs +$CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -ljpeg $libs if [ -e \$\$~test ]; then libs="-ljpeg $libs" ; jpeg="yes" fi @@ -135,7 +136,7 @@ echo "libjpeg: $jpeg" >> ./config.log echo -n "checking for libpng presence... " if [ "$png" != "disabled" ]; then png="no" -cc 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lpng $libs +$CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lpng $libs if [ -e \$\$~test ]; then libs="-lpng $libs" ; png="yes" fi diff --git a/projects/recalbox-fbv/fb_display.c b/projects/recalbox-fbv/fb_display.c index 02e579e2c9..0c346db0ee 100644 --- a/projects/recalbox-fbv/fb_display.c +++ b/projects/recalbox-fbv/fb_display.c @@ -18,8 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - #include #include #include @@ -31,7 +29,9 @@ #include #include #include +#include #include "config.h" + /* Public Use Functions: * * extern void fb_display(unsigned char *rgbbuff, @@ -44,312 +44,364 @@ */ unsigned short red[256], green[256], blue[256]; -struct fb_cmap map332 = {0, 256, red, green, blue, NULL}; +struct fb_cmap map332 = { + 0, + 256, + red, + green, + blue, + NULL +}; unsigned short red_b[256], green_b[256], blue_b[256]; -struct fb_cmap map_back = {0, 256, red_b, green_b, blue_b, NULL}; +struct fb_cmap map_back = { + 0, + 256, + red_b, + green_b, + blue_b, + NULL +}; -int openFB(const char *name); +int openFB(const char* name); + void closeFB(int fh); -void getVarScreenInfo(int fh, struct fb_var_screeninfo *var); -void setVarScreenInfo(int fh, struct fb_var_screeninfo *var); -void getFixScreenInfo(int fh, struct fb_fix_screeninfo *fix); + +void getVarScreenInfo(int fh, struct fb_var_screeninfo* var); + +void setVarScreenInfo(int fh, struct fb_var_screeninfo* var); + +void getFixScreenInfo(int fh, struct fb_fix_screeninfo* fix); + void set332map(int fh); -void* convertRGB2FB(int fh, unsigned char *rgbbuff, unsigned long count, int bpp, int *cpp); -void blit2FB(int fh, void *fbbuff, unsigned char *alpha, - unsigned int pic_xs, unsigned int pic_ys, - unsigned int scr_xs, unsigned int scr_ys, - unsigned int xp, unsigned int yp, - unsigned int xoffs, unsigned int yoffs, - int cpp); - -void fb_display(unsigned char *rgbbuff, unsigned char * alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs) + +void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp, int* cpp); + +void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, unsigned int pic_ys, unsigned int scr_xs, + unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp); + +void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, + int y_offs) { - struct fb_var_screeninfo var; - struct fb_fix_screeninfo fix; - unsigned short *fbbuff = NULL; - int fh = -1, bp = 0; - unsigned long x_stride; - - /* get the framebuffer device handle */ - fh = openFB(NULL); - - /* read current video mode */ - getVarScreenInfo(fh, &var); - getFixScreenInfo(fh, &fix); - - x_stride = (fix.line_length * 8) / var.bits_per_pixel; - - /* correct panning */ - if(x_pan > x_size - x_stride) x_pan = 0; - if(y_pan > y_size - var.yres) y_pan = 0; - /* correct offset */ - if(x_offs + x_size > x_stride) x_offs = 0; - if(y_offs + y_size > var.yres) y_offs = 0; - - /* blit buffer 2 fb */ - fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp); -#if 0 - blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres, x_pan, y_pan, x_offs, y_offs, bp); -#else - blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres_virtual, x_pan, y_pan, x_offs, y_offs + var.yoffset, bp); -#endif - free(fbbuff); - - /* close device */ - closeFB(fh); + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + unsigned short* fbbuff = NULL; + int fh = -1, bp = 0; + unsigned long x_stride; + + /* get the framebuffer device handle */ + fh = openFB(NULL); + + /* read current video mode */ + getVarScreenInfo(fh, &var); + getFixScreenInfo(fh, &fix); + + x_stride = (fix.line_length * 8) / var.bits_per_pixel; + + /* correct panning */ + if (x_pan > x_size - x_stride) x_pan = 0; + if (y_pan > y_size - var.yres) y_pan = 0; + /* correct offset */ + if (x_offs + x_size > x_stride) x_offs = 0; + if (y_offs + y_size > var.yres) y_offs = 0; + + /* blit buffer 2 fb */ + fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp); + #if 0 + blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres, x_pan, y_pan, x_offs, y_offs, bp); + #else + blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres_virtual, x_pan, y_pan, x_offs, y_offs + var.yoffset, + bp); + #endif + free(fbbuff); + + /* close device */ + closeFB(fh); } -void getCurrentRes(int *x, int *y) +void getCurrentRes(int* x, int* y) { - struct fb_var_screeninfo var; - int fh = -1; - fh = openFB(NULL); - getVarScreenInfo(fh, &var); - *x = var.xres; - *y = var.yres; - closeFB(fh); + struct fb_var_screeninfo var; + int fh = -1; + fh = openFB(NULL); + getVarScreenInfo(fh, &var); + *x = var.xres; + *y = var.yres; + closeFB(fh); } -int openFB(const char *name) +int openFB(const char* name) { - int fh; - char *dev; + int fh; + char* dev; - if(name == NULL){ - dev = getenv("FRAMEBUFFER"); - if(dev) name = dev; - else name = DEFAULT_FRAMEBUFFER; - } - - if ((fh = open(name, O_RDWR)) == -1){ - fprintf(stderr, "open %s: %s\n", name, strerror(errno)); - exit(1); - } - return fh; + if (name == NULL) + { + dev = getenv("FRAMEBUFFER"); + if (dev) name = dev; + else name = DEFAULT_FRAMEBUFFER; + } + + if ((fh = open(name, O_RDWR)) == -1) + { + fprintf(stderr, "open %s: %s\n", name, strerror(errno)); + exit(1); + } + return fh; } void closeFB(int fh) { - close(fh); + close(fh); } -void getVarScreenInfo(int fh, struct fb_var_screeninfo *var) +void getVarScreenInfo(int fh, struct fb_var_screeninfo* var) { - if (ioctl(fh, FBIOGET_VSCREENINFO, var)){ - fprintf(stderr, "ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); - exit(1); - } + if (ioctl(fh, FBIOGET_VSCREENINFO, var)) + { + fprintf(stderr, "ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + exit(1); + } } -void setVarScreenInfo(int fh, struct fb_var_screeninfo *var) +void setVarScreenInfo(int fh, struct fb_var_screeninfo* var) { - if (ioctl(fh, FBIOPUT_VSCREENINFO, var)){ - fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); - exit(1); - } + if (ioctl(fh, FBIOPUT_VSCREENINFO, var)) + { + fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); + exit(1); + } } -void getFixScreenInfo(int fh, struct fb_fix_screeninfo *fix) +void getFixScreenInfo(int fh, struct fb_fix_screeninfo* fix) { - if (ioctl(fh, FBIOGET_FSCREENINFO, fix)){ - fprintf(stderr, "ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno)); - exit(1); - } + if (ioctl(fh, FBIOGET_FSCREENINFO, fix)) + { + fprintf(stderr, "ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + exit(1); + } } -void make332map(struct fb_cmap *map) +void make332map(struct fb_cmap* map) { - int rs, gs, bs, i; - int r = 8, g = 8, b = 4; - - map->red = red; - map->green = green; - map->blue = blue; - - rs = 256 / (r - 1); - gs = 256 / (g - 1); - bs = 256 / (b - 1); - - for (i = 0; i < 256; i++) { - map->red[i] = (rs * ((i / (g * b)) % r)) * 255; - map->green[i] = (gs * ((i / b) % g)) * 255; - map->blue[i] = (bs * ((i) % b)) * 255; - } + int rs, gs, bs, i; + int r = 8, g = 8, b = 4; + + map->red = red; + map->green = green; + map->blue = blue; + + rs = 256 / (r - 1); + gs = 256 / (g - 1); + bs = 256 / (b - 1); + + for (i = 0; i < 256; i++) + { + map->red[i] = (rs * ((i / (g * b)) % r)) * 255; + map->green[i] = (gs * ((i / b) % g)) * 255; + map->blue[i] = (bs * ((i) % b)) * 255; + } } -void set8map(int fh, struct fb_cmap *map) +void set8map(int fh, struct fb_cmap* map) { - if (ioctl(fh, FBIOPUTCMAP, map) < 0) { - fprintf(stderr, "Error putting colormap"); - exit(1); - } + if (ioctl(fh, FBIOPUTCMAP, map) < 0) + { + fprintf(stderr, "Error putting colormap"); + exit(1); + } } -void get8map(int fh, struct fb_cmap *map) +void get8map(int fh, struct fb_cmap* map) { - if (ioctl(fh, FBIOGETCMAP, map) < 0) { - fprintf(stderr, "Error getting colormap"); - exit(1); - } + if (ioctl(fh, FBIOGETCMAP, map) < 0) + { + fprintf(stderr, "Error getting colormap"); + exit(1); + } } void set332map(int fh) { - make332map(&map332); - set8map(fh, &map332); + make332map(&map332); + set8map(fh, &map332); } -void blit2FB(int fh, void *fbbuff, unsigned char *alpha, - unsigned int pic_xs, unsigned int pic_ys, - unsigned int scr_xs, unsigned int scr_ys, - unsigned int xp, unsigned int yp, - unsigned int xoffs, unsigned int yoffs, - int cpp) +void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, unsigned int pic_ys, unsigned int scr_xs, + unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp) { - int i, xc, yc; - unsigned char *fb; - - unsigned char *fbptr; - unsigned char *imptr; - - xc = (pic_xs > scr_xs) ? scr_xs : pic_xs; - yc = (pic_ys > scr_ys) ? scr_ys : pic_ys; - - fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); - - if(fb == MAP_FAILED) - { - perror("mmap"); - return; - } - - if(cpp == 1) - { - get8map(fh, &map_back); - set332map(fh); - } - - fbptr = fb + (yoffs * scr_xs + xoffs) * cpp; - imptr = fbbuff + (yp * pic_xs + xp) * cpp; - - if(alpha) - { - unsigned char * alphaptr; - int from, to, x; - - alphaptr = alpha + (yp * pic_xs + xp); - - for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp, alphaptr += pic_xs) - { - for(x = 0; x 0x80) from = v; - } - else - { - if(alphaptr[v] < 0x80) - { - to = v; - break; - } - } - } - if(from == -1) - break; - - if(to == -1) to = xc; - - memcpy(fbptr + (from * cpp), imptr + (from * cpp), (to - from - 1) * cpp); - x += to - from - 1; - } - } - } - else - for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp) - memcpy(fbptr, imptr, xc * cpp); - - if(cpp == 1) - set8map(fh, &map_back); - - munmap(fb, scr_xs * scr_ys * cpp); + int i, xc, yc; + unsigned char* fb; + + unsigned char* fbptr; + unsigned char* imptr; + + xc = (pic_xs > scr_xs) ? scr_xs : pic_xs; + yc = (pic_ys > scr_ys) ? scr_ys : pic_ys; + + fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); + + if (fb == MAP_FAILED) + { + perror("mmap"); + return; + } + + if (cpp == 1) + { + get8map(fh, &map_back); + set332map(fh); + } + + fbptr = fb + (yoffs * scr_xs + xoffs) * cpp; + imptr = fbbuff + (yp * pic_xs + xp) * cpp; + + if (alpha) + { + unsigned char* alphaptr; + int from, to, x; + + alphaptr = alpha + (yp * pic_xs + xp); + + for (i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp, alphaptr += pic_xs) + { + for (x = 0; x < xc; x++) + { + int v; + + from = to = -1; + for (v = x; v < xc; v++) + { + if (from == -1) + { + if (alphaptr[v] > 0x80) from = v; + } + else + { + if (alphaptr[v] < 0x80) + { + to = v; + break; + } + } + } + if (from == -1) + break; + + if (to == -1) to = xc; + + memcpy(fbptr + (from * cpp), imptr + (from * cpp), (to - from - 1) * cpp); + x += to - from - 1; + } + } + } + else + for (i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp) + memcpy(fbptr, imptr, xc * cpp); + + if (cpp == 1) + set8map(fh, &map_back); + + munmap(fb, scr_xs * scr_ys * cpp); } inline static unsigned char make8color(unsigned char r, unsigned char g, unsigned char b) { - return ( - (((r >> 5) & 7) << 5) | - (((g >> 5) & 7) << 2) | - ((b >> 6) & 3) ); + return ((((r >> 5) & 7) << 5) | (((g >> 5) & 7) << 2) | ((b >> 6) & 3)); } inline static unsigned short make15color(unsigned char r, unsigned char g, unsigned char b) { - return ( - (((r >> 3) & 31) << 10) | - (((g >> 3) & 31) << 5) | - ((b >> 3) & 31) ); + return ((((r >> 3) & 31) << 10) | (((g >> 3) & 31) << 5) | ((b >> 3) & 31)); +} + +inline static unsigned short make15color_bgr(unsigned char r, unsigned char g, unsigned char b) +{ + return ((((b >> 3) & 31) << 10) | (((g >> 3) & 31) << 5) | ((r >> 3) & 31)); } inline static unsigned short make16color(unsigned char r, unsigned char g, unsigned char b) { - return ( - (((r >> 3) & 31) << 11) | - (((g >> 2) & 63) << 5) | - ((b >> 3) & 31) ); + return ((((r >> 3) & 31) << 11) | (((g >> 2) & 63) << 5) | ((b >> 3) & 31)); } -void* convertRGB2FB(int fh, unsigned char *rgbbuff, unsigned long count, int bpp, int *cpp) +void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp, int* cpp) { - unsigned long i; - void *fbbuff = NULL; - u_int8_t *c_fbbuff; - u_int16_t *s_fbbuff; - u_int32_t *i_fbbuff; + unsigned long i; + void* fbbuff = NULL; + u_int8_t* c_fbbuff = NULL; + u_int16_t* s_fbbuff = NULL; + u_int32_t* i_fbbuff = NULL; - switch(bpp) + switch (bpp) + { + case 8: + { + *cpp = 1; + c_fbbuff = (unsigned char*) malloc(count * sizeof(unsigned char)); + for (i = 0; i < count; i++) + c_fbbuff[i] = make8color(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); + fbbuff = (void*) c_fbbuff; + break; + } + case 15: + { + struct fb_var_screeninfo var; + getVarScreenInfo(fh, &var); + int is_bgr555 = (var.red.offset == 0 && var.green.offset == 5 && var.blue.offset == 10) ? 1 : 0; + *cpp = 2; + s_fbbuff = (unsigned short*) malloc(count * sizeof(unsigned short)); + if (is_bgr555 != 0) + for (i = 0; i < count; i++) + s_fbbuff[i] = make15color_bgr(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); + else + for (i = 0; i < count; i++) + s_fbbuff[i] = make15color(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); + fbbuff = (void*) s_fbbuff; + break; + } + case 16: + { + struct fb_var_screeninfo var; + getVarScreenInfo(fh, &var); + int is_bgr555 = (var.red.offset == 0 && var.green.offset == 5 && var.blue.offset == 10) ? 1 : 0; + *cpp = 2; + s_fbbuff = (unsigned short*) malloc(count * sizeof(unsigned short)); + if (is_bgr555 != 0) + for (i = 0; i < count; i++) + s_fbbuff[i] = make15color_bgr(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); + else + for (i = 0; i < count; i++) + s_fbbuff[i] = make16color(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); + fbbuff = (void*) s_fbbuff; + break; + } + case 24: + { + *cpp = 3; + c_fbbuff = (unsigned char *) malloc(count * 3 * sizeof(unsigned char)); + for(i = 0; i < (3 * count); i += 3) + { + /* Big endian framebuffer. */ + c_fbbuff[i] = rgbbuff[i+2]; + c_fbbuff[i+1] = rgbbuff[i+1]; + c_fbbuff[i+2] = rgbbuff[i]; + } + fbbuff = (void *) c_fbbuff; + break; + } + case 32: { - case 8: - *cpp = 1; - c_fbbuff = (unsigned char *) malloc(count * sizeof(unsigned char)); - for(i = 0; i < count; i++) - c_fbbuff[i] = make8color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]); - fbbuff = (void *) c_fbbuff; - break; - case 15: - *cpp = 2; - s_fbbuff = (unsigned short *) malloc(count * sizeof(unsigned short)); - for(i = 0; i < count ; i++) - s_fbbuff[i] = make15color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]); - fbbuff = (void *) s_fbbuff; - break; - case 16: - *cpp = 2; - s_fbbuff = (unsigned short *) malloc(count * sizeof(unsigned short)); - for(i = 0; i < count ; i++) - s_fbbuff[i] = make16color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]); - fbbuff = (void *) s_fbbuff; - break; - case 24: - case 32: - *cpp = 4; - i_fbbuff = (unsigned int *) malloc(count * sizeof(unsigned int)); - for(i = 0; i < count ; i++) - i_fbbuff[i] = ((rgbbuff[i*3] << 16) & 0xFF0000) | - ((rgbbuff[i*3+1] << 8) & 0xFF00) | - (rgbbuff[i*3+2] & 0xFF); - fbbuff = (void *) i_fbbuff; - break; - default: - fprintf(stderr, "Unsupported video mode! You've got: %dbpp\n", bpp); - exit(1); + *cpp = 4; + i_fbbuff = (unsigned int*) malloc(count * sizeof(unsigned int)); + for (i = 0; i < count; i++) + i_fbbuff[i] = ((rgbbuff[i * 3] << 16) & 0xFF0000) | ((rgbbuff[i * 3 + 1] << 8) & 0xFF00) | + (rgbbuff[i * 3 + 2] & 0xFF); + fbbuff = (void*) i_fbbuff; + break; } - return fbbuff; + default: fprintf(stderr, "Unsupported video mode! You've got: %dbpp\n", bpp); + exit(1); + } + return fbbuff; } -- GitLab From e7d0bbee738eeed2e71b1cc6f9cbb7a5918fe10b Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 26 Jul 2020 16:40:42 +0200 Subject: [PATCH 05/11] chore(console): disable console modifications --- projects/recalbox-fbv/main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/projects/recalbox-fbv/main.c b/projects/recalbox-fbv/main.c index 54b6a0ff3b..d854dbd61d 100644 --- a/projects/recalbox-fbv/main.c +++ b/projects/recalbox-fbv/main.c @@ -559,13 +559,13 @@ int main(int argc, char **argv) signal(SIGTERM, sighandler); signal(SIGABRT, sighandler); - if(opt_hide_cursor) + /*if(opt_hide_cursor) { printf("\033[?25l"); fflush(stdout); } - - setup_console(1); + + setup_console(1);*/ do { @@ -581,12 +581,13 @@ int main(int argc, char **argv) } } while(opt_loop != 0); - setup_console(0); + /*setup_console(0); if(opt_hide_cursor) { printf("\033[?25h"); fflush(stdout); - } + }*/ + return(0); } -- GitLab From 8727bcc066a23a375da7bbee944f7c2c4de0593d Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 26 Jul 2020 16:49:41 +0200 Subject: [PATCH 06/11] chore(console): remove interactivity & fix remaining cursor op --- projects/recalbox-fbv/main.c | 103 +++-------------------------------- 1 file changed, 9 insertions(+), 94 deletions(-) diff --git a/projects/recalbox-fbv/main.c b/projects/recalbox-fbv/main.c index d854dbd61d..068fb22ecf 100644 --- a/projects/recalbox-fbv/main.c +++ b/projects/recalbox-fbv/main.c @@ -41,7 +41,7 @@ static int opt_clear = 1, opt_ignore_aspect = 0, opt_loop = 0; -void setup_console(int t) +/*void setup_console(int t) { struct termios our_termios; static struct termios old_termios; @@ -56,7 +56,7 @@ void setup_console(int t) else tcsetattr(0, TCSANOW, &old_termios); -} +}*/ static inline void do_rotate(struct image *i, int rot) { @@ -296,11 +296,11 @@ identified: x_pan = y_pan = 0; refresh = 1; retransform = 0; - if(opt_clear) + /*if(opt_clear) { printf("\033[H\033[J"); fflush(stdout); - } + }*/ if(opt_image_info) printf("fbv - The Framebuffer Viewer\n%s\n%d x %d\n", filename, x_size, y_size); } @@ -332,99 +332,14 @@ identified: break; delay = 0; } - - int c = getchar(); - switch(c) - { - case EOF: - case 'q': - ret = 0; - goto done; - case ' ': - case 10: - case 13: - case '>': - case '.': - goto done; - case '<': case ',': - ret = -1; - goto done; - case 'r': - refresh = 1; - break; - case 'a': case 'D': - if(x_pan == 0) break; - x_pan -= i.width / PAN_STEPPING; - if(x_pan < 0) x_pan = 0; - refresh = 1; - break; - case 'd': case 'C': - if(x_offs) break; - if(x_pan >= (i.width - screen_width)) break; - x_pan += i.width / PAN_STEPPING; - if(x_pan > (i.width - screen_width)) x_pan = i.width - screen_width; - refresh = 1; - break; - case 'w': case 'A': - if(y_pan == 0) break; - y_pan -= i.height / PAN_STEPPING; - if(y_pan < 0) y_pan = 0; - refresh = 1; - break; - case 'x': case 'B': - if(y_offs) break; - if(y_pan >= (i.height - screen_height)) break; - y_pan += i.height / PAN_STEPPING; - if(y_pan > (i.height - screen_height)) y_pan = i.height - screen_height; - refresh = 1; - break; - case 'f': - transform_stretch = !transform_stretch; - retransform = 1; - break; - case 'e': - transform_enlarge = !transform_enlarge; - retransform = 1; - break; - case 'k': - transform_cal = !transform_cal; - retransform = 1; - break; - case 'i': - transform_iaspect = !transform_iaspect; - retransform = 1; - break; - case 'p': - transform_cal = 0; - transform_iaspect = 0; - transform_enlarge = 0; - transform_stretch = 0; - retransform = 1; - break; - case 'n': - transform_rotation -= 1; - if(transform_rotation < 0) - transform_rotation += 4; - retransform = 1; - break; - case 'm': - transform_rotation += 1; - if(transform_rotation > 3) - transform_rotation -= 4; - retransform = 1; - break; - default: - break; - } - } done: - if(opt_clear) + /*if(opt_clear) { printf("\033[H\033[J"); fflush(stdout); - } + }*/ error_mem: free(image); @@ -468,14 +383,14 @@ void help(char *name) void sighandler(int s) { - if(opt_hide_cursor) + /*if(opt_hide_cursor) { printf("\033[?25h"); fflush(stdout); } - setup_console(0); + setup_console(0);*/ + _exit(128 + s); - } int main(int argc, char **argv) -- GitLab From f0950776850b4722b4e246615e2e96b36dd381b5 Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 26 Jul 2020 18:04:35 +0200 Subject: [PATCH 07/11] perf: remove & rework some code --- projects/recalbox-fbv/fb_display.c | 27 +- projects/recalbox-fbv/fbv.h | 2 +- projects/recalbox-fbv/main.c | 707 +++++++++++------------------ projects/recalbox-fbv/transforms.c | 92 +--- 4 files changed, 298 insertions(+), 530 deletions(-) diff --git a/projects/recalbox-fbv/fb_display.c b/projects/recalbox-fbv/fb_display.c index 0c346db0ee..bb6ae80abb 100644 --- a/projects/recalbox-fbv/fb_display.c +++ b/projects/recalbox-fbv/fb_display.c @@ -77,17 +77,18 @@ void set332map(int fh); void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp, int* cpp); +void clearFB(int fh, unsigned int scr_xs, unsigned int scr_ys, int cpp); + void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, unsigned int pic_ys, unsigned int scr_xs, unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp); void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, - int y_offs) + int y_offs, int clear_before) { struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; unsigned short* fbbuff = NULL; int fh = -1, bp = 0; - unsigned long x_stride; /* get the framebuffer device handle */ fh = openFB(NULL); @@ -96,7 +97,7 @@ void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_ getVarScreenInfo(fh, &var); getFixScreenInfo(fh, &fix); - x_stride = (fix.line_length * 8) / var.bits_per_pixel; + unsigned long x_stride = (fix.line_length * 8) / var.bits_per_pixel; /* correct panning */ if (x_pan > x_size - x_stride) x_pan = 0; @@ -107,6 +108,10 @@ void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_ /* blit buffer 2 fb */ fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp); + + if (clear_before) + clearFB(fh, x_stride, var.yres_virtual, bp); + #if 0 blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres, x_pan, y_pan, x_offs, y_offs, bp); #else @@ -227,6 +232,22 @@ void set332map(int fh) set8map(fh, &map332); } +void clearFB(int fh, unsigned int scr_xs, unsigned int scr_ys, int cpp) +{ + unsigned char* fb; + fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); + + if (fb == MAP_FAILED) + { + perror("mmap"); + return; + } + + memset(fb, 0, scr_xs * scr_ys * cpp); + + munmap(fb, scr_xs * scr_ys * cpp); +} + void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, unsigned int pic_ys, unsigned int scr_xs, unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp) { diff --git a/projects/recalbox-fbv/fbv.h b/projects/recalbox-fbv/fbv.h index 1bf53faba9..694a57dbd2 100644 --- a/projects/recalbox-fbv/fbv.h +++ b/projects/recalbox-fbv/fbv.h @@ -21,7 +21,7 @@ #define FH_ERROR_FILE 1 /* read/access error */ #define FH_ERROR_FORMAT 2 /* file format error */ -void fb_display(unsigned char *rgbbuff, unsigned char * alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs); +void fb_display(unsigned char *rgbbuff, unsigned char * alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, int clear_before); void getCurrentRes(int *x, int *y); int fh_bmp_id(char *name); diff --git a/projects/recalbox-fbv/main.c b/projects/recalbox-fbv/main.c index 068fb22ecf..c685b874fb 100644 --- a/projects/recalbox-fbv/main.c +++ b/projects/recalbox-fbv/main.c @@ -18,471 +18,316 @@ */ #include -#include -//#include #include #include #include -#include #include #include #include "config.h" #include "fbv.h" -#define PAN_STEPPING 20 +static int opt_clear = 1, opt_alpha = 0, opt_image_info = 1, opt_stretch = 0, opt_delay = 0, opt_enlarge = 0, opt_ignore_aspect = 0, opt_loop = 0; -static int opt_clear = 1, - opt_alpha = 0, - opt_hide_cursor = 1, - opt_image_info = 1, - opt_stretch = 0, - opt_delay = 0, - opt_enlarge = 0, - opt_ignore_aspect = 0, - opt_loop = 0; - -/*void setup_console(int t) -{ - struct termios our_termios; - static struct termios old_termios; - - if(t) - { - tcgetattr(0, &old_termios); - memcpy(&our_termios, &old_termios, sizeof(struct termios)); - our_termios.c_lflag &= ~(ECHO | ICANON); - tcsetattr(0, TCSANOW, &our_termios); - } - else - tcsetattr(0, TCSANOW, &old_termios); - -}*/ - -static inline void do_rotate(struct image *i, int rot) +static inline void do_enlarge(struct image* i, int screen_width, int screen_height, int ignoreaspect) { - if(rot) - { - unsigned char *image = NULL, *alpha = NULL; - - image = rotate(i->rgb, i->width, i->height, rot); - if(i->alpha) - alpha = alpha_rotate(i->alpha, i->width, i->height, rot); - if(i->do_free) - { - free(i->alpha); - free(i->rgb); - } - - i->rgb = image; - i->alpha = alpha; - i->do_free = 1; - - if(rot & 1) - { - int t = i->width; - i->width = i->height; - i->height = t; - } - } -} + if (((i->width > screen_width) || (i->height > screen_height)) && (!ignoreaspect)) + return; + if ((i->width < screen_width) || (i->height < screen_height)) + { + int xsize = i->width, ysize = i->height; + unsigned char* image = NULL, * alpha = NULL; + + if (ignoreaspect) + { + if (i->width < screen_width) + xsize = screen_width; + if (i->height < screen_height) + ysize = screen_height; + goto have_sizes; + } -static inline void do_enlarge(struct image *i, int screen_width, int screen_height, int ignoreaspect) -{ - if(((i->width > screen_width) || (i->height > screen_height)) && (!ignoreaspect)) - return; - if((i->width < screen_width) || (i->height < screen_height)) - { - int xsize = i->width, ysize = i->height; - unsigned char * image = NULL, * alpha = NULL; - - if(ignoreaspect) - { - if(i->width < screen_width) - xsize = screen_width; - if(i->height < screen_height) - ysize = screen_height; - - goto have_sizes; - } - - if((i->height * screen_width / i->width) <= screen_height) - { - xsize = screen_width; - ysize = i->height * screen_width / i->width; - goto have_sizes; - } - - if((i->width * screen_height / i->height) <= screen_width) - { - xsize = i->width * screen_height / i->height; - ysize = screen_height; - goto have_sizes; - } - return; -have_sizes: - image = simple_resize(i->rgb, i->width, i->height, xsize, ysize); - if(i->alpha) - alpha = alpha_resize(i->alpha, i->width, i->height, xsize, ysize); - - if(i->do_free) - { - free(i->alpha); - free(i->rgb); - } - - i->rgb = image; - i->alpha = alpha; - i->do_free = 1; - i->width = xsize; - i->height = ysize; - } + if ((i->height * screen_width / i->width) <= screen_height) + { + xsize = screen_width; + ysize = i->height * screen_width / i->width; + goto have_sizes; + } + + if ((i->width * screen_height / i->height) <= screen_width) + { + xsize = i->width * screen_height / i->height; + ysize = screen_height; + goto have_sizes; + } + return; + have_sizes: + image = simple_resize(i->rgb, i->width, i->height, xsize, ysize); + if (i->alpha) + alpha = alpha_resize(i->alpha, i->width, i->height, xsize, ysize); + + if (i->do_free) + { + free(i->alpha); + free(i->rgb); + } + + i->rgb = image; + i->alpha = alpha; + i->do_free = 1; + i->width = xsize; + i->height = ysize; + } } -static inline void do_fit_to_screen(struct image *i, int screen_width, int screen_height, int ignoreaspect, int cal) +static inline void do_fit_to_screen(struct image* i, int screen_width, int screen_height, int ignoreaspect, int cal) { - if((i->width > screen_width) || (i->height > screen_height)) - { - unsigned char * new_image = NULL, * new_alpha = NULL; - int nx_size = i->width, ny_size = i->height; - - if(ignoreaspect) - { - if(i->width > screen_width) - nx_size = screen_width; - if(i->height > screen_height) - ny_size = screen_height; - } - else - { - if((i->height * screen_width / i->width) <= screen_height) - { - nx_size = screen_width; - ny_size = i->height * screen_width / i->width; - } - else - { - nx_size = i->width * screen_height / i->height; - ny_size = screen_height; - } - } - - if(cal) - new_image = color_average_resize(i->rgb, i->width, i->height, nx_size, ny_size); - else - new_image = simple_resize(i->rgb, i->width, i->height, nx_size, ny_size); - - if(i->alpha) - new_alpha = alpha_resize(i->alpha, i->width, i->height, nx_size, ny_size); - - if(i->do_free) - { - free(i->alpha); - free(i->rgb); - } - - i->rgb = new_image; - i->alpha = new_alpha; - i->do_free = 1; - i->width = nx_size; - i->height = ny_size; - } + if ((i->width > screen_width) || (i->height > screen_height)) + { + unsigned char* new_image = NULL, * new_alpha = NULL; + int nx_size = i->width, ny_size = i->height; + + if (ignoreaspect) + { + if (i->width > screen_width) + nx_size = screen_width; + if (i->height > screen_height) + ny_size = screen_height; + } + else + { + if ((i->height * screen_width / i->width) <= screen_height) + { + nx_size = screen_width; + ny_size = i->height * screen_width / i->width; + } + else + { + nx_size = i->width * screen_height / i->height; + ny_size = screen_height; + } + } + + if (cal) + new_image = color_average_resize(i->rgb, i->width, i->height, nx_size, ny_size); + else + new_image = simple_resize(i->rgb, i->width, i->height, nx_size, ny_size); + + if (i->alpha) + new_alpha = alpha_resize(i->alpha, i->width, i->height, nx_size, ny_size); + + if (i->do_free) + { + free(i->alpha); + free(i->rgb); + } + + i->rgb = new_image; + i->alpha = new_alpha; + i->do_free = 1; + i->width = nx_size; + i->height = ny_size; + } } +static int always_false() +{ + return 0; +} -int show_image(char *filename) +int show_image(char* filename) { - int (*load)(char *, unsigned char *, unsigned char **, int, int) = NULL; - - unsigned char * image = NULL; - unsigned char * alpha = NULL; - - int x_size = 0, y_size = 0, screen_width = 0, screen_height = 0; - int x_pan = 0, y_pan = 0, x_offs = 0, y_offs = 0, refresh = 1, ret = 1; - int delay = opt_delay, retransform = 1; - - int transform_stretch = opt_stretch, transform_enlarge = opt_enlarge, transform_cal = (opt_stretch == 2), - transform_iaspect = opt_ignore_aspect, transform_rotation = 0; - - struct image i; - + int (* load)(char*, unsigned char*, unsigned char**, int, int) = NULL; + + unsigned char* image = NULL; + unsigned char* alpha = NULL; + + int x_size = 0, y_size = 0, screen_width = 0, screen_height = 0; + int ret = 1; + + int transform_stretch = opt_stretch, transform_enlarge = opt_enlarge, + transform_cal = (opt_stretch == 2), transform_iaspect = opt_ignore_aspect; + + struct image i; + + if (always_false()) + { + } #ifdef FBV_SUPPORT_GIF - if(fh_gif_id(filename)) - if(fh_gif_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) - { - load = fh_gif_load; - goto identified; - } + else if (fh_gif_id(filename)) + { + if (fh_gif_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + load = fh_gif_load; + } #endif - #ifdef FBV_SUPPORT_PNG - if(fh_png_id(filename)) - if(fh_png_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) - { - load = fh_png_load; - goto identified; - } + else if (fh_png_id(filename)) + { + if (fh_png_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + load = fh_png_load; + } #endif - #ifdef FBV_SUPPORT_JPEG - if(fh_jpeg_id(filename)) - if(fh_jpeg_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) - { - load = fh_jpeg_load; - goto identified; - } + else if (fh_jpeg_id(filename)) + { + if (fh_jpeg_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + load = fh_jpeg_load; + } #endif - #ifdef FBV_SUPPORT_BMP - if(fh_bmp_id(filename)) - if(fh_bmp_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) - { - load = fh_bmp_load; - goto identified; - } + else if (fh_bmp_id(filename)) + { + if (fh_bmp_getsize(filename, &x_size, &y_size) == FH_ERROR_OK) + load = fh_bmp_load; + } #endif - fprintf(stderr, "%s: Unable to access file or file format unknown.\n", filename); - return(1); - -identified: - - if(!(image = (unsigned char*) malloc(x_size * y_size * 3))) - { - fprintf(stderr, "%s: Out of memory.\n", filename); - goto error_mem; - } - - if(load(filename, image, &alpha, x_size, y_size) != FH_ERROR_OK) - { - fprintf(stderr, "%s: Image data is corrupt?\n", filename); - goto error_mem; - } - - if(!opt_alpha) - { - free(alpha); - alpha = NULL; - } - - - - getCurrentRes(&screen_width, &screen_height); - i.do_free = 0; - while(1) - { - if(retransform) - { - if(i.do_free) - { - free(i.rgb); - free(i.alpha); - } - i.width = x_size; - i.height = y_size; - i.rgb = image; - i.alpha = alpha; - i.do_free = 0; - - - if(transform_rotation) - do_rotate(&i, transform_rotation); - - if(transform_stretch) - do_fit_to_screen(&i, screen_width, screen_height, transform_iaspect, transform_cal); - - if(transform_enlarge) - do_enlarge(&i, screen_width, screen_height, transform_iaspect); - - x_pan = y_pan = 0; - refresh = 1; retransform = 0; - /*if(opt_clear) - { - printf("\033[H\033[J"); - fflush(stdout); - }*/ - if(opt_image_info) - printf("fbv - The Framebuffer Viewer\n%s\n%d x %d\n", filename, x_size, y_size); - } - if(refresh) - { - if(i.width < screen_width) - x_offs = (screen_width - i.width) / 2; - else - x_offs = 0; - - if(i.height < screen_height) - y_offs = (screen_height - i.height) / 2; - else - y_offs = 0; - - fb_display(i.rgb, i.alpha, i.width, i.height, x_pan, y_pan, x_offs, y_offs); - refresh = 0; - } - if(delay) - { - struct timeval tv; - fd_set fds; - tv.tv_sec = delay / 10; - tv.tv_usec = (delay % 10) * 100000; - FD_ZERO(&fds); - FD_SET(0, &fds); - - if(select(1, &fds, NULL, NULL, &tv) <= 0) - break; - delay = 0; - } - } - -done: - /*if(opt_clear) - { - printf("\033[H\033[J"); - fflush(stdout); - }*/ - -error_mem: - free(image); - free(alpha); - if(i.do_free) - { - free(i.rgb); - free(i.alpha); - } - return(ret); + else + { + fprintf(stderr, "%s: Unable to access file or file format unknown.\n", filename); + return (1); + } + + if (!(image = (unsigned char*) malloc(x_size * y_size * 3))) + { + fprintf(stderr, "%s: Out of memory.\n", filename); + goto error_mem; + } + + if (load(filename, image, &alpha, x_size, y_size) != FH_ERROR_OK) + { + fprintf(stderr, "%s: Image data is corrupt?\n", filename); + goto error_mem; + } + + if (!opt_alpha) + { + free(alpha); + alpha = NULL; + } + + getCurrentRes(&screen_width, &screen_height); + i.do_free = 0; + i.width = x_size; + i.height = y_size; + i.rgb = image; + i.alpha = alpha; + + if (transform_stretch) + do_fit_to_screen(&i, screen_width, screen_height, transform_iaspect, transform_cal); + + if (transform_enlarge) + do_enlarge(&i, screen_width, screen_height, transform_iaspect); + + if (opt_image_info) + printf("fbv - The Framebuffer Viewer\n%s\n%d x %d\n", filename, x_size, y_size); + + int x_offs = (i.width < screen_width) ? (screen_width - i.width) / 2 : 0; + int y_offs = (i.height < screen_height) ? (screen_height - i.height) / 2 : 0; + + fb_display(i.rgb, i.alpha, i.width, i.height, 0, 0, x_offs, y_offs, opt_clear); + opt_clear = 0; // Clear only once + if (opt_delay != 0) usleep(opt_delay * 100000); + + error_mem: + free(image); + free(alpha); + if (i.do_free) + { + free(i.rgb); + free(i.alpha); + } + return (ret); } -void help(char *name) +void help(char* name) { - printf("Usage: %s [options] image1 image2 image3 ...\n\n" - "Available options:\n" - " --help | -h : Show this help\n" - " --alpha | -a : Use the alpha channel (if applicable)\n" - " --dontclear | -c : Do not clear the screen before and after displaying the image\n" - " --donthide | -u : Do not hide the cursor before and after displaying the image\n" - " --noinfo | -i : Supress image information\n" - " --stretch | -f : Strech (using a simple resizing routine) the image to fit onto screen if necessary\n" - " --colorstretch| -k : Strech (using a 'color average' resizing routine) the image to fit onto screen if necessary\n" - " --enlarge | -e : Enlarge the image to fit the whole screen if necessary\n" - " --ignore-aspect| -r : Ignore the image aspect while resizing\n" - " --delay | -s : Slideshow, 'delay' is the slideshow delay in tenths of seconds.\n\n" - " --loop | -l : Loop after displaying all images\n" - "Keys:\n" - " r : Redraw the image\n" - " a, d, w, x : Pan the image\n" - " f : Toggle resizing on/off\n" - " k : Toggle resizing quality\n" - " e : Toggle enlarging on/off\n" - " i : Toggle respecting the image aspect on/off\n" - " n : Rotate the image 90 degrees left\n" - " m : Rotate the image 90 degrees right\n" - " p : Disable all transformations\n" - "Copyright (C) 2000 - 2004 Mateusz Golicz, Tomasz Sterna.\n", name); + printf("Usage: %s [options] image1 image2 image3 ...\n\n" + "Available options:\n" + " --help | -h : Show this help\n" + " --alpha | -a : Use the alpha channel (if applicable)\n" + " --dontclear | -c : Do not clear the screen before and after displaying the image\n" + " --donthide | -u : Do not hide the cursor before and after displaying the image\n" + " --noinfo | -i : Supress image information\n" + " --stretch | -f : Strech (using a simple resizing routine) the image to fit onto screen if necessary\n" + " --colorstretch| -k : Strech (using a 'color average' resizing routine) the image to fit onto screen if necessary\n" + " --enlarge | -e : Enlarge the image to fit the whole screen if necessary\n" + " --ignore-aspect| -r : Ignore the image aspect while resizing\n" + " --delay | -s : Slideshow, 'delay' is the slideshow delay in tenths of seconds.\n\n" + " --loop | -l : Loop after displaying all images\n" + "Copyright (C) 2000 - 2004 Mateusz Golicz, Tomasz Sterna.\n", name); } void sighandler(int s) { - /*if(opt_hide_cursor) - { - printf("\033[?25h"); - fflush(stdout); - } - setup_console(0);*/ - - _exit(128 + s); + _exit(128 + s); } -int main(int argc, char **argv) +int main(int argc, char** argv) { - static struct option long_options[] = - { - {"help", no_argument, 0, 'h'}, - {"noclear", no_argument, 0, 'c'}, - {"alpha", no_argument, 0, 'a'}, - {"unhide", no_argument, 0, 'u'}, - {"noinfo", no_argument, 0, 'i'}, - {"stretch", no_argument, 0, 'f'}, - {"colorstrech", no_argument, 0, 'k'}, - {"delay", required_argument, 0, 's'}, - {"enlarge", no_argument, 0, 'e'}, - {"ignore-aspect", no_argument, 0, 'r'}, - {"loop", no_argument, 0, 'l'}, - {0, 0, 0, 0} - }; - - if(argc < 2) - { - help(argv[0]); - fprintf(stderr, "Error: Required argument missing.\n"); - return(1); - } - - for(int c; (c = getopt_long_only(argc, argv, "hcauifks:erl", long_options, NULL)) != EOF; ) - { - switch(c) - { - case 'a': - opt_alpha = 1; - break; - case 'c': - opt_clear = 0; - break; - case 's': - opt_delay = (int)strtol(optarg, NULL, 10); - break; - case 'u': - opt_hide_cursor = 0; - break; - case 'h': - help(argv[0]); - return(0); - case 'i': - opt_image_info = 0; - break; - case 'f': - opt_stretch = 1; - break; - case 'k': - opt_stretch = 2; - break; - case 'e': - opt_enlarge = 1; - break; - case 'r': - opt_ignore_aspect = 1; - break; - case 'l': - opt_loop = 1; + static struct option long_options[] = {{"help", no_argument, 0, 'h'}, + {"noclear", no_argument, 0, 'c'}, + {"alpha", no_argument, 0, 'a'}, + {"noinfo", no_argument, 0, 'i'}, + {"stretch", no_argument, 0, 'f'}, + {"colorstrech", no_argument, 0, 'k'}, + {"delay", required_argument, 0, 's'}, + {"enlarge", no_argument, 0, 'e'}, + {"ignore-aspect", no_argument, 0, 'r'}, + {"loop", no_argument, 0, 'l'}, + {0, 0, 0, 0}}; + + int c = argc; + if (c < 2) + { + help(argv[0]); + fprintf(stderr, "Error: Required argument missing.\n"); + return (1); + } + + while((c = getopt_long_only(argc, argv, "hcaifks:erl", long_options, NULL)) != EOF) + { + switch (c) + { + case 'a': opt_alpha = 1; + break; + case 'c': opt_clear = 0; + break; + case 's': opt_delay = (int) strtol(optarg, NULL, 10); + break; + case 'h': help(argv[0]); + return (0); + case 'i': opt_image_info = 0; + break; + case 'f': opt_stretch = 1; break; - default: - break; - } - } - - - if(!argv[optind]) - { - fprintf(stderr, "Required argument missing! Consult %s -h.\n", argv[0]); - return(1); - } - - signal(SIGHUP, sighandler); - signal(SIGINT, sighandler); - signal(SIGQUIT, sighandler); - signal(SIGSEGV, sighandler); - signal(SIGTERM, sighandler); - signal(SIGABRT, sighandler); - - /*if(opt_hide_cursor) - { - printf("\033[?25l"); - fflush(stdout); - } - - setup_console(1);*/ - - do + case 'k': opt_stretch = 2; + break; + case 'e': opt_enlarge = 1; + break; + case 'r': opt_ignore_aspect = 1; + break; + case 'l': opt_loop = 1; + break; + default: break; + } + } + + if (!argv[optind]) + { + fprintf(stderr, "Required argument missing! Consult %s -h.\n", argv[0]); + return (1); + } + + signal(SIGHUP, sighandler); + signal(SIGINT, sighandler); + signal(SIGQUIT, sighandler); + signal(SIGSEGV, sighandler); + signal(SIGTERM, sighandler); + signal(SIGABRT, sighandler); + + do { for (int i = optind; argv[i];) { @@ -494,15 +339,7 @@ int main(int argc, char **argv) if (i < optind) i = optind; } - } while(opt_loop != 0); - - /*setup_console(0); - - if(opt_hide_cursor) - { - printf("\033[?25h"); - fflush(stdout); - }*/ + } while (opt_loop != 0); - return(0); + return (0); } diff --git a/projects/recalbox-fbv/transforms.c b/projects/recalbox-fbv/transforms.c index e73d70d530..1adfdbac82 100644 --- a/projects/recalbox-fbv/transforms.c +++ b/projects/recalbox-fbv/transforms.c @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include + #include #include @@ -89,93 +89,3 @@ unsigned char* color_average_resize(unsigned char* orgin, int ox, int oy, int dx } return (cr); } - -unsigned char* rotate(unsigned char* i, int ox, int oy, int rot) -{ - unsigned char* n = (unsigned char*) malloc(ox * oy * 3), * p = NULL; - assert(n); - - switch (rot) - { - case 1: /* 90 deg right */ - p = n + (oy - 1) * 3; - for (int y = 0; y < oy; y++, p -= 3) - { - unsigned char* r = p; - for (int x = 0; x < ox; x++, r += oy * 3) - { - r[0] = *(i++); - r[1] = *(i++); - r[2] = *(i++); - } - } - break; - case 2: /* 180 deg */ - i += ox * oy * 3; - p = n; - for (int y = ox * oy; y > 0; y--) - { - i -= 3; - p[0] = i[0]; - p[1] = i[1]; - p[2] = i[2]; - p += 3; - } - break; - case 3: /* 90 deg left */ - p = n; - for (int y = 0; y < oy; y++, p += 3) - { - unsigned char* r = p + ((ox * 3) * oy); - for (int x = 0; x < ox; x++) - { - r -= oy * 3; - r[0] = *(i++); - r[1] = *(i++); - r[2] = *(i++); - } - } - break; - default: break; - } - return (n); -} - -unsigned char* alpha_rotate(unsigned char* i, int ox, int oy, int rot) -{ - unsigned char* n = (unsigned char*) malloc(ox * oy), * p = NULL; - assert(n); - - switch (rot) - { - case 1: /* 90 deg right */ - p = n + (oy - 1); - for (int y = 0; y < oy; y++, p--) - { - unsigned char* r = p; - for (int x = 0; x < ox; x++, r += oy) - *r = *(i++); - } - break; - case 2: /* 180 deg */ - i += ox * oy; - p = n; - for (int y = ox * oy; y > 0; y--) - *(p++) = *(i--); - break; - case 3: /* 90 deg left */ - p = n; - for (int y = 0; y < oy; y++, p++) - { - unsigned char* r = p + (ox * oy); - for (int x = 0; x < ox; x++) - { - r -= oy; - *r = *(i++); - } - } - break; - default: break; - } - return (n); -} -- GitLab From 0773633e24cbdf4de09d315cb164b77a0e173e40 Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 26 Jul 2020 18:28:38 +0200 Subject: [PATCH 08/11] chore(build): move from autotools to cmake --- projects/recalbox-fbv/.idea/.name | 1 + projects/recalbox-fbv/CMakeLists.txt | 10 +- projects/recalbox-fbv/ChangeLog | 33 ----- projects/recalbox-fbv/Make.conf | 2 - projects/recalbox-fbv/Makefile | 36 ------ projects/recalbox-fbv/TODO | 23 ---- projects/recalbox-fbv/VERSION | 1 - projects/recalbox-fbv/config.h | 1 - projects/recalbox-fbv/configure | 177 --------------------------- projects/recalbox-fbv/fbv.1 | 58 --------- projects/recalbox-fbv/mkrelease | 17 --- 11 files changed, 5 insertions(+), 354 deletions(-) create mode 100644 projects/recalbox-fbv/.idea/.name delete mode 100644 projects/recalbox-fbv/ChangeLog delete mode 100644 projects/recalbox-fbv/Make.conf delete mode 100644 projects/recalbox-fbv/Makefile delete mode 100644 projects/recalbox-fbv/TODO delete mode 100644 projects/recalbox-fbv/VERSION delete mode 100755 projects/recalbox-fbv/configure delete mode 100644 projects/recalbox-fbv/fbv.1 delete mode 100755 projects/recalbox-fbv/mkrelease diff --git a/projects/recalbox-fbv/.idea/.name b/projects/recalbox-fbv/.idea/.name new file mode 100644 index 0000000000..27a223c909 --- /dev/null +++ b/projects/recalbox-fbv/.idea/.name @@ -0,0 +1 @@ +fbv2 \ No newline at end of file diff --git a/projects/recalbox-fbv/CMakeLists.txt b/projects/recalbox-fbv/CMakeLists.txt index 8d5476f295..d0d61ed2ef 100644 --- a/projects/recalbox-fbv/CMakeLists.txt +++ b/projects/recalbox-fbv/CMakeLists.txt @@ -1,15 +1,13 @@ cmake_minimum_required(VERSION 2.8) -project(fbv C) +project(fbv2 C) set(CMAKE_C_STANDARD 11) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -O0 -g3") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") include_directories(.) -add_executable(fbv +add_executable(fbv2 bmp.c fb_display.c fbv.h @@ -19,4 +17,4 @@ add_executable(fbv png.c transforms.c) -target_link_libraries(fbv gif png jpeg) +target_link_libraries(fbv2 gif png jpeg) diff --git a/projects/recalbox-fbv/ChangeLog b/projects/recalbox-fbv/ChangeLog deleted file mode 100644 index a4cc0916f9..0000000000 --- a/projects/recalbox-fbv/ChangeLog +++ /dev/null @@ -1,33 +0,0 @@ -0.99 2003-08-24 Mateusz Golicz mtg@elsat.net.pl - * fixes in transparent and interlaced GIF & PNG support - * support for using the alpha channel - * docs update - -0.98 2002-12-05 Nat Ersoz nat.ersoz@myrio.com - * fbv now supports the "stride" feature (it works (hopefully) - well when a device supports a line length longer than - the viewable graphics display) - -0.96 2002-01-15 Tomasz Sterna smoku@jaszczur.org - - * BMP files support - (RLE compression and 16bpp not supported yet) - -0.95 2001-08-09 Tomasz Sterna smoku@jaszczur.org - - * dropped autotools - * added tgt-like configure script - -0.94b 2001-02-19 Marcin Zieba piaskowy@irc.pl - - * adding automake support - * manual page - - 2001-02-18 Marcin Zieba piaskowy@irc.pl - - * main.c: added long options support, fixed? segv. Checked, if user supplied filename. - --0.93b 2000-11-23 Tomasz 'smoku' Sterna - Mateusz 'mteg' Golicz - - * added this entry just to be fair, they did it all. diff --git a/projects/recalbox-fbv/Make.conf b/projects/recalbox-fbv/Make.conf deleted file mode 100644 index a420de7ea7..0000000000 --- a/projects/recalbox-fbv/Make.conf +++ /dev/null @@ -1,2 +0,0 @@ -error: - @echo Please run ./configure first... diff --git a/projects/recalbox-fbv/Makefile b/projects/recalbox-fbv/Makefile deleted file mode 100644 index f3b3da4fd2..0000000000 --- a/projects/recalbox-fbv/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# Makefile -# -# Makefile for fbv - -include Make.conf - -CC = gcc -CFLAGS = -O2 -Wall -D_GNU_SOURCE - -SOURCES = main.c jpeg.c gif.c png.c bmp.c fb_display.c transforms.c -OBJECTS = ${SOURCES:.c=.o} - -OUT = fbv -#LIBS = -lungif -L/usr/X11R6/lib -ljpeg -lpng - -all: $(OUT) - @echo Build DONE. - -$(OUT): $(OBJECTS) - $(CC) $(LDFLAGS) -o $(OUT) $(OBJECTS) $(LIBS) - -clean: - rm -f $(OBJECTS) *~ $$$$~* *.bak core config.log $(OUT) - -distclean: clean - @echo -e "error:\n\t@echo Please run ./configure first..." >Make.conf - rm -f $(OUT) config.h - -install: $(OUT) - cp $(OUT) $(DESTDIR)$(bindir) - gzip -9c $(OUT).1 > $(DESTDIR)$(mandir)/man1/$(OUT).1.gz - -uninstall: $(DESTDIR)$(bindir)/$(OUT) - rm -f $(DESTDIR)$(bindir)/$(OUT) - rm -f $(DESTDIR)$(mandir)/man1/$(OUT).1.gz diff --git a/projects/recalbox-fbv/TODO b/projects/recalbox-fbv/TODO deleted file mode 100644 index 5f4ac0d761..0000000000 --- a/projects/recalbox-fbv/TODO +++ /dev/null @@ -1,23 +0,0 @@ -switching off cursor (it's flashing in upper-left corner) => done -support for multiple files =>done - -command-line switches: -no-clear => done -interpolate-resize => done -fast-resize =>done -slideshow =>done - -keymaps: (needed) -+ zoom in -- zoom out - * "fit to screen" zoom => done as a command line option - next picture => done -<- previous picture => done -cursors panning => done - - -'more normal' configure script :))))))) => DONE - - -make it compile and work on Sparc - I need it ;) - added by piaskowy@irc.pl - diff --git a/projects/recalbox-fbv/VERSION b/projects/recalbox-fbv/VERSION deleted file mode 100644 index d74244a170..0000000000 --- a/projects/recalbox-fbv/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.0b diff --git a/projects/recalbox-fbv/config.h b/projects/recalbox-fbv/config.h index 5b0e54b280..19b65d6fda 100644 --- a/projects/recalbox-fbv/config.h +++ b/projects/recalbox-fbv/config.h @@ -1,4 +1,3 @@ -#define IDSTRING "fbv 1.0b, s-tech - recalbox extented" #define DEFAULT_FRAMEBUFFER "/dev/fb0" #define FBV_SUPPORT_GIF #define FBV_SUPPORT_JPEG diff --git a/projects/recalbox-fbv/configure b/projects/recalbox-fbv/configure deleted file mode 100755 index 762a2f270a..0000000000 --- a/projects/recalbox-fbv/configure +++ /dev/null @@ -1,177 +0,0 @@ -#!/bin/sh -## -## fbv configuration script -## - -# See TGT's ./configure script for in-depth comments, becouse this -# one is delivered from it... - -# If You touch anything below, You're asking for trouble - -BASENAME=$(basename "$0") - -unset prefix -unset infodir -unset mandir -unset srcdir -unset bindir -unset libs -unset ungif -unset jpeg -unset png -unset bmp -unset dfb - -help(){ -cat << EOF >&2 -Usage: ./configure [options] -Options: [defaults in brackets after descriptions] - -If a long option shows an argument as mandatory, then it is mandatory -for the equivalent short option also. Similarly for optional arguments. - -General: - --help print this message - --libs=LIBS additional libraries required (try -lX11 for ungif, -lz for PNG) - -Directory and file names: - --prefix=PREFIX install files in PREFIX [/usr/local] - --bindir=DIR binary executable in DIR [PREFIX/lib] - --infodir=DIR info documentation in DIR [PREFIX/info] - --mandir=DIR man documentation in DIR [PREFIX/man] - -Features and packages: - --without-libungif disable libungif support even if found - --without-libjpeg disable libjpeg support even if found - --without-libpng disable libpng support even if found - --without-bmp disable bmp support -EOF -} - -# get options -TEMP=$(getopt -o h \ ---long help,\ -prefix:,srcdir:,bindir:,\ -infodir:,mandir:,\ -without-libungif,without-libjpeg,without-libpng,without-bmp,libs: \ --n "$BASENAME" -- "$@") - -if [ $? != 0 ] ; then help ; exit 1 ; fi -# -eval set -- "$TEMP" - -# process options -while true ; do - case "$1" in - -h|--help) help ; exit 0 ;; - --libs) libs="$2"; shift 2 ;; - --prefix) prefix="$2" ; shift 2 ;; - --srcdir) srcdir="$2" ; shift 2 ;; - --bindir) bindir="$2" ; shift 2 ;; - --infodir) infodir="$2" ; shift 2 ;; - --mandir) mandir="$2" ; shift 2 ;; - --without-libungif) ungif="disabled" ; shift ;; - --without-libjpeg) jpeg="disabled" ; shift ;; - --without-libpng) png="disabled" ; shift ;; - --without-bmp) bmp="disabled" ; shift ;; - - --) shift ; break ;; - *) help ; exit 1 ;; - esac -done - -[ -z "$CC" ] && CC=cc -[ -z "$prefix" ] && prefix="/usr/local" -[ -z "$bindir" ] && bindir="${prefix}/bin" -[ -z "$mandir" ] && mandir="${prefix}/man" -[ -z "$infodir" ] && infodir="${prefix}/info" - -cat << EOF | tee ./config.log >Make.conf -prefix = $prefix -bindir = $bindir -mandir = $mandir -infodir = $infodir -EOF - -# tests -rm -f \$\$~test \$\$~test.c -cat > \$\$~test.c << EOF -main() -{ -} -EOF -### -echo -n "checking for libungif presence... " -if [ "$ungif" != "disabled" ]; then -xdir="/usr/X11R6" -ungif="no" -echo "libungif check" >>./config.log -echo " 1st:" >>./config.log -$CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lgif $libs -if [ -e \$\$~test ]; then - libs="-lgif $libs" ; ungif="yes" -else - echo " 2nd: -lX11 -L$xdir/lib" >>./config.log - $CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lungif -lX11 -L$xdir/lib $libs - if [ -e \$\$~test ]; then - libs="-lungif -lX11 -L$xdir/lib $libs" ; ungif="yes" - fi -fi -rm -f \$\$~test -fi -echo $ungif -echo "libungif: $ungif" >> ./config.log -### -echo -n "checking for libjpeg presence... " -if [ "$jpeg" != "disabled" ]; then -jpeg="no" -$CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -ljpeg $libs -if [ -e \$\$~test ]; then - libs="-ljpeg $libs" ; jpeg="yes" -fi -fi -echo $jpeg -echo "libjpeg: $jpeg" >> ./config.log -### -echo -n "checking for libpng presence... " -if [ "$png" != "disabled" ]; then -png="no" -$CC 2>>./config.log >>./config.log -o \$\$~test \$\$~test.c -lpng $libs -if [ -e \$\$~test ]; then - libs="-lpng $libs" ; png="yes" -fi -fi -echo $png -echo "libpng: $png" >> ./config.log -### -echo -n "building with bmp support... " -if [ "$bmp" != "disabled" ]; then -bmp="yes" -fi -echo $bmp -echo "bmp: $bmp" >> ./config.log -### -rm -f \$\$~test \$\$~test.c -### -echo -n "checking for DEFAULT_FRAMEBUFFER... " -if [ -n "$FRAMEBUFFER" ]; then - dfb="$FRAMEBUFFER" -else - dfb="/dev/fb0" -fi -echo $dfb -echo "fb: $dfb" >> ./config.log -# -echo >>Make.conf -echo "LIBS = $libs" | tee -a ./config.log >>Make.conf -echo "#define IDSTRING \"fbv "`cat VERSION`", s-tech\"" | tee -a ./config.log >config.h -echo "#define DEFAULT_FRAMEBUFFER \"$dfb\"" | tee -a ./config.log >>config.h -[ "$ungif" != "disabled" ] && echo "#define FBV_SUPPORT_GIF" | tee -a ./config.log >>config.h -[ "$jpeg" != "disabled" ] && echo "#define FBV_SUPPORT_JPEG" | tee -a ./config.log >>config.h -[ "$png" != "disabled" ] && echo "#define FBV_SUPPORT_PNG" | tee -a ./config.log >>config.h -[ "$bmp" != "disabled" ] && echo "#define FBV_SUPPORT_BMP" | tee -a ./config.log >>config.h -echo "installation dir: $bindir" -echo "manuals dir: $mandir" - -exit 0 -## EOF diff --git a/projects/recalbox-fbv/fbv.1 b/projects/recalbox-fbv/fbv.1 deleted file mode 100644 index b7e0bb30fb..0000000000 --- a/projects/recalbox-fbv/fbv.1 +++ /dev/null @@ -1,58 +0,0 @@ -.TH fbv 1 "2001-02-18" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -FrameBuffer Viewer -.SH SYNOPSIS -\fBfbv\fP [options] image1 image2 image3 ... -.SH DESCRIPTION -This is a simple program to view pictures on a framebuffer console. -.PP -.nh -.SH OPTIONS -.TP -.BR "\fB--help\fP" , \fB-h\fP -help -.TP -.BR \fB--alpha\fP , \fB-a\fP -Respect alpha channel (if applicable) -.TP -.BR \fB--noclear\fP , \fB-c\fP -Do not clear the screen before/after displaying image -.TP -.BR \fB--unhide\fP , \fB-u\fP -Do not hide/show cursor before/after displaying image -.TP -.BR \fB--noinfo\fP , \fB-i\fP -Do not show image information -.TP -.BR \fB--stretch\fP , \fB-f\fP -Strech (using simple resize) the image to fit onto screen if necessary -.TP -.BR \fB--colorstretch\fP , \fB-k\fP -Strech (using color average resize) the image to fit onto screen if necessary -.TP -.BR \fB--delay\fP , "\fB-s\fP \fI\fP" -Slideshow, wait 'delay' tenths of a second before displaying each image - -.BR - Use a,d,w and x to scroll the image - - - -.SH AUTHOR -Tomasz 'smoku' Sterna -.br -Mateusz 'mteg' Golicz -.br -Marcin 'Piaskowy' Zieba -.br - diff --git a/projects/recalbox-fbv/mkrelease b/projects/recalbox-fbv/mkrelease deleted file mode 100755 index d5a246a5a9..0000000000 --- a/projects/recalbox-fbv/mkrelease +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -make distclean - -NAME="fbv-`cat VERSION`" -OLDDIR="`pwd`" - -rm -fr fbv-*.tar.gz -cd .. -mv $OLDDIR $NAME - -tar -zcvf $NAME.tar.gz $NAME/ - -mv $NAME $OLDDIR -mv $NAME.tar.gz $OLDDIR - -cd $OLDDIR -- GitLab From 4f26e508819aff1716cbf676eb1e45bf4126ada4 Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Sun, 26 Jul 2020 22:27:55 +0200 Subject: [PATCH 09/11] perf(resize): optimize simple resize algorithm --- projects/recalbox-fbv/transforms.c | 35 +++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/projects/recalbox-fbv/transforms.c b/projects/recalbox-fbv/transforms.c index 1adfdbac82..06bc6679cd 100644 --- a/projects/recalbox-fbv/transforms.c +++ b/projects/recalbox-fbv/transforms.c @@ -26,15 +26,40 @@ unsigned char* simple_resize(unsigned char* orgin, int ox, int oy, int dx, int d assert(cr); unsigned char* l = cr; + // Get 16:16 floating point increment + double xStep = (double)ox / (double)dx; + int pfXStep = (int)(xStep * 65536.0); + for (int j = 0; j < dy; j++, l += dx * 3) { unsigned char* p = orgin + (j * oy / dy * ox * 3); - for (int i = 0, k = 0; i < dx; i++, k += 3) + unsigned int ip = 0; + unsigned int* li = ((unsigned int*)l); + for (int i = dx >> 2; --i >= 0; ) + { + unsigned int pip = (ip >> 16) * 3; ip += pfXStep; + unsigned p1 = p[pip] | (p[pip + 1] << 8) | (p[pip + 2] << 16); + pip = (ip >> 16) * 3; ip += pfXStep; + p1 |= (p[pip] << 24); + unsigned p2 = p[pip + 1] | (p[pip + 2] << 8); + pip = (ip >> 16) * 3; ip += pfXStep; + p2 |= (p[pip] << 16) | (p[pip + 1] << 24); + unsigned p3 = p[pip + 2]; + pip = (ip >> 16) * 3; ip += pfXStep; + p3 |= (p[pip] << 8) | (p[pip + 1] << 16) | (p[pip + 2] << 24); + li[0] = p1; + li[1] = p2; + li[2] = p3; + li += 3; + } + unsigned char* lb = ((unsigned char*)li); + for (int i = dx & 3; --i >= 0; ip += pfXStep) { - int ip = i * ox / dx * 3; - l[k] = p[ip]; - l[k + 1] = p[ip + 1]; - l[k + 2] = p[ip + 2]; + unsigned int pip = (ip >> 16) * 3; + lb[0] = p[pip]; + lb[1] = p[pip + 1]; + lb[2] = p[pip + 2]; + lb += 3; } } return (cr); -- GitLab From ed8db1d8787a2ec0418f3a84f3410625b408dcef Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Mon, 27 Jul 2020 08:19:41 +0200 Subject: [PATCH 10/11] style(warnings): fix all warnings --- projects/recalbox-fbv/bmp.c | 260 ++++++++++++++++------------- projects/recalbox-fbv/fb_display.c | 92 ++++------ projects/recalbox-fbv/png.c | 6 +- 3 files changed, 181 insertions(+), 177 deletions(-) diff --git a/projects/recalbox-fbv/bmp.c b/projects/recalbox-fbv/bmp.c index 7c77d89703..5f143c660e 100644 --- a/projects/recalbox-fbv/bmp.c +++ b/projects/recalbox-fbv/bmp.c @@ -20,14 +20,13 @@ #ifdef FBV_SUPPORT_BMP #include "fbv.h" #include -#include #include #include #define BMP_TORASTER_OFFSET 10 #define BMP_SIZE_OFFSET 18 #define BMP_BPP_OFFSET 28 -#define BMP_RLE_OFFSET 30 +//#define BMP_RLE_OFFSET 30 #define BMP_COLOR_OFFSET 54 #define fill4B(a) ( ( 4 - ( (a) % 4 ) ) & 0x03) @@ -40,10 +39,9 @@ struct color { int fh_bmp_id(char *name) { - int fd; char id[2]; - fd = open(name, O_RDONLY); + int fd = open(name, O_RDONLY); if (fd == -1) { return(0); } @@ -59,26 +57,24 @@ int fh_bmp_id(char *name) void fetch_pallete(int fd, struct color pallete[], int count) { unsigned char buff[4]; - int i; lseek(fd, BMP_COLOR_OFFSET, SEEK_SET); - for (i=0; i>4; - buff[2] = buff[0] & 0x0f; - *wr_buffer++ = pallete[buff[1]].red; - *wr_buffer++ = pallete[buff[1]].green; - *wr_buffer++ = pallete[buff[1]].blue; - *wr_buffer++ = pallete[buff[2]].red; - *wr_buffer++ = pallete[buff[2]].green; - *wr_buffer++ = pallete[buff[2]].blue; - } - if (x%2) { - read(fd, buff, 1); - buff[1] = buff[0]>>4; - *wr_buffer++ = pallete[buff[1]].red; - *wr_buffer++ = pallete[buff[1]].green; - *wr_buffer++ = pallete[buff[1]].blue; - } - if (skip) { - read(fd, buff, skip); - } - wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ - } - break; - case 8: /* 8bit palletized */ - skip = fill4B(x); - fetch_pallete(fd, pallete, 256); - lseek(fd, raster, SEEK_SET); - for (i=0; i> 4; + buff[2] = buff[0] & 0x0f; + *wr_buffer++ = pallete[buff[1]].red; + *wr_buffer++ = pallete[buff[1]].green; + *wr_buffer++ = pallete[buff[1]].blue; + *wr_buffer++ = pallete[buff[2]].red; + *wr_buffer++ = pallete[buff[2]].green; + *wr_buffer++ = pallete[buff[2]].blue; + } + if (x % 2) + { + read(fd, buff, 1); + buff[1] = buff[0] >> 4; + *wr_buffer++ = pallete[buff[1]].red; + *wr_buffer++ = pallete[buff[1]].green; + *wr_buffer++ = pallete[buff[1]].blue; + } + if (skip) + { + read(fd, buff, skip); + } + wr_buffer -= x * 6; /* backoff 2 lines - x*2 *3 */ + } + break; + } + case 8: + { /* 8bit palletized */ + int skip = fill4B(x); + fetch_pallete(fd, pallete, 256); + lseek(fd, raster, SEEK_SET); + for (int i = 0; i < y; i++) + { + for (int j = 0; j < x; j++) + { + read(fd, buff, 1); + *wr_buffer++ = pallete[buff[0]].red; + *wr_buffer++ = pallete[buff[0]].green; + *wr_buffer++ = pallete[buff[0]].blue; + } + if (skip) + { + read(fd, buff, skip); + } + wr_buffer -= x * 6; /* backoff 2 lines - x*2 *3 */ + } + break; + } case 16: /* 16bit RGB */ return(FH_ERROR_FORMAT); - break; - case 24: /* 24bit RGB */ - skip = fill4B(x*3); - lseek(fd, raster, SEEK_SET); - for (i=0; i #include #include -#include #include #include #include #include -#include #include #include #include @@ -69,7 +67,7 @@ void closeFB(int fh); void getVarScreenInfo(int fh, struct fb_var_screeninfo* var); -void setVarScreenInfo(int fh, struct fb_var_screeninfo* var); +//void setVarScreenInfo(int fh, struct fb_var_screeninfo* var); void getFixScreenInfo(int fh, struct fb_fix_screeninfo* fix); @@ -87,27 +85,26 @@ void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_ { struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; - unsigned short* fbbuff = NULL; - int fh = -1, bp = 0; + int bp = 0; /* get the framebuffer device handle */ - fh = openFB(NULL); + int fh = openFB(NULL); /* read current video mode */ getVarScreenInfo(fh, &var); getFixScreenInfo(fh, &fix); - unsigned long x_stride = (fix.line_length * 8) / var.bits_per_pixel; + int x_stride = (int)((fix.line_length * 8) / var.bits_per_pixel); /* correct panning */ if (x_pan > x_size - x_stride) x_pan = 0; - if (y_pan > y_size - var.yres) y_pan = 0; + if (y_pan > y_size - (int)var.yres) y_pan = 0; /* correct offset */ if (x_offs + x_size > x_stride) x_offs = 0; - if (y_offs + y_size > var.yres) y_offs = 0; + if (y_offs + y_size > (int)var.yres) y_offs = 0; /* blit buffer 2 fb */ - fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp); + unsigned short* fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp); if (clear_before) clearFB(fh, x_stride, var.yres_virtual, bp); @@ -127,8 +124,7 @@ void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_ void getCurrentRes(int* x, int* y) { struct fb_var_screeninfo var; - int fh = -1; - fh = openFB(NULL); + int fh = openFB(NULL); getVarScreenInfo(fh, &var); *x = var.xres; *y = var.yres; @@ -137,17 +133,15 @@ void getCurrentRes(int* x, int* y) int openFB(const char* name) { - int fh; - char* dev; - if (name == NULL) { - dev = getenv("FRAMEBUFFER"); + char* dev = getenv("FRAMEBUFFER"); if (dev) name = dev; else name = DEFAULT_FRAMEBUFFER; } - if ((fh = open(name, O_RDWR)) == -1) + int fh = open(name, O_RDWR); + if (fh == -1) { fprintf(stderr, "open %s: %s\n", name, strerror(errno)); exit(1); @@ -169,14 +163,14 @@ void getVarScreenInfo(int fh, struct fb_var_screeninfo* var) } } -void setVarScreenInfo(int fh, struct fb_var_screeninfo* var) +/*void setVarScreenInfo(int fh, struct fb_var_screeninfo* var) { if (ioctl(fh, FBIOPUT_VSCREENINFO, var)) { fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); exit(1); } -} +}*/ void getFixScreenInfo(int fh, struct fb_fix_screeninfo* fix) { @@ -189,18 +183,17 @@ void getFixScreenInfo(int fh, struct fb_fix_screeninfo* fix) void make332map(struct fb_cmap* map) { - int rs, gs, bs, i; int r = 8, g = 8, b = 4; map->red = red; map->green = green; map->blue = blue; - rs = 256 / (r - 1); - gs = 256 / (g - 1); - bs = 256 / (b - 1); + int rs = 256 / (r - 1); + int gs = 256 / (g - 1); + int bs = 256 / (b - 1); - for (i = 0; i < 256; i++) + for (int i = 0; i < 256; i++) { map->red[i] = (rs * ((i / (g * b)) % r)) * 255; map->green[i] = (gs * ((i / b) % g)) * 255; @@ -234,8 +227,7 @@ void set332map(int fh) void clearFB(int fh, unsigned int scr_xs, unsigned int scr_ys, int cpp) { - unsigned char* fb; - fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); + unsigned char* fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); if (fb == MAP_FAILED) { @@ -251,16 +243,10 @@ void clearFB(int fh, unsigned int scr_xs, unsigned int scr_ys, int cpp) void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, unsigned int pic_ys, unsigned int scr_xs, unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp) { - int i, xc, yc; - unsigned char* fb; - - unsigned char* fbptr; - unsigned char* imptr; + int xc = (int)((pic_xs > scr_xs) ? scr_xs : pic_xs); + int yc = (int)((pic_ys > scr_ys) ? scr_ys : pic_ys); - xc = (pic_xs > scr_xs) ? scr_xs : pic_xs; - yc = (pic_ys > scr_ys) ? scr_ys : pic_ys; - - fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); + unsigned char* fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); if (fb == MAP_FAILED) { @@ -274,24 +260,19 @@ void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, un set332map(fh); } - fbptr = fb + (yoffs * scr_xs + xoffs) * cpp; - imptr = fbbuff + (yp * pic_xs + xp) * cpp; + unsigned char* fbptr = fb + (yoffs * scr_xs + xoffs) * cpp; + unsigned char* imptr = fbbuff + (yp * pic_xs + xp) * cpp; if (alpha) { - unsigned char* alphaptr; - int from, to, x; - - alphaptr = alpha + (yp * pic_xs + xp); + unsigned char* alphaptr = alpha + (yp * pic_xs + xp); - for (i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp, alphaptr += pic_xs) + for (int i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp, alphaptr += pic_xs) { - for (x = 0; x < xc; x++) + for (int x = 0; x < xc; x++) { - int v; - - from = to = -1; - for (v = x; v < xc; v++) + int from = -1, to = -1; + for (int v = x; v < xc; v++) { if (from == -1) { @@ -317,7 +298,7 @@ void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, un } } else - for (i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp) + for (int i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp) memcpy(fbptr, imptr, xc * cpp); if (cpp == 1) @@ -348,7 +329,6 @@ inline static unsigned short make16color(unsigned char r, unsigned char g, unsig void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp, int* cpp) { - unsigned long i; void* fbbuff = NULL; u_int8_t* c_fbbuff = NULL; u_int16_t* s_fbbuff = NULL; @@ -360,7 +340,7 @@ void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp { *cpp = 1; c_fbbuff = (unsigned char*) malloc(count * sizeof(unsigned char)); - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) c_fbbuff[i] = make8color(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); fbbuff = (void*) c_fbbuff; break; @@ -373,10 +353,10 @@ void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp *cpp = 2; s_fbbuff = (unsigned short*) malloc(count * sizeof(unsigned short)); if (is_bgr555 != 0) - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) s_fbbuff[i] = make15color_bgr(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); else - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) s_fbbuff[i] = make15color(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); fbbuff = (void*) s_fbbuff; break; @@ -389,10 +369,10 @@ void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp *cpp = 2; s_fbbuff = (unsigned short*) malloc(count * sizeof(unsigned short)); if (is_bgr555 != 0) - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) s_fbbuff[i] = make15color_bgr(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); else - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) s_fbbuff[i] = make16color(rgbbuff[i * 3], rgbbuff[i * 3 + 1], rgbbuff[i * 3 + 2]); fbbuff = (void*) s_fbbuff; break; @@ -401,7 +381,7 @@ void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp { *cpp = 3; c_fbbuff = (unsigned char *) malloc(count * 3 * sizeof(unsigned char)); - for(i = 0; i < (3 * count); i += 3) + for(unsigned long i = 0; i < (3 * count); i += 3) { /* Big endian framebuffer. */ c_fbbuff[i] = rgbbuff[i+2]; @@ -415,7 +395,7 @@ void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp { *cpp = 4; i_fbbuff = (unsigned int*) malloc(count * sizeof(unsigned int)); - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) i_fbbuff[i] = ((rgbbuff[i * 3] << 16) & 0xFF0000) | ((rgbbuff[i * 3 + 1] << 8) & 0xFF00) | (rgbbuff[i * 3 + 2] & 0xFF); fbbuff = (void*) i_fbbuff; diff --git a/projects/recalbox-fbv/png.c b/projects/recalbox-fbv/png.c index 6a169732c1..5be110d66c 100644 --- a/projects/recalbox-fbv/png.c +++ b/projects/recalbox-fbv/png.c @@ -106,13 +106,13 @@ int fh_png_load(char* name, unsigned char* buffer, unsigned char** alpha, int x, unsigned char* fbptr = buffer; aptr = alpha_buffer; - for (int i = 0; i < height; i++) + for (int i = 0; i < (int)height; i++) { unsigned char* trp = rp; png_read_rows(png_ptr, rptr, NULL, 1); - for (int n = 0; n < width; n++, fbptr += 3, trp += 4) + for (int n = 0; n < (int)width; n++, fbptr += 3, trp += 4) { memcpy(fbptr, trp, 3); *(aptr++) = trp[3]; @@ -126,7 +126,7 @@ int fh_png_load(char* name, unsigned char* buffer, unsigned char** alpha, int x, for (int pass = 0; pass < number_passes; pass++) { unsigned char* fbptr = buffer; - for (int i = 0; i < height; i++, fbptr += width * 3) + for (int i = 0; i < (int)height; i++, fbptr += width * 3) { rptr[0] = (png_bytep) fbptr; png_read_rows(png_ptr, rptr, NULL, 1); -- GitLab From 22c3acbe812138c3b3f7ad9a8e7505e4ce3c2f5e Mon Sep 17 00:00:00 2001 From: Bkg2k Date: Thu, 5 Nov 2020 07:26:52 +0100 Subject: [PATCH 11/11] fix(oag2): replace mmap/unmap w/ direct framebuffer file access --- projects/recalbox-fbv/fb_display.c | 42 ++++++++++++------------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/projects/recalbox-fbv/fb_display.c b/projects/recalbox-fbv/fb_display.c index 0a20d0e189..885b5b3659 100644 --- a/projects/recalbox-fbv/fb_display.c +++ b/projects/recalbox-fbv/fb_display.c @@ -75,10 +75,9 @@ void set332map(int fh); void* convertRGB2FB(int fh, unsigned char* rgbbuff, unsigned long count, int bpp, int* cpp); -void clearFB(int fh, unsigned int scr_xs, unsigned int scr_ys, int cpp); - void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, unsigned int pic_ys, unsigned int scr_xs, - unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp); + unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp, + int clear_before); void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, int clear_before) @@ -106,14 +105,11 @@ void fb_display(unsigned char* rgbbuff, unsigned char* alpha, int x_size, int y_ /* blit buffer 2 fb */ unsigned short* fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp); - if (clear_before) - clearFB(fh, x_stride, var.yres_virtual, bp); - #if 0 blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres, x_pan, y_pan, x_offs, y_offs, bp); #else blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres_virtual, x_pan, y_pan, x_offs, y_offs + var.yoffset, - bp); + bp, clear_before); #endif free(fbbuff); @@ -225,30 +221,21 @@ void set332map(int fh) set8map(fh, &map332); } -void clearFB(int fh, unsigned int scr_xs, unsigned int scr_ys, int cpp) -{ - unsigned char* fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); - - if (fb == MAP_FAILED) - { - perror("mmap"); - return; - } - - memset(fb, 0, scr_xs * scr_ys * cpp); - - munmap(fb, scr_xs * scr_ys * cpp); -} - void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, unsigned int pic_ys, unsigned int scr_xs, - unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp) + unsigned int scr_ys, unsigned int xp, unsigned int yp, unsigned int xoffs, unsigned int yoffs, int cpp, int clear_before) { int xc = (int)((pic_xs > scr_xs) ? scr_xs : pic_xs); int yc = (int)((pic_ys > scr_ys) ? scr_ys : pic_ys); - unsigned char* fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0); + unsigned char* fb = (unsigned char*)malloc(scr_xs * scr_ys * cpp); + if (clear_before != 0) memset(fb, 0, scr_xs * scr_ys * cpp); + else + { + read(fh, fb, scr_xs * scr_ys * cpp); + lseek(fh, 0, SEEK_SET); + } - if (fb == MAP_FAILED) + if (fb == NULL /*MAP_FAILED*/) { perror("mmap"); return; @@ -304,7 +291,10 @@ void blit2FB(int fh, void* fbbuff, unsigned char* alpha, unsigned int pic_xs, un if (cpp == 1) set8map(fh, &map_back); - munmap(fb, scr_xs * scr_ys * cpp); + if (write(fh, fb, scr_xs * scr_ys * cpp) != scr_xs * scr_ys * cpp) + perror("write"); + lseek(fh, 0, SEEK_SET); + free(fb); } inline static unsigned char make8color(unsigned char r, unsigned char g, unsigned char b) -- GitLab