Issue #4941 - TWAIN 16-bit greyscale/rgb scan always loaded as 8-bit

Simplify data transfer in the twain plug-in, and add support for
16-bit RGB/grayscale images.
This commit is contained in:
Ell 2020-06-04 20:36:48 +03:00
parent a276f26b6c
commit 00e1172a54
1 changed files with 55 additions and 89 deletions

View File

@ -517,9 +517,13 @@ beginTransferCallback (pTW_IMAGEINFO imageInfo,
{
pClientDataStruct theClientData = g_new (ClientDataStruct, 1);
const Babl *format;
int imageType;
int layerType;
const Babl *format;
GimpImageBaseType imageType;
GimpImageType layerType;
GimpPrecision precision;
gint bpc = imageInfo->BitsPerPixel /
imageInfo->SamplesPerPixel;
#ifdef _DEBUG
@ -530,12 +534,33 @@ beginTransferCallback (pTW_IMAGEINFO imageInfo,
switch (imageInfo->PixelType)
{
case TWPT_BW:
/* Set up the image and layer types */
imageType = GIMP_GRAY;
layerType = GIMP_GRAY_IMAGE;
precision = GIMP_PRECISION_U8_GAMMA;
format = babl_format ("Y' u8");
break;
case TWPT_GRAY:
/* Set up the image and layer types */
imageType = GIMP_GRAY;
layerType = GIMP_GRAY_IMAGE;
format = babl_format ("Y' u8");
switch (bpc)
{
case 8:
precision = GIMP_PRECISION_U8_GAMMA;
format = babl_format ("Y' u8");
break;
case 16:
precision = GIMP_PRECISION_U16_GAMMA;
format = babl_format ("Y' u16");
break;
default:
return FALSE;
}
break;
case TWPT_RGB:
@ -543,7 +568,21 @@ beginTransferCallback (pTW_IMAGEINFO imageInfo,
imageType = GIMP_RGB;
layerType = GIMP_RGB_IMAGE;
format = babl_format ("R'G'B' u8");
switch (bpc)
{
case 8:
precision = GIMP_PRECISION_U8_GAMMA;
format = babl_format ("R'G'B' u8");
break;
case 16:
precision = GIMP_PRECISION_U16_GAMMA;
format = babl_format ("R'G'B' u16");
break;
default:
return FALSE;
}
break;
case TWPT_PALETTE:
@ -588,9 +627,10 @@ beginTransferCallback (pTW_IMAGEINFO imageInfo,
}
/* Create the GIMP image */
theClientData->image = gimp_image_new (imageInfo->ImageWidth,
imageInfo->ImageLength,
imageType);
theClientData->image = gimp_image_new_with_precision (imageInfo->ImageWidth,
imageInfo->ImageLength,
imageType,
precision);
/* Set the actual resolution */
gimp_image_set_resolution (theClientData->image,
@ -703,40 +743,16 @@ oneBytePerSampleTransferCallback (pTW_IMAGEINFO imageInfo,
pTW_IMAGEMEMXFER imageMemXfer,
void *clientData)
{
int row;
char *srcBuf;
char *destBuf;
int bytesPerPixel = imageInfo->BitsPerPixel / 8;
int rows = imageMemXfer->Rows;
int cols = imageMemXfer->Columns;
int rows = imageMemXfer->Rows;
int cols = imageMemXfer->Columns;
pClientDataStruct theClientData = (pClientDataStruct) clientData;
/* Allocate a buffer as necessary */
destBuf = gegl_scratch_new (char, rows * cols * bytesPerPixel);
/* The bytes coming from the source may not be padded in
* a way that GIMP is terribly happy with. It is
* possible to transfer row by row, but that is particularly
* expensive in terms of performance. It is much cheaper
* to rearrange the data and transfer it in one large chunk.
* The next chunk of code rearranges the incoming data into
* a non-padded chunk for GIMP.
*/
srcBuf = (char *) imageMemXfer->Memory.TheMem;
for (row = 0; row < rows; row++)
{
/* Copy the current row */
memcpy ((destBuf + (row * bytesPerPixel * cols)),
(srcBuf + (row * imageMemXfer->BytesPerRow)),
(bytesPerPixel * cols));
}
/* Update the complete chunk */
gegl_buffer_set (theClientData->buffer,
GEGL_RECTANGLE (imageMemXfer->XOffset, imageMemXfer->YOffset,
cols, rows), 0,
theClientData->format, destBuf,
GEGL_AUTO_ROWSTRIDE);
theClientData->format, imageMemXfer->Memory.TheMem,
imageMemXfer->BytesPerRow);
/* Free the buffer */
gegl_scratch_free (destBuf);
@ -761,68 +777,18 @@ twoBytesPerSampleTransferCallback (pTW_IMAGEINFO imageInfo,
pTW_IMAGEMEMXFER imageMemXfer,
void *clientData)
{
static float ratio = 0.00390625;
int row, col, sample;
char *destBuf;
char *destByte;
int rows = imageMemXfer->Rows;
int cols = imageMemXfer->Columns;
TW_UINT16 *samplePtr;
int rows = imageMemXfer->Rows;
int cols = imageMemXfer->Columns;
pClientDataStruct theClientData = (pClientDataStruct) clientData;
/* Allocate a buffer as necessary */
destBuf = gegl_scratch_new (char, rows * cols * imageInfo->SamplesPerPixel);
/* The bytes coming from the source may not be padded in
* a way that GIMP is terribly happy with. It is
* possible to transfer row by row, but that is particularly
* expensive in terms of performance. It is much cheaper
* to rearrange the data and transfer it in one large chunk.
* The next chunk of code rearranges the incoming data into
* a non-padded chunk for GIMP. This function must also
* reduce from multiple bytes per sample down to single byte
* per sample.
*/
/* Work through the rows */
for (row = 0; row < rows; row++)
{
/* The start of this source row */
samplePtr = (TW_UINT16 *)
((char *) imageMemXfer->Memory.TheMem + (row * imageMemXfer->BytesPerRow));
/* The start of this dest row */
destByte = destBuf + (row * imageInfo->SamplesPerPixel * cols);
/* Work through the columns */
for (col = 0; col < cols; col++)
{
/* Finally, work through each of the samples */
for (sample = 0; sample < imageInfo->SamplesPerPixel; sample++)
{
/* Get the value */
TW_UINT16 value = *samplePtr;
/* Move the sample pointer */
samplePtr++;
/* Place in the destination */
*destByte = (char) ((float) value * (float) ratio);
destByte++;
}
}
}
/* Send the complete chunk */
gegl_buffer_set (theClientData->buffer,
GEGL_RECTANGLE (imageMemXfer->XOffset, imageMemXfer->YOffset,
cols, rows), 0,
theClientData->format, destBuf,
theClientData->format, imageMemXfer->Memory.TheMem,
GEGL_AUTO_ROWSTRIDE);
/* Free the buffer */
gegl_scratch_free (destBuf);
/* Update the user on our progress */
theClientData->completedPixels += (cols * rows);
gimp_progress_update ((double) theClientData->completedPixels /