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