본문 바로가기


[프린터] FilterGraphics 래스터데이터 조작

  • 출처
  • 번역 : DwYoon
  • 최종수정일 : 20080215
From: "Ashwin Needamangala"
References: <#zK#IxCfCHA.348@tkmsftngp12>
Subject: Re: how to catch EMF spool file
Date: Fri, 25 Oct 2002 17:46:41 -0700
Message-ID: <#4NF1jIfCHA.1652@tkmsftngp09>
There are APIs provided by GDI for handling EMF files. For example, you could use GdiGetSpoolFileHandle in order to capture the spool file of a particular print job. Refer to the section titled "Using GDI Functions for Print Processors" in the DDK docs for more info. GDI가 제공하는 API중에 EMF파일을 다루는 게 있다. 예를 들어, GdiGetSpoolFileHandle을 이용해서 특정 프린트 잡의 스풀파일을 잡아낼 수 있다. 자세한 건 DDK 문서 중에 "Using GDI Functions for Print Processors" 참조.
As for general comments on your attempting to capture the spool file, I would not recommend it if all you want to do is write a virtual printer driver. I would instead recommend that you write a rendering plug-in similar to the oemuni sample in the DDK and use the IPrintOemUni::FilterGraphics function to dump the data to file. I am posting some additional info on FilterGraphics below. Hope it helps. 스풀파일을 잡아내려 한다는 데에 대해 커멘트 해 보자면, 버추얼 드라이버를 만드는 건 그리 권하지 않겠다. 나라면 DDK의 oemuni 샘플과 비슷한 플럭인을 만들어서 IPrintOemUni::FileterGraphis 함수로 데이터를 덤프하겠다. 아래에 FilterGraphics 에 대한 부가정보를 달았다. 도움이 되길.
The FilterGraphics callback is often used for implementing a bitmap printer driver. This document is throws some light on this callback. FilterGraphics 콜백은 주로 비트맵 프린터 등을 구현할 때 사용된다. 이 문서가 이해하 는 데 도움이 될 것이다.
Basically, you get scan line data in the FilterGraphics callback. 기본적으로 FilterGraphics 콜백에서는 스캔라인 데이터가 들어온다.
The IPrintOemUni::FilterGraphics function allows a rendering plug-in to modify scan line data and send it to the spooler. If you implement this, then Unidrv would not spool your data. instead your method will be called every time a buffer of data is sent and is ready to be spooled. The OEMFilterGraphics callback can be used to implement a special compression method, or to perform bit manipulation on the data stream that is sent to the printer, or both. In either case, the driver's built-in compression code is not used. OEMFilterGraphics is presented with a block of data and is required to send all output the data and to emit them using DrvWriteSpoolBuf. The driver will perform no further processing of the raster data after calling OEMFilterGraphics. IPrintOemUni::FilterGraphics 함수는 랜더링 플럭인이 스캔라인 데이터를 변경하여 스풀러로 보낼 수 있도록 해 준다. 이걸 구현한다면, Unidrv 는 너의 데이터를 스풀하지 않고, 대신 당신이 만든 매소드가 데이터 버퍼를 보내고 스풀준비 됐을 때마다 불릴 것이 다. OEMFilterGraphics 콜백은 특정 압축방법 적용하거나, 프린터로 전송되는 데이터 스트림에 비트 조작을 하기 위해 사용될 수 있다. 어떤 경우에도 드라이버의 빌트인 압축 코드는 사용되지 않는다. OEMFilterGraphics 에는 데이터 블럭이 주어지고, 데이터 아웃풋을 전송, 방출할 때 DrvWriteSpoolBuf 를 사용하여야 한다. 드라이버는  OEMFilterGraphics가 호출된 이후에는 래스터 데이터에 대해 더 이상의 프로세싱을 진행하지 않는다.
I would recommend that you first simply experiment with the OEMUNI sample from the DDK as is. That is, just build the sample in a Checked build environment, enable full debug logging (through the sources file for this sample) and install it on a test machine using the OEMDLL.inf. Then, try printing something very simple from wordpad and observe the debug spew in Windbg. You should see the FilterGraphics() callback spitted out a number of times. Then you can try setting a breakpoint at the return in - 우선은 DDK의 OEMUNI 샘플을 그대로 사용해서 테스트를 해 보길 추천한다. 무슨 말이냐 하면 샘플을 (샘플의 소스파일을 통해서) 풀 디버깅 로깅을 활성화하여 체크빌드 환경 에서 빌드하고, OEMDLL.inf 로 테스트 머신에 인스톨한다. 그리고 간단한 걸 인쇄해 보고 Windbg 에 나오는 디버그 메시지를 관찰한다. FilterGraphics() 콜백이 몇 번 나오는 걸 볼 수 있을 것이다. 그리고 나서 아래 코드의 리턴에 브레이크포인트를 설정해 본다.
HRESULT __stdcall IOemUni::FilterGraphics(    PDEVOBJ   pdevobj,    PBYTE
pBuf,    DWORD       dwLen)
 DWORD dwResult;
 DebugMsg(DLLTEXT("IOemUni::FilterGraphics() entry.\r\n"));
 m_pOEMHelp->DrvWriteSpoolBuf(pdevobj, pBuf, dwLen, &dwResult);
 if (dwResult == dwLen)
  return S_OK;
  return S_FALSE;
You might want to experiment with Paint and then with text. When you provide the FilterGraphics callback in your OEM DLL, it will be used for sending the raster data directly to the printer. The number of scanlines in a block is specified through the optional parameter in the *Resolution section in the gpd : *PinsPerPhysPass (this is explained in the DDK too under < Option Attributes for the Resolution Feature >. This parameter is optional and if not mentioned, it is 1, as for most of the InkJet and page printers; else it should be a multiple of 8. In the FilterGraphics callback above, pBuf points to the buffer containing the scanline raster data to be manipulated by the OEM if necessary (eg compress etc) and finally sent out. dwLen is the length of this buffer. 페인트와 텍스트로 테스트를 해 보라. FilterGraphics 콜백을 OEM DLL에 넣으면, 그 콜백은 래스터 데이터를 프린터로 직접 보내는 데 사용된다. 한 블럭의 스캔라인수는 gpd의 *Resolution 섹션의 옵셔널 패러미터 *PinsPerPhysPass를 이용해 지정할 수 있다. (이에 관한 설명은 DDK 문서 < Option Attributes for the Resolution Feature >을 참조). 이 패러미터는 옵션이며, 지정되지 않았을 때에는 대부분의 잉크젯과 페이지 프린터에서는 1이 되고, 지정하려면 8의 배수여야 한다. 위의 FilterGraphics 콜백에서는 pBuf가 스캔라인 래스터 데이터를 담은 버퍼이고, OEM이 이 버퍼에 대해 압축 등의 조작을 해 내보낼 수 있다. dwLen은 이 버퍼의 길이이다.
Examples why OEMs use the FilterGraphics callback in their plugins are: 1. special compression techniques, 2. Bit manipulation of the incoming raster data before sending it out to the printer etc. (which is what you seem primararily interested in, right?) All the data should finally be sent by FilterGraphics to the printer using the function DrvWriteSpoolBuf(). The driver does not do any more processing on this data sent out by FilterGraphics(). Now, if the OEM is indeed doing some special compression/bit manipulation, he is responsible for allocation of the buffers necessary for doing so. If you do not allocate your own buffers, then your output will overwrite the source buffer if the compresses data is smaller than the source. OEM 이 플럭인에서 FilterGraphics 콜백을 사용하는 예를 들면: 1. 특수 압축 기술, 2. 들어온 래스터 데이터를 내보내기 전에 비트조작하는 것. FilterGraphics가 마지막에 프린터로 전송하는 데이터는 모두 DrvWriteSpoolBuf()를 사용해야 한다. 드라이버는 FilterGraphics()가 전송한 데이터에 대해 더 이상의 작업을 하지 않는다. 자, OEM이 정말 압축이나 비트조작을 하려고 한다면, 이 조작을 위해 필요한 버퍼 할당은 OEM이 해야 한다. 버퍼를 할당하지 않는다면, 압축 데이터가 소스보다 작을 때 결과가 소스를 덮어써 버릴 것이다.
Thus, I think, you should be able to accomplish the raster data manipulation in the plugin using OEMFilterGraphics(). What you are given is simply a chance to postprocess the raster data and the access to the data itself. What you do with it is pretty much upto you and completely in your hand. 그래서, 플럭인에서 OEMFilterGraphics()를 사용하면, 래스터 데이터 조작을 할 수 있을거라 생각한다. 넌 래스터 데이터를 포스트프로세스할 수 있고, 데이터에 접근할 수도 있다. 그걸로 뭘 할지는 완전히 너에게 달려있다.
Using FilterGraphics, you will be getting a known number of scan lines (1 row of 1bpp bitmap) OR The number of scanlines is actually equal to = *PinsPerPhysPass. For monochrome, you have 1 pixel = 1 byte. Bit depth = num of bits/pixel = 1 for monochrome (1bpp). Thus, number of bytes in one scan line = num of pixels/line = page width in pixels (bytes).  
Number of scan lines = Height of the image; for 1bpp, thickness of each scan line = width of 1 pixel; thus num of scan lines=height of image.  
- Ashwin This posting is provided "AS IS" with no warranties, and confers no rights.