mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-06 21:29:27 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
12 KiB
C
1 line
12 KiB
C
/*********************************************************/
|
|
/* This source code copyright (c) 1991-2001, Aaron Giles */
|
|
/* See the Read Me file for licensing information. */
|
|
/* Contact email: mac@aarongiles.com */
|
|
/*********************************************************/
|
|
|
|
//=====================================================================================
|
|
// Generic includes for Macintosh headers
|
|
//=====================================================================================
|
|
|
|
#if THINK_C
|
|
#include "THINK.Header"
|
|
#include <stddef.h>
|
|
#elif applec
|
|
#pragma load ":Headers:MPW.Header"
|
|
#elif __MWERKS__
|
|
//#include "MW.Header"
|
|
#else
|
|
#include "JPEGView.h"
|
|
#endif
|
|
|
|
//=====================================================================================
|
|
// Includes specific to this module
|
|
//=====================================================================================
|
|
|
|
#include "SCRN.h"
|
|
|
|
//=====================================================================================
|
|
// SCRNPrivates: private data structure for SCRN images, maintained for each image.
|
|
//=====================================================================================
|
|
|
|
typedef struct SCRNPrivates SCRNPrivates, *SCRNPrivatesPtr, **SCRNPrivatesHandle;
|
|
|
|
struct SCRNPrivates
|
|
{
|
|
OSType id; // id flag to be sure that we got the right privates
|
|
Boolean oldFormat; // flag: true if this is an old-format image
|
|
};
|
|
|
|
//=====================================================================================
|
|
// Global variables local to this module
|
|
//=====================================================================================
|
|
|
|
static FSSpec gLastSpec;
|
|
|
|
//=====================================================================================
|
|
// Prototypes for functions local to this module
|
|
//=====================================================================================
|
|
|
|
static OSErr DecompressSCRNImage(uchar *dataStart, SCRNPrivatesHandle privates,
|
|
PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length);
|
|
static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow);
|
|
|
|
//=====================================================================================
|
|
// Boolean idSCRN(uchar *theData, long theSize)
|
|
//=====================================================================================
|
|
// Examines the given data and attempts to identify it as a SCRN image.
|
|
//=====================================================================================
|
|
|
|
extern Boolean idSCRN(uchar *theData, long theSize, short refNum, FSSpec *theSpec)
|
|
{
|
|
#if applec
|
|
#pragma unused(theData, theSize)
|
|
#endif
|
|
Boolean ok = false;
|
|
OSErr theErr;
|
|
long size;
|
|
|
|
gLastSpec.vRefNum = 0;
|
|
theErr = GetEOF(refNum, &size);
|
|
if (theErr == noErr && size == (512 / 8 * 342)) ok = true;
|
|
refNum = FSpOpenResFile(theSpec, fsRdPerm);
|
|
if (refNum != -1) {
|
|
Handle dummyHandle;
|
|
SetResLoad(false);
|
|
dummyHandle = GetResource(kPICTType, 0);
|
|
if (dummyHandle) ReleaseResource(dummyHandle);
|
|
SetResLoad(true);
|
|
CloseResFile(refNum);
|
|
if (dummyHandle) {
|
|
gLastSpec = *theSpec;
|
|
ok = true;
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr LoadSCRN(short theFile, ImageHandle theImage)
|
|
//=====================================================================================
|
|
// Loads the SCRN image into memory from disk.
|
|
//=====================================================================================
|
|
|
|
extern OSErr LoadSCRN(short theFile, ImageHandle theImage)
|
|
{
|
|
OSErr theErr = noErr;
|
|
|
|
KeepSpinning();
|
|
if (gLastSpec.vRefNum) {
|
|
theFile = FSpOpenResFile(&gLastSpec, fsRdPerm);
|
|
if (theFile != -1) {
|
|
(*theImage)->data = GetResource(kPICTType, 0);
|
|
if ((*theImage)->data) DetachResource((*theImage)->data);
|
|
CloseResFile(theFile);
|
|
if (!(*theImage)->data) gIntError = errNoLoadMemory, theErr = memFullErr;
|
|
} else gIntError = errCantReadFile, theErr = ResError();
|
|
} else theErr = DefaultLoad(theFile, theImage);
|
|
return theErr;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr OpenSCRN(ImageHandle theImage)
|
|
//=====================================================================================
|
|
// Initializes the image record for a SCRN image.
|
|
//=====================================================================================
|
|
|
|
extern OSErr OpenSCRN(ImageHandle theImage)
|
|
{
|
|
SCRNPrivatesHandle privates;
|
|
OSErr theErr = noErr;
|
|
|
|
if (!(privates = (SCRNPrivatesHandle)NewHandleClear(sizeof(SCRNPrivates))))
|
|
return memFullErr;
|
|
(*theImage)->privateData = (Handle)privates;
|
|
(*privates)->id = kSCRNType;
|
|
(*privates)->oldFormat = (gLastSpec.vRefNum == 0);
|
|
if ((*privates)->oldFormat) {
|
|
(*theImage)->grect.right = 512;
|
|
(*theImage)->grect.bottom = 342;
|
|
(*theImage)->depth = 1;
|
|
(*theImage)->qrect = (*theImage)->crect = (*theImage)->grect;
|
|
(*theImage)->compression = 0;
|
|
BlockMove(gString[strUncompressed], (*theImage)->compressionDesc, *gString[strUncompressed] + 1);
|
|
} else {
|
|
DisposeHandle((Handle)privates);
|
|
(*theImage)->privateData = nil;
|
|
theErr = OpenPICT(theImage);
|
|
}
|
|
return theErr;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr DrawSCRN(Handle theHandle, JVDrawParamsHandle theParams)
|
|
//=====================================================================================
|
|
// Draws a SCRN image into the specified GWorld, from the srcRect into the dstRect,
|
|
// clipping as dstRgn specifies.
|
|
//=====================================================================================
|
|
|
|
extern OSErr DrawSCRN(Handle theHandle, JVDrawParamsHandle theParams)
|
|
{
|
|
SCRNPrivatesHandle privates = (SCRNPrivatesHandle)(*theParams)->privateData;
|
|
NestedProgress theProgress = (*theParams)->progress;
|
|
char hState = HGetState(theHandle);
|
|
OSErr theErr = noErr;
|
|
GWorldPtr theGWorld;
|
|
uchar *dataStart;
|
|
|
|
if (!privates || (*privates)->id != kSCRNType || !(*privates)->oldFormat)
|
|
return DrawPICT(theHandle, theParams);
|
|
if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc,
|
|
codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon);
|
|
HLockHi(theHandle);
|
|
if (theErr == noErr) {
|
|
dataStart = (uchar *)StripAddress(*theHandle);
|
|
theGWorld = NewTempGWorld(512, 342, 1, nil);
|
|
if (theGWorld) {
|
|
theErr = DecompressSCRNImage(dataStart, privates, GetGWorldPixMap(theGWorld),
|
|
(ICMProgressProcRecordPtr)&theProgress, GetHandleSize(theHandle));
|
|
if ((*theParams)->progress.aborted) theErr = codecAbortErr;
|
|
DisposeGWorld(theGWorld);
|
|
} else gIntError = errNoDrawMemory, theErr = memFullErr;
|
|
}
|
|
HSetState(theHandle, hState);
|
|
if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc,
|
|
codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon);
|
|
return theErr;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr FixSCRN(ImageHandle theImage, Handle *finalData, Boolean palette)
|
|
//=====================================================================================
|
|
// Called to convert a JPEG image into a SCRN image; here we just convert it to a PICT
|
|
// and then save.
|
|
//=====================================================================================
|
|
|
|
extern OSErr FixSCRN(ImageHandle theImage, Handle *finalData, Boolean palette)
|
|
{
|
|
return FixPICT(theImage, finalData, palette);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr SaveSCRN(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview,
|
|
// Rect *theRect, Handle privates)
|
|
//=====================================================================================
|
|
// Called to save a SCRN image to disk.
|
|
//=====================================================================================
|
|
|
|
extern OSErr SaveSCRN(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview,
|
|
Rect *theRect, Handle thePrivates)
|
|
{
|
|
SCRNPrivatesHandle privates = (SCRNPrivatesHandle)thePrivates;
|
|
Handle resPict = theHandle;
|
|
short theFile;
|
|
OSErr theErr;
|
|
|
|
if (privates && (*privates)->id == kSCRNType && (*privates)->oldFormat)
|
|
return DefaultSave(theSpec, theHandle, thePreview, theRect, kSCRNType);
|
|
if (MakeMemAvailable(GetHandleSize(theHandle))) {
|
|
theErr = HandToHand(&resPict);
|
|
if (theErr == noErr) {
|
|
KeepSpinning();
|
|
FSpCreateResFile(theSpec, kCreator, kSCRNType, 0);
|
|
KeepSpinning();
|
|
theFile = FSpOpenResFile(theSpec, fsRdWrPerm);
|
|
if (theFile) {
|
|
SpinIndef();
|
|
AddResource(resPict, kPICTType, 0, gString[strJPEGViewPICT]);
|
|
if ((theErr = ResError()) == noErr) {
|
|
WriteResource(resPict);
|
|
KeepSpinning();
|
|
ReleaseResource(resPict);
|
|
CloseResFile(theFile);
|
|
return noErr;
|
|
} else gIntError = errCantWriteFile;
|
|
CloseResFile(theFile);
|
|
} else gIntError = errCantOpenFile, theErr = fnOpnErr;
|
|
FSpDelete(theSpec);
|
|
DisposeHandle(resPict);
|
|
} else gIntError = errNoSaveMemory, theErr = memFullErr;
|
|
} else gIntError = errNoSaveMemory, theErr = memFullErr;
|
|
KeepSpinning();
|
|
return theErr;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// OSErr DecompressSCRNImage(uchar *dataStart, SCRNPrivatesHandle privates,
|
|
// PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length)
|
|
//=====================================================================================
|
|
// Oversees the decompression of a SCRN image, handling banding, and calling the
|
|
// appropriate function to perform the actual decompression.
|
|
//=====================================================================================
|
|
|
|
static OSErr DecompressSCRNImage(uchar *dataStart, SCRNPrivatesHandle privates,
|
|
PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length)
|
|
{
|
|
#if applec
|
|
#pragma unused(privates)
|
|
#endif
|
|
uchar *ptr, *rowStart, *dst, *dataEnd = dataStart + length;
|
|
char pState = GetPixelsState(dstPixMap);
|
|
RgnHandle dstRgn = qd.thePort->visRgn;
|
|
ulong bandRow = 0, row, col;
|
|
char mmuMode = true32b;
|
|
OSErr theErr = noErr;
|
|
|
|
LockPixels(dstPixMap);
|
|
rowStart = (uchar *)GetPixBaseAddr(dstPixMap);
|
|
ptr = dataStart;
|
|
for (row = 0; row < 342; row++) {
|
|
if (ptr < dataStart || ptr > dataEnd) {
|
|
theErr = codecBadDataErr;
|
|
break;
|
|
}
|
|
SwapMMUMode(&mmuMode);
|
|
dst = rowStart;
|
|
for (col = 0; col < 64; col++) *dst++ = *ptr++;
|
|
SwapMMUMode(&mmuMode);
|
|
rowStart += ((*dstPixMap)->rowBytes & 0x3fff);
|
|
if (!(row & 63) && prog->progressProc)
|
|
theErr = (OSErr)CallICMProgressProc(prog->progressProc,
|
|
codecProgressUpdatePercent,
|
|
FixRatio(row, 342), prog->progressRefCon);
|
|
if (++bandRow == Height(&(*dstPixMap)->bounds)) {
|
|
CopyPixMapToDestination(dstPixMap, row - bandRow + 1);
|
|
bandRow = 0;
|
|
rowStart = (uchar *)GetPixBaseAddr(dstPixMap);
|
|
}
|
|
if (theErr != noErr) break;
|
|
}
|
|
if (theErr == noErr && bandRow) CopyPixMapToDestination(dstPixMap, row - bandRow);
|
|
SetPixelsState(dstPixMap, pState);
|
|
return theErr;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow)
|
|
//=====================================================================================
|
|
// Copies the band contained in srcPixMap to the destination, offset from the top by
|
|
// startRow.
|
|
//=====================================================================================
|
|
|
|
static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow)
|
|
{
|
|
Rect srcRect = (*srcPixMap)->bounds, dstRect = (*srcPixMap)->bounds;
|
|
PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort);
|
|
char srcState = HGetState((Handle)srcPixMap);
|
|
char dstState = HGetState((Handle)dstPixMap);
|
|
|
|
OffsetRect(&dstRect, 0, startRow);
|
|
HLock((Handle)srcPixMap);
|
|
HLock((Handle)dstPixMap);
|
|
CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &srcRect, &dstRect,
|
|
srcCopy + ditherCopy, qd.thePort->visRgn);
|
|
HSetState((Handle)dstPixMap, dstState);
|
|
HSetState((Handle)srcPixMap, srcState);
|
|
}
|