home *** CD-ROM | disk | FTP | other *** search
- /*
- * This class contains everything we know about the format of information
- * on a Photo_CD. Note that this knowledge is not complete, it's just
- * as much as has been deciphered by the hpcdtoppm program written by
- * Hadmut Danisch (danisch@ira.uka.de). Some comments from that program:
-
- * hpcdtoppm (Hadmut's pcdtoppm) v0.3
- * Copyright (c) 1992 by Hadmut Danisch (danisch@ira.uka.de).
- * Permission to use and distribute this software and its
- * documentation for noncommercial use and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation. It is not allowed to sell this software in
- * any way. This software is not public domain.
-
- * Some of that program is reimplemented in this class, and the rest is
- * still (currently) off in some C source and header files.
- * These comments by:
- * Garance Alistair Drosehn; Jan 14th, 1993
- */
-
- #import "photoCD_Rdr.h"
-
- #import "pcd.h"
- #define PCD_READ_OK 0
- #define PCD_READ_ERROR 1
- #define PCD_READBUF { \
- if ( READBUF < 1 ) { \
- NXRunAlertPanel(0, \
- " Unexpected eof while reading", \
- 0, 0, 0); \
- } \
- }
- #define PCD_SEEK(x) { \
- if (fseek(fin,((x) * SECSIZE),0)) { \
- NXRunAlertPanel(0, \
- " Unexpected error from fseek to sector %d", \
- 0, 0, 0, (x)); \
- } \
- }
-
- extern void rotateBm( dim *w, dim *h, implane *r, implane *g, implane *b, enum TURNS t);
-
- @implementation photoCD_Rdr
-
- /* methods only called from within this class */
- - (NXBitmapImageRep *) _allocBitmap
- :(dim)width :(dim)height
- red:(uBYTE *)redPlane
- green:(uBYTE *)greenPlane
- blue:(uBYTE *)bluePlane
- {
- u_char *rgb[5];
- NXBitmapImageRep *bitmap;
-
- rgb[0] = redPlane;
- rgb[1] = greenPlane;
- rgb[2] = bluePlane;
- rgb[3] = NULL;
- rgb[4] = NULL;
-
- /* allocate the proper sized BitmapImage and use the planes
- allocated by that for our processing */
- bitmap = [[NXBitmapImageRep alloc] initDataPlanes:rgb
- pixelsWide:width
- pixelsHigh:height
- bitsPerSample:8
- samplesPerPixel:3
- hasAlpha:NO
- isPlanar:YES
- colorSpace:NX_RGBColorSpace
- bytesPerRow:0
- bitsPerPixel:0];
- if ( ! bitmap ) {
- NXRunAlertPanel(0,
- " Unable to allocate bitmap for a %d x %d image",
- 0, 0, 0, width, height);
- /* probably should so something less drastic here */
- exit(9);
- }
-
- return bitmap;
- }
-
-
- - (short)_getExpectedThumbnailCount
- {
- /* assume that the caller is reading an overview file */
- struct ph0 *d;
-
- PCD_SEEK(0);
- PCD_READBUF;
- d = (struct ph0 *) sbuffer;
- return d->num_thumbs;
- }
-
-
- - setDoSharp:(BOOL)wantsDoSharp
- {
- mainSetSharpit( wantsDoSharp );
- return self;
- }
-
-
- - setNextGammaCorrection:(BOOL)wantsNextCorr
- {
- if( wantsNextCorr) mainSetGammaCorr(C_NeXT);
- else mainSetGammaCorr(C_LINEAR);
- return self;
- }
-
-
- - (int)readOverviewFromFile:(char *)ovFil
- curImageCount:(int)initialImageCount
- ImageArray:(ovImageArray *)imageArrayPtr
- MaxEntries:(int)overviewReadMax /* note: settable */
- {
- dim w, h;
- implane Luma, Chroma1, Chroma2;
-
- NXBitmapImageRep *bm;
- int pictNumber, imageCount, expectedCount, readStatus;
- char statStr[45];
-
- fin=fopen(ovFil,"r");
- if ( !fin ) {
- NXRunAlertPanel(0,
- " Unable to open overview file %s",
- 0, 0, 0, ovFil);
- return -1;
- }
-
- /* free overview images from previous photo_cd (if any) */
- for( ; initialImageCount > 0; initialImageCount-- ) {
- bm = (*imageArrayPtr)[initialImageCount];
- if ( bm != nil ) {
- (*imageArrayPtr)[initialImageCount] = nil;
- [bm free];
- }
- }
- initialImageCount = imageCount = 0;
- bm = nil;
-
- expectedCount = [self _getExpectedThumbnailCount];
-
- [readStatusField setStringValue:"Processing thumbnails"];
- [readStatusPanel makeKeyAndOrderFront:self];
-
- w=BaseW/4;
- h=BaseH/4;
-
- pictNumber = 1;
- while ( (!feof(fin)) && (pictNumber <= overviewReadMax) ) {
-
- /* Display a status message for each image, and call
- * NXPing every 4 images to make sure the status messages
- * are seen by the user. Without the call to NXPing, the
- * messages are buffered up, and aren't displayed until
- * that buffer is full.
- */
- sprintf(statStr, "Reading Thumbnail # %d", pictNumber);
- [readStatusField setStringValue:statStr];
- if ( (pictNumber % 4) == 0 ) NXPing();
-
- /* allocate the buffers */
- planealloc(&Luma, w,h);
- planealloc(&Chroma1, w,h);
- planealloc(&Chroma2, w,h);
-
- PCD_SEEK(5 + SeBase16 * (pictNumber - 1));
- readStatus = readplain(w, h, &Luma, &Chroma1, &Chroma2, fin);
- if (readStatus != PCD_READ_OK) {
- if ( (readStatus == PCD_READ_ERROR)
- && ( imageCount == expectedCount) ) {
- /* not a problem, no error message to write */
- }
- else {
- /* more noticable error indication, as none of the
- * other errors should ever happen.
- */
- NXRunAlertPanel(0,
- " Unexpected error (%d) from readplain in"
- " readOverview processing for picture #%d"
- " in file %s",
- 0, 0, 0, readStatus, pictNumber, ovFil);
- }
- break;
- }
- interpolate(&Chroma1);
- interpolate(&Chroma2);
- colconvert(&w,&h,&Luma,&Chroma1,&Chroma2);
- /* at this point Luma is Red, Chroma1 is Green, Chroma2 is Blue */
-
- bm = [self _allocBitmap :w :h
- red:Luma.im green:Chroma1.im blue:Chroma2.im];
-
- imageCount = pictNumber;
- (*imageArrayPtr)[imageCount] = bm;
-
- pictNumber++; /* try for next picture */
- }
-
- fclose(fin);
- fin = 0x0;
-
- if ( imageCount != expectedCount ) {
- /* just a simple error message to console */
- printf("Read in %d overview pictures, but %d were expected in %s\n",
- imageCount, expectedCount, ovFil);
- }
-
- [readStatusPanel close];
- return imageCount;
- }
-
-
- - readBitmapFromFile:(char *)imFile atSize:(enum is_Tags)imageSize
- {
- dim w, h, rp_w, rp_h;
- int seekPos = -1, cd_offset = -1;
- implane Luma, Chroma1, Chroma2;
- NXBitmapImageRep *bm;
- int readStatus;
- enum TURNS turn=T_NONE;
-
- fin=fopen(imFile,"r");
- if ( !fin ) {
- NXRunAlertPanel(0, " Unable to open image file %s",
- 0, 0, 0, imFile);
- return nil;
- }
-
- switch ( imageSize ) {
- case is_Base16_TAG:
- w = rp_w = BaseW / 4;
- h = rp_h = BaseH / 4;
- seekPos = L_Head + 1;
- break;
- case is_Base4_TAG:
- w = rp_w = BaseW / 2;
- h = rp_h = BaseH / 2;
- seekPos = L_Head + L_Base16 + 1;
- break;
- case is_4Base_TAG:
- w = 2 * BaseW;
- rp_w = BaseW;
- h = 2 * BaseH;
- rp_h = BaseH;
- seekPos = L_Head + L_Base16 + L_Base4 + 1; // sic
- break;
- case is_16Base_TAG:
- // this option does seem to work, but it's currently
- // disabled in the preferences panel because it uses
- // *huge* amounts of VM...
- w = 4 * BaseW;
- rp_w = BaseW;
- h = 4 * BaseH;
- rp_h = BaseH;
- seekPos = L_Head + L_Base16 + L_Base4 + 1; // sic
- break;
- default:
- // the correct values for case is_Base_TAG.
- w = rp_w = BaseW;
- h = rp_h = BaseH;
- seekPos = L_Head + L_Base16 + L_Base4 + 1;
- break;
- }
-
- /* allocate the buffers */
- planealloc(&Luma, w,h);
- planealloc(&Chroma1, w,h);
- planealloc(&Chroma2, w,h);
-
- PCD_SEEK(1); PCD_READBUF;
- switch(sbuffer[0xe02 & 0x7ff]&0x03) {
- case 0x00: turn=T_NONE; break;
- case 0x01: turn=T_LEFT; break;
- case 0x03: turn=T_RIGHT; break;
- default:
- NXRunAlertPanel(0,
- " Unexpected “turn” in pickImage processing",
- 0, 0, 0);
- fclose(fin); // perform some clean-up
- fin = 0x0;
- return nil; // can't process the picture
- }
-
- PCD_SEEK( seekPos );
- readStatus = readplain(rp_w, rp_h, &Luma, &Chroma1, &Chroma2, fin);
- if ( readStatus != PCD_READ_OK ) {
- NXRunAlertPanel(0,
- " Unexpected error (%d) from readplain in pickImage"
- " processing for image at w=%d, h=%d",
- 0, 0, 0, readStatus, rp_w, rp_h);
- fclose(fin); // perform some clean-up
- fin = 0x0;
- return nil; // can't process the picture
- }
- interpolate(&Chroma1);
- interpolate(&Chroma2);
- if ( w != rp_w ) { // ie, is_4Base_TAG or is_16Base_TAG
- // these image sizes need more interpolate-tion calls
- interpolate(&Luma);
- interpolate(&Chroma1);
- interpolate(&Chroma2);
-
- // They also need this readhqt/decode processing.
- #define nullplane ((implane *) 0)
- switch ( imageSize ) {
- case is_4Base_TAG:
- cd_offset = L_Head + L_Base16 + L_Base4 + L_Base;
- PCD_SEEK(cd_offset + 4);
- readhqt(w, h, 1, fin);
- PCD_SEEK(cd_offset + 5);
- decode(w, h, &Luma, nullplane, nullplane, 0, fin);
- break;
- case is_16Base_TAG:
- cd_offset = L_Head + L_Base16 + L_Base4 + L_Base;
- PCD_SEEK(cd_offset + 4);
- readhqt(w / 2, h / 2, 1, fin);
- PCD_SEEK(cd_offset + 5);
- decode(w / 2, h / 2, &Luma, nullplane, nullplane, 0, fin);
- interpolate(&Luma);
-
- cd_offset = ftell(fin);
- if (cd_offset % SECSIZE) {
- NXRunAlertPanel(0,
- " Base16 Position error in pickImage",
- 0, 0, 0);
- fclose(fin); // perform some clean-up
- fin = 0x0;
- return nil; // can't process the picture
- }
- cd_offset /= SECSIZE;
-
- PCD_SEEK(cd_offset + 12);
- readhqt(w, h, 3, fin);
- PCD_SEEK(cd_offset + 14);
- decode(w, h, &Luma, &Chroma1, &Chroma2, 0, fin);
-
- interpolate(&Chroma1);
- interpolate(&Chroma2);
- break;
- default:
- NXRunAlertPanel(0, " Internal error in pickImage",
- 0, 0, 0);
- fclose(fin); // perform some clean-up
- fin = 0x0;
- return nil; // can't process the picture
- }
- #undef nullplane
-
- }
-
- colconvert(&w,&h,&Luma,&Chroma1,&Chroma2);
- /* at this point Luma is Red, Chroma1 is Green, Chroma2 is Blue */
-
- if( turn != T_NONE ) {
- rotateBm(&w, &h, &Luma, &Chroma1, &Chroma2, turn);
- }
-
- bm = [self _allocBitmap :w :h
- red:Luma.im green:Chroma1.im blue:Chroma2.im];
-
- fclose(fin);
- fin = 0x0;
-
- /* note that anyone freeing this bitmap will also have to know
- to free the RGB buffers that it's using */
- return bm;
- }
-
-
- /* note that nobody calls this yet, instead there's code that's
- mighty similar to this over in PhotoWinProcs. Oops.
- */
- - freeDataPlanes:(NXBitmapImageRep *)imgBitmap
- {
- u_char *rgb[5];
-
- if ( [imgBitmap isPlanar] ) {
- /* a rather sleezy way to distinguish between images that
- were read in and images which were cut/pasted in... */
- [imgBitmap getDataPlanes:rgb];
- if ( rgb[0] ) free( rgb[0] );
- if ( rgb[1] ) free( rgb[1] );
- if ( rgb[2] ) free( rgb[2] );
- }
-
- return self;
- }
-
-
- @end
-