This is photoCD_Rdr.m in view mode; [Download] [Up]
/* * 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.