mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
rewrite image caching logic
This commit is contained in:
@@ -34,7 +34,7 @@ Image conform_image(const Image& img, const GeneratedImage::Options& options) {
|
|||||||
int iw = image.GetWidth(), ih = image.GetHeight();
|
int iw = image.GetWidth(), ih = image.GetHeight();
|
||||||
if ((iw == options.width && ih == options.height) || (options.width == 0 && options.height == 0)) {
|
if ((iw == options.width && ih == options.height) || (options.width == 0 && options.height == 0)) {
|
||||||
// zoom?
|
// zoom?
|
||||||
if (options.zoom != 1.0) {
|
if (!almost_equal(options.zoom, 1.0)) {
|
||||||
image = resample(image, int(iw * options.zoom), int(ih * options.zoom));
|
image = resample(image, int(iw * options.zoom), int(ih * options.zoom));
|
||||||
} else {
|
} else {
|
||||||
// already the right size
|
// already the right size
|
||||||
@@ -73,7 +73,7 @@ Image conform_image(const Image& img, const GeneratedImage::Options& options) {
|
|||||||
options.width = image.GetWidth();
|
options.width = image.GetWidth();
|
||||||
options.height = image.GetHeight();
|
options.height = image.GetHeight();
|
||||||
// rotate?
|
// rotate?
|
||||||
if (options.angle != 0) {
|
if (!almost_equal(options.angle, 0)) {
|
||||||
image = rotate_image(image, options.angle);
|
image = rotate_image(image, options.angle);
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ bool prepare_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& styl
|
|||||||
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
||||||
// store content properties
|
// store content properties
|
||||||
double zoom = dc.getZoom();
|
double zoom = dc.getZoom();
|
||||||
if (style.content_width != size.width / zoom || style.content_height != size.height / zoom) {
|
if (!almost_equal(style.content_width, size.width / zoom) || !almost_equal(style.content_height, size.height / zoom)) {
|
||||||
style.content_width = size.width / zoom;
|
style.content_width = size.width / zoom;
|
||||||
style.content_height = size.height / zoom;
|
style.content_height = size.height / zoom;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+29
-24
@@ -104,42 +104,47 @@ void CachedScriptableImage::generateCached(const GeneratedImage::Options& option
|
|||||||
ImageCombine combine_i = value->combine();
|
ImageCombine combine_i = value->combine();
|
||||||
if (combine_i != COMBINE_DEFAULT) *combine = combine_i;
|
if (combine_i != COMBINE_DEFAULT) *combine = combine_i;
|
||||||
*size = cached_size;
|
*size = cached_size;
|
||||||
// does the size match?
|
// do the options match?
|
||||||
bool w_ok = cached_size.width == options.width,
|
Radians relative_rotation = options.angle + rad360 - cached_options_angle;
|
||||||
h_ok = cached_size.height == options.height;
|
bool ok = almost_equal(cached_options_size.width, options.width) &&
|
||||||
|
almost_equal(cached_options_size.height, options.height) &&
|
||||||
|
almost_equal(cached_options_zoom, options.zoom) &&
|
||||||
|
cached_options_preserve_aspect == options.preserve_aspect &&
|
||||||
|
cached_options_saturate == options.saturate &&
|
||||||
|
is_straight(relative_rotation); // we only need an {0,90,180,270} degree rotation compared to the cached one, this doesn't reduce image quality
|
||||||
// image or bitmap?
|
// image or bitmap?
|
||||||
if (*combine <= COMBINE_NORMAL) {
|
if (*combine <= COMBINE_NORMAL) {
|
||||||
// bitmap
|
// bitmap
|
||||||
if (cached_b.Ok() && options.angle == cached_angle) {
|
if (cached_b.Ok() && ok && almost_equal(cached_options_angle, options.angle)) {
|
||||||
if ((w_ok && h_ok) || (options.preserve_aspect == ASPECT_FIT && (w_ok || h_ok))) { // only one dimension has to fit when fitting
|
// cached, we are done
|
||||||
// cached, we are done
|
*bitmap = cached_b;
|
||||||
*bitmap = cached_b;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// image
|
// image
|
||||||
Radians relative_rotation = options.angle + rad360 - cached_angle;
|
if (cached_i.Ok() && ok) {
|
||||||
if (cached_i.Ok() && is_straight(relative_rotation)) {
|
if (!almost_equal(cached_options_angle, options.angle)) {
|
||||||
// we need only an {0,90,180,270} degree rotation compared to the cached one, this doesn't reduce image quality
|
// rotate cached image
|
||||||
if ((w_ok && h_ok) || (options.preserve_aspect == ASPECT_FIT && (w_ok || h_ok))) { // only one dimension has to fit when fitting
|
cached_i = rotate_image(cached_i, relative_rotation);
|
||||||
if (options.angle != cached_angle) {
|
cached_options_angle = options.angle;
|
||||||
// rotate cached image
|
|
||||||
cached_i = rotate_image(cached_i, relative_rotation);
|
|
||||||
cached_angle = options.angle;
|
|
||||||
}
|
|
||||||
*image = cached_i;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
*image = cached_i;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// store the options as they were asked for
|
||||||
|
cached_options_size = RealSize(options.width, options.height);
|
||||||
|
cached_options_zoom = options.zoom;
|
||||||
|
cached_options_preserve_aspect = options.preserve_aspect;
|
||||||
|
cached_options_saturate = options.saturate;
|
||||||
|
cached_options_angle = options.angle;
|
||||||
// hack(part1): temporarily set angle to 0, do actual rotation after applying mask
|
// hack(part1): temporarily set angle to 0, do actual rotation after applying mask
|
||||||
Radians a = options.angle;
|
|
||||||
const_cast<GeneratedImage::Options&>(options).angle = 0;
|
const_cast<GeneratedImage::Options&>(options).angle = 0;
|
||||||
// generate
|
// generate
|
||||||
cached_i = generate(options);
|
cached_i = generate(options);
|
||||||
assert(cached_i.Ok());
|
assert(cached_i.Ok());
|
||||||
const_cast<GeneratedImage::Options&>(options).angle = cached_angle = a;
|
const_cast<GeneratedImage::Options&>(options).angle = cached_options_angle;
|
||||||
|
// store the size as it actually is (may have been changed by conform_image() when we generated the image)
|
||||||
*size = cached_size = RealSize(options.width, options.height);
|
*size = cached_size = RealSize(options.width, options.height);
|
||||||
if (mask) {
|
if (mask) {
|
||||||
// apply mask
|
// apply mask
|
||||||
@@ -149,7 +154,7 @@ void CachedScriptableImage::generateCached(const GeneratedImage::Options& option
|
|||||||
mask_opts.angle = 0;
|
mask_opts.angle = 0;
|
||||||
mask->get(mask_opts).setAlpha(cached_i);
|
mask->get(mask_opts).setAlpha(cached_i);
|
||||||
}
|
}
|
||||||
if (options.angle != 0) {
|
if (!almost_equal(options.angle, 0.0)) {
|
||||||
// hack(part2) do the actual rotation now
|
// hack(part2) do the actual rotation now
|
||||||
cached_i = rotate_image(cached_i, options.angle);
|
cached_i = rotate_image(cached_i, options.angle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,10 +98,15 @@ public:
|
|||||||
void clearCache();
|
void clearCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Image cached_i; ///< The cached image
|
Image cached_i; ///< The cached image
|
||||||
Bitmap cached_b; ///< *or* the cached bitmap
|
Bitmap cached_b; ///< *or* the cached bitmap
|
||||||
RealSize cached_size; ///< The size of the image before rotating
|
RealSize cached_size; ///< The size of the image before rotating, may be different than the options size
|
||||||
Radians cached_angle;
|
/// The options as they were last specified
|
||||||
|
RealSize cached_options_size = RealSize(-1.0,-1.0);
|
||||||
|
double cached_options_zoom;
|
||||||
|
Radians cached_options_angle;
|
||||||
|
PreserveAspect cached_options_preserve_aspect;
|
||||||
|
bool cached_options_saturate;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : CachedScriptableMask
|
// ----------------------------------------------------------------------------- : CachedScriptableMask
|
||||||
|
|||||||
Reference in New Issue
Block a user