Reimported scaling
This commit is contained in:
parent
927d0134c7
commit
a9d407a81e
8 changed files with 490 additions and 26 deletions
16
ChangeLog.scale
Normal file
16
ChangeLog.scale
Normal file
|
@ -0,0 +1,16 @@
|
|||
2009-08-24 Colin D Bennett <colin@gibibit.com>
|
||||
|
||||
Bitmap scaling support.
|
||||
|
||||
* conf/common.rmk (pkglib_MODULES): Add bitmap_scale.mod.
|
||||
(bitmap_scale_mod_SOURCES): New variable.
|
||||
(bitmap_scale_mod_CFLAGS): Likewise.
|
||||
(bitmap_scale_mod_LDFLAGS): Likewise.
|
||||
* include/grub/bitmap_scale.h: New file.
|
||||
* term/gfxterm.c (BACKGROUND_CMD_ARGINDEX_MODE): New definiton.
|
||||
(background_image_cmd_options): New variable.
|
||||
(grub_gfxterm_background_image_cmd): Support bitmap stretching.
|
||||
(cmd): Rename and change type to ...
|
||||
(background_image_cmd_handle): ... this. All users updated.
|
||||
(GRUB_MOD_INIT(term_gfxterm)): Make background_image extended command.
|
||||
* video/bitmap_scale.c: New file.
|
|
@ -567,6 +567,12 @@ bitmap_mod_SOURCES = video/bitmap.c
|
|||
bitmap_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
# For bitmap_scale.mod
|
||||
pkglib_MODULES += bitmap_scale.mod
|
||||
bitmap_scale_mod_SOURCES = video/bitmap_scale.c
|
||||
bitmap_scale_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
bitmap_scale_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
# For tga.mod
|
||||
tga_mod_SOURCES = video/readers/tga.c
|
||||
tga_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
|
|
48
include/grub/bitmap_scale.h
Normal file
48
include/grub/bitmap_scale.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* bitmap_scale.h - Bitmap scaling functions. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_BITMAP_SCALE_HEADER
|
||||
#define GRUB_BITMAP_SCALE_HEADER 1
|
||||
|
||||
#include <grub/err.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
|
||||
enum grub_video_bitmap_scale_method
|
||||
{
|
||||
/* Choose the fastest interpolation algorithm. */
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST,
|
||||
/* Choose the highest quality interpolation algorithm. */
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST,
|
||||
|
||||
/* Specific algorithms: */
|
||||
/* Nearest neighbor interpolation. */
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST,
|
||||
/* Bilinear interpolation. */
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR
|
||||
};
|
||||
|
||||
grub_err_t
|
||||
grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
|
||||
int dst_width, int dst_height,
|
||||
struct grub_video_bitmap *src,
|
||||
enum
|
||||
grub_video_bitmap_scale_method scale_method);
|
||||
|
||||
#endif /* ! GRUB_BITMAP_SCALE_HEADER */
|
|
@ -104,4 +104,7 @@ extern grub_uint32_t grub_xnu_heap_real_start;
|
|||
extern grub_size_t grub_xnu_heap_size;
|
||||
extern char *grub_xnu_heap_start;
|
||||
extern struct grub_video_bitmap *grub_xnu_bitmap;
|
||||
typedef enum {GRUB_XNU_BITMAP_CENTER, GRUB_XNU_BITMAP_STRETCH}
|
||||
grub_xnu_bitmap_mode_t;
|
||||
extern grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode;
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/cpu/xnu.h>
|
||||
#include <grub/video_fb.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
@ -37,6 +38,7 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
|
|||
char *tmp, *modevar;
|
||||
void *framebuffer;
|
||||
grub_err_t err;
|
||||
struct grub_video_bitmap *bitmap = NULL;
|
||||
|
||||
modevar = grub_env_get ("gfxpayload");
|
||||
/* Consider only graphical 32-bit deep modes. */
|
||||
|
@ -63,31 +65,46 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
ret = grub_video_get_info (&mode_info);
|
||||
if (ret)
|
||||
return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters");
|
||||
|
||||
if (grub_xnu_bitmap)
|
||||
{
|
||||
if (grub_xnu_bitmap_mode == GRUB_XNU_BITMAP_STRETCH)
|
||||
err = grub_video_bitmap_create_scaled (&bitmap,
|
||||
mode_info.width,
|
||||
mode_info.height,
|
||||
grub_xnu_bitmap,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
||||
else
|
||||
bitmap = grub_xnu_bitmap;
|
||||
}
|
||||
|
||||
if (bitmap)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
x = mode_info.width - grub_xnu_bitmap->mode_info.width;
|
||||
x = mode_info.width - bitmap->mode_info.width;
|
||||
x /= 2;
|
||||
y = mode_info.height - grub_xnu_bitmap->mode_info.height;
|
||||
y = mode_info.height - bitmap->mode_info.height;
|
||||
y /= 2;
|
||||
err = grub_video_blit_bitmap (grub_xnu_bitmap,
|
||||
err = grub_video_blit_bitmap (bitmap,
|
||||
GRUB_VIDEO_BLIT_REPLACE,
|
||||
x > 0 ? x : 0,
|
||||
y > 0 ? y : 0,
|
||||
x < 0 ? -x : 0,
|
||||
y < 0 ? -y : 0,
|
||||
min (grub_xnu_bitmap->mode_info.width,
|
||||
min (bitmap->mode_info.width,
|
||||
mode_info.width),
|
||||
min (grub_xnu_bitmap->mode_info.height,
|
||||
min (bitmap->mode_info.height,
|
||||
mode_info.height));
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
grub_xnu_bitmap = 0;
|
||||
}
|
||||
err = GRUB_ERR_NONE;
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
bitmap = 0;
|
||||
}
|
||||
|
||||
ret = grub_video_get_info_and_fini (&mode_info, &framebuffer);
|
||||
|
@ -100,8 +117,8 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
|
|||
params->lfb_line_len = mode_info.pitch;
|
||||
|
||||
params->lfb_base = PTR_TO_UINT32 (framebuffer);
|
||||
params->lfb_mode = grub_xnu_bitmap
|
||||
? GRUB_XNU_VIDEO_SPLASH : GRUB_XNU_VIDEO_TEXT_IN_VIDEO;
|
||||
params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH
|
||||
: GRUB_XNU_VIDEO_TEXT_IN_VIDEO;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
37
loader/xnu.c
37
loader/xnu.c
|
@ -31,6 +31,7 @@
|
|||
#include <grub/gzio.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
|
||||
struct grub_xnu_devtree_key *grub_xnu_devtree_root = 0;
|
||||
static int driverspackagenum = 0;
|
||||
|
@ -1272,18 +1273,37 @@ grub_cmd_xnu_kextdir (grub_command_t cmd __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
struct grub_video_bitmap *grub_xnu_bitmap = 0;
|
||||
grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode;
|
||||
|
||||
/* Option array indices. */
|
||||
#define XNU_SPLASH_CMD_ARGINDEX_MODE 0
|
||||
|
||||
static const struct grub_arg_option xnu_splash_cmd_options[] =
|
||||
{
|
||||
{"mode", 'm', 0, "Background image mode.", "stretch|normal",
|
||||
ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_xnu_splash (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_cmd_xnu_splash (grub_extcmd_t cmd,
|
||||
int argc, char *args[])
|
||||
{
|
||||
grub_err_t err;
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
if (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set &&
|
||||
grub_strcmp (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg,
|
||||
"stretch") == 0)
|
||||
grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_STRETCH;
|
||||
else
|
||||
grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_CENTER;
|
||||
|
||||
err = grub_video_bitmap_load (&grub_xnu_bitmap, args[0]);
|
||||
if (err)
|
||||
grub_xnu_bitmap = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1316,8 +1336,10 @@ grub_xnu_unlock ()
|
|||
locked = 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_kernel, cmd_mkext, cmd_kext, cmd_kextdir,
|
||||
cmd_ramdisk, cmd_devtree, cmd_resume, cmd_splash;
|
||||
static grub_command_t cmd_kernel, cmd_mkext, cmd_kext, ;
|
||||
static grub_command_t cmd_devtree;
|
||||
static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_resume;
|
||||
static grub_extcmd_t cmd_splash;
|
||||
|
||||
GRUB_MOD_INIT(xnu)
|
||||
{
|
||||
|
@ -1335,8 +1357,11 @@ GRUB_MOD_INIT(xnu)
|
|||
"It will be seen as md0");
|
||||
cmd_devtree = grub_register_command ("xnu_devtree", grub_cmd_xnu_devtree, 0,
|
||||
"Load XNU devtree");
|
||||
cmd_splash = grub_register_command ("xnu_splash", grub_cmd_xnu_splash, 0,
|
||||
"Load a splash image for XNU");
|
||||
cmd_splash = grub_register_extcmd ("xnu_splash",
|
||||
grub_cmd_xnu_splash,
|
||||
GRUB_COMMAND_FLAG_BOTH, 0,
|
||||
"Load a splash image for XNU",
|
||||
xnu_splash_cmd_options);
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
cmd_resume = grub_register_command ("xnu_resume", grub_cmd_xnu_resume,
|
||||
|
@ -1356,5 +1381,5 @@ GRUB_MOD_FINI(xnu)
|
|||
grub_unregister_command (cmd_devtree);
|
||||
grub_unregister_command (cmd_ramdisk);
|
||||
grub_unregister_command (cmd_kernel);
|
||||
grub_unregister_command (cmd_splash);
|
||||
grub_unregister_extcmd (cmd_splash);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <grub/video.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
|
||||
#define DEFAULT_VIDEO_MODE "auto"
|
||||
#define DEFAULT_BORDER_WIDTH 10
|
||||
|
@ -909,11 +911,23 @@ grub_gfxterm_refresh (void)
|
|||
dirty_region_reset ();
|
||||
}
|
||||
|
||||
/* Option array indices. */
|
||||
#define BACKGROUND_CMD_ARGINDEX_MODE 0
|
||||
|
||||
static const struct grub_arg_option background_image_cmd_options[] =
|
||||
{
|
||||
{"mode", 'm', 0, "Background image mode.", "stretch|normal",
|
||||
ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_gfxterm_background_image_cmd (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)),
|
||||
int argc,
|
||||
char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
|
||||
/* Check that we have video adapter active. */
|
||||
if (grub_video_get_info(NULL) != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
@ -937,6 +951,29 @@ grub_gfxterm_background_image_cmd (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (grub_errno != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
/* Determine if the bitmap should be scaled to fit the screen. */
|
||||
if (!state[BACKGROUND_CMD_ARGINDEX_MODE].set
|
||||
|| grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_MODE].arg,
|
||||
"stretch") == 0)
|
||||
{
|
||||
if (mode_info.width != grub_video_bitmap_get_width (bitmap)
|
||||
|| mode_info.height != grub_video_bitmap_get_height (bitmap))
|
||||
{
|
||||
struct grub_video_bitmap *scaled_bitmap;
|
||||
grub_video_bitmap_create_scaled (&scaled_bitmap,
|
||||
mode_info.width,
|
||||
mode_info.height,
|
||||
bitmap,
|
||||
GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
/* Replace the original bitmap with the scaled one. */
|
||||
grub_video_bitmap_destroy (bitmap);
|
||||
bitmap = scaled_bitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If bitmap was loaded correctly, display it. */
|
||||
if (bitmap)
|
||||
{
|
||||
|
@ -975,18 +1012,22 @@ static struct grub_term_output grub_video_term =
|
|||
.next = 0
|
||||
};
|
||||
|
||||
static grub_command_t cmd;
|
||||
static grub_extcmd_t background_image_cmd_handle;
|
||||
|
||||
GRUB_MOD_INIT(term_gfxterm)
|
||||
{
|
||||
grub_term_register_output ("gfxterm", &grub_video_term);
|
||||
cmd = grub_register_command ("background_image",
|
||||
grub_gfxterm_background_image_cmd,
|
||||
0, "Load background image for active terminal");
|
||||
background_image_cmd_handle =
|
||||
grub_register_extcmd ("background_image",
|
||||
grub_gfxterm_background_image_cmd,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"background_image [-m (stretch|normal)] FILE",
|
||||
"Load background image for active terminal.",
|
||||
background_image_cmd_options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(term_gfxterm)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
grub_unregister_extcmd (background_image_cmd_handle);
|
||||
grub_term_unregister_output (&grub_video_term);
|
||||
}
|
||||
|
|
308
video/bitmap_scale.c
Normal file
308
video/bitmap_scale.c
Normal file
|
@ -0,0 +1,308 @@
|
|||
/* bitmap_scale.c - Bitmap scaling. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/bitmap.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/types.h>
|
||||
|
||||
/* Prototypes for module-local functions. */
|
||||
static grub_err_t scale_nn (struct grub_video_bitmap *dst,
|
||||
struct grub_video_bitmap *src);
|
||||
static grub_err_t scale_bilinear (struct grub_video_bitmap *dst,
|
||||
struct grub_video_bitmap *src);
|
||||
|
||||
/* This function creates a new scaled version of the bitmap SRC. The new
|
||||
bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm
|
||||
is given by SCALE_METHOD. If an error is encountered, the return code is
|
||||
not equal to GRUB_ERR_NONE, and the bitmap DST is either not created, or
|
||||
it is destroyed before this function returns.
|
||||
|
||||
Supports only direct color modes which have components separated
|
||||
into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
|
||||
But because of this simplifying assumption, the implementation is
|
||||
greatly simplified. */
|
||||
grub_err_t
|
||||
grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
|
||||
int dst_width, int dst_height,
|
||||
struct grub_video_bitmap *src,
|
||||
enum grub_video_bitmap_scale_method
|
||||
scale_method)
|
||||
{
|
||||
*dst = 0;
|
||||
|
||||
/* Verify the simplifying assumptions. */
|
||||
if (src == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"null src bitmap in grub_video_bitmap_create_scaled");
|
||||
if (src->mode_info.red_field_pos % 8 != 0
|
||||
|| src->mode_info.green_field_pos % 8 != 0
|
||||
|| src->mode_info.blue_field_pos % 8 != 0
|
||||
|| src->mode_info.reserved_field_pos % 8 != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"src format not supported for scale");
|
||||
if (src->mode_info.width == 0 || src->mode_info.height == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"source bitmap has a zero dimension");
|
||||
if (dst_width <= 0 || dst_height <= 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"requested to scale to a size w/ a zero dimension");
|
||||
if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"bitmap to scale has inconsistent Bpp and bpp");
|
||||
|
||||
/* Create the new bitmap. */
|
||||
grub_err_t ret;
|
||||
ret = grub_video_bitmap_create (dst, dst_width, dst_height,
|
||||
src->mode_info.blit_format);
|
||||
if (ret != GRUB_ERR_NONE)
|
||||
return ret; /* Error. */
|
||||
|
||||
switch (scale_method)
|
||||
{
|
||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST:
|
||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST:
|
||||
ret = scale_nn (*dst, src);
|
||||
break;
|
||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST:
|
||||
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR:
|
||||
ret = scale_bilinear (*dst, src);
|
||||
break;
|
||||
default:
|
||||
ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale_method value");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == GRUB_ERR_NONE)
|
||||
{
|
||||
/* Success: *dst is now a pointer to the scaled bitmap. */
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Destroy the bitmap and return the error code. */
|
||||
grub_video_bitmap_destroy (*dst);
|
||||
*dst = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nearest neighbor bitmap scaling algorithm.
|
||||
|
||||
Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the
|
||||
dimensions of DST. This function uses the nearest neighbor algorithm to
|
||||
interpolate the pixels.
|
||||
|
||||
Supports only direct color modes which have components separated
|
||||
into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
|
||||
But because of this simplifying assumption, the implementation is
|
||||
greatly simplified. */
|
||||
static grub_err_t
|
||||
scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
||||
{
|
||||
/* Verify the simplifying assumptions. */
|
||||
if (dst == 0 || src == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale_nn");
|
||||
if (dst->mode_info.red_field_pos % 8 != 0
|
||||
|| dst->mode_info.green_field_pos % 8 != 0
|
||||
|| dst->mode_info.blue_field_pos % 8 != 0
|
||||
|| dst->mode_info.reserved_field_pos % 8 != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported");
|
||||
if (src->mode_info.red_field_pos % 8 != 0
|
||||
|| src->mode_info.green_field_pos % 8 != 0
|
||||
|| src->mode_info.blue_field_pos % 8 != 0
|
||||
|| src->mode_info.reserved_field_pos % 8 != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported");
|
||||
if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
|
||||
|| dst->mode_info.red_mask_size != src->mode_info.red_mask_size
|
||||
|| dst->mode_info.green_field_pos != src->mode_info.green_field_pos
|
||||
|| dst->mode_info.green_mask_size != src->mode_info.green_mask_size
|
||||
|| dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
|
||||
|| dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
|
||||
|| dst->mode_info.reserved_field_pos !=
|
||||
src->mode_info.reserved_field_pos
|
||||
|| dst->mode_info.reserved_mask_size !=
|
||||
src->mode_info.reserved_mask_size)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
|
||||
if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
|
||||
if (dst->mode_info.width == 0 || dst->mode_info.height == 0
|
||||
|| src->mode_info.width == 0 || src->mode_info.height == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension");
|
||||
|
||||
grub_uint8_t *ddata = dst->data;
|
||||
grub_uint8_t *sdata = src->data;
|
||||
int dw = dst->mode_info.width;
|
||||
int dh = dst->mode_info.height;
|
||||
int sw = src->mode_info.width;
|
||||
int sh = src->mode_info.height;
|
||||
int dstride = dst->mode_info.pitch;
|
||||
int sstride = src->mode_info.pitch;
|
||||
/* bytes_per_pixel is the same for both src and dst. */
|
||||
int bytes_per_pixel = dst->mode_info.bytes_per_pixel;
|
||||
|
||||
int dy;
|
||||
for (dy = 0; dy < dh; dy++)
|
||||
{
|
||||
int dx;
|
||||
for (dx = 0; dx < dw; dx++)
|
||||
{
|
||||
grub_uint8_t *dptr;
|
||||
grub_uint8_t *sptr;
|
||||
int sx;
|
||||
int sy;
|
||||
int comp;
|
||||
|
||||
/* Compute the source coordinate that the destination coordinate
|
||||
maps to. Note: sx/sw = dx/dw => sx = sw*dx/dw. */
|
||||
sx = sw * dx / dw;
|
||||
sy = sh * dy / dh;
|
||||
|
||||
/* Get the address of the pixels in src and dst. */
|
||||
dptr = ddata + dy * dstride + dx * bytes_per_pixel;
|
||||
sptr = sdata + sy * sstride + sx * bytes_per_pixel;
|
||||
|
||||
/* Copy the pixel color value. */
|
||||
for (comp = 0; comp < bytes_per_pixel; comp++)
|
||||
dptr[comp] = sptr[comp];
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Bilinear interpolation image scaling algorithm.
|
||||
|
||||
Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the
|
||||
dimensions of DST. This function uses the bilinear interpolation algorithm
|
||||
to interpolate the pixels.
|
||||
|
||||
Supports only direct color modes which have components separated
|
||||
into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
|
||||
But because of this simplifying assumption, the implementation is
|
||||
greatly simplified. */
|
||||
static grub_err_t
|
||||
scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
|
||||
{
|
||||
/* Verify the simplifying assumptions. */
|
||||
if (dst == 0 || src == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale func");
|
||||
if (dst->mode_info.red_field_pos % 8 != 0
|
||||
|| dst->mode_info.green_field_pos % 8 != 0
|
||||
|| dst->mode_info.blue_field_pos % 8 != 0
|
||||
|| dst->mode_info.reserved_field_pos % 8 != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported");
|
||||
if (src->mode_info.red_field_pos % 8 != 0
|
||||
|| src->mode_info.green_field_pos % 8 != 0
|
||||
|| src->mode_info.blue_field_pos % 8 != 0
|
||||
|| src->mode_info.reserved_field_pos % 8 != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported");
|
||||
if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
|
||||
|| dst->mode_info.red_mask_size != src->mode_info.red_mask_size
|
||||
|| dst->mode_info.green_field_pos != src->mode_info.green_field_pos
|
||||
|| dst->mode_info.green_mask_size != src->mode_info.green_mask_size
|
||||
|| dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
|
||||
|| dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
|
||||
|| dst->mode_info.reserved_field_pos !=
|
||||
src->mode_info.reserved_field_pos
|
||||
|| dst->mode_info.reserved_mask_size !=
|
||||
src->mode_info.reserved_mask_size)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
|
||||
if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
|
||||
if (dst->mode_info.width == 0 || dst->mode_info.height == 0
|
||||
|| src->mode_info.width == 0 || src->mode_info.height == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension");
|
||||
|
||||
grub_uint8_t *ddata = dst->data;
|
||||
grub_uint8_t *sdata = src->data;
|
||||
int dw = dst->mode_info.width;
|
||||
int dh = dst->mode_info.height;
|
||||
int sw = src->mode_info.width;
|
||||
int sh = src->mode_info.height;
|
||||
int dstride = dst->mode_info.pitch;
|
||||
int sstride = src->mode_info.pitch;
|
||||
/* bytes_per_pixel is the same for both src and dst. */
|
||||
int bytes_per_pixel = dst->mode_info.bytes_per_pixel;
|
||||
|
||||
int dy;
|
||||
for (dy = 0; dy < dh; dy++)
|
||||
{
|
||||
int dx;
|
||||
for (dx = 0; dx < dw; dx++)
|
||||
{
|
||||
grub_uint8_t *dptr;
|
||||
grub_uint8_t *sptr;
|
||||
int sx;
|
||||
int sy;
|
||||
int comp;
|
||||
|
||||
/* Compute the source coordinate that the destination coordinate
|
||||
maps to. Note: sx/sw = dx/dw => sx = sw*dx/dw. */
|
||||
sx = sw * dx / dw;
|
||||
sy = sh * dy / dh;
|
||||
|
||||
/* Get the address of the pixels in src and dst. */
|
||||
dptr = ddata + dy * dstride + dx * bytes_per_pixel;
|
||||
sptr = sdata + sy * sstride + sx * bytes_per_pixel;
|
||||
|
||||
/* If we have enough space to do so, use bilinear interpolation.
|
||||
Otherwise, fall back to nearest neighbor for this pixel. */
|
||||
if (sx < sw - 1 && sy < sh - 1)
|
||||
{
|
||||
/* Do bilinear interpolation. */
|
||||
|
||||
/* Fixed-point .8 numbers representing the fraction of the
|
||||
distance in the x (u) and y (v) direction within the
|
||||
box of 4 pixels in the source. */
|
||||
int u = (256 * sw * dx / dw) - (sx * 256);
|
||||
int v = (256 * sh * dy / dh) - (sy * 256);
|
||||
|
||||
for (comp = 0; comp < bytes_per_pixel; comp++)
|
||||
{
|
||||
/* Get the component's values for the
|
||||
four source corner pixels. */
|
||||
grub_uint8_t f00 = sptr[comp];
|
||||
grub_uint8_t f10 = sptr[comp + bytes_per_pixel];
|
||||
grub_uint8_t f01 = sptr[comp + sstride];
|
||||
grub_uint8_t f11 = sptr[comp + sstride + bytes_per_pixel];
|
||||
|
||||
/* Do linear interpolations along the top and bottom
|
||||
rows of the box. */
|
||||
grub_uint8_t f0y = (256 - v) * f00 / 256 + v * f01 / 256;
|
||||
grub_uint8_t f1y = (256 - v) * f10 / 256 + v * f11 / 256;
|
||||
|
||||
/* Interpolate vertically. */
|
||||
grub_uint8_t fxy = (256 - u) * f0y / 256 + u * f1y / 256;
|
||||
|
||||
dptr[comp] = fxy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fall back to nearest neighbor interpolation. */
|
||||
/* Copy the pixel color value. */
|
||||
for (comp = 0; comp < bytes_per_pixel; comp++)
|
||||
dptr[comp] = sptr[comp];
|
||||
}
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
Loading…
Reference in a new issue