G12Buffer* QTG12Loader::load(string name) { QString qtName = QString::fromStdString(name); QImage image(qtName); if (image.isNull()) return NULL; G12Buffer *result = new G12Buffer(image.height(), image.width(), false); /** * TODO: Make this faster using .bits() method. * So far don't want to mess with possible image formats * */ for (int i = 0; i < image.height(); i++) { for (int j = 0; j < image.width(); j++) { QRgb pixel = image.pixel(j,i); // Do conversion without qGray to possibly save 9-th bit uint16_t gray = (11 * qRed(pixel) + 16 * qGreen(pixel) + 5 * qBlue(pixel)) >> 1; result->element(i,j) = gray; } } return result; }
G12Buffer * BMPLoader::load(string name) { uint8_t *data = NULL; BMPHeader header; G12Buffer *toReturn = NULL; if (parseBMP(name, &header, &data) != 0) goto fail; toReturn = new G12Buffer(header.h, header.w); for (unsigned i = 0; i < header.h; i++) { uint8_t *src = &(data[header.lineLength * (header.h - i - 1)]); uint16_t *dest = &toReturn->element(i,0); for (unsigned j = 0; j < header.w; j++) { uint8_t b = src[0]; uint8_t g = src[1]; uint8_t r = src[2]; uint16_t gray = RGBColor(r,g,b).luma12(); *dest = gray; src += 3; dest++; } } fail: if (data) delete[] data; return toReturn; }
G12Buffer *BufferFactory::loadG16Bitmap(string name) { if (name.rfind(".pgm") != string::npos) { return PPMLoader().g16BufferCreateFromPPM(name); } G12Buffer *result = NULL; FILE *In = NULL; uint32_t h = 0; uint32_t w = 0; uint16_t d = 0; int read = 0; In = fopen(name.c_str(), "rb"); if (In == NULL) { goto exit; } read = (int)fread(&h, sizeof(uint32_t), 1, In); if (read != 1) { goto exit; } read = (int)fread(&w, sizeof(uint32_t), 1, In); if (read != 1) { goto exit; } if (h > 2000 || w > 2000) { goto exit; } result = new G12Buffer(h,w); for (uint32_t i = 0; i < h; ++i) { for (uint32_t j = 0; j < w; ++j) { read = (int)fread(&d, sizeof(uint16_t), 1, In); if (read != 1) { goto exit; } result->element(i,j) = d; } } exit: if (In != NULL) { fclose(In); } return result; }
void testG12Buffer (void) { /* Test case 1: Create and destroy buffer*/ G12Buffer *a = new G12Buffer(1,1); a->element(0,0) = 0; delete a; /* Test case 2: Test internal buffer destruction */ TestAbstractBufferClass::counter = 0; AbstractBuffer<TestAbstractBufferClass> *b = new AbstractBuffer<TestAbstractBufferClass> ( AbstractBuffer<TestAbstractBufferClass>::DATA_ALIGN_GRANULARITY, AbstractBuffer<TestAbstractBufferClass>::DATA_ALIGN_GRANULARITY ); delete b; ASSERT_TRUE(TestAbstractBufferClass::counter == 0, "Abstract buffer violates the C++ new/delete contract") /* Test case 3: Test internal buffer destruction */ TestAbstractBufferClass::counter = 0; AbstractBuffer<TestAbstractBufferClass> *d = new AbstractBuffer<TestAbstractBufferClass> ( AbstractBuffer<TestAbstractBufferClass>::DATA_ALIGN_GRANULARITY + 1, AbstractBuffer<TestAbstractBufferClass>::DATA_ALIGN_GRANULARITY + 1); delete d; ASSERT_TRUE(TestAbstractBufferClass::counter == 0, "Abstract buffer violates the C++ new/delete contract") /* Test case 4: Alignment */ const unsigned testLen = 100; G12Buffer **c = new G12Buffer *[testLen]; for (unsigned i = 0; i < testLen; i++) { c[i] = new G12Buffer(i+1,i+i); ASSERT_FALSE( ((uintptr_t)c[i]->data) & AbstractBuffer<TestAbstractBufferClass>::DATA_ALIGN_GRANULARITY, "Buffer alignment broken" ); uintptr_t line1 = (uintptr_t)&(c[i]->element(0,0)); uintptr_t line2 = (uintptr_t)&(c[i]->element(1,0)); ASSERT_FALSE( (line1 - line2) & AbstractBuffer<TestAbstractBufferClass>::DATA_ALIGN_GRANULARITY, "Stride alignment broken" ); } for (unsigned i = 0; i < testLen; i++) { delete c[i]; } delete[] c; }
G12Buffer *RGB24Buffer::toG12Buffer() { G12Buffer *toReturn = new G12Buffer(h,w, false); for (int i = 0; i < h; i++) { RGBColor *in = &this->element(i,0); uint16_t *out = &toReturn->element(i,0); int j = 0; #ifdef WITH_SSE_ const int inspan = SSEReader8BBBB_DDDD::BYTE_STEP / sizeof(RGBColor); const int outspan = 8; Int16x8 conR(11); Int16x8 conG(16); Int16x8 conB( 5); for (; j + inspan <= w; j += inspan) { FixedVector<Int16x8,4> r = SSEReader8BBBB_DDDD::read((uint32_t*)in); enum {B1, G1, R1}; Int16x8 result = (conR * r[R1] + conG * r[G1] + conB * r[B1]) >> 1; result.save(out); in += inspan; out += outspan; } #endif for (; j < w; j++) { uint16_t result = element(i,j).luma12(); if (result > G12Buffer::BUFFER_MAX_VALUE - 1) result = G12Buffer::BUFFER_MAX_VALUE - 1; toReturn->element(i, j) = result; } } return toReturn; }
static G12Buffer *CannyDetector::doFilter(G12Buffer *input, const CannyParameters &mCannyParameters) { if (input == NULL) { return NULL; } // non-maximum suppression DerivativeBuffer derBuf(input); G12Buffer *suppressedBuffer = derBuf.nonMaximalSuppression(); // double thresholding for (int i = 0; i < suppressedBuffer->h; i++) { for (int j = 0; j < suppressedBuffer->w; j++ ) { uint16_t pixel = suppressedBuffer->element(i,j); if (pixel < mCannyParameters.minimumThreshold()) { suppressedBuffer->element(i,j) = 0; continue; } if (pixel > mCannyParameters.maximumThreshold()) { suppressedBuffer->element(i,j) = CannyFilter::white; continue; } suppressedBuffer->element(i,j) = CannyFilter::gray; } } // edge tracking if (mCannyParameters.shouldEdgeDetect()) { for (int i = 0; i < suppressedBuffer->h; i++) { for (int j = 0; j < suppressedBuffer->w; j++ ) { if (suppressedBuffer->element(i,j) == CannyFilter::white) CannyFilter::recursiveEdgeProver(suppressedBuffer, i, j); } } for (int i = 0; i < suppressedBuffer->h; i++) for (int j = 0; j < suppressedBuffer->w; j++ ) if (suppressedBuffer->element(i,j) == CannyFilter::gray) suppressedBuffer->element(i,j) = 0; } return suppressedBuffer; }