1/* sane - Scanner Access Now Easy. 2 Copyright (C) 1997 BYTEC GmbH Germany 3 Written by Helmut Koeberle, Email: helmut.koeberle@bytec.de 4 Modified by Manuel Panea <Manuel.Panea@rzg.mpg.de> 5 and Markus Mertinat <Markus.Mertinat@Physik.Uni-Augsburg.DE> 6 7 This file is part of the SANE package. 8 9 This program is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, but 15 WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <https://www.gnu.org/licenses/>. 21 22 As a special exception, the authors of SANE give permission for 23 additional uses of the libraries contained in this release of SANE. 24 25 The exception is that, if you link a SANE library with other files 26 to produce an executable, this does not by itself cause the 27 resulting executable to be covered by the GNU General Public 28 License. Your use of that executable is in no way restricted on 29 account of linking the SANE library code into it. 30 31 This exception does not, however, invalidate any other reasons why 32 the executable file might be covered by the GNU General Public 33 License. 34 35 If you submit changes to SANE to the maintainers to be included in 36 a subsequent release, you agree by submitting the changes that 37 those changes may be distributed with this exception intact. 38 39 If you write modifications of your own for SANE, it is your choice 40 whether to permit this exception to apply to your modifications. 41 If you do not wish that, delete this exception notice. */ 42 43/* This file implements the low-level scsi-commands. */ 44 45static SANE_Status 46test_unit_ready (int fd) 47{ 48 static u_char cmd[6]; 49 int status; 50 DBG (31, ">> test_unit_ready\n"); 51 52 memset (cmd, 0, sizeof (cmd)); 53 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 54 55 DBG (31, "<< test_unit_ready\n"); 56 return (status); 57} 58 59#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS 60static SANE_Status 61request_sense (int fd, void *buf, size_t *buf_size) 62{ 63 static u_char cmd[6]; 64 int status; 65 DBG (31, ">> request_sense\n"); 66 67 memset (cmd, 0, sizeof (cmd)); 68 cmd[0] = 0x03; 69 cmd[4] = 14; 70 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 71 72 DBG (31, "<< request_sense\n"); 73 return (status); 74} 75#endif 76 77static SANE_Status 78inquiry (int fd, int evpd, void *buf, size_t *buf_size) 79{ 80 static u_char cmd[6]; 81 int status; 82 DBG (31, ">> inquiry\n"); 83 84 memset (cmd, 0, sizeof (cmd)); 85 cmd[0] = 0x12; 86 cmd[1] = evpd; 87 cmd[2] = evpd ? 0xf0 : 0; 88 cmd[4] = evpd ? 74 : 36; 89 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 90 91 DBG (31, "<< inquiry\n"); 92 return (status); 93} 94 95#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS 96static SANE_Status 97mode_select (int fd) 98{ 99 static u_char cmd[6 + 12]; 100 int status; 101 DBG (31, ">> mode_select\n"); 102 103 memset (cmd, 0, sizeof (cmd)); 104 cmd[0] = 0x15; 105 cmd[1] = 16; 106 cmd[4] = 12; 107 cmd[6 + 4] = 3; 108 cmd[6 + 5] = 6; 109 cmd[6 + 8] = 0x02; 110 cmd[6 + 9] = 0x58; 111 status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), NULL, NULL); 112 113 DBG (31, "<< mode_select\n"); 114 return (status); 115} 116#endif 117 118static SANE_Status 119reserve_unit (int fd) 120{ 121 static u_char cmd[6]; 122 int status; 123 DBG (31, ">> reserve_unit\n"); 124 125 memset (cmd, 0, sizeof (cmd)); 126 cmd[0] = 0x16; 127 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 128 129 DBG (31, "<< reserve_unit\n"); 130 return (status); 131} 132 133#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS 134static SANE_Status 135release_unit (int fd) 136{ 137 static u_char cmd[6]; 138 int status; 139 DBG (31, ">> release_unit\n"); 140 141 memset (cmd, 0, sizeof (cmd)); 142 cmd[0] = 0x17; 143 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 144 145 DBG (31, "<< release_unit\n"); 146 return (status); 147} 148#endif 149 150static SANE_Status 151mode_sense (int fd, void *buf, size_t *buf_size) 152{ 153 static u_char cmd[6]; 154 int status; 155 DBG (31, ">> mode_sense\n"); 156 157 memset (cmd, 0, sizeof (cmd)); 158 cmd[0] = 0x1a; 159 cmd[2] = 3; 160 cmd[4] = 12; 161 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 162 163 DBG (31, "<< mode_sense\n"); 164 return (status); 165} 166 167static SANE_Status 168scan (int fd) 169{ 170 static u_char cmd[6 + 1]; 171 int status; 172 DBG (31, ">> scan\n"); 173 174 memset (cmd, 0, sizeof (cmd)); 175 cmd[0] = 0x1b; 176 cmd[4] = 1; 177 status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), NULL, NULL); 178 179 DBG (31, "<< scan\n"); 180 return (status); 181} 182 183static SANE_Status 184send_diagnostic (int fd) 185{ 186 static u_char cmd[6]; 187 int status; 188 DBG (31, ">> send_diagnostic\n"); 189 190 memset (cmd, 0, sizeof (cmd)); 191 cmd[0] = 0x1d; 192 cmd[1] = 4; 193 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 194 195 DBG (31, "<< send_diagnostic\n"); 196 return (status); 197} 198 199static SANE_Status 200set_window (int fd, void *data) 201{ 202 static u_char cmd[10]; 203 int status; 204 DBG (31, ">> set_window\n"); 205 206 memset (cmd, 0, sizeof (cmd)); 207 cmd[0] = 0x24; 208 cmd[8] = 72; 209 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), data, 72, NULL, NULL); 210 211 DBG (31, "<< set_window\n"); 212 return (status); 213} 214 215static SANE_Status 216get_window (int fd, void *buf, size_t *buf_size) 217{ 218 static u_char cmd[10]; 219 int status; 220 DBG (31, ">> get_window\n"); 221 222 memset (cmd, 0, sizeof (cmd)); 223 cmd[0] = 0x25; 224 cmd[1] = 1; 225 cmd[8] = 72; 226 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 227 228 DBG (31, "<< get_window\n"); 229 return (status); 230} 231 232static SANE_Status 233read_data (int fd, void *buf, size_t *buf_size) 234{ 235 static u_char cmd[10]; 236 int status; 237 DBG (31, ">> read_data\n"); 238 239 memset (cmd, 0, sizeof (cmd)); 240 cmd[0] = 0x28; 241 cmd[6] = *buf_size >> 16; 242 cmd[7] = *buf_size >> 8; 243 cmd[8] = *buf_size; 244 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 245 246 DBG (31, "<< read_data\n"); 247 return (status); 248} 249 250static SANE_Status 251medium_position (int fd) 252{ 253 static u_char cmd[10]; 254 int status; 255 DBG (31, ">> medium_position\n"); 256 257 memset (cmd, 0, sizeof (cmd)); 258 cmd[0] = 0x31; 259 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 260 261 DBG (31, "<< medium_position\n"); 262 return (status); 263} 264 265#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS 266static SANE_Status 267execute_shading (int fd) 268{ 269 static u_char cmd[10]; 270 int status; 271 DBG (31, ">> execute shading\n"); 272 273 memset (cmd, 0, sizeof (cmd)); 274 cmd[0] = 0xe2; 275 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 276 277 DBG (31, "<< execute shading\n"); 278 return (status); 279} 280#endif 281 282static SANE_Status 283execute_auto_focus (int fd, int AF, int speed, int AE, int count) 284{ 285 static u_char cmd[10]; 286 int status; 287 DBG (7, ">> execute_auto_focus\n"); 288 DBG (7, ">> focus: mode='%d', speed='%d', AE='%d', count='%d'\n", 289 AF, speed, AE, count); 290 291 memset (cmd, 0, sizeof (cmd)); 292 cmd[0] = 0xe0; 293 cmd[1] = (u_char) AF; 294 cmd[2] = (u_char) ((speed << 7) | AE); 295#if 1 296 cmd[4] = (u_char) count; /* seems to work, but may be unsafe */ 297#else /* The Canon software uses this: */ 298 cmd[4] = (u_char) (28 * ((int) (count / 28.5)) + 16); 299#endif 300 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 301 302 DBG (7, "<< execute_auto_focus\n"); 303 return (status); 304} 305 306static SANE_Status 307set_adf_mode (int fd, u_char priority) 308{ 309 static u_char cmd[6]; 310 int status; 311 312 memset (cmd, 0, sizeof (cmd)); 313 cmd[0] = 0xd4; 314 cmd[4] = 0x01; 315 316 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), &priority, 1, NULL, NULL); 317 318 return (status); 319} 320 321static SANE_Status 322get_scan_mode (int fd, u_char page, void *buf, size_t *buf_size) 323{ 324 static u_char cmd[6]; 325 int status; 326 int PageLen = 0x00; 327 328 memset (cmd, 0, sizeof (cmd)); 329 cmd[0] = 0xd5; 330 cmd[2] = page; 331 332 switch (page) 333 { 334 case AUTO_DOC_FEEDER_UNIT: 335 case TRANSPARENCY_UNIT: 336 cmd[4] = 0x0c + PageLen; 337 break; 338 339 case SCAN_CONTROL_CONDITIONS: 340 cmd[4] = 0x14 + PageLen; 341 break; 342 343 case SCAN_CONTROL_CON_FB1200: 344 cmd[2] = 0x20; 345 cmd[4] = 0x17 + PageLen; 346 break; 347 348 default: 349 cmd[4] = 0x24 + PageLen; 350 break; 351 } 352 353 DBG (31, "get scan mode: cmd[4]='0x%0X'\n", cmd[4]); 354 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 355 356 DBG (31, "<< get scan mode\n"); 357 return (status); 358} 359 360static SANE_Status 361define_scan_mode (int fd, u_char page, void *data) 362{ 363 static u_char cmd[6]; 364 u_char pdata[36]; 365 size_t i; 366 int status, pdatalen; 367 DBG (31, ">> define scan mode\n"); 368 369 memset (cmd, 0, sizeof (cmd)); 370 memset (pdata, 0, sizeof (pdata)); 371 cmd[0] = 0xd6; 372 cmd[1] = 0x10; 373 cmd[4] = (page == TRANSPARENCY_UNIT) ? 0x0c 374 : (page == TRANSPARENCY_UNIT_FB1200) ? 0x0c 375 : (page == SCAN_CONTROL_CONDITIONS) ? 0x14 376 : (page == SCAN_CONTROL_CON_FB1200) ? 0x17 : 0x24; 377 378 memcpy (pdata + 4, data, (page == TRANSPARENCY_UNIT) ? 8 379 : (page == TRANSPARENCY_UNIT_FB1200) ? 10 380 : (page == SCAN_CONTROL_CONDITIONS) ? 16 381 : (page == SCAN_CONTROL_CON_FB1200) ? 19 : 32); 382 383 for (i = 0; i < sizeof (cmd); i++) 384 DBG (31, "define scan mode: cmd[%d]='0x%0X'\n", (int) i, 385 cmd[i]); 386 387 for (i = 0; i < sizeof (pdata); i++) 388 DBG (31, "define scan mode: pdata[%d]='0x%0X'\n", (int) i, 389 pdata[i]); 390 391 pdatalen = (page == TRANSPARENCY_UNIT) ? 12 392 : (page == TRANSPARENCY_UNIT_FB1200) ? 14 393 : (page == SCAN_CONTROL_CONDITIONS) ? 20 394 : (page == SCAN_CONTROL_CON_FB1200) ? 23 : 36; 395 396 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), pdata, pdatalen, NULL, 397 NULL); 398 DBG (31, "<< define scan mode\n"); 399 return (status); 400} 401 402static SANE_Status 403get_density_curve (int fd, int component, void *buf, size_t *buf_size, 404 int transfer_data_type) 405{ 406 static u_char cmd[10]; 407 int status; 408 DBG (31, ">> get_density_curve\n"); 409 410 memset (cmd, 0, sizeof (cmd)); 411 cmd[0] = 0x28; 412 cmd[2] = transfer_data_type; 413 cmd[4] = component; 414 cmd[5] = 0; 415 cmd[6] = ((*buf_size) >> 16) & 0xff; 416 cmd[7] = ((*buf_size) >> 8) & 0xff; 417 cmd[8] = (*buf_size) & 0xff; 418 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 419 420 DBG (31, "<< get_density_curve\n"); 421 return (status); 422} 423 424#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS 425static SANE_Status 426get_density_curve_data_format (int fd, void *buf, size_t *buf_size) 427{ 428 static u_char cmd[10]; 429 int status; 430 DBG (31, ">> get_density_curve_data_format\n"); 431 432 memset (cmd, 0, sizeof (cmd)); 433 cmd[0] = 0x28; 434 cmd[2] = 0x03; 435 cmd[4] = 0xff; 436 cmd[5] = 0; 437 cmd[6] = 0; 438 cmd[7] = 0; 439 cmd[8] = 14; 440 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 441 442 DBG (31, "<< get_density_curve_data_format\n"); 443 return (status); 444} 445#endif 446 447static SANE_Status 448set_density_curve (int fd, int component, void *buf, size_t *buf_size, 449 int transfer_data_type) 450{ 451 static u_char cmd[10]; 452 int status; 453 DBG (31, ">> set_density_curve\n"); 454 455 memset (cmd, 0, sizeof (cmd)); 456 cmd[0] = 0x2a; 457 cmd[2] = transfer_data_type; 458 cmd[4] = component; 459 cmd[5] = 0; 460 cmd[6] = ((*buf_size) >> 16) & 0xff; 461 cmd[7] = ((*buf_size) >> 8) & 0xff; 462 cmd[8] = (*buf_size) & 0xff; 463 464 status = 465 sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), buf, *buf_size, NULL, NULL); 466 467 DBG (31, "<< set_density_curve\n"); 468 return (status); 469} 470 471 472/* static SANE_Status */ 473/* set_density_curve_data_format (int fd, void *buf, size_t *buf_size) */ 474/* { */ 475/* static u_char cmd[10]; */ 476/* int status, i; */ 477/* DBG (31, ">> set_density_curve_data_format\n"); */ 478 479/* memset (cmd, 0, sizeof (cmd)); */ 480/* cmd[0] = 0x2a; */ 481/* cmd[2] = 0x03; */ 482/* cmd[4] = 0xff; */ 483/* cmd[5] = 0; */ 484/* cmd[6] = 0; */ 485/* cmd[7] = 0; */ 486/* cmd[8] = 14; */ 487/* status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); */ 488 489/* DBG (31, "<< set_density_curve_data_format\n"); */ 490/* return (status); */ 491/* } */ 492 493#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS 494static SANE_Status 495get_power_on_timer (int fd, void *buf, size_t *buf_size) 496{ 497 static u_char cmd[10]; 498 int status; 499 DBG (31, ">> get power on timer\n"); 500 501 memset (cmd, 0, sizeof (cmd)); 502 cmd[0] = 0xe3; 503 cmd[6] = 1; 504 cmd[7] = 0; 505 cmd[8] = 0; 506 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 507 508 DBG (31, "<< get power on timer\n"); 509 return (status); 510} 511#endif 512 513static SANE_Status 514get_film_status (int fd, void *buf, size_t *buf_size) 515{ 516 static u_char cmd[10]; 517 int status; 518 DBG (31, ">> get film status\n"); 519 520 memset (cmd, 0, sizeof (cmd)); 521 cmd[0] = 0xe1; 522 cmd[6] = 0; 523 cmd[7] = 0; 524 cmd[8] = 4; 525 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 526 527 DBG (31, "<< get film status\n"); 528 return (status); 529} 530 531static SANE_Status 532get_data_status (int fd, void *buf, size_t *buf_size) 533{ 534 static u_char cmd[10]; 535 int status; 536 DBG (31, ">> get_data_status\n"); 537 538 memset (cmd, 0, sizeof (cmd)); 539 cmd[0] = 0x34; 540 cmd[8] = 28; 541 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 542 543 DBG (31, "<< get_data_status\n"); 544 return (status); 545} 546 547/*************** modification for FB620S ***************/ 548static SANE_Status 549reset_scanner (int fd) 550{ 551 static u_char cmd[6]; 552 int status; 553 DBG (31, ">> reset_scanner\n"); 554 555 memset (cmd, 0, sizeof (cmd)); 556 cmd[0] = 0xc1; 557 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 558 559 DBG (31, "<< reset_scanner \n"); 560 return (status); 561} 562 563static SANE_Status 564execute_calibration (int fd) 565{ 566 static u_char cmd[6]; 567 u_char data[2]; 568 int status; 569 DBG (31, ">> execute_calibration\n"); 570 571 memset (cmd, 0, sizeof (cmd)); 572 memset (data, 0, sizeof (data)); 573 cmd[0] = 0xc2; 574 cmd[4] = 2; 575 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), data, sizeof (data), 576 NULL, NULL); 577 578 DBG (31, "<< execute_calibration\n"); 579 return (status); 580} 581 582static SANE_Status 583get_calibration_status (int fd, void *buf, size_t *buf_size) 584{ 585 static u_char cmd[6]; 586 int status; 587 DBG (31, ">> get_calibration_status\n"); 588 589 memset (cmd, 0, sizeof (cmd)); 590 cmd[0] = 0xc3; 591 cmd[4] = *buf_size; 592 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 593 594 DBG (31, "<< get_calibration_status\n"); 595 return (status); 596} 597 598#if 0 599static SANE_Status 600get_switch_status (int fd, void *buf, size_t *buf_size) 601{ 602 static u_char cmd[6]; 603 int status; 604 DBG (31, ">> get_switch_status\n"); 605 606 memset (cmd, 0, sizeof (cmd)); 607 cmd[0] = 0xc4; 608 cmd[4] = 2; 609 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); 610 611 DBG (31, "<< get_switch_status\n"); 612 return (status); 613} 614 615static SANE_Status 616wait_ready(int fd) 617{ 618 SANE_Status status; 619 int retry = 0; 620 621 while ((status = test_unit_ready (fd)) != SANE_STATUS_GOOD) 622 { 623 DBG(5, "wait_ready failed (%d)\n", retry); 624 if (retry++ > 15) 625 return SANE_STATUS_IO_ERROR; 626 sleep(3); 627 } 628 return(status); 629} 630#endif 631 632/*************** modification for FB1200S ***************/ 633static SANE_Status 634cancel (int fd) 635{ 636 static u_char cmd[10]; 637 int status; 638 DBG (31, ">> cancel_FB1200S\n"); 639 640 memset (cmd, 0, sizeof (cmd)); 641 cmd[0] = 0xe4; 642 status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); 643 644 DBG (31, "<< cancel_FB1200S \n"); 645 return (status); 646} 647 648/**************************************************************************/ 649/* As long as we do not know how this scanner stores its density curves, 650 we do the gamma correction with a 8 <--> 12 bit translation table 651 stored in the CANON_Scanner structure. */ 652 653static SANE_Status 654get_density_curve_fs2710 (SANE_Handle handle, int component, u_char *buf, 655 size_t *buf_size) 656{ 657 CANON_Scanner *s = handle; 658 int i; 659 660 for (i = 0; i < 256; i++) 661 *buf++ = s->gamma_map[component][i << 4]; 662 *buf_size = 256; 663 return (SANE_STATUS_GOOD); 664} 665 666static SANE_Status 667set_density_curve_fs2710 (SANE_Handle handle, int component, u_char *buf) 668{ 669 CANON_Scanner *s = handle; 670 int i, j, hi, lo; 671 u_char *p; 672 673 for (i = 1, hi = *buf++, p = &s->gamma_map[component][0]; i <= 256; i++) 674 { 675 lo = hi; 676 hi = (i < 256) ? *buf++ : 2 * *(buf - 1) - *(buf - 2); 677 if (hi > 255) 678 hi = 255; 679 for (j = 0; j < 16; j++) /* do a linear interpolation */ 680 *p++ = (u_char) (lo + ((double) ((hi - lo) * j)) / 16.0 + 0.5); 681 } 682 return (SANE_STATUS_GOOD); 683} 684 685static SANE_Status 686set_parameters_fs2710 (SANE_Handle handle) 687{ 688 CANON_Scanner *s = handle; 689 int i, j, shadow[4], hilite[4]; 690 double x, b, c; 691 692 shadow[1] = s->ShadowR << 4; 693 shadow[2] = s->ShadowG << 4; 694 shadow[3] = s->ShadowB << 4; 695 hilite[1] = s->HiliteR << 4; 696 hilite[2] = s->HiliteG << 4; 697 hilite[3] = s->HiliteB << 4; 698 c = ((double) s->contrast) / 128.0; 699 b = ((double) (s->brightness - 128)) / 128.0; 700 701 for (i = 1; i < 4; i++) 702 { 703 for (j = 0; j < 4096; j++) 704 { 705 if (j <= shadow[i]) 706 s->gamma_map[i][j] = (u_char) ((s->brightness >= 128) ? 707 2 * s->brightness - 256 : 0); 708 else if (j < hilite[i]) 709 { 710 x = ((double) (j - shadow[i])) 711 / ((double) (hilite[i] - shadow[i])); 712 /* first do the contrast correction */ 713 x = (x <= 0.5) ? 0.5 * pow (2 * x, c) 714 : 1.0 - 0.5 * pow (2 * (1.0 - x), c); 715 x = pow (x, 0.5); /* default gamma correction */ 716 x += b; /* brightness correction */ 717 s->gamma_map[i][j] = (u_char) MAX (0, MIN (255, 718 (int) (255.0 * x))); 719 } 720 else 721 s->gamma_map[i][j] = (u_char) ((s->brightness >= 128) ? 722 255 : 2 * s->brightness); 723 } 724 } 725 726 return (SANE_STATUS_GOOD); 727} 728 729/**************************************************************************/ 730