KR100790616B1 - Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead - Google Patents

Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead Download PDF

Info

Publication number
KR100790616B1
KR100790616B1 KR1020027015791A KR20027015791A KR100790616B1 KR 100790616 B1 KR100790616 B1 KR 100790616B1 KR 1020027015791 A KR1020027015791 A KR 1020027015791A KR 20027015791 A KR20027015791 A KR 20027015791A KR 100790616 B1 KR100790616 B1 KR 100790616B1
Authority
KR
South Korea
Prior art keywords
segments
overlap
adjacent
printhead
const
Prior art date
Application number
KR1020027015791A
Other languages
Korean (ko)
Other versions
KR20030024679A (en
Inventor
키아 실버브룩
폴 랩스턴
Original Assignee
실버브룩 리서치 피티와이 리미티드
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by 실버브룩 리서치 피티와이 리미티드 filed Critical 실버브룩 리서치 피티와이 리미티드
Priority to KR1020027015791A priority Critical patent/KR100790616B1/en
Publication of KR20030024679A publication Critical patent/KR20030024679A/en
Application granted granted Critical
Publication of KR100790616B1 publication Critical patent/KR100790616B1/en

Links

Images

Classifications

    • BPERFORMING OPERATIONS; TRANSPORTING
    • B41PRINTING; LINING MACHINES; TYPEWRITERS; STAMPS
    • B41JTYPEWRITERS; SELECTIVE PRINTING MECHANISMS, i.e. MECHANISMS PRINTING OTHERWISE THAN FROM A FORME; CORRECTION OF TYPOGRAPHICAL ERRORS
    • B41J2/00Typewriters or selective printing mechanisms characterised by the printing or marking process for which they are designed
    • B41J2/005Typewriters or selective printing mechanisms characterised by the printing or marking process for which they are designed characterised by bringing liquid or particles selectively into contact with a printing material
    • B41J2/01Ink jet
    • B41J2/135Nozzles
    • B41J2/145Arrangement thereof

Abstract

인접하는 오버랩된 세그먼트의 미스얼라인먼트로 인한 눈으로 인식할 수 있는 아티팩트를 저감하기 위해 페이지 폭 프린트헤드 시스템의 세그먼트간의 가변 오버랩을 보상하기 위한 방법 및 장치가 제공된다. 하나의 방법으로서는, 디더 매트릭스에서의 현재의 디더 값과 오버랩 신호를 합산하여 출력하는 합산수단을 채용하고, 상기 합산수단의 출력값은 비교기에 의해 입력 연속 톤 데이터 값과 비교되어 세그먼트의 오버랩 영역에서의 노즐을 제어하는 출력 보상 디더 값을 제공하게 된다. 다른 방법으로서는, 보상된 디더 매트릭스를 제공하기 위해 소프트웨어 프로그램을 이용한다. 감지 수단은 오버랩 신호를 생성하기 위해 세그먼트의 오버랩의 정도를 측정하여 측정값을 제공한다. 감지 수단은 세그먼트의 온도 또는 상대적인 위치를 감지하도록 할 수 있다. 오버랩의 정도는 다양한 온도에 대해 결정되어 ROM에 저장될 수 있다.A method and apparatus are provided for compensating for variable overlap between segments of a page width printhead system to reduce eye perceptible artifacts due to misalignment of adjacent overlapping segments. As one method, a summation means for summing and outputting an overlap signal with the current dither value in the dither matrix is employed, and the output value of the summation means is compared with the input continuous tone data value by a comparator to determine the overlapping area of the segment. It will provide an output compensation dither value that controls the nozzle. Alternatively, a software program is used to provide a compensated dither matrix. The sensing means measures the degree of overlap of the segments and provides a measurement to produce an overlap signal. The sensing means may be able to sense the temperature or relative position of the segment. The degree of overlap can be determined for various temperatures and stored in the ROM.

잉크젯, 디더 매트릭스, 오버랩, 보상, 프린트헤드, 도트.Inkjet, Dither Matrix, Overlap, Compensation, Printhead, Dots.

Description

드롭―온―디맨드형 프린트헤드에서의 시변 노즐 미스얼라인먼트의 보상 방법 및 장치{METHOD AND APPARATUS FOR COMPENSATION FOR TIME VARYING NOZZLE MISALIGNMENT IN A DROP ON DEMAND PRINTHEAD}METHOD AND APPARATUS FOR COMPENSATION FOR TIME VARYING NOZZLE MISALIGNMENT IN A DROP ON DEMAND PRINTHEAD}

본 발명은 잉크젯 프린팅에 관한 것으로서, 더욱 상세하게는 오버랩하는 세그먼트(overlapping segment)를 가지는 프린트헤드 조립체의 시변 노즐 미스얼라인먼트의 보상 방법 및 장치에 관한 것이다.The present invention relates to inkjet printing, and more particularly, to a method and apparatus for compensating time-varying nozzle misalignment of a printhead assembly having overlapping segments.

본 발명과 관련된 여러가지 방법, 시스템 및 장치가 본 출원과 동시에 본 출원인 또는 본 발명의 양수인에 의해 출원되어 계류중이며, 출원번호는 다음과 같다.Various methods, systems and apparatus related to the present invention are filed and pending by the present applicant or the assignee of the present invention simultaneously with the present application, and the application number is as follows.

PCT/AU00/00518, PCT/AU00/00519, PCT/AU00/00520, PCT/AU00/00521, PCT/AU00/00522, PCT/AU00/00523, PCT/AU00/00524, PCT/AU00/00525, PCT/AU00/00526, PCT/AU00/00527, PCT/AU00/00528, PCT/AU00/00529, PCT/AU00/00530, PCT/AU00/00531, PCT/AU00/00532, PCT/AU00/00533, PCT/AU00/00534, PCT/AU00/00535, PCT/AU00/00536, PCT/AU00/00537, PCT/AU00/00538, PCT/AU00/00539, PCT/AU00/00540, PCT/AU00/00541, PCT/AU00/00542, PCT/AU00/00543, PCT/AU00/00544, PCT/AU00/00545, PCT/AU00/00547, PCT/AU00/00546, PCT/AU00/00554, PCT/AU00/00556, PCT/AU00/00557, PCT/AU00/00558, PCT/AU00/00559, PCT/AU00/00560, PCT/AU00/00561, PCT/AU00/00562, PCT/AU00/00563, PCT/AU00/00564, PCT/AU00/00565, PCT/AU00/00566, PCT/AU00/00567, PCT/AU00/00568, PCT/AU00/00569, PCT/AU00/00570, PCT/AU00/00571, PCT/AU00/00572, PCT/AU00/00573, PCT/AU00/00574, PCT/AU00/00575, PCT/AU00/00576, PCT/AU00/00577, PCT/AU00/00578, PCT/AU00/00579, PCT/AU00/00581, PCT/AU00/00580, PCT/AU00/00582, PCT/AU00/00587, PCT/AU00/00588, PCT/AU00/00589, PCT/AU00/00583, PCT/AU00/00593, PCT/AU00/00590, PCT/AU00/00591, PCT/AU00/00592, PCT/AU00/00584, PCT/AU00/00585, PCT/AU00/00586, PCT/AU00/00594, PCT/AU00/00595, PCT/AU00/00596, PCT/AU00/00597, PCT/AU00/00598, PCT/AU00/00516, PCT/AU00/00517, PCT/AU00/00511, PCT/AU00/00501, PCT/AU00/00502, PCT/AU00/00503, PCT/AU00/00504, PCT/AU00/00505, PCT/AU00/00506, PCT/AU00/00507, PCT/AU00/00508, PCT/AU00/00509, PCT/AU00/00510, PCT/AU00/00512, PCT/AU00/00513, PCT/AU00/00514, PCT/AU00/00515.PCT / AU00 / 00518, PCT / AU00 / 00519, PCT / AU00 / 00520, PCT / AU00 / 00521, PCT / AU00 / 00522, PCT / AU00 / 00523, PCT / AU00 / 00524, PCT / AU00 / 00525, PCT / AU00 / 00526, PCT / AU00 / 00527, PCT / AU00 / 00528, PCT / AU00 / 00529, PCT / AU00 / 00530, PCT / AU00 / 00531, PCT / AU00 / 00532, PCT / AU00 / 00533, PCT / AU00 / 00534, PCT / AU00 / 00535, PCT / AU00 / 00536, PCT / AU00 / 00537, PCT / AU00 / 00538, PCT / AU00 / 00539, PCT / AU00 / 00540, PCT / AU00 / 00541, PCT / AU00 / 00542, PCT / AU00 / 00543, PCT / AU00 / 00544, PCT / AU00 / 00545, PCT / AU00 / 00547, PCT / AU00 / 00546, PCT / AU00 / 00554, PCT / AU00 / 00556, PCT / AU00 / 00557, PCT / AU00 / 00558, PCT / AU00 / 00559, PCT / AU00 / 00560, PCT / AU00 / 00561, PCT / AU00 / 00562, PCT / AU00 / 00563, PCT / AU00 / 00564, PCT / AU00 / 00565, PCT / AU00 / 00566, PCT / AU00 / 00567, PCT / AU00 / 00568, PCT / AU00 / 00569, PCT / AU00 / 00570, PCT / AU00 / 00571, PCT / AU00 / 00572, PCT / AU00 / 00573, PCT / AU00 / 00574, PCT / AU00 / 00575, PCT / AU00 / 00576, PCT / AU00 / 00577, PCT / AU00 / 00578, PCT / AU00 / 00579, PCT / AU00 / 00581, PCT / AU00 / 00580, PCT / AU00 / 00582, PCT / AU00 / 00587, PCT / AU00 / 00588, PCT / AU00 / 00589, PCT / AU00 / 00583, PCT / AU0 0/00593, PCT / AU00 / 00590, PCT / AU00 / 00591, PCT / AU00 / 00592, PCT / AU00 / 00584, PCT / AU00 / 00585, PCT / AU00 / 00586, PCT / AU00 / 00594, PCT / AU00 / 00595, PCT / AU00 / 00596, PCT / AU00 / 00597, PCT / AU00 / 00598, PCT / AU00 / 00516, PCT / AU00 / 00517, PCT / AU00 / 00511, PCT / AU00 / 00501, PCT / AU00 / 00502, PCT / AU00 / 00503, PCT / AU00 / 00504, PCT / AU00 / 00505, PCT / AU00 / 00506, PCT / AU00 / 00507, PCT / AU00 / 00508, PCT / AU00 / 00509, PCT / AU00 / 00510, PCT / AU00 / 00512, PCT / AU00 / 00513, PCT / AU00 / 00514, PCT / AU00 / 00515.

위 출원건들은 본 출원과 관련하여 상호 참고문헌으로서 참조된다.The above applications are referenced as cross-references in connection with the present application.

본 출원인의 다른 출원(PCT/AU98/00500)에는, 새로운 잉크 분사 메카니즘을 채용하여 페이지 폭을 가로질러 고속으로 인쇄하기 위한 일련의 잉크젯 프린팅 장치가 제안되어 있다. 그 장치는 모노리딕 구조의 일부분으로서 설치된 열 벤드 엑 추에이터(thermal bend actuator)를 이용하였다.In another Applicant's application (PCT / AU98 / 00500), a series of inkjet printing apparatuses for printing at high speed across a page width by employing a new ink ejection mechanism is proposed. The device used a thermal bend actuator installed as part of the monolithic structure.

그러한 장치에서는, 페이지 폭 드롭-온-디맨드형 프린트헤드에 적용하기 위해 더 큰 잉크젯 분사 노즐 어레이를 형성하는 것이 바람직하다. 바람직하게는, 매우 높은 해상도의 방울 크기가 요구된다. 예를 들면, 오프셋 프린팅과 같이 경쟁관계에 있는 일반적인 프린팅 시스템들은 1600dpi의 해상도를 허용한다. 그러므로, 예컨대, A4 페이지에 대해, 8인치의 폭을 가진 프린트헤드를 가지고 그 해상도로 인쇄하기 위해서는, 각 컬러마다 약 12800개의 잉크 분사 노즐이 필요하게 된다. 표준 4색으로 가정해도 약 51000개의 잉크 분사 노즐이 필요하게 된다. 표준 4색을 포함하여 고착제(fixative)와 적외선(IR) 잉크를 더하여 6가지 색으로 하면, 76800개의 잉크 분사 노즐이 필요하다는 결과가 된다. 불행히도, 실리콘 웨이퍼 기판과 같이 이음새없이 연속적인 세그먼트의 기판으로 대형 모노리딕 프린트헤드를 제조하는 것은 비현실적이다. 이것은 본질적으로 구조물 크기의 증가와 아울러 생산성의 실질적인 감소를 가져오기 때문이다. 생산성의 문제는 반도체 산업에서 잘 연구된 문제이고, 잉크젯 장치의 제조는 때때로 반도체 또는 이와 유사한 반도체 처리 기술을 이용한다. 특히, 그 분야는 Micro Electro Mechanical Systems(MEMS)로 널리 알려져 있다. MEMS 분야에 대한 연구는 Stom Picraux와 Paul J McWhorter의 1998년 11월 IEEE Spectrum 논문 "The Broad Sweep of Integrated Micro Systems"에서 다루어졌다.In such an apparatus, it is desirable to form a larger array of inkjet spray nozzles for application to a page width drop-on-demand printhead. Preferably, very high resolution droplet sizes are required. For example, competitive printing systems such as offset printing allow for 1600 dpi resolution. Therefore, for example, for an A4 page, to print at that resolution with a printhead that is 8 inches wide, about 12800 ink jetting nozzles are required for each color. Even assuming four standard colors, about 51000 ink jetting nozzles are required. Including six standard colors, plus fixed and infrared (IR) inks, six colors result in 76800 ink jetting nozzles. Unfortunately, it is impractical to manufacture large monolithic printheads with seamlessly continuous segments of substrate, such as silicon wafer substrates. This is inherently an increase in structure size and a substantial reduction in productivity. The problem of productivity is a well studied problem in the semiconductor industry, and the manufacture of inkjet devices sometimes uses semiconductors or similar semiconductor processing techniques. In particular, the field is widely known as Micro Electro Mechanical Systems (MEMS). A study in the field of MEMS was covered in Stom Picraux and Paul J McWhorter's November 1998 IEEE Spectrum paper "The Broad Sweep of Integrated Micro Systems."

높은 생산성의 유지라고 하는 문제에 대한 한가지 해결책은, 매우 긴 프린트헤드를 다수의 세그먼트로 제조하고, 그 세그먼트를 모두 인접하도록 하거나 오버 랩되도록 하는 것이다. 불행히도, 프린트헤드 장치에서 요구되는 극히 높은 피치의 잉크 분사 노즐은 인접한 프린트헤드 세그먼트와의 사이의 공간이 정상적인 작동상태에서 열 사이클의 존재하에서조차 매우 정확하게 제어되어야 한다는 것을 의미한다. 예를 들어, 1600dpi의 해상도를 얻기 위해서는, 노즐과 노즐간 간격이 약 16㎛이 되어야 한다.One solution to the problem of maintaining high productivity is to manufacture very long printheads in multiple segments and have all segments either contiguous or overlapping. Unfortunately, the extremely high pitch ink ejection nozzles required in the printhead device mean that the space between adjacent printhead segments must be controlled very accurately even in the presence of thermal cycles under normal operating conditions. For example, to obtain a resolution of 1600 dpi, the nozzle-to-nozzle spacing should be about 16 μm.

프린트헤드의 주변 상태와 작동 환경은 오버랩 영역에서 프린트헤드의 열 사이클링을 초래할 수 있고, 이것은 인접하는 프린트헤드 세그먼트간의 오버랩의 팽창과 수축을 야기하여 결국은 결과물인 출력이미지에 아티팩트를 발생시키게 된다. 예를 들어, 프린트헤드의 온도는 작동 중에 주변보다 25℃ 더 높이 올라갈 수 있다. 또한, 프린트헤드의 조립체는 프린트헤드 세그먼트와는 다른 열 특성을 가진 재료로 만들어 질 수 있고, 이것은 이들 부품들간에 서로 다른 열 팽창을 야기하게 된다. 실리콘 기판은 각각의 열팽창 계수가 2.6×10-6 및 20×10-6㎛/℃인 엘라스토머(elastomer) 내에 패키지될 수 있다.The ambient conditions and operating environment of the printhead can result in thermal cycling of the printhead in the overlap area, which causes expansion and contraction of the overlap between adjacent printhead segments, which in turn results in artifacts in the resulting output image. For example, the temperature of the printhead may rise 25 ° C. higher than the ambient during operation. In addition, the assembly of the printhead may be made of a material having a different thermal characteristic than the printhead segment, which causes different thermal expansion between these components. The silicon substrate may be packaged in an elastomer having a respective coefficient of thermal expansion of 2.6x10-6 and 20x10-6 μm / ° C.

아티팩트는 2진수 형태로 연속 톤 이미지를 나타내기 위한 프린트헤드의 제한된 해상도와 이미지에서 인접하는 도트의 색의 0.5% 차이를 감지하는 인간의 눈의 능력때문에 발생된다.Artifacts are caused by the limited resolution of the printhead to represent a continuous tone image in binary form and the human eye's ability to detect 0.5% difference in color of adjacent dots in the image.

본 발명의 목적은 동작 중에 오버랩하는 프린트헤드 세그먼트의 상대적 위치를 효과적이고 편리하게 보상하는 메카니즘을 제공하는 데에 있다. It is an object of the present invention to provide a mechanism that effectively and conveniently compensates for the relative position of overlapping printhead segments during operation.                 

본 발명의 제1 측면에 의하면, 오버랩하는 복수의 프린트헤드 세그먼트로 구성되고 인접하는 세그먼트간의 공간적 관계가 시간에 따라 가변하는 잉크 분사 프린트헤드에서, 오버랩된 세그먼트에서의 노즐의 분사를 제어하는 방법에 있어서, (a) 인접하는 프린트헤드 세그먼트간의 오버랩의 정도를 결정하는 단계와, (b) 상기 오버랩하는 세그먼트의 오버랩 영역에 있는 노즐에 대한 하프 토닝 패턴(half toning pattern)을 생성하는 단계와, (c) 상기 프린트헤드 세그먼트의 오버랩으로 인해 발생하는 아티팩트를 감소시키기 위해, 상기 하프 토닝 패턴을 상기 프린트헤드 세그먼트의 오버랩하는 영역에서의 상기 오버랩의 정도의 함수로서 조정하는 단계를 포함하여 이루어지는 노즐의 분사를 제어하는 방법이 제공된다.According to a first aspect of the present invention, there is provided a method for controlling ejection of nozzles from overlapping segments in an ink ejection printhead composed of a plurality of overlapping printhead segments and whose spatial relationship between adjacent segments varies with time. (A) determining the degree of overlap between adjacent printhead segments, (b) generating a half toning pattern for nozzles in the overlap region of the overlapping segments, ( c) adjusting the half toning pattern as a function of the degree of overlap in the overlapping area of the printhead segment to reduce artifacts caused by the overlap of the printhead segment. A method of controlling is provided.

바람직하게는, 오버랩의 정도를 결정하는 단계는 프린트헤드 세그먼트의 온도를 측정하는 것으로 한다. 하프 토닝 패턴은, 바람직하게는, 디더 매트릭스나 디더 볼륨에 의해 생성되고, 디더 매트릭스나 디더 볼륨을 이용하기 전에 현재의 연속 톤 픽셀 출력값에 오버랩 값을 더하도록 하는 변경이 가능하다. 온도를 측정하는 대신에, 각각의 세그먼트상의 기준 스트립(fiduciary strips)을 이용하고, 세그먼트간의 상대적인 움직임의 정도를 결정하기 위한 간섭측정법을 이용하여 거리를 측정하는 것으로 하여도 가능하다.Preferably, the step of determining the degree of overlap is to measure the temperature of the printhead segment. The half toning pattern is preferably generated by a dither matrix or dither volume, and is changeable to add an overlap value to the current continuous tone pixel output value before using the dither matrix or dither volume. Instead of measuring the temperature, it is also possible to use the fiduciary strips on each segment and to measure the distance using interferometry to determine the relative degree of movement between the segments.

본 발명의 다른 측면에 따르면, 공간적으로 떨어져 있으면서 공간적으로 오버랩하는 복수의 프린트헤드 세그먼트와, 인접하는 프린트헤드 세그먼트간의 오버랩의 정도를 측정하기 위한 적어도 하나의 수단과, 연속 톤 이미지의 하프 토닝을 제공하기 위한 수단과, 인접하는 프린트헤드 세그먼트간의 아티팩트를 저감하기 위 해 상기 인접하는 세그먼트간의 오버랩 영역에서 상기 하프 토닝 수단을 조정하는 수단을 포함하여 이루어지는 잉크 분사 프린트헤드 시스템이 제공된다.According to another aspect of the present invention, there is provided a plurality of spatially spaced and overlapping printhead segments, at least one means for measuring the degree of overlap between adjacent printhead segments, and half toning of continuous tone images. And means for adjusting said half toning means in the overlap area between said adjacent segments to reduce artifacts between adjacent printhead segments.

하프 토닝 수단을 조정하기 위한 수단은 연속 톤 입력, 공간적 오버랩 입력 및 이진 입력을 포함할 수 있고, 하프 토닝 수단은 공간적 오버랩 입력을 이용하여 연속 톤 입력을 변경시킴으로써, 프린트헤드 세그먼트의 오버랩 영역에 대해 조정을 위한 출력 이진값을 생성하도록 디더 매트릭스나 디더 볼륨의 순람표(look-up table)에서 이용할 변경된 연속 톤 입력을 생성한다. 하프 톤이나 디더 매트릭스를 조정하기 위한 수단은 하드웨어적으로 실현될 수도 있고, 알고리즘을 채용한 소프트웨어의 수단으로 실현될 수도 있다.Means for adjusting the half toning means may include continuous tone inputs, spatial overlap inputs and binary inputs, and the half toning means may use the spatial overlap inputs to change the continuous tone inputs, thereby overlapping the overlap area of the printhead segment. Generate modified continuous tone inputs to be used in the dither matrix or look-up table of the dither volume to generate output binary values for adjustment. Means for adjusting halftones or dither matrices may be realized in hardware or by means of software employing an algorithm.

본 발명은 청구범위에 의해 특정된다. 상술한 본 발명의 장점 및 그 외의 장점은 첨부도면과 함께 아래의 설명을 참조하여 보다 명백해 질 것이다.The invention is specified by the claims. The above and other advantages of the present invention will become more apparent with reference to the following description in conjunction with the accompanying drawings.

도 1은 본 발명에 따른 인접하는 한 쌍의 프린트헤드 세그먼트를 개략적으로 도시한 구성도,1 is a schematic diagram illustrating a pair of adjacent printhead segments in accordance with the present invention;

도 2는 도 1에 도시된 인접하는 프린트헤드 세그먼트로부터 도트를 인쇄하기 위한 과정을 나타내는 도면,FIG. 2 is a diagram showing a process for printing dots from adjacent printhead segments shown in FIG. 1;

도 3은 본 발명에 따른 인접하는 프린트헤드간의 도트를 혼합하는 과정을 나타내는 도면,3 is a view showing a process of mixing dots between adjacent printheads according to the present invention;

도 4는 본 발명의 실시예에 따라 디더 매트릭스의 가변 제어 과정을 나타내는 도면, 4 is a view showing a variable control process of a dither matrix according to an embodiment of the present invention;                 

도 5는 본 발명의 다른 실시예에 따라 디더 매트릭스의 가변 제어 과정을 나타내는 도면,5 is a view showing a variable control process of a dither matrix according to another embodiment of the present invention;

도 6은 본 발명의 또 다른 실시예에 따라 디더 매트릭스의 가변 제어 과정을 실행하는 알고리즘을 도식적으로 나타내는 도면이다.6 is a diagram schematically showing an algorithm for executing a variable control process of a dither matrix according to another embodiment of the present invention.

제1 실시예에서는, 인접하는 세그먼트간의 오버랩을 조정하기 위해 디지털 프로세싱 메카니즘을 이용하여 온도에 따라 가변하는 인접하는 프린트헤드 세그먼트의 상대적인 이동을 보상하는 방법이 제공된다.In a first embodiment, a method is provided for compensating for relative movement of adjacent printhead segments that vary with temperature using digital processing mechanisms to adjust overlap between adjacent segments.

A4 페이지 폭을 커버하는 프린트헤드의 경우에 10개의 세그먼트가 9개의 오버랩 부분을 가지고 엇걸린 짝으로 반복 배열될 것이다. 세그먼트들의 초기 얼라인먼트는 모노리딕 제조기술(monolithic fabrication techniques) 분야에서 잘 알려진 기술을 이용하여 10㎛ 이내로 만들 수 있다. 6색 잉크 장치에서의 하나의 세그먼트의 폭은, 세그먼트의 노즐이 세로로 지그재그 패턴으로 각각의 중심에서 16㎛ 간격으로 배치되어 있다고 가정할 때, 약 225㎛가 된다.In the case of a printhead covering an A4 page width, ten segments will be arranged in staggered pairs with nine overlapping portions. Initial alignment of the segments can be made within 10 μm using techniques well known in the art of monolithic fabrication techniques. The width of one segment in the six-color ink apparatus is about 225 µm, assuming that the nozzles of the segments are arranged at intervals of 16 µm from each center in a vertical zigzag pattern.

본 실시예에서, 온도센서는 각각의 프린트헤드 세그먼트의 현재의 열특성을 측정하기 위해 각 프린트헤드에 배치된다. 현재의 온도를 측정한 값은 인접하는 프린트헤드 세그먼트간의 오버랩의 양을 결정하는 데에 이용될 수 있다.In this embodiment, a temperature sensor is placed on each printhead to measure the current thermal characteristics of each printhead segment. The current temperature measurement can be used to determine the amount of overlap between adjacent printhead segments.

다르게는, 프린트헤드의 세그먼트들이 물리적 특성 및 반응이 서로 충분히 유사하고, 각 쌍의 오버랩된 세그먼트의 주변 환경이 실질적으로 같다고 가정할 수 있다면, 하나의 온도센서만 이용하는 것도 가능하다. Alternatively, if one can assume that the segments of the printhead are sufficiently similar in physical properties and response to each other and the surrounding environment of each pair of overlapped segments is substantially the same, it is also possible to use only one temperature sensor.                 

오버랩의 정도는 인접하는 프린트헤드 세그먼트간의 하프 토닝을 제어하기 위한 메카니즘을 제공하는 데에 이용된다. 본 발명에서의 이미지의 출력은 종래기술로서 잘 알려진 방법이나 기술을 채용한 디지털 하프 토닝에 의하는 것으로 가정한다. 많은 다른 하프 토닝 기술이 이용될 수 있고, MIT 출판부에서 발행한 Ulichney의 "Digital Half Toning"이라는 논문을 참조할 수 있다.The degree of overlap is used to provide a mechanism for controlling half toning between adjacent printhead segments. The output of the image in the present invention is assumed to be by digital half toning employing a method or technique well known in the art. Many other half toning techniques can be used, and can be found in Ulichney's paper, "Digital Half Toning," published by MIT Publishing.

도 1에 도시된 바와 같이, 인접하는 프린트헤드 세그먼트(2,3)가 각각의 영역(12,13)에서 오버랩한다. 오버랩 영역이 약 40thou(~1mm)로 확장하면서 1600dpi의 해상도를 위해 16㎛의 간격으로 떨어져 있는 64개 노즐의 오버랩이 나타난다. 세그먼트(2)의 영역(10)에서는 이 세그먼트의 노즐들이 잉크 분사에 전용된다. 마찬가지로, 세그먼트(3)의 영역(11)에서는 이 세그먼트의 노즐들이 잉크 분사에 전용된다. 오버랩하는 영역(12,13)에서는, 2개의 프린트헤드 세그먼트(2,3)간의 '혼합'이 이루어지는데, 예컨대 에지(14)를 따라서는 프린트헤드 세그먼트(2)의 노즐들이 영역(12)에서 인쇄에 전용되고, 마찬가지로 에지(15)를 따라서는 세그먼트(3)의 노즐들이 인쇄를 위해 거의 전용되는 식이다. 그 사이에서는, 합성(interpolation)(선형적일 수도 그렇지 않을 수도 있다)이 이 두 에지의 사이에서 행해된다. 따라서, 도 2에 도시된 바와 같이, 한 페이지에 풀 컬러(full color) 출력물을 인쇄할 때, 한쪽의 영역(17)은 프린트헤드 세그먼트(10)에 의해 전용적으로 인쇄되고, 다른쪽의 영역(18)은 프린트헤드 세그먼트(11)(검은색 도트로 표시되어 있다)에 의해 전용적으로 인쇄되며, 영역(19)은 두 세그먼트의 노즐들의 혼합으로 이루어진다. 인쇄 처리과정은 앞서 언급한 참고문헌에 개시되어 있는 것과 같은 하프 토닝 매트릭스로서 잘 알려진 어떠한 것이어도 좋다. 이미 알려진 하프 토닝 매트릭스가 이용되더라도, 실제 이용되는 프린트헤드 세그먼트는 오버랩하는 세그먼트들간의 오버랩 정도를 측정함으로써 얻어지는 혼합 비율에 의존할 것이다.As shown in FIG. 1, adjacent printhead segments 2, 3 overlap in each region 12, 13. Overlap area extends to about 40 tons (~ 1 mm) with overlap of 64 nozzles spaced at intervals of 16 μm for a resolution of 1600 dpi. In the region 10 of the segment 2, the nozzles of this segment are dedicated to ink jetting. Similarly, in the region 11 of the segment 3, the nozzles of this segment are dedicated to ink jetting. In the overlapping areas 12, 13, 'mixing' between the two printhead segments 2, 3 occurs, for example along the edge 14 the nozzles of the printhead segment 2 are in the area 12. Dedicated to printing, and likewise along the edge 15 the nozzles of the segment 3 are almost dedicated for printing. In the meantime, interpolation (which may or may not be linear) is performed between these two edges. Thus, as shown in FIG. 2, when printing a full color output on one page, one area 17 is printed exclusively by the printhead segment 10, and the other area. 18 is exclusively printed by printhead segment 11 (indicated by black dots), and region 19 consists of a mixture of nozzles of two segments. The print process may be any well known as half toning matrix as disclosed in the aforementioned references. Even if a known half-toning matrix is used, the actual printhead segment will depend on the blending ratio obtained by measuring the degree of overlap between the overlapping segments.

그러한 방법 중 하나가 도 3에 도시되어 있다. 도 3에서는 오버랩된 영역 내에서의 선형적 보간(interpolation)을 보여주고 있다. 에지(14)에서 오버랩된 부분(12)에 대응하는 영역에서는 프린트헤드 세그먼트(2)의 노즐을 100% 이용하고, 같은 영역에서 프린트헤드 세그먼트(3)의 에지(7)에서는 출력이 없다. 세그먼트(2)의 에지(14)에서 세그먼트(3)의 에지(15)로 갈수록 영역(12)의 노즐의 이용비율은 점차적으로 감소(선형적으로)하여 에지(9)에서는 0(zero)이 된다. 한편, 영역(13)의 노즐의 이용비율은 에지(15)에 도달할 때까지 균일하게 점진적으로 증가한다. 노즐들간의 오버랩이 증가하는 제1 실시예에서는, 오버랩 영역에서 하프 토닝 드레시홀드(half toning thresholds)가 증가한다. 이것은 혼합 영역에서 인쇄되는 도트의 수를 감소시킨다. 역으로, 프린트헤드 세그먼트가 일반적으로 허용되는 것보다 좀더 이격됨으로써 오버랩이 감소한다면, 도트 빈도(dots frequency)는 하프 토닝 드레시홀드를 감소시킴으로써 증가될 수 있다.One such method is shown in FIG. 3. 3 shows linear interpolation in the overlapped area. In the region corresponding to the overlapped portion 12 at the edge 14, the nozzle of the printhead segment 2 is used 100%, and there is no output at the edge 7 of the printhead segment 3 in the same region. As the edge 14 of the segment 2 goes from the edge 15 of the segment 3 to the edge 15 of the segment 3, the utilization ratio of the nozzles of the region 12 gradually decreases (linearly) so that zero (0) at the edge 9 is reduced. do. On the other hand, the utilization rate of the nozzle in the area 13 increases uniformly and gradually until it reaches the edge 15. In the first embodiment where the overlap between the nozzles increases, half toning thresholds increase in the overlap area. This reduces the number of dots printed in the mixed area. Conversely, if the overlap is reduced by allowing the printhead segments to be more spaced apart than generally allowed, the dots frequency can be increased by reducing the half toning threshold.

도 4에는 하프 토닝 장치가 되시되어 있다. 여기서의 하프 토닝 장치는 현재의 디더값(dither value)(26)을 합산수단(summation means)(27)으로 출력하는 디더 매트릭스(dither matrix)(25)를 가지고, 여기서의 합산수단(27)은 인접하는 세그먼트간의 오버랩의 정도에 따라 포지티브 또는 네가티브로 변하는 오버랩 신호를 또 다른 입력(28)으로 받는다. 비교기(30)는 합산수단 또는 가산기(27)의 출력값(29)을 입력되는 연속 톤 데이터(32)와 비교하여 하프 톤 데이터(31)를 출력한다. 다르게는, 디더링(dithering) 전에 연속 톤 데이터(29)로부터 데이터값(28)을 빼도록 구성한 장치도 유사한 결과를 나타내게 된다. 이 장치가 도 5에 도시되어 있다.A half toning device is shown in FIG. The half toning apparatus here has a dither matrix 25 which outputs the current dither value 26 to the summation means 27, where the summation means 27 Another input 28 is received with an overlap signal that changes positive or negative depending on the degree of overlap between adjacent segments. The comparator 30 outputs the half tone data 31 by comparing the output value 29 of the adder or adder 27 with the input continuous tone data 32. Alternatively, a device configured to subtract the data value 28 from the continuous tone data 29 before dithering will show similar results. This apparatus is shown in FIG.

도 5에 도시된 바와 같이, 출력되는 하프 톤 데이터(52)는, 가산기(46)에 의해 디더 매트릭스(40)의 출력(42)과 오버랩 신호(44)를 더한 다음, 감산기(50)에 의해 가산기(46)의 출력(54)과 연속 톤 데이터(48)의 차를 얻음으로써 생성될 수 있다. 이것은 도 4의 장치와 등가이다.As shown in FIG. 5, the output halftone data 52 is added by the adder 46 by the output 42 of the dither matrix 40 and the overlap signal 44, and then by the subtractor 50. Can be generated by obtaining the difference between the output 54 of the adder 46 and the continuous tone data 48. This is equivalent to the device of FIG. 4.

도 3 및 도 4에 의해 설명한 것과 같은 장치를 이용함으로써, 인접하는 프린트헤드 세그먼트간의 줄무늬 아티팩트의 발생을 저감하기 위한 오버랩 혼합의 제어가 어느 정도 가능하게 된다.By using the apparatus as described with reference to Figs. 3 and 4, it is possible to some extent control the overlap mixing to reduce the occurrence of streaking artifacts between adjacent print head segments.

각각의 오버랩 신호(28)는 교정 계수(calibration factor)와 곱해지거나 교정 오프셋 계수(calibration offset factor)가 더해질 수 있으므로, 인접하는 프린트헤드 세그먼트의 위치의 정확도도 매우 효과적으로 감소할 수 있다. 따라서, 인접하는 프린트헤드 세그먼트는 제조시에는 서로 대략적으로 배치될 수 있다. 그런 다음, 인접하는 세그먼트의 노즐들 사이의 오버랩의 정도를 결정하기 위해 알려진 온도에서 테스트 패턴을 인쇄할 수 있다. 일단 특정의 온도범위에서 오버랩의 정도가 결정되면, 일련의 대응하는 값은 프린트헤드 세그먼트 오버랩에 개별적으로 적용되는 모든 오프셋 값을 프로그래머블 ROM 저장장치에 기록하여 요청이 있는 때에 언제든 제공하도록 할 수 있다. Since each overlap signal 28 can be multiplied by a calibration factor or added with a calibration offset factor, the accuracy of the position of adjacent printhead segments can also be very effectively reduced. Thus, adjacent printhead segments can be roughly disposed with one another during manufacture. The test pattern can then be printed at a known temperature to determine the degree of overlap between the nozzles of adjacent segments. Once the degree of overlap in a particular temperature range has been determined, a series of corresponding values can be written to the programmable ROM storage to provide all the offset values that apply individually to the printhead segment overlap so that they are available at any time.                 

본 발명의 다른 실시예는 프린트헤드의 오버랩된 세그먼트들 사이에서의 아티팩트의 발생을 저감하기 위해 소프트웨어 솔루션을 이용한다. 프린트헤드 세그먼트들간의 가변적인 오버랩을 조정하기 위한 알고리즘의 구현을 포함하는 디더 매트릭스의 전체 소프트웨어 구현이 아래에 첨부되어 있다. 이 프로그램은 C언어로 작성되어 있다. 이 알고리즘은 해당 분야의 당업자가 그 지식의 범위 내에서 변경을 가하여 다른 코드로 작성할 수도 있다. 이 알고리즘에 담겨있는 기술적 배경을 아래에서 설명하겠다.Another embodiment of the present invention utilizes a software solution to reduce the occurrence of artifacts between overlapped segments of the printhead. A full software implementation of the dither matrix is included below, including the implementation of an algorithm for coordinating variable overlap between printhead segments. This program is written in C language. The algorithm may be written in other code by those skilled in the art with modifications within the scope of the knowledge. The technical background behind this algorithm is described below.

분산 도트 확률적 디더링(dispersed dot stochastic dithering)이 2-레벨 도트를 이용하여 연속 톤 픽셀값을 재생하는 데에 이용된다. 분산 도트 디더링은 높은 공간 빈도, 즉 이미지 상세를 거의 도트 해상도의 한계로 재생하고, 한편으로는 이와 동시에 눈에 의해 공간적으로 집중된 때 풀 강도 깊이(full intensity depth)로 더 낮은 공간 빈도를 재생한다. 확률적 디더 매트릭스는 페이지를 가로질러 메워질 때 바람직하지 않은 낮은 빈도 패턴이 없도록 설계된다.Dispersed dot stochastic dithering is used to reproduce continuous tone pixel values using two-level dots. Dispersive dot dithering reproduces high spatial frequencies, i.e., image details to a near limit of dot resolution, while simultaneously reproducing lower spatial frequencies at full intensity depth when spatially concentrated by the eye. Probabilistic dither matrices are designed such that there are no undesirable low frequency patterns when filled across the page.

도트 오버랩은 도트 게인(dot gain) 기술을 이용하여 설계될 수 있다. 도트 게인은 도트 패턴의 이상적인 강도부터 패턴이 인쇄될 때 나타나는 실제의 강도까지의 증가에 의존한다. 잉크젯 프린팅에서, 도트 게인은 잉크 번짐에 의해 주로 문제된다. 번짐은 잉크 및 인쇄 매체의 특성에 의한 기능 그 자체이다. 피그먼트 잉크(pigmented ink)는 표면에서 번질 수는 있어도 매체 내부로 멀리 확산되지는 않는다. 염료 잉크는 매체 내부로 셀룰로오스 섬유를 따라 확산할 수 있다. 번짐을 저감하기 위해 표면 코팅이 이용될 수 있다. Dot overlap can be designed using dot gain technology. The dot gain depends on the increase from the ideal intensity of the dot pattern to the actual intensity that appears when the pattern is printed. In inkjet printing, dot gain is mainly a problem by ink bleeding. Smear is a function itself by the characteristics of the ink and the print media. Pigmented ink may bleed off the surface but does not diffuse far into the medium. The dye ink can diffuse along the cellulose fiber into the medium. Surface coatings can be used to reduce bleeding.                 

도트 게인과 마찬가지로 도트 오버랩의 효과도 도트의 분포에 민감하기 때문에, 오버랩없이 페이지를 완벽하게 메우는 이상적인 도트로 모델링하는 것이 유용한다. 실제 잉크젯 도트는 거의 둥글고 이웃하는 도트와 오버랩되지만, 이상적인 도트는 사각형으로 모델링할 수 있다. 그래서, 이상적인 도트 및 실제의 도트는 도트 게인 파라미터가 된다.Like dot gain, the effect of dot overlap is sensitive to the distribution of dots, so it is useful to model it as an ideal dot that completely fills the page without overlap. Actual inkjet dots are almost round and overlap with neighboring dots, but ideal dots can be modeled as squares. Thus, the ideal dot and the actual dot become dot gain parameters.

도트 게인은 에지 효과(edge effect), 즉 인쇄된 도트와 인접하는 인쇄되지 않은 영역 사이에서의 테두리를 따라 나타나는 효과이다. 도트 게인은 도트 패턴의 에지 링크와 도트 패턴의 영역과의 비율에 비례한다. 도트 게인에 관한 두가지 기술에는 분산 도트 디더링(dispersed dot dithering)과 클러스터 도트 디더링(clustered dot dithering)이 있다. 분산 도트 디더링에서는, 도트는 영역에 균일하게 분배된다. 예컨대, 50% 강도의 도트에서 체커판 패턴(chequer board pattern)이 이용된다. 클러스터 도트 디더링에서, 도트는 중심부의 '색깔이 있는' 영역과 '색깔이 없는' 테두리로 나타내어 지는데, '색깔이 없는' 영역에 대한 '색깔이 있는' 영역의 비율은 인쇄될 도트의 강도와 같다. 그러므로, 분산 도트 디더링이 클러스터 도트 디더링보다 도트 게인에 보다 민감하다.Dot gain is an edge effect, that is, an effect that appears along the border between printed dots and adjacent unprinted areas. The dot gain is proportional to the ratio of the edge link of the dot pattern to the area of the dot pattern. Two techniques for dot gain are distributed dot dithering and clustered dot dithering. In distributed dot dithering, the dots are distributed evenly over the area. For example, a checker board pattern is used in dots of 50% intensity. In cluster dot dithering, dots are represented by a 'colored' area and a 'colorless' border at the center, where the ratio of the 'colored' area to the 'colorless' area is equal to the intensity of the dots to be printed. . Therefore, distributed dot dithering is more sensitive to dot gain than cluster dot dithering.

두개의 인접하는 프린트헤드 세그먼트는 수많은 오버랩하는 노즐들을 가진다. 일반적으로, 인접하는 세그먼트의 대응하는 노즐들간의 완벽한 정합은 없을 것이다. 국부적인 레벨에서는 노즐 간격의 ±절반의 부정합이 있을 수 있는데, 이것은 1600dpi에서 ±8㎛ 정도이다. 보다 높은 레벨에서는, 오버랩하는 노즐의 수가 실제적으로 변할 수 있다. Two adjacent printhead segments have numerous overlapping nozzles. In general, there will be no perfect match between corresponding nozzles of adjacent segments. At the local level, there may be ± half mismatch of nozzle spacing, which is about 8 μm at 1600 dpi. At higher levels, the number of overlapping nozzles may actually vary.                 

어느 한 세그먼트에서 다른 세그먼트까지 또 오버랩 브리지를 가로질러 출력을 부드럽게 혼합하는 제1 접근법은 오버랩 영역을 가로질러 하나의 세그먼트에서 다른 하나의 세그먼트로 두개의 세그먼트에 입력되는 연속 톤을 혼합하는 것으로 이루어진다. 오버랩 영역을 가로지르는 출력 처리과정으로서, 제2 세그먼트는 정비례하는 연속 톤 값을 받고, 이에 대응하여 제1 세그먼트는 도 3에서 상술한 바와 같이 반비례하는 값을 받는다. 선형적인 또는 더 높은 차수의 보간이 이용될 수 있다. 두개의 세그먼트를 통한 출력을 디더(dither)하기 위해 사용되는 디더 매트릭스는 노즐 레벨에서 정합된다.The first approach of smoothly mixing the output from one segment to another and across the overlap bridge consists of mixing the continuous tones input to the two segments from one segment to another across the overlap area. As an output process across the overlap region, the second segment receives a continuous tone value that is directly proportional, and correspondingly the first segment receives a value that is inversely proportional to that described above in FIG. 3. Linear or higher order interpolation may be used. The dither matrix used to dither the output through the two segments is matched at the nozzle level.

제1 접근법은 두가지 결점을 가지고 있다. 먼저, 특정의 도트 위치에서 디더 드레시홀드가 두 세그먼트의 보간된 연속 톤 값보다 작으면, 두 세그먼트는 그 위치에 대해 도트를 생성할 것이다. 두개의 도트가 오버랩하기 때문에, 두 디더 매트릭스에 의해 정해지는 강도는 부분적으로만 재생될 것이고, 이것은 전체적인 강도의 손실을 가져올 것이다. 이것은 대응하는 두 노즐이 하나의 도트를 생산하지 않도록 함으로써 해결할 수 있다. 이것은 상대의 세그먼트에 대한 디더 매트릭스의 역을 이용하거나, 단일 디더 매트릭스를 통해 연속 톤 값을 디더링한 후, 현재의 보간 계수에 의해 주어지는 확률에 따라, 확률적으로 어느 하나 또는 다른 하나의 노즐에 출력 도트를 할당함으로써 해결될 수 있다.The first approach has two drawbacks. First, if the dither threshold at a particular dot position is less than the interpolated continuous tone value of the two segments, the two segments will generate dots for that position. Since the two dots overlap, the intensity determined by the two dither matrices will only be partially reproduced, which will result in a loss of overall intensity. This can be solved by ensuring that two corresponding nozzles do not produce one dot. This is either using the inverse of the dither matrix for the opponent's segment, or dithering the continuous tone values through a single dither matrix, and then probably outputting either one or the other nozzle, depending on the probability given by the current interpolation coefficients. This can be solved by assigning dots.

두번째 결점으로는, 다른 세그먼트에 의해 인쇄된 이웃하는 도트들은 다시 오버랩하여 전체적인 강도의 손실을 가져온다.As a second drawback, neighboring dots printed by other segments overlap again, resulting in a loss of overall intensity.

도 6에 도시된 바와 같이, 각각의 오버랩된 세그먼트의 값은 0.0과 1.0 사이 의 값으로서 수평선(60, 62)을 따라 각각 VA 및 VB로 나타난다. 계산된 출력(66)은 0.0~1.0 범위의 값으로서 수직선(64)에 대해 함수 IA+B로 나타나 있다. 컨투어 평면(68)은 IA+B=0.5에 대한 결과값을 보여준다.As shown in FIG. 6, the value of each overlapped segment is represented by V A and V B along horizontal lines 60 and 62 as values between 0.0 and 1.0, respectively. The calculated output 66 is represented by the function I A + B for the vertical line 64 as a value in the range 0.0-1.0. Contour plane 68 shows the result for I A + B = 0.5.

도 6은 두 세그먼트의 입력 연속 톤 값 VA 및 VB를 관측된 출력 강도 IA+B로 연결하는 3차원 함수의 성질 형상을 나타낸다. 제1 접근법에서는, 입력되는 연속 톤 값 V와 보간 계수 f로부터 VA=(1-f)V 및 VB=fV를 얻는다. 보간 계수가 0.5에 가까워 질수록 입력되는 연속 톤 값과 관측된 출력 강도와의 차이는 커진다. V=10인 경우가 도 6에서 수직선 VA+VB=1.0인 평면에 곡선(200)으로 나타나 있다. 분명히 이 곡선은 함수 표면에 있다. 도 6은, 어떤 종류의 혼합이 일어나면(즉 0.0<f<1.0), 출력 강도는 감소하고, 원하는 출력 강도를 달성하기 위해서는, 두 세그먼트의 입력값의 합이 의도한 출력값을 초과하여야 한다(즉, VA+VB>V)는 것을 보여준다. 이것은 아래 첨부의 알고리즘을 위한 기초이다.FIG. 6 shows the property shape of a three-dimensional function connecting the input continuous tone values V A and V B of two segments to the observed output intensities I A + B. In the first approach, V A = (1-f) V and V B = fV are obtained from the input continuous tone value V and the interpolation coefficient f. As the interpolation coefficient approaches 0.5, the difference between the input continuous tone value and the observed output intensity increases. The case where V = 10 is shown by the curve 200 in the plane of the vertical line V A + V B = 1.0 in FIG. 6. Obviously this curve is on the function surface. 6 shows that if some kind of mixing occurs (i.e. 0.0 <f <1.0), the output intensity is reduced and the sum of the input values of the two segments must exceed the intended output value (ie, to achieve the desired output intensity). , V A + V B > V). This is the basis for the algorithm attached below.

그 함수는, 오직 하나의 세그먼트가 출력에 기여할 때(즉, f=0.0 또는 f=1.0), 선형적 응답을 보여준다. 이것은 물론 디더 매트릭스가 도트 게인의 효과를 포함한다고 가정한 것이다.The function shows a linear response when only one segment contributes to the output (ie f = 0.0 or f = 1.0). This, of course, assumes that the dither matrix includes the effect of dot gain.

앞서 상술한 것은 본 발명의 특정 실시예에 한정된 것이다. 본 발명의 몇몇 또는 모든 특징을 포함하면서 본 발명에 변경 또는 수정을 가할 수 있다는 것은 자명하다. 예컨대, 본 발명은 적절히 프로그램된 디지털 데이터 프로세싱 시스템에 하드웨어나 소프트웨어로서 구현될 수 있는데, 양자 모두 각 분야에서 통상의 지식을 가진자에 의해 용이하게 이루어질 수 있다. 따라서, 본 출원의 청구범위는 본 발명의 기술적 사상과 권리범위의 범위내에서 이루어지는 모든 변경과 수정을 포함한다.What has been described above is limited to specific embodiments of the present invention. It is apparent that changes or modifications can be made to the present invention while including some or all features of the present invention. For example, the present invention may be implemented as hardware or software in a properly programmed digital data processing system, both of which may be readily made by those skilled in the art. Accordingly, the claims of the present application include all changes and modifications made within the scope of the spirit and scope of the present invention.

(본 발명을 구현한 프로그램의 일례)(Example of a program implementing the present invention)

staticstatic

voidvoid

ObtainMisregistrationTransferFunctionObtainMisregistrationTransferFunction

((

int dotsPerPixel,int dotsPerPixel,

int subdotsPerDot,int subdotsPerDot,

BI_Image const& dotImage,BI_Image const & dotImage,

char const* pDotImageName,char const * pDotImageName,

char const* pRefDotImageName,char const * pRefDotImageName,

int const overlapSize,int const overlapSize,

int const overlapIndex, // 0 .. overlapSize-1int const overlapIndex, // 0 .. overlapSize-1

int const misregFactor,int const misregFactor,

BI_Image const& ditherMatrix,BI_Image const & ditherMatrix,

BI_LUT& lutv,BI_LUT & lutv,

BI_LUT& lut0, BI_LUT & lut0,                 

BI_LUT& lut1BI_LUT & lut1

);
);

class RLE_DotLineclass RLE_DotLine

{{

public:public:

RLE_DotLine()RLE_DotLine ()

: m_whiteRun(0), m_blackRun(0) {}: m_whiteRun (0), m_blackRun (0) {}

RLE_DotLine(int whiteRun, int blackRun)RLE_DotLine (int whiteRun, int blackRun)

: m_whiteRun(whiteRun), m_blackRun(blackRun) {}: m_whiteRun (whiteRun), m_blackRun (blackRun) {}

int WhiteRun() const { return m_whiteRun; }int WhiteRun () const {return m_whiteRun; }

int BlackRun() const { return m_blackRun; }
int BlackRun () const {return m_blackRun; }

private:private:

int m_whiteRun;int m_whiteRun;

int m_blackRun;int m_blackRun;

};};

typedef vector<RLE_DotLine, allocator<RLE_DotLine> > RLE_Dot;
typedef vector <RLE_DotLine, allocator <RLE_DotLine>>RLE_Dot;

static static                 

voidvoid

Usage()Usage ()

{{

fprintf(stderr, "usage: SegmentDither\n");fprintf (stderr, "usage: SegmentDither \ n");

fprintf(stderr, " inputImage\n");fprintf (stderr, "inputImage \ n");

fprintf(stderr, " dotsPerPixel\n");fprintf (stderr, "dotPerPixel \ n");

fprintf(stderr, " subdotsPerDot\n");fprintf (stderr, "subdotsPerDot \ n");

fprintf(stderr, " dotImage\n");fprintf (stderr, "dotImage \ n");

fprintf(stderr, " refDotImage\n");fprintf (stderr, "refDotImage \ n");

fprintf(stderr, " overlapCenter\n");fprintf (stderr, "overlapCenter \ n");

fprintf(stderr, " overlapSize\n");fprintf (stderr, "overlapSize \ n");

fprintf(stderr, " misregFactor\n");fprintf (stderr, "misregFactor \ n");

fprintf(stderr, " ditherMatrix\n");fprintf (stderr, "ditherMatrix \ n");

fprintf(stderr, " outputImage\n");fprintf (stderr, "outputImage \ n");

fprintf(stderr, " outputResolution\n");fprintf (stderr, "outputResolution \ n");

exit(1);exit (1);

}
}

staticstatic

void void                 

BadArgument(char const* pErrorMsg)BadArgument (char const * pErrorMsg)

{{

fprintf(stderr, "SegmentDither: argument error: %s\n", pErrorMsg);fprintf (stderr, "SegmentDither: argument error:% s \ n", pErrorMsg);

exit(1);exit (1);

}
}

#define CHECK_ARGUMENT(cond) if (cond) BadArgument(#cond)
#define CHECK_ARGUMENT (cond) if (cond) BadArgument (#cond)

staticstatic

doubledouble

MisregDots(int const misregFactor)MisregDots (int const misregFactor)

{{

return (double)misregFactor / 1000;return (double) misregFactor / 1000;

}
}

staticstatic

intint

MisregSubdots(int const misregFactor, int const subdotsPerDot)MisregSubdots (int const misregFactor, int const subdotsPerDot)

{{

return (int)BU_Round(MisregDots(misregFactor) * subdotsPerDot); return (int) BU_Round (MisregDots (misregFactor) * subdotsPerDot);                 

}
}

staticstatic

voidvoid

PutDotPutdot

((

int const subdotsPerDot,int const subdotsPerDot,

RLE_Dot const& rleDot,RLE_Dot const & rleDot,

int const dotRow,int const dotRow,

int const dotCol,int const dotCol,

int const misregFactor,int const misregFactor,

BI_Image& outputImageBI_Image & outputImage

))

{{

int const misregSubdots = MisregSubdots(misregFactor, subdotsPerDot);int const misregSubdots = MisregSubdots (misregFactor, subdotsPerDot);

int const subdotRow = dotRow * subdotsPerDot;int const subdotRow = dotRow * subdotsPerDot;

int const subdotCol = dotCol * subdotsPerDot;
int const subdotCol = dotCol * subdotsPerDot;

int const dotOverlap = rleDot.size() - subdotsPerDot;int const dotOverlap = rleDot.size ()-subdotsPerDot;

int const dotMargin = dotOverlap / 2;
int const dotMargin = dotOverlap / 2;

RLE_Dot::const_iterator ii = rleDot.begin();RLE_Dot :: const_iterator ii = rleDot.begin ();

for (int i = 0; i < rleDot.size(); i++, ii++)for (int i = 0; i <rleDot.size (); i ++, ii ++)

{{

int const row = subdotRow - dotMargin + i;int const row = subdotRow-dotMargin + i;

if (row < 0 || row >= outputImage.Height())if (row <0 || row> = outputImage.Height ())

continue;
continue;

int const whiteRun = (*ii).WhiteRun();int const whiteRun = (* ii) .WhiteRun ();

int blackRun = (*ii).BlackRun();
int blackRun = (* ii) .BlackRun ();

int col = subdotCol - dotMargin + whiteRun + misregSubdots;int col = subdotCol-dotMargin + whiteRun + misregSubdots;

if (col < 0)if (col <0)

{{

blackRun += col;blackRun + = col;

col = 0;col = 0;

}}

if (col + blackRun >= outputImage.Width())if (col + blackRun> = outputImage.Width ())

blackRun = outputImage.Width() - col;blackRun = outputImage.Width ()-col;

if (blackRun <= 0) if (blackRun <= 0)                 

continue;
continue;

BU_ExpandBitRunBU_ExpandBitRun

((

outputImage.Image(row),outputImage.Image (row),

col,col,

outputImage.Width(),outputImage.Width (),

blackRun,blackRun,

1One

););

}}

}
}

staticstatic

voidvoid

MergeScaleMergeScale

((

double const scale,double const scale,

int& v,int & v,

double& f0, double & f0,                 

double& f1double & f1

))

{{

double const vScaled = (double)v * scale;double const vScaled = (double) v * scale;

if (vScaled <= 255.0)if (vScaled <= 255.0)

{{

v = (int)BU_Round(vScaled);v = (int) BU_Round (vScaled);

}}

elseelse

{{

v = 255;v = 255;

double const fScale = vScaled / 255.0;double const fScale = vScaled / 255.0;

f0 *= fScale;f0 * = fScale;

f1 *= fScale;f1 * = fScale;

}}

}
}

staticstatic

voidvoid

Dither Dither                 

((

BI_Image const& inputImage,BI_Image const & inputImage,

BI_LUT const& lutDotGain,BI_LUT const & lutDotGain,

int const dotsPerPixel,int const dotsPerPixel,

int const subdotsPerDot,int const subdotsPerDot,

BI_Image const& dotImage,BI_Image const & dotImage,

char const* pDotImageName,char const * pDotImageName,

char const* pRefDotImageName,char const * pRefDotImageName,

int const overlapCenter,int const overlapCenter,

int const overlapSize,int const overlapSize,

int const misregFactor,int const misregFactor,

BI_Image const& ditherMatrix,BI_Image const & ditherMatrix,

BI_Image& outputImage,BI_Image & outputImage,

int const outputResolution,int const outputResolution,

bool const bRetain,bool const bRetain,

bool const bSkipLHS,bool const bSkipLHS,

bool const bSkipRHS,bool const bSkipRHS,

bool const bFixedInterp = false,bool const bFixedInterp = false,

double const fixedF0 = 0,double const fixedF0 = 0,

double const fixedF1 = 0 double const fixedF1 = 0                 

))

{{

// compute overlap interval// compute overlap interval

int const overlapStart = overlapCenter - (overlapSize / 2);int const overlapStart = overlapCenter-(overlapSize / 2);

int const overlapEnd = overlapStart + overlapSize - 1;
int const overlapEnd = overlapStart + overlapSize-1;

// copy and invert dither matrix// copy and invert dither matrix

BI_Image ditherMatrix2;BI_Image ditherMatrix2;

ditherMatrix2 = ditherMatrix;ditherMatrix2 = ditherMatrix;

BI_Invert(ditherMatrix2);
BI Invert (ditherMatrix2);

// initialise and clear output image// initialise and clear output image

int const subdotsPerPixel = dotsPerPixel * subdotsPerDot;int const subdotsPerPixel = dotsPerPixel * subdotsPerDot;

int const bilevelHeight = inputImage.Height() * subdotsPerPixel;int const bilevelHeight = inputImage.Height () * subdotsPerPixel;

int const bilevelWidth = inputImage.Width() * subdotsPerPixel;int const bilevelWidth = inputImage.Width () * subdotsPerPixel;

if (!bRetain)if (! bRetain)

{{

// initialise// initialise

outputImage.InitialiseoutputImage.Initialise

( (                 

BI_ColorModel(BI_ColorGrayscale, 1),BI_ColorModel (BI_ColorGrayscale, 1),

bilevelHeight,bilevelHeight,

bilevelWidth,bilevelWidth,

outputResolution,outputResolution,

outputResolutionoutputResolution

);
);

// clear// clear

BI_CC* pOutputRow = outputImage.Image();BI_CC * pOutputRow = outputImage.Image ();

for (int j = 0; j < outputImage.Height(); j++)for (int j = 0; j <outputImage.Height (); j ++)

{{

BU_ClearLine(pOutputRow, outputImage.Width());BU_ClearLine (pOutputRow, outputImage.Width ());

pOutputRow += outputImage.RowSize();pOutputRow + = outputImage.RowSize ();

}}

}
}

// convert dot image to RLE// convert dot image to RLE

RLE_Dot rleDot;RLE_Dot rleDot;

for (int i = 0; i < dotImage.Height(); i++)for (int i = 0; i <dotImage.Height (); i ++)

{ {                 

int const whiteRun = BU_GetBitRunint const whiteRun = BU_GetBitRun

((

dotImage.Image(i),dotImage.Image (i),

0,0,

dotImage.Width(),dotImage.Width (),

0 // white0 // white

););

int blackRun;int blackRun;

if (whiteRun == dotImage.Width())if (whiteRun == dotImage.Width ())

{{

blackRun = 0;blackRun = 0;

}}

elseelse

{{

blackRun = BU_GetBitRunblackRun = BU_GetBitRun

((

dotImage.Image(i),dotImage.Image (i),

whiteRun,whiteRun,

dotImage.Width(),dotImage.Width (),

1 // black 1 // black                 

););

}}

rleDot.push_back(RLE_DotLine(whiteRun, blackRun));rleDot.push_back (RLE_DotLine (whiteRun, blackRun));

}
}

// dither contone input image to bi-level output image// dither contone input image to bi-level output image

BI_CC const* pImage = inputImage.Image();BI_CC const * pImage = inputImage.Image ();

BI_CC const* pRow = pImage;BI_CC const * pRow = pImage;

BI_CC const* pDither = ditherMatrix.Image();BI_CC const * pDither = ditherMatrix.Image ();

BI_CC const* pDitherRow = pDither;BI_CC const * pDitherRow = pDither;

BI_CC const* pDither2 = ditherMatrix2.Image();BI_CC const * pDither2 = ditherMatrix2.Image ();

BI_CC const* pDitherRow2 = pDither2;BI_CC const * pDitherRow2 = pDither2;

int ditherRow = 0;int ditherRow = 0;

for (int row = 0; row < inputImage.Height(); row++)for (int row = 0; row <inputImage.Height (); row ++)

{{

for (int dotRow = 0; dotRow < dotsPerPixel; dotRow++)for (int dotRow = 0; dotRow <dotsPerPixel; dotRow ++)

{{

int const globalDotRow = (row * dotsPerPixel) + dotRow;int const globalDotRow = (row * dotsPerPixel) + dotRow;

BI_CC const* pPixel = pRow;BI_CC const * pPixel = pRow;

BI_CC const* pDitherPixel = pDitherRow; BI_CC const * pDitherPixel = pDitherRow;                 

BI_CC const* pDitherPixel2 = pDitherRow2;BI_CC const * pDitherPixel2 = pDitherRow2;

int ditherCol = 0;int ditherCol = 0;

for (int col = 0; col < inputImage.Width(); col++)for (int col = 0; col <inputImage.Width (); col ++)

{{

int const vRaw = *pPixel++;int const vRaw = * pPixel ++;

int const vDotGain = lutDotGain[vRaw];int const vDotGain = lutDotGain [vRaw];

for (int dotCol = 0; dotCol < dotsPerPixel; dotCol++)for (int dotCol = 0; dotCol <dotsPerPixel; dotCol ++)

{{

int vRawDot = vRaw;int vRawDot = vRaw;

int const t0 = *pDitherPixel;int const t0 = * pDitherPixel;

int const t1 = t0; //*pDitherPixel2;
int const t1 = t0; // * pDitherPixel2;

int const globalDotCol = (col * dotsPerPixel) + dotCol;
int const globalDotCol = (col * dotsPerPixel) + dotCol;

// interpolate intensities in overlap region and dither// interpolate intensities in overlap region and dither

// one or the other or both// one or the other or both

if (!bFixedInterp && globalDotCol < overlapStart) if (! bFixedInterp && globalDotCol <overlapStart)                 

{{

int const t = t0;int const t = t0;

if ((vDotGain == 255) || (vDotGain >= t && vDotGain != 0))if ((vDotGain == 255) || (vDotGain> = t && vDotGain! = 0))

{{

if (!bSkipLHS)if (! bSkipLHS)

{{

PutDotPutdot

((

subdotsPerDot,subdotsPerDot,

rleDot,rleDot,

globalDotRow,globalDotRow,

globalDotCol,globalDotCol,

0,0,

outputImageoutputImage

););

}}

}}

}}

else else                 

if (!bFixedInterp && overlapEnd < globalDotCol)if (! bFixedInterp && overlapEnd <globalDotCol)

{{

int const t = (overlapSize == 0) ? t0 : t1;int const t = (overlapSize == 0)? t0: t1;

if ((vDotGain == 255) || (vDotGain >= t && vDotGain != 0))if ((vDotGain == 255) || (vDotGain> = t && vDotGain! = 0))

{{

if (!bSkipRHS)if (! bSkipRHS)

{{

PutDotPutdot

((

subdotsPerDot,subdotsPerDot,

rleDot,rleDot,

globalDotRow,globalDotRow,

globalDotCol,globalDotCol,

misregFactor,misregFactor,

outputImageoutputImage

););

}}

} }                 

}}

elseelse

{{

#if 1#if 1

// account for stretch or shrink// account for stretch or shrink

if (!bFixedInterp)if (! bFixedInterp)

{{

double const misregDots = MisregDots(misregFactor);double const misregDots = MisregDots (misregFactor);

double const newOverlapSize = overlapSize + misregDots;double const newOverlapSize = overlapSize + misregDots;

double const overlapScale = newOverlapSize / overlapSize;
double const overlapScale = newOverlapSize / overlapSize;

vRawDot = (int)BU_Round(vRawDot * overlapScale);vRawDot = (int) BU_Round (vRawDot * overlapScale);

if (vRawDot > 255)if (vRawDot> 255)

vRawDot = 255;vRawDot = 255;

//MergeScale(overlapScale, vRawDot, f0, f1); // MergeScale (overlapScale, vRawDot, f0, f1);                 

}}

#endif
#endif

#if 1#if 1

// compute interpolation factors// compute interpolation factors

double f0, f1;double f0, f1;

if (bFixedInterp)if (bFixedInterp)

{{

f0 = fixedF0;f0 = fixedF0;

f1 = fixedF1;f1 = fixedF1;

}}

elseelse

{{

// compute overlap index// compute overlap index

int const overlapIndex =int const overlapIndex =

globalDotCol - overlapStart;
globalDotCol-overlapStart;

// obtain misregistration LUTs// obtain misregistration LUTs

BI_LUT lutv;BI_LUT lutv;

BI_LUT lut0; BI_LUT lut0;                 

BI_LUT lut1;BI_LUT lut1;

ObtainMisregistrationTransferFunctionObtainMisregistrationTransferFunction

((

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pRefDotImageName,pRefDotImageName,

overlapSize,overlapSize,

overlapIndex,overlapIndex,

misregFactor,misregFactor,

ditherMatrix,ditherMatrix,

lutv,lutv,

lut0,lut0,

lut1lut1

);
);

// retrieve interpolation factors// retrieve interpolation factors

f0 = (double)lut0[vRawDot] / 255; f0 = (double) lut0 [vRawDot] / 255;                 

f1 = (double)lut1[vRawDot] / 255;f1 = (double) lut1 [vRawDot] / 255;

if (globalDotCol > overlapCenter)if (globalDotCol> overlapCenter)

BU_Swap(f0, f1);
BU_Swap (f0, f1);

// adjust intensity for attenuation// adjust intensity for attenuation

vRawDot = lutv[vRawDot];vRawDot = lutv [vRawDot];

}}

#endif
#endif

// diagnostics// diagnostics

//printf("f0=%5.1lf f1=%5.1lf (%5.1lf) vRaw=%d v=%d\n",//printf("f0=%5.1lf f1 =% 5.1lf (% 5.1lf) vRaw =% d v =% d \ n ",

// f0, f1, f0 + f1, vRaw, vRawDot);
// f0, f1, f0 + f1, vRaw, vRawDot);

// interpolate dither with jitter// interpolate dither with jitter

int vd = 0;int vd = 0;

int v0d = 0;int v0d = 0;

int v1d = 0;int v1d = 0;

if ((vRawDot == 255) || (vRawDot >= t0 && vRawDot != 0)) if ((vRawDot == 255) || (vRawDot> = t0 && vRawDot! = 0))                 

{{

vd = 1;vd = 1;

}
}

double const rr = (double)rand() / RAND_MAX;double const rr = (double) rand () / RAND_MAX;

if (vd && rr < f0)if (vd && rr <f0)

{{

v0d = 1;v0d = 1;

if (!bSkipLHS)if (! bSkipLHS)

{{

PutDotPutdot

((

subdotsPerDot,subdotsPerDot,

rleDot,rleDot,

globalDotRow,globalDotRow,

globalDotCol,globalDotCol,

0,0,

outputImageoutputImage

); );                 

}}

}
}

if (vd && (1.0 - rr) <= f1)if (vd && (1.0-rr) <= f1)

{{

v1d = 1;v1d = 1;

if (!bSkipRHS)if (! bSkipRHS)

{{

PutDotPutdot

((

subdotsPerDot,subdotsPerDot,

rleDot,rleDot,

globalDotRow,globalDotRow,

globalDotCol,globalDotCol,

misregFactor,misregFactor,

outputImageoutputImage

););

}}

}}

#if 0 #if 0                 

if (globalDotRow == 864)if (globalDotRow == 864)

{{

printf("%1d %1d %1d (%3d %3d %3d %3d) ",printf ("% 1d% 1d% 1d (% 3d% 3d% 3d% 3d)",

vd, v0d, v1d, vRawDot, v0, v1, v0 + v1);vd, v0d, v1d, vRawDot, v0, v1, v0 + v1);

if (v0d + v1d < vd)if (v0d + v1d <vd)

printf("?");printf ("?");

if (v0d + v1d > vd)if (v0d + v1d> vd)

printf("#");printf ("#");

printf("\n");printf ("\ n");

}}

#endif#endif

}
}

pDitherPixel++;pDitherPixel ++;

pDitherPixel2++;pDitherPixel2 ++;

ditherCol++;ditherCol ++;

if (ditherCol >= ditherMatrix.Width())if (ditherCol> = ditherMatrix.Width ())

{ {                 

pDitherPixel = pDitherRow;pDitherPixel = pDitherRow;

pDitherPixel2 = pDitherRow2;pDitherPixel2 = pDitherRow2;

ditherCol = 0;ditherCol = 0;

}}

}}

}}

pDitherRow += ditherMatrix.RowSize();pDitherRow + = ditherMatrix.RowSize ();

pDitherRow2 += ditherMatrix2.RowSize();pDitherRow2 + = ditherMatrix2.RowSize ();

ditherRow++;ditherRow ++;

if (ditherRow >= ditherMatrix.Height())if (ditherRow> = ditherMatrix.Height ())

{{

pDitherRow = pDither;pDitherRow = pDither;

pDitherRow2 = pDither2;pDitherRow2 = pDither2;

ditherRow = 0;ditherRow = 0;

}}

}}

pRow += inputImage.RowSize();pRow + = inputImage.RowSize ();

}}

}
}

staticstatic

voidvoid

ChangeFileSuffixChangefilesuffix

((

char const* pPath,char const * pPath,

char const* pSuffix,char const * pSuffix,

char const* pExt,char const * pExt,

char path[_MAX_PATH]char path [_MAX_PATH]

))

{{

char drive[_MAX_DRIVE];char drive [_MAX_DRIVE];

char dir[_MAX_DIR];char dir [_MAX_DIR];

char fname[_MAX_FNAME];char fname [_MAX_FNAME];

char ext[_MAX_EXT];char ext [_MAX_EXT];

_splitpath(pPath, drive, dir, fname, ext);_splitpath (pPath, drive, dir, fname, ext);

strcat(fname, pSuffix);strcat (fname, pSuffix);

_makepath(path, drive, dir, fname, pExt);_makepath (path, drive, dir, fname, pExt);

}
}

static static                 

voidvoid

LogTransferFunction(char const* pType, double const intensity[], int const v)LogTransferFunction (char const * pType, double const intensity [], int const v)

{{

printf("%s: %03d : %5.1lf (%5.1lf)\n",printf ("% s:% 03d:% 5.1lf (% 5.1lf) \ n",

pType, v, intensity[v], v - intensity[v]);pType, v, intensity [v], v-intensity [v]);

}
}

staticstatic

voidvoid

ComputeMisregistrationTransferFunctionComputeMisregistrationTransferFunction

((

int dotsPerPixel,int dotsPerPixel,

int subdotsPerDot,int subdotsPerDot,

BI_Image const& dotImage,BI_Image const & dotImage,

char const* pDotImageName,char const * pDotImageName,

double const f0,double const f0,

double const f1,double const f1,

int const misregFactor,int const misregFactor,

BI_Image const& ditherMatrix,BI_Image const & ditherMatrix,

BI_LUT& lutv, BI_LUT & lutv,                 

BI_LUT& lut0,BI_LUT & lut0,

BI_LUT& lut1BI_LUT & lut1

))

{{

// create test image// create test image

BI_Image testImage;BI_Image testImage;

testImage.InitialisetestImage.Initialise

((

BI_ColorModel(BI_ColorGrayscale),BI_ColorModel (BI_ColorGrayscale),

ditherMatrix.Height(),ditherMatrix.Height (),

ditherMatrix.Width()ditherMatrix.Width ()

);
);

// build identity transfer function// build identity transfer function

BI_LUT identityLut;BI_LUT identityLut;

for (int v = 0; v < 256; v++)for (int v = 0; v <256; v ++)

identityLut[v] = v;
identityLut [v] = v;

// create output image// create output image

BI_Image outputImage;
BI_Image outputImage;

// compute intensity for each gray level// compute intensity for each gray level

double intensity[512];double intensity [512];

int vLast;int vLast;

for (v = 0; v < 512; v++)for (v = 0; v <512; v ++)

{{

// compute extended interpolation factors// compute extended interpolation factors

double f0x, f1x;double f0x, f1x;

int vx;int vx;

if (v <= 255)if (v <= 255)

{{

vx = v;vx = v;

f0x = f0;f0x = f0;

f1x = f1;f1x = f1;

}}

elseelse

{{

vx = 255;vx = 255;

double const fScale = (double)v / 255.0;double const fScale = (double) v / 255.0;

f0x = f0 * fScale; f0x = f0 * fScale;                 

f1x = f1 * fScale;f1x = f1 * fScale;

}
}

// set test image to next intensity// set test image to next intensity

testImage = BI_Color((BI_CC)vx);
testImage = BI_Color ((BI_CC) vx);

// dither test image to bi-level output// dither test image to bi-level output

DitherDither

((

testImage,testImage,

identityLut,identityLut,

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pDotImageName,pDotImageName,

0, 0, // no explicit overlap0, 0, // no explicit overlap

misregFactor,misregFactor,

ditherMatrix,ditherMatrix,

outputImage, outputImage,                 

72, // output resolution72, // output resolution

false, // don't retain output imagefalse, // don't retain output image

false, // don't skip LHSfalse, // don't skip LHS

false, // don't skip RHSfalse, // don't skip RHS

true, // fixed interpolationtrue, // fixed interpolation

f0x,f0x,

f1xf1x

);
);

// determine intensity of dithered bi-level output// determine intensity of dithered bi-level output

long nDots = 0;long nDots = 0;

BI_CC const* pRow = outputImage.Image();BI_CC const * pRow = outputImage.Image ();

for (int row = 0; row < outputImage.Height(); row++)for (int row = 0; row <outputImage.Height (); row ++)

{{

nDots += BU_CountBits(pRow, 0, outputImage.Width());nDots + = BU_CountBits (pRow, 0, outputImage.Width ());

pRow += outputImage.RowSize();pRow + = outputImage.RowSize ();

}}

intensity[v] = 255 * (double)nDots / outputImage.PixelCount();intensity [v] = 255 * (double) nDots / outputImage.PixelCount ();

//LogTransferFunction("misreg", intensity, v);
// LogTransferFunction ("misreg", intensity, v);

vLast = v;vLast = v;

if (intensity[v] >= 255)if (intensity [v]> = 255)

break;break;

}}

LogTransferFunction("misreg", intensity, 1);LogTransferFunction ("misreg", intensity, 1);

LogTransferFunction("misreg", intensity, vLast);
LogTransferFunction ("misreg", intensity, vLast);

// create LUTs// create LUTs

for (int x = 0; x < 256; x++)for (int x = 0; x <256; x ++)

{{

double d = -1;double d = -1;

for (v = 0; v <= vLast; v++)for (v = 0; v <= vLast; v ++)

{{

double const d2 = BU_Abs(intensity[v] - x);double const d2 = BU_Abs (intensity [v]-x);

if (d < 0 || d2 < d)if (d <0 || d2 <d)

{{

d = d2;d = d2;

if (v <= 255)if (v <= 255)

{{

lutv[x] = v; lutv [x] = v;                 

int const k0 = (int)BU_Round(f0 * 255);int const k0 = (int) BU_Round (f0 * 255);

lut0[x] = (BI_CC)BU_Min(k0, 255);lut0 [x] = (BI_CC) BU_Min (k0, 255);

int const k1 = (int)BU_Round(f1 * 255);int const k1 = (int) BU_Round (f1 * 255);

lut1[x] = (BI_CC)BU_Min(k1, 255);lut1 [x] = (BI_CC) BU_Min (k1, 255);

}}

elseelse

{{

lutv[x] = 255;lutv [x] = 255;

int const k0 = (int)BU_Round(f0 * v);int const k0 = (int) BU_Round (f0 * v);

lut0[x] = (BI_CC)BU_Min(k0, 255);lut0 [x] = (BI_CC) BU_Min (k0, 255);

int const k1 = (int)BU_Round(f1 * v);int const k1 = (int) BU_Round (f1 * v);

lut1[x] = (BI_CC)BU_Min(k1, 255);lut1 [x] = (BI_CC) BU_Min (k1, 255);

if (k0 > 255 || k1 > 255)if (k0> 255 || k1> 255)

{{

fprintf(stderr, "k0=%d k1=%d (x=%d v=%d f0=%5.1lf f1=%5.1lf\n",fprintf (stderr, "k0 =% d k1 =% d (x =% d v =% d f0 =% 5.1lf f1 =% 5.1lf \ n",

k0, k1, x, v, f0, f1);k0, k1, x, v, f0, f1);

}}

}}

} }                 

}}

}}

}
}

staticstatic

voidvoid

SimplifyFraction(int& n, int& d)SimplifyFraction (int & n, int & d)

{{

for (int i = n; i > 1 && n > 1; --i)for (int i = n; i> 1 && n> 1; --i)

{{

if ((d % i) == 0)if ((d% i) == 0)

{{

if ((n % i) == 0)if ((n% i) == 0)

{{

n /= i;n / = i;

d /= i;d / = i;

}}

}}

}}

}
}

staticstatic

voidvoid

ObtainMisregistrationTransferFunctionObtainMisregistrationTransferFunction

((

int dotsPerPixel,int dotsPerPixel,

int subdotsPerDot,int subdotsPerDot,

BI_Image const& dotImage,BI_Image const & dotImage,

char const* pDotImageName,char const * pDotImageName,

char const* pRefDotImageName,char const * pRefDotImageName,

int const overlapSize,int const overlapSize,

int const rawOverlapIndex, // 0 .. overlapSize-1int const rawOverlapIndex, // 0 .. overlapSize-1

int const misregFactor,int const misregFactor,

BI_Image const& ditherMatrix,BI_Image const & ditherMatrix,

BI_LUT& lutv,BI_LUT & lutv,

BI_LUT& lut0,BI_LUT & lut0,

BI_LUT& lut1BI_LUT & lut1

))

{{

// normalize overlap index // normalize overlap index                 

int overlapIndex = rawOverlapIndex;int overlapIndex = rawOverlapIndex;

if (overlapIndex >= ((overlapSize + 1) / 2))if (overlapIndex> = ((overlapSize + 1) / 2))

overlapIndex = (overlapSize - 1) - overlapIndex;
overlapIndex = (overlapSize-1)-overlapIndex;

char lutvName[_MAX_PATH];char lutvName [_MAX_PATH];

char lut0Name[_MAX_PATH];char lut0Name [_MAX_PATH];

char lut1Name[_MAX_PATH];char lut1Name [_MAX_PATH];

char suffix[_MAX_FNAME];
char suffix [_MAX_FNAME];

int interpNum = overlapIndex + 1;int interpNum = overlapIndex + 1;

int interpDenom = overlapSize + 1;int interpDenom = overlapSize + 1;

SimplifyFraction(interpNum, interpDenom);
SimplifyFraction (interpNum, interpDenom);

sprintf(suffix, "_%03d_%02d_%02d",sprintf (suffix, "_% 03d_% 02d_% 02d",

BU_Abs(misregFactor), interpNum, interpDenom);BU_Abs (misregFactor), interpNum, interpDenom);

ChangeFileSuffix(pRefDotImageName, suffix, ".amp", lutvName);
ChangeFileSuffix (pRefDotImageName, suffix, ".amp", lutvName);

sprintf(suffix, "_%03d_%02d_%02d_0",sprintf (suffix, "_% 03d_% 02d_% 02d_0",

BU_Abs(misregFactor), interpNum, interpDenom);BU_Abs (misregFactor), interpNum, interpDenom);

ChangeFileSuffix(pRefDotImageName, suffix, ".amp", lut0Name);
ChangeFileSuffix (pRefDotImageName, suffix, ".amp", lut0Name);

sprintf(suffix, "_%03d_%02d_%02d_1",sprintf (suffix, "_% 03d_% 02d_% 02d_1",

BU_Abs(misregFactor), interpNum, interpDenom);BU_Abs (misregFactor), interpNum, interpDenom);

ChangeFileSuffix(pRefDotImageName, suffix, ".amp", lut1Name);
ChangeFileSuffix (pRefDotImageName, suffix, ".amp", lut1Name);

trytry

{{

BU_File lutvFile(lutvName, _O_BINARY | _O_RDONLY);BU_File lutvFile (lutvName, _O_BINARY | _O_RDONLY);

lutv.Load(lutvFile);lutv.Load (lutvFile);

BU_File lut0File(lut0Name, _O_BINARY | _O_RDONLY);BU_File lut0File (lut0Name, _O_BINARY | _O_RDONLY);

lut0.Load(lut0File);lut0.Load (lut0File);

BU_File lut1File(lut1Name, _O_BINARY | _O_RDONLY);BU_File lut1File (lut1Name, _O_BINARY | _O_RDONLY);

lut1.Load(lut1File);lut1.Load (lut1File);

}}

catch (...)catch (...)

{{

// if using a reference dot image, LUTs must already exist// if using a reference dot image, LUTs must already exist

if (strcmp(pDotImageName, pRefDotImageName) != 0)if (strcmp (pDotImageName, pRefDotImageName)! = 0)

{{

fprintf(stderr, "can't load %s or %s or %s\n", fprintf (stderr, "can't load% s or% s or% s \ n",                 

lutvName, lut0Name, lut1Name);lutvName, lut0Name, lut1Name);

exit(1);exit (1);

}
}

// determine interpolation factors// determine interpolation factors

double f1 = (double)interpNum / interpDenom;double f1 = (double) interpNum / interpDenom;

double f0 = 1.0 - f1;
double f0 = 1.0-f1;

ComputeMisregistrationTransferFunctionComputeMisregistrationTransferFunction

((

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

f0,f0,

f1,f1,

BU_Abs(misregFactor),BU_Abs (misregFactor),

ditherMatrix,ditherMatrix,

lutv,lutv,

lut0, lut0,                 

lut1lut1

););

BU_File lutvFile(lutvName, _O_BINARY | _O_WRONLY | _O_CREAT);BU_File lutvFile (lutvName, _O_BINARY | _O_WRONLY | _O_CREAT);

lutv.Save(lutvFile);lutv.Save (lutvFile);

BU_File lut0File(lut0Name, _O_BINARY | _O_WRONLY | _O_CREAT);BU_File lut0File (lut0Name, _O_BINARY | _O_WRONLY | _O_CREAT);

lut0.Save(lut0File);lut0.Save (lut0File);

BU_File lut1File(lut1Name, _O_BINARY | _O_WRONLY | _O_CREAT);BU_File lut1File (lut1Name, _O_BINARY | _O_WRONLY | _O_CREAT);

lut1.Save(lut1File);lut1.Save (lut1File);

}}

}
}

staticstatic

voidvoid

ComputeDotGainTransferFunctionComputeDotGainTransferFunction

((

int dotsPerPixel,int dotsPerPixel,

int subdotsPerDot,int subdotsPerDot,

BI_Image const& dotImage,BI_Image const & dotImage,

char const* pDotImageName,char const * pDotImageName,

BI_Image const& ditherMatrix, BI_Image const & ditherMatrix,                 

BI_LUT& lutDotGainBI_LUT & lutDotGain

))

{{

// create test image// create test image

BI_Image testImage;BI_Image testImage;

testImage.InitialisetestImage.Initialise

((

BI_ColorModel(BI_ColorGrayscale),BI_ColorModel (BI_ColorGrayscale),

ditherMatrix.Height(),ditherMatrix.Height (),

ditherMatrix.Width()ditherMatrix.Width ()

);
);

// build identity transfer function// build identity transfer function

BI_LUT identityTransferFunction;BI_LUT identityTransferFunction;

for (int v = 0; v < 256; v++)for (int v = 0; v <256; v ++)

identityTransferFunction[v] = v;
identityTransferFunction [v] = v;

// create output image// create output image

BI_Image outputImage;
BI_Image outputImage;

// compute intensity for each gray level// compute intensity for each gray level

double intensity[256];double intensity [256];

for (v = 0; v < 256; v++)for (v = 0; v <256; v ++)

{{

// set test image to next intensity// set test image to next intensity

testImage = BI_Color((BI_CC)v);
testImage = BI_Color ((BI_CC) v);

// dither test image to bi-level output// dither test image to bi-level output

DitherDither

((

testImage,testImage,

identityTransferFunction,identityTransferFunction,

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pDotImageName,pDotImageName,

0, 0, // no overlap0, 0, // no overlap

0, // no misregistration0, // no misregistration

ditherMatrix, ditherMatrix,                 

outputImage,outputImage,

72, // output resolution72, // output resolution

false, // don't retain output imagefalse, // don't retain output image

false, // don't skip LHSfalse, // don't skip LHS

false // don't skip RHSfalse // don't skip RHS

);
);

// determine intensity of dithered bi-level output// determine intensity of dithered bi-level output

long nDots = 0;long nDots = 0;

BI_CC const* pRow = outputImage.Image();BI_CC const * pRow = outputImage.Image ();

for (int row = 0; row < outputImage.Height(); row++)for (int row = 0; row <outputImage.Height (); row ++)

{{

nDots += BU_CountBits(pRow, 0, outputImage.Width());nDots + = BU_CountBits (pRow, 0, outputImage.Width ());

pRow += outputImage.RowSize();pRow + = outputImage.RowSize ();

}}

intensity[v] = 255 * (double)nDots / outputImage.PixelCount();intensity [v] = 255 * (double) nDots / outputImage.PixelCount ();

//LogTransferFunction("dot gain", intensity, v);// LogTransferFunction ("dot gain", intensity, v);

}}

LogTransferFunction("dot gain", intensity, 1); LogTransferFunction ("dot gain", intensity, 1);                 

LogTransferFunction("dot gain", intensity, 255);
LogTransferFunction ("dot gain", intensity, 255);

// create LUT// create LUT

for (int x = 0; x < 256; x++)for (int x = 0; x <256; x ++)

{{

double d = -1;double d = -1;

for (v = 0; v < 256; v++)for (v = 0; v <256; v ++)

{{

double const d2 = BU_Abs(intensity[v] - x);double const d2 = BU_Abs (intensity [v]-x);

if (d < 0 || d2 < d)if (d <0 || d2 <d)

{{

d = d2;d = d2;

lutDotGain[x] = v;lutDotGain [x] = v;

}}

}}

}}

}
}

staticstatic

void void                 

ObtainDotGainTransferFunctionObtainDotGainTransferFunction

((

int dotsPerPixel,int dotsPerPixel,

int subdotsPerDot,int subdotsPerDot,

BI_Image const& dotImage,BI_Image const & dotImage,

char const* pDotImageName,char const * pDotImageName,

char const* pRefDotImageName,char const * pRefDotImageName,

BI_Image const& ditherMatrix,BI_Image const & ditherMatrix,

BI_LUT& lutDotGainBI_LUT & lutDotGain

))

{{

char lutName[_MAX_PATH];char lutName [_MAX_PATH];

ChangeFileSuffix(pRefDotImageName, "", ".amp", lutName);ChangeFileSuffix (pRefDotImageName, "", ".amp", lutName);

trytry

{{

BU_File lutFile(lutName, _O_BINARY | _O_RDONLY);BU_File lutFile (lutName, _O_BINARY | _O_RDONLY);

lutDotGain.Load(lutFile);lutDotGain.Load (lutFile);

}}

catch (...)catch (...)

{ {                 

// if using a reference dot image, LUT must already exist// if using a reference dot image, LUT must already exist

if (strcmp(pDotImageName, pRefDotImageName) != 0)if (strcmp (pDotImageName, pRefDotImageName)! = 0)

{{

fprintf(stderr, "can't load %s\n", lutName);fprintf (stderr, "can't load% s \ n", lutName);

exit(1);exit (1);

}}

ComputeDotGainTransferFunctionComputeDotGainTransferFunction

((

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

ditherMatrix,ditherMatrix,

lutDotGainlutDotGain

););

BU_File lutFile(lutName, _O_BINARY | _O_WRONLY | _O_CREAT);BU_File lutFile (lutName, _O_BINARY | _O_WRONLY | _O_CREAT);

lutDotGain.Save(lutFile);lutDotGain.Save (lutFile);

}}

}
}

staticstatic

voidvoid

SegmentDither(int argc, char* argv[])SegmentDither (int argc, char * argv [])

{{

// parse arguments// parse arguments

if (argc != 12)if (argc! = 12)

Usage();Usage ();

char const* pInputImageName = argv[1];char const * pInputImageName = argv [1];

int const dotsPerPixel = atoi(argv[2]);int const dotsPerPixel = atoi (argv [2]);

int const subdotsPerDot = atoi(argv[3]);int const subdotsPerDot = atoi (argv [3]);

char const* pDotImageName = argv[4];char const * pDotImageName = argv [4];

char const* pRefDotImageName = argv[5];char const * pRefDotImageName = argv [5];

int const overlapCenter = atoi(argv[6]);int const overlapCenter = atoi (argv [6]);

int const overlapSize = atoi(argv[7]);int const overlapSize = atoi (argv [7]);

int const misregFactor = atoi(argv[8]);int const misregFactor = atoi (argv [8]);

int const misregSubdots = MisregSubdots(misregFactor, subdotsPerDot);int const misregSubdots = MisregSubdots (misregFactor, subdotsPerDot);

char const* pDitherMatrixName = argv[9];char const * pDitherMatrixName = argv [9];

char const* pOutputImageName = argv[10];char const * pOutputImageName = argv [10];

int const outputResolution = atoi(argv[11]);
int const outputResolution = atoi (argv [11]);

// open input image// open input image

BI_Image inputImage;BI_Image inputImage;

BI_LoadImage(inputImage, pInputImageName);BI_LoadImage (inputImage, pInputImageName);

CHECK_ARGUMENT(inputImage.ColorModel() != BI_ColorModel(BI_ColorGrayscale));CHECK_ARGUMENT (inputImage.ColorModel ()! = BI_ColorModel (BI_ColorGrayscale));

BI_Invert(inputImage); // max is blackBI_Invert (inputImage); // max is black

BI_TIFFSetMinIsBlack(false); // max is black
BI_TIFFSetMinIsBlack (false); // max is black

// check arguments// check arguments

CHECK_ARGUMENT(dotsPerPixel < 1);CHECK_ARGUMENT (dotsPerPixel <1);

CHECK_ARGUMENT(dotsPerPixel > 16);CHECK_ARGUMENT (dotsPerPixel> 16);

CHECK_ARGUMENT(subdotsPerDot < 1);CHECK_ARGUMENT (subdotsPerDot <1);

CHECK_ARGUMENT(subdotsPerDot > 32);CHECK_ARGUMENT (subdotsPerDot> 32);

CHECK_ARGUMENT(overlapCenter < 1);CHECK_ARGUMENT (overlapCenter <1);

CHECK_ARGUMENT(overlapCenter >= inputImage.Width() * dotsPerPixel);CHECK_ARGUMENT (overlapCenter> = inputImage.Width () * dotsPerPixel);

CHECK_ARGUMENT(overlapSize < 0);CHECK_ARGUMENT (overlapSize <0);

CHECK_ARGUMENT(misregSubdots < -subdotsPerDot / 2);CHECK_ARGUMENT (misregSubdots <-subdotsPerDot / 2);

CHECK_ARGUMENT(misregSubdots > subdotsPerDot / 2);CHECK_ARGUMENT (misregSubdots> subdotsPerDot / 2);

CHECK_ARGUMENT(outputResolution <= 0);
CHECK_ARGUMENT (outputResolution <= 0);

// diagnostics// diagnostics

printf("misregSubdots=%d\n", misregSubdots);
printf ("misregSubdots =% d \ n", misregSubdots);

// open dot image// open dot image

BI_Image dotImage;BI_Image dotImage;

BI_LoadImage(dotImage, pDotImageName);BI_LoadImage (dotImage, pDotImageName);

CHECK_ARGUMENT(dotImage.ColorModel() != BI_ColorModel(BI_ColorGrayscale, 1));CHECK_ARGUMENT (dotImage.ColorModel ()! = BI_ColorModel (BI_ColorGrayscale, 1));

CHECK_ARGUMENT(dotImage.Height() < subdotsPerDot);CHECK_ARGUMENT (dotImage.Height () <subdotsPerDot);

CHECK_ARGUMENT(dotImage.Width() < subdotsPerDot);CHECK_ARGUMENT (dotImage.Width () <subdotsPerDot);

CHECK_ARGUMENT(dotImage.Height() != dotImage.Width());CHECK_ARGUMENT (dotImage.Height ()! = DotImage.Width ());

int const dotOverlap = dotImage.Width() - subdotsPerDot;int const dotOverlap = dotImage.Width ()-subdotsPerDot;

CHECK_ARGUMENT((dotOverlap % 2) != 0);
CHECK_ARGUMENT ((dotOverlap% 2)! = 0);

// open dither matrix// open dither matrix

BI_Image ditherMatrix;BI_Image ditherMatrix;

BI_LoadImage(ditherMatrix, pDitherMatrixName);BI_LoadImage (ditherMatrix, pDitherMatrixName);

CHECK_ARGUMENT(ditherMatrix.ColorModel() != BI_ColorModel(BI_ColorGrayscale, 8));CHECK_ARGUMENT (ditherMatrix.ColorModel ()! = BI_ColorModel (BI_ColorGrayscale, 8));

CHECK_ARGUMENT(ditherMatrix.Height() < 16); CHECK_ARGUMENT (ditherMatrix.Height () <16);                 

CHECK_ARGUMENT(ditherMatrix.Width() < 16);
CHECK_ARGUMENT (ditherMatrix.Width () <16);

// create output image// create output image

BI_Image outputImage;
BI_Image outputImage;

// obtain dot gain transfer function for particular dot shape// obtain dot gain transfer function for particular dot shape

BI_LUT lutDotGain;BI_LUT lutDotGain;

ObtainDotGainTransferFunctionObtainDotGainTransferFunction

((

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pRefDotImageName,pRefDotImageName,

ditherMatrix,ditherMatrix,

lutDotGainlutDotGain

);
);

// dither input to bi-level output// dither input to bi-level output

Dither Dither                 

((

inputImage,inputImage,

lutDotGain,lutDotGain,

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pRefDotImageName,pRefDotImageName,

overlapCenter,overlapCenter,

overlapSize,overlapSize,

misregFactor,misregFactor,

ditherMatrix,ditherMatrix,

outputImage,outputImage,

outputResolution,outputResolution,

false, // don't retain output imagefalse, // don't retain output image

false, // don't skip LHSfalse, // don't skip LHS

false // don't skip RHSfalse // don't skip RHS

););

BI_SaveImage(outputImage, pOutputImageName);
BI_SaveImage (outputImage, pOutputImageName);

// dither input to bi-level output (LHS only)// dither input to bi-level output (LHS only)

BI_Image outputImageLHS;BI_Image outputImageLHS;

DitherDither

((

inputImage,inputImage,

lutDotGain,lutDotGain,

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pRefDotImageName,pRefDotImageName,

overlapCenter,overlapCenter,

overlapSize,overlapSize,

misregFactor,misregFactor,

ditherMatrix,ditherMatrix,

outputImageLHS,outputImageLHS,

outputResolution,outputResolution,

false, // don't retain output imagefalse, // don't retain output image

false, // don't skip LHSfalse, // don't skip LHS

true // skip RHS true // skip RHS                 

););

BI_SaveImage(outputImageLHS, "OutLHS.tif");
BI_SaveImage (outputImageLHS, "OutLHS.tif");

// dither input to bi-level output (RHS only)// dither input to bi-level output (RHS only)

BI_Image outputImageRHS;BI_Image outputImageRHS;

DitherDither

((

inputImage,inputImage,

lutDotGain,lutDotGain,

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pRefDotImageName,pRefDotImageName,

overlapCenter,overlapCenter,

overlapSize,overlapSize,

misregFactor,misregFactor,

ditherMatrix,ditherMatrix,

outputImageRHS,outputImageRHS,

outputResolution, outputResolution,                 

false, // don't retain output imagefalse, // don't retain output image

true, // skip LHStrue, // skip LHS

false // don't skip RHSfalse // don't skip RHS

););

BI_SaveImage(outputImageRHS, "OutRHS.tif");
BI_SaveImage (outputImageRHS, "OutRHS.tif");

// dither input to bi-level output (no interp)// dither input to bi-level output (no interp)

BI_Image outputImageNoInterp;BI_Image outputImageNoInterp;

DitherDither

((

inputImage,inputImage,

lutDotGain,lutDotGain,

dotsPerPixel,dotsPerPixel,

subdotsPerDot,subdotsPerDot,

dotImage,dotImage,

pDotImageName,pDotImageName,

pRefDotImageName,pRefDotImageName,

overlapCenter,overlapCenter,

overlapSize,overlapSize,

misregFactor, misregFactor,                 

ditherMatrix,ditherMatrix,

outputImageNoInterp,outputImageNoInterp,

outputResolution,outputResolution,

false, // don't retain output imagefalse, // don't retain output image

false, // skip LHSfalse, // skip LHS

false, // don't skip RHSfalse, // don't skip RHS

true, // fixed interptrue, // fixed interp

0, // f00, // f0

0 // f10 // f1

););

BI_SaveImage(outputImageNoInterp, "OutNoInterp.tif");BI_SaveImage (outputImageNoInterp, "OutNoInterp.tif");

}
}

voidvoid

main(int argc, char* argv[])main (int argc, char * argv [])

{{

trytry

{{

SegmentDither(argc, argv);SegmentDither (argc, argv);

} }                 

catch (BU_Error error)catch (BU_Error error)

{{

error.Print();error.Print ();

}}

exit(0);exit (0);

}}

Claims (19)

오버랩하는 복수의 프린트헤드 세그먼트로 구성되고 인접하는 세그먼트간의 공간적 관계가 시간에 따라 가변하는 잉크 분사 프린트헤드에서, 오버랩된 세그먼트에서의 노즐의 분사를 제어하는 방법에 있어서,In an ink ejection printhead composed of a plurality of overlapping printhead segments and whose spatial relationship between adjacent segments varies in time, the method of controlling ejection of nozzles in the overlapping segment, comprising: (a) 인접하는 프린트헤드 세그먼트간의 오버랩의 정도를 결정하는 단계와,(a) determining the degree of overlap between adjacent printhead segments; (b) 상기 오버랩하는 세그먼트의 오버랩 영역에 있는 노즐에 대한 하프 토닝 패턴(half toning pattern)을 생성하는 단계와,(b) generating a half toning pattern for the nozzles in the overlap region of the overlapping segment; (c) 상기 프린트헤드 세그먼트의 오버랩으로 인해 인쇄된 이미지에서 발생하는 아티팩트를 감소시키기 위해, 상기 하프 토닝 패턴을 상기 프린트헤드 세그먼트의 오버랩하는 영역에서의 측정 결과의 함수로서 조정하는 단계,(c) adjusting the half toning pattern as a function of the measurement result in the overlapping area of the printhead segment to reduce artifacts that occur in the printed image due to the overlap of the printhead segment, 를 포함하여 이루어지는 노즐의 분사를 제어하는 방법.Method of controlling the injection of the nozzle comprising a. 삭제delete 삭제delete 제 1 항에 있어서,The method of claim 1, 상기 오버랩 하는 세그먼트의 오버랩 영역에 있는 노즐에 대한 하프 톤 패턴을 생성하는 단계는 보간 함수를 가진 디더 매트릭스를 채택하는 것을 포함하는 것을 특징으로 하는 노즐의 분사를 제어하는 방법.Generating a halftone pattern for a nozzle in the overlap region of the overlapping segment comprising employing a dither matrix with an interpolation function. 제 4 항에 있어서,The method of claim 4, wherein 상기 하프 톤 패턴을 조정하는 단계는 VA+VB가 V보다 크게 되도록 하는 것(여기서, VA 및 VB는 인접하는 두 세그먼트의 각각의 독립된 디더 매트릭스 값이고, V는 표현되는 연속 톤 값이다)인 것을 특징으로 하는 노즐의 분사를 제어하는 방법.Adjusting the halftone pattern is such that V A + V B is greater than V, where V A and V B are each independent dither matrix values of two adjacent segments, and V is a continuous tone value represented. A method of controlling the injection of the nozzle, characterized in that. 제 5 항에 있어서,The method of claim 5, 상기 하프 톤 패턴을 조정하는 단계는 각 세그먼트의 대응하는 노즐들이 함께 분사하지 않도록 인접하는 세그먼트의 노즐의 분사를 조정하는 단계를 포함하는 것을 특징으로 하는 노즐의 분사를 제어하는 방법.Adjusting the halftone pattern comprises adjusting the spraying of nozzles of adjacent segments such that corresponding nozzles of each segment do not spray together. 제 5 항에 있어서,The method of claim 5, 상기 하프 톤 패턴을 조정하는 단계는 상대측 세그먼트에 대한 디더 매트릭스의 역을 이용하는 단계를 포함하는 것을 특징으로 하는 노즐의 분사를 제어하는 방법.Adjusting the halftone pattern comprises using the inverse of the dither matrix for the opposing segment. 제 5 항에 있어서,The method of claim 5, 상기 하프 톤 패턴을 조정하는 단계는 상기 보간 함수의 현재의 보간 계수에 의해 주어지는 확률에 따라 확률적으로 어느 한 노즐 또는 다른 하나의 노즐에 출력 도트를 배분하는 단계를 포함하는 것을 특징으로 하는 노즐의 분사를 제어하는 방법.Adjusting the halftone pattern comprises randomly distributing output dots to one or the other nozzles according to a probability given by a current interpolation coefficient of the interpolation function. How to control the injection. 삭제delete 오버랩하는 복수의 프린트헤드 세그먼트와;A plurality of overlapping printhead segments; 인접하는 프린트헤드 세그먼트간의 오버랩의 정도를 측정하기 위한 적어도 하나의 수단과;At least one means for measuring the degree of overlap between adjacent printhead segments; 연속 톤 이미지의 하프 토닝을 제공하기 위한 수단과;Means for providing half toning of a continuous tone image; 인접하는 프린트헤드 세그먼트간의 오버랩으로 인하여 인쇄된 이미지에서 아티팩트를 저감하기 위해 상기 인접하는 세그먼트간의 오버랩 영역에서 상기 하프 토닝 수단을 조정하는 수단;Means for adjusting the half toning means in an overlap area between adjacent segments to reduce artifacts in a printed image due to overlap between adjacent print head segments; 을 포함하여 이루어지는 잉크 분사 프린트헤드 시스템.Ink jet printhead system comprising a. 삭제delete 삭제delete 제 10 항에 있어서,The method of claim 10, 상기 연속 톤 이미지의 하프 토닝을 제공하는 수단은 디더 매트릭스를 포함하고, 상기 하프 토닝 수단을 조정하는 수단은 2개의 입력(하나는 상기 디더 매트릭스의 출력이고, 다른 하나는 상기 인접하는 프린트헤드 세그먼트간의 오버랩 정도의 측정을 위한 적어도 하나의 수단으로부터 도출된 오버랩 신호)을 가지는 합산수단을 포함하는 것을 특징으로 하는 잉크 분사 프린트헤드 시스템.The means for providing half toning of the continuous tone image comprises a dither matrix, and the means for adjusting the half toning means comprises two inputs (one is the output of the dither matrix and the other is between the adjacent printhead segments). Ink summarizing means having an overlap signal derived from at least one means for measuring the degree of overlap. 제 13 항에 있어서,The method of claim 13, 상기 합산수단의 출력과 연속 톤 데이터 입력을 비교하여 인접하는 프린트헤드 세그먼트의 대응하는 노즐에 대한 하프 톤 데이터를 출력하는 비교수단을 더 포함하는 것을 특징으로 하는 잉크 분사 프린트헤드 시스템.And means for comparing the output of said summing means and a continuous tone data input to output halftone data for corresponding nozzles of adjacent printhead segments. 제 10 항에 있어서The method of claim 10 상기 인접하는 프린트헤드 세그먼트간의 오버랩 영역에서의 하프 토닝 수단을 조정하는 수단은 상대측 세그먼트에 대한 디더 매트릭스를 인버팅하는 수단을 포함하는 것을 특징으로 하는 잉크 분사 프린트헤드 시스템.And means for adjusting the half toning means in the overlap area between adjacent print head segments comprises means for inverting the dither matrix for the opposing segment. 제 13 항에 있어서,The method of claim 13, 인접하는 프린트헤드 세그먼트의 노즐을 구동하기 위한 하프 톤 데이터 값을 생성하기 위해 연속 톤 데이터 입력 신호로부터 상기 합산수단의 출력을 감산하는 수단을 더 포함하는 것을 특징으로 하는 잉크 분사 프린트헤드 시스템.And means for subtracting the output of the summing means from the continuous tone data input signal to generate halftone data values for driving nozzles of adjacent printhead segments. 공간적으로 오버랩하는 복수의 프린트헤드 세그먼트와;A plurality of printhead segments spatially overlapping; 인접하는 프린트헤드 세그먼트간의 오버랩의 정도를 측정하기 위한 적어도 하나의 수단과;At least one means for measuring the degree of overlap between adjacent printhead segments; 연속 톤 이미지의 하프 토닝을 제공하기 위한 수단과;Means for providing half toning of a continuous tone image; 인접하는 프린트헤드 세그먼트간의 오버랩으로 인하여 인쇄된 이미지에서 아티팩트를 저감하기 위해 상기 인접하는 세그먼트간의 오버랩 영역에서 상기 하프 토닝 수단을 조정하는 수단;Means for adjusting the half toning means in an overlap area between adjacent segments to reduce artifacts in a printed image due to overlap between adjacent print head segments; 을 포함하고,Including, 상기 연속 톤 이미지의 하프 토닝을 제공하기 위한 수단과 상기 인접하는 프린트헤드 세그먼트간의 아티팩트를 저감하기 위해 상기 인접하는 세그먼트간의 오버랩 영역에서 상기 하프 토닝 수단을 조정하는 수단은 프로그래머블 디지털 컴퓨터를 포함하고, 상기 컴퓨터는 인접하는 세그먼트의 대응하는 노즐이 함께 동시에 하나의 도트를 생성하지 않고 원하는 출력값이 인접하는 세그먼트의 두개의 입력 디더 매트릭스 값의 합보다 작도록 연속 톤 픽셀값을 재생하는 분산 도트 확률 디더링의 기능을 가지는 알고리즘이 프로그램되어 있는 잉크 분사 프린트헤드 시스템.Means for providing half toning of the continuous tone image and means for adjusting the half toning means in an overlap region between adjacent segments to reduce artifacts between adjacent printhead segments comprises a programmable digital computer; A computer provides the ability of distributed dot probability dithering to reproduce continuous tone pixel values such that the corresponding nozzles of adjacent segments do not simultaneously produce a single dot together and the desired output value is less than the sum of the two input dither matrix values of the adjacent segments. An ink jet printhead system having an algorithm programmed therein. 삭제delete 제 17 항에 있어서,The method of claim 17, 상기 인접하는 프린트헤드 세그먼트간의 오버랩 정도를 측정하는 적어도 하나의 수단은 상기 인접하는 프린트헤드 세그먼트의 상대적인 위치를 측정하는 수단 을 포함하는 것을 특징으로 하는 잉크 분사 프린트헤드 시스템.At least one means for measuring the degree of overlap between adjacent printhead segments comprises means for measuring the relative position of the adjacent printhead segments.
KR1020027015791A 2002-11-22 2000-05-24 Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead KR100790616B1 (en)

Priority Applications (1)

Application Number Priority Date Filing Date Title
KR1020027015791A KR100790616B1 (en) 2002-11-22 2000-05-24 Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
KR1020027015791A KR100790616B1 (en) 2002-11-22 2000-05-24 Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead

Publications (2)

Publication Number Publication Date
KR20030024679A KR20030024679A (en) 2003-03-26
KR100790616B1 true KR100790616B1 (en) 2007-12-31

Family

ID=41627947

Family Applications (1)

Application Number Title Priority Date Filing Date
KR1020027015791A KR100790616B1 (en) 2002-11-22 2000-05-24 Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead

Country Status (1)

Country Link
KR (1) KR100790616B1 (en)

Citations (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH08118647A (en) * 1994-10-28 1996-05-14 Canon Inc Method and apparatus for correcting recording head, recording head corrected by same apparatus and recording apparatus using recording head
JPH11198380A (en) * 1997-11-06 1999-07-27 Xerox Corp Ink jet printing head and printing method
JPH11334051A (en) * 1998-05-28 1999-12-07 Toshiba Tec Corp Ink jet recording device

Patent Citations (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH08118647A (en) * 1994-10-28 1996-05-14 Canon Inc Method and apparatus for correcting recording head, recording head corrected by same apparatus and recording apparatus using recording head
JPH11198380A (en) * 1997-11-06 1999-07-27 Xerox Corp Ink jet printing head and printing method
JPH11334051A (en) * 1998-05-28 1999-12-07 Toshiba Tec Corp Ink jet recording device

Non-Patent Citations (3)

* Cited by examiner, † Cited by third party
Title
일본공개특허 평08-118647호
일본공개특허 평11-198380호
일본공개특허 평11-334051호

Also Published As

Publication number Publication date
KR20030024679A (en) 2003-03-26

Similar Documents

Publication Publication Date Title
US7938498B2 (en) Inkjet printhead with overlapping segments
US7837289B2 (en) Method of printing with overlapped segements of printhead
US7744183B2 (en) Method of generating halftone print data for overlapping consecutive printhead segments
JP4254840B2 (en) Control of density unevenness in printing
JP2022034526A (en) Repetition uniformity compensation mechanism
AU2000247328A1 (en) Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead
KR100790616B1 (en) Method and apparatus for compensation for time varying nozzle misalignment in a drop on demand printhead
AU2004226970B2 (en) Inkjet printer having compensation for overlapping printhead elements
JPH0624877B2 (en) Inkjet recording method

Legal Events

Date Code Title Description
A201 Request for examination
AMND Amendment
E902 Notification of reason for refusal
AMND Amendment
E601 Decision to refuse application
J201 Request for trial against refusal decision
AMND Amendment
E902 Notification of reason for refusal
B701 Decision to grant
GRNT Written decision to grant
FPAY Annual fee payment

Payment date: 20121207

Year of fee payment: 6

FPAY Annual fee payment

Payment date: 20131210

Year of fee payment: 7

FPAY Annual fee payment

Payment date: 20141209

Year of fee payment: 8

FPAY Annual fee payment

Payment date: 20151207

Year of fee payment: 9

FPAY Annual fee payment

Payment date: 20161209

Year of fee payment: 10

FPAY Annual fee payment

Payment date: 20171212

Year of fee payment: 11

LAPS Lapse due to unpaid annual fee