Ramflxp.cpp 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. //
  20. // FLXP.CPP
  21. //
  22. // 11/15/95 JMI Fixed AllocBuf and FreeBuf to leave more of the dynamic
  23. // allocation up to CImage/CPal.
  24. //
  25. // 03/06/96 JMI Added use of new FLX8_888/PFLX CImage/CPal format and
  26. // conversions. Made the default CImage/CPal type FLX8_888/PFLX
  27. //
  28. ///////////////////////////////////////////////////////////////////////////////
  29. //
  30. // THIS FILE CONTAINS ONLY THE PRIVATE FUNCTIONS.
  31. // THE PUBLIC FUNCTIONS ARE IN FLX.CPP
  32. // ALL MAJOR COMMENT BLOCKS ARE IN FLX.CPP AS WELL.
  33. //
  34. ///////////////////////////////////////////////////////////////////////////////
  35. #include <string.h>
  36. #include <malloc.h>
  37. #include <SMRTHEAP.HPP>
  38. #include "common/SYSTEM.H"
  39. #include "image/IMAGE.H"
  40. #include "ramflx/RAMFLX.H"
  41. #ifdef WIN32
  42. //////////////////////////////////////////////////////////////////////////////////
  43. // Assembly macros for i386.
  44. //////////////////////////////////////////////////////////////////////////////////
  45. // C Declarator for a memfile pointer.
  46. #define MEM UCHAR*
  47. // Call this first with a pointer to the start of the memory area.
  48. // pFile == ptr or reg
  49. // pMem == ptr or reg
  50. #define AMEM_OPEN(pFile, pMem) mov pFile, pMem
  51. //
  52. // Call this to reposition the pointer
  53. // pFile == ptr or reg
  54. // offset == reg or immediate
  55. #define AMEM_SEEK(pFile, offset) add pFile, offset
  56. //
  57. // Call this to Save an offset
  58. // pTell == ptr or reg to get data.
  59. // pFile == ptr or reg
  60. // pMem == ptr or reg used to open mem file
  61. #define AMEM_TELL(pTell, pFile, pMem) __asm mov pTell, pMem\
  62. __asm sub pTell, pFile
  63. //
  64. // Call any of these to get a UCHAR, USHORT, or ULONG from the memory area. The
  65. // pointer is automatically updated to follow the data that was just read.
  66. // These macros also hide the byte-ordering on the Mac vs the PC.
  67. // pDst == [ptr] or reg to get data
  68. // pFile == ptr or reg
  69. #define AMEM_BYTE(pDst, pFile) __asm mov pDst, byte ptr [pFile] \
  70. __asm add pFile, 1
  71. #define AMEM_WORD(pDst, pFile) __asm mov pDst, word ptr [pFile] \
  72. __asm add pFile, 2
  73. #define AMEM_DWORD(pDst, pFile) __asm mov pDst, dword ptr [pFile]\
  74. __asm add pFile, 4
  75. #endif // WIN32
  76. //////////////////////////////////////////////////////////////////////////////////
  77. // Module macros.
  78. //////////////////////////////////////////////////////////////////////////////////
  79. #define DWORDALIGN(i) ((i+3) & ~3)
  80. //////////////////////////////////////////////////////////////////////////////////
  81. // Module specific prototypes.
  82. //////////////////////////////////////////////////////////////////////////////////
  83. static short ConvToFlx8_888(CImage* pImage);
  84. static short ConvFromFlx8_888(CImage* pImage);
  85. //////////////////////////////////////////////////////////////////////////////////
  86. // Link conversion functions into CImage.
  87. IMAGELINKLATE(FLX8_888,
  88. ConvToFlx8_888, ConvFromFlx8_888, // Conversions To and From.
  89. /*pLoad*/NULL, /*pSave*/NULL, // Load and Save.
  90. /*pAlloc*/NULL, /*pDel*/NULL); // Alloc and Delete.
  91. //////////////////////////////////////////////////////////////////////////////////
  92. ///////////////////////////////////////////////////////////////////////////////
  93. //
  94. // Helper function that restarts at beginning of the flic.
  95. //
  96. ///////////////////////////////////////////////////////////////////////////////
  97. void CRamFlx::Restart(void)
  98. {
  99. // Seek to memory file position of frame 1
  100. m_file.Seek(m_filehdr.lOffsetFrame1, SEEK_SET);
  101. // Set frame number to 0 to indicate that nothing's been read yet.
  102. m_sFrameNum = 0;
  103. }
  104. ///////////////////////////////////////////////////////////////////////////////
  105. //
  106. // Instantiable shell function for workhorse DoReadFrame static.
  107. // Returns 0 if successfull, non-zero otherwise.
  108. //
  109. ///////////////////////////////////////////////////////////////////////////////
  110. short CRamFlx::DoReadFrame(CImage* pimageRead)
  111. {
  112. short sError = DoReadFrame(pimageRead, &m_file,
  113. &m_sPixelsModified, &m_sColorsModified);
  114. // If everything went fine, update the frame number.
  115. if (sError == 0)
  116. {
  117. if (m_sNoDelta == TRUE)
  118. {
  119. if (++m_sFrameNum == m_filehdr.sNumFrames)
  120. {
  121. // Seek to file position of frame 1 (the next one we'll do)
  122. m_file.Seek(m_plFrames[1], SEEK_SET);
  123. }
  124. else
  125. {
  126. // Reset frame number
  127. if (m_sFrameNum == (m_filehdr.sNumFrames + 1))
  128. m_sFrameNum = 1;
  129. }
  130. }
  131. else
  132. {
  133. // If frame number reaches NumFrames+1, then we just did the "ring"
  134. // frame, which is the delta between the flic's last and first frames.
  135. if (++m_sFrameNum == (m_filehdr.sNumFrames + 1))
  136. {
  137. // Reset frame number
  138. m_sFrameNum = 1;
  139. // Seek to file position of frame 2 (the next one we'll do)
  140. m_file.Seek(m_filehdr.lOffsetFrame2, SEEK_SET);
  141. }
  142. }
  143. }
  144. return sError;
  145. }
  146. ///////////////////////////////////////////////////////////////////////////////
  147. //
  148. // Read the next flic frame (if flic was just opened, this will read frame 1).
  149. // The "modified" flags are updated in the specified CImage.
  150. // Returns 0 if successfull, non-zero otherwise.
  151. // (static)
  152. //
  153. ///////////////////////////////////////////////////////////////////////////////
  154. short CRamFlx::DoReadFrame(CImage* pimageRead, CNFile* pfile,
  155. short* psPixelsModified, short* psColorsModified)
  156. {
  157. short sError = 0;
  158. // Always clear modified flags to FALSE. The lower-level functions will
  159. // set the appropriate flag to TRUE as necessary.
  160. *psPixelsModified = FALSE;
  161. *psColorsModified = FALSE;
  162. // Get current file position. After each chunk, we add the chunk size
  163. // to this position to get to the next chunk. We must do that seek
  164. // instead of relying on the amount of data that was read from the
  165. // chunk because that amount may be less than the indicated chunk size!
  166. // (This is not clearly documented, but was discovered the hard way!)
  167. long lFramePos = pfile->Tell();
  168. // Read frame chunk header
  169. FLX_FRAME_HDR framehdr;
  170. pfile->Read(&framehdr.lChunkSize);
  171. pfile->Read(&framehdr.wType);
  172. pfile->Read(&framehdr.sNumSubChunks);
  173. pfile->Read(framehdr.bReserved,8);
  174. // Verify that it worked and it's the type we're expecting
  175. if (framehdr.wType == 0xF1FA)
  176. {
  177. //cout << "Frame #" << m_sFrameNum << " has " << framehdr.sNumSubChunks << " data chunks" << endl;
  178. // Go through each of the sub-chunks. If there are no sub-chunks, then
  179. // frame is identical to the previous frame and there's nothing to do.
  180. FLX_DATA_HDR datahdr;
  181. for (short sSub = 0; sSub < framehdr.sNumSubChunks && sError == 0; sSub++)
  182. {
  183. // Get current file position. After each chunk, we add the chunk size
  184. // to this position to get to the next chunk. We must do that seek
  185. // instead of relying on the amount of data that was read from the
  186. // chunk because that amount may be less than the indicated chunk size!
  187. // (This is not clearly documented, but was discovered the hard way!)
  188. long lDataPos = pfile->Tell();
  189. // Read data chunk header
  190. pfile->Read(&datahdr.lChunkSize);
  191. pfile->Read(&datahdr.wType);
  192. // Size of actual data is chunk size minus header size (6)
  193. long lDataSize = datahdr.lChunkSize - 6;
  194. // Call the appropriate function based on data type
  195. switch(datahdr.wType)
  196. {
  197. case FLX_DATA_COLOR256:
  198. //cout << " DATA_COLOR256 of size " << lDataSize << endl;
  199. if (pimageRead->pPalette->pData != NULL)
  200. sError = ReadDataColor( pimageRead, FLX_DATA_COLOR256, pfile,
  201. psColorsModified);
  202. break;
  203. case FLX_DATA_SS2:
  204. //cout << " DATA_SS2 of size " << lDataSize << endl;
  205. if (pimageRead->pData != NULL)
  206. sError = ReadDataSS2(pimageRead, pfile, psPixelsModified);
  207. break;
  208. case FLX_DATA_COLOR:
  209. //cout << " DATA_COLOR of size " << lDataSize << endl;
  210. if (pimageRead->pPalette->pData != NULL)
  211. sError = ReadDataColor( pimageRead, FLX_DATA_COLOR, pfile,
  212. psColorsModified);
  213. break;
  214. case FLX_DATA_LC:
  215. //cout << " DATA_LC of size " << lDataSize << endl;
  216. if (pimageRead->pData != NULL)
  217. sError = ReadDataLC(pimageRead, pfile, psPixelsModified);
  218. break;
  219. case FLX_DATA_BLACK:
  220. //cout << " DATA_BLACK of size " << lDataSize << endl;
  221. if (pimageRead->pData != NULL)
  222. sError = ReadDataBlack(pimageRead, psPixelsModified);
  223. break;
  224. case FLX_DATA_BRUN:
  225. //cout << " DATA_BRUN of size " << lDataSize << endl;
  226. if (pimageRead->pData != NULL)
  227. sError = ReadDataBRun(pimageRead, pfile, psPixelsModified);
  228. break;
  229. case FLX_DATA_COPY:
  230. //cout << " DATA_COPY of size " << lDataSize << endl;
  231. if (pimageRead->pData != NULL)
  232. sError = ReadDataCopy(pimageRead, pfile, psPixelsModified);
  233. break;
  234. case FLX_DATA_PSTAMP:
  235. //cout << " DATA_PSTAMP of size " << lDataSize << endl;
  236. // We always ignore postage stamp data for now.
  237. break;
  238. default:
  239. //cout << " DATA UNKNOWN!!!! of size " << lDataSize << endl;
  240. //comment out the assert 10/20/94 to prevent crash
  241. //assert(0); // Should never get here!
  242. sError = 1;
  243. break;
  244. }
  245. // Adjust file position based on specified chunk size.
  246. pfile->Seek(lDataPos + datahdr.lChunkSize, SEEK_SET);
  247. }
  248. // Adjust file position based on specified chunk size.
  249. pfile->Seek(lFramePos + framehdr.lChunkSize, SEEK_SET);
  250. }
  251. else
  252. sError = 1;
  253. return sError;
  254. }
  255. ///////////////////////////////////////////////////////////////////////////////
  256. //
  257. // Handler for data chunks containing color information (FLX_DATA_COLOR256 and
  258. // FLX_DATA_COLOR.)
  259. //
  260. // The first word of data specifies the number of "packets" that follow.
  261. // Each packet consists of a byte that specifies the number of colors to
  262. // skip, a byte that specifies the number of colors to do, and three bytes
  263. // of RGB data for each of the colors to do.
  264. //
  265. // The idea is that the color palette index starts out at 0. For each
  266. // packet, we add the number of colors to skip to the color palette index.
  267. // We then get the number of colors to do and, for each one, we read the
  268. // 3 byte RGB data and copy it to the next color in the palette. This is
  269. // repeated for each packet.
  270. //
  271. // NOTE: The Autodesk doc's don't mention this, but if the number of colors
  272. // to do is 0, it really means 256! This was discovered the hard way.
  273. //
  274. // As an example, to change palette colors 2, 7, 8 and 9, the following data
  275. // would be used:
  276. //
  277. // 2 ; word specifies 2 packets
  278. // 2, 1, r,g,b ; skip 2, do 1
  279. // 4, 3, r,g,b, r,g,b, r,g,b ; skip 4, do 3
  280. //
  281. // The only difference between the two color-oriented data types are that
  282. // for FLX_DATA_COLOR256, the RGB values range from 0 to 255, while for
  283. // FLX_DATA_COLOR, they range from 0 to 63. This is an older format, so
  284. // we convert them to the newer format by shifting them left 2 bits.
  285. // (static)
  286. //
  287. ///////////////////////////////////////////////////////////////////////////////
  288. short CRamFlx::ReadDataColor( CImage* pimageRead, short sDataType,
  289. CNFile* pfile, short* psColorsModified)
  290. {
  291. //assert(pimageRead->prgbColors != NULL);
  292. // instead of assert, just return error
  293. if (pimageRead->pPalette->pData == NULL)
  294. return 1;
  295. short sError = 0;
  296. // Read number of packets
  297. short sNumPackets;
  298. pfile->Read(&sNumPackets);
  299. // Start the color index at 0 and then process each of the packets
  300. short sColorIndex = 0;
  301. short sCnt;
  302. short sColorDo;
  303. UCHAR bColorSkip;
  304. UCHAR bVal;
  305. // Pointer for more easily dealing with the palette in RGB888 format.
  306. PRGBT8 prgbt;
  307. for (short sPack = 0; (sPack < sNumPackets) && (sError == 0); sPack++)
  308. {
  309. // Read number of colors to skip and add to color index
  310. pfile->Read(&bColorSkip);
  311. sColorIndex = sColorIndex + (short)bColorSkip;
  312. // Read number of colors to do. This determines how many sets
  313. // of r,g,b data (3 bytes) will follow. If this count is 0, it
  314. // must be interpreted as a count of 256!
  315. pfile->Read(&bVal);
  316. if (bVal != 0)
  317. sColorDo = (short)bVal;
  318. else
  319. sColorDo = (short)256;
  320. // Make sure we won't index past end of palette! This would only
  321. // happen if we were getting bogus data from the file.
  322. if ((sColorIndex + sColorDo) <= 256)
  323. {
  324. // We need to create a temporary palette in FLX8_888:PFLX and then
  325. // convert it to the user's type. To do this we actually must create
  326. // an image as well since the conversion functions work on image's
  327. // more than just palettes.
  328. CPal palTemp;
  329. CImage imageTemp;
  330. // Point image's palette ptr to the palette.
  331. imageTemp.pPalette = &palTemp;
  332. imageTemp.ulType = FLX8_888;
  333. imageTemp.ulSize = 0L;
  334. // Create some palette data for RGBQUADs.
  335. palTemp.sStartIndex = 0;
  336. palTemp.sNumEntries = sColorDo;
  337. palTemp.ulType = PFLX;
  338. palTemp.sPalEntrySize = CPal::GetPalEntrySize(palTemp.ulType);
  339. if (palTemp.CreateData(palTemp.sNumEntries * palTemp.sPalEntrySize) == 0)
  340. {
  341. prgbt = (PRGBT8)palTemp.pData;
  342. pfile->Read(prgbt, sColorDo * palTemp.sPalEntrySize);
  343. if (sDataType == FLX_DATA_COLOR256)
  344. {
  345. // Done.
  346. }
  347. else
  348. {
  349. // Intensify these values in place.
  350. for (sCnt = 0; sCnt < sColorDo; sCnt++, prgbt++)
  351. {
  352. prgbt->ucRed = prgbt->ucRed << 2;
  353. prgbt->ucGreen = prgbt->ucGreen << 2;
  354. prgbt->ucBlue = prgbt->ucBlue << 2;
  355. }
  356. }
  357. // If types are different . . .
  358. if (imageTemp.ulType != pimageRead->ulType)
  359. {
  360. // Convert to user buffer type.
  361. if (imageTemp.Convert(pimageRead->ulType) != NOT_SUPPORTED)
  362. {
  363. // Converted successfully.
  364. }
  365. else
  366. {
  367. TRACE("ReadDataColor(): No conversion to palette type.\n");
  368. sError = 2;
  369. }
  370. }
  371. if (sError == 0)
  372. {
  373. ASSERT(sColorIndex * pimageRead->pPalette->sPalEntrySize + palTemp.ulSize <= pimageRead->pPalette->ulSize);
  374. // Copy data.
  375. memcpy( (UCHAR*)pimageRead->pPalette->pData + sColorIndex * pimageRead->pPalette->sPalEntrySize,
  376. palTemp.pData,
  377. palTemp.ulSize);
  378. }
  379. // Advance counter.
  380. sColorIndex += sColorDo;
  381. // Destroy temp palette.
  382. palTemp.DestroyData();
  383. }
  384. else
  385. {
  386. sError = 1;
  387. }
  388. }
  389. else
  390. sError = 1;
  391. }
  392. // Set modified flag
  393. *psColorsModified = TRUE;
  394. return sError;
  395. }
  396. ///////////////////////////////////////////////////////////////////////////////
  397. //
  398. // Handler for data chunks of type FLX_DATA_BLACK.
  399. //
  400. // These chunks contain no data. They are essentially a command that tells
  401. // us to clear all the pixels to color index 0.
  402. // (static)
  403. //
  404. ///////////////////////////////////////////////////////////////////////////////
  405. short CRamFlx::ReadDataBlack(CImage* pimageRead, short* psPixelsModified)
  406. {
  407. //assert(pimageRead->pbPixels != NULL);
  408. //assert(pimageRead->sPitch > 0);
  409. // let's just return with error instead of asserting and crashing
  410. if ((pimageRead->pData == NULL) || (pimageRead->lPitch <= 0))
  411. return 1;
  412. // Clear the image to 0 one row at a time. Note that we use the pitch
  413. // to move from the start of one row to the start of the next row.
  414. UCHAR* pbMem = (UCHAR*)pimageRead->pData;
  415. for (short y = 0; y < pimageRead->lHeight; y++)
  416. {
  417. memset(pbMem, 0, pimageRead->lWidth);
  418. pbMem += (ULONG)pimageRead->lPitch;
  419. }
  420. // Set modified flag
  421. *psPixelsModified = TRUE;
  422. // There can be no error!
  423. return 0;
  424. }
  425. ///////////////////////////////////////////////////////////////////////////////
  426. //
  427. // Handler for data chunks of type FLX_DATA_COPY.
  428. //
  429. // These chunks contain an uncompressed image of the frame. The number of
  430. // bytes following the chunk is the animation's width times its height.
  431. // The data goes from left to right and then top to bottom.
  432. //
  433. // These chunks occur rarely, being used only if the compressed frame would
  434. // take up more room than the uncompressed frame!
  435. // (static)
  436. //
  437. ///////////////////////////////////////////////////////////////////////////////
  438. short CRamFlx::ReadDataCopy( CImage* pimageRead, CNFile* pfile,
  439. short* psPixelsModified)
  440. {
  441. //assert(pimageRead->pbPixels != NULL);
  442. //assert(pimageRead->sPitch > 0);
  443. // let's just return with error instead of asserting
  444. if ((pimageRead->pData == NULL) || (pimageRead->lPitch <= 0))
  445. return 1;
  446. short sError = 0;
  447. // Read in the image one row at a time. Note that we use the pitch
  448. // to move from the start of on row to the start of the next row.
  449. UCHAR* pbMem = (UCHAR*)pimageRead->pData;
  450. for (short y = 0; y < pimageRead->lHeight; y++)
  451. {
  452. // Copy pixels
  453. // memcpy(pbMem,m_pCurFlxBuf,m_filehdr.sWidth);
  454. // Increment buffer pointers
  455. // m_pCurFlxBuf = MEM_SEEK(m_pCurFlxBuf,m_filehdr.sWidth);
  456. pfile->Read(pbMem, pimageRead->lWidth);
  457. pbMem += (ULONG)pimageRead->lPitch;
  458. }
  459. // Set modified flag
  460. *psPixelsModified = TRUE;
  461. return sError;
  462. }
  463. ///////////////////////////////////////////////////////////////////////////////
  464. //
  465. // Handler for data chunks of type FLX_DATA_BRUN.
  466. //
  467. // These chunks contain the entire image in compressed form. This is usually
  468. // used for the first frame or within a postage stamp image chunk.
  469. //
  470. // The data is organized into lines, starting at the top of the image and
  471. // moving down. The number of lines is based on the height in the flic header.
  472. //
  473. // The data for each line starts with a byte that contains the number of
  474. // packets for that line. This is a holdover from the original Autodesk
  475. // Animator which only supported a width of 320, so it didn't need more than
  476. // 255 packets. Animator Pro, which supports much larger widths, may need
  477. // more than 255 packets, so it can't use a byte. The officially sanctioned
  478. // way to deal with this byte is to ignore it, and to instead use the width
  479. // (from the flic header) to determine when each line is done (simply keep
  480. // count of the number of pixels that have been decompressed for that line,
  481. // and when it reaches the width, the line is done).
  482. //
  483. // Each packet contains a count byte followed by one or more pixels. If the
  484. // count is negative (bit 7 = 1) then its absolute value is the number of pixels
  485. // that follow it. If the count is positive (bit 7 = 0) then a single pixel
  486. // follows it and that pixel is to be replicated that number of times.
  487. // (static)
  488. //
  489. ///////////////////////////////////////////////////////////////////////////////
  490. short CRamFlx::ReadDataBRun( CImage* pimageRead, CNFile* pfile,
  491. short* psPixelsModified)
  492. {
  493. //assert(pimageRead->pbPixels != NULL);
  494. //assert(pimageRead->sPitch > 0);
  495. // let's just return with error instead of asserting
  496. if ((pimageRead->pData == NULL) || (pimageRead->lPitch <= 0))
  497. return 1;
  498. // added 10/20/94 to trap errors and exit! instead of asserting
  499. short sError = 0;
  500. UCHAR* pbRow = (UCHAR*)pimageRead->pData;
  501. #ifndef WIN32
  502. UCHAR bVal;
  503. S8 cVal;
  504. short sCount;
  505. short x;
  506. short y;
  507. UCHAR* pbPix;
  508. // Decompress image one row at a time. Note that we use the pitch
  509. // to move from the start of one row to the start of the next row.
  510. pbRow = (UCHAR*)pimageRead->pData;
  511. for (y = 0; (y < pimageRead->lHeight) && (sError == 0); y++)
  512. {
  513. // First byte is number of packets, which can be ignored (Animator used
  514. // it, but Animator Pro, which supports width > 320, does not.)
  515. // cVal = MEM_BYTE(m_pCurFlxBuf);
  516. pfile->Read(&cVal);
  517. // Keep processing packets until we reach the width
  518. pbPix = pbRow;
  519. x = 0;
  520. while ((x < pimageRead->lWidth) && (sError == 0))
  521. {
  522. // First byte of each packet is type/size. If bit 7 is 1, bits 6-0
  523. // are number of pixels to be copied. If bit 7 is 0, bits 6-0 are
  524. // the number of times to replicate a single pixel.
  525. // cVal = MEM_BYTE(m_pCurFlxBuf);
  526. pfile->Read(&cVal);
  527. //assert(cVal != 0); // Not sure how to handle 0!
  528. if (cVal != 0)
  529. {
  530. sCount = (short)cVal;
  531. if (sCount < 0)
  532. {
  533. sCount = -sCount;
  534. x += sCount;
  535. // Copy pixels
  536. // memcpy(pbPix,m_pCurFlxBuf,sCount);
  537. // Increment buffer pointers
  538. // m_pCurFlxBuf = MEM_SEEK(m_pCurFlxBuf,sCount);
  539. pfile->Read(pbPix, sCount);
  540. pbPix += (ULONG)sCount;
  541. }
  542. else
  543. {
  544. x += sCount;
  545. // bVal = MEM_BYTE(m_pCurFlxBuf);
  546. pfile->Read(&bVal);
  547. memset(pbPix, (int)bVal, (size_t)sCount);
  548. pbPix += (ULONG)sCount;
  549. }
  550. }
  551. else
  552. {
  553. sError = 1;
  554. }
  555. }
  556. pbRow += (ULONG)pimageRead->lPitch;
  557. }
  558. #else
  559. // Locals needed (b/c we can't use this->).
  560. long lPitch = pimageRead->lPitch;
  561. MEM pCurFlxBuf = pfile->GetMemory() + pfile->Tell();
  562. short sHeight = (short)pimageRead->lHeight;
  563. short sWidth = (short)pimageRead->lWidth;
  564. __asm
  565. {
  566. // Decompress image one row at a time. Note that we use the pitch
  567. // to move from the start of one row to the start of the next row.
  568. mov esi, pCurFlxBuf ; File ptr.
  569. mov bx, sHeight ; for (y = 0; (y < m_filehdr.sHeight) && (sError == 0); y++)
  570. cmp bx, 0 ; If sHeight == 0, done.
  571. je BRunMainLoopDone
  572. cld ; Clear direction flag.
  573. mov edi, pbRow ; pbPix = pbRow;
  574. xor ecx, ecx ; clear ecx.
  575. BRunMainLoop:
  576. // First byte is number of packets, which can be ignored (Animator used
  577. // it, but Animator Pro, which supports width > 320, does not.)
  578. AMEM_BYTE(cl, esi) ; cVal = MEM_BYTE(m_pCurFlxBuf);
  579. // Keep processing packets until we reach the width
  580. mov dx, sWidth ; x = 0; ASM version counts down instead of up.
  581. BRunPacketLoop: ; while ((x < m_filehdr.sWidth) && (sError == 0))
  582. // First byte of each packet is type/size. If bit 7 is 1, bits 6-0
  583. // are number of pixels to be copied. If bit 7 is 0, bits 6-0 are
  584. // the number of times to replicate a single pixel.
  585. AMEM_BYTE(cl, esi) ; cVal = MEM_BYTE(m_pCurFlxBuf);
  586. //assert(cVal != 0); // Not sure how to handle 0!
  587. ; sCount = (short)cVal;
  588. cmp cl, 0 ; if (sCount >= 0)
  589. jge BRunRepeat ; handle repeat pixel
  590. ; else handle uniques
  591. neg cl ; sCount = -sCount;
  592. sub dx, cx ; x += sCount; ASM version counts down instead of up.
  593. // Copy pixels
  594. ; memcpy(pbPix,m_pCurFlxBuf,sCount);
  595. ; pbPix += (ULONG)sCount;
  596. // Increment buffer pointers
  597. ; m_pCurFlxBuf = MEM_SEEK(m_pCurFlxBuf,sCount);
  598. rep movs byte ptr [edi], byte ptr [esi] ; Copy by bytes. Does nothing if cx is 0.
  599. jnz BRunPacketLoop ; If we do not hit zero (from sub), continue loop.
  600. jmp BRunPacketLoopDone
  601. BRunRepeat:
  602. // Get repeat pixel.
  603. AMEM_BYTE(al, esi) ; bVal = MEM_BYTE(m_pCurFlxBuf);
  604. sub dx, cx ; x += sCount; ASM version counts down instead of up.
  605. ; memset(pbPix, (int)bVal, (size_t)sCount);
  606. ; pbPix += (ULONG)sCount;
  607. rep stos byte ptr [edi] ; Set pixels. Does nothing if cx is 0.
  608. jnz BRunPacketLoop ; If we do not hit zero (from sub), continue loop.
  609. BRunPacketLoopDone:
  610. mov edi, pbRow
  611. add edi, lPitch ; pbRow += (ULONG)pimageRead->lPitch;
  612. mov pbRow, edi ; Remember for next iteration.
  613. dec bx ; Decrement y.
  614. jnz BRunMainLoop ; If not zero, loop.
  615. BRunMainLoopDone:
  616. mov pCurFlxBuf, esi ; Restore file ptr.
  617. }
  618. pfile->Seek((long)(pCurFlxBuf - pfile->GetMemory()), SEEK_SET);
  619. #endif // def WIN32
  620. // just return if error has been set
  621. if (sError == 1)
  622. return sError;
  623. // Set modified flag
  624. *psPixelsModified = TRUE;
  625. return 0;
  626. }
  627. ///////////////////////////////////////////////////////////////////////////////
  628. //
  629. // Handler for data chunks of type FLX_DATA_LC.
  630. //
  631. // These chunks contain the differences between the previous frame and this
  632. // frame. These are the most common types of pixel data chunks in the older
  633. // FLI files written by the original Autodesk animator. This is no longer used
  634. // by Animator Pro, but they may appear in an Animator Pro file if Animator Pro
  635. // reads an older file and modifies only some of its frames.
  636. //
  637. // The first word (16 bits) specifies the y coordinate of the first line that
  638. // was different from the previous image. This value can range from 0 to
  639. // height - 1.
  640. //
  641. // The second word (16 bits) specifies the number of lines that are represented
  642. // in this data chunk.
  643. //
  644. // The following data is organized into lines, starting at the specified y
  645. // coordinate and moving down.
  646. //
  647. // The data for each line starts with a byte that contains the number of
  648. // packets for that line. (Note: Unlike the BRUN compression, this packet
  649. // count cannot be ignored because there's no other way to know how many pixels
  650. // will be updated on each line.)
  651. //
  652. // Each packet starts with a byte that indicates how many pixels to move to the
  653. // right. At the start of each line, the position is assumed to be at the
  654. // first (left-most) pixel on that line. This skip count is added to that
  655. // position to move to the first pixel that will be changed by this packet.
  656. // This process continues across the line, with each packet adding on to the
  657. // position that the previous packet ended up on. For instance, if the first
  658. // packet specified a skip of 8 and then copied 3 pixels to the screen, then
  659. // second packet would start at 11 and would add its skip count to that.
  660. //
  661. // The skip byte is followed by a count byte which is followed by one or more
  662. // pixels. If the count is positive (bit 7 = 0) then that is the number of
  663. // pixels that follow it. If the count is negative (bit 7 = 1) then a single
  664. // pixel follows it and the count's absolute value specifies how often that
  665. // pixel is to be replicated. (Note: The positive/negative nature of the
  666. // count is reversed from the BTUN compression!)
  667. // (static)
  668. //
  669. ///////////////////////////////////////////////////////////////////////////////
  670. short CRamFlx::ReadDataLC( CImage* pimageRead, CNFile* pfile,
  671. short* psPixelsModified)
  672. {
  673. //assert(pimageRead->pbPixels != NULL);
  674. //assert(pimageRead->sPitch > 0);
  675. // just return with error instead of asserting
  676. if ((pimageRead->pData == NULL) || (pimageRead->lPitch <= 0))
  677. return 1;
  678. short y;
  679. short lines;
  680. UCHAR* pbRow;
  681. // The first word specifies the starting y (another way of looking at it
  682. // is the number of lines that are unchanged from the previous image).
  683. // y = MEM_WORD(m_pCurFlxBuf);
  684. pfile->Read(&y);
  685. // Init row pointer to point at start of specified row
  686. pbRow = (UCHAR*)pimageRead->pData + ((ULONG)y * (ULONG)pimageRead->lPitch);
  687. // The second word specifies the number of lines in this chunk.
  688. // lines = MEM_WORD(m_pCurFlxBuf);
  689. pfile->Read(&lines);
  690. // Let's check to see if the pixels are modified from the previous frame by
  691. // checking the number of delta lines. If the number of delta lines is zero, then
  692. // we know that there is no delta.
  693. if (lines < 1)
  694. {
  695. // Set to unmodified.
  696. *psPixelsModified = FALSE;
  697. }
  698. else
  699. {
  700. // Set modified flag
  701. *psPixelsModified = TRUE;
  702. }
  703. #ifndef WIN32
  704. UCHAR bVal;
  705. S8 cVal;
  706. short sCount;
  707. UCHAR* pbPix;
  708. short packets;
  709. while (lines > 0)
  710. {
  711. // Set pixel pointer to start of row
  712. pbPix = pbRow;
  713. // For debugging, prefetch a bunch of values to view them in the debugger
  714. #if 0
  715. long lPos = pfile->tellg();
  716. static UCHAR bData[100];
  717. pfile->read(bData, sizeof(bData));
  718. pfile->seekg(lPos);
  719. #endif
  720. // The first byte for each line is the number of packets.
  721. // This can be 0, which indicates no changes on that line.
  722. // bVal = MEM_BYTE(m_pCurFlxBuf);
  723. pfile->Read(&bVal);
  724. packets = (short)bVal;
  725. while (packets > 0)
  726. {
  727. // The first byte of each packet is a column skip.
  728. // Adjust pixel pointer to skip that number of pixels.
  729. // bVal = MEM_BYTE(m_pCurFlxBuf);
  730. pfile->Read(&bVal);
  731. pbPix = pbPix + (ULONG)bVal;
  732. // Second byte of each packet is type/size. If bit 7 is 0, bits 6-0
  733. // are number of pixels to be copied. If bit 7 is 1, bits 6-0 are
  734. // the number of times to replicate a single pixel.
  735. // cVal = MEM_BYTE(m_pCurFlxBuf);
  736. pfile->Read(&cVal);
  737. // assert(cVal != 0); // Not sure how to handle 0, so stop if it comes up!
  738. if (cVal == 0)
  739. cVal = 0;
  740. sCount = (short)cVal;
  741. if (sCount > 0)
  742. {
  743. // memcpy(pbPix,m_pCurFlxBuf,sCount);
  744. // m_pCurFlxBuf = MEM_SEEK(m_pCurFlxBuf,sCount);
  745. pfile->Read(pbPix, sCount);
  746. pbPix += (ULONG)sCount;
  747. }
  748. else
  749. {
  750. sCount = -sCount;
  751. // bVal = MEM_BYTE(m_pCurFlxBuf);
  752. pfile->Read(&bVal);
  753. memset(pbPix, (int)bVal, (size_t)sCount);
  754. pbPix += (ULONG)sCount;
  755. }
  756. // Adjust remaining packets
  757. packets--;
  758. }
  759. // Move row pointer to start of next row
  760. pbRow += (ULONG)pimageRead->lPitch;
  761. // Adjust remaining lines
  762. lines--;
  763. }
  764. #else
  765. // Locals needed (b/c we can't use this->).
  766. long lPitch = pimageRead->lPitch;
  767. MEM pCurFlxBuf = pfile->GetMemory() + pfile->Tell();
  768. __asm
  769. {
  770. mov esi, pCurFlxBuf ; File ptr.
  771. mov dx, lines ; Number of lines to process.
  772. cmp dx, 0 ; If lines == 0,
  773. je LCMainLoopDone ; nothing to do.
  774. // Set pixel pointer to start of row
  775. mov edi, pbRow ; pbPix = pbRow;
  776. xor ebx, ebx
  777. xor ecx, ecx
  778. LCMainLoop: ; while (lines > 0)
  779. // The first byte for each line is the number of packets.
  780. // This can be 0, which indicates no changes on that line.
  781. AMEM_BYTE(ah, esi) ; bVal = MEM_BYTE(m_pCurFlxBuf);
  782. cmp ah, 0 ; If packets <= 0
  783. jle LCPacketLoopDone ; done.
  784. ; packets = (short)bVal;
  785. LCPacketLoop: ; while (packets > 0)
  786. // The first byte of each packet is a column skip.
  787. // Adjust pixel pointer to skip that number of pixels.
  788. AMEM_BYTE(bl, esi) ; bVal = MEM_BYTE(m_pCurFlxBuf);
  789. add edi, ebx ; pbPix = pbPix + (ULONG)bVal;
  790. // Second byte of each packet is type/size. If bit 7 is 0, bits 6-0
  791. // are number of pixels to be copied. If bit 7 is 1, bits 6-0 are
  792. // the number of times to replicate a single pixel.
  793. AMEM_BYTE(cl, esi) ; cVal = MEM_BYTE(m_pCurFlxBuf);
  794. // assert(cVal != 0); // Not sure how to handle 0, so stop if it comes up!
  795. ; sCount = (short)cVal;
  796. cmp cl, 0 ; if (sCount < 0)
  797. jl LCRepeat ; handle repeat pixel
  798. ; else handle uniques
  799. ; memcpy(pbPix,m_pCurFlxBuf,sCount);
  800. ; m_pCurFlxBuf = MEM_SEEK(m_pCurFlxBuf,sCount);
  801. ; pbPix += (ULONG)sCount;
  802. rep movs byte ptr [edi], byte ptr [esi] ; Copy by bytes. Does nothing if cx is 0.
  803. jmp LCNextPacket
  804. LCRepeat:
  805. neg cl ; sCount = -sCount;
  806. // Get repeat pixel.
  807. AMEM_BYTE(al, esi) ; bVal = MEM_BYTE(m_pCurFlxBuf);
  808. ; memset(pbPix, (int)bVal, (size_t)sCount);
  809. ; pbPix += (ULONG)sCount;
  810. rep stos byte ptr [edi] ; Set pixels. Does nothing if cx is 0.
  811. LCNextPacket:
  812. // Adjust remaining packets
  813. dec ah ; packets--;
  814. jnz LCPacketLoop ; If not zero, continue looping.
  815. LCPacketLoopDone:
  816. // Move row pointer to start of next row
  817. mov edi, pbRow
  818. add edi, lPitch ; pbRow += (ULONG)pimageRead->lPitch;
  819. mov pbRow, edi ; Remember for next iteration.
  820. // Adjust remaining lines
  821. dec dx ; lines--;
  822. jnz LCMainLoop ; If not zero, continue looping.
  823. LCMainLoopDone:
  824. mov pCurFlxBuf, esi ; Restore file ptr.
  825. }
  826. pfile->Seek((long)(pCurFlxBuf - pfile->GetMemory()), SEEK_SET);
  827. #endif // ndef WIN32
  828. return 0;
  829. }
  830. ///////////////////////////////////////////////////////////////////////////////
  831. //
  832. // Handler for data chunks of type FLX_DATA_SS2.
  833. //
  834. // These chunks contain the differences between the previous frame and this
  835. // frame. They are similar to FLX_DATA_LC, but are word oriented instead of
  836. // byte oriented.
  837. //
  838. // The first word for "each line can begin with some optional words
  839. // that are used to skip lines and set the last byte in the line for
  840. // animations with odd widths." The next word will be the number of
  841. // packets. The first byte of each packet is a column skip.
  842. // Second byte of each packet is type/size. If bit 7 is 0, bits 6-0
  843. // are number of pixel pairs to be copied. If bit 7 is 1, bits 6-0 are
  844. // the number of times to replicate a single pixel pair.
  845. // (static)
  846. //
  847. ///////////////////////////////////////////////////////////////////////////////
  848. short CRamFlx::ReadDataSS2(CImage* pimageRead, CNFile* pfile,
  849. short* psPixelsModified)
  850. {
  851. //assert(pimageRead->pbPixels != NULL);
  852. //assert(pimageRead->sPitch > 0);
  853. // just return with error instead of asserting
  854. if ((pimageRead->pData == NULL) || (pimageRead->lPitch <= 0))
  855. return 1;
  856. short lines;
  857. short packets;
  858. UCHAR byLastByte;
  859. short bLastByte = FALSE;
  860. // The first word specifies the starting y (another way of looking at it
  861. // is the number of lines that are unchanged from the previous image).
  862. // pfile->Read(&y, 2); not in FLI_SS2
  863. // The first word specifies the number of lines in this chunk.
  864. // lines = MEM_WORD(m_pCurFlxBuf);
  865. pfile->Read(&lines);
  866. // Let's check to see if any actual delta is being processed and set the
  867. // pixels modified flag accordingly.
  868. if (lines < 1)
  869. {
  870. // Make sure the modified flag is FALSE.
  871. *psPixelsModified = FALSE;
  872. }
  873. else
  874. {
  875. // Set modified flag to true.
  876. *psPixelsModified = TRUE;
  877. }
  878. #ifndef WIN32
  879. UCHAR bVal;
  880. S8 cVal;
  881. USHORT wVal;
  882. short sCount;
  883. short y;
  884. UCHAR* pbPix;
  885. // Start at line 0
  886. y = 0;
  887. while (lines > 0)
  888. {
  889. // The first word for "each line can begin with some optional words
  890. // that are used to skip lines and set the last byte in the line for
  891. // animations with odd widths."
  892. do
  893. {
  894. // wVal = MEM_WORD(m_pCurFlxBuf);
  895. pfile->Read(&wVal);
  896. // "The high order two bits of the word is used to determine the
  897. // contents of the word."
  898. switch (wVal & 0xC000)
  899. {
  900. // 0 0 The word contains the packet count; the packets follow
  901. // this word. This is our signal to stop processing "optional
  902. // words".
  903. case 0x0000:
  904. break;
  905. // 1 0 "The low order byte is to be stored in the last bye of
  906. // the current line. The packet count always folows this word."
  907. // This is another signal to stop processing "optional words".
  908. case 0x8000:
  909. //assert(bLastByte != TRUE); // We should not have already set the "last byte".
  910. // if this error condition occurs, let's just break out of everything and return error
  911. // this should not cause any problems with the stack since return should clear it
  912. if (bLastByte == TRUE)
  913. return 1;
  914. byLastByte = (UCHAR)(wVal & (USHORT)0x00ff);
  915. bLastByte = TRUE;
  916. // Read the packet count.
  917. // wVal = MEM_WORD(m_pCurFlxBuf);
  918. pfile->Read(&wVal);
  919. break;
  920. // 1 1 "The word contains a line skip count. The number of
  921. // lines skipped is given by the absolute value of the word.
  922. // This is NOT a signal to stop processing "optional words".
  923. case 0xC000:
  924. // Skip abs(wVal) lines
  925. y += -((short)wVal);
  926. break;
  927. }
  928. } while ((wVal & 0xC000) == 0xC000);
  929. // The packet count should now be in wVal.
  930. packets = (short)wVal;
  931. // Init pointer to point at start of specified row
  932. pbPix = (UCHAR*)pimageRead->pData + ((ULONG)y * (ULONG)pimageRead->lPitch);
  933. while (packets > 0)
  934. {
  935. // The first byte of each packet is a column skip.
  936. // Adjust pixel pointer to skip that number of pixels.
  937. // bVal = MEM_BYTE(m_pCurFlxBuf);
  938. pfile->Read(&bVal);
  939. pbPix = pbPix + (ULONG)bVal;
  940. // Second byte of each packet is type/size. If bit 7 is 0, bits 6-0
  941. // are number of pixel pairs to be copied. If bit 7 is 1, bits 6-0 are
  942. // the number of times to replicate a single pixel pair.
  943. // cVal = MEM_BYTE(m_pCurFlxBuf);
  944. pfile->Read(&cVal);
  945. sCount = (short)cVal;
  946. if (sCount > 0)
  947. {
  948. sCount *= sizeof(USHORT);
  949. // memcpy(pbPix, m_pCurFlxBuf, sCount);
  950. // m_pCurFlxBuf = MEM_SEEK(m_pCurFlxBuf,sCount);
  951. pfile->Read(pbPix, sCount);
  952. pbPix += (ULONG)(sCount);
  953. }
  954. else
  955. {
  956. sCount = (short)-sCount;
  957. // wVal = MEM_WORD(m_pCurFlxBuf);
  958. pfile->Read(&wVal);
  959. // memset(pbPix, (int)wVal, (size_t)sCount);
  960. USHORT* pwPix = (USHORT*)pbPix;
  961. for (short i = 0; i < sCount; i++)
  962. *pwPix++ = wVal;
  963. pbPix = (UCHAR*)pwPix;
  964. }
  965. // Adjust remaining packets
  966. packets--;
  967. }
  968. // Place last byte if specified.
  969. if (bLastByte == TRUE)
  970. {
  971. // Get pointer to end of this row.
  972. pbPix = (UCHAR*)pimageRead->pData + (((ULONG)y + 1L) * (ULONG)pimageRead->lPitch) - 1L;
  973. // Set pixel at end of row.
  974. *pbPix = byLastByte;
  975. bLastByte = FALSE;
  976. }
  977. // Adjust remaining lines
  978. lines--;
  979. // Go to next line
  980. y++;
  981. }
  982. #else // ifdef WIN32
  983. // Need a local for this-> stuff.
  984. MEM pCurFlxBuf = pfile->GetMemory() + pfile->Tell();
  985. void* pData = pimageRead->pData;
  986. long lPitch = pimageRead->lPitch;
  987. long lWidth = pimageRead->lWidth;
  988. __asm
  989. {
  990. cmp lines, 0 ; If lines == 0
  991. je SS2MainLoopDone ; Done
  992. cld ; clear direction flag.
  993. mov esi, pCurFlxBuf ; Get file ptr.
  994. xor ebx, ebx ; Clear so we can use high 16 bits for match.
  995. xor edx, edx ; Clear so we can use high 16 bits for match.
  996. SS2MainLoop:
  997. // The first word for "each line can begin with some optional words
  998. // that are used to skip lines and set the last byte in the line for
  999. // animations with odd widths."
  1000. OptionalPacketsLoop:
  1001. AMEM_WORD(ax, esi) ; wVal = MEM_WORD(m_pCurFlxBuf);
  1002. // "The high order two bits of the word is used to determine the
  1003. // contents of the word."
  1004. test ah, 0C0H
  1005. // If 0 0, the word contains the packet count; the packets follow
  1006. // this word. This is our signal to stop processing "optional
  1007. // words".
  1008. jz OptionalPacketsDone ; If 0, we are done.
  1009. test ah, 040H ; If not in ah then al contains
  1010. jz StoreLastByte ; contains byte for end of line.
  1011. // 1 1 "The word contains a line skip count. The number of
  1012. // lines skipped is given by the absolute value of the word.
  1013. // This is NOT a signal to stop processing "optional words".
  1014. // Skip abs(wVal) lines
  1015. neg ax ; Make positive.
  1016. add bx, ax ; y += -((short)wVal);
  1017. // Continue
  1018. jmp OptionalPacketsLoop
  1019. StoreLastByte:
  1020. // 1 0 "The low order byte is to be stored in the last byte of
  1021. // the current line. The packet count always folows this word."
  1022. // This is another signal to stop processing "optional words".
  1023. mov byLastByte, al ; byLastByte = (UCHAR)(wVal & (USHORT)0x00ff);
  1024. mov bLastByte, TRUE ; bLastByte = TRUE;
  1025. // Read the packet count.
  1026. AMEM_WORD(ax, esi) ; wVal = MEM_WORD(m_pCurFlxBuf);
  1027. OptionalPacketsDone:
  1028. // The packet count should now be in wVal (ax).
  1029. mov packets, ax ; packets = (short)wVal;
  1030. // Init pointer to point at start of specified row
  1031. ;pbPix = (UCHAR*)pimageRead->pData + ((ULONG)y * (ULONG)pimageRead->lPitch);
  1032. mov eax, lPitch ; pimageRead->lPitch
  1033. mul ebx ; Multiply by y. Counting on edx getting 0000.
  1034. mov edi, eax ; Copy result.
  1035. add edi, pData ; pimageRead->pData
  1036. // If nothing to do . . .
  1037. cmp packets, 0 ; If packets == 0
  1038. je SS2PacketLoopDone ; done.
  1039. SS2PacketLoop:
  1040. // Make sure everything in edx is clear.
  1041. xor edx, edx
  1042. // The first byte of each packet is a column skip.
  1043. // Adjust pixel pointer to skip that number of pixels.
  1044. AMEM_BYTE(dl, esi) ; bVal = MEM_BYTE(pCurFlxBuf);
  1045. add edi, edx ; pbPix = pbPix + (ULONG)bVal;
  1046. xor ecx, ecx ; Clear ecx just in case.
  1047. // Second byte of each packet is type/size. If bit 7 is 0, bits 6-0
  1048. // are number of pixel pairs to be copied. If bit 7 is 1, bits 6-0 are
  1049. // the number of times to replicate a single pixel pair.
  1050. AMEM_BYTE(cl, esi) ; cVal = MEM_BYTE(pCurFlxBuf);
  1051. // cl contains cVal/sCount.
  1052. ; sCount = (short)cVal
  1053. cmp cl, 0 ; if (sCount > 0)
  1054. jle SS2Repeat ; handle repeat packets,
  1055. ; else, uniques
  1056. // Setup copy
  1057. shr cx, 1 ; by dwords.
  1058. ; memcpy(pbPix, pCurFlxBuf, sCount);
  1059. ; pCurFlxBuf = MEM_SEEK(pCurFlxBuf,sCount);
  1060. ; pbPix += (ULONG)(sCount);
  1061. rep movs dword ptr [edi], dword ptr [esi] ; Copy by dwords. Does nothing if cx is 0.
  1062. jnc SS2RunDone ; If no carry from shr
  1063. movs word ptr [edi], word ptr [esi] ; Copy last word.
  1064. jmp SS2RunDone
  1065. SS2Repeat:
  1066. neg cl ; sCount = (short)-sCount;
  1067. // Setup memset.
  1068. // Get repeat pixel.
  1069. // NOTE: High part of eax could be dirty from multiplies, but we
  1070. // shift that out.
  1071. AMEM_WORD(ax, esi) ; wVal = MEM_WORD(pCurFlxBuf);
  1072. ; Here, for more speed, we copy by dword, so we duplicate ax in eax high
  1073. mov dx, ax ; copy ax so we can put it back.
  1074. shl eax, 16 ; shift ax into eax high
  1075. mov ax, dx ; put ax back into eax low
  1076. shr cx, 1 ; by dwords.
  1077. ; USHORT* pwPix = (USHORT*)pbPix;
  1078. ; for (short i = 0; i < sCount; i++)
  1079. ; *pwPix++ = wVal;
  1080. ; pbPix = (UCHAR*)pwPix;
  1081. rep stos dword ptr [edi] ; Store. If cx == 0, skipped.
  1082. jnc SS2RunDone ; If there was no carry from the shift right
  1083. stos word ptr [edi] ; Store last word.
  1084. SS2RunDone:
  1085. // Adjust remaining packets
  1086. dec packets ; packets--;
  1087. jnz SS2PacketLoop ; Loop
  1088. SS2PacketLoopDone:
  1089. // Place last byte if specified.
  1090. cmp bLastByte, FALSE ; if (bLastByte == FALSE)
  1091. je NoLastByte ; don't copy last byte.
  1092. // Get pointer to end of this row.
  1093. ; pbPix = (UCHAR*)pimageRead->pData
  1094. ; + ((long)y * pimageRead->lPitch)
  1095. ; + pimageRead->lWidth - 1L;
  1096. mov eax, lPitch ; pimageRead->lPitch
  1097. mul ebx ; Multiply by y. Counting on edx getting 0000.
  1098. mov edi, eax ; Copy result.
  1099. add edi, lWidth ; pimageRead->lWidth
  1100. dec edi ; -1L
  1101. add edi, pData ; pimageRead->pData
  1102. // Set pixel at end of row.
  1103. ; *pbPix = byLastByte;
  1104. mov al, byLastByte ; Get byLastByte
  1105. mov byte ptr [edi], al ; Store it.
  1106. mov bLastByte, FALSE ; bLastByte = FALSE;
  1107. NoLastByte:
  1108. // Go to next line
  1109. inc bx ; y++;
  1110. // Adjust remaining lines
  1111. dec lines ; lines--
  1112. jnz SS2MainLoop
  1113. SS2MainLoopDone:
  1114. // Put back for C++ code.
  1115. mov pCurFlxBuf, esi ; Restore file ptr.
  1116. }
  1117. pfile->Seek((long)(pCurFlxBuf - pfile->GetMemory()), SEEK_SET);
  1118. #endif // ndef WIN32
  1119. return 0;
  1120. }
  1121. ///////////////////////////////////////////////////////////////////////////////
  1122. //
  1123. // Helper function that reads the header of the flic file. Always returns
  1124. // with file position at start of frame 1.
  1125. //
  1126. ///////////////////////////////////////////////////////////////////////////////
  1127. short CRamFlx::ReadHeader(CNFile* pfile)
  1128. {
  1129. // Seek to start of file
  1130. pfile->Seek(0, SEEK_SET);
  1131. // Read the part of the file header that's common to FLC and FLI files.
  1132. pfile->Read(&m_filehdr.lEntireFileSize);
  1133. pfile->Read(&m_filehdr.wMagic);
  1134. pfile->Read(&m_filehdr.sNumFrames);
  1135. pfile->Read(&m_filehdr.sWidth);
  1136. pfile->Read(&m_filehdr.sHeight);
  1137. pfile->Read(&m_filehdr.sDepth);
  1138. pfile->Read(&m_filehdr.sFlags);
  1139. // The headers become different at this point
  1140. if (m_filehdr.wMagic == FLX_MAGIC_FLC)
  1141. {
  1142. // Read the remainder of the FLC header
  1143. pfile->Read(&m_filehdr.lMilliPerFrame);
  1144. pfile->Read(&m_filehdr.sReserveA);
  1145. pfile->Read(&m_filehdr.dCreatedTime);
  1146. pfile->Read(&m_filehdr.dCreator);
  1147. pfile->Read(&m_filehdr.dUpdatedTime);
  1148. pfile->Read(&m_filehdr.dUpdater);
  1149. pfile->Read(&m_filehdr.sAspectX);
  1150. pfile->Read(&m_filehdr.sAspectY);
  1151. pfile->Read(m_filehdr.bReservedB, sizeof(m_filehdr.bReservedB));
  1152. pfile->Read(&m_filehdr.lOffsetFrame1);
  1153. pfile->Read(&m_filehdr.lOffsetFrame2);
  1154. pfile->Read(m_filehdr.bReservedC, sizeof(m_filehdr.bReservedC));
  1155. // In FLC files, an optional prefix chunk may follow the header.
  1156. // According to Autodesk it contains information not related to
  1157. // animation playback and should be ignored. They also say that
  1158. // programs other than Animator Pro shouldn't write it.
  1159. // We currently ignore this chunk. In the future, we might
  1160. // consider preserving it in case this flic is written out to a
  1161. // new file. The easiest way to skip over it is to seek directly
  1162. // to the first frame using the offset specified in the header.
  1163. // Seek directly to first frame.
  1164. pfile->Seek(m_filehdr.lOffsetFrame1, SEEK_SET);
  1165. }
  1166. else
  1167. {
  1168. // Read the FLI's jiffies (a jiffy is 1/70th second) and convert to
  1169. // to FLC's milliseconds.
  1170. short sJiffies;
  1171. pfile->Read(&sJiffies);
  1172. m_filehdr.lMilliPerFrame = (long)( (double)sJiffies * ((double)1000 / (double)70L) + (double)0.5 );
  1173. // Set times to 0 for lack of better value (some day, we could read the
  1174. // file's date and time stamp and put it here). We use "FLIB" for the
  1175. // serial numbers, which is safe according to the doc's.
  1176. m_filehdr.dCreatedTime = 0;
  1177. m_filehdr.dCreator = 0x464c4942;
  1178. m_filehdr.dUpdatedTime = 0;
  1179. m_filehdr.dUpdater = 0x464c4942;
  1180. // Aspect ratio for 320x200 (which is the only FLI size) is 6:5
  1181. m_filehdr.sAspectX = 6;
  1182. m_filehdr.sAspectY = 5;
  1183. // Skip to end of header. This is also the starting position of
  1184. // frame 1, which we save in the header.
  1185. pfile->Seek(128, SEEK_SET);
  1186. m_filehdr.lOffsetFrame1 = pfile->Tell();
  1187. // Get size of frame 1's chunk in order to calculate the starting
  1188. // position of frame 2.
  1189. long lSizeFrame1;
  1190. pfile->Read(&lSizeFrame1);
  1191. m_filehdr.lOffsetFrame2 = m_filehdr.lOffsetFrame1 + lSizeFrame1;
  1192. // Seek to start of frame 1
  1193. pfile->Seek(m_filehdr.lOffsetFrame1, SEEK_SET);
  1194. }
  1195. // Allocate space for RAM buffer
  1196. short sError=0;
  1197. long lSizeFile = m_filehdr.lEntireFileSize - m_filehdr.lOffsetFrame1;
  1198. if ((m_pucFlxBuf = (UCHAR*)malloc(lSizeFile)) != NULL)
  1199. {
  1200. pfile->Read(m_pucFlxBuf, lSizeFile);
  1201. // m_pCurFlxBuf = MEM_OPEN(m_pFlxBuf);
  1202. // Adjust frame offsets
  1203. m_filehdr.lOffsetFrame2 -= m_filehdr.lOffsetFrame1;
  1204. m_filehdr.lOffsetFrame1 = 0;
  1205. m_file.Open(m_pucFlxBuf, lSizeFile, ENDIAN_LITTLE);
  1206. }
  1207. else sError = -1;
  1208. // If good then return success, otherwise return error.
  1209. if (pfile->Error() == FALSE && sError == 0)
  1210. return 0;
  1211. else
  1212. return 1;
  1213. return sError;
  1214. }
  1215. ///////////////////////////////////////////////////////////////////////////////
  1216. //
  1217. // Helper function that clears file header.
  1218. //
  1219. ///////////////////////////////////////////////////////////////////////////////
  1220. void CRamFlx::ClearHeader(void)
  1221. {
  1222. // Clear all fields in file header
  1223. short i;
  1224. m_filehdr.lEntireFileSize = 0;
  1225. m_filehdr.wMagic = 0;
  1226. m_filehdr.sNumFrames = 0;
  1227. m_filehdr.sWidth = 0;
  1228. m_filehdr.sHeight = 0;
  1229. m_filehdr.sDepth = 0;
  1230. m_filehdr.sFlags = 0;
  1231. m_filehdr.lMilliPerFrame = 0;
  1232. m_filehdr.sReserveA = 0;
  1233. m_filehdr.dCreatedTime = 0;
  1234. m_filehdr.dCreator = 0;
  1235. m_filehdr.dUpdatedTime = 0;
  1236. m_filehdr.dUpdater = 0;
  1237. m_filehdr.sAspectX = 0;
  1238. m_filehdr.sAspectY = 0;
  1239. for (i = 0; i < sizeof(m_filehdr.bReservedB); i++)
  1240. m_filehdr.bReservedB[i] = 0;
  1241. m_filehdr.lOffsetFrame1 = 0;
  1242. m_filehdr.lOffsetFrame2 = 0;
  1243. for (i = 0; i < sizeof(m_filehdr.bReservedC); i++)
  1244. m_filehdr.bReservedC[i] = 0;
  1245. }
  1246. ///////////////////////////////////////////////////////////////////////////////
  1247. //
  1248. // Helper functions to deal with memory associated with buf's.
  1249. //
  1250. ///////////////////////////////////////////////////////////////////////////////
  1251. void CRamFlx::InitBuf(CImage* pimage)
  1252. {
  1253. // The pointers MUST be cleared to NULL so we can tell later on whether
  1254. // any memory needs to be freed.
  1255. pimage->pData = NULL;
  1256. if (pimage->pPalette != NULL)
  1257. {
  1258. pimage->pPalette->pData = NULL;
  1259. }
  1260. }
  1261. short CRamFlx::AllocBuf(CImage* pimage, long lWidth, long lHeight, short sColors)
  1262. {
  1263. short sError=0;
  1264. // Allocate image buffer for pixels & set pitch to width
  1265. pimage->ulType = FLX8_888;
  1266. pimage->lWidth = lWidth;
  1267. pimage->lHeight = lHeight;
  1268. pimage->lPitch = DWORDALIGN(lWidth);
  1269. pimage->ulSize = pimage->lPitch * lHeight;
  1270. pimage->sDepth = 8;
  1271. sError = pimage->CreateData(pimage->ulSize); // Allocate image space, returns 0 on success
  1272. if (sError == 0)
  1273. {
  1274. if (pimage->CreatePalette(sColors * CPal::GetPalEntrySize(PFLX)) == 0)
  1275. {
  1276. // Allocate palette buffer for colors
  1277. pimage->pPalette->ulType = PFLX;
  1278. pimage->pPalette->sNumEntries = sColors;
  1279. pimage->pPalette->sPalEntrySize = CPal::GetPalEntrySize(PFLX);
  1280. }
  1281. else
  1282. {
  1283. sError = 1;
  1284. }
  1285. }
  1286. // If it worked then return success
  1287. if (sError == 0)
  1288. return 0;
  1289. // Else free anything that did get allocated and return failure
  1290. else
  1291. {
  1292. FreeBuf(pimage);
  1293. return 1;
  1294. }
  1295. }
  1296. void CRamFlx::FreeBuf(CImage* pimage)
  1297. {
  1298. if (pimage != NULL)
  1299. {
  1300. pimage->DestroyData();
  1301. if (pimage->pPalette != NULL)
  1302. {
  1303. pimage->DestroyPalette();
  1304. }
  1305. }
  1306. }
  1307. void CRamFlx::CopyBuf(CImage* pimageDst, CImage* pimageSrc)
  1308. {
  1309. // Copy initial CImage member variables
  1310. pimageDst->ulType = pimageSrc->ulType;
  1311. pimageDst->ulSize = pimageSrc->ulSize;
  1312. pimageDst->lWidth = pimageSrc->lWidth;
  1313. pimageDst->lHeight = pimageSrc->lHeight;
  1314. pimageDst->lPitch = pimageSrc->lPitch;
  1315. pimageDst->sDepth = pimageSrc->sDepth;
  1316. // Copy pixels one row at a time
  1317. UCHAR* pbSrc = (UCHAR*)pimageSrc->pData;
  1318. UCHAR* pbDst = (UCHAR*)pimageDst->pData;
  1319. for (short y = 0; y < pimageSrc->lHeight; y++)
  1320. {
  1321. memcpy(pbDst, pbSrc, pimageSrc->lWidth);
  1322. pbSrc += (ULONG)pimageSrc->lPitch;
  1323. pbDst += (ULONG)pimageDst->lPitch;
  1324. }
  1325. // Copy initial CPal member variables
  1326. pimageDst->pPalette->ulType = pimageSrc->pPalette->ulType;
  1327. pimageDst->pPalette->ulSize = pimageSrc->pPalette->ulSize;
  1328. pimageDst->pPalette->sStartIndex = pimageSrc->pPalette->sStartIndex;
  1329. pimageDst->pPalette->sNumEntries = pimageSrc->pPalette->sNumEntries;
  1330. pimageDst->pPalette->sPalEntrySize = pimageSrc->pPalette->sPalEntrySize;
  1331. // Copy colors
  1332. memcpy( pimageDst->pPalette->pData, pimageSrc->pPalette->pData,
  1333. pimageDst->pPalette->sNumEntries * pimageDst->pPalette->sPalEntrySize);
  1334. }
  1335. /////////////////////////////////////////////////////////////////////////////////////
  1336. // CreateFramePointers
  1337. //
  1338. // CreateFramePointers creates a list of byte pointers
  1339. // These byte pointers point to each frame within
  1340. // the flic memory file (frame 1 to n). To retrieve a frame,
  1341. // seek m_file to the frame position wanted and call DoReadFrame.
  1342. //
  1343. // These frame positions can only be used with a flic containing no delta compression
  1344. /////////////////////////////////////////////////////////////////////////////////////
  1345. short CRamFlx::CreateFramePointers(void)
  1346. {
  1347. short sError = 0;
  1348. long lSizeFrame;
  1349. // Allocate the space for the frame pointers
  1350. if ((m_plFrames = (long*)malloc((m_filehdr.sNumFrames+1) * sizeof(long))) == NULL)
  1351. sError = -1;
  1352. else
  1353. {
  1354. // Assign all the frame pointers
  1355. for (short sFrame = 1; sFrame <= m_filehdr.sNumFrames; sFrame++)
  1356. {
  1357. // Set pointer to frame
  1358. m_plFrames[sFrame] = m_file.Tell();
  1359. // Get size of frame
  1360. // lSizeFrame = MEM_DWORD(m_pCurFlxBuf);
  1361. m_file.Read(&lSizeFrame);
  1362. // Seek to beginning of next frame
  1363. // m_pCurFlxBuf = MEM_SEEK(m_pCurFlxBuf,lSizeFrame - sizeof(ULONG));
  1364. m_file.Seek(lSizeFrame - sizeof(ULONG), SEEK_CUR);
  1365. }
  1366. }
  1367. return sError;
  1368. }
  1369. ///////////////////////////////////////////////////////////////////////////////
  1370. // CImage/CPal FLX8_888/PFLX link late functions.
  1371. ///////////////////////////////////////////////////////////////////////////////
  1372. /////////////////////////////////////////////////////////////////////////////////////
  1373. //
  1374. // Convert to FLX8_888 format from a standard format.
  1375. // Returns FLX8_888 on success; NOT_SUPPORTED otherwise.
  1376. //
  1377. /////////////////////////////////////////////////////////////////////////////////////
  1378. static short ConvToFlx8_888(CImage* pImage)
  1379. {
  1380. short sRes = NOT_SUPPORTED; // Assume error.
  1381. ASSERT(pImage != NULL);
  1382. switch (pImage->ulType)
  1383. {
  1384. case BMP8:
  1385. // The only difference from BMP8 is the palette.
  1386. if (pImage->pPalette != NULL)
  1387. {
  1388. if (pImage->pPalette->ulType == PDIB)
  1389. {
  1390. CPal* ppal = pImage->pPalette;
  1391. // Detatch the original palette data from the Image's palette.
  1392. IM_RGBQUAD* prgbq = (IM_RGBQUAD*)ppal->DetatchData();
  1393. // Create new palette data for the pImage
  1394. if (ppal->CreateData((ppal->sStartIndex + ppal->sNumEntries) * CPal::GetPalEntrySize(PFLX)) == 0)
  1395. {
  1396. PRGBT8 prgbt = (PRGBT8)ppal->pData;
  1397. for (short sIndex = ppal->sStartIndex; sIndex < ppal->sStartIndex + ppal->sNumEntries; sIndex++)
  1398. {
  1399. prgbt[sIndex].ucRed = prgbq[sIndex].rgbRed;
  1400. prgbt[sIndex].ucGreen = prgbq[sIndex].rgbGreen;
  1401. prgbt[sIndex].ucBlue = prgbq[sIndex].rgbBlue;
  1402. }
  1403. // Set new parameters.
  1404. ppal->ulType = PFLX;
  1405. ppal->sPalEntrySize = CPal::GetPalEntrySize(ppal->ulType);
  1406. pImage->ulType = FLX8_888;
  1407. sRes = FLX8_888;
  1408. }
  1409. else
  1410. {
  1411. TRACE("ConvToFlx8_888(): Unable to allocate new buffer.\n");
  1412. }
  1413. // If successful . . .
  1414. if (sRes != NOT_SUPPORTED)
  1415. {
  1416. // Destroy the old palette data.
  1417. CImage::DestroyDetatchedData((void**)&prgbq);
  1418. }
  1419. else
  1420. {
  1421. // Restore the palette data.
  1422. ppal->pData = (UCHAR*)prgbq;
  1423. }
  1424. }
  1425. else
  1426. {
  1427. TRACE("ConvToFlx8_888(): Palette is not BMP8:PDIB.\n");
  1428. }
  1429. }
  1430. else
  1431. {
  1432. TRACE("ConvToFlx8_888(): No palette!?\n");
  1433. }
  1434. break;
  1435. default:
  1436. // All others not supported.
  1437. break;
  1438. }
  1439. return sRes;
  1440. }
  1441. /////////////////////////////////////////////////////////////////////////////////////
  1442. //
  1443. // Convert from FLX8_888 format to a standard format.
  1444. // Returns new format on success; NOT_SUPPORTED otherwise.
  1445. //
  1446. /////////////////////////////////////////////////////////////////////////////////////
  1447. static short ConvFromFlx8_888(CImage* pImage)
  1448. {
  1449. short sRes = NOT_SUPPORTED; // Assume error.
  1450. ASSERT(pImage != NULL);
  1451. ASSERT(pImage->ulType == FLX8_888);
  1452. // Convert to BMP8.
  1453. // The only difference from BMP8 is the palette.
  1454. if (pImage->pPalette != NULL)
  1455. {
  1456. if (pImage->pPalette->ulType == PFLX)
  1457. {
  1458. CPal* ppal = pImage->pPalette;
  1459. // Detatch the original palette data from the Image's palette.
  1460. PRGBT8 prgbt = (PRGBT8)ppal->DetatchData();
  1461. // Create new palette data for the pImage
  1462. if (ppal->CreateData((ppal->sStartIndex + ppal->sNumEntries) * CPal::GetPalEntrySize(PDIB)) == 0)
  1463. {
  1464. IM_RGBQUAD* prgbq = (IM_RGBQUAD*)ppal->pData;
  1465. for (short sIndex = ppal->sStartIndex; sIndex < ppal->sStartIndex + ppal->sNumEntries; sIndex++)
  1466. {
  1467. prgbq[sIndex].rgbRed = prgbt[sIndex].ucRed;
  1468. prgbq[sIndex].rgbGreen = prgbt[sIndex].ucGreen;
  1469. prgbq[sIndex].rgbBlue = prgbt[sIndex].ucBlue;
  1470. }
  1471. // Set new parameters.
  1472. ppal->ulType = PDIB;
  1473. ppal->sPalEntrySize = CPal::GetPalEntrySize(ppal->ulType);
  1474. pImage->ulType = BMP8;
  1475. sRes = BMP8;
  1476. }
  1477. else
  1478. {
  1479. TRACE("ConvFromFlx8_888(): Unable to allocate new buffer.\n");
  1480. }
  1481. // If successful . . .
  1482. if (sRes != NOT_SUPPORTED)
  1483. {
  1484. // Destroy the old palette data.
  1485. CImage::DestroyDetatchedData((void**)&prgbt);
  1486. }
  1487. else
  1488. {
  1489. // Restore the palette data.
  1490. ppal->pData = (UCHAR*)prgbt;
  1491. }
  1492. }
  1493. else
  1494. {
  1495. TRACE("ConvFromFlx8_888(): Palette is not FLX8_888:PFLX.\n");
  1496. }
  1497. }
  1498. else
  1499. {
  1500. TRACE("ConvFromFlx8_888(): No palette!?\n");
  1501. }
  1502. return sRes;
  1503. }
  1504. ///////////////////////////////////////////////////////////////////////////////
  1505. // EOF
  1506. ///////////////////////////////////////////////////////////////////////////////