BUG correction: keep_aspect_ratio does bot work for images. Now we can set the containerWidth and containerHeight params for automatic cropping

Signed-off-by: Vincent-FK <vincent.buso@funkey-project.com>
This commit is contained in:
Vincent-FK 2020-03-31 01:35:48 +02:00
parent 21ff820179
commit 2eb437708d
4 changed files with 158 additions and 68 deletions

View File

@ -442,7 +442,7 @@ void Battery::draw()
if(scaling_needed){
cache_scaling_needed = (texture_prescaled_ == NULL)?true:(texture_prescaled_->w != rect.w || texture_prescaled_->h != rect.h);
if(cache_scaling_needed){
texture_prescaled_ = SDL::zoomSurface(texture_, NULL, &rect);
texture_prescaled_ = SDL::zoomSurface(texture_, NULL, &rect, NULL);
if(texture_prescaled_ == NULL){
printf("ERROR in %s - Could not create texture_prescaled_\n", __func__);
use_prescaled = false;

View File

@ -131,43 +131,62 @@ void Image::draw()
rect.h = static_cast<int>(baseViewInfo.ScaledHeight());
rect.w = static_cast<int>(baseViewInfo.ScaledWidth());
/* Cache scaling */
scaling_needed = rect.w!=0 && rect.h!=0 && (texture_->w != rect.w || texture_->h != rect.h);
if(scaling_needed){
cache_scaling_needed = (texture_prescaled_ == NULL)?true:(texture_prescaled_->w != rect.w || texture_prescaled_->h != rect.h);
if(cache_scaling_needed){
texture_prescaled_ = SDL::zoomSurface(texture_, NULL, &rect);
if(texture_prescaled_ == NULL){
printf("ERROR in %s - Could not create texture_prescaled_\n", __func__);
use_prescaled = false;
}
if(imgBitsPerPx_ > 16 && ditheringAuthorized_){
needDithering_ = true;
}
}
/* Cropping needed ? */
bool cropping_needed = false;
SDL_Rect rect_cropping;
if ( (baseViewInfo.ContainerWidth > 0 && baseViewInfo.ContainerHeight > 0) &&
(baseViewInfo.ContainerWidth != rect.w || baseViewInfo.ContainerHeight != rect.h)){
cropping_needed = true;
rect_cropping.x = (rect.w - baseViewInfo.ContainerWidth)/2;
rect_cropping.y = (rect.h - baseViewInfo.ContainerHeight)/2;
rect_cropping.w = baseViewInfo.ContainerWidth;
rect_cropping.h = baseViewInfo.ContainerHeight;
/*printf("\nrect = [{%d, %d} %dx%d], rect_cropping = [{%d, %d} %dx%d]\n",
rect.x, rect.y, rect.w, rect.h,
rect_cropping.x, rect_cropping.y, rect_cropping.w, rect_cropping.h);*/
}
if(texture_prescaled_ != NULL){
use_prescaled = true;
}
/* Cache scaling */
scaling_needed = (rect.w!=0 && rect.h!=0) && (texture_->w != rect.w || texture_->h != rect.h);
if(scaling_needed){
cache_scaling_needed = (texture_prescaled_ == NULL)?true:
((!cropping_needed && (texture_prescaled_->w != rect.w || texture_prescaled_->h != rect.h)) ||
(cropping_needed && (texture_prescaled_->w != rect_cropping.w || texture_prescaled_->h != rect_cropping.h) ));
if(cache_scaling_needed){
/*printf("\nComputing prescaling and cropping in Image.cpp %s\n", cropping_needed?"and cropping":"");*/
texture_prescaled_ = SDL::zoomSurface(texture_, NULL, &rect, cropping_needed?&rect_cropping:NULL);
if(texture_prescaled_ == NULL){
printf("ERROR in %s - Could not create texture_prescaled_\n", __func__);
use_prescaled = false;
}
if(imgBitsPerPx_ > 16 && ditheringAuthorized_){
needDithering_ = true;
}
}
/* Surface to display */
SDL_Surface * surfaceToRender = NULL;
if(use_prescaled && texture_prescaled_ != NULL){
surfaceToRender = texture_prescaled_;
}
else{
surfaceToRender = texture_;
}
if(texture_prescaled_ != NULL){
use_prescaled = true;
}
}
/* Dithering */
if(needDithering_){
//printf("Dither: %s\n", file_.c_str());
SDL::ditherSurface32bppTo16Bpp(surfaceToRender);
needDithering_ = false;
}
/* Surface to display */
SDL_Surface * surfaceToRender = NULL;
if(use_prescaled && texture_prescaled_ != NULL){
surfaceToRender = texture_prescaled_;
}
else{
surfaceToRender = texture_;
}
/* Render */
SDL::renderCopy(surfaceToRender, baseViewInfo.Alpha, NULL, &rect, baseViewInfo);
/* Dithering */
if(needDithering_){
//printf("Dither: %s\n", file_.c_str());
SDL::ditherSurface32bppTo16Bpp(surfaceToRender);
needDithering_ = false;
}
/* Render */
//printf("image render\n");
SDL::renderCopy(surfaceToRender, baseViewInfo.Alpha, NULL, &rect, baseViewInfo);
}
}

View File

@ -549,7 +549,7 @@ SDL_Surface * SDL::flip_surface( SDL_Surface *surface, int flags )
}
/// Nearest neighboor optimized with possible out of screen coordinates (for cropping)
SDL_Surface * SDL::zoomSurface(SDL_Surface *src_surface, SDL_Rect *src_rect_origin, SDL_Rect *dst_rect){
SDL_Surface * SDL::zoomSurface(SDL_Surface *src_surface, SDL_Rect *src_rect_origin, SDL_Rect *dst_rect, SDL_Rect *post_cropping_rect){
/* Declare vars */
int x_ratio;
@ -564,7 +564,6 @@ SDL_Surface * SDL::zoomSurface(SDL_Surface *src_surface, SDL_Rect *src_rect_orig
printf("ERROR in %s, sanity check\n", __func__);
return NULL;
}
/* Sanity checks */
if( src_rect_origin == NULL){
srcRect.x = 0;
srcRect.y = 0;
@ -593,6 +592,14 @@ SDL_Surface * SDL::zoomSurface(SDL_Surface *src_surface, SDL_Rect *src_rect_orig
printf("ERROR src_rect->y (%d) > src_rect->h(%d) \n", srcRect.y, srcRect.h);
return NULL;
}
if( post_cropping_rect != NULL ){
if( post_cropping_rect->w > dst_rect->w){
post_cropping_rect->w = dst_rect->w;
}
if( post_cropping_rect->h > dst_rect->h){
post_cropping_rect->h = dst_rect->h;
}
}
/*printf("zoomSurface: src_surface->w = %d, src_surface->h = %d, src_surface->BytesPerPixel = %d, src_rect = {%d, %d, %d, %d}, dst_rect = {%d, %d, %d, %d}\n",
src_surface->w, src_surface->h, src_surface->format->BytesPerPixel, src_rect->x, src_rect->y, src_rect->w, src_rect->h, dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);*/
@ -601,7 +608,7 @@ SDL_Surface * SDL::zoomSurface(SDL_Surface *src_surface, SDL_Rect *src_rect_orig
x_ratio = (int)((srcRect.w <<16) / dst_rect->w);
y_ratio = (int)((srcRect.h <<16) / dst_rect->h);
/* Create new output surface */
/* Create dst surface */
SDL_Surface *dst_surface = SDL_CreateRGBSurface(src_surface->flags,
dst_rect->w, dst_rect->h,
src_surface->format->BitsPerPixel,
@ -612,31 +619,62 @@ SDL_Surface * SDL::zoomSurface(SDL_Surface *src_surface, SDL_Rect *src_rect_orig
}
/* Columns iterations */
for (i = 0; i < dst_surface->h; i++)
for (i = 0; i < dst_surface->h; i++)
{
/* Get current lines in src and dst surfaces */
uint8_t* t = ( (uint8_t*) dst_surface->pixels + (i*dst_surface->w)*dst_surface->format->BytesPerPixel );
y2 = ((i*y_ratio)>>16);
uint8_t* p = ( (uint8_t*) src_surface->pixels + ((y2+srcRect.y)*src_surface->w)*src_surface->format->BytesPerPixel );
rat = srcRect.x << 16;
/* Lines iterations */
for (j = 0; j < dst_surface->w; j++)
{
/* Get current lines in src and dst surfaces */
uint8_t* t = ( (uint8_t*) dst_surface->pixels + (i*dst_surface->w)*dst_surface->format->BytesPerPixel );
y2 = ((i*y_ratio)>>16);
uint8_t* p = ( (uint8_t*) src_surface->pixels + ((y2+srcRect.y)*src_surface->w)*src_surface->format->BytesPerPixel );
rat = srcRect.x << 16;
/* Get current pixel in src surface */
x2 = (rat>>16);
/* Lines iterations */
for (j = 0; j < dst_surface->w; j++)
{
/* Copy src pixel in dst surface */
//printf("dst_pix_off = %d, x2=%d, y2=%d, p[%d] = %d\n", t-(uint8_t*)dst_surface->pixels, x2, y2, x2, p[x2*src_surface->format->BytesPerPixel]);
memcpy(t, p+x2*src_surface->format->BytesPerPixel, dst_surface->format->BytesPerPixel);
t += dst_surface->format->BytesPerPixel;
/* Get current pixel in src surface */
x2 = (rat>>16);
/* Copy src pixel in dst surface */
//printf("dst_pix_off = %d, x2=%d, y2=%d, p[%d] = %d\n", t-(uint8_t*)dst_surface->pixels, x2, y2, x2, p[x2*src_surface->format->BytesPerPixel]);
memcpy(t, p+x2*src_surface->format->BytesPerPixel, dst_surface->format->BytesPerPixel);
t += dst_surface->format->BytesPerPixel;
/* Update x position in source surface */
rat += x_ratio;
}
/* Update x position in source surface */
rat += x_ratio;
}
}
/* Post cropping */
if(post_cropping_rect != NULL){
/* Save prev dst_surface ptr */
SDL_Surface *prev_dst_surface = dst_surface;
/* Create dst surface */
dst_surface = SDL_CreateRGBSurface(src_surface->flags,
post_cropping_rect->w, post_cropping_rect->h,
src_surface->format->BitsPerPixel,
src_surface->format->Rmask, src_surface->format->Gmask,
src_surface->format->Bmask, src_surface->format->Amask);
if(dst_surface == NULL){
printf("ERROR in %s, cannot create dst_surface for post cropping: %s\n", __func__, SDL_GetError());
dst_surface = prev_dst_surface;
}
else{
/*printf("dst_surface is being cropped. prev_dst_surface(%dx%d) -> dst_surface(%dx%d)!!!!!\n",
prev_dst_surface->w, prev_dst_surface->h, dst_surface->w, dst_surface->h);
printf("post_cropping_rect [{%d,%d} %dx%d]\n",
post_cropping_rect->x, post_cropping_rect->y, post_cropping_rect->w, post_cropping_rect->h);*/
/* Copy cropped surface */
if(SDL_BlitSurface(prev_dst_surface, post_cropping_rect, dst_surface, NULL)){
printf("ERROR in %s, cannot blit previous dst_surface for post cropping: %s\n", __func__, SDL_GetError());
}
/* Free previous surface */
SDL_FreeSurface(prev_dst_surface);
}
}
/* Return new zoomed surface */
return dst_surface;
@ -705,13 +743,18 @@ bool SDL::renderCopy( SDL_Surface *texture, float alpha, SDL_Rect *src, SDL_Rect
dstRectCopy.h = dstRect.h;
/*printf("before viewinfo remniement -> srcRectCopy->w = %d, srcRectCopy->h = %d, dstRectCopy->w = %d, dstRectCopy->h = %d, viewInfo->ContainerWidth = %f, viewInfo->ContainerHeight = %f\n",
srcRectCopy.w, srcRectCopy.h, dstRectCopy.w, dstRectCopy.h, viewInfo.ContainerWidth, viewInfo.ContainerHeight);*/
/*printf("before viewinfo remniement -> srcRect->w = %d, srcRect->h = %d, dstRectCopy->w = %d, dstRectCopy->h = %d, viewInfo->ContainerWidth = %f, viewInfo->ContainerHeight = %f\n",
srcRect.w, srcRect.h, dstRectCopy.w, dstRectCopy.h, viewInfo.ContainerWidth, viewInfo.ContainerHeight);*/
#if 0
// If a container has been defined, limit the display to the container boundaries.
if ( viewInfo.ContainerWidth > 0 && viewInfo.ContainerHeight > 0 &&
dstRectCopy.w > 0 && dstRectCopy.h > 0 )
{
if(viewInfo.ContainerX <= 0)
viewInfo.ContainerX = dstRectCopy.x;
if(viewInfo.ContainerY <= 0)
viewInfo.ContainerY = dstRectCopy.y;
// Correct if the image falls to the left of the container
if ( dstRect.x < viewInfo.ContainerX )
@ -745,14 +788,44 @@ bool SDL::renderCopy( SDL_Surface *texture, float alpha, SDL_Rect *src, SDL_Rect
srcRect.w = static_cast<int>( dstRect.w * scaleX );
srcRect.h = static_cast<int>( dstRect.h * scaleY );
/*printf("viewInfo->ContainerWidth = %f, viewInfo->ContainerHeight = %f\n", viewInfo.ContainerWidth, viewInfo.ContainerHeight);
printf("before viewinfo remaniement -> srcRectCopy = [{%d, %d} %dx%d] ---> srcRect = [{%d, %d} %dx%d]\n",
srcRectCopy.x, srcRectCopy.y, srcRectCopy.w, srcRectCopy.h, srcRect.x, srcRect.y, srcRect.w, srcRect.h);
printf("before viewinfo remaniement -> dstRectCopy = [{%d, %d} %dx%d] ---> dstRect = [{%d, %d} %dx%d]\n\n",
dstRectCopy.x, dstRectCopy.y, dstRectCopy.w, dstRectCopy.h, dstRect.x, dstRect.y, dstRect.w, dstRect.h);*/
}
#endif
/* Cropping needed ? */
bool cropping_needed = false;
SDL_Rect rect_cropping;
/*if(viewInfo.ContainerWidth > 0 && viewInfo.ContainerHeight > 0)
printf("Testing if cropping needed ? dst_rect = [{%d, %d} %dx%d]\n",
dstRect.x, dstRect.y, dstRect.w, dstRect.h);*/
if ( (viewInfo.ContainerWidth > 0 && viewInfo.ContainerHeight > 0) &&
(viewInfo.ContainerWidth != dstRect.w || viewInfo.ContainerHeight != dstRect.h) ){
cropping_needed = true;
rect_cropping.x = (dstRect.w - viewInfo.ContainerWidth)/2;
rect_cropping.y = (dstRect.h - viewInfo.ContainerHeight)/2;
rect_cropping.w = viewInfo.ContainerWidth;
rect_cropping.h = viewInfo.ContainerHeight;
dstRect.x += rect_cropping.x;
dstRect.y += rect_cropping.y;
/*printf("cropping needed in sdl ?srcRect = [{%d, %d} %dx%d], rect_cropping = [{%d, %d} %dx%d]\n",
srcRect.x, srcRect.y, srcRect.w, srcRect.h,
rect_cropping.x, rect_cropping.y, rect_cropping.w, rect_cropping.h);*/
}
/* Scaling */
#define WITH_SCALING
#ifdef WITH_SCALING
scaling_needed = !dstRect.w==0 && !dstRect.h==0 && (srcRect.w != dstRect.w || srcRect.h != dstRect.h);
scaling_needed = (dstRect.w != 0 && dstRect.h!=0) &&
((!cropping_needed && (srcRect.w != dstRect.w || srcRect.h != dstRect.h)) ||
(cropping_needed && (srcRect.w != rect_cropping.w || srcRect.h != rect_cropping.h) ));
if(scaling_needed){
texture_zoomed = zoomSurface(texture, &srcRect, &dstRect);
/*printf("Scaling needed in %s\n", __func__);
printf("Scaling needed in sdl ?srcRect = [{%d, %d} %dx%d], dst_rect = [{%d, %d} %dx%d]\n",
srcRect.x, srcRect.y, srcRect.w, srcRect.h,
dstRect.x, dstRect.y, cropping_needed?rect_cropping.w:dstRect.w, cropping_needed?rect_cropping.h:dstRect.h);*/
texture_zoomed = zoomSurface(texture, &srcRect, &dstRect, cropping_needed?&rect_cropping:NULL);
if(texture_zoomed == NULL){
printf("ERROR in %s - Could not create texture_zoomed\n", __func__);
return false;
@ -761,7 +834,6 @@ bool SDL::renderCopy( SDL_Surface *texture, float alpha, SDL_Rect *src, SDL_Rect
surface_to_blit = texture_zoomed;
}
}
#endif //WITH_SCALING
@ -817,9 +889,6 @@ bool SDL::renderCopy( SDL_Surface *texture, float alpha, SDL_Rect *src, SDL_Rect
if(texture_zoomed)
SDL_FreeSurface(texture_zoomed);
/* Reset viewInfo */
viewInfo.ContainerWidth = -1;
viewInfo.ContainerHeight = -1;

View File

@ -24,6 +24,8 @@
//Flip flags
#define FLIP_VERTICAL 1
#define FLIP_HORIZONTAL 2
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
class Configuration;
@ -36,7 +38,7 @@ public:
static SDL_mutex *getMutex( );
static SDL_Surface *getWindow( );
static void renderAndFlipWindow( );
static SDL_Surface * zoomSurface(SDL_Surface *surface_ptr, SDL_Rect *src_rect_origin, SDL_Rect *dst_rect);
static SDL_Surface * zoomSurface(SDL_Surface *surface_ptr, SDL_Rect *src_rect_origin, SDL_Rect *dst_rect, SDL_Rect *post_cropping_rect);
static void ditherSurface32bppTo16Bpp(SDL_Surface *src_surface);
static bool renderCopy( SDL_Surface *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, ViewInfo &viewInfo );
static int getWindowWidth( )