roq.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. #import "roq.h"
  2. #import "codec.h"
  3. #ifdef __MACOS__
  4. blah
  5. #endif
  6. @implementation roq
  7. - init
  8. {
  9. cWindow = eWindow = sWindow = 0;
  10. image = 0;
  11. quietMode = NO;
  12. encoder = 0;
  13. previousSize = 0;
  14. lastFrame = NO;
  15. codes = malloc( 4*1024 );
  16. dataStuff=NO;
  17. return self;
  18. }
  19. - (void)dealloc
  20. {
  21. free( codes );
  22. if (image) [image dealloc];
  23. if (encoder) [encoder dealloc];
  24. return;
  25. }
  26. - encodeQuietly:(BOOL)which
  27. {
  28. quietMode = which;
  29. return self;
  30. }
  31. - (BOOL)isQuiet
  32. {
  33. return quietMode;
  34. }
  35. - (BOOL)isLastFrame
  36. {
  37. return lastFrame;
  38. }
  39. - (BOOL)scaleable
  40. {
  41. return [paramFileId isScaleable];
  42. }
  43. - (BOOL)paramNoAlpha
  44. {
  45. return [paramFileId noAlpha];
  46. }
  47. - (BOOL)makingVideo
  48. {
  49. return YES; //[paramFileId timecode];
  50. }
  51. - (BOOL)searchType
  52. {
  53. return [paramFileId searchType];
  54. }
  55. - (BOOL)hasSound
  56. {
  57. return [paramFileId hasSound];
  58. }
  59. - (int)previousFrameSize
  60. {
  61. return previousSize;
  62. }
  63. -(int)firstFrameSize
  64. {
  65. return [paramFileId firstFrameSize];
  66. }
  67. -(int)normalFrameSize
  68. {
  69. return [paramFileId normalFrameSize];
  70. }
  71. - (char *)currentFilename
  72. {
  73. return currentFile;
  74. }
  75. -encodeStream: (id)paramInputFile
  76. {
  77. int onFrame;
  78. char f0[MAXPATHLEN], f1[MAXPATHLEN], f2[MAXPATHLEN];
  79. int morestuff;
  80. onFrame = 1;
  81. encoder = [[codec alloc] init: self];
  82. numberOfFrames = [paramInputFile numberOfFrames];
  83. paramFileId = paramInputFile;
  84. if ([paramInputFile noAlpha]==YES) printf("encodeStream: eluding alpha\n");
  85. f0[0] = 0;
  86. strcpy( f1, [paramInputFile getNextImageFilename]);
  87. if (( [paramInputFile moreFrames] == YES )) strcpy( f2, [paramInputFile getNextImageFilename]);
  88. morestuff = numberOfFrames;
  89. while( morestuff ) {
  90. [self loadAndDisplayImage: f1];
  91. if (onFrame==1 && ([image hadAlpha]==NO || [paramInputFile noAlpha]==YES) && ![self makingVideo] && ![self scaleable]) {
  92. [encoder sparseEncode: self];
  93. // [self writeLossless];
  94. } else {
  95. if (!strcmp( f0, f1 ) && strcmp( f1, f2) ) {
  96. [self writeHangFrame];
  97. } else {
  98. [encoder sparseEncode: self];
  99. }
  100. }
  101. onFrame++;
  102. strcpy( f0, f1 );
  103. strcpy( f1, f2 );
  104. if ([paramInputFile moreFrames] == YES) strcpy( f2, [paramInputFile getNextImageFilename]);
  105. morestuff--;
  106. }
  107. if (numberOfFrames != 1) {
  108. if ([image hadAlpha] && [paramInputFile noAlpha]==NO) {
  109. lastFrame = YES;
  110. [encoder sparseEncode: self];
  111. } else {
  112. [self writeLossless];
  113. }
  114. }
  115. return self;
  116. }
  117. - write16Word:(word *)aWord to:(FILE *)stream
  118. {
  119. byte a, b;
  120. a = *aWord & 0xff;
  121. b = *aWord >> 8;
  122. fputc( a, stream );
  123. fputc( b, stream );
  124. return self;
  125. }
  126. - write32Word:( unsigned int *)aWord to:(FILE *)stream
  127. {
  128. byte a, b, c, d;
  129. a = *aWord & 0xff;
  130. b = (*aWord >> 8) & 0xff;
  131. c = (*aWord >> 16) & 0xff;
  132. d = (*aWord >> 24) & 0xff;
  133. fputc( a, stream );
  134. fputc( b, stream );
  135. fputc( c, stream );
  136. fputc( d, stream );
  137. return self;
  138. }
  139. -(int)sizeFile:(FILE *)ftosize;
  140. {
  141. long int fat, fend;
  142. fat = ftell(ftosize);
  143. fseek( ftosize, 0, SEEK_END );
  144. fend = ftell(ftosize);
  145. fseek( ftosize, fat, SEEK_SET);
  146. return (fend);
  147. }
  148. - convertPlanertoPacked
  149. {
  150. byte *iPlane[5], *newdata, *olddata;
  151. int x,y,index, sample, pixelsWide, pixelsHigh;
  152. TByteBitmapImageRep *newImage;
  153. pixelsWide = [image pixelsWide];
  154. pixelsHigh = [image pixelsHigh];
  155. printf("convertPlanertoPacked: converting\n");
  156. newImage = [[TByteBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
  157. pixelsWide: pixelsWide
  158. pixelsHigh: pixelsHigh
  159. bitsPerSample: 8
  160. samplesPerPixel: 4
  161. hasAlpha: YES
  162. isPlanar: NO
  163. colorSpaceName: NSCalibratedRGBColorSpace
  164. bytesPerRow: 0
  165. bitsPerPixel: 0];
  166. newdata = [newImage bitmapData];
  167. index = 0;
  168. if ([image isPlanar]) {
  169. [image getBitmapDataPlanes: iPlane];
  170. for(y=0;y<pixelsHigh;y++) {
  171. for(x=0;x<pixelsWide;x++) {
  172. newdata[index++] = iPlane[0][y*pixelsWide+x];
  173. newdata[index++] = iPlane[1][y*pixelsWide+x];
  174. newdata[index++] = iPlane[2][y*pixelsWide+x];
  175. if ([image hasAlpha]) {
  176. newdata[index++] = iPlane[3][y*pixelsWide+x];
  177. } else {
  178. newdata[index++] = 255;
  179. }
  180. }
  181. }
  182. } else {
  183. sample = 0;
  184. olddata = [image bitmapData];
  185. for(y=0;y<pixelsHigh;y++) {
  186. for(x=0;x<pixelsWide;x++) {
  187. newdata[index++] = olddata[sample++];
  188. newdata[index++] = olddata[sample++];
  189. newdata[index++] = olddata[sample++];
  190. if ([image hasAlpha]) {
  191. newdata[index++] = olddata[sample++];
  192. } else {
  193. newdata[index++] = 255;
  194. }
  195. }
  196. }
  197. }
  198. [image dealloc];
  199. image = newImage;
  200. return self;
  201. }
  202. - writeLossless
  203. {
  204. word direct;
  205. unsigned int j;
  206. char tempFile[MAXPATHLEN];
  207. FILE *ftemp;
  208. byte *buffer;
  209. int res, mess;
  210. [self convertPlanertoPacked];
  211. if (!dataStuff) {
  212. [self initRoQPatterns];
  213. dataStuff=YES;
  214. }
  215. direct = RoQ_QUAD_JPEG;
  216. [self write16Word: &direct to: RoQFile];
  217. sprintf(tempFile, "%s.jpg",[paramFileId roqTempFilename]);
  218. [image writeJFIF:tempFile quality: [paramFileId jpegQuality]];
  219. ftemp = fopen(tempFile, "rb");
  220. if (!ftemp) { fprintf(stderr, "Could not open temp file\n"); exit(1); }
  221. j = [self sizeFile: ftemp];
  222. printf("writeLossless: writing %d bytes to RoQ_QUAD_JPEG\n", j);
  223. [self write32Word: &j to: RoQFile];
  224. direct = 0; // flags
  225. [self write16Word: &direct to: RoQFile];
  226. buffer = malloc( 16384 );
  227. do {
  228. res = fread( buffer, 1, 16384, ftemp);
  229. mess = fwrite( buffer, 1, res, RoQFile );
  230. if (res != mess) { fprintf(stderr, "Could not write to output stream\n"); exit(1); }
  231. } while ( res == 16384 );
  232. free( buffer );
  233. fclose(ftemp);
  234. [encoder setPreviousImage: tempFile from: image parent: self];
  235. remove( tempFile );
  236. fflush( RoQFile );
  237. return self;
  238. }
  239. - initRoQFile:(const char *)RoQFilename
  240. {
  241. word i;
  242. static int finit = 0;
  243. if (!finit) {
  244. finit++;
  245. printf("initRoQFile: %s\n", RoQFilename);
  246. RoQFile = fopen( RoQFilename, "w" );
  247. // chmod(RoQFilename, S_IREAD|S_IWRITE|S_ISUID|S_ISGID|0070|0007 );
  248. if (!RoQFile) {
  249. fprintf(stderr,"Unable to open output file %s.\n", RoQFilename);
  250. exit(1);
  251. }
  252. i = RoQ_ID;
  253. [self write16Word: &i to: RoQFile];
  254. i = 0xffff;
  255. [self write16Word: &i to: RoQFile];
  256. [self write16Word: &i to: RoQFile];
  257. i = 24; // framerate
  258. [self write16Word: &i to: RoQFile];
  259. fflush( RoQFile );
  260. }
  261. strcpy( roqOutfile, RoQFilename );
  262. return self;
  263. }
  264. - initRoQPatterns
  265. {
  266. int j;
  267. word direct;
  268. direct = RoQ_QUAD_INFO;
  269. [self write16Word: &direct to: RoQFile];
  270. j = 8;
  271. [self write32Word: &j to: RoQFile];
  272. printf("initRoQPatterns: outputting %d bytes to RoQ_INFO\n", j);
  273. direct = [image hadAlpha];
  274. if ([self paramNoAlpha] == YES) direct = 0;
  275. [self write16Word: &direct to: RoQFile];
  276. direct = [image pixelsWide];
  277. [self write16Word: &direct to: RoQFile];
  278. direct = [image pixelsHigh];
  279. [self write16Word: &direct to: RoQFile];
  280. direct = 8;
  281. [self write16Word: &direct to: RoQFile];
  282. direct = 4;
  283. [self write16Word: &direct to: RoQFile];
  284. fflush( RoQFile );
  285. return self;
  286. }
  287. - closeRoQFile
  288. {
  289. fflush( RoQFile );
  290. printf("closeRoQFile: closing RoQ file\n");
  291. fclose( RoQFile );
  292. return self;
  293. }
  294. - writeHangFrame
  295. {
  296. int j;
  297. word direct;
  298. printf("*******************************************************************\n");
  299. direct = RoQ_QUAD_HANG;
  300. [self write16Word: &direct to: RoQFile];
  301. j = 0;
  302. [self write32Word: &j to: RoQFile];
  303. direct = 0;
  304. [self write16Word: &direct to: RoQFile];
  305. return self;
  306. }
  307. - writeCodeBookToStream: (byte *)codebook size: (int)csize flags: (word)cflags
  308. {
  309. int j;
  310. word direct;
  311. if (!csize) {
  312. printf("writeCodeBook: NO VQ DATA!!!!\n");
  313. return self;
  314. }
  315. direct = RoQ_QUAD_CODEBOOK;
  316. [self write16Word: &direct to: RoQFile];
  317. j = csize;
  318. [self write32Word: &j to: RoQFile];
  319. printf("writeCodeBook: outputting %d bytes to RoQ_QUAD_CODEBOOK\n", j);
  320. direct = cflags;
  321. [self write16Word: &direct to: RoQFile];
  322. fwrite( codebook, j, 1, RoQFile);
  323. fflush( RoQFile );
  324. return self;
  325. }
  326. - writeCodeBook: (byte *)codebook
  327. {
  328. memcpy( codes, codebook, 4096 );
  329. return self;
  330. }
  331. - writeFrame:(quadcel *)pquad
  332. {
  333. word action, direct;
  334. int onCCC, onAction, i, j, code;
  335. byte *cccList;
  336. BOOL *use2, *use4;
  337. int dx,dy,dxMean,dyMean,index2[256],index4[256], dimension;
  338. cccList = malloc( numQuadCels * 8); // maximum length
  339. use2 = malloc(256*sizeof(BOOL));
  340. use4 = malloc(256*sizeof(BOOL));
  341. for(i=0;i<256;i++) {
  342. use2[i] = NO;
  343. use4[i] = NO;
  344. }
  345. action = 0;
  346. j = onAction = 0;
  347. onCCC = 2; // onAction going to go at zero
  348. dxMean = [encoder motMeanX];
  349. dyMean = [encoder motMeanY];
  350. if ([image hadAlpha]) dimension = 10; else dimension = 6;
  351. for (i=0; i<numQuadCels; i++) {
  352. if ( pquad[i].size && pquad[i].size < 16 ) {
  353. switch( pquad[i].status ) {
  354. case SLD:
  355. use4[pquad[i].patten[0]] = YES;
  356. use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = YES;
  357. use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = YES;
  358. use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = YES;
  359. use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = YES;
  360. break;
  361. case PAT:
  362. use4[pquad[i].patten[0]] = YES;
  363. use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = YES;
  364. use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = YES;
  365. use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = YES;
  366. use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = YES;
  367. break;
  368. case CCC:
  369. use2[pquad[i].patten[1]] = YES;
  370. use2[pquad[i].patten[2]] = YES;
  371. use2[pquad[i].patten[3]] = YES;
  372. use2[pquad[i].patten[4]] = YES;
  373. }
  374. }
  375. }
  376. if (!dataStuff) {
  377. dataStuff=YES;
  378. [self initRoQPatterns];
  379. if ([image hadAlpha]) i = 3584; else i = 2560;
  380. [self writeCodeBookToStream: codes size: i flags: 0];
  381. for(i=0;i<256;i++) {
  382. index2[i] = i;
  383. index4[i] = i;
  384. }
  385. } else {
  386. j = 0;
  387. for(i=0;i<256;i++) {
  388. if (use2[i]) {
  389. index2[i] = j;
  390. for(dx=0;dx<dimension;dx++) cccList[j*dimension+dx] = codes[i*dimension+dx];
  391. j++;
  392. }
  393. }
  394. code = j*dimension;
  395. direct = j;
  396. printf("writeFrame: really used %d 2x2 cels\n", j);
  397. j = 0;
  398. for(i=0;i<256;i++) {
  399. if (use4[i]) {
  400. index4[i] = j;
  401. for(dx=0;dx<4;dx++) cccList[j*4+code+dx] = index2[codes[i*4+(dimension*256)+dx]];
  402. j++;
  403. }
  404. }
  405. code += j*4;
  406. direct = (direct<<8) + j;
  407. printf("writeFrame: really used %d 4x4 cels\n", j);
  408. if ([image hadAlpha]) i = 3584; else i = 2560;
  409. if ( code == i || j == 256) {
  410. [self writeCodeBookToStream: codes size: i flags: 0];
  411. } else {
  412. [self writeCodeBookToStream: cccList size: code flags: direct];
  413. }
  414. }
  415. action = 0;
  416. j = onAction = 0;
  417. for (i=0; i<numQuadCels; i++) {
  418. if ( pquad[i].size && pquad[i].size < 16 ) {
  419. code = -1;
  420. switch( pquad[i].status ) {
  421. case DEP:
  422. code = 3;
  423. break;
  424. case SLD:
  425. code = 2;
  426. cccList[onCCC++] = index4[pquad[i].patten[0]];
  427. break;
  428. case MOT:
  429. code = 0;
  430. break;
  431. case FCC:
  432. code = 1;
  433. dx = ((pquad[i].domain >> 8 )) - 128 - dxMean + 8;
  434. dy = ((pquad[i].domain & 0xff)) - 128 - dyMean + 8;
  435. if (dx>15 || dx<0 || dy>15 || dy<0 ) {
  436. printf("writeFrame: FCC error %d,%d mean %d,%d at %d,%d,%d rmse %f\n", dx,dy, dxMean, dyMean,pquad[i].xat,pquad[i].yat,pquad[i].size, pquad[i].snr[FCC] );
  437. exit(1);
  438. }
  439. cccList[onCCC++] = (dx<<4)+dy;
  440. break;
  441. case PAT:
  442. code = 2;
  443. cccList[onCCC++] = index4[pquad[i].patten[0]];
  444. break;
  445. case CCC:
  446. code = 3;
  447. cccList[onCCC++] = index2[pquad[i].patten[1]];
  448. cccList[onCCC++] = index2[pquad[i].patten[2]];
  449. cccList[onCCC++] = index2[pquad[i].patten[3]];
  450. cccList[onCCC++] = index2[pquad[i].patten[4]];
  451. break;
  452. case DEAD:
  453. fprintf(stderr,"dead cels in picture\n");
  454. break;
  455. }
  456. if (code == -1) {
  457. fprintf(stderr, "writeFrame: an error occurred writing the frame\n");
  458. exit(2);
  459. }
  460. action = (action<<2)|code;
  461. j++;
  462. if (j == 8) {
  463. j = 0;
  464. cccList[onAction+0] = (action & 0xff);
  465. cccList[onAction+1] = ((action >> 8) & 0xff);
  466. onAction = onCCC;
  467. onCCC += 2;
  468. }
  469. }
  470. }
  471. if (j) {
  472. action <<= ((8-j)*2);
  473. cccList[onAction+0] = (action & 0xff);
  474. cccList[onAction+1] = ((action >> 8) & 0xff);
  475. }
  476. direct = RoQ_QUAD_VQ;
  477. [self write16Word: &direct to: RoQFile];
  478. j = onCCC;
  479. [self write32Word: &j to: RoQFile];
  480. direct = dyMean;
  481. direct &= 0xff;
  482. direct += (dxMean<<8); // flags
  483. [self write16Word: &direct to: RoQFile];
  484. printf("writeFrame: outputting %d bytes to RoQ_QUAD_VQ\n", j);
  485. previousSize = j;
  486. fwrite( cccList, onCCC, 1, RoQFile );
  487. fflush( RoQFile );
  488. free( cccList );
  489. free( use2 );
  490. free( use4 );
  491. return self;
  492. }
  493. - writePuzzleFrame:(quadcel *)pquad
  494. {
  495. return self;
  496. }
  497. - (TByteBitmapImageRep *)scaleImage: (TByteBitmapImageRep *)toscale
  498. {
  499. int newx, newy,x,y,s,linesize;
  500. TByteBitmapImageRep *newImage;
  501. unsigned char *i0, *i1;
  502. int newv;
  503. newx = 288;
  504. if ([toscale pixelsHigh] == 160) {
  505. newy = 320;
  506. } else {
  507. newy = [toscale pixelsHigh];
  508. }
  509. newImage = [[TByteBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
  510. pixelsWide: newx
  511. pixelsHigh: newy
  512. bitsPerSample: 8
  513. samplesPerPixel: 4
  514. hasAlpha: YES
  515. isPlanar: NO
  516. colorSpaceName: NSCalibratedRGBColorSpace
  517. bytesPerRow: 0
  518. bitsPerPixel: 0];
  519. i0 = [toscale bitmapData];
  520. i1 = [newImage bitmapData];
  521. linesize = [toscale pixelsWide]*4;
  522. for(y=0; y<newy; y++) {
  523. for(x=0; x<320; x++) {
  524. if (x>=16 && x<304) {
  525. for(s=0;s<4;s++) {
  526. if ([toscale pixelsHigh] == 160) {
  527. newv = i0[(x*2+0)*4+(y>>1)*linesize+s];
  528. newv += i0[(x*2+1)*4+(y>>1)*linesize+s];
  529. newv += i0[(x*2+0)*4+((y>>1)+1)*linesize+s];
  530. newv += i0[(x*2+1)*4+((y>>1)+1)*linesize+s];
  531. newv = newv/4;
  532. } else {
  533. newv = i0[(x*2+0)*4+y*linesize+s];
  534. newv += i0[(x*2+1)*4+y*linesize+s];
  535. newv = newv/2;
  536. }
  537. i1[(x-16)*4+y*(288*4)+s] = newv;
  538. }
  539. }
  540. }
  541. }
  542. return (newImage);
  543. }
  544. //
  545. // load a frame, create a window (if neccesary) and display the frame
  546. //
  547. - loadAndDisplayImage: (const char *) filename
  548. {
  549. NSRect cRect;
  550. char *secondFilename,firstFilename[MAXPATHLEN+1];
  551. id image1;
  552. NSSize newSize;
  553. // unsigned char *imageData;
  554. // static BOOL cleared = NO;
  555. if (image) [image dealloc];
  556. printf("loadAndDisplayImage: %s\n", filename);
  557. strcpy( currentFile, filename );
  558. image = [TByteBitmapImageRep alloc];
  559. if (!(secondFilename= strchr(filename,'\n'))) { //one filename, no compositing
  560. [image initFromFile: filename ];
  561. }
  562. else {
  563. strncpy(firstFilename,filename,secondFilename-filename);
  564. firstFilename[secondFilename-filename]='\0';
  565. secondFilename++;//point past the \n
  566. image1 = [[TByteBitmapImageRep alloc] initFromFile:firstFilename];
  567. [image initFromFile: secondFilename ];//result will be in here
  568. //image is the composite of those two...
  569. [self composite:image1 to:image];
  570. }
  571. //
  572. // wolf stuff
  573. //
  574. newSize.width = 256;
  575. newSize.height = 256;
  576. [image setSize: newSize];
  577. if ([paramFileId output3DO] == YES) {
  578. image1 = [self scaleImage: image];
  579. [image dealloc];
  580. image = image1;
  581. }
  582. numQuadCels = (([image pixelsWide] & 0xfff0)*([image pixelsHigh] & 0xfff0))/(MINSIZE*MINSIZE);
  583. numQuadCels += numQuadCels/4 + numQuadCels/16;
  584. // if ([paramFileId deltaFrames] == YES && cleared == NO && [image isPlanar] == NO) {
  585. // cleared = YES;
  586. // imageData = [image data];
  587. // memset( imageData, 0, [image pixelsWide]*[image pixelsHigh]*[image samplesPerPixel]);
  588. // }
  589. if (!quietMode) printf("loadAndDisplayImage: %dx%d\n", [image pixelsWide], [image pixelsHigh]);
  590. if (!quietMode) {
  591. if (!cWindow) {
  592. cRect.origin.x = 8.0 * 48.0;
  593. cRect.origin.y = ([image pixelsHigh]+80);
  594. cRect.size.width = [image pixelsWide];
  595. cRect.size.height = [image pixelsHigh];
  596. cWindow = [[NSWindow alloc] initWithContentRect:cRect styleMask:NSTitledWindowMask
  597. backing:NSBackingStoreBuffered defer:NO];
  598. cRect.origin.x = cRect.origin.y = 0.0;
  599. // [[cWindow contentView] setClipping:NO];
  600. [cWindow setTitle: @"current frame"];
  601. [cWindow makeKeyAndOrderFront: [cWindow contentView]];
  602. [cWindow display];
  603. }
  604. cRect = [[cWindow contentView] bounds];
  605. [[cWindow contentView] lockFocus];
  606. [image drawInRect: cRect];
  607. [[cWindow contentView] unlockFocus];
  608. [cWindow flushWindow];
  609. if (!eWindow) {
  610. cRect.origin.x = 8.0 * 48.0 - ([image pixelsWide]>>1) - 4;
  611. cRect.origin.y = ([image pixelsHigh]+80);
  612. cRect.size.width = [image pixelsWide] >> 1;
  613. cRect.size.height = [image pixelsHigh] >> 1;
  614. eWindow = [[NSWindow alloc] initWithContentRect:cRect styleMask:NSTitledWindowMask
  615. backing:NSBackingStoreBuffered defer:NO];
  616. cRect.origin.x = cRect.origin.y = 0.0;
  617. // [[eWindow contentView] setClipping:NO];
  618. [eWindow setTitle: @"cel error"];
  619. [eWindow makeKeyAndOrderFront: [eWindow contentView]];
  620. [eWindow display];
  621. }
  622. if (!sWindow) {
  623. cRect.origin.x = 8.0 * 48.0 - ([image pixelsWide]>>1) - 4;
  624. cRect.origin.y = ([image pixelsHigh]+80) + (([image pixelsHigh]+48)>>1);
  625. cRect.size.width = [image pixelsWide] >> 1;
  626. cRect.size.height = [image pixelsHigh] >> 1;
  627. sWindow = [[NSWindow alloc] initWithContentRect: cRect styleMask:NSTitledWindowMask
  628. backing:NSBackingStoreBuffered defer:NO];
  629. cRect.origin.x = cRect.origin.y = 0.0;
  630. // [[eWindow contentView] setClipping:NO];
  631. [sWindow setTitle: @"quadtree map"];
  632. [sWindow makeKeyAndOrderFront: [sWindow contentView]];
  633. [sWindow display];
  634. }
  635. cRect = [[sWindow contentView] bounds];
  636. [[sWindow contentView] lockFocus];
  637. [image drawInRect: cRect];
  638. [[sWindow contentView] unlockFocus];
  639. [sWindow flushWindow];
  640. cRect = [[eWindow contentView] bounds];
  641. [[eWindow contentView] lockFocus];
  642. [image drawInRect: cRect];
  643. [[eWindow contentView] unlockFocus];
  644. [eWindow flushWindow];
  645. if (!errImage) {
  646. errImage = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
  647. pixelsWide: 1
  648. pixelsHigh: 1
  649. bitsPerSample: 8
  650. samplesPerPixel: 3
  651. hasAlpha: NO
  652. isPlanar: NO
  653. colorSpaceName: NSCalibratedRGBColorSpace
  654. bytesPerRow: 0
  655. bitsPerPixel: 0];
  656. }
  657. // NSPing();
  658. }
  659. return self;
  660. }
  661. - markQuadx: (int)xat quady: (int)yat quads: (int)size error: (float)cerror type: (int)choice
  662. {
  663. NSRect cRect;
  664. byte *err;
  665. static int ywasat = -1;
  666. if (!quietMode) {
  667. cRect.origin.x = (xat)>>1;
  668. cRect.origin.y = ([image pixelsHigh] - yat - size)>>1;
  669. cRect.size.width = cRect.size.height = (size)>>1;
  670. if (size < 1) {
  671. [[sWindow contentView] lockFocus];
  672. if (size == 8 && choice == 1) {
  673. PSsetgray(NSWhite);
  674. } else if (size == 8 && choice == 3) {
  675. PSsetgray(NSLightGray);
  676. } else if (size == 4) {
  677. PSsetgray(NSDarkGray);
  678. } else if (size == 2) {
  679. PSsetgray(NSBlack);
  680. }
  681. NSFrameRectWithWidth(cRect,0.0);
  682. [[sWindow contentView] unlockFocus];
  683. if (!(ywasat & 31)) {
  684. [sWindow flushWindow];
  685. }
  686. }
  687. err = [errImage bitmapData];
  688. err[0] = err[1] = err[2] = 0;
  689. if ( cerror > 31 ) cerror = 31;
  690. if (choice & 1) err[0] = (int)cerror*8;
  691. if (choice & 2) err[1] = (int)cerror*8;
  692. if (choice & 4) err[2] = (int)cerror*8;
  693. [[eWindow contentView] lockFocus];
  694. [errImage drawInRect: cRect];
  695. [[eWindow contentView] unlockFocus];
  696. if (!(ywasat & 31)) {
  697. [eWindow flushWindow];
  698. }
  699. ywasat++;
  700. }
  701. return self;
  702. }
  703. - (NSBitmapImageRep*)currentImage
  704. {
  705. return image;
  706. }
  707. - (id)errorWindow
  708. {
  709. return eWindow;
  710. }
  711. - (id)scaleWindow
  712. {
  713. return sWindow;
  714. }
  715. - (int)numberOfFrames {
  716. return numberOfFrames;
  717. }
  718. - composite:(NSBitmapImageRep *)source to: (NSBitmapImageRep *)destination
  719. {
  720. unsigned short value;
  721. int x,y,bpp,inc,pixelsWide,pixelsHigh,yoff,pixel;
  722. byte *iPlane[5], *dPlane[5];
  723. bpp = [source samplesPerPixel];
  724. pixelsWide = [source pixelsWide];
  725. pixelsHigh = [source pixelsHigh];
  726. if ([source isPlanar]) {
  727. [source getBitmapDataPlanes: iPlane];
  728. [destination getBitmapDataPlanes: dPlane];
  729. for(y=0;y<pixelsHigh;y++) {
  730. yoff = y*pixelsWide;
  731. for(x=0;x<pixelsWide;x++) {
  732. if ([destination hasAlpha]) {
  733. value = dPlane[3][yoff+x];
  734. } else {
  735. value = 255;
  736. }
  737. if (value == 0) {
  738. dPlane[0][yoff+x] = iPlane[0][yoff+x];
  739. dPlane[1][yoff+x] = iPlane[1][yoff+x];
  740. dPlane[2][yoff+x] = iPlane[2][yoff+x];
  741. dPlane[3][yoff+x] = iPlane[3][yoff+x];
  742. } else if (value != 255) {
  743. pixel = ((iPlane[0][yoff+x]*(255-value))/255) + ((dPlane[0][yoff+x]*value)/255);
  744. dPlane[0][yoff+x] = pixel;
  745. pixel = ((iPlane[1][yoff+x]*(255-value))/255) + ((dPlane[1][yoff+x]*value)/255);
  746. dPlane[1][yoff+x] = pixel;
  747. pixel = ((iPlane[2][yoff+x]*(255-value))/255) + ((dPlane[2][yoff+x]*value)/255);
  748. dPlane[2][yoff+x] = pixel;
  749. if ([destination hasAlpha]) {
  750. if (iPlane[3][yoff+x]>dPlane[3][yoff+x]) dPlane[3][yoff+x] = iPlane[3][yoff+x];
  751. }
  752. }
  753. }
  754. }
  755. } else {
  756. iPlane[0] = [source bitmapData];
  757. dPlane[0] = [destination bitmapData];
  758. for(y=0;y<pixelsHigh;y++) {
  759. yoff = y*pixelsWide*bpp;
  760. for(x=0;x<pixelsWide;x++) {
  761. inc = x*bpp;
  762. if ([destination hasAlpha]) {
  763. value = dPlane[0][yoff+inc+3];
  764. } else {
  765. value = 255;
  766. }
  767. if (value == 0) {
  768. dPlane[0][yoff+inc+0] = iPlane[0][yoff+inc+0];
  769. dPlane[0][yoff+inc+1] = iPlane[0][yoff+inc+1];
  770. dPlane[0][yoff+inc+2] = iPlane[0][yoff+inc+2];
  771. dPlane[0][yoff+inc+3] = iPlane[0][yoff+inc+3];
  772. } else if (value != 255) {
  773. pixel = ((iPlane[0][yoff+inc+0]*(255-value))/255) + ((dPlane[0][yoff+inc+0]*value)/255);
  774. dPlane[0][yoff+inc+0] = pixel;
  775. pixel = ((iPlane[0][yoff+inc+1]*(255-value))/255) + ((dPlane[0][yoff+inc+1]*value)/255);
  776. dPlane[0][yoff+inc+1] = pixel;
  777. pixel = ((iPlane[0][yoff+inc+2]*(255-value))/255) + ((dPlane[0][yoff+inc+2]*value)/255);
  778. dPlane[0][yoff+inc+2] = pixel;
  779. if ([destination hasAlpha]) {
  780. if (iPlane[0][yoff+inc+3]>dPlane[0][yoff+inc+3]) dPlane[0][yoff+inc+3] = iPlane[0][yoff+inc+3];
  781. }
  782. }
  783. }
  784. }
  785. }
  786. return self;
  787. }
  788. @end