JPEGView/Source/C/SCRN.c
Aaron Giles 92bdb55672 JPEGView 3.3 for Macintosh
These are the sources for the final official release of JPEGView for the
Mac, back in 1994.
2015-02-05 00:18:10 -08:00

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);
}