Skip navigation
Currently Being Moderated

libjpeg / debug

Sep 7, 2010 3:14 PM

Hi,

 

I need to use efficient jpeg encoder in my air project but all compiled libraried i've found* have memory leaks.

 

* libraries i've found:

1) http://www.websector.de/blog/2009/06/21/speed-up-jpeg-encoding-using-a lchemy/

2) http://segfaultlabs.com/devlogs/alchemy-asynchronous-jpeg-encoding

 

I decided to compile code from page 2) and I succeeded but it produces completly black images. I couldn't find anything wrong in the code just by reading it so I started to wonder how could I debug it to find what causes the problem.

 

For example there's a loop where argb row is converted to rgb:

 

for ( j=0,i=0; i<row_stride; i+=3, j+=4 ) {

     rgbRow[i+2] = argbRow[j+3];

     rgbRow[i+1] = argbRow[j+2];

     rgbRow[i] = argbRow[j+1];

};

 

I assume that bitmapData passed to alchemy jpeg enocoder is correct and that libjpeg encoding functions work fine. I'd like to check if bytes in rgbRow are not zeros but I can't find a way how. Could anyone help me, please?

 
Replies
  • Currently Being Moderated
    Sep 7, 2010 3:50 PM   in reply to Piotr Wierzgała

    Hello Piotr,

     

    Flash uses RGBA and LSB .

    http://en.wikipedia.org/wiki/Least_significant_bit

    Your code does not take the alpha channel into account.

     

    Please have a look at this post and search for onFrame()

    http://forums.adobe.com/thread/689742?tstart=0

     

    There are also other posts that explain how to deal with sharing ByteArrays between C and AS.

    This post might help too:

    http://forums.adobe.com/message/2976678#2976678

     

    Good luck,

     

    - Bernd

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 7, 2010 8:13 PM   in reply to Piotr Wierzgała

    I use the library in #2, there's no memory leak (assuming you don't count the 2MB that's required for Alchemy, and only use 1 instance of the library instead of creating multiple). If I get a chance I'll compare my .c file with his to see if there's anything different that might be causing trouble for you.
    It's a very nice library, it's like 10x as fast as the AS3-only jpeg libraries. The JPEGs I'm encoding aren't too big (640x480 max), so I don't even use the async library call, since that is a bit slower

     
    |
    Mark as:
  • Currently Being Moderated
    Sep 9, 2010 9:42 AM   in reply to davr64

    Here's the C code I'm using:

     

     

    /***

         asynchronous jpeg encoding

         see it in action at :
              http://segfaultlabs.com/blog/post/asynchronous-jpeg-encoding

         author: Mateusz Malczak ( http://segfaultlabs.com )

    ***/
    #include <AS3.h>
    #include <stdio.h>
    #include <setjmp.h>
    #include "jerror.h"
    #include "jpeglib.h"

    /* read, write, seek, close a File inside Alchemy, File = ByteArray */
    static int readba(void *cookie, char *dst, int size)
    {
         return AS3_ByteArray_readBytes(dst, (AS3_Val)cookie, size);
    }

    static int writeba(void *cookie, const char *src, int size)
    {
         return AS3_ByteArray_writeBytes((AS3_Val)cookie, (char *)src, size);
    }

    static fpos_t seekba(void *cookie, fpos_t offs, int whence)
    {
         return AS3_ByteArray_seek((AS3_Val)cookie, offs, whence);
    }

    static int closeba(void *cookie)
    {
         AS3_Val zero = AS3_Int(0);
         AS3_SetS((AS3_Val)cookie, "position", zero);
         AS3_Release(zero);
         return 0;
    }


    AS3_Val fileTest( void *data, AS3_Val args )
    {
         /* image dimensions and compression quality */
         int image_width = 0;
         int image_height = 0;
         int quality = 0;
              
         AS3_Val source;

         AS3_Val dest;
         
         /* parse arguments passed from as3 code */
         AS3_ArrayValue( args, "AS3ValType, AS3ValType, IntType, IntType, IntType", &source, &dest, &image_width, &image_height, &quality );

         /* open bytearrayy stream */
         FILE *output = funopen((void *)dest, readba, writeba, seekba, closeba);

         /* jpeg code based on libjpeg example */
         struct jpeg_compress_struct cinfo;
         struct jpeg_error_mgr jerr;
         unsigned char *argbRow = (unsigned char *)malloc( image_width * 4 );
         JSAMPROW row_pointer[1];     
         /* Step 1: allocate and initialize JPEG compression object */
         cinfo.err = jpeg_std_error(&jerr);
         jpeg_create_compress(&cinfo);
         jpeg_stdio_dest(&cinfo, output);
         /* Step 3: set parameters for compression */
         cinfo.image_width = image_width;      /* image width and height, in pixels */
         cinfo.image_height = image_height;
         cinfo.input_components = 3;          /* # of color components per pixel */
         cinfo.in_color_space = JCS_RGB;      /* colorspace of input image */
         jpeg_set_defaults(&cinfo);
         jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
         /* Step 4: Start compressor */
         jpeg_start_compress(&cinfo, TRUE);
         /* Step 5: while (scan lines remain to be written) */
         int i,j, yeld;
         int argb_row_stride = image_width * 4;
         int row_stride = image_width * 3;     /* JSAMPLEs per row in image_buffer */
         yeld = 0;
         while (cinfo.next_scanline < cinfo.image_height)
         {
              /* get lne from input */
              AS3_ByteArray_readBytes( argbRow, source, argb_row_stride );          
              /* skip alpha channel */
                   for ( j=1,i=0; i<row_stride; i+=3,j+=4 )
                        *(unsigned int*)(argbRow+i) = *(unsigned int*)(argbRow+j);
              row_pointer[0] = & argbRow[0];
              (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
              /* next 6 lines can be used to tune asynchronous performance
               * the more flyield's calls, the faster function runs, but
               * also more flash player slow downs
               */
                   yeld += 1;
                        if ( yeld > 10 )
                        {
                             yeld = 0;
                             flyield();
                        };
         }
         
         free( argbRow );
         
         /* Step 6: Finish compression */
         jpeg_finish_compress(&cinfo);
         /* Step 7: release JPEG compression object */
         jpeg_destroy_compress(&cinfo);
         
         fclose( output );

         AS3_Release( source ); // release hold on var passed in
         
         return dest; // returning var auto releases hold on it
    };

    int main()
    {
         AS3_Val encodeAsync_ = AS3_FunctionAsync( NULL, fileTest );
         AS3_Val encode_ = AS3_Function( NULL, fileTest );
         AS3_Val airobj = AS3_Object("encodeAsync: AS3ValType, encode: AS3ValType",
                                            encodeAsync_,
                                            encode_ );
         AS3_Release( encodeAsync_ );
         AS3_Release( encode_ );
         AS3_LibInit( airobj );
         return 0;
    };
     
    |
    Mark as:
  • Currently Being Moderated
    Sep 9, 2010 9:47 AM   in reply to davr64

    And here's how I call it from actionscript:

     

        static private var alchemyJpeg:Object = null; // Alchemy JPEG library

        static private function initAlchemy():void {
            /* init alchemy object */
            var init:CLibInit = new CLibInit(); //get library obejct
            alchemyJpeg = init.init(); // initialize library exported class
        }


        static private function encodeJpeg(bd:BimapData):ByteArray {
            var pixels:ByteArray = bd.getPixels(bd.rect);
            var bytes:ByteArray = new ByteArray();
            pixels.position = 0;
            if(alchemyJpeg == null)
                initAlchemy();
            alchemyJpeg.encode( pixels, bytes, bd.width, bd.height, 80 );
            return bytes;
        }

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 7:07 PM   in reply to davr64

    @Wierzgala

    Thanks for posting the C source code, it's really useful.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 18, 2012 11:05 PM   in reply to davr64

    @davr64

    When the bytes retrieves from C, I use Image.source = bytes, can't display the image, could you help me?

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 20, 2012 9:33 AM   in reply to jasonzhuang

    @jasonzhuang,

     

    Try something like:

        var loader:flash.display.Loader = new flash.display.Loader();
        loader
    .contentLoaderInfo.addEventListener(Event.COMPLETE, function (e:Event) : void {
            image.source
    = new Bitmap(loader.content);
       
    });
        loader
    .loadBytes(bytes);

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points