diff options
Diffstat (limited to 'app/wlib/mswlib/backgnd.c')
-rw-r--r-- | app/wlib/mswlib/backgnd.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/app/wlib/mswlib/backgnd.c b/app/wlib/mswlib/backgnd.c new file mode 100644 index 0000000..d35f19a --- /dev/null +++ b/app/wlib/mswlib/backgnd.c @@ -0,0 +1,220 @@ +/** \file backgnd.c +* Layout background image +*/ + +/* XTrkCad - Model Railroad CAD +* Copyright (C) 2018 Martin Fischer +* +* 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; either version 2 of the License, or +* (at your option) any later version. +* +* 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, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <windows.h> + +#include <FreeImage.h> +#include "i18n.h" +#include "mswint.h" + +static char *lastErrorMessage; /**< store last message from FreeImage */ +#define ERRORPUNCTUATION " : " + +/**
+ * FreeImage error handler
+ * \param fif Format / Plugin responsible for the error
+ * \param message Error message
+ */ + +static void
+HandleFreeImageError(FREE_IMAGE_FORMAT fif, const char *message)
+{
+ unsigned totalLength = strlen(message) + 1;
+
+ if (fif != FIF_UNKNOWN) {
+ totalLength += strlen(FreeImage_GetFormatFromFIF(fif)) + strlen(ERRORPUNCTUATION);
+ }
+
+ lastErrorMessage = malloc(totalLength);
+
+ if (fif != FIF_UNKNOWN) {
+ sprintf(lastErrorMessage,
+ "%s" ERRORPUNCTUATION "%s",
+ FreeImage_GetFormatFromFIF(fif),
+ message);
+ } else {
+ strcpy(lastErrorMessage, message);
+ }
+} + +/**
+* Load the background image
+* \param bd drawing context
+* \param path filename for image file, if NULL the existing background will be removed
+* \param error returned error message
+* \return -1 unsupported or invalid file, 0 success, 1 background removed
+*/ + +int +wDrawSetBackground(wDraw_p bd, char * path, char ** error) +{ + FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; + + FreeImage_SetOutputMessage(HandleFreeImageError); +
+ if (lastErrorMessage) {
+ free(lastErrorMessage);
+ lastErrorMessage = NULL;
+ } + + if (path) { + // check the file signature and deduce its format + // (the second argument is currently not used by FreeImage) + fif = FreeImage_GetFileType(path, 0); + + if (fif == FIF_UNKNOWN) { + // no signature ? + // try to guess the file format from the file extension + fif = FreeImage_GetFIFFromFilename(path); + } + + // check that the plugin has reading capabilities ... + if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { + // ok, let's load the file + bd->background = FreeImage_Load(fif, path, 0); + + // unless a bad file format, we are done ! + if (!bd->background) { + *error = lastErrorMessage; + return (-1); + } else { + return (0); + } + } else { + *error = strdup(_("Image file is invalid or cannot be read.")); + return (-1); + } + } else { + if (bd->background) { + FreeImage_Unload(bd->background); + bd->background = 0; + } + + return (1); + } +} + +/**
+* Draw background to screen. The background will be sized and rotated before being shown. The bitmap
+* is scaled so that the width is equal to size. The height is changed proportionally.
+*
+* \param bd drawing context
+* \param pos_x, pos_y bitmap position
+* \param size desired width after scaling
+* \param angle
+* \param screen visibility of bitmap in percent
+*/ + +void +wDrawShowBackground(wDraw_p bd, wPos_t pos_x, wPos_t pos_y, wPos_t size, + wAngle_t angle, int screen) +{ + if (bd->background) { + double scale; + FIBITMAP *tmp; + FIBITMAP *rotated; + + if (size == 0) { + scale = 1.0; + } else { + scale = (double)size / FreeImage_GetWidth(bd->background); + } + + tmp = FreeImage_RescaleRect(bd->background, + (int)((double)FreeImage_GetWidth(bd->background) * scale), + (int)((double)FreeImage_GetHeight(bd->background) * scale), + 0, + 0, + FreeImage_GetWidth(bd->background), + FreeImage_GetHeight(bd->background), + FILTER_BILINEAR, + 0); + FreeImage_AdjustColors(tmp, screen, -screen, 1.0, FALSE); + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(tmp); + + switch (image_type) { + case FIT_BITMAP: + switch (FreeImage_GetBPP(tmp)) { + case 8: { + BYTE color = 255; + rotated = FreeImage_Rotate(tmp, angle, &color); + } + break; + + case 24: // we could also use 'RGBTRIPLE color' here + case 32: { + RGBQUAD color = { 255, 255, 255, 0 }; + // for 24-bit images, the first 3 bytes will be read + // for 32-bit images, the first 4 bytes will be read + rotated = FreeImage_Rotate(tmp, angle, &color); + } + break; + } + + break; + + case FIT_UINT16: { + WORD color = 255; + rotated = FreeImage_Rotate(tmp, angle, &color); + } + break; + + case FIT_RGB16: // we could also use 'FIRGB16 color' here + case FIT_RGBA16: { + FIRGBA16 color = { 255, 255, 255, 0 }; + // for RGB16 images, the first 3 WORD will be read + // for RGBA16 images, the first 4 WORD will be read + rotated = FreeImage_Rotate(tmp, angle, &color); + } + break; + + case FIT_FLOAT: { + float color = 1.0F; + rotated = FreeImage_Rotate(tmp, angle, &color); + } + break; + + case FIT_RGBF: // we could also use 'FIRGBF color' here + case FIT_RGBAF: { + FIRGBAF color = { 1, 1, 1, 0 }; + // for RGBF images, the first 3 float will be read + // for RGBAF images, the first 4 float will be read + rotated = FreeImage_Rotate(tmp, angle, &color); + } + break; + } + + SetDIBitsToDevice(bd->hDc, + pos_x, + bd->h - pos_y - FreeImage_GetHeight(rotated), + FreeImage_GetWidth(rotated), + FreeImage_GetHeight(rotated), + 0, 0, + 0, + FreeImage_GetHeight(rotated), + FreeImage_GetBits(rotated), + FreeImage_GetInfo(rotated), + DIB_RGB_COLORS); + FreeImage_Unload(tmp); + FreeImage_Unload(rotated); + } +}
\ No newline at end of file |