home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Archived / Updates / Flash / flashplayer / flashlib / c++ / bitmap next >
Encoding:
Text File  |  2000-05-28  |  11.8 KB  |  577 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 buildJpegAlpha(Bitmap *b, unsigned char *buffer)
  129. {
  130.     z_stream    stream;
  131.     int        status;
  132.     unsigned char  *data;
  133.  
  134.     data = new unsigned char[b->width*b->height];
  135.     if (data == NULL)
  136.         return -1;
  137.  
  138.     stream.next_in = buffer;
  139.     stream.avail_in = 1;
  140.     stream.next_out = data;
  141.     stream.avail_out = b->width*b->height;
  142.     stream.zalloc = Z_NULL;
  143.     stream.zfree = Z_NULL;
  144.  
  145.     status = inflateInit(&stream);
  146.  
  147.     while (1) {
  148.         status = inflate(&stream, Z_SYNC_FLUSH) ;
  149.         if (status == Z_STREAM_END) {
  150.             break;
  151.         }
  152.         if (status != Z_OK) {
  153.             printf("Zlib data error : %s\n", stream.msg);
  154.         delete data;
  155.             return -1;
  156.         }
  157.         stream.avail_in = 1;
  158.     }
  159.  
  160.     inflateEnd(&stream);
  161.  
  162.     b->alpha_buf = data;
  163.  
  164.     return 0;
  165. }
  166.  
  167. int
  168. Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset)
  169. {
  170.     struct jpeg_decompress_struct cInfo;
  171.     struct jpeg_source_mgr mySrcMgr;
  172.     MyErrorHandler errorMgr;
  173.     JSAMPROW buffer[1];
  174.     unsigned char *ptrPix;
  175.     int stride;
  176.     long n;
  177.  
  178. #if PRINT&1
  179.         printf("flash: loading jpeg (interchange)\n");
  180. #endif
  181.  
  182.     // Kludge to correct some corrupted files
  183.     if (stream[1] == 0xd9 && stream[3] == 0xd8) {
  184.         stream[3] = 0xd9;
  185.         stream[1] = 0xd8;
  186.     }
  187.  
  188.     // Setup error handler
  189.     cInfo.err = jpeg_std_error(&errorMgr.pub);
  190.     errorMgr.pub.error_exit = errorExit;
  191.  
  192.     if (setjmp(errorMgr.setjmp_buffer)) {
  193.         // JPEG data Error
  194.         jpeg_destroy_decompress(&cInfo);
  195.         if (pixels) {
  196.             delete[] pixels;
  197.             pixels = NULL;
  198.         }
  199.         return -1;
  200.     }
  201.  
  202.     // Set current stream pointer to stream
  203.     inputData = stream;
  204.  
  205.     // Here it's Ok
  206.  
  207.     jpeg_create_decompress(&cInfo);
  208.  
  209.     // Setup source manager structure
  210.     mySrcMgr.init_source = initSource;
  211.     mySrcMgr.fill_input_buffer = fillInputBuffer;
  212.     mySrcMgr.skip_input_data = skipInputData;
  213.     mySrcMgr.resync_to_restart = resyncToRestart;
  214.     mySrcMgr.term_source = termSource;
  215.  
  216.     // Set default source manager
  217.     cInfo.src = &mySrcMgr;
  218.  
  219.     jpeg_read_header(&cInfo, FALSE);
  220.  
  221.     jpeg_read_header(&cInfo, TRUE);
  222.     cInfo.quantize_colors = TRUE;    // Create colormapped image
  223.     jpeg_start_decompress(&cInfo);
  224.  
  225.     // Set objet dimensions
  226.     height = cInfo.output_height;
  227.     width = cInfo.output_width;
  228.         bpl = width;
  229.     pixels = new unsigned char [height*width];
  230.     if (pixels == NULL) {
  231.         jpeg_finish_decompress(&cInfo);
  232.         jpeg_destroy_decompress(&cInfo);
  233.         return -1;
  234.     }
  235.     ptrPix = pixels;
  236.  
  237.     stride = cInfo.output_width * cInfo.output_components;
  238.  
  239.     buffer[0] = (JSAMPROW)malloc(stride);
  240.  
  241.     while (cInfo.output_scanline < cInfo.output_height) {
  242.  
  243.         jpeg_read_scanlines(&cInfo, buffer, 1);
  244.  
  245.         memcpy(ptrPix,buffer[0],stride);
  246.  
  247.         ptrPix+= stride;
  248.     }
  249.  
  250.         free(buffer[0]);
  251.  
  252.     colormap = new Color[cInfo.actual_number_of_colors];
  253.     if (colormap == NULL) {
  254.         delete pixels;
  255.         jpeg_finish_decompress(&cInfo);
  256.         jpeg_destroy_decompress(&cInfo);
  257.         return -1;
  258.     }
  259.     nbColors = cInfo.actual_number_of_colors;
  260.  
  261.     for(n=0; n < nbColors; n++)
  262.     {
  263.         colormap[n].red = cInfo.colormap[0][n];
  264.         colormap[n].green = cInfo.colormap[1][n];
  265.         colormap[n].blue = cInfo.colormap[2][n];
  266.     }
  267.  
  268.     jpeg_finish_decompress(&cInfo);
  269.     jpeg_destroy_decompress(&cInfo);
  270.  
  271.         if (read_alpha) {
  272.             if (buildJpegAlpha(this,  stream + offset) < 0) {
  273.             return -1;
  274.         }
  275.         }
  276.     return 0;
  277. }
  278.  
  279. // Read JPEG image using pre-loaded Tables
  280.  
  281. int
  282. Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream)
  283. {
  284.     JSAMPROW buffer[1];
  285.     unsigned char *ptrPix;
  286.     int stride;
  287.     long n;
  288.     int status;
  289.  
  290. #if PRINT&1
  291.         printf("flash: loading jpeg (abbreviated)\n");
  292. #endif
  293.  
  294.     // Set current stream pointer to stream
  295.     inputData = stream;
  296.  
  297.     // Error handler
  298.     if (setjmp(jpegErrorMgr.setjmp_buffer)) {
  299.         // JPEG data Error
  300.         //jpeg_destroy_decompress(&jpegObject);
  301.         if (pixels) {
  302.             delete[] pixels;
  303.             pixels = NULL;
  304.         }
  305.         return -1;
  306.     }
  307.  
  308.     // Here it's ok
  309.  
  310.     jpeg_read_header(&jpegObject, TRUE);
  311.     jpegObject.quantize_colors = TRUE;    // Create colormapped image
  312.     jpeg_start_decompress(&jpegObject);
  313.  
  314.     // Set objet dimensions
  315.     height = jpegObject.output_height;
  316.     width = jpegObject.output_width;
  317.         bpl = width;
  318.     pixels = new unsigned char [height*width];
  319.     if (pixels == NULL) {
  320.         jpeg_finish_decompress(&jpegObject);
  321.         return -1;
  322.     }
  323.     ptrPix = pixels;
  324.  
  325.     stride = jpegObject.output_width * jpegObject.output_components;
  326.  
  327.     buffer[0] = (JSAMPROW)malloc(stride);
  328.  
  329.     while (jpegObject.output_scanline < jpegObject.output_height) {
  330.  
  331.         status = jpeg_read_scanlines(&jpegObject, buffer, 1);
  332.  
  333.         memcpy(ptrPix,buffer[0],stride);
  334.  
  335.         ptrPix+= stride;
  336.     }
  337.  
  338.         free(buffer[0]);
  339.  
  340.     colormap = new Color[jpegObject.actual_number_of_colors];
  341.     if (colormap == NULL) {
  342.         jpeg_finish_decompress(&jpegObject);
  343.         delete pixels;
  344.         return -1;
  345.     }
  346.     nbColors = jpegObject.actual_number_of_colors;
  347.  
  348.     for(n=0; n < nbColors; n++)
  349.     {
  350.         colormap[n].red = jpegObject.colormap[0][n];
  351.         colormap[n].green = jpegObject.colormap[1][n];
  352.         colormap[n].blue = jpegObject.colormap[2][n];
  353.     }
  354.  
  355.     status = jpeg_finish_decompress(&jpegObject);
  356.  
  357.     return 0;
  358. }
  359.  
  360. // Just init JPEG object and read JPEG Tables
  361.  
  362. int
  363. Bitmap::readJpegTables(unsigned char *stream)
  364. {
  365.     if (haveTables) {
  366.         //Error, it has already been initialized
  367.         return -1;
  368.     }
  369.  
  370.     // Setup error handler
  371.     jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
  372.     jpegErrorMgr.pub.error_exit = errorExit;
  373.  
  374.     if (setjmp(jpegErrorMgr.setjmp_buffer)) {
  375.         // JPEG data Error
  376.         jpeg_destroy_decompress(&jpegObject);
  377.         return -1;
  378.     }
  379.  
  380.     // Set current stream pointer to stream
  381.     inputData = stream;
  382.  
  383.     // Here it's Ok
  384.  
  385.     jpeg_create_decompress(&jpegObject);
  386.  
  387.     // Setup source manager structure
  388.     jpegSourceManager.init_source = initSource;
  389.     jpegSourceManager.fill_input_buffer = fillInputBuffer;
  390.     jpegSourceManager.skip_input_data = skipInputData;
  391.     jpegSourceManager.resync_to_restart = resyncToRestart;
  392.     jpegSourceManager.term_source = termSource;
  393.  
  394.     // Set default source manager
  395.     jpegObject.src = &jpegSourceManager;
  396.  
  397.     jpeg_read_header(&jpegObject, FALSE);
  398.  
  399.     haveTables = 1;
  400.  
  401.     return 0;
  402. }
  403.  
  404. int Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize)
  405. {
  406.     z_stream    stream;
  407.     int        status;
  408.     unsigned char  *data;
  409.  
  410. #if PRINT&1
  411.         printf("flash: loading with zlib\n");
  412. #endif
  413.  
  414.     this->width = width;
  415.     this->height = height;
  416.         this->bpl = width;
  417.  
  418.     stream.next_in = buffer;
  419.     stream.avail_in = 1;
  420.     stream.zalloc = Z_NULL;
  421.     stream.zfree = Z_NULL;
  422.  
  423.     tableSize++;
  424.  
  425.     // Uncompress Color Table
  426.     if (format == 3) {
  427.         unsigned char *colorTable;
  428.         long n;
  429.  
  430.         // Ajust width for 32 bit padding
  431.         width = (width+3)/4*4;
  432.         this->width = width;
  433.         this->bpl = width;
  434.  
  435.         depth = 1;
  436.         colorTable = new unsigned char[tableSize*3];
  437.         if (colorTable == NULL) {
  438.             return -1;
  439.         }
  440.  
  441.         stream.next_out = colorTable;
  442.         stream.avail_out = tableSize*3;
  443.  
  444.         inflateInit(&stream);
  445.  
  446.         while (1) {
  447.             status = inflate(&stream, Z_SYNC_FLUSH);
  448.             if (status == Z_STREAM_END) {
  449.                     break;
  450.             }
  451.             if (status != Z_OK) {
  452.                 printf("Zlib cmap error : %s\n", stream.msg);
  453.                 return -1;
  454.             }
  455.             stream.avail_in = 1;
  456.             // Colormap if full
  457.             if (stream.avail_out == 0) {
  458.                 break;
  459.             }
  460.         }
  461.  
  462.         nbColors = tableSize;
  463.  
  464.         colormap = new Color[nbColors];
  465.         if (colormap == NULL) {
  466.             delete colorTable;
  467.             return -1;
  468.         }
  469.  
  470.         for(n=0; n < nbColors; n++) {
  471.             colormap[n].red = colorTable[n*3+0];
  472.             colormap[n].green = colorTable[n*3+1];
  473.             colormap[n].blue = colorTable[n*3+2];
  474.         }
  475.  
  476.         delete colorTable;
  477.  
  478.     } else if (format == 4) {
  479.         depth = 2;
  480.     } else if (format == 5) {
  481.         depth = 4;
  482.     }
  483.  
  484.     data = new unsigned char[depth*width*height];
  485.     if (data == NULL) {
  486.         if (colormap) delete colormap;
  487.         return -1;
  488.     }
  489.  
  490.     stream.next_out = data;
  491.     stream.avail_out = depth*width*height;
  492.  
  493.     if (format != 3) {
  494.         status = inflateInit(&stream);
  495.     }
  496.  
  497.     while (1) {
  498.         status = inflate(&stream, Z_SYNC_FLUSH) ;
  499.         if (status == Z_STREAM_END) {
  500.                 break;
  501.         }
  502.         if (status != Z_OK) {
  503.             printf("Zlib data error : %s\n", stream.msg);
  504.             delete data;
  505.             return -1;
  506.         }
  507.         stream.avail_in = 1;
  508.     }
  509.  
  510.     inflateEnd(&stream);
  511.  
  512.     pixels = new unsigned char [height*width];
  513.     if (pixels == NULL) {
  514.         if (colormap) delete colormap;
  515.         delete data;
  516.         return -1;
  517.     }
  518.  
  519.     if (format != 3) {
  520.         int n,c;
  521.         unsigned char r,g,b,a;
  522.         unsigned char *ptr;
  523.  
  524.                 r = g = b = a = 0; /* to supress warnings */
  525.  
  526.         nbColors = 0;
  527.         colormap = new Color[256];
  528.         if (colormap == NULL) {
  529.             delete data;
  530.             delete pixels;
  531.             return -1;
  532.         }
  533.                 memset(colormap, 0, 256 * sizeof(Color));
  534.         ptr = pixels;
  535.  
  536.         for(n=0; n < width*height*depth; n+=depth,ptr++) {
  537.  
  538.             switch (format) {
  539.                 case 4:
  540.                     break;
  541.                 case 5:
  542.                     a = data[n];
  543.                     // Reduce color dynamic range
  544.                     r = data[n+1]&0xe0;
  545.                     g = data[n+2]&0xe0;
  546.                     b = data[n+3]&0xe0;
  547.                     break;
  548.             }
  549.             for(c=0; c < nbColors; c++) {
  550.                 if (r == colormap[c].red
  551.                 &&  g == colormap[c].green
  552.                 &&  b == colormap[c].blue) {
  553.                     *ptr = c;
  554.                     break;
  555.                 }
  556.             }
  557.             if (c == nbColors) {
  558.                 if (nbColors == 256) continue;
  559.                 nbColors++;
  560.                 if (nbColors == 256) {
  561.                     //printf("Colormap entries exhausted. After %d scanned pixels\n", n/4);
  562.                 }
  563.                 colormap[c].alpha = a;
  564.                 colormap[c].red   = r;
  565.                 colormap[c].green = g;
  566.                 colormap[c].blue  = b;
  567.                 *ptr = c;
  568.             }
  569.         }
  570.     } else {
  571.         memcpy(pixels, data, width*height);
  572.     }
  573.  
  574.     delete data;
  575.     return 0;
  576. }
  577.