diff --git a/QuickDrawViewer/Info.plist b/QuickDrawViewer/Info.plist index c01fceb..ad27746 100644 --- a/QuickDrawViewer/Info.plist +++ b/QuickDrawViewer/Info.plist @@ -17,30 +17,30 @@ CFBundleTypeRole Viewer + CFBundleTypeName + Apple QuicDraw pictures LSItemContentTypes com.apple.pict - CFBundleTypeName - Apple QuicDraw pictures - - - CFBundleTypeRole - None - CFBundleTypeName - PDF - LSItemContentTypes - - com.adobe.pdf - + + CFBundleTypeRole + Viewer + CFBundleTypeName + Apple MacPaint pictures + LSItemContentTypes + + com.apple.macpaint-image + + UTImportedTypeDeclarations UTTypeConformsTo - + public.image UTTypeDescription QuickTime Picture @@ -57,7 +57,7 @@ UTTypeConformsTo - public.plain-text + public.image UTTypeDescription Quickdraw Picture @@ -71,6 +71,23 @@ + + UTTypeConformsTo + + public.image + + UTTypeDescription + MacPaint Picture + UTTypeIdentifier + com.apple.macpaint-image + UTTypeTagSpecification + + public.filename-extension + + pntg + + + diff --git a/QuickDrawViewer/MacPaint.swift b/QuickDrawViewer/MacPaint.swift index e7aa2fa..4516794 100644 --- a/QuickDrawViewer/MacPaint.swift +++ b/QuickDrawViewer/MacPaint.swift @@ -7,18 +7,45 @@ import Foundation -// MacPaint images are fixed size (720 × 576) PackBit compressed bitmaps. +/// MacPaint images are fixed size (720 × 576) PackBit compressed bitmaps. class MacPaintImage : PixMapMetadata { func load(data : Data) throws { self.bitmap = try DecompressPackBit(data: Array(data), unpackedSize: 720 * 72); + // For some reason, MacPaint pictures have black and white inverted. + for i in 0.. some OpCode { + let bitRect = BitRectOpcode(isPacked: true); + bitRect.bitmapInfo.rowBytes = self.rowBytes; + let frame = QDRect(topLeft: .zero, dimension: self.dimensions); + bitRect.bitmapInfo.bounds = frame; + bitRect.bitmapInfo.srcRect = frame; + bitRect.bitmapInfo.dstRect = frame; + bitRect.bitmapInfo.data = bitmap; + return bitRect; + } + + /// Convert a MacPaint images into a minimalistic picture. + /// This is enough for this program, but a valid quickdraw file would have some header operations. + func macPicture(filename: String?) -> QDPicture { + let frame = QDRect(topLeft: .zero, dimension: self.dimensions); + let picture = QDPicture(size: -1, frame: frame, filename: filename); + picture.opcodes.append(makeOpcode()); + return picture; } let rowBytes: Int = 72; // 576 ÷ 8 var cmpSize: Int = 1; var pixelSize: Int = 1; let dimensions = QDDelta(dv: FixedPoint(720), dh: FixedPoint(576)); - var clut: QDColorTable? = QDColorTable.whiteBlack; + var clut: QDColorTable? = QDColorTable.blackWhite; var bitmap: [UInt8] = []; - } + diff --git a/QuickDrawViewer/QuickTime.swift b/QuickDrawViewer/QuickTime.swift index 4139c38..6d13da5 100644 --- a/QuickDrawViewer/QuickTime.swift +++ b/QuickDrawViewer/QuickTime.swift @@ -399,6 +399,8 @@ func parseQuickTimeStream(reader: QuickDrawDataReader, quicktimePayload: inout Q /// Parse a QuickTime image into a QuickDraw picture. /// This will fail if the QuickTime image does not have an `idsc` (image description) atom. +/// Note that the resulting file is enough for this program, a valid QuickDraw file would require some +/// header operations. /// - Parameter reader: reader pointing to the data. /// - Throws: if data is corrupt / unreadable /// - Returns: a _fake_ QuickDraw image with a single QuickTime opcode. diff --git a/QuickDrawViewer/UI/QuickDrawViewerDocument.swift b/QuickDrawViewer/UI/QuickDrawViewerDocument.swift index 618f538..eb4f7ea 100644 --- a/QuickDrawViewer/UI/QuickDrawViewerDocument.swift +++ b/QuickDrawViewer/UI/QuickDrawViewerDocument.swift @@ -16,6 +16,9 @@ extension UTType { static var quickTimeImage: UTType { UTType(importedAs: "com.apple.quicktime-image") } + static var macPaintImage : UTType { + UTType(importedAs: "com.apple.macpaint-image") + } } struct QuickDrawViewerDocument: FileDocument { @@ -58,12 +61,17 @@ struct QuickDrawViewerDocument: FileDocument { logger.log(level: .error, "Failed parsing quicktime: \(error)"); throw error; } + case .macPaintImage: + let macPaint = MacPaintImage(); + try macPaint.load(data: data.subdata(in: 512.. FileWrapper { diff --git a/README.md b/README.md index 54c7977..c6dd6b1 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,17 @@ I wanted to teach myself Swift programming, and needed something a bit more invo This program is far from finished, but I decided to release it for the 40th anniversary of the original Macintosh computer: QuickDraw was the graphical language of the original Macintosh, and the format used to store and exchange images on the computer. Support for these files has been slowly decaying with newer versions of Mac OS X, and on my M1 PowerBook, Preview can only open a small subset of the files I have. +## Supported File types + +This application basically handles QuickDraw image files, but also two related (but distinct) image formats: + +* QuickTime images (`QTIF`) +* MacPaint images (`PNTG`) + +These two formats are handled by converting them into QuickDraw at load time. +QuickTime images are supported so far as the underlying codec is supported. +MacPaint images are supported by virtue of being one of codecs that can be embedded inside QuickTime. + ## Structure This program has basically three parts: @@ -36,7 +47,6 @@ It supports the following features. * MacPaint * Apple Video (`RPZA`), Apple Component Video (`YUV2`). * Planar Video (`8BPS`). -* QuickTime images which use a supported codec (see above). Some basic comment parsing is used to improve images, in particular: