summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/src-all/DisplayResampleImage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-all/DisplayResampleImage.cpp')
-rw-r--r--src/VBox/Main/src-all/DisplayResampleImage.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/VBox/Main/src-all/DisplayResampleImage.cpp b/src/VBox/Main/src-all/DisplayResampleImage.cpp
new file mode 100644
index 00000000..04f0cdbe
--- /dev/null
+++ b/src/VBox/Main/src-all/DisplayResampleImage.cpp
@@ -0,0 +1,159 @@
+/* $Id: DisplayResampleImage.cpp $ */
+/** @file
+ * Image resampling code, used for snapshot thumbnails.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * 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, in version 3 of the
+ * License.
+ *
+ * This program 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 this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include <iprt/types.h>
+
+DECLINLINE(void) imageSetPixel (uint8_t *im, int x, int y, int color, int w)
+{
+ *(int32_t *)(im + y * w * 4 + x * 4) = color;
+}
+
+#define trueColorGetAlpha(c) (((c) & 0x7F000000) >> 24)
+#define trueColorGetRed(c) (((c) & 0xFF0000) >> 16)
+#define trueColorGetGreen(c) (((c) & 0x00FF00) >> 8)
+#define trueColorGetBlue(c) ((c) & 0x0000FF)
+
+/* Fast integer implementation for 32 bpp bitmap scaling.
+ * Using fixed point values * 16.
+ */
+typedef int32_t FIXEDPOINT;
+#define INT_TO_FIXEDPOINT(i) (FIXEDPOINT)((i) << 4)
+#define FIXEDPOINT_TO_INT(v) (int)((v) >> 4)
+#define FIXEDPOINT_FLOOR(v) ((v) & ~0xF)
+#define FIXEDPOINT_FRACTION(v) ((v) & 0xF)
+
+/* For 32 bit source only. */
+void BitmapScale32 (uint8_t *dst,
+ int dstW, int dstH,
+ const uint8_t *src,
+ int iDeltaLine,
+ int srcW, int srcH)
+{
+ int x, y;
+
+ for (y = 0; y < dstH; y++)
+ {
+ FIXEDPOINT sy1 = INT_TO_FIXEDPOINT(y * srcH) / dstH;
+ FIXEDPOINT sy2 = INT_TO_FIXEDPOINT((y + 1) * srcH) / dstH;
+
+ for (x = 0; x < dstW; x++)
+ {
+ FIXEDPOINT red = 0, green = 0, blue = 0;
+
+ FIXEDPOINT sx1 = INT_TO_FIXEDPOINT(x * srcW) / dstW;
+ FIXEDPOINT sx2 = INT_TO_FIXEDPOINT((x + 1) * srcW) / dstW;
+
+ FIXEDPOINT spixels = (sx2 - sx1) * (sy2 - sy1);
+
+ FIXEDPOINT sy = sy1;
+
+ do
+ {
+ FIXEDPOINT yportion;
+ if (FIXEDPOINT_FLOOR (sy) == FIXEDPOINT_FLOOR (sy1))
+ {
+ yportion = INT_TO_FIXEDPOINT(1) - FIXEDPOINT_FRACTION(sy);
+ if (yportion > sy2 - sy1)
+ {
+ yportion = sy2 - sy1;
+ }
+ sy = FIXEDPOINT_FLOOR (sy);
+ }
+ else if (sy == FIXEDPOINT_FLOOR (sy2))
+ {
+ yportion = FIXEDPOINT_FRACTION(sy2);
+ }
+ else
+ {
+ yportion = INT_TO_FIXEDPOINT(1);
+ }
+
+ const uint8_t *pu8SrcLine = src + iDeltaLine * FIXEDPOINT_TO_INT(sy);
+ FIXEDPOINT sx = sx1;
+ do
+ {
+ FIXEDPOINT xportion;
+ FIXEDPOINT pcontribution;
+ if (FIXEDPOINT_FLOOR (sx) == FIXEDPOINT_FLOOR (sx1))
+ {
+ xportion = INT_TO_FIXEDPOINT(1) - FIXEDPOINT_FRACTION(sx);
+ if (xportion > sx2 - sx1)
+ {
+ xportion = sx2 - sx1;
+ }
+ pcontribution = xportion * yportion;
+ sx = FIXEDPOINT_FLOOR (sx);
+ }
+ else if (sx == FIXEDPOINT_FLOOR (sx2))
+ {
+ xportion = FIXEDPOINT_FRACTION(sx2);
+ pcontribution = xportion * yportion;
+ }
+ else
+ {
+ xportion = INT_TO_FIXEDPOINT(1);
+ pcontribution = xportion * yportion;
+ }
+ /* Color depth specific code begin */
+ int32_t p = *(int32_t *)(pu8SrcLine + FIXEDPOINT_TO_INT(sx) * 4);
+ /* Color depth specific code end */
+ red += trueColorGetRed (p) * pcontribution;
+ green += trueColorGetGreen (p) * pcontribution;
+ blue += trueColorGetBlue (p) * pcontribution;
+
+ sx += INT_TO_FIXEDPOINT(1);
+ } while (sx < sx2);
+
+ sy += INT_TO_FIXEDPOINT(1);
+ } while (sy < sy2);
+
+ if (spixels != 0)
+ {
+ red /= spixels;
+ green /= spixels;
+ blue /= spixels;
+ }
+ /* Clamping to allow for rounding errors above */
+ if (red > 255)
+ {
+ red = 255;
+ }
+ if (green > 255)
+ {
+ green = 255;
+ }
+ if (blue > 255)
+ {
+ blue = 255;
+ }
+ imageSetPixel (dst,
+ x, y,
+ ( ((int) red) << 16) + (((int) green) << 8) + ((int) blue),
+ dstW);
+ }
+ }
+}