GLGraphics.pas 129 KB

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