1 #include "SonixCamDevice.h" 2 #include "CamDebug.h" 3 #include "CamSensor.h" 4 #include "CamBufferingDeframer.h" 5 #include "CamStreamingDeframer.h" 6 7 #include <usb/USBDevice.h> 8 #include <usb/USBConfiguration.h> 9 #include <usb/USBInterface.h> 10 11 #include <interface/Bitmap.h> 12 #include <media/Buffer.h> 13 14 const usb_named_support_descriptor kSupportedDevices[] = { 15 {{ 0, 0, 0, 0x0c45, 0x6005 }, "Sonix", "Sonix"}, 16 {{ 0, 0, 0, 0x0c45, 0x6009 }, "Trust", "spacec@m 120" }, 17 {{ 0, 0, 0, 0x0c45, 0x600D }, "Trust", "spacec@m 120" }, 18 {{ 0, 0, 0, 0, 0}, NULL, NULL } 19 }; 20 21 // 12 bytes actually 22 static const uint8 sof_mark_1[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00 }; 23 static const uint8 sof_mark_2[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01 }; 24 static const uint8 *sof_marks[] = { sof_mark_1, sof_mark_2 }; 25 26 static const uint8 eof_mark_1[] = { 0x00, 0x00, 0x00, 0x00 }; 27 static const uint8 eof_mark_2[] = { 0x40, 0x00, 0x00, 0x00 }; 28 static const uint8 eof_mark_3[] = { 0x80, 0x00, 0x00, 0x00 }; 29 static const uint8 eof_mark_4[] = { 0xc0, 0x00, 0x00, 0x00 }; 30 static const uint8 *eof_marks[] = { eof_mark_1, eof_mark_2, eof_mark_3, eof_mark_4 }; 31 32 void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT); 33 void bayer2rgb32le(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT); 34 35 // ----------------------------------------------------------------------------- 36 SonixCamDevice::SonixCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) 37 :CamDevice(_addon, _device) 38 { 39 uchar data[8]; /* store bytes returned from sonix commands */ 40 status_t err; 41 fFrameTagState = 0; 42 43 memset(fCachedRegs, 0, SN9C102_REG_COUNT); 44 fChipVersion = 2; 45 if ((GetDevice()->ProductID() & ~0x3F) == 0x6080) { 46 fChipVersion = 3; // says V4L2 47 } 48 switch (GetDevice()->ProductID()) { 49 case 0x6001: 50 case 0x6005: 51 case 0x60ab: 52 fSensor = CreateSensor("tas5110c1b"); 53 break; 54 default: 55 break; 56 } 57 58 // fDeframer = new CamBufferingDeframer(this); 59 fDeframer = new CamStreamingDeframer(this); 60 fDeframer->RegisterSOFTags(sof_marks, 2, sizeof(sof_mark_1), 12); 61 fDeframer->RegisterEOFTags(eof_marks, 4, sizeof(eof_mark_1), sizeof(eof_mark_1)); 62 SetDataInput(fDeframer); 63 64 /* init hw */ 65 66 const BUSBConfiguration *config = GetDevice()->ConfigurationAt(0); 67 if (config) { 68 const BUSBInterface *inter = config->InterfaceAt(0); 69 int i; 70 71 GetDevice()->SetConfiguration(config); 72 73 for (i = 0; inter && (i < inter->CountEndpoints()); i++) { 74 const BUSBEndpoint *e = inter->EndpointAt(i); 75 if (e && e->IsBulk() && e->IsInput()) { 76 fBulkIn = e; 77 PRINT((CH ": Using inter[0].endpoint[%d]; maxpktsz: %d" CT, i, e->MaxPacketSize())); 78 break; 79 } 80 } 81 82 } 83 84 /* sanity check */ 85 err = ReadReg(SN9C102_ASIC_ID, data); 86 if (err < 0 || data[0] != 0x10) { 87 PRINT((CH ": BAD ASIC signature! (%u != %u)" CT, data[0], 0x10)); 88 return; 89 } 90 91 92 if (Sensor()) { 93 PRINT((CH ": CamSensor: %s" CT, Sensor()->Name())); 94 fInitStatus = Sensor()->Setup(); 95 // SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1)); 96 // SetVideoFrame(BRect(0, 0, 320-1, 240-1)); 97 } 98 //SetScale(1); 99 } 100 101 // ----------------------------------------------------------------------------- 102 SonixCamDevice::~SonixCamDevice() 103 { 104 if (Sensor()) 105 delete fSensor; 106 fSensor = NULL; 107 } 108 109 // ----------------------------------------------------------------------------- 110 bool 111 SonixCamDevice::SupportsBulk() 112 { 113 return true; 114 } 115 116 // ----------------------------------------------------------------------------- 117 bool 118 SonixCamDevice::SupportsIsochronous() 119 { 120 return true; 121 } 122 123 // ----------------------------------------------------------------------------- 124 status_t 125 SonixCamDevice::StartTransfer() 126 { 127 status_t err; 128 uint8 r; 129 130 SetScale(1); 131 if (Sensor()) 132 SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1)); 133 134 SetVideoFrame(BRect(0, 0, 320-1, 240-1)); 135 136 DumpRegs(); 137 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true); 138 if (err < 0) 139 return err; 140 r |= 0x04; 141 err = WriteReg8(SN9C102_CHIP_CTRL, r); 142 if (err < 0) 143 return err; 144 return CamDevice::StartTransfer(); 145 } 146 147 // ----------------------------------------------------------------------------- 148 status_t 149 SonixCamDevice::StopTransfer() 150 { 151 status_t err; 152 uint8 r; 153 154 DumpRegs(); 155 err = CamDevice::StopTransfer(); 156 // if (err < 0) 157 // return err; 158 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true); 159 if (err < 0) 160 return err; 161 r &= ~0x04; 162 err = WriteReg8(SN9C102_CHIP_CTRL, r); 163 if (err < 0) 164 return err; 165 return err; 166 } 167 168 // ----------------------------------------------------------------------------- 169 ssize_t 170 SonixCamDevice::WriteReg(uint16 address, uint8 *data, size_t count) 171 { 172 PRINT((CH "(%u, @%p, %u)" CT, address, data, count)); 173 if (address + count > SN9C102_REG_COUNT) { 174 PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count)); 175 return EINVAL; 176 } 177 memcpy(&fCachedRegs[address], data, count); 178 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x08, address, 0, count, data); 179 } 180 181 // ----------------------------------------------------------------------------- 182 ssize_t 183 SonixCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached) 184 { 185 PRINT((CH "(%u, @%p, %u, %d)" CT, address, data, count, cached)); 186 if (address + count > SN9C102_REG_COUNT) { 187 PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count)); 188 return EINVAL; 189 } 190 if (cached) { 191 memcpy(data, &fCachedRegs[address], count); 192 return count; 193 } 194 return SendCommand(USB_REQTYPE_DEVICE_IN, 0x00, address, 0, count, data); 195 } 196 197 // ----------------------------------------------------------------------------- 198 status_t 199 SonixCamDevice::GetStatusIIC() 200 { 201 status_t err; 202 uint8 status = 0; 203 err = ReadReg(SN9C102_I2C_SETUP, &status); 204 //dprintf(ID "i2c_status: error 0x%08lx, status = %02x\n", err, status); 205 if (err < 0) 206 return err; 207 return (status&0x08)?EIO:0; 208 } 209 210 // ----------------------------------------------------------------------------- 211 status_t 212 SonixCamDevice::WaitReadyIIC() 213 { 214 status_t err; 215 uint8 status = 0; 216 int tries = 5; 217 if (!Sensor()) 218 return B_NO_INIT; 219 while (tries--) { 220 err = ReadReg(SN9C102_I2C_SETUP, &status); 221 //dprintf(ID "i2c_wait_ready: error 0x%08lx, status = %02x\n", err, status); 222 if (err < 0) return err; 223 if (status & 0x04) return B_OK; 224 //XXX:FIXME:spin((1+5+11*dev->sensor->use_400kHz)*8); 225 snooze((1+5+11*Sensor()->Use400kHz())*8); 226 } 227 return EBUSY; 228 } 229 230 // ----------------------------------------------------------------------------- 231 ssize_t 232 SonixCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 233 { 234 status_t err; 235 uint8 status; 236 uint8 buffer[8]; 237 if (!Sensor()) 238 return B_NO_INIT; 239 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4); 240 count++; // includes address 241 if (count > 5) 242 return EINVAL; 243 buffer[0] = (count << 4) | Sensor()->Use400kHz()?0x01:0 244 | Sensor()->UseRealIIC()?0x80:0; 245 buffer[1] = Sensor()->IICWriteAddress(); 246 buffer[2] = address; 247 memset(&buffer[3], 0, 5); 248 memcpy(&buffer[3], data, count); 249 buffer[7] = 0x14; /* absolutely no idea why V4L2 driver use that value */ 250 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8); 251 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err); 252 //PRINT((CH ": WriteReg: %s" CT, strerror(err))); 253 if (err < 0) return err; 254 err = WaitReadyIIC(); 255 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err); 256 //PRINT((CH ": Wait: %s" CT, strerror(err))); 257 if (err) return err; 258 err = GetStatusIIC(); 259 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err); 260 //PRINT((CH ": Status: %s" CT, strerror(err))); 261 if (err) return err; 262 //dprintf(ID "sonix_i2c_write_multi: succeeded\n"); 263 PRINT((CH ": success" CT)); 264 return B_OK; 265 } 266 267 // ----------------------------------------------------------------------------- 268 ssize_t 269 SonixCamDevice::ReadIIC(uint8 address, uint8 *data) 270 { 271 status_t err, lasterr = B_OK; 272 uint8 status; 273 uint8 buffer[8]; 274 if (!Sensor()) 275 return B_NO_INIT; 276 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4); 277 buffer[0] = (1 << 4) | Sensor()->Use400kHz()?0x01:0 278 | Sensor()->UseRealIIC()?0x80:0; 279 buffer[1] = Sensor()->IICWriteAddress(); 280 buffer[2] = address; 281 buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */ 282 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8); 283 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err); 284 if (err) return err; 285 err = WaitReadyIIC(); 286 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err); 287 //if (err) return err; 288 289 290 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4); 291 buffer[0] = (1 << 4) | Sensor()->Use400kHz()?0x01:0 292 | 0x02 | Sensor()->UseRealIIC()?0x80:0; /* read 1 byte */ 293 buffer[1] = Sensor()->IICReadAddress();//IICWriteAddress 294 buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */ 295 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8); 296 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err); 297 if (err) return err; 298 err = WaitReadyIIC(); 299 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err); 300 if (err) return err; 301 302 err = ReadReg(SN9C102_I2C_DATA0, buffer, 5); 303 if (err) lasterr = err; 304 305 err = GetStatusIIC(); 306 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err); 307 if (err) return err; 308 //dprintf(ID "sonix_i2c_write_multi: succeeded\n"); 309 if (lasterr) return err; 310 311 /* we should get what we want in buffer[4] according to the V4L2 driver... 312 * probably because the 5 bytes are a bit shift register? 313 */ 314 *data = buffer[4]; 315 316 return 1; 317 } 318 319 // ----------------------------------------------------------------------------- 320 status_t 321 SonixCamDevice::SetVideoFrame(BRect frame) 322 { 323 uint16 x, y, width, height; 324 x = (uint16)frame.left; 325 y = (uint16)frame.top; 326 width = (uint16)(frame.right - frame.left + 1) / 16; 327 height = (uint16)(frame.bottom - frame.top + 1) / 16; 328 PRINT((CH "(%u, %u, %u, %u)" CT, x, y, width, height)); 329 330 WriteReg8(SN9C102_H_START, x); 331 WriteReg8(SN9C102_V_START, y); 332 WriteReg8(SN9C102_H_SIZE, width); 333 WriteReg8(SN9C102_V_SIZE, height); 334 if (Sensor()) { 335 Sensor()->SetVideoFrame(frame); 336 } 337 return CamDevice::SetVideoFrame(frame); 338 } 339 340 // ----------------------------------------------------------------------------- 341 status_t 342 SonixCamDevice::SetScale(float scale) 343 { 344 status_t err; 345 uint8 r; 346 int iscale = (int)scale; 347 348 PRINT((CH "(%u)" CT, iscale)); 349 err = ReadReg(SN9C102_SYNC_N_SCALE, &r, 1, true); 350 if (err < 0) 351 return err; 352 r &= ~0x30; 353 switch (iscale) { 354 case 1: 355 case 2: 356 case 4: 357 r |= ((iscale-1) << 4); 358 break; 359 default: 360 return EINVAL; 361 } 362 err = WriteReg8(SN9C102_SYNC_N_SCALE, r); 363 return err; 364 } 365 366 // ----------------------------------------------------------------------------- 367 status_t 368 SonixCamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue) 369 { 370 return B_OK; 371 } 372 373 // ----------------------------------------------------------------------------- 374 size_t 375 SonixCamDevice::MinRawFrameSize() 376 { 377 // if (fCompressionEnabled) { ... return ; } 378 BRect vf(VideoFrame()); 379 int w = vf.IntegerWidth()+1; 380 int h = vf.IntegerHeight()+1; 381 // 1 byte/pixel 382 return (size_t)(w*h); 383 } 384 385 // ----------------------------------------------------------------------------- 386 size_t 387 SonixCamDevice::MaxRawFrameSize() 388 { 389 // if (fCompressionEnabled) { ... return ; } 390 return MinRawFrameSize()+1024*0; // fixed size frame (uncompressed) 391 } 392 393 // ----------------------------------------------------------------------------- 394 bool 395 SonixCamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen) 396 { 397 // SOF come with an 00, 40, 80, C0 sequence, 398 // supposedly corresponding with an equal byte in the end tag 399 fFrameTagState = tag[7] & 0xC0; 400 PRINT((CH "(, %d) state %x" CT, taglen, fFrameTagState)); 401 402 // which seems to be the same as of the EOF tag 403 return true; 404 } 405 406 // ----------------------------------------------------------------------------- 407 bool 408 SonixCamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen) 409 { 410 //PRINT((CH "(, %d) %x == %x" CT, taglen, (tag[0] & 0xC0), fFrameTagState)); 411 // make sure the tag corresponds to the SOF we refer to 412 if ((tag[0] & 0xC0) != fFrameTagState) { 413 PRINT((CH ": discarded EOF %x != %x" CT, fFrameTagState, tag[0] & 0xC0)); 414 return false; 415 } 416 //PRINT((CH ": validated EOF %x, len %d" CT, fFrameTagState, datalen)); 417 return true; 418 } 419 420 // ----------------------------------------------------------------------------- 421 status_t 422 SonixCamDevice::GetFrameBitmap(BBitmap **bm) 423 { 424 BBitmap *b; 425 CamFrame *f; 426 bigtime_t stamp; 427 status_t err; 428 PRINT((CH "()" CT)); 429 err = fDeframer->WaitFrame(200000); 430 if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); } 431 if (err < B_OK) 432 return err; 433 err = fDeframer->GetFrame(&f, &stamp); 434 if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); } 435 if (err < B_OK) 436 return err; 437 PRINT((CH ": VideoFrame = %fx%f,%fx%f" CT, VideoFrame().left, VideoFrame().top, VideoFrame().right, VideoFrame().bottom)); 438 439 long int w = VideoFrame().right - VideoFrame().left + 1; 440 long int h = VideoFrame().bottom - VideoFrame().top + 1; 441 b = new BBitmap(VideoFrame().OffsetToSelf(0,0), 0, B_RGB32, w*4); 442 PRINT((CH ": Frame: %dx%d" CT, w, h)); 443 444 bayer2rgb24((unsigned char *)b->Bits(), (unsigned char *)f->Buffer(), w, h); 445 446 PRINT((CH ": got 1 frame (len %d)" CT, b->BitsLength())); 447 *bm = b; 448 return B_OK; 449 } 450 451 // ----------------------------------------------------------------------------- 452 status_t 453 SonixCamDevice::FillFrameBuffer(BBuffer *buffer) 454 { 455 CamFrame *f; 456 bigtime_t stamp; 457 status_t err; 458 PRINT((CH "()" CT)); 459 460 memset(buffer->Data(), 0, buffer->SizeAvailable()); 461 err = fDeframer->WaitFrame(2000000); 462 if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); } 463 if (err < B_OK) 464 return err; 465 466 err = fDeframer->GetFrame(&f, &stamp); 467 if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); } 468 if (err < B_OK) 469 return err; 470 471 long int w = VideoFrame().right - VideoFrame().left + 1; 472 long int h = VideoFrame().bottom - VideoFrame().top + 1; 473 PRINT((CH ": VideoFrame = %fx%f,%fx%f Frame: %dx%d" CT, VideoFrame().left, VideoFrame().top, VideoFrame().right, VideoFrame().bottom, w, h)); 474 475 if (buffer->SizeAvailable() >= w*h*4) 476 bayer2rgb32le((unsigned char *)buffer->Data(), (unsigned char *)f->Buffer(), w, h); 477 478 delete f; 479 480 PRINT((CH ": available %d, required %d" CT, buffer->SizeAvailable(), w*h*4)); 481 if (buffer->SizeAvailable() < w*h*4) 482 return E2BIG; 483 PRINT((CH ": got 1 frame (len %d)" CT, buffer->SizeUsed())); 484 return B_OK; 485 } 486 487 // ----------------------------------------------------------------------------- 488 void 489 /* DEBUG: dump the SN regs */ 490 SonixCamDevice::DumpRegs() 491 { 492 uint8 regs[SN9C102_REG_COUNT]; 493 status_t err; 494 495 //err = sonix_get_regs(dev, SN_ASIC_ID, regs, SN_REG_COUNT); 496 err = ReadReg(0, regs, SN9C102_REG_COUNT); 497 if (err < 0) 498 return; 499 printf("REG1: %02x %02x %02x %02x %02x %02x %02x %02x\n", 500 regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]); 501 printf(" 2: %02x %02x %02x %02x %02x %02x %02x %02x\n", 502 regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15]); 503 printf(" 3: %02x %02x %02x %02x %02x %02x %02x %02x\n", 504 regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23]); 505 printf(" 4: %02x %02x %02x %02x %02x %02x %02x %02x\n", 506 regs[24], regs[25], regs[26], regs[27], regs[28], regs[29], regs[30], regs[31]); 507 } 508 509 // ----------------------------------------------------------------------------- 510 status_t 511 SonixCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 512 uint16 index, uint16 length, void* data) 513 { 514 size_t ret; 515 if (length > 64) 516 return EINVAL; 517 if (!GetDevice()) 518 return ENODEV; 519 ret = GetDevice()->ControlTransfer( 520 USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT | dir, 521 request, value, index, length, data); 522 return ret; 523 } 524 525 // ----------------------------------------------------------------------------- 526 SonixCamDeviceAddon::SonixCamDeviceAddon(WebCamMediaAddOn* webcam) 527 : CamDeviceAddon(webcam) 528 { 529 SetSupportedDevices(kSupportedDevices); 530 } 531 532 // ----------------------------------------------------------------------------- 533 SonixCamDeviceAddon::~SonixCamDeviceAddon() 534 { 535 } 536 537 // ----------------------------------------------------------------------------- 538 const char * 539 SonixCamDeviceAddon::BrandName() 540 { 541 return "Sonix"; 542 } 543 544 // ----------------------------------------------------------------------------- 545 SonixCamDevice * 546 SonixCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 547 { 548 return new SonixCamDevice(*this, from); 549 } 550 551 extern "C" status_t 552 B_WEBCAM_MKINTFUNC(sonix) 553 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 554 { 555 *addon = new SonixCamDeviceAddon(webcam); 556 return B_OK; 557 } 558 559 // XXX: REMOVE ME 560 561 562 563 /* 564 * BAYER2RGB24 ROUTINE TAKEN FROM: 565 * 566 * Sonix SN9C101 based webcam basic I/F routines 567 * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp> 568 * 569 * Redistribution and use in source and binary forms, with or without 570 * modification, are permitted provided that the following conditions 571 * are met: 572 * 1. Redistributions of source code must retain the above copyright 573 * notice, this list of conditions and the following disclaimer. 574 * 2. Redistributions in binary form must reproduce the above copyright 575 * notice, this list of conditions and the following disclaimer in the 576 * documentation and/or other materials provided with the distribution. 577 * 578 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 579 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 580 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 581 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 582 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 583 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 584 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 585 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 586 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 587 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 588 * SUCH DAMAGE. 589 */ 590 591 void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT) 592 { 593 long int i; 594 unsigned char *rawpt, *scanpt; 595 long int size; 596 597 rawpt = src; 598 scanpt = dst; 599 size = WIDTH*HEIGHT; 600 601 for ( i = 0; i < size; i++ ) { 602 if ( (i/WIDTH) % 2 == 0 ) { 603 if ( (i % 2) == 0 ) { 604 /* B */ 605 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) { 606 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 607 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */ 608 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 609 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */ 610 *scanpt++ = *rawpt; /* B */ 611 } else { 612 /* first line or left column */ 613 *scanpt++ = *(rawpt+WIDTH+1); /* R */ 614 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */ 615 *scanpt++ = *rawpt; /* B */ 616 } 617 } else { 618 /* (B)G */ 619 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) { 620 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */ 621 *scanpt++ = *rawpt; /* G */ 622 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */ 623 } else { 624 /* first line or right column */ 625 *scanpt++ = *(rawpt+WIDTH); /* R */ 626 *scanpt++ = *rawpt; /* G */ 627 *scanpt++ = *(rawpt-1); /* B */ 628 } 629 } 630 } else { 631 if ( (i % 2) == 0 ) { 632 /* G(R) */ 633 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) { 634 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */ 635 *scanpt++ = *rawpt; /* G */ 636 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */ 637 } else { 638 /* bottom line or left column */ 639 *scanpt++ = *(rawpt+1); /* R */ 640 *scanpt++ = *rawpt; /* G */ 641 *scanpt++ = *(rawpt-WIDTH); /* B */ 642 } 643 } else { 644 /* R */ 645 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) { 646 *scanpt++ = *rawpt; /* R */ 647 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 648 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */ 649 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 650 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */ 651 } else { 652 /* bottom line or right column */ 653 *scanpt++ = *rawpt; /* R */ 654 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */ 655 *scanpt++ = *(rawpt-WIDTH-1); /* B */ 656 } 657 } 658 } 659 rawpt++; 660 } 661 662 } 663 664 /* modified bayer2rgb24 to output rgb-32 little endian (B_RGB32) 665 * François Revol 666 */ 667 668 void bayer2rgb32le(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT) 669 { 670 long int i; 671 unsigned char *rawpt, *scanpt; 672 long int size; 673 674 rawpt = src; 675 scanpt = dst; 676 size = WIDTH*HEIGHT; 677 678 for ( i = 0; i < size; i++ ) { 679 if ( (i/WIDTH) % 2 == 0 ) { 680 if ( (i % 2) == 0 ) { 681 /* B */ 682 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) { 683 *scanpt++ = *rawpt; /* B */ 684 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 685 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */ 686 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 687 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */ 688 } else { 689 /* first line or left column */ 690 *scanpt++ = *rawpt; /* B */ 691 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */ 692 *scanpt++ = *(rawpt+WIDTH+1); /* R */ 693 } 694 } else { 695 /* (B)G */ 696 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) { 697 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */ 698 *scanpt++ = *rawpt; /* G */ 699 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */ 700 } else { 701 /* first line or right column */ 702 *scanpt++ = *(rawpt-1); /* B */ 703 *scanpt++ = *rawpt; /* G */ 704 *scanpt++ = *(rawpt+WIDTH); /* R */ 705 } 706 } 707 } else { 708 if ( (i % 2) == 0 ) { 709 /* G(R) */ 710 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) { 711 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */ 712 *scanpt++ = *rawpt; /* G */ 713 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */ 714 } else { 715 /* bottom line or left column */ 716 *scanpt++ = *(rawpt-WIDTH); /* B */ 717 *scanpt++ = *rawpt; /* G */ 718 *scanpt++ = *(rawpt+1); /* R */ 719 } 720 } else { 721 /* R */ 722 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) { 723 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 724 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */ 725 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 726 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */ 727 *scanpt++ = *rawpt; /* R */ 728 } else { 729 /* bottom line or right column */ 730 *scanpt++ = *(rawpt-WIDTH-1); /* B */ 731 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */ 732 *scanpt++ = *rawpt; /* R */ 733 } 734 } 735 } 736 rawpt++; 737 scanpt++; 738 } 739 740 } 741 742 743