fixes issue #565, NSRecursiveLock_win32 header fix, better PDF DCTDecode, LZW PDF stream decompress, PDF inline images fix

This commit is contained in:
Christopher Lloyd 2010-12-15 22:39:25 -05:00
parent d68d54ba12
commit 6ddb01ce98
11 changed files with 161 additions and 51 deletions

View File

@ -6,21 +6,21 @@ typedef struct _O2ImageDestination *CGImageDestinationRef;
#import <CoreGraphics/CGDataConsumer.h>
#import <CoreFoundation/CFURL.h>
const CFStringRef kCGImageDestinationLossyCompressionQuality;
const CFStringRef kCGImageDestinationBackgroundColor;
COREGRAPHICS_EXPORT const CFStringRef kCGImageDestinationLossyCompressionQuality;
COREGRAPHICS_EXPORT const CFStringRef kCGImageDestinationBackgroundColor;
CFTypeID CGImageDestinationGetTypeID(void);
COREGRAPHICS_EXPORT CFTypeID CGImageDestinationGetTypeID(void);
CFArrayRef CGImageDestinationCopyTypeIdentifiers(void);
COREGRAPHICS_EXPORT CFArrayRef CGImageDestinationCopyTypeIdentifiers(void);
CGImageDestinationRef CGImageDestinationCreateWithData(CFMutableDataRef data,CFStringRef type,size_t imageCount,CFDictionaryRef options);
CGImageDestinationRef CGImageDestinationCreateWithDataConsumer(CGDataConsumerRef dataConsumer,CFStringRef type,size_t imageCount,CFDictionaryRef options);
CGImageDestinationRef CGImageDestinationCreateWithURL(CFURLRef url,CFStringRef type,size_t imageCount,CFDictionaryRef options);
COREGRAPHICS_EXPORT CGImageDestinationRef CGImageDestinationCreateWithData(CFMutableDataRef data,CFStringRef type,size_t imageCount,CFDictionaryRef options);
COREGRAPHICS_EXPORT CGImageDestinationRef CGImageDestinationCreateWithDataConsumer(CGDataConsumerRef dataConsumer,CFStringRef type,size_t imageCount,CFDictionaryRef options);
COREGRAPHICS_EXPORT CGImageDestinationRef CGImageDestinationCreateWithURL(CFURLRef url,CFStringRef type,size_t imageCount,CFDictionaryRef options);
void CGImageDestinationSetProperties(CGImageDestinationRef self,CFDictionaryRef properties);
COREGRAPHICS_EXPORT void CGImageDestinationSetProperties(CGImageDestinationRef self,CFDictionaryRef properties);
void CGImageDestinationAddImage(CGImageDestinationRef self,CGImageRef image,CFDictionaryRef properties);
void CGImageDestinationAddImageFromSource(CGImageDestinationRef self,CGImageSourceRef imageSource,size_t index,CFDictionaryRef properties);
COREGRAPHICS_EXPORT void CGImageDestinationAddImage(CGImageDestinationRef self,CGImageRef image,CFDictionaryRef properties);
COREGRAPHICS_EXPORT void CGImageDestinationAddImageFromSource(CGImageDestinationRef self,CGImageSourceRef imageSource,size_t index,CFDictionaryRef properties);
bool CGImageDestinationFinalize(CGImageDestinationRef self);
COREGRAPHICS_EXPORT bool CGImageDestinationFinalize(CGImageDestinationRef self);

View File

@ -5,11 +5,10 @@
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#import <Cocoa/Cocoa.h>
#import <Foundation/NSLock.h>
#import <windows.h>
@interface NSRecursiveLock_win32 : NSObject <NSLocking> {
@interface NSRecursiveLock_win32 : NSRecursiveLock <NSLocking> {
CRITICAL_SECTION _lock;
NSString *_name;
}

View File

@ -39,7 +39,7 @@ CFDataRef O2DataProviderCopyData(O2DataProviderRef self);
size_t O2DataProviderRewind(O2DataProviderRef self);
size_t O2DataProviderGetBytesAtPosition(O2DataProviderRef self,void *buffer,size_t length,size_t position);
size_t O2DataProviderGetBytesAtPosition(O2DataProviderRef self,void *buffer,size_t length,size_t position);
size_t O2DataProviderGetBytes(O2DataProviderRef self,void *buffer,size_t length);
-(NSInputStream *)inputStream;

View File

@ -1059,14 +1059,15 @@ NSData *O2DCTDecode(NSData *data) {
jpeg decoder;
int width,height;
int comp;
int bitsPerPixel=8;
int bytesPerRow=(bitsPerPixel/(sizeof(char)*8))*width;
void *bytes=stbi_jpeg_load_from_memory(&decoder,[data bytes],[data length],&width,&height,&comp,STBI_grey);
void *bytes=stbi_jpeg_load_from_memory(&decoder,[data bytes],[data length],&width,&height,&comp,STBI_default);
int bytesPerRow=comp*width;
if(bytes==NULL)
return nil;
return [[NSData alloc] initWithBytesNoCopy:bytes length:bytesPerRow*height];
NSData *result=[[NSData alloc] initWithBytesNoCopy:bytes length:bytesPerRow*height];
return result;
}
+(BOOL)isPresentInDataProvider:(O2DataProvider *)provider {

View File

@ -53,5 +53,4 @@ typedef struct LZWFileType {
} LZWFileType;
int DLZWSetupDecompress(LZWFileType * LZWFile);
int DLZWDecompressLine(LZWFileType * LZWFile,LZWPixelType * Line,int LineLen);
NSData *LZWDecodeWithExpectedResultLength(NSData *data,unsigned stripLength);

View File

@ -22,6 +22,7 @@ THE SOFTWARE.
*/
#import <Onyx2D/O2LZW.h>
#import <Onyx2D/O2DataConsumer.h>
#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
#define LZ_BITS 12
@ -153,7 +154,7 @@ static int DLZWGetPrefixChar(LZWPrefixType *Prefix,int Code,int ClearCode) {
return Code;
}
int DLZWDecompressLine(LZWFileType * LZWFile,LZWPixelType * Line,int LineLen) {
int DLZWDecompressLine(LZWFileType * LZWFile,O2DataConsumerRef consumer,int LineLen) {
int i = 0;
int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
@ -196,7 +197,10 @@ int DLZWDecompressLine(LZWFileType * LZWFile,LZWPixelType * Line,int LineLen) {
} else {
if (CrntCode < ClearCode) {
/* This is simple - its pixel scalar, so add it to output: */
Line[i] = CrntCode;
uint8_t bytes[1];
bytes[0]=CrntCode;
O2DataConsumerPutBytes(consumer,bytes,1);
i++;
} else
#define RUNNING_CODE_MINUS 2
@ -244,8 +248,11 @@ int DLZWDecompressLine(LZWFileType * LZWFile,LZWPixelType * Line,int LineLen) {
/* Now lets pop all the stack into output: */
while (StackPtr != 0 && i < LineLen){
uint8_t bytes[1];
bytes[0]=Stack[--StackPtr];
O2DataConsumerPutBytes(consumer,bytes,1);
Line[i] = Stack[--StackPtr];
i++;
}
}
@ -272,3 +279,24 @@ int DLZWDecompressLine(LZWFileType * LZWFile,LZWPixelType * Line,int LineLen) {
return GIF_OK;
}
NSData *LZWDecodeWithExpectedResultLength(NSData *data,unsigned stripLength){
NSMutableData *outputData=[NSMutableData data];
O2DataConsumerRef consumer=O2DataConsumerCreateWithCFData(outputData);
LZWFileType lzwStream;
lzwStream.inputStream=[NSInputStream inputStreamWithData:data];
[lzwStream.inputStream open];
lzwStream.PixelCount=stripLength;
DLZWSetupDecompress(&lzwStream);
int error;
if((error=DLZWDecompressLine(&lzwStream,consumer,stripLength))==0)
NSLog(@"error=%d",error);
O2DataConsumerRelease(consumer);
return outputData;
}

View File

@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
#import <Onyx2D/O2zlib.h>
#import <Onyx2D/O2LZW.h>
#import <string.h>
#import <Onyx2D/O2ImageSource_JPEG.h>
@ -36,7 +37,7 @@ NSData *O2PDFFilterWithName(const char *name,NSData *data,O2PDFDictionary *param
}
+(NSData *)LZWDecode_data:(NSData *)data parameters:(O2PDFDictionary *)parameters {
return nil;
return LZWDecodeWithExpectedResultLength(data,[data length]*10);
}
+(NSData *)decodeWithName:(const char *)name data:(NSData *)data parameters:(O2PDFDictionary *)parameters {
@ -45,6 +46,9 @@ NSData *O2PDFFilterWithName(const char *name,NSData *data,O2PDFDictionary *param
else if((strcmp(name,"DCTDecode")==0) || (strcmp(name,"DCT")==0)){
return O2DCTDecode(data);
}
else if((strcmp(name,"LZWDecode")==0) || (strcmp(name,"LZW")==0)){
data=LZWDecodeWithExpectedResultLength(data,[data length]*10);
}
else {
O2PDFError(__FILE__,__LINE__,@"Unknown O2PDFFilter name = %s, parameters=%@",name,parameters);
return nil;

View File

@ -86,7 +86,7 @@ void O2PDF_render_BDC(O2PDFScanner *scanner,void *info) {
// Begin inline image object
void O2PDF_render_BI(O2PDFScanner *scanner,void *info) {
O2PDFFix(__FILE__,__LINE__,@"BI unimplemented");
// do nothing, all the values are pushed on the stack and ID handles them
}
// Begin marked-content sequence
@ -362,7 +362,7 @@ void O2PDF_render_DP(O2PDFScanner *scanner,void *info) {
// End inline image object
void O2PDF_render_EI(O2PDFScanner *scanner,void *info) {
O2PDFFix(__FILE__,__LINE__,@"EI unimplemented");
// do nothing, everything is implemented by ID, EI is a formality
}
// End marked-content sequence
@ -615,7 +615,76 @@ void O2PDF_render_i(O2PDFScanner *scanner,void *info) {
// Begin inline image data
void O2PDF_render_ID(O2PDFScanner *scanner,void *info) {
O2PDFFix(__FILE__,__LINE__,@"ID unimplemented");
O2PDFDictionary *dictionary=[O2PDFDictionary pdfDictionary];
while(YES) {
O2PDFObject *value;
const char *key;
if(!O2PDFScannerPopObject(scanner,&value))
break;
if(!O2PDFScannerPopName(scanner,&key)){
O2PDFError(__FILE__,__LINE__,@"popName failed");
break;
}
[dictionary setObjectForKey:key value:value];
}
O2PDFInteger bitsPerComponent=0;
O2PDFObject *colorSpace=NULL;
O2PDFArray *decode=NULL;
O2PDFObject *decodeParms=NULL;
O2PDFObject *filter=NULL;
O2PDFInteger height=0;
O2PDFBoolean imageMask=NO;
const char *intent=NULL;
O2PDFBoolean interpolate=NO;
O2PDFInteger width=0;
if(![dictionary getIntegerForKey:"BPC" value:&bitsPerComponent])
if(![dictionary getIntegerForKey:"BitsPerComponent" value:&bitsPerComponent]){
}
if(![dictionary getObjectForKey:"CS" value:&colorSpace])
if(![dictionary getObjectForKey:"ColorSpace" value:&colorSpace]){
}
if(![dictionary getArrayForKey:"D" value:&decode])
if(![dictionary getArrayForKey:"Decode" value:&decode]){
}
if(![dictionary getObjectForKey:"DP" value:&decodeParms])
if(![dictionary getObjectForKey:"DecodeParms" value:&decodeParms]){
}
if(![dictionary getObjectForKey:"F" value:&filter])
if(![dictionary getObjectForKey:"Filter" value:&filter]){
}
if(![dictionary getIntegerForKey:"H" value:&height])
if(![dictionary getIntegerForKey:"Height" value:&height]){
}
if(![dictionary getBooleanForKey:"IM" value:&imageMask])
if(![dictionary getBooleanForKey:"ImageMask" value:&imageMask]){
}
if(![dictionary getObjectForKey:"Intent" value:&intent])
if(![dictionary getBooleanForKey:"I" value:&interpolate])
if(![dictionary getBooleanForKey:"Interpolate" value:&interpolate]){
}
if(![dictionary getIntegerForKey:"W" value:&width])
if(![dictionary getIntegerForKey:"Width" value:&width]){
}
size_t bytesPerRow=(width*bitsPerComponent)/8;
NSData *data=O2PDFScannerCreateDataWithLength(scanner,height*bytesPerRow);
}
// setlinejoin, Set line join style

View File

@ -8,6 +8,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import <Onyx2D/O2PDFObject.h>
@class O2PDFScanner;
typedef O2PDFScanner *O2PDFScannerRef;
@class NSData,NSMutableArray;
@class O2PDFContentStream,O2PDFOperatorTable;
@class O2PDFString,O2PDFArray,O2PDFDictionary,O2PDFStream,O2PDFxref,O2PDFObject_identifier;
@ -26,6 +30,8 @@ BOOL O2PDFParseIndirectObject(NSData *data,O2PDFInteger position,O2PDFObject **o
O2PDFContentStream *_stream;
O2PDFOperatorTable *_operatorTable;
void *_info;
O2PDFInteger _currentStream;
O2PDFInteger _position;
}
-initWithContentStream:(O2PDFContentStream *)stream operatorTable:(O2PDFOperatorTable *)operatorTable info:(void *)info;
@ -42,6 +48,9 @@ BOOL O2PDFScannerPopArray(O2PDFScanner *scanner,O2PDFArray **value);
BOOL O2PDFScannerPopDictionary(O2PDFScanner *scanner,O2PDFDictionary **value);
BOOL O2PDFScannerPopStream(O2PDFScanner *scanner,O2PDFStream **value);
NSData *O2PDFScannerCreateDataWithLength(O2PDFScanner *scanner,size_t length);
-(BOOL)scan;
@end

View File

@ -1122,20 +1122,38 @@ BOOL O2PDFScannerPopStream(O2PDFScanner *self,O2PDFStream **value) {
return [lastObject checkForType:kO2PDFObjectTypeStream value:value];
}
NSData *O2PDFScannerCreateDataWithLength(O2PDFScanner *self,size_t length) {
NSArray *streams=[self->_stream streams];
O2PDFObject *object=[streams objectAtIndex:self->_currentStream];
O2PDFStream *stream;
if(![object checkForType:kO2PDFObjectTypeStream value:&stream])
return nil;
NSData *data=[stream data];
NSData *result=[data subdataWithRange:NSMakeRange(self->_position,length)];
self->_position+=length;
return result;
}
-(BOOL)scanStream:(O2PDFStream *)stream {
O2PDFxref *xref=[stream xref];
NSData *data=[stream data];
const char *bytes=[data bytes];
unsigned length=[data length];
O2PDFInteger position=0;
_position=0;
if(O2PDFScannerDumpStream)
NSLog(@"data[%d]=%@",[data length],[[[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding] autorelease]);
while(position<length) {
while(_position<length) {
O2PDFObject *object;
if(!O2PDFParseObject(bytes,length,position,&position,&object,xref))
if(!O2PDFParseObject(bytes,length,_position,&_position,&object,xref))
return NO;
if(object==NULL)
@ -1162,10 +1180,10 @@ BOOL O2PDFScannerPopStream(O2PDFScanner *self,O2PDFStream **value) {
-(BOOL)scan {
BOOL result=YES;
NSArray *streams=[_stream streams];
int i,count=[streams count];
int count=[streams count];
for(i=0;(i<count) && result;i++){
O2PDFObject *object=[streams objectAtIndex:i];
for(_currentStream=0;(_currentStream<count) && result;_currentStream++){
O2PDFObject *object=[streams objectAtIndex:_currentStream];
O2PDFStream *scan;
if(![object checkForType:kO2PDFObjectTypeStream value:&scan])

View File

@ -316,23 +316,6 @@ static void decode_R8_G8_B8_Afill(const unsigned char *stripBytes,unsigned byteC
*pixelBytesRowp=pixelBytesRow;
}
NSData *LZWDecode(NSData *data,unsigned stripLength){
NSMutableData *result=[NSMutableData dataWithLength:stripLength];
LZWFileType lzwStream;
lzwStream.inputStream=[NSInputStream inputStreamWithData:data];
[lzwStream.inputStream open];
lzwStream.PixelCount=stripLength;
DLZWSetupDecompress(&lzwStream);
int error;
if((error=DLZWDecompressLine(&lzwStream,[result mutableBytes],stripLength))==0)
NSLog(@"error=%d",error);
return result;
}
void depredict_R8G8B8A8(uint8_t *pixelBytes,unsigned bytesPerRow,unsigned height){
int y;
@ -430,7 +413,7 @@ void depredict_R8G8B8A8(uint8_t *pixelBytes,unsigned bytesPerRow,unsigned height
stripLength*=bytesPerRow;
data=LZWDecode(data,stripLength);
data=LZWDecodeWithExpectedResultLength(data,stripLength);
if(_samplesPerPixel==4)
decode_R8_G8_B8_A8([data bytes],stripLength,pixelBytes,_imageWidth*4,&pixelBytesRow,_imageLength);