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 uint32 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 buffer[8]; 232 if (!Sensor()) 233 return B_NO_INIT; 234 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4); 235 count++; // includes address 236 if (count > 5) 237 return EINVAL; 238 buffer[0] = (count << 4) | Sensor()->Use400kHz()?0x01:0 239 | Sensor()->UseRealIIC()?0x80:0; 240 buffer[1] = Sensor()->IICWriteAddress(); 241 buffer[2] = address; 242 memset(&buffer[3], 0, 5); 243 memcpy(&buffer[3], data, count); 244 buffer[7] = 0x14; /* absolutely no idea why V4L2 driver use that value */ 245 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8); 246 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err); 247 //PRINT((CH ": WriteReg: %s" CT, strerror(err))); 248 if (err < 0) return err; 249 err = WaitReadyIIC(); 250 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err); 251 //PRINT((CH ": Wait: %s" CT, strerror(err))); 252 if (err) return err; 253 err = GetStatusIIC(); 254 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err); 255 //PRINT((CH ": Status: %s" CT, strerror(err))); 256 if (err) return err; 257 //dprintf(ID "sonix_i2c_write_multi: succeeded\n"); 258 PRINT((CH ": success" CT)); 259 return B_OK; 260 } 261 262 // ----------------------------------------------------------------------------- 263 ssize_t 264 SonixCamDevice::ReadIIC(uint8 address, uint8 *data) 265 { 266 status_t err, lasterr = B_OK; 267 uint8 buffer[8]; 268 if (!Sensor()) 269 return B_NO_INIT; 270 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4); 271 buffer[0] = (1 << 4) | Sensor()->Use400kHz()?0x01:0 272 | Sensor()->UseRealIIC()?0x80:0; 273 buffer[1] = Sensor()->IICWriteAddress(); 274 buffer[2] = address; 275 buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */ 276 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8); 277 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err); 278 if (err) return err; 279 err = WaitReadyIIC(); 280 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err); 281 //if (err) return err; 282 283 284 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4); 285 buffer[0] = (1 << 4) | Sensor()->Use400kHz()?0x01:0 286 | 0x02 | Sensor()->UseRealIIC()?0x80:0; /* read 1 byte */ 287 buffer[1] = Sensor()->IICReadAddress();//IICWriteAddress 288 buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */ 289 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8); 290 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err); 291 if (err) return err; 292 err = WaitReadyIIC(); 293 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err); 294 if (err) return err; 295 296 err = ReadReg(SN9C102_I2C_DATA0, buffer, 5); 297 if (err) lasterr = err; 298 299 err = GetStatusIIC(); 300 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err); 301 if (err) return err; 302 //dprintf(ID "sonix_i2c_write_multi: succeeded\n"); 303 if (lasterr) return err; 304 305 /* we should get what we want in buffer[4] according to the V4L2 driver... 306 * probably because the 5 bytes are a bit shift register? 307 */ 308 *data = buffer[4]; 309 310 return 1; 311 } 312 313 // ----------------------------------------------------------------------------- 314 status_t 315 SonixCamDevice::SetVideoFrame(BRect frame) 316 { 317 uint16 x, y, width, height; 318 x = (uint16)frame.left; 319 y = (uint16)frame.top; 320 width = (uint16)(frame.right - frame.left + 1) / 16; 321 height = (uint16)(frame.bottom - frame.top + 1) / 16; 322 PRINT((CH "(%u, %u, %u, %u)" CT, x, y, width, height)); 323 324 WriteReg8(SN9C102_H_START, x); 325 WriteReg8(SN9C102_V_START, y); 326 WriteReg8(SN9C102_H_SIZE, width); 327 WriteReg8(SN9C102_V_SIZE, height); 328 if (Sensor()) { 329 Sensor()->SetVideoFrame(frame); 330 } 331 return CamDevice::SetVideoFrame(frame); 332 } 333 334 // ----------------------------------------------------------------------------- 335 status_t 336 SonixCamDevice::SetScale(float scale) 337 { 338 status_t err; 339 uint8 r; 340 int iscale = (int)scale; 341 342 PRINT((CH "(%u)" CT, iscale)); 343 err = ReadReg(SN9C102_SYNC_N_SCALE, &r, 1, true); 344 if (err < 0) 345 return err; 346 r &= ~0x30; 347 switch (iscale) { 348 case 1: 349 case 2: 350 case 4: 351 r |= ((iscale-1) << 4); 352 break; 353 default: 354 return EINVAL; 355 } 356 err = WriteReg8(SN9C102_SYNC_N_SCALE, r); 357 return err; 358 } 359 360 // ----------------------------------------------------------------------------- 361 status_t 362 SonixCamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue) 363 { 364 return B_OK; 365 } 366 367 // ----------------------------------------------------------------------------- 368 size_t 369 SonixCamDevice::MinRawFrameSize() 370 { 371 // if (fCompressionEnabled) { ... return ; } 372 BRect vf(VideoFrame()); 373 int w = vf.IntegerWidth()+1; 374 int h = vf.IntegerHeight()+1; 375 // 1 byte/pixel 376 return (size_t)(w*h); 377 } 378 379 // ----------------------------------------------------------------------------- 380 size_t 381 SonixCamDevice::MaxRawFrameSize() 382 { 383 // if (fCompressionEnabled) { ... return ; } 384 return MinRawFrameSize()+1024*0; // fixed size frame (uncompressed) 385 } 386 387 // ----------------------------------------------------------------------------- 388 bool 389 SonixCamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen) 390 { 391 // SOF come with an 00, 40, 80, C0 sequence, 392 // supposedly corresponding with an equal byte in the end tag 393 fFrameTagState = tag[7] & 0xC0; 394 PRINT((CH "(, %d) state %x" CT, taglen, fFrameTagState)); 395 396 // which seems to be the same as of the EOF tag 397 return true; 398 } 399 400 // ----------------------------------------------------------------------------- 401 bool 402 SonixCamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen) 403 { 404 //PRINT((CH "(, %d) %x == %x" CT, taglen, (tag[0] & 0xC0), fFrameTagState)); 405 // make sure the tag corresponds to the SOF we refer to 406 if ((tag[0] & 0xC0) != fFrameTagState) { 407 PRINT((CH ": discarded EOF %x != %x" CT, fFrameTagState, tag[0] & 0xC0)); 408 return false; 409 } 410 //PRINT((CH ": validated EOF %x, len %d" CT, fFrameTagState, datalen)); 411 return true; 412 } 413 414 // ----------------------------------------------------------------------------- 415 status_t 416 SonixCamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp /* = NULL */) 417 { 418 BBitmap *b; 419 CamFrame *f; 420 status_t err; 421 PRINT((CH "()" CT)); 422 err = fDeframer->WaitFrame(200000); 423 if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); } 424 if (err < B_OK) 425 return err; 426 err = fDeframer->GetFrame(&f, stamp); 427 if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); } 428 if (err < B_OK) 429 return err; 430 PRINT((CH ": VideoFrame = %fx%f,%fx%f" CT, VideoFrame().left, VideoFrame().top, VideoFrame().right, VideoFrame().bottom)); 431 432 long int w = (long)(VideoFrame().right - VideoFrame().left + 1); 433 long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1); 434 b = new BBitmap(VideoFrame().OffsetToSelf(0,0), 0, B_RGB32, w*4); 435 PRINT((CH ": Frame: %dx%d" CT, w, h)); 436 437 bayer2rgb24((unsigned char *)b->Bits(), (unsigned char *)f->Buffer(), w, h); 438 439 PRINT((CH ": got 1 frame (len %d)" CT, b->BitsLength())); 440 *bm = b; 441 return B_OK; 442 } 443 444 // ----------------------------------------------------------------------------- 445 status_t 446 SonixCamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp) 447 { 448 CamFrame *f; 449 status_t err; 450 PRINT((CH "()" CT)); 451 452 memset(buffer->Data(), 0, buffer->SizeAvailable()); 453 err = fDeframer->WaitFrame(2000000); 454 if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); } 455 if (err < B_OK) 456 return err; 457 458 err = fDeframer->GetFrame(&f, stamp); 459 if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); } 460 if (err < B_OK) 461 return err; 462 463 long int w = (long)(VideoFrame().right - VideoFrame().left + 1); 464 long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1); 465 PRINT((CH ": VideoFrame = %fx%f,%fx%f Frame: %dx%d" CT, VideoFrame().left, VideoFrame().top, VideoFrame().right, VideoFrame().bottom, w, h)); 466 467 if (buffer->SizeAvailable() >= (size_t)w*h*4) 468 bayer2rgb32le((unsigned char *)buffer->Data(), (unsigned char *)f->Buffer(), w, h); 469 470 delete f; 471 472 PRINT((CH ": available %d, required %d" CT, buffer->SizeAvailable(), w*h*4)); 473 if (buffer->SizeAvailable() < (size_t)w*h*4) 474 return E2BIG; 475 PRINT((CH ": got 1 frame (len %d)" CT, buffer->SizeUsed())); 476 return B_OK; 477 } 478 479 // ----------------------------------------------------------------------------- 480 void 481 /* DEBUG: dump the SN regs */ 482 SonixCamDevice::DumpRegs() 483 { 484 uint8 regs[SN9C102_REG_COUNT]; 485 status_t err; 486 487 //err = sonix_get_regs(dev, SN_ASIC_ID, regs, SN_REG_COUNT); 488 err = ReadReg(0, regs, SN9C102_REG_COUNT); 489 if (err < 0) 490 return; 491 printf("REG1: %02x %02x %02x %02x %02x %02x %02x %02x\n", 492 regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]); 493 printf(" 2: %02x %02x %02x %02x %02x %02x %02x %02x\n", 494 regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15]); 495 printf(" 3: %02x %02x %02x %02x %02x %02x %02x %02x\n", 496 regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23]); 497 printf(" 4: %02x %02x %02x %02x %02x %02x %02x %02x\n", 498 regs[24], regs[25], regs[26], regs[27], regs[28], regs[29], regs[30], regs[31]); 499 } 500 501 // ----------------------------------------------------------------------------- 502 status_t 503 SonixCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 504 uint16 index, uint16 length, void* data) 505 { 506 size_t ret; 507 if (length > 64) 508 return EINVAL; 509 if (!GetDevice()) 510 return ENODEV; 511 ret = GetDevice()->ControlTransfer( 512 USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT | dir, 513 request, value, index, length, data); 514 return ret; 515 } 516 517 // ----------------------------------------------------------------------------- 518 SonixCamDeviceAddon::SonixCamDeviceAddon(WebCamMediaAddOn* webcam) 519 : CamDeviceAddon(webcam) 520 { 521 SetSupportedDevices(kSupportedDevices); 522 } 523 524 // ----------------------------------------------------------------------------- 525 SonixCamDeviceAddon::~SonixCamDeviceAddon() 526 { 527 } 528 529 // ----------------------------------------------------------------------------- 530 const char * 531 SonixCamDeviceAddon::BrandName() 532 { 533 return "Sonix"; 534 } 535 536 // ----------------------------------------------------------------------------- 537 SonixCamDevice * 538 SonixCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 539 { 540 return new SonixCamDevice(*this, from); 541 } 542 543 extern "C" status_t 544 B_WEBCAM_MKINTFUNC(sonix) 545 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 546 { 547 *addon = new SonixCamDeviceAddon(webcam); 548 return B_OK; 549 } 550 551 // XXX: REMOVE ME 552 553 554 555 /* 556 * BAYER2RGB24 ROUTINE TAKEN FROM: 557 * 558 * Sonix SN9C101 based webcam basic I/F routines 559 * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp> 560 * 561 * Redistribution and use in source and binary forms, with or without 562 * modification, are permitted provided that the following conditions 563 * are met: 564 * 1. Redistributions of source code must retain the above copyright 565 * notice, this list of conditions and the following disclaimer. 566 * 2. Redistributions in binary form must reproduce the above copyright 567 * notice, this list of conditions and the following disclaimer in the 568 * documentation and/or other materials provided with the distribution. 569 * 570 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 571 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 572 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 573 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 574 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 575 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 576 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 577 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 578 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 579 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 580 * SUCH DAMAGE. 581 */ 582 583 void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT) 584 { 585 long int i; 586 unsigned char *rawpt, *scanpt; 587 long int size; 588 589 rawpt = src; 590 scanpt = dst; 591 size = WIDTH*HEIGHT; 592 593 for ( i = 0; i < size; i++ ) { 594 if ( (i/WIDTH) % 2 == 0 ) { 595 if ( (i % 2) == 0 ) { 596 /* B */ 597 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) { 598 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 599 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */ 600 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 601 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */ 602 *scanpt++ = *rawpt; /* B */ 603 } else { 604 /* first line or left column */ 605 *scanpt++ = *(rawpt+WIDTH+1); /* R */ 606 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */ 607 *scanpt++ = *rawpt; /* B */ 608 } 609 } else { 610 /* (B)G */ 611 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) { 612 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */ 613 *scanpt++ = *rawpt; /* G */ 614 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */ 615 } else { 616 /* first line or right column */ 617 *scanpt++ = *(rawpt+WIDTH); /* R */ 618 *scanpt++ = *rawpt; /* G */ 619 *scanpt++ = *(rawpt-1); /* B */ 620 } 621 } 622 } else { 623 if ( (i % 2) == 0 ) { 624 /* G(R) */ 625 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) { 626 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */ 627 *scanpt++ = *rawpt; /* G */ 628 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */ 629 } else { 630 /* bottom line or left column */ 631 *scanpt++ = *(rawpt+1); /* R */ 632 *scanpt++ = *rawpt; /* G */ 633 *scanpt++ = *(rawpt-WIDTH); /* B */ 634 } 635 } else { 636 /* R */ 637 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) { 638 *scanpt++ = *rawpt; /* R */ 639 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 640 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */ 641 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 642 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */ 643 } else { 644 /* bottom line or right column */ 645 *scanpt++ = *rawpt; /* R */ 646 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */ 647 *scanpt++ = *(rawpt-WIDTH-1); /* B */ 648 } 649 } 650 } 651 rawpt++; 652 } 653 654 } 655 656 /* modified bayer2rgb24 to output rgb-32 little endian (B_RGB32) 657 * François Revol 658 */ 659 660 void bayer2rgb32le(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT) 661 { 662 long int i; 663 unsigned char *rawpt, *scanpt; 664 long int size; 665 666 rawpt = src; 667 scanpt = dst; 668 size = WIDTH*HEIGHT; 669 670 for ( i = 0; i < size; i++ ) { 671 if ( (i/WIDTH) % 2 == 0 ) { 672 if ( (i % 2) == 0 ) { 673 /* B */ 674 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) { 675 *scanpt++ = *rawpt; /* B */ 676 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 677 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */ 678 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 679 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */ 680 } else { 681 /* first line or left column */ 682 *scanpt++ = *rawpt; /* B */ 683 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */ 684 *scanpt++ = *(rawpt+WIDTH+1); /* R */ 685 } 686 } else { 687 /* (B)G */ 688 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) { 689 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */ 690 *scanpt++ = *rawpt; /* G */ 691 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */ 692 } else { 693 /* first line or right column */ 694 *scanpt++ = *(rawpt-1); /* B */ 695 *scanpt++ = *rawpt; /* G */ 696 *scanpt++ = *(rawpt+WIDTH); /* R */ 697 } 698 } 699 } else { 700 if ( (i % 2) == 0 ) { 701 /* G(R) */ 702 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) { 703 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */ 704 *scanpt++ = *rawpt; /* G */ 705 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */ 706 } else { 707 /* bottom line or left column */ 708 *scanpt++ = *(rawpt-WIDTH); /* B */ 709 *scanpt++ = *rawpt; /* G */ 710 *scanpt++ = *(rawpt+1); /* R */ 711 } 712 } else { 713 /* R */ 714 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) { 715 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ 716 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */ 717 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+ 718 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */ 719 *scanpt++ = *rawpt; /* R */ 720 } else { 721 /* bottom line or right column */ 722 *scanpt++ = *(rawpt-WIDTH-1); /* B */ 723 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */ 724 *scanpt++ = *rawpt; /* R */ 725 } 726 } 727 } 728 rawpt++; 729 scanpt++; 730 } 731 732 } 733 734 735