Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
ygopro
Commits
e6d5b279
Commit
e6d5b279
authored
Feb 07, 2026
by
mercury233
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add ImageResizer class
parent
fcebe3ee
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
119 additions
and
79 deletions
+119
-79
gframe/image_manager.cpp
gframe/image_manager.cpp
+5
-79
gframe/image_manager.h
gframe/image_manager.h
+1
-0
gframe/image_resizer.cpp
gframe/image_resizer.cpp
+94
-0
gframe/image_resizer.h
gframe/image_resizer.h
+19
-0
No files found.
gframe/image_manager.cpp
View file @
e6d5b279
#include "image_manager.h"
#include "image_resizer.h"
#include "game.h"
#include <cmath>
#include <thread>
...
...
@@ -120,83 +121,8 @@ void ImageManager::ResizeTexture() {
if
(
!
tBackGround_deck
)
tBackGround_deck
=
tBackGround
;
}
/** Scale image using nearest neighbor anti-aliasing.
* Function by Warr1024, from https://github.com/minetest/minetest/issues/2419, modified. */
void
imageScaleNNAA
(
irr
::
video
::
IImage
*
src
,
irr
::
video
::
IImage
*
dest
,
bool
use_threading
)
{
const
auto
&
srcDim
=
src
->
getDimension
();
const
auto
&
destDim
=
dest
->
getDimension
();
if
(
destDim
.
Width
==
0
||
destDim
.
Height
==
0
)
return
;
// Cache scale ratios.
const
double
rx
=
(
double
)
srcDim
.
Width
/
destDim
.
Width
;
const
double
ry
=
(
double
)
srcDim
.
Height
/
destDim
.
Height
;
#pragma omp parallel if(use_threading)
{
// Walk each destination image pixel.
#pragma omp for schedule(dynamic)
for
(
irr
::
s32
dy
=
0
;
dy
<
(
irr
::
s32
)
destDim
.
Height
;
dy
++
)
{
for
(
irr
::
s32
dx
=
0
;
dx
<
(
irr
::
s32
)
destDim
.
Width
;
dx
++
)
{
// Calculate floating-point source rectangle bounds.
double
minsx
=
dx
*
rx
;
double
maxsx
=
minsx
+
rx
;
double
minsy
=
dy
*
ry
;
double
maxsy
=
minsy
+
ry
;
irr
::
u32
sx_begin
=
(
irr
::
u32
)
std
::
floor
(
minsx
);
irr
::
u32
sx_end
=
(
irr
::
u32
)
std
::
ceil
(
maxsx
);
if
(
sx_end
>
srcDim
.
Width
)
sx_end
=
srcDim
.
Width
;
irr
::
u32
sy_begin
=
(
irr
::
u32
)
std
::
floor
(
minsy
);
irr
::
u32
sy_end
=
(
irr
::
u32
)
std
::
ceil
(
maxsy
);
if
(
sy_end
>
srcDim
.
Height
)
sy_end
=
srcDim
.
Height
;
// Total area, and integral of r, g, b values over that area,
// initialized to zero, to be summed up in next loops.
double
area
=
0
,
ra
=
0
,
ga
=
0
,
ba
=
0
,
aa
=
0
;
irr
::
video
::
SColor
pxl
,
npxl
;
// Loop over the integral pixel positions described by those bounds.
for
(
irr
::
u32
sy
=
sy_begin
;
sy
<
sy_end
;
sy
++
)
{
for
(
irr
::
u32
sx
=
sx_begin
;
sx
<
sx_end
;
sx
++
)
{
// Calculate width, height, then area of dest pixel
// that's covered by this source pixel.
double
pw
=
1
;
if
(
minsx
>
sx
)
pw
+=
sx
-
minsx
;
if
(
maxsx
<
(
sx
+
1
))
pw
+=
maxsx
-
sx
-
1
;
double
ph
=
1
;
if
(
minsy
>
sy
)
ph
+=
sy
-
minsy
;
if
(
maxsy
<
(
sy
+
1
))
ph
+=
maxsy
-
sy
-
1
;
double
pa
=
pw
*
ph
;
// Get source pixel and add it to totals, weighted
// by covered area and alpha.
pxl
=
src
->
getPixel
(
sx
,
sy
);
area
+=
pa
;
ra
+=
pa
*
pxl
.
getRed
();
ga
+=
pa
*
pxl
.
getGreen
();
ba
+=
pa
*
pxl
.
getBlue
();
aa
+=
pa
*
pxl
.
getAlpha
();
}
}
// Set the destination image pixel to the average color.
if
(
area
>
0
)
{
npxl
.
set
((
irr
::
u32
)(
aa
/
area
+
0.5
),
(
irr
::
u32
)(
ra
/
area
+
0.5
),
(
irr
::
u32
)(
ga
/
area
+
0.5
),
(
irr
::
u32
)(
ba
/
area
+
0.5
));
}
else
{
npxl
.
set
(
0
);
}
dest
->
setPixel
(
dx
,
dy
,
npxl
);
}
}
}
// end of parallel region
void
ImageManager
::
resizeImage
(
irr
::
video
::
IImage
*
src
,
irr
::
video
::
IImage
*
dest
,
bool
use_threading
)
{
imageResizer
.
resize
(
src
,
dest
,
use_threading
);
}
/** Convert image to texture, resizing if needed.
* @param name Texture name (Irrlicht texture key).
...
...
@@ -210,7 +136,7 @@ irr::video::ITexture* ImageManager::addTexture(const char* name, irr::video::IIm
texture
=
driver
->
addTexture
(
name
,
srcimg
);
}
else
{
irr
::
video
::
IImage
*
destimg
=
driver
->
createImage
(
srcimg
->
getColorFormat
(),
irr
::
core
::
dimension2d
<
irr
::
u32
>
(
width
,
height
));
imageScaleNNAA
(
srcimg
,
destimg
,
mainGame
->
gameConf
.
use_image_scale_multi_thread
);
resizeImage
(
srcimg
,
destimg
,
mainGame
->
gameConf
.
use_image_scale_multi_thread
);
texture
=
driver
->
addTexture
(
name
,
destimg
);
destimg
->
drop
();
}
...
...
@@ -321,7 +247,7 @@ int ImageManager::LoadThumbThread() {
imageManager
.
tThumbLoadingMutex
.
unlock
();
}
else
{
irr
::
video
::
IImage
*
destimg
=
imageManager
.
driver
->
createImage
(
img
->
getColorFormat
(),
irr
::
core
::
dimension2d
<
irr
::
u32
>
(
width
,
height
));
image
ScaleNNAA
(
img
,
destimg
,
mainGame
->
gameConf
.
use_image_scale_multi_thread
);
image
Manager
.
resizeImage
(
img
,
destimg
,
mainGame
->
gameConf
.
use_image_scale_multi_thread
);
img
->
drop
();
imageManager
.
tThumbLoadingMutex
.
lock
();
if
(
imageManager
.
tThumbLoadingThreadRunning
)
...
...
gframe/image_manager.h
View file @
e6d5b279
...
...
@@ -11,6 +11,7 @@ namespace ygo {
class
ImageManager
{
private:
void
resizeImage
(
irr
::
video
::
IImage
*
src
,
irr
::
video
::
IImage
*
dest
,
bool
use_threading
);
irr
::
video
::
ITexture
*
addTexture
(
const
char
*
name
,
irr
::
video
::
IImage
*
srcimg
,
irr
::
s32
width
,
irr
::
s32
height
);
public:
bool
Initial
();
...
...
gframe/image_resizer.cpp
0 → 100644
View file @
e6d5b279
#include "image_resizer.h"
#include <cmath>
#ifdef _OPENMP
#include <omp.h>
#endif
namespace
ygo
{
ImageResizer
imageResizer
;
/** Scale image using nearest neighbor anti-aliasing.
* Function by Warr1024, from https://github.com/minetest/minetest/issues/2419, modified. */
void
ImageResizer
::
imageScaleNNAA
(
irr
::
video
::
IImage
*
src
,
irr
::
video
::
IImage
*
dest
,
bool
use_threading
)
{
const
auto
&
srcDim
=
src
->
getDimension
();
const
auto
&
destDim
=
dest
->
getDimension
();
if
(
destDim
.
Width
==
0
||
destDim
.
Height
==
0
)
return
;
// Cache scale ratios.
const
double
rx
=
(
double
)
srcDim
.
Width
/
destDim
.
Width
;
const
double
ry
=
(
double
)
srcDim
.
Height
/
destDim
.
Height
;
#pragma omp parallel if(use_threading)
{
// Walk each destination image pixel.
#pragma omp for schedule(dynamic)
for
(
irr
::
s32
dy
=
0
;
dy
<
(
irr
::
s32
)
destDim
.
Height
;
dy
++
)
{
for
(
irr
::
s32
dx
=
0
;
dx
<
(
irr
::
s32
)
destDim
.
Width
;
dx
++
)
{
// Calculate floating-point source rectangle bounds.
double
minsx
=
dx
*
rx
;
double
maxsx
=
minsx
+
rx
;
double
minsy
=
dy
*
ry
;
double
maxsy
=
minsy
+
ry
;
irr
::
u32
sx_begin
=
(
irr
::
u32
)
std
::
floor
(
minsx
);
irr
::
u32
sx_end
=
(
irr
::
u32
)
std
::
ceil
(
maxsx
);
if
(
sx_end
>
srcDim
.
Width
)
sx_end
=
srcDim
.
Width
;
irr
::
u32
sy_begin
=
(
irr
::
u32
)
std
::
floor
(
minsy
);
irr
::
u32
sy_end
=
(
irr
::
u32
)
std
::
ceil
(
maxsy
);
if
(
sy_end
>
srcDim
.
Height
)
sy_end
=
srcDim
.
Height
;
// Total area, and integral of r, g, b values over that area,
// initialized to zero, to be summed up in next loops.
double
area
=
0
,
ra
=
0
,
ga
=
0
,
ba
=
0
,
aa
=
0
;
irr
::
video
::
SColor
pxl
,
npxl
;
// Loop over the integral pixel positions described by those bounds.
for
(
irr
::
u32
sy
=
sy_begin
;
sy
<
sy_end
;
sy
++
)
{
for
(
irr
::
u32
sx
=
sx_begin
;
sx
<
sx_end
;
sx
++
)
{
// Calculate width, height, then area of dest pixel
// that's covered by this source pixel.
double
pw
=
1
;
if
(
minsx
>
sx
)
pw
+=
sx
-
minsx
;
if
(
maxsx
<
(
sx
+
1
))
pw
+=
maxsx
-
sx
-
1
;
double
ph
=
1
;
if
(
minsy
>
sy
)
ph
+=
sy
-
minsy
;
if
(
maxsy
<
(
sy
+
1
))
ph
+=
maxsy
-
sy
-
1
;
double
pa
=
pw
*
ph
;
// Get source pixel and add it to totals, weighted
// by covered area and alpha.
pxl
=
src
->
getPixel
(
sx
,
sy
);
area
+=
pa
;
ra
+=
pa
*
pxl
.
getRed
();
ga
+=
pa
*
pxl
.
getGreen
();
ba
+=
pa
*
pxl
.
getBlue
();
aa
+=
pa
*
pxl
.
getAlpha
();
}
}
// Set the destination image pixel to the average color.
if
(
area
>
0
)
{
npxl
.
set
((
irr
::
u32
)(
aa
/
area
+
0.5
),
(
irr
::
u32
)(
ra
/
area
+
0.5
),
(
irr
::
u32
)(
ga
/
area
+
0.5
),
(
irr
::
u32
)(
ba
/
area
+
0.5
));
}
else
{
npxl
.
set
(
0
);
}
dest
->
setPixel
(
dx
,
dy
,
npxl
);
}
}
}
// end of parallel region
}
void
ImageResizer
::
resize
(
irr
::
video
::
IImage
*
src
,
irr
::
video
::
IImage
*
dest
,
bool
use_threading
)
{
imageScaleNNAA
(
src
,
dest
,
use_threading
);
}
}
// namespace ygo
gframe/image_resizer.h
0 → 100644
View file @
e6d5b279
#ifndef IMAGE_RESIZER_H
#define IMAGE_RESIZER_H
#include <irrlicht.h>
namespace
ygo
{
class
ImageResizer
{
private:
void
imageScaleNNAA
(
irr
::
video
::
IImage
*
src
,
irr
::
video
::
IImage
*
dest
,
bool
use_threading
);
public:
void
resize
(
irr
::
video
::
IImage
*
src
,
irr
::
video
::
IImage
*
dest
,
bool
use_threading
);
};
extern
ImageResizer
imageResizer
;
}
// namespace ygo
#endif // IMAGE_RESIZER_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment