void scan_image (const char *filename) { scanner.reset(); // normally scanner would reset associated decoder, // but this debug program connects them manually // (to make intermediate state more readily available) // so decoder must also be reset manually decoder.reset(); Magick::Image image; image.read(filename); string file = image.baseFilename(); size_t baseidx = file.rfind('/'); if(baseidx != string::npos) file = file.substr(baseidx + 1, file.length() - baseidx - 1); ofstream svg((file + ".svg").c_str()); unsigned inwidth = image.columns(); unsigned flush1 = inwidth / 32; unsigned flush0 = 2; unsigned width = inwidth + flush1 + flush0; unsigned height = image.rows(); unsigned midy = (height + 1) / 2 + 2; image.crop(Magick::Geometry(inwidth, 1, 0, midy)); image.size(Magick::Geometry(width, 1, 0, 0)); svg << "<?xml version='1.0'?>" << endl << "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN'" << " 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>" << endl << "<svg version='1.1' id='top'" << " width='10in' height='6in' preserveAspectRatio='xMinYMid slice'" << " overflow='visible' viewBox='0,0 " << width * 2 << ",384'" << " xmlns:xlink='http://www.w3.org/1999/xlink'" << " xmlns='http://www.w3.org/2000/svg'>" << endl << "<defs><style type='text/css'><![CDATA[" << endl << " * { stroke-linejoin: round; stroke-linecap: round;" << " stroke-width: .1; text-anchor: middle;" << " image-rendering: optimizeSpeed;" << " font-size: 6; font-weight: bold }" << endl << " path { fill: none }" << endl << " #zero { stroke: #00f }" << endl << " #edges { stroke: #f00 }" << endl << " #cur-edge { stroke: #f44 }" << endl << " #raw { stroke: orange }" << endl << " #y0 { stroke: yellow }" << endl << " #y1 { stroke: #0c0 }" << endl << " #y2 { stroke: #0aa }" << endl << " .y1thr { stroke: #f0f }" << endl << " rect.bar { fill: black }" << endl << " text.bar { fill: white }" << endl << " rect.space { fill: white }" << endl << " text.space { fill: black }" << endl << " text.data { fill: #44f; font-size: 16 }" << endl << "]]></style></defs>" << endl << "<image width='" << width * 2 << "' height='384'" << " preserveAspectRatio='none'" << " xlink:href='" << file << ".png'/>" << endl << "<g transform='translate(1,384) scale(2,-.5)'>" << endl; // brute force unsigned raw[width]; { // extract scan from image pixels image.modifyImage(); Magick::Pixels view(image); Magick::PixelPacket *pxp = view.get(0, 0, width, 1); Magick::ColorYUV y; double max = 0; svg << "<path id='raw' d='M"; unsigned i; for(i = 0; i < inwidth; i++, pxp++) { y = *pxp; if(max < y.y()) max = y.y(); raw[i] = (unsigned)(y.y() * 0x100); svg << ((i != 1) ? " " : " L ") << i << "," << raw[i]; y.u(0); y.v(0); *pxp = y; } y.y(max); /* flush scan FIXME? */ for(; i < inwidth + flush1; i++) { raw[i] = (unsigned)(y.y() * 0x100); svg << " " << i << "," << raw[i]; *pxp++ = y; } y.y(0); for(; i < width; i++) { raw[i] = (unsigned)(y.y() * 0x100); svg << " " << i << "," << raw[i]; *pxp++ = y; } view.sync(); svg << "'/>" << endl << "</g>" << endl; } image.depth(8); image.write(file + ".png"); // process scan and capture calculated values unsigned cur_edge[width], last_edge[width]; int y0[width], y1[width], y2[width], y1_thr[width]; svg << "<g transform='translate(-3)'>" << endl; for(unsigned i = 0; i < width; i++) { int edge = scanner.scan_y(raw[i]); unsigned x; zbar_scanner_get_state(scanner.get_c_scanner(), &x, &cur_edge[i], &last_edge[i], &y0[i], &y1[i], &y2[i], &y1_thr[i]); #ifdef DEBUG_SCANNER cerr << endl; #endif cur_edge[i] += i - x; if(edge) { last_edge[i] += i - x; unsigned w = scanner.get_width(); svg << "<rect x='" << (2. * (last_edge[i] - w) / ZBAR_FRAC) << "' width='" << (w * 2. / ZBAR_FRAC) << "' height='32' class='" << (scanner.get_color() ? "space" : "bar") << "'/>" << endl << "<text transform='translate(" << ((2. * last_edge[i] - w) / ZBAR_FRAC) - 3 << ",16) rotate(90)' class='" << (scanner.get_color() ? "space" : "bar") << "'>" << endl << w << "</text>" << endl; zbar_symbol_type_t sym = decoder.decode_width(w); if(sym > ZBAR_PARTIAL) { svg << "<text transform='translate(" << (2. * (last_edge[i] + w) / ZBAR_FRAC) << ",208) rotate(90)' class='data'>" << decoder.get_data_string() << "</text>" << endl; } } else last_edge[i] = 0; } svg << "</g>" << endl << "<g transform='translate(-3,384) scale(2,-.5)'>" << endl << "<path id='edges' d='"; for(unsigned i = 0; i < width; i++) if(last_edge[i]) svg << " M" << ((double)last_edge[i] / ZBAR_FRAC) << ",0v768"; svg << "'/>" << endl << "</g>" << endl << "<g transform='translate(-1,384) scale(2,-.5)'>" << endl << "<path id='y0' d='M"; for(unsigned i = 0; i < width; i++) svg << ((i != 1) ? " " : " L ") << i << "," << y0[i]; svg << "'/>" << endl << "</g>" << endl; svg << "<g transform='translate(-1,128) scale(2,-1)'>" << endl << "<line id='zero' x2='" << width << "'/>" << endl << "<path id='cur-edge' d='"; for(unsigned i = 1; i < width - 1; i++) if(!last_edge[i + 1] && (cur_edge[i] != cur_edge[i + 1])) svg << " M" << ((double)cur_edge[i] / ZBAR_FRAC) - 1 << ",-32v64"; svg << "'/>" << endl << "<path class='y1thr' d='M"; for(unsigned i = 0; i < width; i++) svg << ((i != 1) ? " " : " L ") << i << "," << y1_thr[i]; svg << "'/>" << endl << "<path class='y1thr' d='M"; for(unsigned i = 0; i < width; i++) svg << ((i != 1) ? " " : " L ") << i << "," << -y1_thr[i]; svg << "'/>" << endl << "<path id='y1' d='M"; for(unsigned i = 0; i < width; i++) svg << ((i != 1) ? " " : " L ") << (i - 0.5) << "," << y1[i]; svg << "'/>" << endl << "<path id='y2' d='M"; for(unsigned i = 0; i < width; i++) svg << ((i != 1) ? " " : " L ") << i << "," << y2[i]; svg << "'/>" << endl << "</g>" << endl; svg << "</svg>" << endl; }
void Magick::composeImage::operator()( Magick::Image &image_ ) const { image_.compose( _compose ); }
void Magick::densityImage::operator()( Magick::Image &image_ ) const { image_.density( _geomery ); }
void Magick::chromaWhitePointImage::operator()( Magick::Image &image_ ) const { image_.chromaWhitePoint( _x, _y ); }
void Magick::colorFuzzImage::operator()( Magick::Image &image_ ) const { image_.colorFuzz( _fuzz ); }
void Magick::backgroundColorImage::operator()( Magick::Image &image_ ) const { image_.backgroundColor( _color ); }
void Magick::boxColorImage::operator()( Magick::Image &image_ ) const { image_.boxColor( _boxColor ); }
void Magick::thresholdImage::operator()( Magick::Image &image_ ) const { image_.threshold( _threshold ); }
void Magick::transparentImage::operator()( Magick::Image &image_ ) const { image_.transparent( _color ); }
void Magick::textureImage::operator()( Magick::Image &image_ ) const { image_.texture( _texture ); }
void Magick::annotateImage::operator()( Magick::Image &image_ ) const { image_.annotate( _text, _geometry, _gravity, _degrees ); }
void Magick::swirlImage::operator()( Magick::Image &image_ ) const { image_.swirl( _degrees ); }
void CIMDisplayView::DoDisplayImage( Image &inImage, CDC* pDC ) { // make sure we're getting a valid image! if (!inImage.isValid()) { return; } // if the view is dirty, dispose the old offscreen! if ( mViewDirty == true ) { delete mOffscreenDC; mOffscreenDC = NULL; } // make sure we have a valid destination DC if (pDC != NULL) { // if we don't already have a ready offscreen, then prepare one if ( !mOffscreenDC ) { // // Set up the Windows bitmap header // BITMAPINFOHEADER bmi; bmi.biSize = sizeof(BITMAPINFOHEADER); // Size of structure bmi.biWidth = inImage.columns(); // Bitmaps width in pixels bmi.biHeight = (-1)*inImage.rows(); // Bitmaps height n pixels bmi.biPlanes = 1; // Number of planes in the image bmi.biBitCount = 32; // The number of bits per pixel bmi.biCompression = BI_RGB; // The type of compression used bmi.biSizeImage = 0; // The size of the image in bytes bmi.biXPelsPerMeter = 0; // Horizontal resolution bmi.biYPelsPerMeter = 0; // Veritical resolution bmi.biClrUsed = 0; // Number of colors actually used bmi.biClrImportant = 0; // Colors most important mBMI = bmi; // keep it for clipboard use... RGBQUAD *prgbaDIB = 0; HBITMAP hBitmap = CreateDIBSection ( pDC->m_hDC, // handle to device context (BITMAPINFO *)&bmi, // pointer to structure containing bitmap size, format, and color data DIB_RGB_COLORS, // color data type indicator: RGB values or palette indices (void**)&prgbaDIB, // pointer to variable to receive a pointer to the bitmap's bit values NULL, // optional handle to a file mapping object 0 // offset to the bitmap bit values within the file mapping object ); if ( !hBitmap ) { CString message; message.FormatMessage("Windows failed to allocate bitmap of size %1!d!x%2!d!!", inImage.rows(), inImage.columns()); DoDisplayError("DoDisplayImage",message); return; } // // If image is non-opaque, apply a pattern background so // non-opaque regions become evident. // Magick::Image image=inImage; if (inImage.matte()) { Magick::Image texture; texture.read("image:checkerboard"); image.texture(texture); image.matte(false); } // // Extract the pixels from Magick++ image object and convert to a DIB section // const unsigned int columns = image.columns(); const unsigned int rows = image.rows(); RGBQUAD *pDestPixel = prgbaDIB; for( unsigned int row = 0 ; row < rows ; row++ ) { const PixelPacket *pPixels = image.getConstPixels(0,row,columns,1); #if QuantumDepth == 8 // Form of PixelPacket is identical to RGBQUAD when QuantumDepth==8 memcpy((void*)pDestPixel,(const void*)pPixels,sizeof(PixelPacket)*columns); pDestPixel += columns; #else // 16 or 32 bit Quantum // Transfer pixels, scaling to Quantum for( unsigned long nPixelCount = columns; nPixelCount ; nPixelCount-- ) { pDestPixel->rgbRed = ScaleQuantumToChar(pPixels->red); pDestPixel->rgbGreen = ScaleQuantumToChar(pPixels->green); pDestPixel->rgbBlue = ScaleQuantumToChar(pPixels->blue); pDestPixel->rgbReserved = 0; ++pDestPixel; ++pPixels; } #endif } // Create a display surface mOffscreenDC = new CDC(); mOffscreenDC->CreateCompatibleDC( pDC ); // Clear the background (Is this really necessary?) //CRect rectClient; //GetClientRect(rectClient); //mOffscreenDC->FillSolidRect(rectClient,mOffscreenDC->GetBkColor()); // Now copy the bitmap to device mOffscreenDC->SelectObject( hBitmap ); } pDC->BitBlt( 0, 0, inImage.columns(), inImage.rows(), mOffscreenDC, 0, 0, SRCCOPY ); mViewDirty = false; // not any more! // draw the marching ants, if any bool isPrinting = pDC->IsPrinting(); if ( !isPrinting && m_tracker.m_rect.Width() && m_tracker.m_rect.Height() ) m_tracker.Draw( pDC ); } }
GradientCalculator::GradientCalculator(Magick::Image& image) { m_pixels = image.getConstPixels(0, 0, image.columns(), image.rows()); m_size.Set(image.columns(), image.rows()); }
void Magick::blurImage::operator()( Magick::Image &image_ ) const { image_.blur( _radius, _sigma ); }
void Magick::trimImage::operator()( Magick::Image &image_ ) const { image_.trim( ); }
void Magick::animationIterationsImage::operator()( Magick::Image &image_ ) const { image_.animationIterations( _iterations ); }
void Magick::waveImage::operator()( Magick::Image &image_ ) const { image_.wave( _amplitude, _wavelength ); }
void Magick::backgroundTextureImage::operator()( Magick::Image &image_ ) const { image_.backgroundTexture( _backgroundTexture ); }
void Magick::resizeImage::operator()( Magick::Image &image_ ) const { image_.resize( _geometry ); }
void Magick::chromaRedPrimaryImage::operator()( Magick::Image &image_ ) const { image_.chromaRedPrimary( _x, _y ); }
void Magick::zoomImage::operator()( Magick::Image &image_ ) const { image_.zoom( _geometry ); }
void Magick::borderImage::operator()( Magick::Image &image_ ) const { image_.border( _geometry ); }
void Magick::antiAliasImage::operator()( Magick::Image &image_ ) const { image_.antiAlias( _flag ); }
void Magick::colorMapImage::operator()( Magick::Image &image_ ) const { image_.colorMap( _index, _color ); }
void Magick::adjoinImage::operator()( Magick::Image &image_ ) const { image_.adjoin( _flag ); }
void Magick::compressTypeImage::operator()( Magick::Image &image_ ) const { image_.compressType( _compressType ); }
void Magick::animationDelayImage::operator()( Magick::Image &image_ ) const { image_.animationDelay( _delay ); }
void Magick::depthImage::operator()( Magick::Image &image_ ) const { image_.depth( _depth ); }
void Magick::strokeColorImage::operator()( Magick::Image &image_ ) const { image_.strokeColor( _strokeColor ); }