Want more features on Pastebin? Sign Up, it's FREE!
Guest

vanjalolz

By: a guest on Dec 1st, 2007  |  syntax: C  |  size: 14.39 KB  |  views: 65  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.  *  tga.h
  3.  *
  4.  *
  5.  */
  6. #include "config.h"
  7. #ifdef __APPLE__
  8. #include <GLUT/glut.h>
  9. #else
  10. #include <GL/glut.h>
  11. #endif
  12.  
  13. GLuint
  14. loadTGATexture (const char *filename, GLuint texid = 0);
  15.  
  16. /*
  17.  *  tga.cpp
  18.  *
  19.  */
  20.  
  21. #include "tga.h"
  22.  
  23.  
  24. /*
  25.  * tga.c -- tga texture loader
  26.  * last modification: dec. 15, 2005
  27.  *
  28.  * Copyright (c) 2005 David HENRY
  29.  *
  30.  * Permission is hereby granted, free of charge, to any person
  31.  * obtaining a copy of this software and associated documentation
  32.  * files (the "Software"), to deal in the Software without
  33.  * restriction, including without limitation the rights to use,
  34.  * copy, modify, merge, publish, distribute, sublicense, and/or
  35.  * sell copies of the Software, and to permit persons to whom the
  36.  * Software is furnished to do so, subject to the following conditions:
  37.  *
  38.  * The above copyright notice and this permission notice shall be
  39.  * included in all copies or substantial portions of the Software.
  40.  *
  41.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  42.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  43.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  44.  * NONINFRINGEMENT.
  45.  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  46.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  47.  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  48.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  49.  *
  50.  * gcc -Wall -ansi -L/usr/X11R6/lib -lGL -lGLU -lglut tga.c -o tga
  51.  */
  52.  
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55.  
  56.  
  57. /* OpenGL texture info */
  58. typedef struct
  59. {
  60.         GLsizei width;
  61.         GLsizei height;
  62.        
  63.         GLenum format;
  64.         GLint   internalFormat;
  65.         GLuint id;
  66.        
  67.         GLubyte *texels;
  68.        
  69. } gl_texture_t;
  70.  
  71.  
  72. #pragma pack(push, 1)
  73. /* tga header */
  74. typedef struct
  75. {
  76.         GLubyte id_lenght;          /* size of image id */
  77.         GLubyte colormap_type;      /* 1 is has a colormap */
  78.         GLubyte image_type;         /* compression type */
  79.        
  80.         short   cm_first_entry;       /* colormap origin */
  81.         short   cm_length;            /* colormap length */
  82.         GLubyte cm_size;            /* colormap size */
  83.        
  84.         short   x_origin;             /* bottom left x coord origin */
  85.         short   y_origin;             /* bottom left y coord origin */
  86.        
  87.         short   width;                /* picture width (in pixels) */
  88.         short   height;               /* picture height (in pixels) */
  89.        
  90.         GLubyte pixel_depth;        /* bits per pixel: 8, 16, 24 or 32 */
  91.         GLubyte image_descriptor;   /* 24 bits = 0x00; 32 bits = 0x80 */
  92.        
  93. } tga_header_t;
  94. #pragma pack(pop)
  95.  
  96.  
  97. /* texture id for exemple */
  98. GLuint texId = 0;
  99.  
  100.  
  101. void
  102. GetTextureInfo (tga_header_t *header, gl_texture_t *texinfo)
  103. {
  104.         texinfo->width = header->width;
  105.         texinfo->height = header->height;
  106.        
  107.         switch (header->image_type)
  108.     {
  109.                 case 3:  /* grayscale 8 bits */
  110.                 case 11: /* grayscale 8 bits (RLE) */
  111.                 {
  112.                         if (header->pixel_depth == 8)
  113.                         {
  114.                                 texinfo->format = GL_LUMINANCE;
  115.                                 texinfo->internalFormat = 1;
  116.                         }
  117.                         else /* 16 bits */
  118.                         {
  119.                                 texinfo->format = GL_LUMINANCE_ALPHA;
  120.                                 texinfo->internalFormat = 2;
  121.                         }
  122.                        
  123.                         break;
  124.                 }
  125.                        
  126.                 case 1:  /* 8 bits color index */
  127.                 case 2:  /* BGR 16-24-32 bits */
  128.                 case 9:  /* 8 bits color index (RLE) */
  129.                 case 10: /* BGR 16-24-32 bits (RLE) */
  130.                 {
  131.                         /* 8 bits and 16 bits images will be converted to 24 bits */
  132.                         if (header->pixel_depth <= 24)
  133.                         {
  134.                                 texinfo->format = GL_RGB;
  135.                                 texinfo->internalFormat = 3;
  136.                         }
  137.                         else /* 32 bits */
  138.                         {
  139.                                 texinfo->format = GL_RGBA;
  140.                                 texinfo->internalFormat = 4;
  141.                         }
  142.                        
  143.                         break;
  144.                 }
  145.     }
  146. }
  147.  
  148.  
  149. void
  150. ReadTGA8bits (FILE *fp, GLubyte *colormap, gl_texture_t *texinfo)
  151. {
  152.         int i;
  153.         GLubyte color;
  154.        
  155.         for (i = 0; i < texinfo->width * texinfo->height; ++i)
  156.     {
  157.                 /* read index color byte */
  158.                 color = (GLubyte)fgetc (fp);
  159.                
  160.                 /* convert to RGB 24 bits */
  161.                 texinfo->texels[(i * 3) + 2] = colormap[(color * 3) + 0];
  162.                 texinfo->texels[(i * 3) + 1] = colormap[(color * 3) + 1];
  163.                 texinfo->texels[(i * 3) + 0] = colormap[(color * 3) + 2];
  164.     }
  165. }
  166.  
  167.  
  168. void
  169. ReadTGA16bits (FILE *fp, gl_texture_t *texinfo)
  170. {
  171.         int i;
  172.         unsigned short color;
  173.        
  174.         for (i = 0; i < texinfo->width * texinfo->height; ++i)
  175.     {
  176.                 /* read color word */
  177.                 color = fgetc (fp) + (fgetc (fp) << 8);
  178.                
  179.                 /* convert BGR to RGB */
  180.                 texinfo->texels[(i * 3) + 0] = (GLubyte)(((color & 0x7C00) >> 10) << 3);
  181.                 texinfo->texels[(i * 3) + 1] = (GLubyte)(((color & 0x03E0) >>  5) << 3);
  182.                 texinfo->texels[(i * 3) + 2] = (GLubyte)(((color & 0x001F) >>  0) << 3);
  183.     }
  184. }
  185.  
  186.  
  187. void
  188. ReadTGA24bits (FILE *fp, gl_texture_t *texinfo)
  189. {
  190.         int i;
  191.        
  192.         for (i = 0; i < texinfo->width * texinfo->height; ++i)
  193.     {
  194.                 /* read and convert BGR to RGB */
  195.                 texinfo->texels[(i * 3) + 2] = (GLubyte)fgetc (fp);
  196.                 texinfo->texels[(i * 3) + 1] = (GLubyte)fgetc (fp);
  197.                 texinfo->texels[(i * 3) + 0] = (GLubyte)fgetc (fp);
  198.     }
  199. }
  200.  
  201.  
  202. void
  203. ReadTGA32bits (FILE *fp, gl_texture_t *texinfo)
  204. {
  205.         int i;
  206.        
  207.         for (i = 0; i < texinfo->width * texinfo->height; ++i)
  208.     {
  209.                 /* read and convert BGRA to RGBA */
  210.                 texinfo->texels[(i * 4) + 2] = (GLubyte)fgetc (fp);
  211.                 texinfo->texels[(i * 4) + 1] = (GLubyte)fgetc (fp);
  212.                 texinfo->texels[(i * 4) + 0] = (GLubyte)fgetc (fp);
  213.                 texinfo->texels[(i * 4) + 3] = (GLubyte)fgetc (fp);
  214.     }
  215. }
  216.  
  217.  
  218. void
  219. ReadTGAgray8bits (FILE *fp, gl_texture_t *texinfo)
  220. {
  221.         int i;
  222.        
  223.         for (i = 0; i < texinfo->width * texinfo->height; ++i)
  224.     {
  225.                 /* read grayscale color byte */
  226.                 texinfo->texels[i] = (GLubyte)fgetc (fp);
  227.     }
  228. }
  229.  
  230.  
  231. void
  232. ReadTGAgray16bits (FILE *fp, gl_texture_t *texinfo)
  233. {
  234.         int i;
  235.        
  236.         for (i = 0; i < texinfo->width * texinfo->height; ++i)
  237.     {
  238.                 /* read grayscale color + alpha channel bytes */
  239.                 texinfo->texels[(i * 2) + 0] = (GLubyte)fgetc (fp);
  240.                 texinfo->texels[(i * 2) + 1] = (GLubyte)fgetc (fp);
  241.     }
  242. }
  243.  
  244.  
  245. void
  246. ReadTGA8bitsRLE (FILE *fp, GLubyte *colormap, gl_texture_t *texinfo)
  247. {
  248.         int i, size;
  249.         GLubyte color;
  250.         GLubyte packet_header;
  251.         GLubyte *ptr = texinfo->texels;
  252.        
  253.         while (ptr < texinfo->texels + (texinfo->width * texinfo->height) * 3)
  254.     {
  255.                 /* read first byte */
  256.                 packet_header = (GLubyte)fgetc (fp);
  257.                 size = 1 + (packet_header & 0x7f);
  258.                
  259.                 if (packet_header & 0x80)
  260.                 {
  261.                         /* run-length packet */
  262.                         color = (GLubyte)fgetc (fp);
  263.                        
  264.                         for (i = 0; i < size; ++i, ptr += 3)
  265.                         {
  266.                                 ptr[0] = colormap[(color * 3) + 2];
  267.                                 ptr[1] = colormap[(color * 3) + 1];
  268.                                 ptr[2] = colormap[(color * 3) + 0];
  269.                         }
  270.                 }
  271.                 else
  272.                 {
  273.                         /* non run-length packet */
  274.                         for (i = 0; i < size; ++i, ptr += 3)
  275.                         {
  276.                                 color = (GLubyte)fgetc (fp);
  277.                                
  278.                                 ptr[0] = colormap[(color * 3) + 2];
  279.                                 ptr[1] = colormap[(color * 3) + 1];
  280.                                 ptr[2] = colormap[(color * 3) + 0];
  281.                         }
  282.                 }
  283.     }
  284. }
  285.  
  286.  
  287. void
  288. ReadTGA16bitsRLE (FILE *fp, gl_texture_t *texinfo)
  289. {
  290.         int i, size;
  291.         unsigned short color;
  292.         GLubyte packet_header;
  293.         GLubyte *ptr = texinfo->texels;
  294.        
  295.         while (ptr < texinfo->texels + (texinfo->width * texinfo->height) * 3)
  296.     {
  297.                 /* read first byte */
  298.                 packet_header = fgetc (fp);
  299.                 size = 1 + (packet_header & 0x7f);
  300.                
  301.                 if (packet_header & 0x80)
  302.                 {
  303.                         /* run-length packet */
  304.                         color = fgetc (fp) + (fgetc (fp) << 8);
  305.                        
  306.                         for (i = 0; i < size; ++i, ptr += 3)
  307.                         {
  308.                                 ptr[0] = (GLubyte)(((color & 0x7C00) >> 10) << 3);
  309.                                 ptr[1] = (GLubyte)(((color & 0x03E0) >>  5) << 3);
  310.                                 ptr[2] = (GLubyte)(((color & 0x001F) >>  0) << 3);
  311.                         }
  312.                 }
  313.                 else
  314.                 {
  315.                         /* non run-length packet */
  316.                         for (i = 0; i < size; ++i, ptr += 3)
  317.                         {
  318.                                 color = fgetc (fp) + (fgetc (fp) << 8);
  319.                                
  320.                                 ptr[0] = (GLubyte)(((color & 0x7C00) >> 10) << 3);
  321.                                 ptr[1] = (GLubyte)(((color & 0x03E0) >>  5) << 3);
  322.                                 ptr[2] = (GLubyte)(((color & 0x001F) >>  0) << 3);
  323.                         }
  324.                 }
  325.     }
  326. }
  327.  
  328.  
  329. void
  330. ReadTGA24bitsRLE (FILE *fp, gl_texture_t *texinfo)
  331. {
  332.         int i, size;
  333.         GLubyte rgb[3];
  334.         GLubyte packet_header;
  335.         GLubyte *ptr = texinfo->texels;
  336.        
  337.         while (ptr < texinfo->texels + (texinfo->width * texinfo->height) * 3)
  338.     {
  339.                 /* read first byte */
  340.                 packet_header = (GLubyte)fgetc (fp);
  341.                 size = 1 + (packet_header & 0x7f);
  342.                
  343.                 if (packet_header & 0x80)
  344.                 {
  345.                         /* run-length packet */
  346.                         fread (rgb, sizeof (GLubyte), 3, fp);
  347.                        
  348.                         for (i = 0; i < size; ++i, ptr += 3)
  349.                         {
  350.                                 ptr[0] = rgb[2];
  351.                                 ptr[1] = rgb[1];
  352.                                 ptr[2] = rgb[0];
  353.                         }
  354.                 }
  355.                 else
  356.                 {
  357.                         /* non run-length packet */
  358.                         for (i = 0; i < size; ++i, ptr += 3)
  359.                         {
  360.                                 ptr[2] = (GLubyte)fgetc (fp);
  361.                                 ptr[1] = (GLubyte)fgetc (fp);
  362.                                 ptr[0] = (GLubyte)fgetc (fp);
  363.                         }
  364.                 }
  365.     }
  366. }
  367.  
  368.  
  369. void
  370. ReadTGA32bitsRLE (FILE *fp, gl_texture_t *texinfo)
  371. {
  372.         int i, size;
  373.         GLubyte rgba[4];
  374.         GLubyte packet_header;
  375.         GLubyte *ptr = texinfo->texels;
  376.        
  377.         while (ptr < texinfo->texels + (texinfo->width * texinfo->height) * 4)
  378.     {
  379.                 /* read first byte */
  380.                 packet_header = (GLubyte)fgetc (fp);
  381.                 size = 1 + (packet_header & 0x7f);
  382.                
  383.                 if (packet_header & 0x80)
  384.                 {
  385.                         /* run-length packet */
  386.                         fread (rgba, sizeof (GLubyte), 4, fp);
  387.                        
  388.                         for (i = 0; i < size; ++i, ptr += 4)
  389.                         {
  390.                                 ptr[0] = rgba[2];
  391.                                 ptr[1] = rgba[1];
  392.                                 ptr[2] = rgba[0];
  393.                                 ptr[3] = rgba[3];
  394.                         }
  395.                 }
  396.                 else
  397.                 {
  398.                         /* non run-length packet */
  399.                         for (i = 0; i < size; ++i, ptr += 4)
  400.                         {
  401.                                 ptr[2] = (GLubyte)fgetc (fp);
  402.                                 ptr[1] = (GLubyte)fgetc (fp);
  403.                                 ptr[0] = (GLubyte)fgetc (fp);
  404.                                 ptr[3] = (GLubyte)fgetc (fp);
  405.                         }
  406.                 }
  407.     }
  408. }
  409.  
  410.  
  411. void
  412. ReadTGAgray8bitsRLE (FILE *fp, gl_texture_t *texinfo)
  413. {
  414.         int i, size;
  415.         GLubyte color;
  416.         GLubyte packet_header;
  417.         GLubyte *ptr = texinfo->texels;
  418.        
  419.         while (ptr < texinfo->texels + (texinfo->width * texinfo->height))
  420.     {
  421.                 /* read first byte */
  422.                 packet_header = (GLubyte)fgetc (fp);
  423.                 size = 1 + (packet_header & 0x7f);
  424.                
  425.                 if (packet_header & 0x80)
  426.                 {
  427.                         /* run-length packet */
  428.                         color = (GLubyte)fgetc (fp);
  429.                        
  430.                         for (i = 0; i < size; ++i, ptr++)
  431.                                 *ptr = color;
  432.                 }
  433.                 else
  434.                 {
  435.                         /* non run-length packet */
  436.                         for (i = 0; i < size; ++i, ptr++)
  437.                                 *ptr = (GLubyte)fgetc (fp);
  438.                 }
  439.     }
  440. }
  441.  
  442.  
  443. void
  444. ReadTGAgray16bitsRLE (FILE *fp, gl_texture_t *texinfo)
  445. {
  446.         int i, size;
  447.         GLubyte color, alpha;
  448.         GLubyte packet_header;
  449.         GLubyte *ptr = texinfo->texels;
  450.        
  451.         while (ptr < texinfo->texels + (texinfo->width * texinfo->height) * 2)
  452.     {
  453.                 /* read first byte */
  454.                 packet_header = (GLubyte)fgetc (fp);
  455.                 size = 1 + (packet_header & 0x7f);
  456.                
  457.                 if (packet_header & 0x80)
  458.                 {
  459.                         /* run-length packet */
  460.                         color = (GLubyte)fgetc (fp);
  461.                         alpha = (GLubyte)fgetc (fp);
  462.                        
  463.                         for (i = 0; i < size; ++i, ptr += 2)
  464.                         {
  465.                                 ptr[0] = color;
  466.                                 ptr[1] = alpha;
  467.                         }
  468.                 }
  469.                 else
  470.                 {
  471.                         /* non run-length packet */
  472.                         for (i = 0; i < size; ++i, ptr += 2)
  473.                         {
  474.                                 ptr[0] = (GLubyte)fgetc (fp);
  475.                                 ptr[1] = (GLubyte)fgetc (fp);
  476.                         }
  477.                 }
  478.     }
  479. }
  480.  
  481.  
  482. gl_texture_t *
  483. ReadTGAFile (const char *filename)
  484. {
  485.         FILE *fp;
  486.         gl_texture_t *texinfo;
  487.         tga_header_t header;
  488.         GLubyte *colormap = NULL;
  489.        
  490.         fp = fopen (filename, "rb");
  491.         if (!fp)
  492.     {
  493.                 fprintf (stderr, "error: couldn't open \"%s\"!\n", filename);
  494.                 return NULL;
  495.     }
  496.        
  497.         /* read header */
  498.         fread (&header, sizeof (tga_header_t), 1, fp);
  499.        
  500.         texinfo = (gl_texture_t *)malloc (sizeof (gl_texture_t));
  501.         GetTextureInfo (&header, texinfo);
  502.         fseek (fp, header.id_lenght, SEEK_CUR);
  503.        
  504.         /* memory allocation */
  505.         texinfo->texels = (GLubyte *)malloc (sizeof (GLubyte) *
  506.                                                                                  texinfo->width * texinfo->height * texinfo->internalFormat);
  507.         if (!texinfo->texels)
  508.     {
  509.                 free (texinfo);
  510.                 return NULL;
  511.     }
  512.        
  513.         /* read color map */
  514.         if (header.colormap_type)
  515.     {
  516.                 /* NOTE: color map is stored in BGR format */
  517.                 colormap = (GLubyte *)malloc (sizeof (GLubyte)
  518.                                                                           * header.cm_length * (header.cm_size >> 3));
  519.                 fread (colormap, sizeof (GLubyte), header.cm_length
  520.                            * (header.cm_size >> 3), fp);
  521.     }
  522.        
  523.         /* read image data */
  524.         switch (header.image_type)
  525.     {
  526.                 case 0:
  527.                         /* no data */
  528.                         break;
  529.                        
  530.                 case 1:
  531.                         /* uncompressed 8 bits color index */
  532.                         ReadTGA8bits (fp, colormap, texinfo);
  533.                         break;
  534.                        
  535.                 case 2:
  536.                         /* uncompressed 16-24-32 bits */
  537.                         switch (header.pixel_depth)
  538.                 {
  539.                         case 16:
  540.                                 ReadTGA16bits (fp, texinfo);
  541.                                 break;
  542.                                
  543.                         case 24:
  544.                                 ReadTGA24bits (fp, texinfo);
  545.                                 break;
  546.                                
  547.                         case 32:
  548.                                 ReadTGA32bits (fp, texinfo);
  549.                                 break;
  550.                 }
  551.                        
  552.                         break;
  553.                        
  554.                 case 3:
  555.                         /* uncompressed 8 or 16 bits grayscale */
  556.                         if (header.pixel_depth == 8)
  557.                                 ReadTGAgray8bits (fp, texinfo);
  558.                         else /* 16 */
  559.                                 ReadTGAgray16bits (fp, texinfo);
  560.                        
  561.                         break;
  562.                        
  563.                         case 9:
  564.                         /* RLE compressed 8 bits color index */
  565.                         ReadTGA8bitsRLE (fp, colormap, texinfo);
  566.                         break;
  567.                        
  568.                         case 10:
  569.                         /* RLE compressed 16-24-32 bits */
  570.                         switch (header.pixel_depth)
  571.                 {
  572.                         case 16:
  573.                                 ReadTGA16bitsRLE (fp, texinfo);
  574.                                 break;
  575.                                
  576.                         case 24:
  577.                                 ReadTGA24bitsRLE (fp, texinfo);
  578.                                 break;
  579.                                
  580.                         case 32:
  581.                                 ReadTGA32bitsRLE (fp, texinfo);
  582.                                 break;
  583.                 }
  584.                        
  585.                         break;
  586.                        
  587.                         case 11:
  588.                         /* RLE compressed 8 or 16 bits grayscale */
  589.                         if (header.pixel_depth == 8)
  590.                                 ReadTGAgray8bitsRLE (fp, texinfo);
  591.                         else /* 16 */
  592.                                 ReadTGAgray16bitsRLE (fp, texinfo);
  593.                        
  594.                         break;
  595.                        
  596.                         default:
  597.                         /* image type is not correct */
  598.                         fprintf (stderr, "error: unknown TGA image type %i!\n", header.image_type);
  599.                         free (texinfo->texels);
  600.                         free (texinfo);
  601.                         texinfo = NULL;
  602.                         break;
  603.     }
  604.        
  605.         /* no longer need colormap data */
  606.         if (colormap)
  607.                 free (colormap);
  608.        
  609.         fclose (fp);
  610.         return texinfo;
  611. }
  612.  
  613.  
  614. GLuint
  615. loadTGATexture (const char *filename, GLuint texid)
  616. {
  617.         gl_texture_t *tga_tex = NULL;
  618.         GLuint tex_id = 0;
  619.        
  620.         tga_tex = ReadTGAFile (filename);
  621.        
  622.         if (tga_tex && tga_tex->texels)
  623.     {
  624.                 /* generate texture */
  625.                 if(!texid)
  626.                         glGenTextures (1, &tga_tex->id);
  627.                 else
  628.                         tga_tex->id = texid;
  629.                 glBindTexture (GL_TEXTURE_2D, tga_tex->id);
  630.                
  631.                 /* setup some parameters for texture filters and mipmapping */
  632.                 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/);
  633.                 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  634.                
  635.                
  636.                 glTexImage2D (GL_TEXTURE_2D, 0, tga_tex->internalFormat,
  637.                                           tga_tex->width, tga_tex->height, 0, tga_tex->format,
  638.                                           GL_UNSIGNED_BYTE, tga_tex->texels);
  639.                
  640.                 /*
  641.                  gluBuild2DMipmaps (GL_TEXTURE_2D, tga_tex->internalFormat,
  642.                  tga_tex->width, tga_tex->height,
  643.                  tga_tex->format, GL_UNSIGNED_BYTE, tga_tex->texels);
  644.                  */
  645.                
  646.                 tex_id = tga_tex->id;
  647.                
  648.                 /* OpenGL has its own copy of texture data */
  649.                 free (tga_tex->texels);
  650.                 free (tga_tex);
  651.     }
  652.        
  653.         return tex_id;
  654. }
clone this paste RAW Paste Data