【发布时间】:2014-04-22 03:10:55
【问题描述】:
我正在开发一个程序,该程序使用 Quartz 2D 和 Objective C 将针线图案输出为 PDF 文件。我使用了另一个用 Python 编码的程序,它输出 postscript 文件,当我打开它们时将它们转换为 PDF预览。由于第二个应用程序是开源的,我已经能够检查我用于布局我的 PDF 的设置是否相同,特别是正方形的大小和它们之间的间隙大小。
在下图中,另一个程序的输出在左侧,而我的在右侧,两者都是实际大小。我遇到的问题是,在实际大小下,我的输出中的间隙线是断断续续的,而在另一个中,所有的间隙都可以看到。我想知道是否有人知道允许这样做的 postscript 文件的渲染差异。我可以放大我的输出并显示差距,但我不明白为什么会有这种差异。
正方形设置为 8 像素宽和高,在两个应用程序中它们之间有 1 像素的间隙,每 10 个正方形有 2 像素宽的间隙,我的设置为不使用抗锯齿。通过我的输出,我尝试直接绘制到 CGPDFContext 并绘制到 CGLayerRef 然后将图层绘制到 PDF 上下文,但我得到了相同的结果。我使用整数值来定位布局,并且我很确定我已经避免尝试将正方形放置在像素位置的小数部分中。
我也尝试将输出绘制到 CGBitmapContext,然后将生成的位图绘制到 PDF 上下文,但放大后会产生可怕的伪影,因为它是被放大的光栅。
我注意到的最后一个区别是 postscript 生成的 PDF 的文件大小比我制作的要小得多,我认为这可能与我绘制的路径有关,因为它说要绘制到PDF 上下文将绘图记录为写入文件的一系列 PDF 绘图命令,我想这与仅显示图像相比会占用相当多的空间。
我已经在下面包含了我的代码来生成我的 PDF,以防它会有所帮助,但我真的只是想知道 postscript 和 Quartz 之间是否存在可以解释这些差异的渲染差异,以及是否有办法制作我的输出匹配。
(上传者说我需要至少 10 个声望才能发布图片,但我再次拥有此链接 http://i.stack.imgur.com/nr588.jpg,postscript 输出在左侧,我的 Quartz 输出在右侧,在我的输出中,网格线是间歇)
-(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);}
【问题讨论】:
标签: objective-c macos pdf-generation quartz-2d postscript