Thread: Need help rotating a JEPG using libjpeg v9

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    9

    Need help rotating a JEPG using libjpeg v9

    I've spent several days going through the motions getting libjpeg v9 compiled. I can run jpegtran.exe, which is one of the compiled files to successfully rotate jpeg's divisible by 16 in WxH. Now I'm trying to implement a code based solution using the included example.c and transupp.c functions. There may be a better way than this but I'm not sure how else. transupp.c has the function do_rot_180 and example.c has read_JPEG_file and write_JPEG_file and I've tried making a project that includes those functions and the #include files that each file requires but it's not compiling.

    I'm kind of a noob when it comes to the more advanced aspects of C++ so I'm sure I'm missing something with the .DLL or supposedly a .lib (I can't find one) or something. I'm good at working within functional projects but that's just because all of the more complicated set up stuff is taken care of for the most part.

    Current code:
    Code:
    /*********************************************************************************/
    /* Defines                                                                         */
    /*********************************************************************************/
    
    #define JPEG_INTERNALS
    
    /*********************************************************************************/
    /* Includes                                                                         */
    /*********************************************************************************/
    
    //extern "C"
    //{
    //#include "include/jpeglib.h"
    //}
    
    //#include "include/jinclude.h"
    //#include "include/jpeglib.h"
    //#include "include/transupp.h"
    //#include "include/jerror.h"
    
    #include <stdio.h>
    #include <iostream>
    
    #include "jinclude.h"
    #include "jpeglib.h"
    #include "transupp.h"
    #include "jerror.h"
    
    #include <ctype.h>
    #include <setjmp.h>
    
    //using namespace std;
    
    /*********************************************************************************/
    /* External Declarations                                                         */
    /*********************************************************************************/
    
    extern JSAMPLE * image_buffer;    /* Points to large array of R,G,B-order data      */
    extern int image_height;        /* Number of rows in image                          */
    extern int image_width;            /* Number of columns in image                      */
    
    /*********************************************************************************/
    /* General Functions                                                             */
    /*********************************************************************************/
    
    LOCAL(void)
    do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
            JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
            jvirt_barray_ptr *src_coef_arrays,
            jvirt_barray_ptr *dst_coef_arrays)
    /* 180 degree rotation is equivalent to
     *   1. Vertical mirroring;
     *   2. Horizontal mirroring.
     * These two steps are merged into a single processing routine.
     */
    {
      JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
      JDIMENSION x_crop_blocks, y_crop_blocks;
      int ci, i, j, offset_y;
      JBLOCKARRAY src_buffer, dst_buffer;
      JBLOCKROW src_row_ptr, dst_row_ptr;
      JCOEFPTR src_ptr, dst_ptr;
      jpeg_component_info *compptr;
    
      MCU_cols = srcinfo->output_width /
        (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
      MCU_rows = srcinfo->output_height /
        (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
    
      for (ci = 0; ci < dstinfo->num_components; ci++) {
        compptr = dstinfo->comp_info + ci;
        comp_width = MCU_cols * compptr->h_samp_factor;
        comp_height = MCU_rows * compptr->v_samp_factor;
        x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
        y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
        for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
         dst_blk_y += compptr->v_samp_factor) {
          dst_buffer = (*srcinfo->mem->access_virt_barray)
        ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
         (JDIMENSION) compptr->v_samp_factor, TRUE);
          if (y_crop_blocks + dst_blk_y < comp_height) {
        /* Row is within the vertically mirrorable area. */
        src_buffer = (*srcinfo->mem->access_virt_barray)
          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
           comp_height - y_crop_blocks - dst_blk_y -
           (JDIMENSION) compptr->v_samp_factor,
           (JDIMENSION) compptr->v_samp_factor, FALSE);
          } else {
        /* Bottom-edge rows are only mirrored horizontally. */
        src_buffer = (*srcinfo->mem->access_virt_barray)
          ((j_common_ptr) srcinfo, src_coef_arrays[ci],
           dst_blk_y + y_crop_blocks,
           (JDIMENSION) compptr->v_samp_factor, FALSE);
          }
          for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
        dst_row_ptr = dst_buffer[offset_y];
        if (y_crop_blocks + dst_blk_y < comp_height) {
          /* Row is within the mirrorable area. */
          src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
          for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
            dst_ptr = dst_row_ptr[dst_blk_x];
            if (x_crop_blocks + dst_blk_x < comp_width) {
              /* Process the blocks that can be mirrored both ways. */
              src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
              for (i = 0; i < DCTSIZE; i += 2) {
            /* For even row, negate every odd column. */
            for (j = 0; j < DCTSIZE; j += 2) {
              *dst_ptr++ = *src_ptr++;
              *dst_ptr++ = - *src_ptr++;
            }
            /* For odd row, negate every even column. */
            for (j = 0; j < DCTSIZE; j += 2) {
              *dst_ptr++ = - *src_ptr++;
              *dst_ptr++ = *src_ptr++;
            }
              }
            } else {
              /* Any remaining right-edge blocks are only mirrored vertically. */
              src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
              for (i = 0; i < DCTSIZE; i += 2) {
            for (j = 0; j < DCTSIZE; j++)
              *dst_ptr++ = *src_ptr++;
            for (j = 0; j < DCTSIZE; j++)
              *dst_ptr++ = - *src_ptr++;
              }
            }
          }
        } else {
          /* Remaining rows are just mirrored horizontally. */
          src_row_ptr = src_buffer[offset_y];
          for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
            if (x_crop_blocks + dst_blk_x < comp_width) {
              /* Process the blocks that can be mirrored. */
              dst_ptr = dst_row_ptr[dst_blk_x];
              src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
              for (i = 0; i < DCTSIZE2; i += 2) {
            *dst_ptr++ = *src_ptr++;
            *dst_ptr++ = - *src_ptr++;
              }
            } else {
              /* Any remaining right-edge blocks are only copied. */
              jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
                      dst_row_ptr + dst_blk_x,
                      (JDIMENSION) 1);
            }
          }
        }
          }
        }
      }
    }
    
    GLOBAL(int)
    read_JPEG_file (char * filename)
    {
        struct jpeg_decompress_struct cinfo;
        //struct my_error_mgr jerr;
    
        FILE * infile;            /* source file                                          */
        JSAMPARRAY buffer;        /* Output row buffer                                 */
        int row_stride;            /* physical row width in output buffer                  */
    
        if ((infile = fopen(filename, "rb")) == NULL) {
            fprintf(stderr, "can't open %s\n", filename);
            return 0;
        }
    
    //    cinfo.err = jpeg_std_error(&jerr.pub);
    //    jerr.pub.error_exit = my_error_exit;
    //
    //    if (setjmp(jerr.setjmp_buffer)) {
    //        /* If we get here, the JPEG code has signaled an error.
    //         * We need to clean up the JPEG object, close the input file, and return.
    //         */
    //        jpeg_destroy_decompress(&cinfo);
    //        fclose(infile);
    //        return 0;
    //    }
    
        jpeg_create_decompress(&cinfo);
        jpeg_stdio_src(&cinfo, infile);
    
        (void) jpeg_read_header(&cinfo, TRUE);
    
    //    (void) jpeg_start_decompress(&cinfo);
    //
    //    row_stride = cinfo.output_width * cinfo.output_components;
    //
    //    buffer = (*cinfo.mem->alloc_sarray)
    //            ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
    //
    //    while (cinfo.output_scanline < cinfo.output_height) {
    //        /* jpeg_read_scanlines expects an array of pointers to scanlines.
    //         * Here the array is only one element long, but you could ask for
    //         * more than one scanline at a time if that's more convenient.
    //         */
    //        (void) jpeg_read_scanlines(&cinfo, buffer, 1);
    //        /* Assume put_scanline_someplace wants a pointer and sample count. */
    //        put_scanline_someplace(buffer[0], row_stride);
    //    }
    //
    //    (void) jpeg_finish_decompress(&cinfo);
    //    jpeg_destroy_decompress(&cinfo);
    
        fclose(infile);
        return 1;
    }
    
    /*********************************************************************************/
    /* Main Execution Block                                                             */
    /*********************************************************************************/
    
    int main() {
    
    
        return 0;
    }
    
    /*********************************************************************************/
    /* End of Program                                                                 */
    /*********************************************************************************/
    The issue right now, assuming what I'm doing is in the right direction, is that `jpeg_CreateDecompress', `jpeg_stdio_src', and `jpeg_read_header' claim to be undefined.

    Also, I'm doing in this the latest Eclipse CDT on Windows 7 if that makes any difference.
    Last edited by Xenosis; 01-31-2013 at 01:38 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > #include "jinclude.h"
    > #include "jpeglib.h"
    > #include "transupp.h"
    > #include "jerror.h"
    So where did you get all these files from?

    If you downloaded and unzipped some JPEG SDK package, you should have got the library files as well.
    They might be .dll files or .lib files.

    From the look of things, you haven't told the linker where to find the library files.

    On the command line, the full command might be
    gcc -I./include -L./lib prog.cpp -llibjpeg.lib

    The -I path you might have already added to your project settings for the compiler.
    The -L path and -l filename need to be added to the project settings for the linker.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    Thanks for the reply.

    I compiled libjpeg v9 myself using ./configure --enable-shared --enable-static & make in mingw shell. Output for ./configure:
    Code:
    ild
    checking for gcc... gcc
    checking whether the C compiler (gcc  ) works... yes
    checking whether the C compiler (gcc  ) is a cross-compiler... no
    checking whether we are using GNU C... yes
    checking how to run the C preprocessor... gcc -E
    checking for function prototypes... yes
    checking for stddef.h... yes
    checking for stdlib.h... yes
    checking for string.h... yes
    checking for size_t... yes
    checking for type unsigned char... yes
    checking for type unsigned short... yes
    checking for type void... yes
    checking for working const... yes
    checking for inline... __inline__
    checking for broken incomplete types... ok
    checking for short external names... ok
    checking to see if char is signed... yes
    checking to see if right shift is signed... yes
    checking to see if fopen accepts b spec... yes
    checking for a BSD compatible install... /bin/install -c
    checking for ranlib... ranlib
    checking host system type... i386-pc-mingw32
    checking for ranlib... ranlib
    checking for gcc... gcc
    checking whether we are using GNU C... yes
    checking for gcc option to produce PIC... -fPIC
    checking if gcc PIC flag -fPIC works... no
    checking if gcc static flag -static works... -static
    checking whether ln -s works... no
    checking for ld used by GCC... ./c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../
    ../mingw32/bin/ld.exe
    checking if the linker (./c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../ming
    w32/bin/ld.exe) is GNU ld... yes
    checking whether the linker (./c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../..
    /mingw32/bin/ld.exe) supports shared libraries... yes
    checking for BSD-compatible nm... /mingw/bin/nm
    checking command to parse /mingw/bin/nm output... no
    checking how to hardcode library paths into programs... immediate
    checking for ./c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.
    exe option to reload object files... -r
    checking dynamic linker characteristics... no
    checking if libtool supports shared libraries... no
    checking whether to build shared libraries... no
    checking whether to build static libraries... yes
    checking for objdir... .libs
    creating libtool
    checking libjpeg version number... 62
    creating ./config.status
    creating Makefile
    creating jconfig.h
    jconfig.h is unchanged
    I just noticed that the config/make apparently isn't making a shared library (I honestly don't know what that is anyways).

    All the include files are in include/ of the project folder and I set the project to look to include/ for include files. The include files resolve just fine - that's the weird part. I've added the correct paths for the libs folder (containing .a and .la file) and the include folder (containing the headers in the code).

    All I got in terms of a lib was a .a and a .la - no .lib. Do you know how I can get a .lib?

    I actually am trying 6b now since I wasn't having any luck with 9 and for the most part the same issue is here. Undefined references to functions that are defined in the include include files. v9 made a .DLL while v6b did not..
    Last edited by Xenosis; 01-31-2013 at 03:11 PM.

  4. #4
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    Is there a time limit on editing? I've literally never double posted anywhere because I always edit but the edit button disappeared.

    I found this, which seems to be the only indication of a libjpeg.lib in the install.doc:

    Note that you must make libjpeg.lib before making cjpeg.ttp, djpeg.ttp,
    or jpegtran.ttp. You'll have to perform the self-test by hand.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > All I got in terms of a lib was a .a and a .la - no .lib. Do you know how I can get a .lib?
    .a should be fine - it's the default suffix for a library on Unix/Linux systems.

    In which case, if you have libjpeg.a, the thing you need to tell the linker is -ljpeg
    The lib prefix and .a suffix are assumed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    Ah ha! I assumed that -L with the libs directory was enough and -l libjpeg was redundant.

    That totally worked though, thanks!

    Now I have to figure out how to use do_rot_180 inline with the functions.

  7. #7
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    Hmm.. running into more issues. I'm testing two builds v6b and v9 pulling the core contents of jpegtran.c. The code is essentially identical on both but the includes/libraries differ I'm sure.

    For v6b I am getting this issue:

    Code:
    g++ "-LC:\\path\\path\\workspace2\\jpeg6bmanip\\libs" -o jpeg6bmanip.exe jpeg6bmanip.o -llibjpeg.a -llibjpeg.la 
    c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: cannot find -llibjpeg.a
    c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: cannot find -llibjpeg.la
    collect2.exe: error: ld returned 1 exit status
    For v9 I am getting these issues:

    Code:
    g++ "-IC:\\path\\directory\\workspace2\\jpegManipulator\\include" -O0 -g3 -Wall -c -fmessage-length=0 -o jpegManipulator.o "..\\jpegManipulator.cpp" 
    g++ "-LC:\\path\\directory\\workspace2\\jpegManipulator\\lib" -o jpegManipulator.exe jpegManipulator.o -llibjpeg.a -llibjpeg.dll.a -llibjpeg.la 
    c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: cannot find -llibjpeg.a
    c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: cannot find -llibjpeg.dll.a
    c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: cannot find -llibjpeg.la
    collect2.exe: error: ld returned 1 exit status
    Code:
    g++ "-IC:\\path\\directory\\workspace2\\jpegManipulator\\include" -O0 -g3 -Wall -c -fmessage-length=0 -o jpegManipulator.o "..\\jpegManipulator.cpp" 
    g++ "-LC:\\path\\directory\\workspace2\\jpegManipulator\\lib" -o jpegManipulator.exe jpegManipulator.o -llibjpeg 
    jpegManipulator.o: In function `main':
    C:\path\directory\workspace2\jpegManipulator\Debug/../jpegManipulator.cpp:255: undefined reference to `jcopy_markers_setup(jpeg_decompress_struct*, JCOPY_OPTION)'
    C:\path\directory\workspace2\jpegManipulator\Debug/../jpegManipulator.cpp:258: undefined reference to `jtransform_request_workspace(jpeg_decompress_struct*, jpeg_transform_info*)'
    C:\path\directory\workspace2\jpegManipulator\Debug/../jpegManipulator.cpp:265: undefined reference to `jtransform_adjust_parameters(jpeg_decompress_struct*, jpeg_compress_struct*, jvirt_barray_control**, jpeg_transform_info*)'
    C:\path\directory\workspace2\jpegManipulator\Debug/../jpegManipulator.cpp:269: undefined reference to `jcopy_markers_execute(jpeg_decompress_struct*, jpeg_compress_struct*, JCOPY_OPTION)'
    C:\path\directory\workspace2\jpegManipulator\Debug/../jpegManipulator.cpp:273: undefined reference to `jtransform_execute_transform(jpeg_decompress_struct*, jpeg_compress_struct*, jvirt_barray_control**, jpeg_transform_info*)'
    collect2.exe: error: ld returned 1 exit status

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    For the first one, it's worth using file explorer to look in C:\\path\\path\\workspace2\\jpeg6bmanip\\libs to see what the actual library names are.

    Next, it's worth experimenting with the syntax for the -l option.
    I don't know which variation MinGW on Windows uses, so some experimentation is needed. If you pass the -v option when you're linking object files with libraries to produce executables, you'll get a lot more information (like the syntax of -L and -l options).

    > c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe
    Check to see if you have the 'nm' program.

    This handy tool can tell you what symbol names reside in an object file or library.
    Eg.
    nm libjpeg.a
    Best to redirect the output to a file you can view in an editor
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    I have verified the file names and their existence in the lib/libs folders.

    I do have nm.exe in c:/mingw/bin/

    I tried executing nm.exe on libjpeg.a but that info is less than useless to me... I wouldn't know where/how to being interpreting it.

    I appreciate the suggestions though. libjpeg has been a nightmare from the beginning and its cursed 'flexibility' is making it a ridiculous task to just port a rotate function.

    I'm pretty much about ready to give up on it entirely because I'm not even sure (if I can ever get it to compile) that I'd be able to integrate it into where I'd need to.
    Last edited by Xenosis; 02-01-2013 at 01:26 PM.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    In the nm output, look for things like
    jcopy_markers_setup(jpeg_decompress_struct*, JCOPY_OPTION)

    Start with something vague, like 'jcopy' to begin with, and see if you can spot where the difference emerges.

    Unless you also compiled the libraries with your own compiler, there is a chance that the library is either not built as a C++ library, or it was built with a different C++ compiler.

    In fact, if it's a C library, you should have
    Code:
    extern "C" {
    #include "jinclude.h"
    #include "jpeglib.h"
    #include "transupp.h"
    #include "jerror.h"
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    ill give nm another shot.

    I compiled the .a file from the mingw shell for the version used in eclipse but the libjpeg stuff has its own make and ./configure routine so perhaps it wasn't made to work for my purposes?

    This is the output for ./configure:

    dll - configure script not enabling make to generate shared library - Stack Overflow

  12. #12
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    I know it's not an answer... but have you considered using a ready-made binary version for Windows? All you need to develop programs with it are the header files and then of course the library files themselves.
    I know that's not the right answer but some things just don't compile easily on Windows.

    Jpeg for Windows

  13. #13
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    That is essentially what I'm going for c99tutorial. I have a project built for winCE/win32 that has jpeg libs included and they compile fine. I would be just fine using ready-made binaries as long as they offer lossless jpeg rotation.

    The current problem is noted in edit 3 here: http://stackoverflow.com/q/14631530/1666510
    Last edited by Xenosis; 02-04-2013 at 09:40 AM.

  14. #14
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The linker flag "-lfoo" means to link with the library called "libfoo.a".

    Therefore if your library is called libjpeg.a, you must pass "-ljpeg." If your library name does not conform to the libXXX.a format, then you cannot link using the -l flag at all, and must instead explicitly give the name AND PATH of the .a file (WITHOUT the -l part)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  15. #15
    Registered User
    Join Date
    Jan 2013
    Posts
    9
    Quote Originally Posted by brewbuck View Post
    The linker flag "-lfoo" means to link with the library called "libfoo.a".

    Therefore if your library is called libjpeg.a, you must pass "-ljpeg." If your library name does not conform to the libXXX.a format, then you cannot link using the -l flag at all, and must instead explicitly give the name AND PATH of the .a file (WITHOUT the -l part)
    Thanks, that ended up being the issue there. Unfortunately after that, I hit another snag: c++ - Eclipse CDT unable to find library file - Stack Overflow

    Code:
    No source file named jpeglib.h.
    I get the above output upon debugging the program AFTER compiling it successfully. It won't run maybe because it's looking for that .h somewhere that it isn't?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. trouble using libjpeg
    By divsragha in forum Game Programming
    Replies: 7
    Last Post: 07-12-2011, 10:17 AM
  2. linker error when using libjpeg
    By s-men in forum C++ Programming
    Replies: 2
    Last Post: 08-21-2008, 10:02 AM
  3. libjpeg problems linking in cpp
    By parad0x13 in forum C++ Programming
    Replies: 4
    Last Post: 07-19-2008, 04:29 PM
  4. libjpeg sgefault on jpeg_read_scanlines()
    By Syko in forum C Programming
    Replies: 6
    Last Post: 11-27-2005, 02:14 AM
  5. Compiler errors when using libjpeg.
    By Nikanoru in forum C++ Programming
    Replies: 11
    Last Post: 08-07-2003, 06:46 AM

Tags for this Thread