plug-ins: Add Windows WIA scanner plug-in
We dropped 32bit Windows support in GIMP 3.2.2, which also removed the 32bit-only TWAIN scanner plug-in. This patch adds a new plug-in that uses the 64bit compatible WIA API for scanning. It should restore the support for scanning on Windows.
This commit is contained in:
parent
a377367145
commit
86740b51e8
4 changed files with 344 additions and 0 deletions
|
|
@ -1123,6 +1123,9 @@ conf.set('HAVE_LIBGUDEV', gudev.found())
|
||||||
directx = platform_windows ? cc.find_library('dxguid') : no_dep
|
directx = platform_windows ? cc.find_library('dxguid') : no_dep
|
||||||
conf.set('HAVE_DX_DINPUT', directx.found())
|
conf.set('HAVE_DX_DINPUT', directx.found())
|
||||||
|
|
||||||
|
# Windows Image Acquistion (WIA)
|
||||||
|
wia = platform_windows ? cc.find_library('wiaguid') : no_dep
|
||||||
|
|
||||||
cfitsio_dep = dependency('cfitsio', required: get_option('fits'))
|
cfitsio_dep = dependency('cfitsio', required: get_option('fits'))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,11 @@ endif
|
||||||
|
|
||||||
if platform_windows
|
if platform_windows
|
||||||
common_plugins_list += { 'name': 'file-lnk', }
|
common_plugins_list += { 'name': 'file-lnk', }
|
||||||
|
if wia.found()
|
||||||
|
common_plugins_list += { 'name': 'wia',
|
||||||
|
'deps': [ wia ],
|
||||||
|
}
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if platform_linux
|
if platform_linux
|
||||||
|
|
|
||||||
335
plug-ins/common/wia.c
Normal file
335
plug-ins/common/wia.c
Normal file
|
|
@ -0,0 +1,335 @@
|
||||||
|
/* GIMP - The GNU Image Manipulation Program
|
||||||
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||||
|
*
|
||||||
|
* WIA Scanner plug-in
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 Alex S.
|
||||||
|
*
|
||||||
|
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h> /* Needed when compiling with gcc */
|
||||||
|
#include <wia.h>
|
||||||
|
#include <wia_lh.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libgimp/gimp.h"
|
||||||
|
#include "libgimp/stdplugins-intl.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define PLUG_IN_NAME "wia-acquire"
|
||||||
|
#define PLUG_IN_DESCRIPTION _("Capture an image from a WIA datasource")
|
||||||
|
#define PLUG_IN_HELP N_("This plug-in will capture an image from a WIA datasource")
|
||||||
|
|
||||||
|
#define MAX_FOLDER_PATH 1024
|
||||||
|
|
||||||
|
typedef struct _Wia Wia;
|
||||||
|
typedef struct _WiaClass WiaClass;
|
||||||
|
|
||||||
|
struct _Wia
|
||||||
|
{
|
||||||
|
GimpPlugIn parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _WiaClass
|
||||||
|
{
|
||||||
|
GimpPlugInClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define WIA_TYPE (wia_get_type ())
|
||||||
|
#define WIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WIA_TYPE, Wia))
|
||||||
|
|
||||||
|
GType wia_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
static GList * wia_query_procedures (GimpPlugIn *plug_in);
|
||||||
|
static GimpProcedure * wia_create_procedure (GimpPlugIn *plug_in,
|
||||||
|
const gchar *name);
|
||||||
|
|
||||||
|
static GimpValueArray * wia_run (GimpProcedure *procedure,
|
||||||
|
GimpRunMode run_mode,
|
||||||
|
GimpImage *image,
|
||||||
|
GimpDrawable **drawables,
|
||||||
|
GimpProcedureConfig *config,
|
||||||
|
gpointer run_data);
|
||||||
|
|
||||||
|
static GimpValueArray * wia_main (GimpProcedure *procedure,
|
||||||
|
GimpProcedureConfig *config);
|
||||||
|
|
||||||
|
static HRESULT CreateWiaDeviceManager (IWiaDevMgr2 **ppWiaDevMgr);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (Wia, wia, GIMP_TYPE_PLUG_IN)
|
||||||
|
|
||||||
|
GIMP_MAIN (WIA_TYPE)
|
||||||
|
DEFINE_STD_SET_I18N
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
wia_class_init (WiaClass *klass)
|
||||||
|
{
|
||||||
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
||||||
|
|
||||||
|
plug_in_class->query_procedures = wia_query_procedures;
|
||||||
|
plug_in_class->create_procedure = wia_create_procedure;
|
||||||
|
plug_in_class->set_i18n = STD_SET_I18N;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wia_init (Wia *wia)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static GList *
|
||||||
|
wia_query_procedures (GimpPlugIn *plug_in)
|
||||||
|
{
|
||||||
|
return g_list_append (NULL, g_strdup (PLUG_IN_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GimpProcedure *
|
||||||
|
wia_create_procedure (GimpPlugIn *plug_in,
|
||||||
|
const gchar *name)
|
||||||
|
{
|
||||||
|
GimpProcedure *procedure = NULL;
|
||||||
|
|
||||||
|
if (! strcmp (name, PLUG_IN_NAME))
|
||||||
|
{
|
||||||
|
procedure = gimp_image_procedure_new (plug_in, name,
|
||||||
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
||||||
|
wia_run, NULL, NULL);
|
||||||
|
|
||||||
|
gimp_procedure_set_image_types (procedure, "*");
|
||||||
|
gimp_procedure_set_sensitivity_mask (procedure,
|
||||||
|
GIMP_PROCEDURE_SENSITIVE_DRAWABLE |
|
||||||
|
GIMP_PROCEDURE_SENSITIVE_DRAWABLES |
|
||||||
|
GIMP_PROCEDURE_SENSITIVE_NO_DRAWABLES |
|
||||||
|
GIMP_PROCEDURE_SENSITIVE_NO_IMAGE);
|
||||||
|
|
||||||
|
gimp_procedure_set_menu_label (procedure, _("_Scanner/Camera..."));
|
||||||
|
gimp_procedure_add_menu_path (procedure, "<Image>/File/Create");
|
||||||
|
|
||||||
|
gimp_procedure_set_documentation (procedure,
|
||||||
|
PLUG_IN_DESCRIPTION,
|
||||||
|
PLUG_IN_HELP,
|
||||||
|
name);
|
||||||
|
gimp_procedure_set_attribution (procedure,
|
||||||
|
"Alx Sa",
|
||||||
|
"Alx Sa",
|
||||||
|
"2026");
|
||||||
|
|
||||||
|
gimp_procedure_add_string_aux_argument (procedure, "scan-directory",
|
||||||
|
NULL, NULL,
|
||||||
|
NULL,
|
||||||
|
GIMP_PARAM_READWRITE);
|
||||||
|
|
||||||
|
gimp_procedure_add_core_object_array_return_value (procedure, "images",
|
||||||
|
"Array of acquired images",
|
||||||
|
"Array of acquired images",
|
||||||
|
GIMP_TYPE_IMAGE,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return procedure;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GimpValueArray *
|
||||||
|
wia_run (GimpProcedure *procedure,
|
||||||
|
GimpRunMode run_mode,
|
||||||
|
GimpImage *image,
|
||||||
|
GimpDrawable **drawables,
|
||||||
|
GimpProcedureConfig *config,
|
||||||
|
gpointer run_data)
|
||||||
|
{
|
||||||
|
gegl_init (NULL, NULL);
|
||||||
|
|
||||||
|
if (run_mode == GIMP_RUN_NONINTERACTIVE)
|
||||||
|
/* Currently, we don't do non-interactive calls.
|
||||||
|
* Bail if someone tries to call us non-interactively
|
||||||
|
*/
|
||||||
|
return gimp_procedure_new_return_values (procedure, GIMP_PDB_CALLING_ERROR,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return wia_main (procedure, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Windows methods */
|
||||||
|
static HRESULT
|
||||||
|
CreateWiaDeviceManager (IWiaDevMgr2 **ppWiaDevMgr)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (NULL == ppWiaDevMgr)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
*ppWiaDevMgr = NULL;
|
||||||
|
|
||||||
|
hr = CoCreateInstance (&CLSID_WiaDevMgr2, NULL, CLSCTX_LOCAL_SERVER,
|
||||||
|
&IID_IWiaDevMgr2, (void**) ppWiaDevMgr);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GimpValueArray *
|
||||||
|
wia_main (GimpProcedure *procedure,
|
||||||
|
GimpProcedureConfig *config)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
HRESULT hr = CoInitialize (NULL);
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr))
|
||||||
|
{
|
||||||
|
IWiaDevMgr2 *pWiaDevMgr2 = NULL;
|
||||||
|
|
||||||
|
hr = CreateWiaDeviceManager (&pWiaDevMgr2);
|
||||||
|
|
||||||
|
if (SUCCEEDED (hr))
|
||||||
|
{
|
||||||
|
GimpImage **images = NULL;
|
||||||
|
GimpValueArray *return_vals = NULL;
|
||||||
|
HWND window_handle;
|
||||||
|
LONG nFiles = 0;
|
||||||
|
LPWSTR *rFilePaths = NULL;
|
||||||
|
IWiaItem2 *pItem = NULL;
|
||||||
|
BSTR szFolder = NULL;
|
||||||
|
BSTR szFileName;
|
||||||
|
TCHAR temp_path[MAX_FOLDER_PATH];
|
||||||
|
gchar *scan_directory = NULL;
|
||||||
|
|
||||||
|
szFileName = SysAllocString (L"GIMP-SCANNED-IMAGE");
|
||||||
|
|
||||||
|
/* Check if we have a saved directory, and if so, if it's still
|
||||||
|
* valid. */
|
||||||
|
g_object_get (config, "scan-directory", &scan_directory, NULL);
|
||||||
|
if (scan_directory != NULL)
|
||||||
|
{
|
||||||
|
GDir *directory = g_dir_open (scan_directory, 0, NULL);
|
||||||
|
|
||||||
|
if (directory)
|
||||||
|
{
|
||||||
|
szFolder =
|
||||||
|
SysAllocString (g_utf8_to_utf16 (scan_directory, -1, NULL,
|
||||||
|
NULL, NULL));
|
||||||
|
g_dir_close (directory);
|
||||||
|
}
|
||||||
|
g_free (scan_directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, use Window's temp location */
|
||||||
|
if (szFolder == NULL)
|
||||||
|
{
|
||||||
|
GetTempPath (MAX_FOLDER_PATH, temp_path);
|
||||||
|
szFolder = SysAllocString (g_utf8_to_utf16 (temp_path, -1, NULL,
|
||||||
|
NULL, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Values taken from app/gui/gui-unique.h */
|
||||||
|
window_handle = FindWindowW (L"GimpWin32UniqueHandler", L"GimpProxy");
|
||||||
|
|
||||||
|
hr = pWiaDevMgr2->lpVtbl->GetImageDlg (pWiaDevMgr2, 0, NULL, window_handle,
|
||||||
|
szFolder, szFileName, &nFiles,
|
||||||
|
&rFilePaths, &pItem);
|
||||||
|
SysFreeString (szFolder);
|
||||||
|
SysFreeString (szFileName);
|
||||||
|
|
||||||
|
if (FAILED (hr))
|
||||||
|
{
|
||||||
|
pWiaDevMgr2->lpVtbl->Release (pWiaDevMgr2);
|
||||||
|
pWiaDevMgr2 = NULL;
|
||||||
|
|
||||||
|
CoUninitialize ();
|
||||||
|
|
||||||
|
g_set_error (&error, GIMP_PLUG_IN_ERROR, 0,
|
||||||
|
_("Unable to read scanned images."));
|
||||||
|
|
||||||
|
return gimp_procedure_new_return_values (procedure,
|
||||||
|
GIMP_PDB_EXECUTION_ERROR,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nFiles > 0)
|
||||||
|
{
|
||||||
|
gboolean has_directory = FALSE;
|
||||||
|
images = g_new0 (GimpImage *, nFiles + 1);
|
||||||
|
|
||||||
|
for (gint i = 0; i < nFiles; i++)
|
||||||
|
{
|
||||||
|
gchar *filename = g_utf16_to_utf8 (rFilePaths[i], -1, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
if (filename)
|
||||||
|
{
|
||||||
|
GFile *file = g_file_new_for_path (filename);
|
||||||
|
|
||||||
|
images[i] = gimp_file_load (GIMP_RUN_NONINTERACTIVE,
|
||||||
|
file);
|
||||||
|
gimp_display_new (images[i]);
|
||||||
|
if (! gimp_image_undo_is_enabled (images[i]))
|
||||||
|
gimp_image_undo_enable (images[i]);
|
||||||
|
|
||||||
|
/* Store first valid directory for later use */
|
||||||
|
if (! has_directory)
|
||||||
|
{
|
||||||
|
GFile *parent = g_file_get_parent (file);
|
||||||
|
|
||||||
|
g_object_set (config,
|
||||||
|
"scan-directory",
|
||||||
|
g_file_get_parse_name (parent),
|
||||||
|
NULL);
|
||||||
|
g_object_unref (parent);
|
||||||
|
|
||||||
|
has_directory = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (file);
|
||||||
|
g_free (filename);
|
||||||
|
}
|
||||||
|
SysFreeString (rFilePaths[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoTaskMemFree (rFilePaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
pWiaDevMgr2->lpVtbl->Release (pWiaDevMgr2);
|
||||||
|
pWiaDevMgr2 = NULL;
|
||||||
|
|
||||||
|
CoUninitialize ();
|
||||||
|
|
||||||
|
return_vals = gimp_procedure_new_return_values (procedure,
|
||||||
|
GIMP_PDB_SUCCESS,
|
||||||
|
NULL);
|
||||||
|
GIMP_VALUES_TAKE_CORE_OBJECT_ARRAY (return_vals, 1, images);
|
||||||
|
|
||||||
|
return return_vals;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error (&error, GIMP_PLUG_IN_ERROR, 0,
|
||||||
|
_("WIA driver not found, scanning not available"));
|
||||||
|
|
||||||
|
return gimp_procedure_new_return_values (procedure,
|
||||||
|
GIMP_PDB_EXECUTION_ERROR,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoUninitialize ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
@ -93,6 +93,7 @@ plug-ins/common/warp.c
|
||||||
plug-ins/common/wavelet-decompose.c
|
plug-ins/common/wavelet-decompose.c
|
||||||
plug-ins/common/web-browser.c
|
plug-ins/common/web-browser.c
|
||||||
plug-ins/common/web-page.c
|
plug-ins/common/web-page.c
|
||||||
|
plug-ins/common/wia.c
|
||||||
plug-ins/file-bmp/bmp-export.c
|
plug-ins/file-bmp/bmp-export.c
|
||||||
plug-ins/file-bmp/bmp-load.c
|
plug-ins/file-bmp/bmp-load.c
|
||||||
plug-ins/file-bmp/bmp.c
|
plug-ins/file-bmp/bmp.c
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue