rockbox/apps/plugins/lib/pluginlib_bmp.c
Thomas Martitz a1842c04f9 lcd-24bit: Introduce a 24-bit mid-level LCD driver
With LCD driver all calculation will be performed on RGB888 and the hardware/OS
can display from our 24bit framebuffer.

It is not yet as performance optimized as the existing drivers but should be
good enough.The vast number of small changes is due to the fact that
fb_data can be a struct type now, while most of the code expected a scalar type.

lcd-as-memframe ASM code does not work with 24bit currently so the with 24bit
it enforces the generic C code.

All plugins are ported over. Except for rockpaint. It uses so much memory that
it wouldnt fit into the 512k plugin buffer anymore (patches welcome).

Change-Id: Ibb1964545028ce0d8ff9833ccc3ab66be3ee0754
2014-06-21 00:15:53 +02:00

167 lines
5.3 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 by Antoine Cellerier <dionoea -at- videolan -dot- org>
* Copyright (C) 2009 by Andrew Mahone
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "pluginlib_bmp.h"
#include "lcd.h"
#include "file.h"
#include "system.h"
#if defined(HAVE_LCD_COLOR)
#define LE16(x) (htole16(x))&0xff, ((htole16(x))>>8)&0xff
#define LE32(x) (htole32(x))&0xff, ((htole32(x))>>8)&0xff, ((htole32(x))>>16)&0xff, ((htole32(x))>>24)&0xff
/**
* Save to 24 bit bitmap.
*/
int save_bmp_file( char* filename, struct bitmap *bm )
{
int line_width = (bm->width*3+3) & ~3;
int padsize = line_width - bm->width*3;
const unsigned char header[] =
{
0x42, 0x4d, /* signature - 'BM' */
LE32( bm->height*line_width + 54 + 4*0 ), /* file size in bytes */
0x00, 0x00, 0x00, 0x00, /* 0, 0 */
LE32( 54 + 4*0 ), /* offset to bitmap */
0x28, 0x00, 0x00, 0x00, /* size of this struct (40) */
LE32( bm->width ), /* bmap width in pixels */
LE32( bm->height ), /* bmap height in pixels */
0x01, 0x00, /* num planes - always 1 */
LE16( 24 ), /* bits per pixel */
LE32( 0 ), /* compression flag */
LE32( bm->height*line_width ), /* image size in bytes */
0xc4, 0x0e, 0x00, 0x00, /* horz resolution */
0xc4, 0x0e, 0x00, 0x00, /* vert resolution */
LE32( 0 ), /* 0 -> color table size */
LE32( 0 ) /* important color count */
};
int fh;
int x,y;
if( bm->format != FORMAT_NATIVE ) return -1;
fh = rb->creat( filename , 0666);
if( fh < 0 ) return -1;
rb->write( fh, header, sizeof( header ) );
for( y = bm->height-1; y >= 0; y-- )
{
for( x = 0; x < bm->width; x++ )
{
fb_data *d = (fb_data*)( bm->data ) + (x+y*bm->width);
unsigned char c[] =
{
FB_UNPACK_BLUE( *d ),
FB_UNPACK_GREEN( *d ),
FB_UNPACK_RED( *d )
};
rb->write( fh, c, 3 );
}
if(padsize != 0)
{
unsigned int c = 0; /* padsize is at most 3. */
rb->write( fh, &c, padsize );
}
}
rb->close( fh );
return 1;
}
#endif /* HAVE_LCD_COLOR */
/**
Very simple image scale from src to dst (nearest neighbour).
Source and destination dimensions are read from the struct bitmap.
FIXME: this doesn't work well for LCD_DEPTH<4
*/
void simple_resize_bitmap(struct bitmap *src, struct bitmap *dst)
{
#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
const int srcw = src->height;
const int srch = src->width;
const int dstw = dst->height;
const int dsth = dst->width;
#else
const int srcw = src->width;
const int srch = src->height;
const int dstw = dst->width;
const int dsth = dst->height;
#endif
const fb_data *srcd = (fb_data *)(src->data);
const fb_data *dstd = (fb_data *)(dst->data);
const long xrstep = ((srcw-1) << 8) / (dstw-1);
const long yrstep = ((srch-1) << 8) / (dsth-1);
fb_data *src_row, *dst_row;
long xr, yr = 0;
int src_x, src_y, dst_x, dst_y;
for (dst_y=0; dst_y < dsth; dst_y++)
{
src_y = (yr >> 8);
src_row = (fb_data *)&srcd[src_y * srcw];
dst_row = (fb_data *)&dstd[dst_y * dstw];
for (xr=0,dst_x=0; dst_x < dstw; dst_x++)
{
src_x = (xr >> 8);
dst_row[dst_x] = src_row[src_x];
xr += xrstep;
}
yr += yrstep;
}
}
#if (LCD_DEPTH < 4)
/**
Same as simple_resize_bitmap except this is for use with greylib.
*/
void grey_resize_bitmap(struct bitmap *src, struct bitmap *dst)
{
const int srcw = src->width;
const int srch = src->height;
const int dstw = dst->width;
const int dsth = dst->height;
const long xrstep = ((srcw-1) << 8) / (dstw-1);
const long yrstep = ((srch-1) << 8) / (dsth-1);
unsigned char *srcd = src->data;
unsigned char *dstd = dst->data;
unsigned char *src_row, *dst_row;
long xr, yr = 0;
int src_x, src_y, dst_x, dst_y;
for (dst_y=0; dst_y < dsth; dst_y++)
{
src_y = (yr >> 8);
src_row = &srcd[src_y * srcw];
dst_row = &dstd[dst_y * dstw];
for (xr=0,dst_x=0; dst_x < dstw; dst_x++)
{
src_x = (xr >> 8);
dst_row[dst_x] = src_row[src_x];
xr += xrstep;
}
yr += yrstep;
}
}
#endif
#include "wrappers.h"
/* import the core bmp loader */
#include "recorder/bmp.c"