Skip to content

Commit e4789fa

Browse files
committed
Fix reading of 1-bit depth data
1 parent 3aeeb30 commit e4789fa

1 file changed

Lines changed: 30 additions & 11 deletions

File tree

_sane.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -422,17 +422,24 @@ SaneDev_snap(SaneDevObject *self, PyObject *args)
422422

423423
RAISE_IF(p.depth != 1 && p.depth != 8 && p.depth != 16, "Bad pixel depth");
424424

425-
int imgSampelsPerPixel = (p.format == SANE_FRAME_GRAY ? 1 : 3);
425+
int imgSamplesPerPixel = (p.format == SANE_FRAME_GRAY ? 1 : 3);
426426
int imgPixelsPerLine = p.pixels_per_line;
427427
int imgSampleSize = (p.depth == 16 && allow16bitsamples ? 2 : 1);
428-
int imgBytesPerLine = imgPixelsPerLine * imgSampelsPerPixel * imgSampleSize;
428+
int imgBytesPerLine = imgPixelsPerLine * imgSamplesPerPixel * imgSampleSize;
429+
int imgBytesPerScanLine = imgBytesPerLine;
430+
if(p.depth == 1)
431+
{
432+
/* See Sane spec chapter 4.3.8 */
433+
imgBytesPerScanLine = imgSamplesPerPixel * ((imgPixelsPerLine + 7) / 8);
434+
}
429435
int imgBufCurLine = 0;
430436
int imgBufLines = p.lines < 1 ? 1 : p.lines;
437+
const unsigned char bitMasks[8] = {128, 64, 32, 16, 8, 4, 2, 1};
431438
SANE_Byte* imgBuf = (SANE_Byte*)malloc(imgBufLines * imgBytesPerLine);
432439

433440
SANE_Int lineBufUsed = 0;
434-
SANE_Byte* lineBuf = (SANE_Byte*)malloc(imgBytesPerLine);
435-
int i;
441+
SANE_Byte* lineBuf = (SANE_Byte*)malloc(imgBytesPerScanLine);
442+
int i, j;
436443

437444
/* Read data */
438445
Py_BEGIN_ALLOW_THREADS
@@ -442,11 +449,11 @@ SaneDev_snap(SaneDevObject *self, PyObject *args)
442449
{
443450
/* Read one line */
444451
lineBufUsed = 0;
445-
while(lineBufUsed < imgBytesPerLine)
452+
while(lineBufUsed < imgBytesPerScanLine)
446453
{
447454
SANE_Int nRead = 0;
448455
st = sane_read(self->h, lineBuf + lineBufUsed,
449-
imgBytesPerLine - lineBufUsed,
456+
imgBytesPerScanLine - lineBufUsed,
450457
&nRead);
451458
if(st != SANE_STATUS_GOOD)
452459
break;
@@ -484,8 +491,16 @@ SaneDev_snap(SaneDevObject *self, PyObject *args)
484491
{
485492
if(p.depth == 1)
486493
{
487-
for(i = 0; i < imgBytesPerLine; ++i)
488-
imgBuf[imgBufOffset + i] = lineBuf[i / 8] & (0x80 >> (i % 8)) ? 0 : 255;
494+
/* See Sane spec chapter 3.2.1 */
495+
for(j = 0; j < imgSamplesPerPixel; ++j)
496+
{
497+
for(i = 0; i < imgPixelsPerLine; ++i)
498+
{
499+
int iImgBuf = imgBufOffset + imgSamplesPerPixel * i + j;
500+
int lineByte = imgSamplesPerPixel * (i / 8) + j;
501+
imgBuf[iImgBuf] = (lineBuf[lineByte] & bitMasks[i % 8]) ? 0 : 255;
502+
}
503+
}
489504
}
490505
else if(p.depth == 8)
491506
{
@@ -511,8 +526,12 @@ SaneDev_snap(SaneDevObject *self, PyObject *args)
511526
int channel = p.format - SANE_FRAME_RED;
512527
if(p.depth == 1)
513528
{
514-
for(i = 0; i < p.pixels_per_line; ++i)
515-
imgBuf[imgBufOffset + 3 * i + channel] = lineBuf[i / 8] & (0x80 >> (i % 8)) ? 0 : 255;
529+
/* See Sane spec chapter 3.2.1 */
530+
for(i = 0; i < imgPixelsPerLine; ++i)
531+
{
532+
int iImgBuf = imgBufOffset + 3 * i + channel;
533+
imgBuf[iImgBuf] = (lineBuf[i / 8] & bitMasks[i % 8]) ? 0 : 255;
534+
}
516535
}
517536
else if(p.depth == 8)
518537
{
@@ -569,7 +588,7 @@ SaneDev_snap(SaneDevObject *self, PyObject *args)
569588
return NULL;
570589

571590
PyObject* ret = Py_BuildValue("Oiiii", pyByteArray, imgPixelsPerLine,
572-
imgBufLines, imgSampelsPerPixel,
591+
imgBufLines, imgSamplesPerPixel,
573592
imgSampleSize);
574593
Py_DECREF(pyByteArray);
575594

0 commit comments

Comments
 (0)