2014-04-22 13 views
0

저는 석영 2D 및 목표 C를 사용하여 바느질 패턴을 PDF 파일로 출력하는 프로그램을 작성하고 있습니다. 파이썬에서 코딩 된 다른 프로그램을 사용하여 포스트 스크립트 파일을 출력합니다. 미리보기에서 열면 PDF로 변환됩니다. 두 번째 응용 프로그램은 오픈 소스이기 때문에 필자는 PDF 레이아웃에 사용하는 설정, 특히 사각형 사이의 갭 크기와 크기가 동일한 지 확인했습니다.포스트 스크립트 대 석영 2D에서 생성 된 PDF

아래 이미지에서 다른 프로그램의 출력은 왼쪽에 있고 광산은 오른쪽에 있고 둘 다 실제 크기입니다. 내가 겪고있는 문제는 실제 크기에서 출력물의 갭 라인이 간헐적 인 반면, 다른 한편으로는 모든 갭을 볼 수 있다는 것입니다. 누구든지 포스트 스크립트 파일과의 렌더링 차이에 대해 알고 있다면 궁금합니다. 내 출력을 확대 할 수 있으며 틈이 나타나지만 왜 이런 차이가 있는지 이해할 수 없습니다.

정사각형은 8 픽셀 너비와 높이가되도록 설정되어 있으며 두 응용 프로그램에서 간격이 1 픽셀 씩 간격이 2 픽셀 씩 10 개마다 정해지며 광산에서는 에일리어싱을 사용하지 않도록 설정됩니다. 필자는 CGPDFContext로 직접 드로잉을 시도하고 CGLayerRef로 드로잉하여 레이어를 PDF 컨텍스트로 드로잉 해 보았습니다. 그러나 동일한 결과를 얻었습니다. 레이아웃 배치에 정수 값을 사용하고 있으며 픽셀 위치의 일부에 사각형을 배치하는 것을 피했습니다.

또한 출력을 CGBitmapContext로 그려 넣고 결과 비트 맵을 PDF 컨텍스트로 그려 보았습니다. 그러나 확대 된 래스터이므로 끔찍한 결과가 나타납니다.

필자가 지적한 마지막 차이점은 포스트 스크립트에서 생성 된 PDF의 파일 크기가 제작 한 파일 크기보다 훨씬 작으며 그림 그리기 이후부터 그려야 할 경로와 관련이 있다고 생각합니다. PDF 컨텍스트는 그림을 파일에 기록 된 일련의 PDF 드로잉 명령으로 기록합니다. 이미지를 표시하는 것과 비교하면 상당히 많은 공간이 필요합니다.

필자는 아래 코드를 작성하여 도움이 될만한 코드를 포함 시켰지만, 포스트 스크립트와 Quartz 사이에 렌더링 차이가 있는지 궁금해하고 있습니다. 이러한 차이점을 설명 할 수 있고 내 출력이 일치하도록하십시오.

이 (업 로더 내가 이미지를 게시하려면 적어도 10 평판 필요하지만, 내가 다시이 링크 http://i.stack.imgur.com/nr588.jpg을 말한다 포스트 스크립트 출력은 왼쪽에, 내 석영 출력이 오른쪽에 내 출력에, 눈금 선은 간헐적)

-(void)makePDF:(NSImage*)image withPixelArray:(unsigned char *)rawData{ 

NSString *currentUserHomeDirectory = NSHomeDirectory(); 

currentUserHomeDirectory = [currentUserHomeDirectory stringByAppendingString:@"/Desktop/"]; 
currentUserHomeDirectory = [currentUserHomeDirectory stringByAppendingString:[image name]]; 
currentUserHomeDirectory = [currentUserHomeDirectory stringByAppendingPathExtension:@"pdf"]; 

CGContextRef pdfContext; 
CFStringRef path; 
CFURLRef url; 

int width = 792; 
int height = 612; 

CFMutableDictionaryRef myDictionary = NULL; 
CFMutableDictionaryRef pageDictionary = NULL; 

const char *filename = [currentUserHomeDirectory UTF8String]; 
path = CFStringCreateWithCString (NULL, filename, 
            kCFStringEncodingUTF8); 
url = CFURLCreateWithFileSystemPath (NULL, path, 
            kCFURLPOSIXPathStyle, 0); 
CFRelease (path); 
myDictionary = CFDictionaryCreateMutable(NULL, 0, 
             &kCFTypeDictionaryKeyCallBacks, 
             &kCFTypeDictionaryValueCallBacks); 

CGRect pageRect = CGRectMake(0, 0, width, height); 

pdfContext = CGPDFContextCreateWithURL (url, &pageRect, myDictionary); 

const CGFloat whitePoint[3]= {0.95047, 1.0, 1.08883}; 

const CGFloat blackPoint[3]={0,0,0}; 
const CGFloat gammavalues[3] = {2.2,2.2,2.2}; 
const CGFloat matrix[9] = {0.4124564, 0.3575761, 0.1804375, 0.2126729, 0.7151522, 0.072175, 0.0193339, 0.119192, 0.9503041}; 

CGColorSpaceRef myColorSpace = CGColorSpaceCreateCalibratedRGB(&whitePoint[3], &blackPoint[3], &gammavalues[3], &matrix[9]); 

CGContextSetFillColorSpace (
          pdfContext, 
          myColorSpace 
          ); 

int annotationNumber =0; 
int match=0; 

CFRelease(myDictionary); 
CFRelease(url); 
pageDictionary = CFDictionaryCreateMutable(NULL, 0, 
              &kCFTypeDictionaryKeyCallBacks, 
              &kCFTypeDictionaryValueCallBacks); 

CFDataRef boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof (CGRect)); 
CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData); 

int m = 0; 
int sidestep = 0; 
int downstep = 0; 
int maxc = 0; 
int maxr = 0; 
int columnsPerPage = 70; 
int rowsPerPage = 60; 

int symbolSize = 8; 
int gapSize=1; 


CGContextSetShouldAntialias(pdfContext, NO); 

int pages = ceil([image size].width/columnsPerPage) * ceil([image size].height/rowsPerPage); 

for (int g=0; g<pages; g++) { 

    int offsetX = 32; 
    int offsetY = 32; 

    if (sidestep == ceil([image size].width/columnsPerPage)-1) { 
     maxc=[image size].width-sidestep*columnsPerPage; 
    }else { 
     maxc=columnsPerPage; 
    } 

    if (downstep == ceil([image size].height/rowsPerPage)-1) { 
     maxr=[image size].height-downstep*rowsPerPage; 
    }else { 
     maxr=rowsPerPage; 
    } 

    CGPDFContextBeginPage (pdfContext, pageDictionary); 
    CGContextTranslateCTM(pdfContext, 0.0, 612); 
    CGContextScaleCTM(pdfContext, 1.0, -1.0); 
    CGContextSetShouldAntialias(pdfContext, NO); 
    int r=0; 

    while (r<maxr){ 
     int c=0; 
     while (c<maxc){ 
      m = sidestep*columnsPerPage+c+downstep*[image size].width*rowsPerPage+r*[image size].width; 

      //Reset offsetX 
      if (c==0) { 
       offsetX=32; 
      } 
      //Increase offset for gridlines 
      if (c==0 && r%10==0&&r!=0) { 
       offsetY+=2; 
      } 
      if (c%10==0&&c!=0) { 
       offsetX+=2; 
      } 
      //DRAW SQUARES 

      CGContextSetRGBFillColor (pdfContext, (double)rawData[m*4]/255.,(double) rawData[m*4+1]/255., (double)rawData[m*4+2]/255., 1); 

      CGContextFillRect (pdfContext, CGRectMake (c*(symbolSize+gapSize)+offsetX, r*(symbolSize+gapSize)+offsetY, symbolSize, symbolSize)); 

      if ([usedColorsPaths count]!=0) { 

       for (int z=0; z<[usedColorsPaths count]; z++) { 


        if ([[[usedColorsPaths allKeys] objectAtIndex:z] isEqualToString:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4], rawData[m*4+1], rawData[m*4+2]]]) { 
         match=1; 

         if (rawData[m*4+3] == 0) { 

          CGContextDrawLayerAtPoint (pdfContext, CGPointMake(c*(symbolSize+1)+offsetX-2, r*(symbolSize+1)+offsetY-2), [Anotations colorAnnotations:pdfContext :[[usedColorsPaths objectForKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4],rawData[m*4+1],rawData[m*4+2]]]intValue] :symbolSize+4 :0]); 

         } 
         else{ 

          CGContextDrawLayerAtPoint (pdfContext, CGPointMake(c*(symbolSize+1)+offsetX, r*(symbolSize+1)+offsetY),[Anotations colorAnnotations:pdfContext :[[usedColorsPaths objectForKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4], rawData[m*4+1], rawData[m*4+2]]] intValue] :symbolSize :0]); 
         } 
         break; 
        } 

       } 
       if (match==0) { 
        if (rawData[m*4+3] == 0) { 
         [usedColorsPaths setObject:[NSNumber numberWithInt:455] forKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4], rawData[m*4+1], rawData[m*4+2]]]; 

         CGContextDrawLayerAtPoint (pdfContext, CGPointMake(c*(symbolSize+1)+offsetX-2, r*(symbolSize+1)+offsetY-2), [Anotations colorAnnotations:pdfContext :[[usedColorsPaths objectForKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4],rawData[m*4+1],rawData[m*4+2]]]intValue] :symbolSize+4 :0]); 

        } 
        else{ 
         [usedColorsPaths setObject:[NSNumber numberWithInt:annotationNumber] forKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4], rawData[m*4+1], rawData[m*4+2]]]; 

         CGContextDrawLayerAtPoint (pdfContext, CGPointMake(c*(symbolSize+1)+offsetX, r*(symbolSize+1)+offsetY), [Anotations colorAnnotations:pdfContext :[[usedColorsPaths objectForKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4],rawData[m*4+1],rawData[m*4+2]]]intValue] :symbolSize :0]); 
        } 



        annotationNumber++; 

        if (annotationNumber==9) { 
         annotationNumber=0; 
        } 

       } 
       match=0; 
      } 
      if ([usedColorsPaths count]==0) { 

       if (rawData[m*4+3] == 0) { 
        [usedColorsPaths setObject:[NSNumber numberWithInt:455] forKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4], rawData[m*4+1], rawData[m*4+2]]]; 

        CGContextDrawLayerAtPoint (pdfContext, CGPointMake(c*(symbolSize+1)+offsetX-2, r*(symbolSize+1)+offsetY-2), [Anotations colorAnnotations:pdfContext :[[usedColorsPaths objectForKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4],rawData[m*4+1],rawData[m*4+2]]]intValue] :symbolSize+4 :0]); 
       } 
       else{ 

        [usedColorsPaths setObject:[NSNumber numberWithInt:annotationNumber] forKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4], rawData[m*4+1], rawData[m*4+2]]]; 

        CGContextDrawLayerAtPoint (pdfContext, CGPointMake(c*(symbolSize+1)+offsetX, r*(symbolSize+1)+offsetY), [Anotations colorAnnotations:pdfContext :[[usedColorsPaths objectForKey:[NSString stringWithFormat:@"%i,%i,%i",rawData[m*4],rawData[m*4+1],rawData[m*4+2]]]intValue] :symbolSize :0]); 
       } 

       annotationNumber++; 

      } 


      c++; 

     } 

     r++; 
    } 
    sidestep++; 
    if (sidestep == ceil([image size].width/columnsPerPage)) { 
     sidestep=0; 
     downstep+=1; 
    } 
    CGContextSaveGState(pdfContext); 

    CGPDFContextEndPage (pdfContext); 

} 

CGContextRelease(pdfContext); 
CFRelease(pageDictionary); 
CFRelease(boxData);} 

답변

0

크기가 다른, 또는 줄 간격이 여기에 간헐적이지만, 왜 몇 점의 이유에 대한 판단을 할 수 있기를 나는 모두 PDF 파일을 참조해야합니다 :

을 가장 파일 크기가 다른 이유는 하나의 PDF 파일에 내용 스트림 (사용자가 참조하는 그리기 작업) 압축 된 반면, 다른 압축하지 않습니다.

일반적으로 이미지 해상도가 매우 낮은 경우가 아니라면 비트 맵 이미지를 포함하는 것보다 드로잉 작업 시퀀스가 ​​더 간단합니다. RGB 이미지는 모든 이미지 샘플에 대해 3 바이트를 사용합니다. 300 dpi 크기의 1 인치 정사각형 이미지가 300x300x3 바이트 또는 270,000 바이트라고 생각하면 이미지가 모두 하나의 색상 (아래 예제 참조)이라면 22 바이트의 PDF 드로잉 작업에서 설명 할 수 있습니다.

제곱의 크기 또는 다른 그래픽 기능을 픽셀 단위로 지정할 수 없습니다. PDF는 비트 맵 형식이 아닌 벡터 기반 확장 가능 형식입니다. Mac에서 작동하지 않아 샘플 코드에 대해서는 언급 할 수 없지만 픽셀 너비와 높이 (픽셀 단위로 지정)를 혼동하는 것으로 의심됩니다. 이는 동일하지 않습니다.폭과 높이는 용지 크기를 나타내며, PDF 파일이 비트 맵으로 렌더링 될 때까지 관련된 픽셀이 없으며, 이때 장치의 해상도에 따라 각 포인트에 몇 개의 픽셀이 있는지가 결정됩니다.

PDF를 1 인치 정사각형으로 생각하십시오. 그 (72)의 폭과 나는 순수한 빨간색이 사각형을 채울 수 있습니다 (72)의 높이를 가질 것, 그에 대한 PDF 작업은 다음과 같습니다 그래서 RGB에 비 쓰다듬어 색상을 설정되어

1 0 0 rg 
0 0 72 72 re 

을 (1 , 0, 0), 0, 0 (왼쪽 하단)에서 시작하여 폭 72 포인트, 높이 72 포인트 (각 방향으로 1 인치)에 해당하는 사각형을 그 색상으로 채 웁니다.

여기 내 PC의 화면에서 1 인치 정사각형이 96x96 픽셀로 렌더링됩니다. 이제 저는 망막 디스플레이가있는 iPad에서 사각형을 보았습니다. 사각형은 264 픽셀 씩 264로 렌더링되었습니다. 마지막으로 레이저 프린터로 인쇄하면 정사각형은 600 픽셀 x 600으로 렌더링됩니다. PDF 내용은 변경되지 않았지만 확실히 픽셀 수가 있습니다. 사각형은 물론 단순합니다. 대신 원을 사용할 수 있었고 분명히 고해상도 디스플레이가 더 매끄러운 곡선을 갖게되었습니다. 물론, 이미지를 사용하면 커브의 매끄러움이 '구워집니다', 해상도를 변경하면 PDF를 렌더링 할 수있는 장치가 렌더링 될 수 있습니다. 렌더링 할 이미지 샘플을 버리거나 보간하는 것입니다. 새로운 것들. 크기를 줄이면 들쭉날쭉 해 보이며 크기를 늘리면 퍼지 어집니다. 벡터 표현은 부드럽고 현재 해상도에 의해서만 제한됩니다.

PDF의 요지는 PDF가 하나의 해상도에만 국한되지 않고 모든 파일에 인쇄 할 수 있으며 각 장치에서 출력이 가능한 한 동일해야한다는 것입니다.

이제는 "레이아웃 배치에 정수 값 사용"문제가 있다고 생각합니다. 그렇게하지 않으면 올바른 (즉, 예상 된) 결과를 얻을 수 없습니다. 레이아웃에 대해 실제 수치를 사용하여 위치를 미세하게 제어 할 수 있어야합니다. 당신이 이 아니고 개별 픽셀 주소 지정, 좌표 시스템에서 그래픽을 배치하고 있다는 것을 기억하십시오. 해상도는 PDF 파일 (즉,보기 또는 인쇄)을 렌더링 할 때만 나타납니다. 픽셀에 대한 관심을 제쳐두고 포지셔닝에만 집중해야합니다.

+0

답장을 보내 주셔서 감사합니다. 어도비 일러스트 레이터에서 약간의 작업을하므로 픽셀이 아닌 점을 사용하여 벡터가 만들어지는 방법을 얻지 만 PDF 컨텍스트를 만들 때 점의 페이지 크기를 나타내는 직사각형을 제공 한 다음 해당 컨텍스트에 그려야합니다. , 그릴 곳을 지정합니다. 나는 그들이 픽셀을 부름으로써 용어를 잘못 사용했다고 생각해. 미안. 저에게 PDF 예제를 공유 할 수있는 방법이 있다면 기꺼이 하겠지만 제가 제공 한 이미지는 예제의 직접적인 스크린 샷입니다. PDF로 그림을 그리는 것이 중독과 중독 사이의 공간을 보여주는 데 어려움을 겪고 있습니다. – nintandrew

+0

파일을 보관 용 계정에 집어 넣고 여기에 URL을 공유 하시겠습니까?사용하는 좌표는 실수가 아니고 정수가되어야하며 그렇게하면 제대로 작동해야합니다 (물론 Mac 프로그래머가 아니기 때문에 Quartz에 대해 전혀 알지 못합니다). Quartz가 당신을 정수 좌표로 제한한다고 생각할 수도 있지만, 그것은 거의 불가능할 것 같다. 단순히 실제 값을 대신 사용해 보았습니까? 아, 또한 확대 할 때 예상되는 틈이 나타나면 그 틈이 1 픽셀 너비보다 훨씬 작은 지점까지 출력을 확대하여 발생하는 뷰어의 인위적인 결과입니다. – KenS

+0

도움을 주셔서 감사합니다. 그러나 이것이 안티 앨리어싱 문제였습니다. 앤티 앨리어싱이 없으면 확대 된 뷰에서 프로그램에 단일 포인트 간격을 렌더링하는 데 문제가있었습니다. 수정 사항은 앤티 엘리 어싱을 다시 켜는 것이었고 결과물은 매력처럼 작동합니다. 이 문제를 조사 할 시간을내어 주셔서 감사합니다. 간과 한 것 같은 간단한 일이었습니다. – nintandrew

0

그래서 다른 일로 그 문제를 뒤범벅하면 내 문제로 인해 앤티 앨리어싱이 꺼져 있다는 것을 알았습니다. 더 선명한 그림을 원한다고 생각했지만 PDF에 벡터 그래픽이 포함되어 있기 때문에 앤티 엘리 어싱은 문제가 없으며 그래픽을 확대하여 선명하게 유지합니다.

내가 한 첫 번째 작업은 미리보기로, 미리보기> 환경 설정> PDF로 이동하여 "1 포인트를 1 화면 픽셀로 100 % 스케일로 정의"를 선택했습니다. 내 앤티 앨리어싱을 해제 한 상태에서 원하는대로 내 이미지가 표시되었지만 확대하면 미리보기가 어려워서 1 픽셀 간격을 그릴 때가 어려워졌습니다.

다음 코드를 변경하여 앤티 엘리 어싱을 끄고 내 출력이 완벽하게 렌더링되므로 앤티 앨리어싱을 사용하면 문제가 해결됩니다. 꽤 당혹스러워서 3 일 동안 알아낼 수 없지만,이 간단한 수정으로 인해 기쁩니다.