home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 19 / Amiga Plus Leser CD 19.iso / Tools / Freeware / Swf_Player / Lib / bitmap.cc < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-17  |  12.5 KB  |  607 lines

  1. /////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //  
  22.  
  23. #include "swf.h"
  24.  
  25. #ifdef RCSID
  26. static char *rcsid = "$Id: bitmap.cc,v 1.5 1999/09/09 13:19:01 ode Exp $";
  27. #endif
  28.  
  29. static unsigned char *inputData;
  30.  
  31. // Class variables
  32.  
  33. int Bitmap::haveTables = 0;
  34.  
  35. struct jpeg_decompress_struct Bitmap::jpegObject;
  36.  
  37. struct jpeg_source_mgr Bitmap::jpegSourceManager;
  38.  
  39. MyErrorHandler Bitmap::jpegErrorMgr;
  40.  
  41. Bitmap::Bitmap(long id, int level) : Character(BitmapType, id )
  42. {
  43.     pixels = NULL;
  44.     alpha_buf = NULL;
  45.     colormap = NULL;
  46.     nbColors = 0;
  47.     defLevel = level;
  48. }
  49.  
  50. Bitmap::~Bitmap()
  51. {
  52.     if (pixels) {
  53.         delete[] pixels;
  54.     }
  55.         if (alpha_buf) {
  56.             delete[] alpha_buf;
  57.         }
  58.     if (colormap)
  59.     {
  60.         delete colormap;
  61.     }
  62.     if (haveTables) {
  63.         jpeg_destroy_decompress(&jpegObject);
  64.         haveTables = 0;
  65.     }
  66. }
  67.  
  68. static void errorExit(j_common_ptr info)
  69. {
  70.     (*info->err->output_message) (info);
  71.     longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1);
  72. }
  73.  
  74. // Methods for Source data manager
  75. static void initSource(struct jpeg_decompress_struct *cInfo)
  76. {
  77.     cInfo->src->bytes_in_buffer = 0;
  78. }
  79.  
  80. static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo)
  81. {
  82.     cInfo->src->next_input_byte = inputData;
  83.     cInfo->src->bytes_in_buffer = 1;
  84.     inputData++;
  85.  
  86.     return 1;
  87. }
  88.  
  89. static void skipInputData(struct jpeg_decompress_struct *cInfo, long count)
  90. {
  91.     cInfo->src->bytes_in_buffer = 0;
  92.     inputData += count;
  93. }
  94.  
  95. static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired)
  96. {
  97.     return jpeg_resync_to_restart(cInfo, desired);
  98. }
  99.  
  100. static void termSource(struct jpeg_decompress_struct *cInfo)
  101. {
  102. }
  103.  
  104. long Bitmap::getWidth()
  105. {
  106.     return width;
  107. }
  108.  
  109. long Bitmap::getHeight()
  110. {
  111.     return height;
  112. }
  113.  
  114. Color *
  115. Bitmap::getColormap(long *n) {
  116.        if (n) *n = nbColors;
  117.        return colormap;
  118. }
  119.  
  120. unsigned char *
  121. Bitmap::getPixels()
  122. {
  123.        return pixels;
  124. }
  125.  
  126. // Read Tables and Compressed data to produce an image
  127.  
  128. static int
  129. buildJpegAlpha(Bitmap *b, unsigned char *buffer)
  130. {
  131.     z_stream    stream;
  132.     int        status;
  133.     unsigned char  *data;
  134.  
  135.     data = new unsigned char[b->width*b->height];
  136.     if (data == NULL) 
  137.         return -1;
  138.  
  139.     stream.next_in = buffer;
  140.     stream.avail_in = 1;
  141.     stream.next_out = data;
  142.     stream.avail_out = b->width*b->height;
  143.     stream.zalloc = Z_NULL;
  144.     stream.zfree = Z_NULL;
  145.             
  146.     status = inflateInit(&stream);
  147.  
  148.     while (1) {
  149.         status = inflate(&stream, Z_SYNC_FLUSH) ;
  150.         if (status == Z_STREAM_END) {
  151.             break;
  152.         }
  153.         if (status != Z_OK) {
  154.             printf("Zlib data error : %s\n", stream.msg);
  155.         delete data;
  156.             return -1;
  157.         }
  158.         stream.avail_in = 1;
  159.     }
  160.  
  161.     inflateEnd(&stream);
  162.             
  163.     b->alpha_buf = data;
  164.  
  165.     return 0;
  166. }
  167.  
  168. int
  169. Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset)
  170. {
  171.     struct jpeg_decompress_struct cInfo;
  172.     struct jpeg_source_mgr mySrcMgr;
  173.     MyErrorHandler errorMgr;
  174.     JSAMPROW buffer[1];
  175.     unsigned char *ptrPix;
  176.     int stride;
  177.     long n;
  178.  
  179. #if PRINT&1
  180.         printf("flash: loading jpeg (interchange)\n");
  181. #endif
  182.  
  183.     // Kludge to correct some corrupted files
  184.     if (stream[1] == 0xd9 && stream[3] == 0xd8) {
  185.         stream[3] = 0xd9;
  186.         stream[1] = 0xd8;
  187.     }
  188.  
  189.     // Setup error handler
  190.     cInfo.err = jpeg_std_error(&errorMgr.pub);
  191.     errorMgr.pub.error_exit = errorExit;
  192.  
  193.     if (setjmp(errorMgr.setjmp_buffer)) {
  194.         // JPEG data Error
  195.         jpeg_destroy_decompress(&cInfo);
  196.         if (pixels) {
  197.             delete[] pixels;
  198.             pixels = NULL;
  199.         }
  200.         return -1;
  201.     }
  202.  
  203.     // Set current stream pointer to stream
  204.     inputData = stream;
  205.  
  206.     // Here it's Ok
  207.  
  208.     jpeg_create_decompress(&cInfo);
  209.  
  210.     // Setup source manager structure
  211.     mySrcMgr.init_source = initSource;
  212.     mySrcMgr.fill_input_buffer = fillInputBuffer;
  213.     mySrcMgr.skip_input_data = skipInputData;
  214.     mySrcMgr.resync_to_restart = resyncToRestart;
  215.     mySrcMgr.term_source = termSource;
  216.  
  217.     // Set default source manager
  218.     cInfo.src = &mySrcMgr;
  219.  
  220.     jpeg_read_header(&cInfo, FALSE);
  221.  
  222.     jpeg_read_header(&cInfo, TRUE);
  223.     cInfo.quantize_colors = TRUE;    // Create colormapped image
  224.     jpeg_start_decompress(&cInfo);
  225.  
  226.     // Set objet dimensions
  227.     height = cInfo.output_height;
  228.     width = cInfo.output_width;
  229.         bpl = width;
  230.     pixels = new unsigned char [height*width];
  231.     if (pixels == NULL) {
  232.         jpeg_finish_decompress(&cInfo);
  233.         jpeg_destroy_decompress(&cInfo);
  234.         return -1;
  235.     }
  236.     ptrPix = pixels;
  237.  
  238.     stride = cInfo.output_width * cInfo.output_components;
  239.  
  240.     buffer[0] = (JSAMPROW)malloc(stride);
  241.  
  242.     while (cInfo.output_scanline < cInfo.output_height) {
  243.  
  244.         jpeg_read_scanlines(&cInfo, buffer, 1);
  245.  
  246.         memcpy(ptrPix,buffer[0],stride);
  247.  
  248.         ptrPix+= stride;
  249.     }
  250.  
  251.         free(buffer[0]);
  252.  
  253.     colormap = new Color[cInfo.actual_number_of_colors];
  254.     if (colormap == NULL) {
  255.         delete pixels;
  256.         jpeg_finish_decompress(&cInfo);
  257.         jpeg_destroy_decompress(&cInfo);
  258.         return -1;
  259.     }
  260.     nbColors = cInfo.actual_number_of_colors;
  261.  
  262.     for(n=0; n < nbColors; n++)
  263.     {
  264.         colormap[n].red = cInfo.colormap[0][n];
  265.         colormap[n].green = cInfo.colormap[1][n];
  266.         colormap[n].blue = cInfo.colormap[2][n];
  267.     }
  268.  
  269.     jpeg_finish_decompress(&cInfo);
  270.     jpeg_destroy_decompress(&cInfo);
  271.  
  272.         if (read_alpha) {
  273.             if (buildJpegAlpha(this,  stream + offset) < 0) {
  274.             return -1;
  275.         }
  276.         }
  277.     return 0;
  278. }
  279.  
  280. // Read JPEG image using pre-loaded Tables
  281.  
  282. int
  283. Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream)
  284. {
  285.     JSAMPROW buffer[1];
  286.     unsigned char *ptrPix;
  287.     int stride;
  288.     long n;
  289.     int status;
  290.  
  291. #if PRINT&1
  292.         printf("flash: loading jpeg (abbreviated)\n");
  293. #endif
  294.  
  295.     // Set current stream pointer to stream
  296.     inputData = stream;
  297.  
  298.     // Error handler
  299.     if (setjmp(jpegErrorMgr.setjmp_buffer)) {
  300.         // JPEG data Error
  301.         //jpeg_destroy_decompress(&jpegObject);
  302.         if (pixels) {
  303.             delete[] pixels;
  304.             pixels = NULL;
  305.         }
  306.         return -1;
  307.     }
  308.  
  309.     // Here it's ok
  310.  
  311.     jpeg_read_header(&jpegObject, TRUE);
  312.     jpegObject.quantize_colors = TRUE;    // Create colormapped image
  313.     jpeg_start_decompress(&jpegObject);
  314.  
  315.     // Set objet dimensions
  316.     height = jpegObject.output_height;
  317.     width = jpegObject.output_width;
  318.         bpl = width;
  319.     pixels = new unsigned char [height*width];
  320.     if (pixels == NULL) {
  321.         jpeg_finish_decompress(&jpegObject);
  322.         return -1;
  323.     }
  324.     ptrPix = pixels;
  325.  
  326.     stride = jpegObject.output_width * jpegObject.output_components;
  327.  
  328.     buffer[0] = (JSAMPROW)malloc(stride);
  329.  
  330.     while (jpegObject.output_scanline < jpegObject.output_height) {
  331.  
  332.         status = jpeg_read_scanlines(&jpegObject, buffer, 1);
  333.  
  334.         memcpy(ptrPix,buffer[0],stride);
  335.  
  336.         ptrPix+= stride;
  337.     }
  338.         
  339.         free(buffer[0]);
  340.  
  341.     colormap = new Color[jpegObject.actual_number_of_colors];
  342.     if (colormap == NULL) {
  343.         jpeg_finish_decompress(&jpegObject);
  344.         delete pixels;
  345.         return -1;
  346.     }
  347.     nbColors = jpegObject.actual_number_of_colors;
  348.  
  349.     for(n=0; n < nbColors; n++)
  350.     {
  351.         colormap[n].red = jpegObject.colormap[0][n];
  352.         colormap[n].green = jpegObject.colormap[1][n];
  353.         colormap[n].blue = jpegObject.colormap[2][n];
  354.     }
  355.  
  356.     status = jpeg_finish_decompress(&jpegObject);
  357.  
  358.     return 0;
  359. }
  360.  
  361. // Just init JPEG object and read JPEG Tables
  362.  
  363. int
  364. Bitmap::readJpegTables(unsigned char *stream)
  365. {
  366.     if (haveTables) {
  367.         //Error, it has already been initialized
  368.         return -1;
  369.     }
  370.  
  371.     // Setup error handler
  372.     jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
  373.     jpegErrorMgr.pub.error_exit = errorExit;
  374.  
  375.     if (setjmp(jpegErrorMgr.setjmp_buffer)) {
  376.         // JPEG data Error
  377.         jpeg_destroy_decompress(&jpegObject);
  378.         return -1;
  379.     }
  380.  
  381.     // Set current stream pointer to stream
  382.     inputData = stream;
  383.  
  384.     // Here it's Ok
  385.  
  386.     jpeg_create_decompress(&jpegObject);
  387.  
  388.     // Setup source manager structure
  389.     jpegSourceManager.init_source = initSource;
  390.     jpegSourceManager.fill_input_buffer = fillInputBuffer;
  391.     jpegSourceManager.skip_input_data = skipInputData;
  392.     jpegSourceManager.resync_to_restart = resyncToRestart;
  393.     jpegSourceManager.term_source = termSource;
  394.  
  395.     // Set default source manager
  396.     jpegObject.src = &jpegSourceManager;
  397.  
  398.     jpeg_read_header(&jpegObject, FALSE);
  399.  
  400.     haveTables = 1;
  401.  
  402.     return 0;
  403. }
  404.  
  405. int
  406. Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize, int tableHasAlpha)
  407. {
  408.     z_stream    stream;
  409.     int        status;
  410.     unsigned char  *data;
  411.     int        elementSize;
  412.  
  413. #if PRINT&1
  414.         printf("flash: loading with zlib\n");
  415. #endif
  416.  
  417.     this->width = width;
  418.     this->height = height;
  419.         this->bpl = width;
  420.  
  421.     if (tableHasAlpha) {
  422.         elementSize = 4;    // Cmap is RGBA
  423.     } else {
  424.         elementSize = 3;    // Cmap is RGB
  425.     }
  426.  
  427.     stream.next_in = buffer;
  428.     stream.avail_in = 1;
  429.     stream.zalloc = Z_NULL;
  430.     stream.zfree = Z_NULL;
  431.  
  432.     tableSize++;
  433.  
  434.     // Uncompress Color Table
  435.     if (format == 3) {
  436.         unsigned char *colorTable;
  437.         long n;
  438.  
  439.         // Ajust width for 32 bit padding
  440.         width = (width+3)/4*4;
  441.         this->width = width;
  442.         this->bpl = width;
  443.  
  444.         depth = 1;
  445.         colorTable = new unsigned char[tableSize*elementSize];
  446.         if (colorTable == NULL) {
  447.             return -1;
  448.         }
  449.  
  450.         stream.next_out = colorTable;
  451.         stream.avail_out = tableSize*elementSize;
  452.  
  453.         inflateInit(&stream);
  454.  
  455.         while (1) {
  456.             status = inflate(&stream, Z_SYNC_FLUSH);
  457.             if (status == Z_STREAM_END) {
  458.                     break;
  459.             }
  460.             if (status != Z_OK) {
  461.                 printf("Zlib cmap error : %s\n", stream.msg);
  462.                 return -1;
  463.             }
  464.             stream.avail_in = 1;
  465.             // Colormap if full
  466.             if (stream.avail_out == 0) {
  467.                 break;
  468.             }
  469.         }
  470.  
  471.         nbColors = tableSize;
  472.  
  473.         colormap = new Color[nbColors];
  474.         if (colormap == NULL) {
  475.             delete colorTable;
  476.             return -1;
  477.         }
  478.  
  479.         for(n=0; n < nbColors; n++) {
  480.             colormap[n].red = colorTable[n*elementSize+0];
  481.             colormap[n].green = colorTable[n*elementSize+1];
  482.             colormap[n].blue = colorTable[n*elementSize+2];
  483.             if (tableHasAlpha) {
  484.                 colormap[n].alpha = colorTable[n*elementSize+3];
  485.             }
  486.         }
  487.  
  488.         delete colorTable;
  489.  
  490.     } else if (format == 4) {
  491.         depth = 2;
  492.         width = (width+1)/2*2;
  493.         this->bpl = width;
  494.     } else if (format == 5) {
  495.         depth = 4;
  496.     }
  497.  
  498.     data = new unsigned char[depth*width*height];
  499.     if (data == NULL) {
  500.         if (colormap) delete colormap;
  501.         return -1;
  502.     }
  503.  
  504.     stream.next_out = data;
  505.     stream.avail_out = depth*width*height;
  506.  
  507.     if (format != 3) {
  508.         status = inflateInit(&stream);
  509.     }
  510.  
  511.     while (1) {
  512.         status = inflate(&stream, Z_SYNC_FLUSH) ;
  513.         if (status == Z_STREAM_END) {
  514.                 break;
  515.         }
  516.         if (status != Z_OK) {
  517.             printf("Zlib data error : %s\n", stream.msg);
  518.             delete data;
  519.             return -1;
  520.         }
  521.         stream.avail_in = 1;
  522.     }
  523.  
  524.     inflateEnd(&stream);
  525.  
  526.     pixels = new unsigned char [height*width];
  527.     if (pixels == NULL) {
  528.         if (colormap) delete colormap;
  529.         delete data;
  530.         return -1;
  531.     }
  532.  
  533.     if (format != 3) {
  534.         int n,c;
  535.         unsigned char r,g,b,a;
  536.         unsigned char *ptr;
  537.  
  538.                 r = g = b = a = 0; /* to supress warnings */
  539.  
  540.         nbColors = 0;
  541.         colormap = new Color[256];
  542.         if (colormap == NULL) {
  543.             delete data;
  544.             delete pixels;
  545.             return -1;
  546.         }
  547.                 memset(colormap, 0, 256 * sizeof(Color));
  548.         ptr = pixels;
  549.         
  550.         for(n=0; n < width*height*depth; n+=depth,ptr++) {
  551.                     
  552.             switch (format) {
  553.                 case 4:
  554.                     a = 1;
  555.                     r = (data[n] & 0x78)<<1;
  556.                     g = ((data[n] & 0x03)<<6) | (data[n+1] & 0xc0)>>2;
  557.                     b = (data[n+1] & 0x1e)<<3;
  558.                     break;
  559.                 case 5:
  560.                     a = data[n];
  561.                     // Reduce color dynamic range
  562.                     r = data[n+1]&0xe0;
  563.                     g = data[n+2]&0xe0;
  564.                     b = data[n+3]&0xe0;
  565.                     break;
  566.             }
  567.             for(c=0; c < nbColors; c++) {
  568.                 if (r == colormap[c].red
  569.                 &&  g == colormap[c].green
  570.                 &&  b == colormap[c].blue) {
  571.                     *ptr = c;
  572.                     break;
  573.                 }
  574.             }
  575.             if (c == nbColors) {
  576.                 if (nbColors == 256) continue;
  577.                 nbColors++;
  578.                 if (nbColors == 256) {
  579.                     //printf("Colormap entries exhausted. After %d scanned pixels\n", n/4);
  580.                 }
  581.                 colormap[c].alpha = a;
  582.                 colormap[c].red   = r;
  583.                 colormap[c].green = g;
  584.                 colormap[c].blue  = b;
  585.                 *ptr = c;
  586.             }
  587.         }
  588.     } else {
  589.         memcpy(pixels, data, width*height);
  590.         if (tableHasAlpha) {
  591.             int n;
  592.             unsigned char *ptr, *alpha;
  593.  
  594.             alpha_buf = (unsigned char *)malloc(width*height);
  595.             ptr = data;
  596.             alpha = alpha_buf;
  597.             for(n=0; n < width*height; n++, ptr++, alpha++) {
  598.                 *alpha = colormap[*ptr].alpha;
  599.             }
  600.         }
  601.     }
  602.  
  603.     delete data;
  604.     return 0;
  605. }
  606.  
  607.