home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 February / Chip_2001-02_cd1.bin / bonus / demos / CS / exp / SOURCES / GLENGINE / image.cpp < prev    next >
C/C++ Source or Header  |  2000-08-20  |  11KB  |  478 lines

  1. #include <stdio.h>
  2. #include <malloc.h>
  3. #include <fcntl.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <iostream>
  9.  
  10. #include "image.h"
  11.  
  12. #define IMAGE_TEXT_OUT 1
  13.  
  14. Image::Image () {
  15.   paleta = 0;
  16.   bitmap = 0;
  17.   h = w = 0;
  18.   form = OGL_IMAGE_NULL;
  19. }
  20.  
  21. Image::Image (const char* filename) {
  22.   paleta = 0;
  23.   bitmap = 0;
  24.   h = w = 0;
  25.   form = OGL_IMAGE_NULL;
  26.   Load(filename);
  27. }
  28.  
  29. Image::~Image () {
  30.   delete[] paleta;
  31.   delete[] bitmap;
  32. }
  33.  
  34. void Image::Scale(int sirka, int vyska)
  35. {
  36.   int elementsize = 0;
  37.   switch(format()) {
  38.     case OGL_IMAGE_RGBA8888:
  39.     case OGL_IMAGE_ARGB8888:
  40.       elementsize = 4;
  41.       break;
  42.     case OGL_IMAGE_RGB888:
  43.       elementsize = 3;
  44.       break;
  45.     case OGL_IMAGE_INDEX8:
  46.     case OGL_IMAGE_LUMINANCE8:
  47.       elementsize = 1;
  48.       break;
  49.     default:
  50.       return;
  51.     }
  52.  
  53. //  vyska=h;
  54. //  sirka=w;
  55.  
  56.   unsigned char* n_bitmap = new unsigned char[vyska*sirka*elementsize];
  57.   unsigned char* n=n_bitmap;
  58.   unsigned char* p, *pp;
  59.  
  60.   float xx=0.0,yy=0.0;
  61.  
  62.   float dx=float(w)/sirka;
  63.   float dy=float(h)/vyska;
  64.  
  65.   for (int y=0; y<vyska;y++)
  66.     {
  67.     p=bitmap+(int(yy))*elementsize*w;
  68.     for (int x=0; x<sirka;x++)
  69.       {
  70.       pp=p+(int(xx))*elementsize;
  71.       for(int i=elementsize;i;i--) *n++=*pp++;
  72.       xx+=dx;
  73.       }
  74.     xx=0.0;
  75.     yy+=dy;
  76.     }
  77. delete[] bitmap;
  78. bitmap=n_bitmap;
  79. w=sirka;
  80. h=vyska;
  81. }
  82.  
  83. void Image::FlipVertical () {
  84.   int elementsize = 0;
  85.   switch(format()) {
  86.     case OGL_IMAGE_RGBA8888:
  87.     case OGL_IMAGE_ARGB8888:
  88.       elementsize = 4;
  89.       break;
  90.     case OGL_IMAGE_RGB888:
  91.       elementsize = 3;
  92.       break;
  93.     case OGL_IMAGE_INDEX8:
  94.     case OGL_IMAGE_LUMINANCE8:
  95.       elementsize = 1;
  96.       break;
  97.     default:
  98.       return;
  99.     }
  100.   unsigned char *p1, *p2, *pp1, *pp2;
  101.   unsigned char x;
  102.   int linewidth = width()*elementsize;
  103.   p1 = data();
  104.   p2 = p1 + linewidth*(height()-1);
  105.   int half = height()/2;
  106.  
  107.   for(int i=half; i; i--) {
  108.     pp1 = p1;
  109.     pp2 = p2;
  110.     for(int j=linewidth; j; j--) {
  111.       x = *pp1;
  112.       *pp1 = *pp2;
  113.       *pp2 = x;
  114.       pp1++;
  115.       pp2++;
  116.     }
  117.     p1+=linewidth;
  118.     p2-=linewidth;
  119.   }
  120. }
  121.  
  122.  
  123. int Image::LoadBMP (const char* filename)
  124. {
  125.   int f;
  126.   struct stat *st;
  127.   st = (struct stat *) malloc(sizeof(*st));
  128.  
  129.   f = open(filename, O_BINARY|O_RDONLY);
  130.   if (f==(-1))
  131.       return 0;
  132.  
  133.   fstat(f,st);
  134.   int filesize = st->st_size;
  135.   unsigned char *buffer = new unsigned char[filesize];
  136.   read(f, buffer, filesize);
  137.   close(f);
  138.   free(st);
  139.  
  140.   header.bfType = *(short*)buffer;
  141.   if(header.bfType!=0x4d42)
  142.     return 0;
  143.  
  144.   header.bfSize = *(long*)(buffer+2);
  145.   header.bfReserved1 = *(short*)(buffer+6);
  146.   header.bfReserved2 = *(short*)(buffer+8);
  147.   header.bfOffBits = *(long*)(buffer+10);
  148.  
  149.   header.biSize = *(long*)(buffer+14);
  150.   header.biWidth = *(long*)(buffer+18);
  151.   header.biHeight = *(long*)(buffer+22);
  152.   header.biPlanes = *(short*)(buffer+26);
  153.   header.biBitCount = *(short*)(buffer+28);
  154.   header.biCompression = *(long*)(buffer+30);
  155.   header.biSizeImage = *(long*)(buffer+34);
  156.   header.biXPelsPerMeter = *(long*)(buffer+38);
  157.   header.biYPelsPerMeter = *(long*)(buffer+42);
  158.   header.biClrUsed = *(long*)(buffer+46);
  159.   header.biClrImportant = *(long*)(buffer+50);
  160. /*
  161.   if (IMAGE_TEXT_OUT) printf("bmp size: %ld\n", header.bfSize);
  162.   if (IMAGE_TEXT_OUT) printf("width: %ld\n",header.biWidth);
  163.   if (IMAGE_TEXT_OUT) printf("height: %ld\n",header.biHeight);
  164.   if (IMAGE_TEXT_OUT) printf("planes: %hd\n",header.biPlanes);
  165.   if (IMAGE_TEXT_OUT) printf("bpp: %hd\n",header.biBitCount);
  166.   if (IMAGE_TEXT_OUT) printf("compression: %ld\n",header.biCompression);
  167.   header.biClrUsed ? if (IMAGE_TEXT_OUT) printf("    colors used: %ld, ",header.biClrUsed)
  168.                    : if (IMAGE_TEXT_OUT) printf("    colors used: ALL, ");
  169.   header.biClrImportant ? if (IMAGE_TEXT_OUT) printf("colors important: %ld\n",header.biClrImportant)
  170.                         : if (IMAGE_TEXT_OUT) printf("colors important: ALL\n");
  171. */
  172.   w = header.biWidth;
  173.   h = header.biHeight;
  174.   bpp = header.biBitCount;
  175.  
  176.   unsigned char *data;
  177.   unsigned char *map, *map2;
  178.   unsigned char *pal;
  179.   int actualcolors;
  180.  
  181.   switch(bpp) {
  182.  
  183.     //  Monochromatic
  184.     case 1:
  185.       break;
  186.  
  187.     // Indexed 16 color
  188.     case 4:
  189.       break;
  190.  
  191.     // Indexed 256 color
  192.     case 8:
  193.       form = OGL_IMAGE_INDEX8;
  194.       paleta = new unsigned long[256];
  195.       pal = buffer + 54;
  196.       actualcolors = header.biClrUsed ? header.biClrUsed : 256;
  197.       for(int i=0; i<actualcolors; i++, pal+=4)
  198.           paleta[i] = (*pal) | (*(pal+1)<<8) | (*(pal+2)<<16);
  199.  
  200.       data = buffer + header.bfOffBits;
  201.       bitmap = new unsigned char[h*w];
  202.  
  203.       switch(header.biCompression) {
  204.  
  205.         case BMP_RGB:
  206.           map = bitmap + w*(h-1);
  207.  
  208.           for(int i=h; i; i--)
  209.           {
  210.               map2=map;
  211.  
  212.               for(int j=w; j; j--)
  213.                   *map2++ = *data++;
  214.  
  215.               map -= w;
  216.           }
  217.           break;
  218.  
  219.         case BMP_RLE8:
  220.           break;
  221.  
  222.         case BMP_RLE4:
  223.           break;
  224.         }
  225.  
  226.       break;
  227.  
  228.     //  24bpp images
  229.     case 24:
  230.       form = OGL_IMAGE_RGBA8888;
  231.       data = buffer + header.bfOffBits;
  232.       bitmap = new unsigned char[(h*w)<<2];
  233.  
  234.       map = bitmap;
  235.  
  236.       for(int i=h*w; i; i--)
  237.       {
  238.         *map++ = *(data+2);
  239.         *map++ = *(data+1);
  240.         *map++ = *data;
  241.         *map++ = 255;
  242.         data+=3;
  243.  
  244. //        *map++ = *data++;
  245. //        *map++ = *data++;
  246. //        *map++ = *data++;
  247. //        *map++ = 255;
  248.       }
  249.  
  250.       FlipVertical();
  251.  
  252.       break;
  253.  
  254.   }
  255.  
  256.   free(buffer);
  257.   return 1;
  258. }
  259.  
  260. int Image::LoadPNG (const char* filename) {
  261.  
  262.   FILE *fp = fopen(filename, "rb");
  263.  
  264.   if(!fp)
  265.   {
  266.     if (IMAGE_TEXT_OUT) printf("file %s not found\n", filename);
  267.     return 0;
  268.   }
  269.  
  270.   png_structp png_ptr = png_create_read_struct
  271.      (PNG_LIBPNG_VER_STRING, (png_voidp)0,
  272.       0, 0);
  273.   if (!png_ptr)
  274.   {
  275.     if (IMAGE_TEXT_OUT) printf("png read structure cannot be created\n");
  276.     fclose(fp);
  277.     return 0;
  278.   }
  279.  
  280.   png_infop info_ptr = png_create_info_struct(png_ptr);
  281.   if (!info_ptr)
  282.   {
  283.     if (IMAGE_TEXT_OUT) printf("png info structure cannot be created\n");
  284.     png_destroy_read_struct(&png_ptr,
  285.        (png_infopp)0, (png_infopp)0);
  286.     fclose(fp);
  287.     return 0;
  288.   }
  289.  
  290.   png_infop end_info = png_create_info_struct(png_ptr);
  291.   if (!end_info)
  292.   {
  293.     png_destroy_read_struct(&png_ptr, &info_ptr,
  294.       (png_infopp)0);
  295.     fclose(fp);
  296.     return 0;
  297.   }
  298.  
  299.   png_init_io(png_ptr, fp);
  300.   png_read_info(png_ptr, info_ptr);
  301.  
  302.   w = png_get_image_width(png_ptr, info_ptr);
  303.   h = png_get_image_height(png_ptr, info_ptr);
  304.  
  305.   png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  306.   png_byte color_type = png_get_color_type(png_ptr, info_ptr);
  307.  
  308.   if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_PALETTE)
  309.   {
  310.     form = OGL_IMAGE_INDEX8;
  311.     png_bytep rowpointers[h];
  312.     bitmap = new unsigned char[h*w];
  313.     paleta = new unsigned long[256];
  314.     png_colorp pngpal;
  315.     int num_palette;
  316.     bpp=bit_depth;
  317.  
  318.     png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette);
  319.  
  320.     for(png_uint_16 i=0; i<num_palette; i++)
  321.         paleta[i] = (pngpal[i].red<<16)|(pngpal[i].green<<8)|(pngpal[i].blue);
  322.  
  323.     for(long i=0; i<h; i++)
  324.         rowpointers[i] = (png_bytep)(bitmap+i*w);
  325.  
  326.     png_read_image(png_ptr, rowpointers);
  327.  
  328.     png_read_end(png_ptr, end_info);
  329.     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  330.  
  331.     fclose(fp);
  332.     return 1;
  333.   }
  334.  
  335.   if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_GRAY)
  336.   {
  337. //        if (IMAGE_TEXT_OUT) printf("Grayscale ");
  338.     form = OGL_IMAGE_LUMINANCE8;
  339.     png_bytep rowpointers[h];
  340.     bitmap = new unsigned char[h*w];
  341.     bpp=bit_depth;
  342.     for(long i=0; i<h; i++)
  343.         rowpointers[i] = (png_bytep)(bitmap+i*w);
  344.  
  345.     png_read_image(png_ptr, rowpointers);
  346.     png_read_end(png_ptr, end_info);
  347.     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  348.  
  349. //        if (IMAGE_TEXT_OUT) printf("%s\n",filename);
  350.  
  351.     fclose(fp);
  352.     return 1;
  353.   }
  354.  
  355.  
  356.   if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB)
  357.   {
  358.     form = OGL_IMAGE_RGBA8888;
  359.     png_bytep rowpointers[h];
  360.     bitmap = new unsigned char[h*w*4];
  361.     bpp=bit_depth;
  362.  
  363.     for(long i=0; i<h; i++)
  364.         rowpointers[i] = (png_bytep)(bitmap+i*w*4);
  365.  
  366. //    png_set_bgr(png_ptr);
  367.     png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
  368.  
  369.     png_read_update_info(png_ptr, info_ptr);
  370.  
  371.     png_read_image(png_ptr, rowpointers);
  372.  
  373.     png_read_end(png_ptr, end_info);
  374.     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  375.  
  376.     fclose(fp);
  377.     return 1;
  378.   }
  379.  
  380.   if(bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  381.   {
  382.     form = OGL_IMAGE_RGBA8888;
  383.     png_bytep rowpointers[h];
  384.     bitmap = new unsigned char[h*w*4];
  385.     bpp=bit_depth;
  386.  
  387.     for(long i=0; i<h; i++)
  388.         rowpointers[i] = (png_bytep)(bitmap+i*w*4);
  389.  
  390. //    png_set_bgr(png_ptr);
  391.     png_read_update_info(png_ptr, info_ptr);
  392.     png_read_image(png_ptr, rowpointers);
  393.     png_read_end(png_ptr, end_info);
  394.     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  395.  
  396.     fclose(fp);
  397.     return 1;
  398.   }
  399.  
  400.   png_read_end(png_ptr, end_info);
  401.   png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  402.  
  403.   fclose(fp);
  404.   return 0;
  405. }
  406.  
  407. int Image::LoadJPG(const char *filename)
  408. {
  409.   struct jpeg_decompress_struct cinfo;
  410.   struct jpeg_error_mgr jerr;
  411.  
  412.   FILE * infile;        /* source file */
  413.   int row_stride;        /* physical row width in output buffer */
  414.  
  415.   if ((infile = fopen(filename, "rb")) == 0) {
  416.     if (IMAGE_TEXT_OUT) fprintf(stderr, "can't open %s\n", filename);
  417.     return 0;
  418.   }
  419.  
  420.   cinfo.err = jpeg_std_error(&jerr);
  421.   jpeg_create_decompress(&cinfo);
  422.   jpeg_stdio_src(&cinfo, infile);
  423.   jpeg_read_header(&cinfo, TRUE);
  424.   jpeg_start_decompress(&cinfo);
  425.   row_stride = cinfo.output_width * cinfo.output_components;
  426.   
  427.   if (IMAGE_TEXT_OUT) cout<<"width: " << cinfo.output_width << ",";
  428.   if (IMAGE_TEXT_OUT) cout<<"height: " << cinfo.output_height << ",";
  429.   if (IMAGE_TEXT_OUT) cout<<"components: " <<cinfo.output_components << endl;
  430.  
  431.   bitmap = new unsigned char[row_stride*cinfo.output_height];
  432.   w = cinfo.output_width;
  433.   h = cinfo.output_height;
  434.   form = OGL_IMAGE_RGB888;
  435.   bpp = cinfo.output_components << 3;
  436.  
  437.   JSAMPROW row_pointer[1];
  438.   int i=0;
  439.  
  440.   while (cinfo.output_scanline < cinfo.output_height) {
  441.     row_pointer[0] = bitmap+i*row_stride;
  442.     i++;
  443.     jpeg_read_scanlines(&cinfo, row_pointer, 1);
  444.   }
  445.  
  446.   jpeg_finish_decompress(&cinfo);
  447.   jpeg_destroy_decompress(&cinfo);
  448.   fclose(infile);
  449.   return 1;
  450. }
  451.  
  452. const char *getext(const char *str) {
  453.   const char *ext = 0;
  454.   while(*str)
  455.   {
  456.     if(*str==46) ext=str+1;
  457.     str++;
  458.   }
  459.   if(*ext==0)
  460.     ext = 0;
  461.   return ext;
  462. }
  463.  
  464. int Image::Load(const char *filename)
  465. {
  466.   const char *extension = getext(filename);
  467.  
  468.   if(stricmp(extension, "bmp")==0) {
  469.     return LoadBMP(filename);
  470.   }
  471.   if(stricmp(extension, "png")==0) {
  472.     return LoadPNG(filename);
  473.   }
  474.   if(stricmp(extension, "jpg")==0) {
  475.     return LoadJPG(filename);
  476.   }
  477.   return 0;
  478. }