GLS.Graphics.pas 129 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.Graphics;
  5. (*
  6. Utility class and functions to manipulate a bitmap in OpenGL's default
  7. byte order (GL_RGBA vs TBitmap's GL_BGRA)
  8. Note: TGLBitmap32 = TGLImage has support for Alex Denissov's Graphics32 library
  9. (http://www.g32.org), just make sure the USE_GRAPHICS32 conditionnal
  10. is active in GLScene.inc and recompile.
  11. *)
  12. interface
  13. {$I Stage.Defines.inc}
  14. uses
  15. Winapi.OpenGL,
  16. Winapi.OpenGLext,
  17. Winapi.Windows,
  18. System.Classes,
  19. System.SysUtils,
  20. System.SyncObjs,
  21. System.Math,
  22. VCL.Graphics,
  23. VCL.Imaging.Pngimage,
  24. VCL.Consts,
  25. {$IFDEF USE_GRAPHICS32} GR32, {$ENDIF}
  26. Stage.OpenGLTokens,
  27. Stage.VectorTypes,
  28. Stage.TextureFormat,
  29. Stage.VectorGeometry,
  30. Stage.Strings,
  31. GLS.State,
  32. GLS.ApplicationFileIO,
  33. GLS.PersistentClasses,
  34. GLS.Context,
  35. GLS.ImageUtils,
  36. GLS.Color,
  37. Stage.Utils,
  38. Stage.Logger;
  39. {$DEFINE PRF_HACK_PASSES}
  40. type
  41. TGLPixel24 = packed record
  42. r, g, b: Byte;
  43. end;
  44. PGLPixel24 = ^TGLPixel24;
  45. TGLPixel32 = packed record
  46. r, g, b, a: Byte;
  47. end;
  48. PGLPixel32 = ^TGLPixel32;
  49. TGLPixel32Array = array[0..MaxInt shr 3] of TGLPixel32;
  50. PGLPixel32Array = ^TGLPixel32Array;
  51. TGLLODStreamingState = (ssKeeping, ssLoading, ssLoaded, ssTransfered);
  52. TGLImageLevelDesc = record
  53. Width: Integer;
  54. Height: Integer;
  55. Depth: Integer;
  56. PBO: TGLUnpackPBOHandle;
  57. MapAddress: Pointer;
  58. Offset: LongWord;
  59. StreamOffset: LongWord;
  60. Size: LongWord;
  61. State: TGLLODStreamingState;
  62. end;
  63. TGLImageLODRange = 0..15;
  64. TGLImagePiramid = array[TGLImageLODRange] of TGLImageLevelDesc;
  65. TGLBaseImage = class(TGLDataFile)
  66. private
  67. FSourceStream: TStream;
  68. FStreamLevel: TGLImageLODRange;
  69. FFinishEvent: TFinishTaskEvent;
  70. {$IFDEF USE_SERVICE_CONTEXT}
  71. procedure ImageStreamingTask; stdcall;
  72. {$ENDIF}
  73. protected
  74. fData: PGLPixel32Array;
  75. FLOD: TGLImagePiramid;
  76. fLevelCount: TGLImageLODRange;
  77. fColorFormat: Cardinal;
  78. fInternalFormat: TGLInternalFormat;
  79. fDataType: Cardinal;
  80. fElementSize: Integer;
  81. fCubeMap: Boolean;
  82. fTextureArray: Boolean;
  83. function GetData: PGLPixel32Array; virtual;
  84. function GetWidth: Integer;
  85. function GetHeight: Integer;
  86. function GetDepth: Integer;
  87. function GetLevelAddress(ALevel: Byte): Pointer; overload;
  88. function GetLevelAddress(ALevel, AFace: Byte): Pointer; overload;
  89. function GetLevelWidth(ALOD: TGLImageLODRange): Integer;
  90. function GetLevelHeight(ALOD: TGLImageLODRange): Integer;
  91. function GetLevelDepth(ALOD: TGLImageLODRange): Integer;
  92. function GetLevelPBO(ALOD: TGLImageLODRange): TGLUnpackPBOHandle;
  93. function GetLevelOffset(ALOD: TGLImageLODRange): Integer;
  94. function GetLevelSizeInByte(ALOD: TGLImageLODRange): Integer;
  95. function GetLevelStreamingState(ALOD: TGLImageLODRange): TGLLODStreamingState;
  96. procedure SetLevelStreamingState(ALOD: TGLImageLODRange; AState: TGLLODStreamingState);
  97. procedure SaveHeader;
  98. procedure LoadHeader;
  99. procedure StartStreaming;
  100. procedure DoStreaming;
  101. public
  102. constructor Create; reintroduce; virtual;
  103. destructor Destroy; override;
  104. procedure Assign(Source: TPersistent); override;
  105. function GetTextureTarget: TGLTextureTarget;
  106. // Registers the bitmap's content as an OpenGL texture map.
  107. procedure RegisterAsOpenGLTexture(
  108. AHandle: TGLTextureHandle;
  109. aMipmapGen: Boolean;
  110. aTexFormat: Cardinal;
  111. out texWidth: integer;
  112. out texHeight: integer;
  113. out texDepth: integer); virtual;
  114. // Assigns from any Texture.
  115. function AssignFromTexture(
  116. AHandle: TGLTextureHandle;
  117. const CastToFormat: Boolean;
  118. const intFormat: TGLInternalFormat = tfRGBA8;
  119. const colorFormat: Cardinal = 0;
  120. const dataType: Cardinal = 0): Boolean; virtual;
  121. (* Convert vertical cross format of non compressed, non mipmaped image
  122. to six face of cube map *)
  123. function ConvertCrossToCubeMap: Boolean;
  124. // Convert flat image to volume by dividing it into slice.
  125. function ConvertToVolume(const col, row: Integer; const MakeArray: Boolean): Boolean;
  126. // Return size in byte of all image
  127. function DataSize: Cardinal;
  128. //True if the bitmap is empty (ie. width or height is zero).
  129. function IsEmpty: Boolean;
  130. function IsCompressed: Boolean;
  131. function IsVolume: Boolean;
  132. //Narrow image data to simple RGBA8 ubyte
  133. procedure Narrow;
  134. //Generate LOD pyramid
  135. procedure GenerateMipmap(AFilter: TImageFilterFunction); virtual;
  136. // Leave top level and remove other
  137. procedure UnMipmap; virtual;
  138. // Direct Access to image data
  139. property Data: PGLPixel32Array read GetData;
  140. // Set image of error.
  141. procedure SetErrorImage;
  142. // Recalculate levels information based on first level.
  143. procedure UpdateLevelsInfo;
  144. property LevelWidth[ALOD: TGLImageLODRange]: Integer read GetLevelWidth;
  145. property LevelHeight[ALOD: TGLImageLODRange]: Integer read GetLevelHeight;
  146. property LevelDepth[ALOD: TGLImageLODRange]: Integer read GetLevelDepth;
  147. property LevelPixelBuffer[ALOD: TGLImageLODRange]: TGLUnpackPBOHandle
  148. read GetLevelPBO;
  149. // LOD offset in byte
  150. property LevelOffset[ALOD: TGLImageLODRange]: Integer read GetLevelOffset;
  151. // LOD size in byte
  152. property LevelSizeInByte[ALOD: TGLImageLODRange]: Integer
  153. read GetLevelSizeInByte;
  154. property LevelStreamingState[ALOD: TGLImageLODRange]: TGLLODStreamingState
  155. read GetLevelStreamingState write SetLevelStreamingState;
  156. // Number of levels.
  157. property LevelCount: TGLImageLODRange read fLevelCount;
  158. property InternalFormat: TGLInternalFormat read FInternalFormat;
  159. property ColorFormat: Cardinal read fColorFormat;
  160. property DataType: Cardinal read fDataType;
  161. property ElementSize: Integer read fElementSize;
  162. property CubeMap: Boolean read fCubeMap;
  163. property TextureArray: Boolean read fTextureArray;
  164. end;
  165. TGLBaseImageClass = class of TGLBaseImage;
  166. (* Contains and manipulates a 32 bits (24+8) bitmap.
  167. This is the base class for preparing and manipulating textures in GLS.Scene,
  168. this function does not rely on a windows handle and should be used for
  169. in-memory manipulations only.
  170. 16 bits textures are automatically converted to 24 bits and an opaque (255)
  171. alpha channel is assumed for all planes, the byte order is as specified
  172. in GL_RGBA. If 32 bits is used in this class, it can however output 16 bits texture
  173. data for use in OpenGL.
  174. The class has support for registering its content as a texture, as well
  175. as for directly drawing/reading from the current OpenGL buffer. *)
  176. TGLImage = class(TGLBaseImage)
  177. private
  178. FVerticalReverseOnAssignFromBitmap: Boolean;
  179. FBlank: Boolean;
  180. fOldColorFormat: Cardinal;
  181. fOldDataType: Cardinal;
  182. procedure DataConvertTask;
  183. protected
  184. procedure SetWidth(val: Integer);
  185. procedure SetHeight(const val: Integer);
  186. procedure SetDepth(const val: Integer);
  187. procedure SetBlank(const Value: Boolean);
  188. procedure SetCubeMap(const val: Boolean);
  189. procedure SetArray(const val: Boolean);
  190. function GetScanLine(index: Integer): PGLPixel32Array;
  191. procedure AssignFrom24BitsBitmap(aBitmap: TBitmap);
  192. procedure AssignFrom32BitsBitmap(aBitmap: TBitmap);
  193. {$IFDEF USE_GRAPHICS32}
  194. procedure AssignFromBitmap32(aBitmap32: TBitmap32);
  195. {$ENDIF}
  196. procedure AssignFromPngImage(aPngImage: TPngImage);
  197. public
  198. constructor Create; override;
  199. destructor Destroy; override;
  200. // Accepts TGLImage and TGraphic subclasses.
  201. procedure Assign(Source: TPersistent); override;
  202. (* Assigns from a 24 bits bitmap without swapping RGB.
  203. This is faster than a regular assignment, but R and B channels
  204. will be reversed (from what you would view in a TImage). Suitable
  205. if you do your own drawing and reverse RGB on the drawing side.
  206. If you're after speed, don't forget to set the bitmap's dimensions
  207. to a power of two! *)
  208. procedure AssignFromBitmap24WithoutRGBSwap(aBitmap: TBitmap);
  209. (* Assigns from a 2D Texture.
  210. The context which holds the texture must be active and the texture
  211. handle valid. *)
  212. procedure AssignFromTexture2D(textureHandle: Cardinal); overload;
  213. (*Assigns from a Texture handle.
  214. If the handle is invalid, the bitmap32 will be empty. *)
  215. procedure AssignFromTexture2D(textureHandle: TGLTextureHandle); overload;
  216. // Create a 32 bits TBitmap from self content.
  217. function Create32BitsBitmap: TBitmap;
  218. // Width of the bitmap.
  219. property Width: Integer read GetWidth write SetWidth;
  220. // Height of the bitmap.
  221. property Height: Integer read GetHeight write SetHeight;
  222. // Depth of the bitmap.
  223. property Depth: Integer read GetDepth write SetDepth;
  224. // OpenGL color format
  225. property ColorFormat: Cardinal read fColorFormat;
  226. // Recommended texture internal format
  227. property InternalFormat: TGLInternalFormat read FInternalFormat write
  228. FInternalFormat;
  229. // OpenGL data type
  230. property DataType: Cardinal read fDataType;
  231. // Size in bytes of pixel or block
  232. property ElementSize: Integer read fElementSize;
  233. property CubeMap: Boolean read fCubeMap write SetCubeMap;
  234. property TextureArray: Boolean read fTextureArray write SetArray;
  235. (* Access to a specific Bitmap ScanLine. index should be in the [0; Height[ range.
  236. Warning : this function is NOT protected against invalid indexes,
  237. and invoking it is invalid if the bitmap is Empty. *)
  238. property ScanLine[index: Integer]: PGLPixel32Array read GetScanLine;
  239. property VerticalReverseOnAssignFromBitmap: Boolean read
  240. FVerticalReverseOnAssignFromBitmap write
  241. FVerticalReverseOnAssignFromBitmap;
  242. (* Set Blank to true if you actually don't need to allocate data in main menory.
  243. Useful for textures that are generated by the GPU on the fly. *)
  244. property Blank: boolean read FBlank write SetBlank;
  245. // Recast image OpenGL data type and color format.
  246. procedure SetColorFormatDataType(const AColorFormat, ADataType: Cardinal);
  247. (* Set Alpha channel values to the pixel intensity.
  248. The intensity is calculated as the mean of RGB components. *)
  249. procedure SetAlphaFromIntensity;
  250. (* Set Alpha channel to 0 for pixels of given color, 255 for others).
  251. This makes pixels of given color totally transparent while the others
  252. are completely opaque. *)
  253. procedure SetAlphaTransparentForColor(const aColor: TColor); overload;
  254. procedure SetAlphaTransparentForColor(const aColor: TGLPixel32); overload;
  255. procedure SetAlphaTransparentForColor(const aColor: TGLPixel24); overload;
  256. // Set Alpha channel values to given byte value.
  257. procedure SetAlphaToValue(const aValue: Byte);
  258. // Set Alpha channel values to given float [0..1] value.
  259. procedure SetAlphaToFloatValue(const aValue: Single);
  260. (* Inverts the AlphaChannel component.
  261. What was transparent becomes opaque and vice-versa. *)
  262. procedure InvertAlpha;
  263. // AlphaChannel components are replaced by their sqrt.
  264. procedure SqrtAlpha;
  265. // Apply a brightness (scaled saturating) correction to the RGB components.
  266. procedure BrightnessCorrection(const factor: Single);
  267. // Apply a gamma correction to the RGB components.
  268. procedure GammaCorrection(const gamma: Single);
  269. (* Downsample the bitmap by a factor of 2 in both dimensions.
  270. If one of the dimensions is 1 or less, does nothing. *)
  271. procedure DownSampleByFactor2;
  272. (* Reads the given area from the current active OpenGL rendering context.
  273. The best spot for reading pixels is within a SceneViewer's PostRender
  274. event : the scene has been fully rendered and the OpenGL context
  275. is still active. *)
  276. procedure ReadPixels(const area: TRect);
  277. (* Draws the whole bitmap at given position in the current OpenGL context.
  278. This function must be called with a rendering context active.
  279. Blending and Alpha channel functions are not altered by this function
  280. and must be adjusted separately. *)
  281. procedure DrawPixels(const x, y: Single);
  282. (* Converts a grayscale 'elevation' bitmap to normal map.
  283. Actually, only the Green component in the original bitmap is used. *)
  284. procedure GrayScaleToNormalMap(const scale: Single;
  285. wrapX: Boolean = True; wrapY: Boolean = True);
  286. // Assumes the bitmap content is a normal map and normalizes all pixels.
  287. procedure NormalizeNormalMap;
  288. // Converts a TImage back into a TBitmap
  289. procedure AssignToBitmap(aBitmap: TBitmap);
  290. // Generate level of detail.
  291. procedure GenerateMipmap(AFilter: TImageFilterFunction); override;
  292. // Clear all levels except first.
  293. procedure UnMipmap; override;
  294. end;
  295. TGLBitmap32 = TGLImage;
  296. TGLRasterFileFormat = class
  297. public
  298. BaseImageClass: TGLBaseImageClass;
  299. Extension: string;
  300. Description: string;
  301. DescResID: Integer;
  302. end;
  303. // Stores registered raster file formats.
  304. TGLRasterFileFormatsList = class(TGLPersistentObjectList)
  305. public
  306. destructor Destroy; override;
  307. procedure Add(const Ext, Desc: string; DescID: Integer; AClass:
  308. TGLBaseImageClass);
  309. function FindExt(ext: string): TGLBaseImageClass;
  310. function FindFromFileName(const fileName: string): TGLBaseImageClass;
  311. function FindFromStream(const AStream: TStream): TGLBaseImageClass;
  312. procedure Remove(AClass: TGLBaseImageClass);
  313. procedure BuildFilterStrings(imageFileClass: TGLBaseImageClass;
  314. var descriptions, filters: string;
  315. formatsThatCanBeOpened: Boolean = True;
  316. formatsThatCanBeSaved: Boolean = False);
  317. function FindExtByIndex(index: Integer;
  318. formatsThatCanBeOpened: Boolean = True;
  319. formatsThatCanBeSaved: Boolean = False): string;
  320. end;
  321. EInvalidRasterFile = class(Exception);
  322. procedure Div2(var Value: Integer);
  323. procedure BGR24ToRGB24(src, dest: Pointer; pixelCount: Integer);
  324. procedure BGR24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  325. procedure RGB24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  326. procedure BGRA32ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  327. procedure GammaCorrectRGBArray(base: Pointer; pixelCount: Integer; gamma: Single);
  328. procedure BrightenRGBArray(base: Pointer; pixelCount: Integer; factor: Single);
  329. // Read access to the list of registered vector file formats
  330. function GetRasterFileFormats: TGLRasterFileFormatsList;
  331. (* Returns an extension by its index
  332. in the internal image files dialogs filter.
  333. Use InternalImageFileFormatsFilter to obtain the filter. *)
  334. function RasterFileFormatExtensionByIndex(index: Integer): string;
  335. procedure RegisterRasterFormat(const AExtension, ADescription: string;
  336. AClass: TGLBaseImageClass);
  337. procedure UnregisterRasterFormat(AClass: TGLBaseImageClass);
  338. // Return an optimal number of texture pyramid
  339. function GetImageLodNumber(w, h, d: Integer; IsVolume: Boolean): Integer;
  340. (* Returns the TGraphicClass associated to the extension, if any.
  341. Accepts anExtension with or without the '.' *)
  342. function GraphicClassForExtension(const anExtension: string): TGraphicClass;
  343. (* Adds to the passed TStrings the list of registered formats.
  344. Convention is "extension=description" for the string, the Objects hold
  345. the corresponding TGraphicClass (extensions do not include the '.'). *)
  346. procedure HackTPictureRegisteredFormats(destList: TStrings);
  347. var
  348. vVerticalFlipDDS: Boolean = True;
  349. implementation // ------------------------------------------------------------
  350. var
  351. vRasterFileFormats: TGLRasterFileFormatsList;
  352. // ------------------------------ Raster File Registries
  353. function GetRasterFileFormats: TGLRasterFileFormatsList;
  354. begin
  355. if not Assigned(vRasterFileFormats) then
  356. vRasterFileFormats := TGLRasterFileFormatsList.Create;
  357. Result := vRasterFileFormats;
  358. end;
  359. procedure RegisterRasterFormat(const AExtension, ADescription: string;
  360. AClass: TGLBaseImageClass);
  361. begin
  362. RegisterClass(AClass);
  363. GetRasterFileFormats.Add(AExtension, ADescription, 0, AClass);
  364. end;
  365. procedure UnregisterRasterFormat(AClass: TGLBaseImageClass);
  366. begin
  367. if Assigned(vRasterFileFormats) then
  368. vRasterFileFormats.Remove(AClass);
  369. end;
  370. function RasterFileFormatExtensionByIndex(index: Integer): string;
  371. begin
  372. Result := GetRasterFileFormats.FindExtByIndex(index);
  373. end;
  374. destructor TGLRasterFileFormatsList.Destroy;
  375. begin
  376. Clean;
  377. inherited;
  378. end;
  379. procedure TGLRasterFileFormatsList.Add(const Ext, Desc: string; DescID: Integer;
  380. AClass: TGLBaseImageClass);
  381. var
  382. newRec: TGLRasterFileFormat;
  383. begin
  384. newRec := TGLRasterFileFormat.Create;
  385. with newRec do
  386. begin
  387. Extension := AnsiLowerCase(Ext);
  388. BaseImageClass := AClass;
  389. Description := Desc;
  390. DescResID := DescID;
  391. end;
  392. inherited Add(newRec);
  393. end;
  394. function TGLRasterFileFormatsList.FindExt(Ext: string): TGLBaseImageClass;
  395. var
  396. i: Integer;
  397. begin
  398. Ext := AnsiLowerCase(Ext);
  399. for i := Count - 1 downto 0 do
  400. with TGLRasterFileFormat(Items[i]) do
  401. begin
  402. if Extension = Ext then
  403. begin
  404. Result := BaseImageClass;
  405. Exit;
  406. end;
  407. end;
  408. Result := nil;
  409. end;
  410. function TGLRasterFileFormatsList.FindFromFileName(const fileName: string):
  411. TGLBaseImageClass;
  412. var
  413. Ext: string;
  414. begin
  415. Ext := ExtractFileExt(FileName);
  416. System.Delete(Ext, 1, 1);
  417. Result := FindExt(Ext);
  418. if not Assigned(Result) then
  419. raise EInvalidRasterFile.CreateFmt(strUnknownExtension,
  420. [Ext, 'GLFile' + UpperCase(Ext)]);
  421. end;
  422. function TGLRasterFileFormatsList.FindFromStream(const AStream: TStream): TGLBaseImageClass;
  423. var
  424. Ext: string;
  425. magic: array [0 .. 1] of LongWord;
  426. begin
  427. magic[0] := 0;
  428. magic[1] := 1;
  429. AStream.ReadBuffer(magic, 2 * SizeOf(LongWord));
  430. AStream.Seek(-2 * SizeOf(LongWord), 1);
  431. if magic[0] = $20534444 then
  432. Ext := 'DDS'
  433. else if magic[1] = $4354334F then
  434. Ext := 'O3TC'
  435. else if (magic[0] and $0000FFFF) = $00003F23 then
  436. Ext := 'HDR'
  437. else if (magic[0] = $474E5089) and (magic[1] = $0A1A0A0D) then
  438. Ext := 'PNG'
  439. else if (magic[0] = $E0FFD8FF) and (magic[1] = $464A1000) then
  440. Ext := 'JPG';
  441. Result := FindExt(Ext);
  442. if not Assigned(Result) then
  443. raise EInvalidRasterFile.CreateFmt(strUnknownExtension,
  444. [Ext, 'GLFile' + UpperCase(Ext)]);
  445. end;
  446. procedure TGLRasterFileFormatsList.Remove(AClass: TGLBaseImageClass);
  447. var
  448. i: Integer;
  449. begin
  450. for i := Count - 1 downto 0 do
  451. begin
  452. if TGLRasterFileFormat(Items[i]).BaseImageClass.InheritsFrom(AClass) then
  453. DeleteAndFree(i);
  454. end;
  455. end;
  456. procedure TGLRasterFileFormatsList.BuildFilterStrings(
  457. imageFileClass: TGLBaseImageClass;
  458. var descriptions, filters: string;
  459. formatsThatCanBeOpened: Boolean = True;
  460. formatsThatCanBeSaved: Boolean = False);
  461. var
  462. k, i: Integer;
  463. p: TGLRasterFileFormat;
  464. begin
  465. descriptions := '';
  466. filters := '';
  467. k := 0;
  468. for i := 0 to Count - 1 do
  469. begin
  470. p := TGLRasterFileFormat(Items[i]);
  471. if p.BaseImageClass.InheritsFrom(imageFileClass) and (p.Extension <> '')
  472. and ((formatsThatCanBeOpened and (dfcRead in
  473. p.BaseImageClass.Capabilities))
  474. or (formatsThatCanBeSaved and (dfcWrite in p.BaseImageClass.Capabilities))) then
  475. begin
  476. with p do
  477. begin
  478. if k <> 0 then
  479. begin
  480. descriptions := descriptions + '|';
  481. filters := filters + ';';
  482. end;
  483. if (Description = '') and (DescResID <> 0) then
  484. Description := LoadStr(DescResID);
  485. FmtStr(descriptions, '%s%s (*.%s)|*.%2:s', [descriptions, Description,
  486. Extension]);
  487. filters := filters + '*.' + Extension;
  488. Inc(k);
  489. end;
  490. end;
  491. end;
  492. if (k > 1) and (not formatsThatCanBeSaved) then
  493. FmtStr(descriptions, '%s (%s)|%1:s|%s',
  494. [sAllFilter, filters, descriptions]);
  495. end;
  496. function TGLRasterFileFormatsList.FindExtByIndex(index: Integer;
  497. formatsThatCanBeOpened: Boolean = True;
  498. formatsThatCanBeSaved: Boolean = False): string;
  499. var
  500. i: Integer;
  501. p: TGLRasterFileFormat;
  502. begin
  503. Result := '';
  504. if index > 0 then
  505. begin
  506. for i := 0 to Count - 1 do
  507. begin
  508. p := TGLRasterFileFormat(Items[i]);
  509. if (formatsThatCanBeOpened and (dfcRead in p.BaseImageClass.Capabilities))
  510. or (formatsThatCanBeSaved and (dfcWrite in
  511. p.BaseImageClass.Capabilities)) then
  512. begin
  513. if index = 1 then
  514. begin
  515. Result := p.Extension;
  516. Break;
  517. end
  518. else
  519. Dec(index);
  520. end;
  521. end;
  522. end;
  523. end;
  524. procedure Div2(var Value: Integer);
  525. begin
  526. Value := Value div 2;
  527. if Value = 0 then
  528. Inc(Value);
  529. end;
  530. function GetImageLodNumber(w, h, d: integer; IsVolume: Boolean): Integer;
  531. var
  532. L: Integer;
  533. begin
  534. L := 1;
  535. d := MaxInteger(d, 1);
  536. while ((w > 1) or (h > 1) or (d > 1)) do
  537. begin
  538. Div2(w);
  539. Div2(h);
  540. if IsVolume then
  541. Div2(d);
  542. Inc(L);
  543. end;
  544. Result := L;
  545. end;
  546. procedure CalcImagePiramid(var APiramid: TGLImagePiramid);
  547. begin
  548. //
  549. end;
  550. // -------------------- RGBA Utils
  551. procedure GammaCorrectRGBArray(base: Pointer; pixelCount: Integer;
  552. gamma: Single);
  553. var
  554. vGammaLUT: array[0..255] of Byte;
  555. invGamma: Single;
  556. i: Integer;
  557. ptr: PByte;
  558. begin
  559. if pixelCount < 1 then
  560. Exit;
  561. Assert(gamma > 0);
  562. // build LUT
  563. if gamma < 0.1 then
  564. invGamma := 10
  565. else
  566. invGamma := 1 / gamma;
  567. for i := 0 to 255 do
  568. vGammaLUT[i] := Round(255 * Power(i * (1 / 255), InvGamma));
  569. // perform correction
  570. ptr := base;
  571. for i := 0 to pixelCount * 3 - 1 do
  572. begin
  573. ptr^ := vGammaLUT[ptr^];
  574. Inc(ptr);
  575. end;
  576. end;
  577. procedure GammaCorrectRGBAArray(base: Pointer; pixelCount: Integer;
  578. gamma: Single);
  579. var
  580. vGammaLUT: array [0 .. 255] of Byte;
  581. pLUT: PByteArray;
  582. invGamma: Single;
  583. i: Integer;
  584. ptr: PByte;
  585. begin
  586. if pixelCount < 1 then
  587. Exit;
  588. Assert(gamma > 0);
  589. // build LUT
  590. if gamma < 0.1 then
  591. invGamma := 10
  592. else
  593. invGamma := 1 / gamma;
  594. for i := 0 to 255 do
  595. vGammaLUT[i] := Round(255 * Power(i * (1 / 255), invGamma));
  596. // perform correction
  597. ptr := base;
  598. pLUT := @vGammaLUT[0];
  599. for i := 0 to pixelCount - 1 do
  600. begin
  601. ptr^ := pLUT^[ptr^];
  602. Inc(ptr);
  603. ptr^ := pLUT^[ptr^];
  604. Inc(ptr);
  605. ptr^ := pLUT^[ptr^];
  606. Inc(ptr, 2);
  607. end;
  608. end;
  609. procedure BrightenRGBArray(base: Pointer; pixelCount: Integer; factor: Single);
  610. var
  611. vBrightnessLUT: array[0..255] of Byte;
  612. i, k: Integer;
  613. ptr: PByte;
  614. begin
  615. if pixelCount < 1 then
  616. Exit;
  617. Assert(factor >= 0);
  618. // build LUT
  619. for i := 0 to 255 do
  620. begin
  621. k := Round(factor * i);
  622. if k > 255 then
  623. k := 255;
  624. vBrightnessLUT[i] := Byte(k);
  625. end;
  626. // perform correction
  627. ptr := base;
  628. for i := 0 to pixelCount * 3 - 1 do
  629. begin
  630. ptr^ := vBrightnessLUT[ptr^];
  631. Inc(ptr);
  632. end;
  633. end;
  634. procedure BrightenRGBAArray(base: Pointer; pixelCount: Integer; factor: Single);
  635. var
  636. vBrightnessLUT: array[0..255] of Byte;
  637. pLUT: PByteArray;
  638. i: Integer;
  639. ptr: PByte;
  640. k: Integer;
  641. begin
  642. if pixelCount < 1 then
  643. Exit;
  644. Assert(factor >= 0);
  645. // build LUT
  646. for i := 0 to 255 do
  647. begin
  648. k := Round(factor * i);
  649. if k > 255 then
  650. k := 255;
  651. vBrightnessLUT[i] := k;
  652. end;
  653. // perform correction
  654. ptr := base;
  655. pLUT := @vBrightnessLUT[0];
  656. for i := 0 to pixelCount - 1 do
  657. begin
  658. ptr^ := pLUT^[ptr^];
  659. Inc(ptr);
  660. ptr^ := pLUT^[ptr^];
  661. Inc(ptr);
  662. ptr^ := pLUT^[ptr^];
  663. Inc(ptr, 2);
  664. end;
  665. end;
  666. procedure BGR24ToRGB24(src, dest: Pointer; pixelCount: Integer); register;
  667. begin
  668. while pixelCount > 0 do
  669. begin
  670. PAnsiChar(dest)[0] := PAnsiChar(src)[2];
  671. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  672. PAnsiChar(dest)[2] := PAnsiChar(src)[0];
  673. Inc(PAnsiChar(dest), 3);
  674. Inc(PAnsiChar(src), 3);
  675. Dec(pixelCount);
  676. end;
  677. end;
  678. procedure BGR24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  679. begin
  680. while pixelCount > 0 do
  681. begin
  682. PAnsiChar(dest)[0] := PAnsiChar(src)[2];
  683. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  684. PAnsiChar(dest)[2] := PAnsiChar(src)[0];
  685. PAnsiChar(dest)[3] := #255;
  686. Inc(PAnsiChar(dest), 4);
  687. Inc(PAnsiChar(src), 3);
  688. Dec(pixelCount);
  689. end;
  690. end;
  691. procedure RGB24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  692. begin
  693. while pixelCount > 0 do
  694. begin
  695. PAnsiChar(dest)[0] := PAnsiChar(src)[0];
  696. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  697. PAnsiChar(dest)[2] := PAnsiChar(src)[2];
  698. PAnsiChar(dest)[3] := #255;
  699. Inc(PAnsiChar(dest), 4);
  700. Inc(PAnsiChar(src), 3);
  701. Dec(pixelCount);
  702. end;
  703. end;
  704. procedure BGRA32ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  705. begin
  706. while pixelCount > 0 do
  707. begin
  708. PAnsiChar(dest)[0] := PAnsiChar(src)[2];
  709. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  710. PAnsiChar(dest)[2] := PAnsiChar(src)[0];
  711. PAnsiChar(dest)[3] := PAnsiChar(src)[3];
  712. Inc(PAnsiChar(dest), 4);
  713. Inc(PAnsiChar(src), 4);
  714. Dec(pixelCount);
  715. end;
  716. end;
  717. // ------------------
  718. // ------------------ TGLBaseImage ------------------
  719. // ------------------
  720. constructor TGLBaseImage.Create;
  721. begin
  722. inherited Create(Self);
  723. FillChar(FLOD, SizeOf(TGLImagePiramid), $00);
  724. fLevelCount := 1; // first level always is present
  725. fColorFormat := GL_RGBA;
  726. fInternalFormat := tfRGBA8;
  727. fDataType := GL_UNSIGNED_BYTE;
  728. fElementSize := 4;
  729. fCubeMap := False;
  730. fTextureArray := False;
  731. end;
  732. destructor TGLBaseImage.Destroy;
  733. var
  734. level: TGLImageLODRange;
  735. begin
  736. if Assigned(fData) then
  737. begin
  738. FreeMem(fData);
  739. fData := nil;
  740. end;
  741. FreeAndNil(FFinishEvent);
  742. for level := 0 to High(TGLImageLODRange) do
  743. begin
  744. FLOD[level].PBO.Free;
  745. end;
  746. FSourceStream.Free;
  747. inherited Destroy;
  748. end;
  749. procedure TGLBaseImage.Assign(Source: TPersistent);
  750. var
  751. img: TGLBaseImage;
  752. Size: Integer;
  753. begin
  754. if Source is TGLBaseImage then
  755. begin
  756. img := Source as TGLBaseImage;
  757. FLOD := img.FLOD;
  758. fLevelCount := img.fLevelCount;
  759. fColorFormat := img.fColorFormat;
  760. fInternalFormat := img.fInternalFormat;
  761. fDataType := img.fDataType;
  762. fElementSize := img.fElementSize;
  763. fCubeMap := img.fCubeMap;
  764. fTextureArray := img.fTextureArray;
  765. Size := img.DataSize;
  766. ReallocMem(fData, Size);
  767. Move(img.fData^, fData^, Size);
  768. end
  769. else if Source <> nil then
  770. inherited; // raise AssingError
  771. end;
  772. function TGLBaseImage.GetTextureTarget: TGLTextureTarget;
  773. begin
  774. Result := ttTexture2D;
  775. // Choose a texture target
  776. if GetHeight = 1 then
  777. Result := ttTexture1D;
  778. if fCubeMap then
  779. Result := ttTextureCube;
  780. if IsVolume then
  781. Result := ttTexture3D;
  782. if fTextureArray then
  783. begin
  784. if (GetDepth < 2) then
  785. Result := ttTexture1Darray
  786. else
  787. Result := ttTexture2DArray;
  788. if fCubeMap then
  789. Result := ttTextureCubeArray;
  790. end;
  791. if ((FInternalFormat >= tfFLOAT_R16)
  792. and (FInternalFormat <= tfFLOAT_RGBA32)) then
  793. Result := ttTextureRect;
  794. end;
  795. function TGLBaseImage.DataSize: Cardinal;
  796. var
  797. L: TGLImageLODRange;
  798. s: Cardinal;
  799. begin
  800. s := 0;
  801. if not IsEmpty then
  802. begin
  803. UpdateLevelsInfo;
  804. for l := 0 to FLevelCount - 1 do
  805. s := s + FLOD[l].Size;
  806. end;
  807. Result := s;
  808. end;
  809. function TGLBaseImage.GetWidth: Integer;
  810. begin
  811. Result := FLOD[0].Width;
  812. end;
  813. function TGLBaseImage.GetDepth: Integer;
  814. begin
  815. Result := FLOD[0].Depth;
  816. end;
  817. function TGLBaseImage.GetHeight: Integer;
  818. begin
  819. Result := FLOD[0].Height;
  820. end;
  821. function TGLBaseImage.GetLevelAddress(ALevel: Byte): Pointer;
  822. begin
  823. Result := fData;
  824. Inc(PByte(Result), FLOD[ALevel].Offset);
  825. end;
  826. function TGLBaseImage.GetLevelAddress(ALevel, AFace: Byte): Pointer;
  827. begin
  828. Result := fData;
  829. Inc(PByte(Result), FLOD[ALevel].Offset);
  830. Inc(PByte(Result), AFace * (FLOD[ALevel].Size div 6));
  831. end;
  832. function TGLBaseImage.GetLevelDepth(ALOD: TGLImageLODRange): Integer;
  833. begin
  834. Result := FLOD[ALOD].Depth;
  835. end;
  836. function TGLBaseImage.GetLevelHeight(ALOD: TGLImageLODRange): Integer;
  837. begin
  838. Result := FLOD[ALOD].Height;
  839. end;
  840. function TGLBaseImage.GetLevelOffset(ALOD: TGLImageLODRange): Integer;
  841. begin
  842. Result := FLOD[ALOD].Offset;
  843. end;
  844. function TGLBaseImage.GetLevelPBO(ALOD: TGLImageLODRange): TGLUnpackPBOHandle;
  845. begin
  846. Result := FLOD[ALOD].PBO;
  847. end;
  848. function TGLBaseImage.GetLevelSizeInByte(ALOD: TGLImageLODRange): Integer;
  849. begin
  850. Result := FLOD[ALOD].Size;
  851. end;
  852. function TGLBaseImage.GetLevelStreamingState(ALOD: TGLImageLODRange): TGLLODStreamingState;
  853. begin
  854. Result := FLOD[ALOD].State;
  855. end;
  856. function TGLBaseImage.GetLevelWidth(ALOD: TGLImageLODRange): Integer;
  857. begin
  858. Result := FLOD[ALOD].Width;
  859. end;
  860. function TGLBaseImage.IsEmpty: Boolean;
  861. begin
  862. Result := (GetWidth = 0) or (GetHeight = 0);
  863. end;
  864. function TGLBaseImage.IsCompressed: Boolean;
  865. begin
  866. Result := IsCompressedFormat(fInternalFormat);
  867. end;
  868. function TGLBaseImage.IsVolume: Boolean;
  869. begin
  870. Result := (GetDepth > 0) and not fTextureArray and not fCubeMap;
  871. end;
  872. function TGLBaseImage.ConvertCrossToCubeMap: Boolean;
  873. var
  874. fW, fH, cubeSize, realCubeSize, e: Integer;
  875. lData: PByteArray;
  876. ptr: PGLubyte;
  877. i, j: Integer;
  878. bGenMipmap: Boolean;
  879. begin
  880. Result := False;
  881. // Can't already be a cubemap
  882. if fCubeMap or fTextureArray then
  883. Exit;
  884. //this function only supports vertical cross format for now (3 wide by 4 high)
  885. if (GetWidth div 3 <> GetHeight div 4)
  886. or (GetWidth mod 3 <> 0)
  887. or (GetHeight mod 4 <> 0)
  888. or (GetDepth > 0) then
  889. Exit;
  890. bGenMipmap := FLevelCount > 1;
  891. UnMipmap;
  892. // Get the source data
  893. lData := PByteArray(fData);
  894. if IsCompressed then
  895. begin
  896. fW := (GetWidth + 3) div 4;
  897. fH := (GetHeight + 3) div 4;
  898. realCubeSize := (fH div 4) * 4;
  899. end
  900. else
  901. begin
  902. fW := GetWidth;
  903. fH := GetHeight;
  904. realCubeSize := fH div 4;
  905. end;
  906. cubeSize := fH;
  907. GetMem(fData, fW * fH * fElementSize);
  908. FLOD[0].Width := realCubeSize;
  909. FLOD[0].Height := realCubeSize;
  910. FLOD[0].Depth := 6;
  911. // Extract the faces
  912. ptr := PGLubyte(fData);
  913. // positive X
  914. for j := 0 to cubeSize - 1 do
  915. begin
  916. e := ((fH - (cubeSize + j + 1)) * fW + 2 * cubeSize) * fElementSize;
  917. Move(lData[e], ptr^, cubeSize * fElementSize);
  918. Inc(ptr, cubeSize * fElementSize);
  919. end;
  920. // negative X
  921. for j := 0 to cubeSize - 1 do
  922. begin
  923. Move(lData[(fH - (cubeSize + j + 1)) * fW * fElementSize],
  924. ptr^, cubeSize * fElementSize);
  925. Inc(ptr, cubeSize * fElementSize);
  926. end;
  927. // positive Y
  928. for j := 0 to cubeSize - 1 do
  929. begin
  930. e := ((4 * cubeSize - j - 1) * fW + cubeSize) * fElementSize;
  931. Move(lData[e], ptr^, cubeSize * fElementSize);
  932. Inc(ptr, cubeSize * fElementSize);
  933. end;
  934. // negative Y
  935. for j := 0 to cubeSize - 1 do
  936. begin
  937. e := ((2 * cubeSize - j - 1) * fW + cubeSize) * fElementSize;
  938. Move(lData[e], ptr^, cubeSize * fElementSize);
  939. Inc(ptr, cubeSize * fElementSize);
  940. end;
  941. // positive Z
  942. for j := 0 to cubeSize - 1 do
  943. begin
  944. e := ((fH - (cubeSize + j + 1)) * fW + cubeSize) * fElementSize;
  945. Move(lData[e], ptr^, cubeSize * fElementSize);
  946. Inc(ptr, cubeSize * fElementSize);
  947. end;
  948. // negative Z
  949. for j := 0 to cubeSize - 1 do
  950. for i := 0 to cubeSize - 1 do
  951. begin
  952. e := (j * fW + 2 * cubeSize - (i + 1)) * fElementSize;
  953. Move(lData[e], ptr^, fElementSize);
  954. Inc(ptr, fElementSize);
  955. end;
  956. // Set the new # of faces, width and height
  957. fCubeMap := true;
  958. FreeMem(lData);
  959. if bGenMipmap then
  960. GenerateMipmap(ImageTriangleFilter);
  961. Result := true;
  962. end;
  963. function TGLBaseImage.ConvertToVolume(const col, row: Integer; const MakeArray:
  964. Boolean): Boolean;
  965. var
  966. fW, fH, sW, sH, sD: Integer;
  967. lData: PByteArray;
  968. ptr: PGLubyte;
  969. i, j, k: Integer;
  970. begin
  971. Result := false;
  972. if fCubeMap then
  973. Exit;
  974. if (GetDepth > 0) and not fTextureArray and MakeArray then
  975. begin
  976. // Let volume be array
  977. fTextureArray := True;
  978. Result := True;
  979. Exit;
  980. end;
  981. if fTextureArray and not MakeArray then
  982. begin
  983. // Let array be volume
  984. fTextureArray := False;
  985. Result := True;
  986. Exit;
  987. end;
  988. Result := MakeArray;
  989. // Check sizes
  990. sD := col * row;
  991. if sD < 1 then
  992. Exit;
  993. if IsCompressed then
  994. begin
  995. fW := (GetWidth + 3) div 4;
  996. fH := (GetHeight + 3) div 4;
  997. end
  998. else
  999. begin
  1000. fW := GetWidth;
  1001. fH := GetHeight;
  1002. end;
  1003. sW := fW div col;
  1004. sH := fH div row;
  1005. if (sW = 0) or (sH = 0) then
  1006. begin
  1007. Result := False;
  1008. Exit;
  1009. end;
  1010. // Mipmaps are not supported
  1011. UnMipmap;
  1012. // Get the source data
  1013. lData := PByteArray(fData);
  1014. GetMem(fData, sW * sH * sD * fElementSize);
  1015. ptr := PGLubyte(fData);
  1016. for i := 0 to row - 1 do
  1017. for j := 0 to col - 1 do
  1018. for k := 0 to sH - 1 do
  1019. begin
  1020. Move(lData[(i * fW * sH + j * sW + k * fW) * fElementSize],
  1021. ptr^, sW * fElementSize);
  1022. Inc(ptr, sW * fElementSize);
  1023. end;
  1024. if IsCompressed then
  1025. begin
  1026. FLOD[0].Width := sW * 4;
  1027. FLOD[0].Height := sH * 4;
  1028. end
  1029. else
  1030. begin
  1031. FLOD[0].Width := sW;
  1032. FLOD[0].Height := sH;
  1033. end;
  1034. FLOD[0].Depth := sD;
  1035. fTextureArray := Result;
  1036. FreeMem(lData);
  1037. Result := True;
  1038. end;
  1039. procedure TGLBaseImage.SetErrorImage;
  1040. const
  1041. cTextureError: array[0..12287] of Byte = (
  1042. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1043. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1044. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1045. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1046. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$3A,$00,$00,$FF,$DB,$90,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$90,$DB,$FF,$FF,$B6,$90,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$3A,$00,$00,$FF,$DB,$90,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$90,$DB,$FF,$00,$00,$00,
  1047. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$00,$66,$B6,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1048. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$B6,$FF,$FF,$00,$00,$66,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1049. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$90,$DB,$FF,$FF,$B6,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1050. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1051. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1052. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$3A,$90,$DB,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1053. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$90,$DB,$FF,$00,$00,$3A,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1054. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1055. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$3A,$90,$DB,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1056. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1057. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1058. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1059. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1060. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1061. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1062. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1063. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1064. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1065. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1066. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$DB,$FF,$DB,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1067. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$DB,$FF,$DB,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1068. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1069. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1070. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1071. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1072. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1073. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1074. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1075. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1076. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1077. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1078. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1079. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1080. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1081. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1082. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1083. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1084. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1085. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1086. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1087. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1088. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1089. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1090. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1091. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1092. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1093. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1094. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1095. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1096. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1097. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1098. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1099. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$90,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1100. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1101. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1102. $00,$00,$00,$00,$00,$00,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$90,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1103. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1104. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1105. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  1106. );
  1107. begin
  1108. UnMipmap;
  1109. FLOD[0].Width := 64;
  1110. FLOD[0].Height := 64;
  1111. FLOD[0].Depth := 0;
  1112. fColorFormat := GL_RGBA;
  1113. fInternalFormat := tfRGB8;
  1114. fDataType := GL_UNSIGNED_BYTE;
  1115. fElementSize := 4;
  1116. fCubeMap := false;
  1117. fTextureArray := false;
  1118. FColorFormat := GL_RGB;
  1119. ReallocMem(FData, DataSize);
  1120. Move(cTextureError[0], FData[0], DataSize);
  1121. end;
  1122. procedure TGLBaseImage.SetLevelStreamingState(ALOD: TGLImageLODRange;
  1123. AState: TGLLODStreamingState);
  1124. begin
  1125. FLOD[ALOD].State := AState;
  1126. end;
  1127. procedure TGLBaseImage.Narrow;
  1128. var
  1129. Size: Integer;
  1130. newData: Pointer;
  1131. begin
  1132. // Check for already norrow
  1133. if (fColorFormat = GL_RGBA)
  1134. and (GetDepth = 0)
  1135. and (fDataType = GL_UNSIGNED_BYTE)
  1136. and (FLevelCount = 1)
  1137. and not (fTextureArray or fCubeMap) then
  1138. Exit;
  1139. UnMipmap;
  1140. // Use image utils
  1141. Size := GetWidth * GetHeight * 4;
  1142. GetMem(newData, Size);
  1143. try
  1144. ConvertImage(
  1145. fData, newData,
  1146. fColorFormat, GL_RGBA,
  1147. fDataType, GL_UNSIGNED_BYTE,
  1148. GetWidth, GetHeight);
  1149. except
  1150. GLSLogger.LogError(Format(strCantConvertImg, [ClassName]));
  1151. SetErrorImage;
  1152. FreeMem(newData);
  1153. Exit;
  1154. end;
  1155. fInternalFormat := tfRGBA8;
  1156. fColorFormat := GL_RGBA;
  1157. fDataType := GL_UNSIGNED_BYTE;
  1158. fElementSize := 4;
  1159. fTextureArray := False;
  1160. fCubeMap := False;
  1161. FreeMem(fData);
  1162. fData := newData;
  1163. end;
  1164. procedure TGLBaseImage.GenerateMipmap(AFilter: TImageFilterFunction);
  1165. var
  1166. LAddresses: TPointerArray;
  1167. level, slice, d: Integer;
  1168. begin
  1169. UnMipmap;
  1170. if IsVolume then
  1171. begin
  1172. fLevelCount := GetImageLodNumber(GetWidth, GetHeight, GetDepth, True);
  1173. UpdateLevelsInfo;
  1174. ReallocMem(FData, DataSize);
  1175. // Message Hint 'TGLBaseImage.GenerateMipmap not yet implemented for volume images'
  1176. end
  1177. else
  1178. begin
  1179. fLevelCount := GetImageLodNumber(GetWidth, GetHeight, GetDepth, False);
  1180. ReallocMem(FData, DataSize);
  1181. SetLength(LAddresses, fLevelCount-1);
  1182. for level := 1 to fLevelCount-1 do
  1183. LAddresses[level-1] := GetLevelAddress(level);
  1184. d := MaxInteger(GetDepth, 1);
  1185. for slice := 0 to d - 1 do
  1186. begin
  1187. Build2DMipmap(GetLevelAddress(0), LAddresses, fColorFormat, fDataType,
  1188. AFilter, GetWidth, GetHeight);
  1189. for level := 1 to fLevelCount - 1 do
  1190. Inc(PByte(LAddresses[level - 1]), GetLevelSizeInByte(level) div d);
  1191. end;
  1192. end;
  1193. end;
  1194. procedure TGLBaseImage.UnMipmap;
  1195. var
  1196. level: TGLImageLODRange;
  1197. begin
  1198. for level := 1 to High(TGLImageLODRange) do
  1199. begin
  1200. FLOD[level].Width := 0;
  1201. FLOD[level].Height := 0;
  1202. FLOD[level].Depth := 0;
  1203. end;
  1204. FLevelCount := 1;
  1205. end;
  1206. procedure TGLBaseImage.UpdateLevelsInfo;
  1207. var
  1208. level: TGLImageLODRange;
  1209. w, h, d: Integer;
  1210. function GetSize(const level: Integer): Integer;
  1211. var
  1212. ld, bw, bh, lsize: Integer;
  1213. begin
  1214. if fTextureArray then
  1215. ld := FLOD[0].Depth
  1216. else
  1217. ld := d;
  1218. if ld = 0 then
  1219. ld := 1;
  1220. if IsCompressed then
  1221. begin
  1222. bw := (w + 3) div 4;
  1223. bh := (h + 3) div 4;
  1224. end
  1225. else
  1226. begin
  1227. bw := w;
  1228. bh := h;
  1229. end;
  1230. if bh = 0 then
  1231. bh := 1;
  1232. lsize := bw * bh * ld * fElementSize;
  1233. if fCubeMap and not fTextureArray then
  1234. lsize := lsize * 6;
  1235. // Align to Double Word
  1236. if (lsize and 3) <> 0 then
  1237. lsize := 4 * (1 + lsize div 4);
  1238. Result := lsize;
  1239. end;
  1240. begin
  1241. w := FLOD[0].Width;
  1242. h := FLOD[0].Height;
  1243. d := FLOD[0].Depth;
  1244. FLOD[0].Size := GetSize(0);
  1245. FLOD[0].Offset := 0;
  1246. for level := 1 to High(TGLImageLODRange) do
  1247. begin
  1248. Div2(w);
  1249. Div2(h);
  1250. if not fTextureArray then
  1251. d := d div 2;
  1252. FLOD[level].Width := w;
  1253. FLOD[level].Height := h;
  1254. FLOD[level].Depth := d;
  1255. FLOD[level].Offset := FLOD[level - 1].Offset + FLOD[level - 1].Size;
  1256. FLOD[level].Size := GetSize(level);
  1257. end;
  1258. end;
  1259. function TGLBaseImage.GetData: PGLPixel32Array;
  1260. begin
  1261. Result := fData;
  1262. end;
  1263. procedure TGLBaseImage.RegisterAsOpenGLTexture(
  1264. AHandle: TGLTextureHandle;
  1265. aMipmapGen: Boolean;
  1266. aTexFormat: Cardinal;
  1267. out texWidth: integer;
  1268. out texHeight: integer;
  1269. out texDepth: integer);
  1270. var
  1271. glTarget: Cardinal;
  1272. glHandle: Cardinal;
  1273. Level: integer;
  1274. LLevelCount, face: integer;
  1275. bCompress, bBlank: boolean;
  1276. w, h, d, cw, ch, maxSize: TGLsizei;
  1277. p, buffer: Pointer;
  1278. vtcBuffer, top, bottom: PGLubyte;
  1279. i, j, k: Integer;
  1280. transferMethod: 0..3;
  1281. function blockOffset(x, y, z: Integer): Integer;
  1282. begin
  1283. if z >= (d and -4) then
  1284. Result := fElementSize * (cw * ch * (d and -4) + x +
  1285. cw * (y + ch * (z - 4 * ch)))
  1286. else
  1287. Result := fElementSize * (4 * (x + cw * (y + ch * floor(z / 4))) + (z and
  1288. 3));
  1289. if Result < 0 then
  1290. Result := 0;
  1291. end;
  1292. begin
  1293. if AHandle.Target = ttNoShape then
  1294. Exit;
  1295. UpdateLevelsInfo;
  1296. if Self is TGLImage then
  1297. bBlank := TGLImage(Self).Blank
  1298. else
  1299. bBlank := False;
  1300. // Check for Non-power-of-two
  1301. if not gl.ARB_texture_non_power_of_two then
  1302. begin
  1303. w := RoundUpToPowerOf2(GetWidth);
  1304. h := RoundUpToPowerOf2(GetHeight);
  1305. d := RoundUpToPowerOf2(GetDepth);
  1306. if GetDepth = 0 then
  1307. d := 0;
  1308. end
  1309. else
  1310. begin
  1311. w := GetWidth;
  1312. h := GetHeight;
  1313. d := GetDepth;
  1314. end;
  1315. // Check maximum dimension
  1316. maxSize := CurrentGLContext.GLStates.MaxTextureSize;
  1317. if w > maxSize then
  1318. w := maxSize;
  1319. if h > maxSize then
  1320. h := maxSize;
  1321. texWidth := w;
  1322. texHeight := h;
  1323. texDepth := d;
  1324. LLevelCount := fLevelCount;
  1325. bCompress := IsCompressed;
  1326. // Rescale if need and can
  1327. buffer := nil;
  1328. if (w <> GetWidth) or (h <> GetHeight) then
  1329. begin
  1330. if not((d > 0) // not volume
  1331. or bCompress // not compressed
  1332. or bBlank) then // not blank
  1333. begin
  1334. GetMem(buffer, w * h * fElementSize);
  1335. try
  1336. RescaleImage(fData, buffer, fColorFormat, fDataType,
  1337. ImageLanczos3Filter, GetWidth, GetHeight, w, h);
  1338. LLevelCount := 1;
  1339. except
  1340. bBlank := True;
  1341. end;
  1342. end
  1343. else
  1344. bBlank := True;
  1345. end;
  1346. if Self is TGLImage then
  1347. TGLImage(Self).FBlank := bBlank;
  1348. glHandle := AHandle.Handle;
  1349. glTarget := DecodeTextureTarget(AHandle.Target);
  1350. // Hardware mipmap autogeneration
  1351. aMipmapGen := aMipmapGen and IsTargetSupportMipmap(glTarget);
  1352. aMipmapGen := aMipmapGen and (LLevelCount = 1);
  1353. if aMipmapGen then
  1354. begin
  1355. if gl.SGIS_generate_mipmap then
  1356. begin
  1357. if gl.EXT_direct_state_access then
  1358. gl.TexParameterf(
  1359. glTarget,
  1360. GL_GENERATE_MIPMAP_SGIS,
  1361. GL_TRUE)
  1362. else
  1363. gl.TexParameteri(glTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
  1364. end
  1365. else
  1366. begin
  1367. // Software LODs generation
  1368. Self.GenerateMipmap(ImageTriangleFilter);
  1369. LLevelCount := LevelCount;
  1370. end;
  1371. end;
  1372. // Setup top limitation of LODs
  1373. if gl.SGIS_texture_lod and (LLevelCount > 1) then
  1374. if gl.EXT_direct_state_access then
  1375. gl.TexParameterf(
  1376. glTarget,
  1377. GL_TEXTURE_MAX_LEVEL_SGIS,
  1378. LLevelCount - 1)
  1379. else
  1380. gl.TexParameteri(glTarget, GL_TEXTURE_MAX_LEVEL_SGIS, LLevelCount - 1);
  1381. // Select transfer method
  1382. if bCompress then
  1383. transferMethod := 1
  1384. else
  1385. transferMethod := 0;
  1386. if gl.EXT_direct_state_access then
  1387. transferMethod := transferMethod + 2;
  1388. // if image is blank then doing only allocatation texture in videomemory
  1389. vtcBuffer := nil;
  1390. case AHandle.Target of
  1391. ttTexture1D:
  1392. for level := 0 to LLevelCount - 1 do
  1393. begin
  1394. if Assigned(buffer) then
  1395. p := buffer
  1396. else if not bBlank then
  1397. p := GetLevelAddress(level)
  1398. else
  1399. p := nil;
  1400. case transferMethod of
  1401. 0: gl.TexImage1D(glTarget, level, aTexFormat, w, 0, fColorFormat,
  1402. fDataType, p);
  1403. 1: gl.CompressedTexImage1D(glTarget, level, aTexFormat, w, 0,
  1404. GetLevelSizeInByte(level), p);
  1405. 2: gl.TextureImage1D(glHandle, glTarget, level, aTexFormat, w, 0,
  1406. fColorFormat, fDataType, p);
  1407. 3: gl.CompressedTextureImage1D(glHandle, glTarget, level, aTexFormat, w,
  1408. 0, GetLevelSizeInByte(level), p)
  1409. end;
  1410. Div2(w);
  1411. end;
  1412. ttTexture2D:
  1413. for Level := 0 to LLevelCount - 1 do
  1414. begin
  1415. if Assigned(buffer) then
  1416. p := buffer
  1417. else if not bBlank then
  1418. p := GetLevelAddress(Level)
  1419. else
  1420. p := nil;
  1421. case transferMethod of
  1422. 0: gl.TexImage2D(glTarget, level, aTexFormat, w, h, 0, fColorFormat,
  1423. fDataType, p);
  1424. 1: gl.CompressedTexImage2D(glTarget, level, aTexFormat, w, h, 0,
  1425. GetLevelSizeInByte(level), p);
  1426. 2: gl.TextureImage2D(glHandle, glTarget, level, aTexFormat, w, h, 0,
  1427. fColorFormat, fDataType, p);
  1428. 3: gl.CompressedTextureImage2D(glHandle, glTarget, level, aTexFormat, w,
  1429. h, 0, GetLevelSizeInByte(level), p);
  1430. end;
  1431. Div2(w);
  1432. Div2(h);
  1433. end;
  1434. ttTextureRect:
  1435. begin
  1436. if Assigned(buffer) then
  1437. p := buffer
  1438. else if not bBlank then
  1439. p := GetLevelAddress(0)
  1440. else
  1441. p := nil;
  1442. case transferMethod of
  1443. 0: gl.TexImage2D(glTarget, 0, aTexFormat, w, h, 0, fColorFormat,
  1444. fDataType, p);
  1445. 1: gl.CompressedTexImage2D(glTarget, 0, aTexFormat, w, h, 0,
  1446. GetLevelSizeInByte(0), p);
  1447. 2: gl.TextureImage2D(glHandle, glTarget, 0, aTexFormat, w, h, 0,
  1448. fColorFormat, fDataType, p);
  1449. 3: gl.CompressedTextureImage2D(glHandle, glTarget, 0, aTexFormat, w, h,
  1450. 0, GetLevelSizeInByte(0), p);
  1451. end;
  1452. end;
  1453. ttTexture3D:
  1454. for Level := 0 to LLevelCount - 1 do
  1455. begin
  1456. if Assigned(buffer) then
  1457. p := buffer
  1458. else if not bBlank then
  1459. p := GetLevelAddress(Level)
  1460. else
  1461. p := nil;
  1462. if gl.NV_texture_compression_vtc and bCompress then
  1463. begin
  1464. // Shufle blocks for Volume Texture Compression
  1465. if Assigned(p) then
  1466. begin
  1467. cw := (w + 3) div 4;
  1468. ch := (h + 3) div 4;
  1469. if Level = 0 then
  1470. GetMem(vtcBuffer, GetLevelSizeInByte(0));
  1471. top := p;
  1472. for k := 0 to d - 1 do
  1473. for i := 0 to ch - 1 do
  1474. for j := 0 to cw - 1 do
  1475. begin
  1476. bottom := vtcBuffer;
  1477. Inc(bottom, blockOffset(j, i, k));
  1478. Move(top^, bottom^, fElementSize);
  1479. Inc(top, fElementSize);
  1480. end;
  1481. end;
  1482. if gl.EXT_direct_state_access then
  1483. gl.CompressedTextureImage3D(glHandle, glTarget, level, aTexFormat, w,
  1484. h, d, 0, GetLevelSizeInByte(level), vtcBuffer)
  1485. else
  1486. gl.CompressedTexImage3D(glTarget, level, aTexFormat, w, h, d, 0,
  1487. GetLevelSizeInByte(level), vtcBuffer);
  1488. end
  1489. else
  1490. begin
  1491. // Normal compression
  1492. case transferMethod of
  1493. 0: gl.TexImage3D(glTarget, level, aTexFormat, w, h, d, 0,
  1494. fColorFormat, fDataType, p);
  1495. 1: gl.CompressedTexImage3D(glTarget, level, aTexFormat, w, h, d, 0,
  1496. GetLevelSizeInByte(level), p);
  1497. 2: gl.TextureImage3D(glHandle, glTarget, level, aTexFormat, w, h, d,
  1498. 0, fColorFormat, fDataType, p);
  1499. 3: gl.CompressedTextureImage3D(glHandle, glTarget, level, aTexFormat,
  1500. w, h, d, 0, GetLevelSizeInByte(level), p);
  1501. end;
  1502. end;
  1503. Div2(w);
  1504. Div2(h);
  1505. Div2(d);
  1506. end;
  1507. ttTextureCube:
  1508. for Level := 0 to LLevelCount - 1 do
  1509. begin
  1510. for face := GL_TEXTURE_CUBE_MAP_POSITIVE_X to
  1511. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z do
  1512. begin
  1513. if Assigned(buffer) then
  1514. p := buffer
  1515. else if not bBlank then
  1516. p := GetLevelAddress(level, face - GL_TEXTURE_CUBE_MAP_POSITIVE_X)
  1517. else
  1518. p := nil;
  1519. case transferMethod of
  1520. 0: gl.TexImage2D(face, level, aTexFormat, w, h, 0, fColorFormat,
  1521. fDataType, p);
  1522. 1: gl.CompressedTexImage2D(face, level, aTexFormat, w, h, 0,
  1523. GetLevelSizeInByte(level) div 6, p);
  1524. 2: gl.TextureImage2D(glHandle, face, level, aTexFormat, w, h, 0,
  1525. fColorFormat, fDataType, p);
  1526. 3: gl.CompressedTextureImage2D(glHandle, face, level, aTexFormat, w,
  1527. h, 0, GetLevelSizeInByte(level) div 6, p);
  1528. end;
  1529. end;
  1530. Div2(w);
  1531. Div2(h);
  1532. end;
  1533. ttTexture1DArray:
  1534. for Level := 0 to LLevelCount - 1 do
  1535. begin
  1536. if Assigned(buffer) then
  1537. p := buffer
  1538. else if not bBlank then
  1539. p := GetLevelAddress(Level)
  1540. else
  1541. p := nil;
  1542. case transferMethod of
  1543. 0: gl.TexImage2D(glTarget, level, aTexFormat, w, h, 0, fColorFormat,
  1544. fDataType, p);
  1545. 1: gl.CompressedTexImage2D(glTarget, level, aTexFormat, w, h, 0,
  1546. GetLevelSizeInByte(level), p);
  1547. 2: gl.TextureImage2D(glHandle, glTarget, level, aTexFormat, w, h, 0,
  1548. fColorFormat, fDataType, p);
  1549. 3: gl.CompressedTextureImage2D(glHandle, glTarget, level, aTexFormat, w,
  1550. h, 0, GetLevelSizeInByte(level), p);
  1551. end;
  1552. Div2(w);
  1553. end;
  1554. ttTexture2DArray, ttTextureCubeArray:
  1555. for Level := 0 to LLevelCount - 1 do
  1556. begin
  1557. if Assigned(buffer) then
  1558. p := buffer
  1559. else if not bBlank then
  1560. p := GetLevelAddress(Level)
  1561. else
  1562. p := nil;
  1563. case transferMethod of
  1564. 0: gl.TexImage3D(glTarget, level, aTexFormat, w, h, d, 0, fColorFormat,
  1565. fDataType, p);
  1566. 1: gl.CompressedTexImage3D(glTarget, level, aTexFormat, w, h, d, 0,
  1567. GetLevelSizeInByte(level), p);
  1568. 2: gl.TextureImage3D(glHandle, glTarget, level, aTexFormat, w, h, d, 0,
  1569. fColorFormat, fDataType, p);
  1570. 3: gl.CompressedTextureImage3D(glHandle, glTarget, level, aTexFormat, w,
  1571. h, d, 0, GetLevelSizeInByte(level), p);
  1572. end;
  1573. Div2(w);
  1574. Div2(h);
  1575. end;
  1576. end; // of case
  1577. if Assigned(buffer) then
  1578. FreeMem(buffer);
  1579. if Assigned(vtcBuffer) then
  1580. FreeMem(vtcBuffer);
  1581. end;
  1582. function TGLBaseImage.AssignFromTexture(AHandle: TGLTextureHandle;
  1583. const CastToFormat: Boolean; const intFormat: TGLInternalFormat = tfRGBA8;
  1584. const colorFormat: Cardinal = 0; const dataType: Cardinal = 0): Boolean;
  1585. var
  1586. LContext: TGLContext;
  1587. texFormat, texLod, optLod: Cardinal;
  1588. glTarget: Cardinal;
  1589. level, maxFace, face: Integer;
  1590. lData: PGLubyte;
  1591. residentFormat: TGLInternalFormat;
  1592. bCompressed: Boolean;
  1593. vtcBuffer, top, bottom: PGLubyte;
  1594. i, j, k: Integer;
  1595. w, d, h, cw, ch: Integer;
  1596. function blockOffset(x, y, z: Integer): Integer;
  1597. begin
  1598. if z >= (d and -4) then
  1599. Result := fElementSize * (cw * ch * (d and -4) + x + cw *
  1600. (y + ch * (z - 4 * ch)))
  1601. else
  1602. Result := fElementSize * (4 * (x + cw * (y + ch * floor(z / 4))) +
  1603. (z and 3));
  1604. end;
  1605. begin
  1606. Result := False;
  1607. LContext := CurrentGLContext;
  1608. if LContext = nil then
  1609. begin
  1610. LContext := AHandle.RenderingContext;
  1611. if LContext = nil then
  1612. Exit;
  1613. end;
  1614. LContext.Activate;
  1615. if AHandle.IsDataNeedUpdate then
  1616. begin
  1617. LContext.Deactivate;
  1618. Exit;
  1619. end;
  1620. glTarget := DecodeTextureTarget(AHandle.Target);
  1621. try
  1622. LContext.GLStates.TextureBinding[0, AHandle.Target] := AHandle.Handle;
  1623. FLevelCount := 0;
  1624. gl.GetTexParameteriv(glTarget, GL_TEXTURE_MAX_LEVEL, @texLod);
  1625. if glTarget = GL_TEXTURE_CUBE_MAP then
  1626. begin
  1627. fCubeMap := True;
  1628. maxFace := 5;
  1629. glTarget := GL_TEXTURE_CUBE_MAP_POSITIVE_X;
  1630. end
  1631. else
  1632. begin
  1633. fCubeMap := False;
  1634. maxFace := 0;
  1635. end;
  1636. fTextureArray := (glTarget = GL_TEXTURE_1D_ARRAY) or
  1637. (glTarget = GL_TEXTURE_2D_ARRAY) or
  1638. (glTarget = GL_TEXTURE_CUBE_MAP_ARRAY);
  1639. repeat
  1640. // Check level existence
  1641. gl.GetTexLevelParameteriv(glTarget, FLevelCount,
  1642. GL_TEXTURE_INTERNAL_FORMAT,
  1643. @texFormat);
  1644. if texFormat = 1 then
  1645. Break;
  1646. Inc(FLevelCount);
  1647. if FLevelCount = 1 then
  1648. begin
  1649. gl.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_WIDTH, @FLOD[0].Width);
  1650. gl.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_HEIGHT,@FLOD[0].Height);
  1651. FLOD[0].Depth := 0;
  1652. if (glTarget = GL_TEXTURE_3D)
  1653. or (glTarget = GL_TEXTURE_2D_ARRAY)
  1654. or (glTarget = GL_TEXTURE_CUBE_MAP_ARRAY) then
  1655. gl.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_DEPTH, @FLOD[0].Depth);
  1656. residentFormat := OpenGLFormatToInternalFormat(texFormat);
  1657. if CastToFormat then
  1658. fInternalFormat := residentFormat
  1659. else
  1660. fInternalFormat := intFormat;
  1661. FindCompatibleDataFormat(fInternalFormat, fColorFormat, fDataType);
  1662. // Substitute properties if need
  1663. if colorFormat > 0 then
  1664. fColorFormat := colorFormat;
  1665. if dataType > 0 then
  1666. fDataType := dataType;
  1667. // Get optimal number or MipMap levels
  1668. optLod := GetImageLodNumber(GetWidth, GetHeight, GetDepth, glTarget = GL_TEXTURE_3D);
  1669. if texLod > optLod then
  1670. texLod := optLod;
  1671. // Check for MipMap posibility
  1672. if ((fInternalFormat >= tfFLOAT_R16)
  1673. and (fInternalFormat <= tfFLOAT_RGBA32)) then
  1674. texLod := 1;
  1675. end;
  1676. until FLevelCount = Integer(texLod);
  1677. if FLevelCount > 0 then
  1678. begin
  1679. fElementSize := GetTextureElementSize(fColorFormat, fDataType);
  1680. UpdateLevelsInfo;
  1681. ReallocMem(FData, DataSize);
  1682. lData := PGLubyte(fData);
  1683. bCompressed := IsCompressed;
  1684. vtcBuffer := nil;
  1685. w := GetWidth;
  1686. h := GetHeight;
  1687. d := GetDepth;
  1688. for face := 0 to maxFace do
  1689. begin
  1690. if fCubeMap then
  1691. glTarget := face + GL_TEXTURE_CUBE_MAP_POSITIVE_X;
  1692. for level := 0 to FLevelCount - 1 do
  1693. begin
  1694. if bCompressed then
  1695. begin
  1696. if GL.NV_texture_compression_vtc and (d > 1) and not fTextureArray then
  1697. begin
  1698. if level = 0 then
  1699. GetMem(vtcBuffer, GetLevelSizeInByte(0));
  1700. gl.GetCompressedTexImage(glTarget, level, vtcBuffer);
  1701. // Shufle blocks from VTC to S3TC
  1702. cw := (w + 3) div 4;
  1703. ch := (h + 3) div 4;
  1704. top := lData;
  1705. for k := 0 to d - 1 do
  1706. for i := 0 to ch - 1 do
  1707. for j := 0 to cw - 1 do
  1708. begin
  1709. bottom := vtcBuffer;
  1710. Inc(bottom, blockOffset(j, i, k));
  1711. Move(bottom^, top^, fElementSize);
  1712. Inc(top, fElementSize);
  1713. end;
  1714. Div2(w);
  1715. Div2(h);
  1716. Div2(d);
  1717. end
  1718. else
  1719. gl.GetCompressedTexImage(glTarget, level, lData);
  1720. end
  1721. else
  1722. gl.GetTexImage(glTarget, level, fColorFormat, fDataType, lData);
  1723. Inc(lData, GetLevelSizeInByte(level));
  1724. end; // for level
  1725. end; // for face
  1726. if Assigned(vtcBuffer) then
  1727. FreeMem(vtcBuffer);
  1728. // Check memory corruption
  1729. ReallocMem(FData, DataSize);
  1730. end;
  1731. if Self is TGLImage then
  1732. begin
  1733. TGLImage(Self).FBlank := FLevelCount = 0;
  1734. if FLevelCount = 0 then
  1735. begin
  1736. UnMipmap;
  1737. FreeMem(fData);
  1738. fData := nil;
  1739. end;
  1740. end;
  1741. gl.CheckError;
  1742. Result := True;
  1743. finally
  1744. LContext.Deactivate;
  1745. end;
  1746. end;
  1747. procedure TGLBaseImage.SaveHeader;
  1748. var
  1749. Temp: Integer;
  1750. LStream: TStream;
  1751. begin
  1752. Temp := 0;
  1753. LStream := nil;
  1754. try
  1755. LStream := TFileStream.Create(ResourceName, fmOpenWrite or fmCreate);
  1756. with LStream do
  1757. begin
  1758. Write(Temp, SizeOf(Integer)); // Version
  1759. Write(FLOD[0].Width, SizeOf(Integer));
  1760. Write(FLOD[0].Height, SizeOf(Integer));
  1761. Write(FLOD[0].Depth, SizeOf(Integer));
  1762. Write(fColorFormat, SizeOf(Cardinal));
  1763. Temp := Integer(fInternalFormat);
  1764. Write(Temp, SizeOf(Integer));
  1765. Write(fDataType, SizeOf(Cardinal));
  1766. Write(fElementSize, SizeOf(Integer));
  1767. Write(fLevelCount, SizeOf(TGLImageLODRange));
  1768. Temp := Integer(fCubeMap);
  1769. Write(Temp, SizeOf(Integer));
  1770. Temp := Integer(fTextureArray);
  1771. Write(Temp, SizeOf(Integer));
  1772. end;
  1773. finally
  1774. LStream.Free;
  1775. end;
  1776. end;
  1777. procedure TGLBaseImage.LoadHeader;
  1778. var
  1779. Temp: Integer;
  1780. LStream: TStream;
  1781. begin
  1782. LStream := nil;
  1783. try
  1784. LStream := TFileStream.Create(ResourceName, fmOpenRead);
  1785. with LStream do
  1786. begin
  1787. Read(Temp, SizeOf(Integer)); // Version
  1788. if Temp > 0 then
  1789. begin
  1790. GLSLogger.LogError(Format(strUnknownArchive, [Self.ClassType, Temp]));
  1791. Abort;
  1792. end;
  1793. Read(FLOD[0].Width, SizeOf(Integer));
  1794. Read(FLOD[0].Height, SizeOf(Integer));
  1795. Read(FLOD[0].Depth, SizeOf(Integer));
  1796. Read(fColorFormat, SizeOf(Cardinal));
  1797. Read(Temp, SizeOf(Integer));
  1798. fInternalFormat := TGLInternalFormat(Temp);
  1799. Read(fDataType, SizeOf(Cardinal));
  1800. Read(fElementSize, SizeOf(Integer));
  1801. Read(fLevelCount, SizeOf(TGLImageLODRange));
  1802. Read(Temp, SizeOf(Integer));
  1803. fCubeMap := Boolean(Temp);
  1804. Read(Temp, SizeOf(Integer));
  1805. fTextureArray := Boolean(Temp);
  1806. UpdateLevelsInfo;
  1807. end;
  1808. finally
  1809. LStream.Free;
  1810. end;
  1811. end;
  1812. var
  1813. vGlobalStreamingTaskCounter: Integer = 0;
  1814. procedure TGLBaseImage.StartStreaming;
  1815. var
  1816. level: TGLImageLODRange;
  1817. begin
  1818. FStreamLevel := fLevelCount - 1;
  1819. for level := 0 to High(TGLImageLODRange) do
  1820. FLOD[level].State := ssKeeping;
  1821. end;
  1822. procedure TGLBaseImage.DoStreaming;
  1823. begin
  1824. {$IFDEF USE_SERVICE_CONTEXT}
  1825. if Assigned(FFinishEvent) then
  1826. begin
  1827. if FFinishEvent.WaitFor(0) <> wrSignaled then
  1828. Exit;
  1829. end
  1830. else
  1831. FFinishEvent := TFinishTaskEvent.Create;
  1832. Inc(vGlobalStreamingTaskCounter);
  1833. AddTaskForServiceContext(ImageStreamingTask, FFinishEvent);
  1834. {$ENDIF}
  1835. end;
  1836. {$IFDEF USE_SERVICE_CONTEXT}
  1837. procedure TGLBaseImage.ImageStreamingTask;
  1838. var
  1839. readSize: Integer;
  1840. ptr: PByte;
  1841. begin
  1842. with FLOD[FStreamLevel] do
  1843. begin
  1844. if PBO = nil then
  1845. PBO := TGLUnpackPBOHandle.Create;
  1846. PBO.AllocateHandle;
  1847. if PBO.IsDataNeedUpdate then
  1848. begin
  1849. (* This may work with multiple unshared context, but never tested
  1850. because unlikely. *)
  1851. PBO.BindBufferData(nil, MaxInteger(Size, 1024), GL_STREAM_DRAW);
  1852. if Assigned(MapAddress) then
  1853. if not PBO.UnmapBuffer then
  1854. Exit;
  1855. MapAddress := PBO.MapBuffer(GL_WRITE_ONLY);
  1856. StreamOffset := 0;
  1857. PBO.UnBind;
  1858. PBO.NotifyDataUpdated;
  1859. end;
  1860. if FSourceStream = nil then
  1861. begin
  1862. FSourceStream := TFileStream.Create(ResourceName +
  1863. IntToHex(FStreamLevel,2), fmOpenRead + fmShareDenyNone);
  1864. end;
  1865. // Move to position of next piece and read it
  1866. readSize := MinInteger(Cardinal(8192 div vGlobalStreamingTaskCounter),
  1867. Cardinal(Size - StreamOffset));
  1868. if readSize > 0 then
  1869. begin
  1870. ptr := PByte(MapAddress);
  1871. Inc(ptr, StreamOffset);
  1872. FSourceStream.Read(ptr^, readSize);
  1873. Inc(StreamOffset, readSize);
  1874. end;
  1875. Dec(vGlobalStreamingTaskCounter);
  1876. if StreamOffset >= Size then
  1877. begin
  1878. PBO.Bind;
  1879. if PBO.UnmapBuffer then
  1880. State := ssLoaded;
  1881. PBO.UnBind;
  1882. if State <> ssLoaded then
  1883. Exit; // Can't unmap
  1884. MapAddress := nil;
  1885. StreamOffset := 0;
  1886. if FStreamLevel > 0 then
  1887. Dec(FStreamLevel);
  1888. FSourceStream.Destroy;
  1889. FSourceStream := nil;
  1890. end;
  1891. end;
  1892. end;
  1893. {$ENDIF}
  1894. // ------------------
  1895. // ------------------ TGLImage ------------------
  1896. // ------------------
  1897. constructor TGLImage.Create;
  1898. begin
  1899. inherited Create;
  1900. SetBlank(False);
  1901. end;
  1902. destructor TGLImage.Destroy;
  1903. begin
  1904. inherited Destroy;
  1905. end;
  1906. procedure TGLImage.Assign(Source: TPersistent);
  1907. var
  1908. bmp: TBitmap;
  1909. graphic: TGraphic;
  1910. begin
  1911. if (Source is TGLImage) or (Source is TGLBaseImage) then
  1912. begin
  1913. if Source is TGLImage then
  1914. FBlank := TGLImage(Source).FBlank
  1915. else
  1916. FBlank := False;
  1917. if not FBlank then
  1918. inherited
  1919. else
  1920. begin
  1921. FLOD := TGLImage(Source).FLOD;
  1922. FLevelCount := TGLImage(Source).FLevelCount;
  1923. fCubeMap := TGLImage(Source).fCubeMap;
  1924. fColorFormat := TGLImage(Source).fColorFormat;
  1925. fInternalFormat := TGLImage(Source).fInternalFormat;
  1926. fDataType := TGLImage(Source).fDataType;
  1927. fElementSize := TGLImage(Source).fElementSize;
  1928. fTextureArray := TGLImage(Source).fTextureArray;
  1929. end;
  1930. end
  1931. else if Source is TGraphic then
  1932. begin
  1933. if (Source is TBitmap)
  1934. and (TBitmap(Source).PixelFormat in [pf24bit, pf32bit])
  1935. and (((TBitmap(Source).Width and 3) = 0) or gl.EXT_bgra) then
  1936. begin
  1937. if TBitmap(Source).PixelFormat = pf24bit then
  1938. AssignFrom24BitsBitmap(TBitmap(Source))
  1939. else
  1940. AssignFrom32BitsBitmap(TBitmap(Source))
  1941. end
  1942. else if Source is TPngImage then
  1943. AssignFromPngImage(TPngImage(Source))
  1944. else
  1945. begin
  1946. graphic := TGraphic(Source);
  1947. bmp := TBitmap.Create;
  1948. try
  1949. // crossbuilder: useless to set pixelformat before setting the size ?
  1950. // or maybe just useless at all on gtk .. as soon as
  1951. // bmp.canvas is touched, it's the pixelformat of the device
  1952. // no matter what was adjusted before ??
  1953. // bmp.PixelFormat:=glpf24bit;
  1954. // bmp.Height:=graphic.Height;
  1955. // crossbuilder: using setsize because setting width or height while
  1956. // the other one is zero results in not setting with/hight
  1957. bmp.PixelFormat := pf24bit;
  1958. bmp.Height := graphic.Height;
  1959. if (graphic.Width and 3) = 0 then
  1960. begin
  1961. bmp.Width := graphic.Width;
  1962. bmp.Canvas.Draw(0, 0, graphic);
  1963. end
  1964. else
  1965. begin
  1966. bmp.Width := (graphic.Width and $FFFC) + 4;
  1967. bmp.Canvas.StretchDraw(Rect(0, 0, bmp.Width, bmp.Height), graphic);
  1968. end;
  1969. AssignFrom24BitsBitmap(bmp);
  1970. finally
  1971. bmp.Free;
  1972. end;
  1973. end;
  1974. {$IFDEF USE_GRAPHICS32}
  1975. end
  1976. else if Source is TBitmap32 then
  1977. begin
  1978. Narrow;
  1979. AssignFromBitmap32(TBitmap32(Source));
  1980. {$ENDIF}
  1981. end
  1982. else
  1983. inherited;
  1984. end;
  1985. procedure TGLImage.AssignFrom24BitsBitmap(aBitmap: TBitmap);
  1986. var
  1987. y, lineSize: Integer;
  1988. rowOffset: Int64;
  1989. pSrc, pDest: PAnsiChar;
  1990. begin
  1991. Assert(aBitmap.PixelFormat = pf24bit);
  1992. UnMipmap;
  1993. FLOD[0].Width := aBitmap.Width;
  1994. FLOD[0].Height := aBitmap.Height;
  1995. FLOD[0].Depth := 0;
  1996. if gl.EXT_bgra then
  1997. begin
  1998. fColorFormat := GL_BGR;
  1999. fElementSize := 3;
  2000. end
  2001. else
  2002. begin
  2003. Assert((aBitmap.Width and 3) = 0);
  2004. fColorFormat := GL_RGBA;
  2005. fElementSize := 4;
  2006. end;
  2007. fInternalFormat := tfRGBA8;
  2008. fDataType := GL_UNSIGNED_BYTE;
  2009. fCubeMap := False;
  2010. fTextureArray := False;
  2011. ReallocMem(fData, DataSize);
  2012. FBlank := False;
  2013. lineSize := GetWidth * fElementSize;
  2014. if Height > 0 then
  2015. begin
  2016. pDest := @PAnsiChar(FData)[GetWidth * fElementSize * (GetHeight - 1)];
  2017. if Height = 1 then
  2018. begin
  2019. if gl.EXT_bgra then
  2020. begin
  2021. pSrc := aBitmap.ScanLine[0]; //BitmapScanLine(aBitmap, 0);
  2022. Move(pSrc^, pDest^, lineSize);
  2023. end
  2024. else
  2025. BGR24ToRGBA32(aBitmap.ScanLine[0], pDest, GetWidth);
  2026. end
  2027. else
  2028. begin
  2029. if VerticalReverseOnAssignFromBitmap then
  2030. begin
  2031. pSrc := aBitmap.ScanLine[GetHeight - 1];
  2032. rowOffset := Integer(aBitmap.ScanLine[GetHeight - 2]) - Integer(pSrc);
  2033. end
  2034. else
  2035. begin
  2036. pSrc := aBitmap.ScanLine[0];
  2037. rowOffset := Int64(aBitmap.ScanLine[1]) - Int64(pSrc);
  2038. end;
  2039. if gl.EXT_bgra then
  2040. begin
  2041. for y := 0 to Height - 1 do
  2042. begin
  2043. Move(pSrc^, pDest^, lineSize);
  2044. Dec(pDest, lineSize);
  2045. Inc(pSrc, rowOffset);
  2046. end;
  2047. end
  2048. else
  2049. begin
  2050. for y := 0 to Height - 1 do
  2051. begin
  2052. BGR24ToRGBA32(pSrc, pDest, Width);
  2053. Dec(pDest, lineSize);
  2054. Inc(pSrc, rowOffset);
  2055. end;
  2056. end;
  2057. end;
  2058. end;
  2059. end;
  2060. procedure TGLImage.AssignFromBitmap24WithoutRGBSwap(aBitmap: TBitmap);
  2061. var
  2062. y: Integer;
  2063. rowOffset: Int64;
  2064. pSrc, pDest: PAnsiChar;
  2065. begin
  2066. Assert(aBitmap.PixelFormat = pf24bit);
  2067. Assert((aBitmap.Width and 3) = 0);
  2068. UnMipmap;
  2069. FLOD[0].Width := aBitmap.Width;
  2070. FLOD[0].Height := aBitmap.Height;
  2071. FLOD[0].Depth := 0;
  2072. fColorFormat := GL_RGBA;
  2073. fInternalFormat := tfRGBA8;
  2074. fDataType := GL_UNSIGNED_BYTE;
  2075. fElementSize := 4;
  2076. fCubeMap := False;
  2077. fTextureArray := False;
  2078. ReallocMem(fData, DataSize);
  2079. FBlank := False;
  2080. if Height > 0 then
  2081. begin
  2082. pDest := @PAnsiChar(fData)[Width * 4 * (Height - 1)];
  2083. if Height = 1 then
  2084. begin
  2085. RGB24ToRGBA32(aBitmap.ScanLine[0], pDest, GetWidth);
  2086. end
  2087. else
  2088. begin
  2089. if VerticalReverseOnAssignFromBitmap then
  2090. begin
  2091. pSrc := aBitmap.ScanLine[GetHeight - 1];
  2092. rowOffset := Cardinal(aBitmap.ScanLine[GetHeight - 2]);
  2093. Dec(rowOffset, Cardinal(pSrc));
  2094. end
  2095. else
  2096. begin
  2097. pSrc := aBitmap.ScanLine[0];
  2098. rowOffset := Cardinal(aBitmap.ScanLine[1]);
  2099. Dec(rowOffset, Cardinal(pSrc));
  2100. end;
  2101. for y := 0 to Height - 1 do
  2102. begin
  2103. RGB24ToRGBA32(pSrc, pDest, GetWidth);
  2104. Dec(pDest, GetWidth * 4);
  2105. Inc(pSrc, rowOffset);
  2106. end;
  2107. end;
  2108. end;
  2109. end;
  2110. procedure TGLImage.AssignFrom32BitsBitmap(aBitmap: TBitmap);
  2111. var
  2112. y: Integer;
  2113. rowOffset: Int64;
  2114. pSrc, pDest: PAnsiChar;
  2115. begin
  2116. Assert(aBitmap.PixelFormat = pf32bit);
  2117. UnMipmap;
  2118. FLOD[0].Width := aBitmap.Width;
  2119. FLOD[0].Height := aBitmap.Height;
  2120. FLOD[0].Depth := 0;
  2121. if gl.EXT_bgra then
  2122. fColorFormat := GL_BGRA
  2123. else
  2124. begin
  2125. Assert((aBitmap.Width and 3) = 0);
  2126. fColorFormat := GL_RGBA;
  2127. end;
  2128. fInternalFormat := tfRGBA8;
  2129. fDataType := GL_UNSIGNED_BYTE;
  2130. fElementSize := 4;
  2131. fCubeMap := False;
  2132. fTextureArray := False;
  2133. ReallocMem(fData, DataSize);
  2134. FBlank := False;
  2135. if Height > 0 then
  2136. begin
  2137. pDest := @PAnsiChar(FData)[Width * 4 * (Height - 1)];
  2138. if VerticalReverseOnAssignFromBitmap then
  2139. begin
  2140. pSrc := aBitmap.ScanLine[Height - 1];
  2141. if Height > 1 then
  2142. begin
  2143. rowOffset := Cardinal(aBitmap.ScanLine[Height - 2]);
  2144. Dec(rowOffset, Cardinal(pSrc));
  2145. end
  2146. else
  2147. rowOffset := 0;
  2148. end
  2149. else
  2150. begin
  2151. pSrc := aBitmap.ScanLine[0];
  2152. if Height > 1 then
  2153. begin
  2154. rowOffset := Cardinal(aBitmap.ScanLine[1]);
  2155. Dec(rowOffset, Cardinal(pSrc));
  2156. end
  2157. else
  2158. rowOffset := 0;
  2159. end;
  2160. if gl.EXT_bgra then
  2161. begin
  2162. for y := 0 to Height - 1 do
  2163. begin
  2164. Move(pSrc^, pDest^, Width * 4);
  2165. Dec(pDest, Width * 4);
  2166. Inc(pSrc, rowOffset);
  2167. end;
  2168. end
  2169. else
  2170. begin
  2171. for y := 0 to Height - 1 do
  2172. begin
  2173. BGRA32ToRGBA32(pSrc, pDest, Width);
  2174. Dec(pDest, Width * 4);
  2175. Inc(pSrc, rowOffset);
  2176. end;
  2177. end;
  2178. end;
  2179. end;
  2180. {$IFDEF USE_GRAPHICS32}
  2181. procedure TGLImage.AssignFromBitmap32(aBitmap32: TBitmap32);
  2182. var
  2183. y: Integer;
  2184. pSrc, pDest: PAnsiChar;
  2185. begin
  2186. UnMipmap;
  2187. FLOD[0].Width := aBitmap32.Width;
  2188. FLOD[0].Height := aBitmap32.Height;
  2189. FLOD[0].Depth := 0;
  2190. fColorFormat := GL_RGBA;
  2191. fInternalFormat := tfRGBA8;
  2192. fDataType := GL_UNSIGNED_BYTE;
  2193. fElementSize := 4;
  2194. fCubeMap := False;
  2195. fTextureArray := False;
  2196. ReallocMem(fData, DataSize);
  2197. FBlank := False;
  2198. if Height > 0 then
  2199. begin
  2200. pDest := @PAnsiChar(FData)[Width * 4 * (Height - 1)];
  2201. for y := 0 to Height - 1 do
  2202. begin
  2203. if VerticalReverseOnAssignFromBitmap then
  2204. pSrc := PAnsiChar(aBitmap32.ScanLine[Height - 1 - y])
  2205. else
  2206. pSrc := PAnsiChar(aBitmap32.ScanLine[y]);
  2207. BGRA32ToRGBA32(pSrc, pDest, Width);
  2208. Dec(pDest, Width * 4);
  2209. end;
  2210. end;
  2211. end;
  2212. {$ENDIF}
  2213. procedure TGLImage.AssignFromPngImage(aPngImage: TPngImage);
  2214. var
  2215. i, j: Integer;
  2216. SourceScan: PRGBLine;
  2217. DestScan: PGLPixel32Array;
  2218. AlphaScan: VCL.Imaging.Pngimage.PByteArray;
  2219. Pixel: Integer;
  2220. begin
  2221. if (aPngImage.Width and 3) > 0 then
  2222. aPngImage.Resize((aPngImage.Width and $FFFC) + 4, aPngImage.Height);
  2223. UnMipmap;
  2224. FLOD[0].Width := aPngImage.Width;
  2225. FLOD[0].Height := aPngImage.Height;
  2226. FLOD[0].Depth := 0;
  2227. fColorFormat := GL_RGBA;
  2228. fInternalFormat := tfRGBA8;
  2229. fDataType := GL_UNSIGNED_BYTE;
  2230. fElementSize := 4;
  2231. fCubeMap := False;
  2232. fTextureArray := False;
  2233. ReallocMem(fData, DataSize);
  2234. FBlank := False;
  2235. case aPngImage.Header.ColorType of
  2236. { Direct ScanLine (24 Bits) }
  2237. COLOR_RGB, COLOR_RGBALPHA: for j := 1 to aPngImage.Height do
  2238. begin
  2239. SourceScan := aPngImage.Scanline[aPngImage.Height - j];
  2240. AlphaScan := aPngImage.AlphaScanline[aPngImage.Height - j];
  2241. DestScan := ScanLine[Pred(j)];
  2242. for i := 0 to Pred(aPngImage.Width) do
  2243. begin
  2244. DestScan^[i].r := SourceScan^[i].rgbtRed;
  2245. DestScan^[i].g := SourceScan^[i].rgbtGreen;
  2246. DestScan^[i].b := SourceScan^[i].rgbtBlue;
  2247. if Assigned(AlphaScan) then
  2248. DestScan^[i].a := AlphaScan^[i]
  2249. else
  2250. DestScan^[i].a := $FF;
  2251. end;
  2252. end;
  2253. else
  2254. // Internal Decode TColor - Palette
  2255. for j := 1 to aPngImage.Height do
  2256. begin
  2257. AlphaScan := aPngImage.AlphaScanline[aPngImage.Height - j];
  2258. DestScan := ScanLine[Pred(j)];
  2259. for i := 0 to Pred(aPngImage.Width) do
  2260. begin
  2261. Pixel := aPngImage.Pixels[i, aPngImage.Height - j];
  2262. DestScan^[i].r := Pixel and $FF;
  2263. DestScan^[i].g := (Pixel shr 8) and $FF;
  2264. DestScan^[i].b := (Pixel shr 16) and $FF;
  2265. if Assigned(AlphaScan) then
  2266. DestScan^[i].a := AlphaScan^[i]
  2267. else
  2268. DestScan^[i].a := $FF;
  2269. end;
  2270. end;
  2271. end;
  2272. end;
  2273. procedure TGLImage.AssignFromTexture2D(textureHandle: Cardinal);
  2274. var
  2275. oldTex: Cardinal;
  2276. begin
  2277. UnMipmap;
  2278. with CurrentGLContext.GLStates do
  2279. begin
  2280. oldTex := TextureBinding[ActiveTexture, ttTexture2D];
  2281. TextureBinding[ActiveTexture, ttTexture2D] := textureHandle;
  2282. gl.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, @FLOD[0].Width);
  2283. gl.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, @FLOD[0].Height);
  2284. FLOD[0].Depth := 0;
  2285. fColorFormat := GL_RGBA;
  2286. fInternalFormat := tfRGBA8;
  2287. fDataType := GL_UNSIGNED_BYTE;
  2288. fElementSize := 4;
  2289. fCubeMap := False;
  2290. fTextureArray := False;
  2291. ReallocMem(fData, DataSize);
  2292. gl.GetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, fData);
  2293. FBlank := False;
  2294. TextureBinding[ActiveTexture, ttTexture2D] := oldTex;
  2295. end;
  2296. end;
  2297. procedure TGLImage.AssignFromTexture2D(textureHandle: TGLTextureHandle);
  2298. var
  2299. oldContext: TGLContext;
  2300. contextActivate: Boolean;
  2301. begin
  2302. if Assigned(textureHandle) and (textureHandle.Handle <> 0) then
  2303. begin
  2304. oldContext := CurrentGLContext;
  2305. contextActivate := (oldContext <> textureHandle.RenderingContext);
  2306. if contextActivate then
  2307. begin
  2308. if Assigned(oldContext) then
  2309. oldContext.Deactivate;
  2310. textureHandle.RenderingContext.Activate;
  2311. end;
  2312. try
  2313. AssignFromTexture2D(textureHandle.Handle);
  2314. finally
  2315. if contextActivate then
  2316. begin
  2317. textureHandle.RenderingContext.Deactivate;
  2318. if Assigned(oldContext) then
  2319. oldContext.Activate;
  2320. end;
  2321. end;
  2322. end
  2323. else
  2324. begin
  2325. // Make image empty
  2326. UnMipmap;
  2327. FLOD[0].Width := 0;
  2328. FLOD[0].Height := 0;
  2329. FLOD[0].Depth := 0;
  2330. fColorFormat := GL_RGBA;
  2331. fInternalFormat := tfRGBA8;
  2332. fDataType := GL_UNSIGNED_BYTE;
  2333. fElementSize := 4;
  2334. fCubeMap := False;
  2335. fTextureArray := False;
  2336. ReallocMem(fData, DataSize);
  2337. end;
  2338. end;
  2339. function TGLImage.Create32BitsBitmap: TBitmap;
  2340. var
  2341. y, x, x4: Integer;
  2342. pSrc, pDest: PAnsiChar;
  2343. begin
  2344. if FBlank then
  2345. begin
  2346. Result := nil;
  2347. Exit;
  2348. end;
  2349. Narrow;
  2350. Result := TBitmap.Create;
  2351. Result.PixelFormat := pf32bit;
  2352. Result.Width := Width;
  2353. Result.Height := Height;
  2354. if Height > 0 then
  2355. begin
  2356. pSrc := @PAnsiChar(fData)[Width * 4 * (Height - 1)];
  2357. for y := 0 to Height - 1 do
  2358. begin
  2359. pDest := Result.ScanLine[y];
  2360. for x := 0 to Width - 1 do
  2361. begin
  2362. x4 := x * 4;
  2363. pDest[x4 + 0] := pSrc[x4 + 2];
  2364. pDest[x4 + 1] := pSrc[x4 + 1];
  2365. pDest[x4 + 2] := pSrc[x4 + 0];
  2366. pDest[x4 + 3] := pSrc[x4 + 3];
  2367. end;
  2368. Dec(pSrc, Width * 4);
  2369. end;
  2370. end;
  2371. end;
  2372. procedure TGLImage.SetWidth(val: Integer);
  2373. begin
  2374. if val <> FLOD[0].Width then
  2375. begin
  2376. Assert(val >= 0);
  2377. FLOD[0].Width := val;
  2378. FBlank := True;
  2379. end;
  2380. end;
  2381. procedure TGLImage.SetHeight(const val: Integer);
  2382. begin
  2383. if val <> FLOD[0].Height then
  2384. begin
  2385. Assert(val >= 0);
  2386. FLOD[0].Height := val;
  2387. FBlank := True;
  2388. end;
  2389. end;
  2390. procedure TGLImage.SetDepth(const val: Integer);
  2391. begin
  2392. if val <> FLOD[0].Depth then
  2393. begin
  2394. Assert(val >= 0);
  2395. FLOD[0].Depth := val;
  2396. FBlank := True;
  2397. end;
  2398. end;
  2399. procedure TGLImage.SetCubeMap(const val: Boolean);
  2400. begin
  2401. if val <> fCubeMap then
  2402. begin
  2403. fCubeMap := val;
  2404. FBlank := True;
  2405. end;
  2406. end;
  2407. procedure TGLImage.SetArray(const val: Boolean);
  2408. begin
  2409. if val <> fTextureArray then
  2410. begin
  2411. fTextureArray := val;
  2412. FBlank := True;
  2413. end;
  2414. end;
  2415. procedure TGLImage.SetColorFormatDataType(const AColorFormat, ADataType: Cardinal);
  2416. begin
  2417. if FBlank then
  2418. begin
  2419. fDataType := ADataType;
  2420. fColorFormat := AColorFormat;
  2421. Exit;
  2422. end;
  2423. fOldDataType := fDataType;
  2424. fOldColorFormat := fColorFormat;
  2425. fDataType := ADataType;
  2426. fColorFormat := AColorFormat;
  2427. fElementSize := GetTextureElementSize(fColorFormat, fDataType);
  2428. DataConvertTask;
  2429. end;
  2430. function TGLImage.GetScanLine(index: Integer): PGLPixel32Array;
  2431. begin
  2432. Narrow;
  2433. Result := PGLPixel32Array(@fData[index * GetWidth]);
  2434. end;
  2435. procedure TGLImage.SetAlphaFromIntensity;
  2436. var
  2437. i: Integer;
  2438. begin
  2439. Narrow;
  2440. for i := 0 to (DataSize div 4) - 1 do
  2441. with FData^[i] do
  2442. a := (Integer(r) + Integer(g) + Integer(b)) div 3;
  2443. end;
  2444. procedure TGLImage.SetAlphaTransparentForColor(const aColor: TColor);
  2445. var
  2446. color: TGLPixel24;
  2447. begin
  2448. color.r := GetRValue(aColor);
  2449. color.g := GetGValue(aColor);
  2450. color.b := GetBValue(aColor);
  2451. SetAlphaTransparentForColor(color);
  2452. end;
  2453. procedure TGLImage.SetAlphaTransparentForColor(const aColor: TGLPixel32);
  2454. var
  2455. color: TGLPixel24;
  2456. begin
  2457. color.r := aColor.r;
  2458. color.g := aColor.g;
  2459. color.b := aColor.b;
  2460. SetAlphaTransparentForColor(color);
  2461. end;
  2462. procedure TGLImage.SetAlphaTransparentForColor(const aColor: TGLPixel24);
  2463. var
  2464. i: Integer;
  2465. intCol: Integer;
  2466. begin
  2467. Narrow;
  2468. intCol := (PInteger(@aColor)^) and $FFFFFF;
  2469. for i := 0 to (DataSize div 4) - 1 do
  2470. if PInteger(@FData[i])^ and $FFFFFF = intCol then
  2471. FData^[i].a := 0
  2472. else
  2473. FData^[i].a := 255;
  2474. end;
  2475. procedure TGLImage.SetAlphaToValue(const aValue: Byte);
  2476. var
  2477. i: Integer;
  2478. begin
  2479. Narrow;
  2480. for i := 0 to (DataSize div 4) - 1 do
  2481. FData^[i].a := aValue
  2482. end;
  2483. procedure TGLImage.SetAlphaToFloatValue(const aValue: Single);
  2484. begin
  2485. SetAlphaToValue(Byte(Trunc(aValue * 255) and 255));
  2486. end;
  2487. procedure TGLImage.InvertAlpha;
  2488. var
  2489. i: Integer;
  2490. begin
  2491. Narrow;
  2492. for i := (DataSize div 4) - 1 downto 0 do
  2493. FData^[i].a := 255 - FData^[i].a;
  2494. end;
  2495. procedure TGLImage.SqrtAlpha;
  2496. var
  2497. i: Integer;
  2498. sqrt255Array: PSqrt255Array;
  2499. begin
  2500. Narrow;
  2501. sqrt255Array := GetSqrt255Array;
  2502. for i := 0 to (DataSize div 4) - 1 do
  2503. with FData^[i] do
  2504. a := sqrt255Array^[(Integer(r) + Integer(g) + Integer(b)) div 3];
  2505. end;
  2506. procedure TGLImage.BrightnessCorrection(const factor: Single);
  2507. begin
  2508. if Assigned(FData) then
  2509. begin
  2510. Narrow;
  2511. BrightenRGBAArray(Data, DataSize div 4, factor);
  2512. end;
  2513. end;
  2514. procedure TGLImage.GammaCorrection(const gamma: Single);
  2515. begin
  2516. if Assigned(FData) then
  2517. begin
  2518. Narrow;
  2519. GammaCorrectRGBAArray(Data, DataSize div 4, gamma);
  2520. end;
  2521. end;
  2522. procedure TGLImage.DownSampleByFactor2;
  2523. type
  2524. T2Pixel32 = packed array[0..1] of TGLPixel32;
  2525. P2Pixel32 = ^T2Pixel32;
  2526. procedure ProcessRowPascal(pDest: PGLPixel32; pLineA, pLineB: P2Pixel32; n:
  2527. Integer);
  2528. var
  2529. i: Integer;
  2530. begin
  2531. for i := 0 to n - 1 do
  2532. begin
  2533. pDest^.r := (pLineA^[0].r + pLineA^[1].r + pLineB^[0].r +
  2534. pLineB^[1].r) shr 2;
  2535. pDest^.g := (pLineA^[0].g + pLineA^[1].g + pLineB^[0].g +
  2536. pLineB^[1].g) shr 2;
  2537. pDest^.b := (pLineA^[0].b + pLineA^[1].b + pLineB^[0].b +
  2538. pLineB^[1].b) shr 2;
  2539. pDest^.a := (pLineA^[0].a + pLineA^[1].a + pLineB^[0].a +
  2540. pLineB^[1].a) shr 2;
  2541. Inc(pLineA);
  2542. Inc(pLineB);
  2543. Inc(pDest);
  2544. end;
  2545. end; // }
  2546. var
  2547. y, w2, h2: Integer;
  2548. pDest: PGLPixel32;
  2549. pLineA, pLineB: P2Pixel32;
  2550. begin
  2551. if (GetWidth <= 1) or (GetHeight <= 1) then
  2552. Exit;
  2553. Narrow;
  2554. w2 := GetWidth shr 1;
  2555. h2 := GetHeight shr 1;
  2556. pDest := @fData[0];
  2557. pLineA := @fData[0];
  2558. pLineB := @fData[Width];
  2559. for y := 0 to h2 - 1 do
  2560. begin
  2561. ProcessRowPascal(pDest, pLineA, pLineB, w2);
  2562. Inc(pDest, w2);
  2563. Inc(pLineA, Width);
  2564. Inc(pLineB, Width);
  2565. end;
  2566. FLOD[0].Width := w2;
  2567. FLOD[0].Height := h2;
  2568. ReallocMem(fData, DataSize);
  2569. end;
  2570. procedure TGLImage.ReadPixels(const area: TRect);
  2571. begin
  2572. UnMipmap;
  2573. FLOD[0].Width := (area.Right - area.Left) and $FFFC;
  2574. FLOD[0].Height := (area.Bottom - area.Top);
  2575. FLOD[0].Depth := 0;
  2576. fColorFormat := GL_RGBA;
  2577. fInternalFormat := tfRGBA8;
  2578. fDataType := GL_UNSIGNED_BYTE;
  2579. fElementSize := 4;
  2580. fCubeMap := false;
  2581. fTextureArray := false;
  2582. fBlank := false;
  2583. ReallocMem(FData, DataSize);
  2584. gl.ReadPixels(0, 0, GetWidth, GetHeight, GL_RGBA, GL_UNSIGNED_BYTE, FData);
  2585. end;
  2586. procedure TGLImage.DrawPixels(const x, y: Single);
  2587. begin
  2588. if fBlank or IsEmpty then
  2589. Exit;
  2590. // Assert(not CurrentGLContext.GLStates.ForwardContext);
  2591. gl.RasterPos2f(x, y);
  2592. gl.DrawPixels(Width, Height, fColorFormat, fDataType, FData);
  2593. end;
  2594. procedure TGLImage.GrayScaleToNormalMap(const scale: Single;
  2595. wrapX: Boolean = True; wrapY: Boolean = True);
  2596. var
  2597. x, y: Integer;
  2598. dcx, dcy: Single;
  2599. invLen: Single;
  2600. maskX, maskY: Integer;
  2601. curRow, nextRow, prevRow: PGLPixel32Array;
  2602. normalMapBuffer: PGLPixel32Array;
  2603. p: PGLPixel32;
  2604. begin
  2605. if Assigned(FData) then
  2606. begin
  2607. Narrow;
  2608. GetMem(normalMapBuffer, DataSize);
  2609. try
  2610. maskX := Width - 1;
  2611. maskY := Height - 1;
  2612. p := @normalMapBuffer[0];
  2613. for y := 0 to Height - 1 do
  2614. begin
  2615. curRow := GetScanLine(y);
  2616. if wrapY then
  2617. begin
  2618. prevRow := GetScanLine((y - 1) and maskY);
  2619. nextRow := GetScanLine((y + 1) and maskY);
  2620. end
  2621. else
  2622. begin
  2623. if y > 0 then
  2624. prevRow := GetScanLine(y - 1)
  2625. else
  2626. prevRow := curRow;
  2627. if y < Height - 1 then
  2628. nextRow := GetScanLine(y + 1)
  2629. else
  2630. nextRow := curRow;
  2631. end;
  2632. for x := 0 to Width - 1 do
  2633. begin
  2634. if wrapX then
  2635. dcx := scale * (curRow^[(x - 1) and maskX].g - curRow^[(x + 1) and
  2636. maskX].g)
  2637. else
  2638. begin
  2639. if x = 0 then
  2640. dcx := scale * (curRow^[x].g - curRow^[x + 1].g)
  2641. else if x < Width - 1 then
  2642. dcx := scale * (curRow^[x - 1].g - curRow^[x].g)
  2643. else
  2644. dcx := scale * (curRow^[x - 1].g - curRow^[x + 1].g);
  2645. end;
  2646. dcy := scale * (prevRow^[x].g - nextRow^[x].g);
  2647. invLen := 127 * RSqrt(dcx * dcx + dcy * dcy + 1);
  2648. with p^ do
  2649. begin
  2650. r := Integer(Round(128 + ClampValue(dcx * invLen, -128, 127)));
  2651. g := Integer(Round(128 + ClampValue(dcy * invLen, -128, 127)));
  2652. b := Integer(Round(128 + ClampValue(invLen, -128, 127)));
  2653. a := 255;
  2654. end;
  2655. Inc(p);
  2656. end;
  2657. end;
  2658. Move(normalMapBuffer^, FData^, DataSize);
  2659. finally
  2660. FreeMem(normalMapBuffer);
  2661. end;
  2662. end;
  2663. end;
  2664. procedure TGLImage.NormalizeNormalMap;
  2665. var
  2666. x, y: Integer;
  2667. sr, sg, sb: Single;
  2668. invLen: Single;
  2669. curRow: PGLPixel32Array;
  2670. p: PGLPixel32;
  2671. const
  2672. cInv128: Single = 1 / 128;
  2673. begin
  2674. if not IsEmpty and not Blank then
  2675. begin
  2676. Narrow;
  2677. for y := 0 to Height - 1 do
  2678. begin
  2679. curRow := @FData[y * GetWidth];
  2680. for x := 0 to GetWidth - 1 do
  2681. begin
  2682. p := @curRow[x];
  2683. sr := (p^.r - 128) * cInv128;
  2684. sg := (p^.g - 128) * cInv128;
  2685. sb := (p^.b - 128) * cInv128;
  2686. invLen := RSqrt(sr * sr + sg * sg + sb * sb);
  2687. p^.r := Round(128 + 127 * ClampValue(sr * invLen, -1, 1));
  2688. p^.g := Round(128 + 127 * ClampValue(sg * invLen, -1, 1));
  2689. p^.b := Round(128 + 127 * ClampValue(sb * invLen, -1, 1));
  2690. end;
  2691. end;
  2692. end;
  2693. end;
  2694. procedure TGLImage.SetBlank(const Value: boolean);
  2695. begin
  2696. if not Value and not IsEmpty then
  2697. ReallocMem(FData, DataSize);
  2698. FBlank := Value;
  2699. end;
  2700. procedure TGLImage.AssignToBitmap(aBitmap: TBitmap);
  2701. var
  2702. y: integer;
  2703. pSrc, pDest: PAnsiChar;
  2704. begin
  2705. Narrow;
  2706. aBitmap.Width := GetWidth;
  2707. aBitmap.Height := GetHeight;
  2708. aBitmap.PixelFormat := pf32bit;
  2709. if FVerticalReverseOnAssignFromBitmap then
  2710. begin
  2711. for y := 0 to GetHeight - 1 do
  2712. begin
  2713. pSrc := @PAnsiChar(FData)[y * (GetWidth * 4)];
  2714. pDest := aBitmap.ScanLine[y];
  2715. BGRA32ToRGBA32(pSrc, pDest, GetWidth);
  2716. end;
  2717. end
  2718. else
  2719. begin
  2720. for y := 0 to GetHeight - 1 do
  2721. begin
  2722. pSrc := @PAnsiChar(FData)[y * (GetWidth * 4)];
  2723. pDest := aBitmap.ScanLine[GetHeight - 1 - y];
  2724. BGRA32ToRGBA32(pSrc, pDest, GetWidth);
  2725. end;
  2726. end;
  2727. end;
  2728. procedure TGLImage.GenerateMipmap(AFilter: TImageFilterFunction);
  2729. begin
  2730. if not FBlank then
  2731. inherited GenerateMipmap(AFilter);
  2732. end;
  2733. procedure TGLImage.UnMipmap;
  2734. begin
  2735. inherited UnMipmap;
  2736. if not (fBlank or IsEmpty) then
  2737. ReallocMem(FData, DataSize);
  2738. end;
  2739. procedure TGLImage.DataConvertTask;
  2740. var
  2741. oldLOD: TGLImagePiramid;
  2742. newData: Pointer;
  2743. ptr: PByte;
  2744. L: TGLImageLODRange;
  2745. d: Integer;
  2746. begin
  2747. oldLOD := FLOD;
  2748. if IsVolume then
  2749. begin
  2750. // Message Hint 'TGLImage.DataConvertTask not yet implemented for volume images'
  2751. end
  2752. else
  2753. begin
  2754. GetMem(newData, DataSize);
  2755. d := MaxInteger(GetDepth, 1);
  2756. try
  2757. for L := FLevelCount - 1 downto 0 do
  2758. begin
  2759. ptr := newData;
  2760. Inc(ptr, oldLOD[L].Offset);
  2761. ConvertImage(GetLevelAddress(L), ptr, fOldColorFormat, fColorFormat,
  2762. fOldDataType, fDataType, oldLOD[L].Width, oldLOD[L].Height * d);
  2763. end;
  2764. FreeMem(fData);
  2765. fData := newData;
  2766. except
  2767. FreeMem(newData);
  2768. GLSLogger.LogError(Format(strCantConvertImg, [ClassName]));
  2769. SetErrorImage;
  2770. end;
  2771. end;
  2772. end;
  2773. function GraphicClassForExtension(const anExtension: string): TGraphicClass;
  2774. var
  2775. i: integer;
  2776. sl: TStringList;
  2777. buf: string;
  2778. begin
  2779. Result := nil;
  2780. if anExtension = '' then
  2781. Exit;
  2782. if anExtension[1] = '.' then
  2783. buf := Copy(anExtension, 2, MaxInt)
  2784. else
  2785. buf := anExtension;
  2786. sl := TStringList.Create;
  2787. try
  2788. HackTPictureRegisteredFormats(sl);
  2789. i := sl.IndexOfName(buf);
  2790. if i >= 0 then
  2791. Result := TGraphicClass(sl.Objects[i]);
  2792. finally
  2793. sl.Free;
  2794. end;
  2795. end;
  2796. type
  2797. PFileFormat = ^TFileFormat;
  2798. TFileFormat = record
  2799. GraphicClass: TGraphicClass;
  2800. Extension: string;
  2801. Description: string;
  2802. DescResID: integer;
  2803. end;
  2804. // HackTPictureRegisteredFormats
  2805. {$IFOPT R+}
  2806. {$DEFINE HackTPictureRegisteredFormats_Disable_RangeCheck}
  2807. {$R-}
  2808. {$ENDIF}
  2809. procedure HackTPictureRegisteredFormats(destList: TStrings);
  2810. var
  2811. pRegisterFileFormat, pCallGetFileFormat, pGetFileFormats, pFileFormats: PAnsiChar;
  2812. iCall: cardinal;
  2813. i: integer;
  2814. list: TList;
  2815. fileFormat: PFileFormat;
  2816. begin
  2817. {$MESSAGE WARN 'HackTPictureRegisteredFormats will crash when Graphics.pas is compiled with the 'Use Debug DCUs' option'}
  2818. pRegisterFileFormat := PAnsiChar(@TPicture.RegisterFileFormat);
  2819. if pRegisterFileFormat[0] = #$FF then // in case of BPL redirector
  2820. pRegisterFileFormat := PAnsiChar(PCardinal(PCardinal(@pRegisterFileFormat[2])^)^);
  2821. pCallGetFileFormat := @pRegisterFileFormat[16];
  2822. iCall := PCardinal(pCallGetFileFormat)^;
  2823. pGetFileFormats := @pCallGetFileFormat[iCall + 4];
  2824. pFileFormats := PAnsiChar(PCardinal(@pGetFileFormats[2])^);
  2825. list := TList(PCardinal(pFileFormats)^);
  2826. if list <> nil then
  2827. begin
  2828. for i := 0 to list.Count - 1 do
  2829. begin
  2830. fileFormat := PFileFormat(list[i]);
  2831. destList.AddObject(fileFormat.Extension + '=' + fileFormat.Description,
  2832. TObject(fileFormat.GraphicClass));
  2833. end;
  2834. end;
  2835. end;
  2836. {$IFDEF HackTPictureRegisteredFormats_Disable_RangeCheck}
  2837. {$R+}
  2838. {$UNDEF HackTPictureRegisteredFormats_Disable_RangeCheck}
  2839. {$ENDIF}
  2840. //---------------------------------------------------
  2841. initialization
  2842. //---------------------------------------------------
  2843. finalization
  2844. FreeAndNil(vRasterFileFormats);
  2845. end.