Jon Carrier Digital Halftone Final

Embed Size (px)

Citation preview

  • 7/30/2019 Jon Carrier Digital Halftone Final

    1/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    0 | P a g e

    Digital Halftone(Dithering) Methodsand ApplicationsDigital Image ProcessingIn this paper, the topic of digital halftones, or dithering, is discussed. In particular,the methods of implementation are discussed for the three classical categorieswhich are random, ordered, and error diffusion dithering. A good understandingof dithering is necessary prior to understanding how and when dithering isnecessary or beneficial to the designer. This paper includes discussions of specifictypes of dithering including one of the most popular techniques called Floyd-Steinberg and also includes actual implementations in MATLAB [See Appendix].Several applications will be discussed that encompass not only image processingbut audio signal processing, and optics.

    2008

    Jonathan CarrierUniversity of New Hampshire

    4/28/2008

  • 7/30/2019 Jon Carrier Digital Halftone Final

    2/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    1 | P a g e

    In t roduc t ion

    n Digital Image Processing, intensity quantization has always been a topic of interest as a simplelossy compression technique; it has also been of

    interest when rendering an image on some form of

    display. In the early days of digital image processing,image quantization was used as a mechanism toreduce the file size that was needed to be transmittedon fax machines. This worked fairly well for text as itgenerally consisted of only two tones (i.e. black onwhite). However, if an image were to be processedthrough this method, there would be huge perceptualand mathematical losses in the desired image. Onekind of perceptual distortion that occurs duringintensity quantization is false contouring. Falsecontouring refers to the contour lines that are

    produced during the quantization of the intensitylevels (generally, although not limited to, lowfrequency transitions in an image). Due to theselosses and distortions that occur during quantization,many people have developed methods/algorithms toreduce the apparent loss of the image. These methodsare commonly referred to as digital halftones, or more generically dithering. Historically, half-toningrefers to the process that was used in printing presses.The idea of half-toning was that instead of having anexpensive and slow system that creates mixtures of white and black to create a gray scale image (or

    pallet), we could instead use black dots of ink withvarying radii onto a white sheet of paper to resemblethe original image. In other words, to representdarker regions of an image, larger dots can be usedthus giving the apparent effect that the region isdarker than a portion of the image that has smaller dots. Essentially we are creating a larger set of intensities with two tones (black and white). This isthe essence of dithering.

    What is di ther?

    ither, pronounced \ di -thr \ , by definition,means to tremble or to act nervously or indecisively [1]. In terms of signal

    processing, dithering means to add uncertainty to asignal; or in other words, add noise. This at first mayseem to make little sense to an engineer, as noise, atleast to an engineer's fundamental understanding, isunwanted. However, after careful consideration wecan make sense of this concept through this paper.

    What ' s the po in t?

    o why in the world would you want to addnoise to a signal? Well to be honest, we areexploiting the imperfections that human

    sensors have, be it the eyes or the ears. In digital

    image processing, it is of great interest to study thehuman eye and how it perceives the world that welive in. One of the fundamental concepts that can belearned about the human eye is that it has a naturallowpass filter. This means if a digital image hasdiscontinuities or high frequency transitions, thehuman eye has the ability to take an average of a setof neighboring pixels which in turn, smoothes theimage's appearance and merges several colors or intensities that are close to each other into oneaveraged color or intensity. The further away thehuman is from the image, the more the image getsfiltered through this process. A similar effect can besaid about observing an image too close; however,this concept will not be considered in this paper.

    In implementation, dithering is the process of representing more intensity levels than what the bitdepth of the image is capable of. In a simple case, agrayscale image can be represented by different

    patterns of black and white pixels. Take for instance,an image that is pure white; we would like thedithered result to be nothing but white pixels.Likewise, for a pure black image we would like just

    black pixels. However, if we consider an image thathas a mid gray level (I.e 50% black), the bestrepresentation of that tone would be an interlacedimage of black and white pixels, more commonlyknown as a checkerboard pattern. Through thisexploitation of the human eye, we can make a varietyof intensities by closely pairing intensities, or evencolors, together.

    Figure 1: Midtone Gray to Dithered Representation

    I

    D

    S

  • 7/30/2019 Jon Carrier Digital Halftone Final

    3/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    2 | P a g e

    How Do I Dither?

    Random Dither

    ow that we have a basic understanding of what dithering is, let us discuss the differenttypes of dithering. There are three classical

    methods of dithering, each of which have manydifferent methods of implementation. The first andmost basic method is random dithering. Randomdithering is the process of creating a random (psuedo-random, possibly uniformly distributed or Gaussian)threshold for the pixel that is being processed. Thismethod dates back to as early as 1951 which wasimplemented as a remedy to the thresholding

    problem. The main flaw to thresholding is the factthat quantization error is left on each pixel instead of attempting to correct or spread error out among itsneighbors as a means to reduce the apparent loss.Creating a static threshold causes dramatic falsecontouring that the user may or may not want in theresulting image. The effects of thresholding can beobserved by comparing Figure 2A with 2B andcomparing 3 with 5.

    Figure 2: Comparison of the Gradient Test Pattern (TOP),Average Threshold of Gradient Test Pattern (MIDDLE),and Random Dither of Gradient Test Pattern (BOTTOM).

    Figure 3: Average Threshold of Nautica Hat

    Creating a random dither is very simple but it's oftennot an acceptable method of dithering. Despite this, itwill be discussed due to the historic nature andevolution of the dithering process. To create a

    randomly dithered image (from an 8-bit gray-scaleimage), a random value from 0 to 255 is created as athreshold. If the pixel of interest is greater than or equal to that threshold, force it to 255 (white),otherwise, force it to 0 (black). This process isrepeated on each pixel in the image. Randomdithering obviously results in a noisy image but themain benefit is that it is free of artifacts that arecaused by having static thresholding points (this will

    be expanded on when ordered dithering is discussed).Ideally, random dithering is the best method in lowfrequency transitions, and in fact, it produces themost desirable result on a gradient pattern that goesfrom 0 to 255 as there are no apparent artifacts thatthe eye gets attracted to (such as false contours or other patterns).

    Figure 4: Random Dither of Hat

    Figure 5: Nautica Hat

  • 7/30/2019 Jon Carrier Digital Halftone Final

    4/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    3 | P a g e

    Ordered Dither

    ne might think, there must be a better method than just adding noise; well, thereis...and then there isn't. The two other

    classical methods may give you a cleaner lookingimage but they don't come without a price. Ordered

    dithering is the next classical method which aims attaking a kernel that acts as a thresholding device.This concept is an improvement on random dithering,at least in practical terms, as there is a considerationof how neighboring pixels should be treated. The bad

    part of this algorithm though, is that this process isnot a pixel by pixel operation. In other words, aregion of the image is observed and compared to thekernel. Once those pixels in that region have beenadjusted according to the threshold limits, acompletely new region is analyzed (meaning each

    pixel is only touched on once during the entire process). This flaw in the process causes patterns to

    be easily viewed by the human eye. Even though this'patternization' of the image may come acrossvisually as a flaw, in hardware or software it is ahuge plus, as it encourages parallel processing. Other algorithms that use pixel by pixel processing oftendepend on some prior pixel's value thus forcing suchalgorithms to be serial which increases the processingtime substantially.

    In the classical case, the kernel is designed as acluster of dots which produce apparent intensitieswithin the image. As mentioned before, printingsystems use a specific version of this, often referredto as halftoning. The idea of this method is to have alarger dot (or larger cluster of dots) to representdarker portions of an image and have smaller dots (or less clustering of dots) to represent lighter portions of an image. The classical version of this method can beviewed below in Figure 7.

    Figure 6: Gradient Test Pattern

    Figure 7: Halftone Dither

    Figure 8: Bayer Dither

    Recognized by its crosshatched appearance, a morerecent form of ordered dither, is the Bayer method of dithering. In 1976, Bayer discussed efficient and fastways of dithering using ordered dithering. He notedthat optimal dithering kernels can be made by havingthem sized at 2 nx2n where each value in the kerneltakes on a unique value that goes from 0 toval{2 nx2 n}. For instance:

    Figure 9: Bayer Ordered Dithering Kernels. From [2]

    The two kernels above are for dispersed dots andclustered dots respectively. These are just two out of the many possible results from Bayer dithering. Thedispersed dots version of Bayer dithering is themost notable and recognizable version of this form of ordered dithering due to its crosshatching-like results.See Figure 10 below.

    Figure 10: Bayer Dither of Nautica Hat

    [0 8 2 10

    12 4 14 6

    3 11 1 9

    15 7 13 5 ][

    6 7 8 9

    5 0 1 10

    4 3 2 11

    15 14 13 12 ]

    O

  • 7/30/2019 Jon Carrier Digital Halftone Final

    5/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    4 | P a g e

    Error Diffusion Dithering

    astly, there is error diffusion. The principal behind error diffusion is simple, if error existson a pixel due to quantization, then attempt to

    share that error amongst it's neighboring pixels

    (please note: it isn't really sharing but readjustment of unprocessed pixels). In 1976, the classical exampleof error diffusion was published by Robert Floyd andLouis Steinberg. The Floyd-Steinberg algorithm as itwas named, used a very simple kernel that propagatesthe error down and to the right of the pixel being

    processed. This meant that the processing began at

    Figure 11: Error Diffusion Feedback Network

    the top left corner of the image being processed andworked across left to right, row by row. At roughlythe same time however, Jarvis, Judice, and Ninkediscussed another kernel that was a more complicatedyet achieved a better result (at least in terms of minimizing the artifacts that become present in suchan algorithm). Due to the slow nature of the kernel,and less spatial resolution which is important to text-

    based information, the Jarvis, Judice, and Ninkealgorithm did not get the same amount of attention asthe Floyd-Steinberg.

    Figure 12: Floyd-Steinberg Kernel

    Figure 13: Jarvis, Judice, and Ninke Kernel

    Some research has taken place to improve the speedof the minimized average error method that Jarvis,Judice, and Ninke developed, where people havedeveloped variations of the kernel that they defined.One such alternative is the Atkinson dither. Thisdithering method propagates only a third of the error.Due to this method of propagation, the result tends to blow out the dark and light areas of the image. Thishas the tendency to reduce the appearance of artifactsin the light and dark regions. One additional noteabout the Floyd-Steinberg kernel was that it wasspecifically designed to give the checkerboard patternwhen the intensity level was at 50% (in fact, Floyd-Steinberg dithering was used in Figure #1 to createthe checkerboard pattern from the gray tone). Thefollowing page contains a comparison of the Floyd-Steinberg, the Jarvis, Judice, and Ninke , and theAtkinson algorithms.

    [0 0 0

    0 05

    16

    3

    16

    7

    16

    1

    16

    ]

    [0 0 0 0 0

    0 0 0 0 0

    0 0 07

    48

    5

    483

    48

    5

    48

    7

    48

    5

    48

    3

    48

    1

    48

    3

    48

    5

    48

    3

    48

    1

    48]L

  • 7/30/2019 Jon Carrier Digital Halftone Final

    6/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    5 | P a g e

    Figure 14: Comparison of the Floyd-Steinberg (TOP), the Jarvis, Judice, and Ninke (MIDDLE), and the Atkinson(BOTTOM) algorithms. Note: Image has been enlarged for ease of viewing.

    Figure 16:Nautica Hat

    Figure 18: Floyd-Steinberg Dither

    Figure 15: Jarvis, Judice, and Ninke Dither

    Figure 17: Atkinson Dither

  • 7/30/2019 Jon Carrier Digital Halftone Final

    7/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    6 | P a g e

    Image Fusion

    mage fusion is a method of taking two imagesand combining them in some fashion to give theuser a better representation of what is meaningful

    in the image (such as medical imaging, combining X-

    rays with thermal properties). Although not suitablefor medical purposes due to the tradeoff of spatialresolution, dithering can beused as a method of imagefusion by combining theconcept of ordered ditheringwith error diffusion. As wewere able to see in the

    previous sections, ordereddithering results in apatternized representation of the image while error diffusionresults in fine grain representations of an image. If we apply both these concepts together we should beable to get a kernel that overlays the image and wherethe thresholding error gets diffused. To do this isquite simple, first define a kernel to apply such asFigure 20. Then process the image as you normallywould if you were using ordered dithering. However,instead of just quantizing the values based on theordered dither kernel, we introduce an error diffusionkernel that attempts to distribute the error across thecurrent section of the image. This process is repeateduntil the entire image has been processed. Below isan example of this method.

    Figure 20: Image Fused with Texture

    There are MANY more algorithms that could bediscussed each of which have trade-offs; however, ingeneral it can be observed that a better ditheringalgorithm comes at the cost of processing time.

    Color Dithering

    ow that we have discussed the three types of dithering and applied some examples of eachin black and white, we can now start

    discussing how these can be implemented in color.

    To dither in color is very simple, instead of dealingwith a single intensity that describes a grayscalerange we can start to think in terms of three colorintensities that describe a color space. Since Matlabnatively uses RGB color we will stick to the 3-channel method instead of other variants.

    For example, say we would like to produce a randomdither of an image in color. To do this we simplylook at a pixel's RGB intensities and compare thoseto randomly generated threshold value. If you arewondering why we don't create three randomthreshold values for each pixel, the answer is really

    just a matter of preference. The nice thing aboutcreating one random threshold per pixel is that if youhave a grayscale image and it is being processedthrough a color random dither, the result will be

    black and white, where as the alternative method willnot; not only that but you cut the random number generations by a third, thus speeding up the process.Below are some results (in color) of all the dither methods previously discussed.

    Figure 21: Kopipi Island

    I

    Figure 19: Texture

  • 7/30/2019 Jon Carrier Digital Halftone Final

    8/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    7 | P a g e

    Figure 22: Kopipi Island with Average Thresholding

    Figure 23: Kopipi Island with Random Dither

    Figure 24: Kopipi Island with Bayer Dither

    Figure 25: Kopipi Island with Floyd-Steinberg Dither

    Figure 26: Kopipi Island; Jarvis, Judice, and Ninke Dither

    Figure 27: Kopipi Island with Atkinson Dither

  • 7/30/2019 Jon Carrier Digital Halftone Final

    9/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    8 | P a g e

    Appl ica t ions

    ow that the implementations have beendiscussed along with some of the flaws and

    benefits, it might now be clear as to howdithering can be used.

    Printing Systems

    As mentioned before, the printing industry has founddithering to be very useful for representing images inlaser printing. Instead of designing expensivesystems that can mix colors together accurately andfast, historically, many printing systems have decidedto go with dithering, which helps to reduce thehardware costs while maintaining a better representation of an image than what a standardthreshold or intensity quantization system canachieve. Historically, ordered dithering was used tocreate the images as it was easier to control the radiusof the dot of ink rather than many finely spaced dots.

    Monitor Technology

    Monitors have used dithering is two ways. The first,is the same way that this article has discussed whichis spatial dithering . Older monitors or some newer LCD displays (such as the ones on a cellular phone or camera) that were limited in color intensities or

    possibly limited to black and white, used hardware todither the output so that if an image was to be

    presented, the user would have an easier timeinterpreting the image. Industrial displays such as

    electroluminescent and vacuum florescent displaysthat are used for their long life and wide operatingtemperature ranges have a use for these algorithms aswell, since they are limited to either black and whiteor 1-3 bits per color channel. The second way thatmonitors use dithering is temporal dithering . Instead

    of sacrificing spatial resolution in order to reduceintensity quantization we can choose to dither over time. Since more recent displays are able to achievefast refresh rates that are well above the human eye'sflicker fusion rate, we can opt to dither over time.The idea behind this is simple, say that we have agray color tone that is 50% black, as we noted beforethe optimal representation for such an intensity is acheckerboard pattern. To do this temporally, wesimply would alternate (in time) black and white atthe highest frequency thus giving the impression thatthe image is a midtone gray. For darker tones, wewould increase the number of occurrences of dark tones compared to light tones over a period of time.Similarly for light tones, we would want moreoccurrences of light tones than dark tones over a

    period of time.

    A/D Conversion in Audio Signal Processing

    A common process in signal processing is theconversion from an analog waveform to a digitalwaveform. In Audio Signal Processing, this process

    becomes very important as the human ear is particular to picking out differences in frequencies,similar to a spectrum analyzer. As you may know, asquare pulse in the time domain produces a sinc pulsein the frequency domain. It can be suspected that theresulting frequency components from the quantized(zero-order hold operation) audio waveform willhave a similar effect. It turns out that thisquantization boosts frequencies that the ear is verykeen at picking up and distorts the intended audio

    signal. To counter this, dithering can be used as theear is less susceptible to this form of noise. It can beshown that creating a random dither on the signalimproves the signal to audible noise ratio as itreduces the additional periodicity due to quantization.

    Figure 28: Simple Block Diagram of Temporal Dither Process

  • 7/30/2019 Jon Carrier Digital Halftone Final

    10/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    9 | P a g e

    Optical Transmission

    In optics, pulses of light are sent down a waveguidewhich at the other end get received and convertedfrom optical to electrical via an O/E converter.Optical launch power is a primary concern of adevice's optical transmitter, if the launch power is too

    weak, the eye opening on the far end is severelydegraded and has a high probability of error. It isdesirable to have a high enough launch power toensure an open eye across a long haul transmission;however, the concept of stimulated Brillouinscattering (SBS) often comes into play and limitsnormal transmission techniques. SBS is an effect thatoccurs due to a non-uniform medium that containsvariation in density (i.e. a Graded-Index MultimodeFiber). If the medium is non-uniform and thethreshold that is determined by the medium isexceeded, the signal will produce acoustic signalsthat will cause attenuation and saturation in power, as

    well as back-propagation that causes degradations tothe signal. It turns out that this is where the conceptof dithering comes into play. By dithering the pulsesof light coming out of the transmitter, the thresholdcan be increased thus allowing for longer transmissions over a medium.

    Conclus ions

    n this paper, we discussed the concept of dithering and how it could be applied to varioussystems. Dithering serves as a technique to

    represent more intensities than the bit depth is

    capable of at the cost of spatial resolution. It could beobserved that the more simplistic the ditheringalgorithm, in general, the faster and less accurate therepresentation. Hopefully from this paper, you havegained a solid understanding of the trade-offs

    involved in dithering, and that in general, this should be the last process that the image undergoes beforedisplay, leaving a copy of the original stored inmemory. Finally, we arrive at the original statementthat, dithering can be described as adding noise toreduce noise; this should now make sense since weare reducing the periodicity caused by quantization.

    References

    [1] Merriam- Webster Dictionary, Dither. http://www.merriam-webster.com/cgi-bin/dictionary?book=Dictionary&va=dithering

    [2] Nika Aldrich, Dither Explained: An explanation and proof of the benefit of dither for the audio enginee r,Cadenza Recording,April 25, 2002.http://www.users.qwest.net/~volt42/cadenzarecording/DitherExplained.pdf

    [3] Alejo Hausner, Graph -Order Dithering, University of NewHampshire.http://www.cs.unh.edu/~ah/publications/spie06/hausner-graph-order-dither.pdf

    [4] Wikipedia, Dither, April 28, 2008.http://en.wikipedia.org/wiki/Dither

    [5] http://verlagmartinkoch.at/software/dither/index.html

    [6] Wikipedia, Error Diffusion , April 28, 2008.http://en.wikipedia.org/wiki/Error_diffusion

    [7] JDSU, Suppre ssion of Stimulated Brillouin Scattering http://www.jdsu.com/product-literature/brillouinscattering_tn_cms_ae_0306.pdf

    [8] Lee Daniel Crocker, What is Digital Halftoning? January 2,1989.http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT

    I

    http://www.merriam-webster.com/cgi-bin/dictionary?book=Dictionary&va=ditheringhttp://www.merriam-webster.com/cgi-bin/dictionary?book=Dictionary&va=ditheringhttp://www.merriam-webster.com/cgi-bin/dictionary?book=Dictionary&va=ditheringhttp://www.merriam-webster.com/cgi-bin/dictionary?book=Dictionary&va=ditheringhttp://www.users.qwest.net/~volt42/cadenzarecording/DitherExplained.pdfhttp://www.users.qwest.net/~volt42/cadenzarecording/DitherExplained.pdfhttp://www.users.qwest.net/~volt42/cadenzarecording/DitherExplained.pdfhttp://www.cs.unh.edu/~ah/publications/spie06/hausner-graph-order-dither.pdfhttp://www.cs.unh.edu/~ah/publications/spie06/hausner-graph-order-dither.pdfhttp://www.cs.unh.edu/~ah/publications/spie06/hausner-graph-order-dither.pdfhttp://en.wikipedia.org/wiki/Ditherhttp://en.wikipedia.org/wiki/Ditherhttp://verlagmartinkoch.at/software/dither/index.htmlhttp://verlagmartinkoch.at/software/dither/index.htmlhttp://verlagmartinkoch.at/software/dither/index.htmlhttp://en.wikipedia.org/wiki/Error_diffusionhttp://en.wikipedia.org/wiki/Error_diffusionhttp://www.jdsu.com/product-literature/brillouinscattering_tn_cms_ae_0306.pdfhttp://www.jdsu.com/product-literature/brillouinscattering_tn_cms_ae_0306.pdfhttp://www.jdsu.com/product-literature/brillouinscattering_tn_cms_ae_0306.pdfhttp://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXThttp://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXThttp://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXThttp://www.jdsu.com/product-literature/brillouinscattering_tn_cms_ae_0306.pdfhttp://www.jdsu.com/product-literature/brillouinscattering_tn_cms_ae_0306.pdfhttp://en.wikipedia.org/wiki/Error_diffusionhttp://verlagmartinkoch.at/software/dither/index.htmlhttp://en.wikipedia.org/wiki/Ditherhttp://www.cs.unh.edu/~ah/publications/spie06/hausner-graph-order-dither.pdfhttp://www.cs.unh.edu/~ah/publications/spie06/hausner-graph-order-dither.pdfhttp://www.users.qwest.net/~volt42/cadenzarecording/DitherExplained.pdfhttp://www.users.qwest.net/~volt42/cadenzarecording/DitherExplained.pdfhttp://www.merriam-webster.com/cgi-bin/dictionary?book=Dictionary&va=ditheringhttp://www.merriam-webster.com/cgi-bin/dictionary?book=Dictionary&va=dithering
  • 7/30/2019 Jon Carrier Digital Halftone Final

    11/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    x | P a g e

    Appendix

    Matlab Code

    Please NOTE: The function below is normally integrated into a GUI and there are function callsthat are not include for the sake of simplicity. Each of the algorithms can be found in the codebelow. If you need the other function please contact the author of this paper.

    function JonCarrier_Dither warning off ; Kernel=[]; clc; disp( 'Processing...' ) % ================================================================ %% Handle Information % ================================================================ ditherMethods=get(findobj( 'Tag' , 'dither' ), 'String' ); ditherMethod=char(ditherMethods(get(findobj( 'Tag' , 'dither' ), 'value' )));

    colorize=get(findobj( 'Tag' , 'dither_colorize' ), 'Value' ); bits=str2num(get(findobj( 'Tag' , 'dither_bits' ), 'String' )); images=get(findobj( 'Tag' , 'Image' ), 'String' ); imNum=get(findobj( 'Tag' , 'Image' ), 'Value' ); getCurrentAxisData=0; % ================================================================ %% Make GrayScale Image and Indexed versions of color/gray % ================================================================ if getCurrentAxisData==0 InputImage = imread(deblank(char(images(imNum)))); else disp( 'Select Your Desired Axis and Press ENTER...' ) waitforbuttonpress InputImage = get(get(gca, 'Children' ), 'CData' ); figure(30) imshow(InputImage) end

    %Correct the Image Dimensions and Scale if needed for binary data NumberOfIntensityLevels = 2^bits; NumberOfColors=2^(bits*3); if ndims(InputImage)>2 InputImageColor=InputImage; InputImage = rgb2gray(InputImage);else InputImageColor(:,:,1)=(InputImage); InputImageColor(:,:,2)=(InputImage); InputImageColor(:,:,3)=(InputImage); if max(max(InputImage))

  • 7/30/2019 Jon Carrier Digital Halftone Final

    12/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xi | P a g e

    figure(2) imshow(InputImageColor) JonCarrier_TightAxis( 'Original (Color)' ) end h=waitbar(0, 'Processing Image...' ); switch ditherMethod case 'Average-Threshold' % ================================================================

    %% Average Threshold % ================================================================ tic if colorize==0 AverageThreshold=InputImage>mean(mean(InputImage)); AverageThreshold=double(AverageThreshold)*255; figure(3) imshow(AverageThreshold, map); JonCarrier_TightAxis( 'Average Threshold' ) else AverageThreshold_R=InputImageColor(:,:,1)>mean(mean(InputImageColor(:,:,1))); AverageThreshold_G=InputImageColor(:,:,2)>mean(mean(InputImageColor(:,:,2))); AverageThreshold_B=InputImageColor(:,:,3)>mean(mean(InputImageColor(:,:,3))); AverageThresholdColor_R=AverageThreshold_R*255; AverageThresholdColor_G=AverageThreshold_G*255; AverageThresholdColor_B=AverageThreshold_B*255; AverageThresholdColor(:,:,1)=AverageThresholdColor_R;

    AverageThresholdColor(:,:,2)=AverageThresholdColor_G; AverageThresholdColor(:,:,3)=AverageThresholdColor_B; figure(4) imshow(AverageThresholdColor, color_map); JonCarrier_TightAxis( 'Average Threshold (Color)' ) end toc case 'Intensity Quantization' % ================================================================ %% Indexed Color and Grayscale % ================================================================ tic % Ii = InputImage; if colorize==0 figure(5) imshow(indexed_gray,map) JonCarrier_TightAxis( 'Indexed Image' )

    else figure(6) imshow(indexed_color,color_map) JonCarrier_TightAxis( 'Indexed Image (Color)' ) end toc case 'Random-Threshold' % ================================================================ %% Random Dither the Original Image % ================================================================ tic if colorize==0 [rows cols dummy]=size(InputImage); random=double(InputImage); randomized=double(InputImage); %Random_threshold=127+60*randn(rows,cols); Random_threshold=(255).*rand(rows,cols);

    randomized(find(random>=Random_threshold))=255; randomized(find(random=Random_threshold))=255;

  • 7/30/2019 Jon Carrier Digital Halftone Final

    13/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xii | P a g e

    randomized(find(random2 KernelColor=Kernel; Kernel = rgb2gray(Kernel); else

    if max(max(Kernel))=Kernel(x,y) Halftone(i+x,j+y)=255; else Halftone(i+x,j+y)=0; end end end end end figure(11) Halftone=Halftone(1:end-pad2,1:end-pad1,:); imshow(Halftone); JonCarrier_TightAxis( 'Ordered Dither' ) else

    if not(isempty(InputImageColor)) [x map]=rgb2ind(InputImageColor, NumberOfColors, 'nodither' ); [n dummy]=size(Kernel); [rows cols dummy]=size(InputImageColor); Half=double(InputImageColor); pad1=n*ceil(cols/n)-cols+1; HalfT(:,:,1)=[Half(:,:,1),Half(:,cols,1)*ones(1,pad1)]; %add padding on left HalfT(:,:,2)=[Half(:,:,2),Half(:,cols,2)*ones(1,pad1)]; %add padding on left HalfT(:,:,3)=[Half(:,:,3),Half(:,cols,3)*ones(1,pad1)]; %add padding on left pad2=n*ceil(rows/n)-rows+1; Halftone(:,:,1)=[HalfT(:,:,1);ones(pad2,1)*HalfT(rows,:,1)]; %add padding on bottom Halftone(:,:,2)=[HalfT(:,:,2);ones(pad2,1)*HalfT(rows,:,2)]; %add padding on bottom

  • 7/30/2019 Jon Carrier Digital Halftone Final

    14/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xiii | P a g e

    Halftone(:,:,3)=[HalfT(:,:,3);ones(pad2,1)*HalfT(rows,:,3)]; %add padding on bottom for j=1:n:cols for i=1:n:rows if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end for x=1:n for y=1:n

    if Halftone(i+x,j+y,1)>=Kernel(x,y) Halftone(i+x,j+y,1)=255; else Halftone(i+x,j+y,1)=0; end if Halftone(i+x,j+y,2)>=Kernel(x,y) Halftone(i+x,j+y,2)=255; else Halftone(i+x,j+y,2)=0; end if Halftone(i+x,j+y,3)>=Kernel(x,y) Halftone(i+x,j+y,3)=255; else Halftone(i+x,j+y,3)=0; end end end

    end end figure(12) Halftone=Halftone(1:end-pad2,1:end-pad1,:); imshow(Halftone./255,color_map); JonCarrier_TightAxis( 'Ordered Dither (Color)' ) end end case 1 kSET={ 'dispersed-dot.jpg' , 'dispersed-dot-90.jpg' , 'dispersed-dot-180.jpg' , 'dispersed-dot-270.jpg' , 'dispersed-dot-fliplr.jpg' , 'dispersed-dot-flipud.jpg' , 'dispersed-dot-flipud-fliplr-90.jpg' , 'dispersed-dot-flipud-fliplr-270.jpg' }; %,'clustered-dot.jpg' [a b]=size(kSET); for i=1:b kCELL{i}=imread(deblank(char(kSET{i}))); end KernelNUM=JonCarrier_KernelSelect(random);

    Kernel = kCELL{KernelNUM}; if colorize==0 [n dummy]=size(Kernel); [rows cols dummy]=size(InputImage); Halftone=double(InputImage); pad1=n*ceil(cols/n)-cols+2; Halftone=[Halftone,Halftone(:,cols)*ones(1,pad1)]; %add padding on left pad2=n*ceil(rows/n)-rows+2; Halftone=[Halftone;ones(pad2,1)*Halftone(rows,:)]; %add padding on bottom for j=1:n:cols for i=1:n:rows if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end KernelNUM=JonCarrier_KernelSelect(random); Kernel = kCELL{KernelNUM}; for x=1:n

    for y=1:n if Halftone(i+x,j+y)>=Kernel(x,y) Halftone(i+x,j+y)=255; else Halftone(i+x,j+y)=0; end end end end end figure(11) Halftone=Halftone(1:end-pad2,1:end-pad1,:);

  • 7/30/2019 Jon Carrier Digital Halftone Final

    15/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xiv | P a g e

    imshow(Halftone); JonCarrier_TightAxis( 'Ordered Dither' ) else if not(isempty(InputImageColor)) KernelNUM=JonCarrier_KernelSelect(random); Kernel = kCELL{KernelNUM}; [x map]=rgb2ind(InputImageColor, NumberOfColors, 'nodither' ); [n dummy]=size(Kernel);

    [rows cols dummy]=size(InputImageColor); Half=double(InputImageColor); pad1=n*ceil(cols/n)-cols+1; HalfT(:,:,1)=[Half(:,:,1),Half(:,cols,1)*ones(1,pad1)]; %add padding on left HalfT(:,:,2)=[Half(:,:,2),Half(:,cols,2)*ones(1,pad1)]; %add padding on left HalfT(:,:,3)=[Half(:,:,3),Half(:,cols,3)*ones(1,pad1)]; %add padding on left pad2=n*ceil(rows/n)-rows+1; Halftone(:,:,1)=[HalfT(:,:,1);ones(pad2,1)*HalfT(rows,:,1)]; %add padding on bottom Halftone(:,:,2)=[HalfT(:,:,2);ones(pad2,1)*HalfT(rows,:,2)]; %add padding on bottom Halftone(:,:,3)=[HalfT(:,:,3);ones(pad2,1)*HalfT(rows,:,3)]; %add padding on bottom for j=1:n:cols for i=1:n:rows KernelNUM=JonCarrier_KernelSelect(random); Kernel = kCELL{KernelNUM}; if mod((j+cols*(i))/(rows*cols)*100,1)==0waitbar((j+cols*(i))/(rows*cols)) end

    for x=1:n for y=1:n if Halftone(i+x,j+y,1)>=Kernel(x,y) Halftone(i+x,j+y,1)=255; else Halftone(i+x,j+y,1)=0; end if Halftone(i+x,j+y,2)>=Kernel(x,y) Halftone(i+x,j+y,2)=255; else Halftone(i+x,j+y,2)=0; end if Halftone(i+x,j+y,3)>=Kernel(x,y) Halftone(i+x,j+y,3)=255; else Halftone(i+x,j+y,3)=0; end

    end end end end figure(12) Halftone=Halftone(1:end-pad2,1:end-pad1,:); imshow(Halftone./255,color_map); JonCarrier_TightAxis( 'Ordered Dither (Color)' ) end end end toc case 'Matlab' % ================================================================ %% Matlab Dither % ================================================================ tic

    if colorize==0 figure(13) matlabDither=dither(InputImage); imshow(matlabDither); %imshow(matlabDither,map); JonCarrier_TightAxis( 'Matlab Dither' ) else [matlabDither_color, color_map] = rgb2ind(InputImageColor, NumberOfIntensityLevels); figure(14) imshow(matlabDither_color,color_map); JonCarrier_TightAxis( 'Matlab Dither (Color)' ) end

  • 7/30/2019 Jon Carrier Digital Halftone Final

    16/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xv | P a g e

    toc case 'Floyd-Steinberg' % ================================================================ %% Floyd-Steinberg Dither the Original Image % ================================================================ tic Kernel=[ 0 0 0; 0 0 5; 3 7 1]; if colorize==0

    levels=NumberOfIntensityLevels;[rows cols dummy]=size(InputImage);pixel=double(InputImage); pixel=[ones(rows,1).*pixel(:,1),pixel,ones(rows,1).*pixel(:,cols)]; %add padding on left and right pixel=[ones(1,cols+2).*pixel(1,:);pixel;ones(1,cols+2).*pixel(rows,:)]; %add padding on top andbottom for i=2:rows+1 for j=2:cols+1 if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end oldpixel=pixel(i,j); newpixel=quant(oldpixel,255/(levels-1)); pixel(i,j)=newpixel; quantizationError=oldpixel-newpixel; pixel(i-1:i+1,j-1:j+1)=pixel(i-1:i+1,j-1:j+1)+1/16*Kernel.*quantizationError; end

    end figure(15) pixel=pixel(2:end-1,2:end-1); imshow(pixel./255); JonCarrier_TightAxis( 'Floyd-Steinberg Dither' ) else if not(isempty(InputImageColor))levels=NumberOfIntensityLevels; %NumberOfColors;% [x map]=rgb2ind(InputImageColor,levels, 'nodither' ); [rows cols dummy]=size(InputImage); pixel=double(InputImageColor); pixel=[ones(rows,1,3).*pixel(:,1,:),pixel,ones(rows,1,3).*pixel(:,cols,:)]; %add padding onleft,right pixel=[ones(1,cols+2,3).*pixel(1,:,:);pixel;ones(1,cols+2,3).*pixel(rows,:,:)]; %add pad ontop,bottom for i=2:rows+1 for j=2:cols+1

    if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end % Error Diffusion on RED, GREEN, and BLUE channels oldpixel=pixel(i,j,:); newpixel=quant(oldpixel,255/(levels-1)); %255*round((oldpixel+127)/256); pixel(i,j,:)=newpixel; quantizationError=oldpixel-newpixel; Diffuse(:,:,1)=quantizationError(:,:,1)*(1/16.*Kernel); Diffuse(:,:,2)=quantizationError(:,:,2)*(1/16.*Kernel); Diffuse(:,:,3)=quantizationError(:,:,3)*(1/16.*Kernel); pixel(i-1:i+1,j-1:j+1,:)=pixel(i-1:i+1,j-1:j+1,:)+Diffuse; end end figure(16) pixel=pixel(2:end-1,2:end-1,:); imshow(pixel./255,map);

    JonCarrier_TightAxis( 'Floyd-Steinberg Dither (Color)' ) end end toc case 'Jarvis-Judice-Ninke' % ================================================================ %% Jarvis, Judice, and Ninke Dither the Original Image % ================================================================ tic Kernel=[0 0 0 0 0; 0 0 0 0 0; 0 0 0 7 5; 3 5 7 5 3; 1 3 5 3 1];if colorize==0 levels=NumberOfIntensityLevels;

  • 7/30/2019 Jon Carrier Digital Halftone Final

    17/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xvi | P a g e

    [rows cols dummy]=size(InputImage); pixel=double(InputImage); pixel=[pixel(:,1),pixel(:,1),pixel,pixel(:,cols),pixel(:,cols)]; %add padding on left and right pixel=[pixel(1,:);pixel(1,:);pixel;pixel(rows,:);pixel(rows,:)]; %add padding on top and bottom for i=3:rows+2 for j=3:cols+2if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols))

    end oldpixel=pixel(i,j); newpixel=quant(oldpixel,255/(levels-1)); pixel(i,j)=newpixel; quantizationError=oldpixel-newpixel; pixel(i-2:i+2,j-2:j+2)=pixel(i-2:i+2,j-2:j+2)+quantizationError*1/48.*Kernel; end end figure(17) pixel=pixel(3:end-2,3:end-2); imshow(pixel./255); JonCarrier_TightAxis( 'Jarvis, Judice, and Ninke Dither' ) else if not(isempty(InputImageColor))levels=NumberOfIntensityLevels; %NumberOfColors;% [x map]=rgb2ind(InputImageColor,levels, 'nodither' ); [rows cols dummy]=size(InputImage);

    pixel=double(InputImageColor); pixel=[pixel(:,1,:),pixel(:,1,:),pixel,pixel(:,cols,:),pixel(:,cols,:)]; %add padding on left andright pixel=[pixel(1,:,:);pixel(1,:,:);pixel;pixel(rows,:,:);pixel(rows,:,:)]; %add padding on top andbottom for i=3:rows+2 for j=3:cols+2 if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end % Error Diffusion on RED, GREEN, and BLUE channels oldpixel=pixel(i,j,:); newpixel=quant(oldpixel,255/(levels-1)); %255*round((oldpixel+127)/256); pixel(i,j,:)=newpixel; quantizationError=oldpixel-newpixel; Diffuse(:,:,1)=quantizationError(:,:,1)*(1/48.*Kernel); Diffuse(:,:,2)=quantizationError(:,:,2)*(1/48.*Kernel);

    Diffuse(:,:,3)=quantizationError(:,:,3)*(1/48.*Kernel); pixel(i-2:i+2,j-2:j+2,:)=pixel(i-2:i+2,j-2:j+2,:)+Diffuse; end end figure(18) pixel=pixel(2:end-1,2:end-1,:); imshow(pixel./255,map); JonCarrier_TightAxis( 'Jarvis, Judice, and Ninke Dither (Color)' ) end end toc case 'Atkinson' % ================================================================ %% Atkinson Dither the Original Image % ================================================================ tic Kernel=[0 0 0 0 0; 0 0 0 0 0; 0 0 0 1 1; 0 1 1 1 0; 0 0 1 0 0];if colorize==0 levels=NumberOfIntensityLevels; [rows cols dummy]=size(InputImage); pixel=double(InputImage); pixel=[pixel(:,1),pixel(:,1),pixel,pixel(:,cols),pixel(:,cols)]; %add padding on left and right pixel=[pixel(1,:);pixel(1,:);pixel;pixel(rows,:);pixel(rows,:)]; %add padding on top and bottom for i=3:rows+2 for j=3:cols+2if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end oldpixel=pixel(i,j);

  • 7/30/2019 Jon Carrier Digital Halftone Final

    18/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xvii | P a g e

    newpixel=quant(oldpixel,255/(levels-1)); pixel(i,j)=newpixel; quantizationError=oldpixel-newpixel; pixel(i-2:i+2,j-2:j+2)=pixel(i-2:i+2,j-2:j+2)+quantizationError*1/8.*Kernel; end end figure(19) pixel=pixel(3:end-2,3:end-2);

    imshow(pixel./255); JonCarrier_TightAxis( 'Atkinson Dither' ) else if not(isempty(InputImageColor))levels=NumberOfIntensityLevels; %NumberOfColors;% [x map]=rgb2ind(InputImageColor,levels, 'nodither' ); [rows cols dummy]=size(InputImage); pixel=double(InputImageColor); pixel=[pixel(:,1,:),pixel(:,1,:),pixel,pixel(:,cols,:),pixel(:,cols,:)]; %add padding on left andright pixel=[pixel(1,:,:);pixel(1,:,:);pixel;pixel(rows,:,:);pixel(rows,:,:)]; %add padding on top andbottom for i=3:rows+2 for j=3:cols+2 if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end

    % Error Diffusion on RED, GREEN, and BLUE channels oldpixel=pixel(i,j,:); newpixel=quant(oldpixel,255/(levels-1)); %255*round((oldpixel+127)/256); pixel(i,j,:)=newpixel; quantizationError=oldpixel-newpixel; Diffuse(:,:,1)=quantizationError(:,:,1)*(1/8.*Kernel); Diffuse(:,:,2)=quantizationError(:,:,2)*(1/8.*Kernel); Diffuse(:,:,3)=quantizationError(:,:,3)*(1/8.*Kernel); pixel(i-2:i+2,j-2:j+2,:)=pixel(i-2:i+2,j-2:j+2,:)+Diffuse; end end figure(21) pixel=pixel(2:end-1,2:end-1,:); imshow(pixel./255,map); JonCarrier_TightAxis( 'Atkinson Dither (Color)' ) end end

    toc case 'Image Fusion' % ================================================================ %% Image Fusion using Ordered Dither and Floyd-Steinberg % ================================================================ tic JonCarrier_KernelSelect(0) uiwait pause(.5) images=get(findobj( 'Tag' , 'Project_Kernel' ), 'String' ); imNum=get(findobj( 'Tag' , 'Project_Kernel' ), 'Value' ); Kernel = imread(deblank(char(images(imNum)))); if ndims(Kernel)>2 KernelColor=Kernel; Kernel = rgb2gray(Kernel); else if max(max(Kernel))

  • 7/30/2019 Jon Carrier Digital Halftone Final

    19/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xviii | P a g e

    Halftone=[HalfT;ones(pad2,1)*HalfT(rows,:)]; %add padding on bottom for j=1:n:cols for i=1:n:rows if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end for x=1:n for y=1:n

    if Halftone(i+x,j+y)>=Kernel(x,y) oldpixel=Halftone(i+x,j+y); newpixel=255; Halftone(i+x,j+y)=newpixel; quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y)=Halftone(i+1+x,j+y)+7/16*quantizationError; Halftone(i-1+x,j+1+y)=Halftone(i-1+x,j+1+y)+3/16*quantizationError; Halftone(i+x,j+1+y)=Halftone(i+x,j+1+y)+5/16*quantizationError; Halftone(i+1+x,j+1+y)=Halftone(i+1+x,j+1+y)+1/16*quantizationError; else Halftone(i+x,j+y)=0;oldpixel=Halftone(i+x,j+y); newpixel=0; Halftone(i+x,j+y)=newpixel; quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y)=Halftone(i+1+x,j+y)+7/16*quantizationError; Halftone(i-1+x,j+1+y)=Halftone(i-1+x,j+1+y)+3/16*quantizationError; Halftone(i+x,j+1+y)=Halftone(i+x,j+1+y)+5/16*quantizationError;

    Halftone(i+1+x,j+1+y)=Halftone(i+1+x,j+1+y)+1/16*quantizationError; end end end end end figure(22) Halftone=Halftone(1:end-pad2,1:end-pad1); imshow(Halftone); JonCarrier_TightAxis( 'Image Fusion' ) else if not(isempty(InputImageColor)) [x map]=rgb2ind(InputImageColor, NumberOfIntensityLevels, 'nodither' ); [n dummy]=size(Kernel); [rows cols dummy]=size(InputImageColor); Half=double(InputImageColor); pad1=n*ceil(cols/n)-cols+2;

    HalfT(:,:,1)=[Half(:,:,1),Half(:,cols,1)*ones(1,pad1)]; %add padding on left HalfT(:,:,2)=[Half(:,:,2),Half(:,cols,2)*ones(1,pad1)]; %add padding on left HalfT(:,:,3)=[Half(:,:,3),Half(:,cols,3)*ones(1,pad1)]; %add padding on left pad2=n*ceil(rows/n)-rows+2; Halftone(:,:,1)=[HalfT(:,:,1);ones(pad2,1)*HalfT(rows,:,1)]; %add padding on bottom Halftone(:,:,2)=[HalfT(:,:,2);ones(pad2,1)*HalfT(rows,:,2)]; %add padding on bottom Halftone(:,:,3)=[HalfT(:,:,3);ones(pad2,1)*HalfT(rows,:,3)]; %add padding on bottom for j=1:n:cols for i=1:n:rows if mod((j+cols*(i))/(rows*cols)*100,1)==0 waitbar((j+cols*(i))/(rows*cols)) end for x=1:n for y=1:n if Halftone(i+x,j+y,1)>=Kernel(x,y) oldpixel=Halftone(i+x,j+y,1); newpixel=255;

    Halftone(i+x,j+y,1)=newpixel; quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y,1)=Halftone(i+1+x,j+y,1)+7/16*quantizationError; Halftone(i-1+x,j+1+y,1)=Halftone(i-1+x,j+1+y,1)+3/16*quantizationError; Halftone(i+x,j+1+y,1)=Halftone(i+x,j+1+y,1)+5/16*quantizationError; Halftone(i+1+x,j+1+y,1)=Halftone(i+1+x,j+1+y,1)+1/16*quantizationError; else oldpixel=Halftone(i+x,j+y,1); newpixel=0; Halftone(i+x,j+y,1)=newpixel; quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y,1)=Halftone(i+1+x,j+y,1)+7/16*quantizationError;

  • 7/30/2019 Jon Carrier Digital Halftone Final

    20/20

    April 28, 2008 [DIGITAL HALFTONE (DITHERING) METHODS AND APPLICATIONS]

    xix | P a g e

    Halftone(i-1+x,j+1+y,1)=Halftone(i-1+x,j+1+y,1)+3/16*quantizationError; Halftone(i+x,j+1+y,1)=Halftone(i+x,j+1+y,1)+5/16*quantizationError; Halftone(i+1+x,j+1+y,1)=Halftone(i+1+x,j+1+y,1)+1/16*quantizationError; end if Halftone(i+x,j+y,2)>=Kernel(x,y) oldpixel=Halftone(i+x,j+y,2); newpixel=255; Halftone(i+x,j+y,2)=newpixel;

    quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y,2)=Halftone(i+1+x,j+y,2)+7/16*quantizationError; Halftone(i-1+x,j+1+y,2)=Halftone(i-1+x,j+1+y,2)+3/16*quantizationError; Halftone(i+x,j+1+y,2)=Halftone(i+x,j+1+y,2)+5/16*quantizationError; Halftone(i+1+x,j+1+y,2)=Halftone(i+1+x,j+1+y,2)+1/16*quantizationError; else oldpixel=Halftone(i+x,j+y,2); newpixel=0; Halftone(i+x,j+y,2)=newpixel; quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y,2)=Halftone(i+1+x,j+y,2)+7/16*quantizationError; Halftone(i-1+x,j+1+y,2)=Halftone(i-1+x,j+1+y,2)+3/16*quantizationError; Halftone(i+x,j+1+y,2)=Halftone(i+x,j+1+y,2)+5/16*quantizationError; Halftone(i+1+x,j+1+y,2)=Halftone(i+1+x,j+1+y,2)+1/16*quantizationError; end if Halftone(i+x,j+y,3)>=Kernel(x,y) oldpixel=Halftone(i+x,j+y,3);

    newpixel=255; Halftone(i+x,j+y,3)=newpixel; quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y,3)=Halftone(i+1+x,j+y,3)+7/16*quantizationError; Halftone(i-1+x,j+1+y,3)=Halftone(i-1+x,j+1+y,3)+3/16*quantizationError; Halftone(i+x,j+1+y,3)=Halftone(i+x,j+1+y,3)+5/16*quantizationError; Halftone(i+1+x,j+1+y,3)=Halftone(i+1+x,j+1+y,3)+1/16*quantizationError; else oldpixel=Halftone(i+x,j+y,3); newpixel=0; Halftone(i+x,j+y,3)=newpixel; quantizationError=oldpixel-newpixel; Halftone(i+1+x,j+y,3)=Halftone(i+1+x,j+y,3)+7/16*quantizationError; Halftone(i-1+x,j+1+y,3)=Halftone(i-1+x,j+1+y,3)+3/16*quantizationError; Halftone(i+x,j+1+y,3)=Halftone(i+x,j+1+y,3)+5/16*quantizationError; Halftone(i+1+x,j+1+y,3)=Halftone(i+1+x,j+1+y,3)+1/16*quantizationError; end

    end end end end figure(23) Halftone=Halftone(1:end-pad2,1:end-pad1,:); imshow(Halftone./255,color_map); JonCarrier_TightAxis( 'Image Fusion (Color)' ) end end toc end % ================================================================ %% Return to GUI % ================================================================ figure(10) Kernel

    close(h) disp( 'Done.' )