ImageMagick and lossless JPEG rotation?

Discussion in 'Digital Photography' started by Jim Garrison, Sep 30, 2003.

  1. Jim Garrison

    Jim Garrison Guest

    Can anyone tell me if ImageMagick does lossless 90-degree rotation?

    TIA,
    Jim Garrison
    Jim Garrison, Sep 30, 2003
    #1
    1. Advertising

  2. Jim Garrison

    Mike Graham Guest

    In article <Ig6eb.171228$>, Jim Garrison wrote:

    > Can anyone tell me if ImageMagick does lossless 90-degree rotation?


    I don't believe that it does. There is a list of lossless rotators at
    http://www.jpegclub.org, and it's not on the list. Mind you, there is only
    *one* linux app on the list, and I'm finding it to be a pig to install on my
    system, so I'd love to find out that I'm wrong about ImageMagick.

    --
    =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Mike Graham | Metalworker, rustic, part-time zealot.
    mike 'at' metalmangler.com |
    <http://www.metalmangler.com>| Caledon, Ontario, Canada

    Lousy photographer with a really nice camera - Olympus C3020Zoom.
    When that's broken I can use my Nikon D100 :cool:
    <http://www.metalmangler.com/photos/photos.htm>
    <http://www.photo.net/shared/community-member?user_id=766040>
    Mike Graham, Sep 30, 2003
    #2
    1. Advertising

  3. On Tue, 30 Sep 2003 05:58:23 -0400, Mike Graham wrote:

    > In article <Ig6eb.171228$>, Jim Garrison
    > wrote:
    >
    >> Can anyone tell me if ImageMagick does lossless 90-degree rotation?

    >
    > I don't believe that it does. There is a list of lossless rotators at
    > http://www.jpegclub.org, and it's not on the list. Mind you, there is
    > only *one* linux app on the list, and I'm finding it to be a pig to
    > install on my system, so I'd love to find out that I'm wrong about
    > ImageMagick.


    AFAIK, you're not wrong - Imagemagick doesn't do lossless rotation. I use
    jpegtran to do lossless rotation, which works very well. I have a shell
    script which goes through each JPEG file in a directory, reads the
    orientation tag from EXIF data, then calls jpegtran will appropriate
    options to losslessly rotate the JPEG and preserve EXIF data. I can post
    it if there's any interest.

    Mike.
    Mike Brodbelt, Sep 30, 2003
    #3
  4. Mike Brodbelt <m.brodbelt@__NO_SPAM_PLEASE__coruscant.demon.co.uk> writes:
    > AFAIK, you're not wrong - Imagemagick doesn't do lossless rotation. I use
    > jpegtran to do lossless rotation, which works very well. I have a shell
    > script which goes through each JPEG file in a directory, reads the
    > orientation tag from EXIF data, then calls jpegtran will appropriate
    > options to losslessly rotate the JPEG and preserve EXIF data. I can post
    > it if there's any interest.


    I wouldn't mind seeing the script.

    --
    Richard W Kaszeta

    http://www.kaszeta.org/rich
    Richard Kaszeta, Sep 30, 2003
    #4
  5. Jim Garrison

    Ron Olsen Guest

    m.brodbelt@__NO_SPAM_PLEASE__coruscant.demon.co.uk wrote:
    >
    > AFAIK, you're not wrong - Imagemagick doesn't do lossless rotation. I use
    > jpegtran to do lossless rotation, which works very well. I have a shell
    > script which goes through each JPEG file in a directory, reads the
    > orientation tag from EXIF data, then calls jpegtran will appropriate
    > options to losslessly rotate the JPEG and preserve EXIF data. I can post
    > it if there's any interest.
    >


    jhead also does automatic rotation from the orientation tag, using jpegtran
    to do the rotation:

    http://www.sentex.net/~mwandel/jhead/

    --
    Ron Olsen
    Ron Olsen, Sep 30, 2003
    #5
  6. Jim Garrison

    Mike Graham Guest

    In article <pan.2003.09.30.12.05.04.543810@__NO_SPAM_PLEASE__coruscant.demon.co.uk>, Mike Brodbelt wrote:

    > AFAIK, you're not wrong - Imagemagick doesn't do lossless rotation. I use
    > jpegtran to do lossless rotation, which works very well. I have a shell
    > script which goes through each JPEG file in a directory, reads the
    > orientation tag from EXIF data, then calls jpegtran will appropriate
    > options to losslessly rotate the JPEG and preserve EXIF data. I can post
    > it if there's any interest.


    Oooh! Oooh! I'm interested! Cool idea! In exchange I can offer you
    something I found in the archives of the Nikon D100 mailing list. It's a
    perl script written by one David Proulx, and it renames image files to the
    date stored in the metadata, right down to the second. Very handy! The
    date is done YYYYMMDD-hh:mm:ss so that files are sorted chronologically.
    The readme for the file has no copyright info or anything, so I am confident
    that it is public domain.

    --
    =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Mike Graham | Metalworker, rustic, part-time zealot.
    mike 'at' metalmangler.com |
    <http://www.metalmangler.com>| Caledon, Ontario, Canada

    Lousy photographer with a really nice camera - Olympus C3020Zoom.
    When that's broken I can use my Nikon D100 :cool:
    <http://www.metalmangler.com/photos/photos.htm>
    <http://www.photo.net/shared/community-member?user_id=766040>
    Mike Graham, Sep 30, 2003
    #6
  7. Jim Garrison

    Mike Graham Guest

    In article <>, Ron Olsen wrote:

    > jhead also does automatic rotation from the orientation tag, using jpegtran
    > to do the rotation:
    >
    > http://www.sentex.net/~mwandel/jhead/


    Wow. It looks like jhead does a *lot*.

    --
    =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    Mike Graham | Metalworker, rustic, part-time zealot.
    mike 'at' metalmangler.com |
    <http://www.metalmangler.com>| Caledon, Ontario, Canada

    Lousy photographer with a really nice camera - Olympus C3020Zoom.
    When that's broken I can use my Nikon D100 :cool:
    <http://www.metalmangler.com/photos/photos.htm>
    <http://www.photo.net/shared/community-member?user_id=766040>
    Mike Graham, Sep 30, 2003
    #7
  8. On Tue, 30 Sep 2003 16:38:15 -0400, Mike Graham wrote:

    > Oooh! Oooh! I'm interested! Cool idea! In exchange I can offer you
    > something I found in the archives of the Nikon D100 mailing list. It's a
    > perl script written by one David Proulx, and it renames image files to the
    > date stored in the metadata, right down to the second. Very handy! The
    > date is done YYYYMMDD-hh:mm:ss so that files are sorted chronologically.
    > The readme for the file has no copyright info or anything, so I am confident
    > that it is public domain.


    Ok, I'm attaching it below. There are two parts - a shell script, and a
    small c program which must be available on the path when you run the shell
    script. You also need jpegtran installed and available. There may be other
    ways to do this now - I've had this for ages, and it's always worked well
    for me. I found it on as web forum somewhere ages ago, IIRR.

    Enjoy,

    Mike.


    exifautotran.sh - shell script wrapper
    ==========8<==========8<==========8<==========8<==========8<==========8<
    # exifautotran [list of files]
    #
    # Transforms Exif files so that Orientation becomes 1
    #
    for i
    do
    case `jpegexiforient -n "$i"` in
    1) transform="";;
    2) transform="-flip horizontal";;
    3) transform="-rotate 180";;
    4) transform="-flip vertical";;
    5) transform="-transpose";;
    6) transform="-rotate 90";;
    7) transform="-transverse";;
    8) transform="-rotate 270";;
    *) transform="";;
    esac
    if test -n "$transform"; then
    echo Executing: jpegtran -copy all $transform $i
    jpegtran -copy all $transform "$i" > tempfile
    if test $? -ne 0; then
    echo Error while transforming $i - skipped.
    else
    rm "$i"
    mv tempfile "$i"
    jpegexiforient -1 "$i" > /dev/null
    fi
    fi
    done
    ==========8<==========8<==========8<==========8<==========8<==========8<
    jpegexiforient.c - compile with "gcc -O2 -o jpegexiforient jpegexiforient.c"
    ==========8<==========8<==========8<==========8<==========8<==========8<
    /*
    * jpegexiforient.c
    *
    * This is a utility program to get and set the Exif Orientation Tag.
    * It can be used together with jpegtran in scripts for automatic
    * orientation correction of digital camera pictures.
    *
    * The Exif orientation value gives the orientation of the camera
    * relative to the scene when the image was captured. The relation
    * of the '0th row' and '0th column' to visual position is shown as
    * below.
    *
    * Value | 0th Row | 0th Column
    * ------+-------------+-----------
    * 1 | top | left side
    * 2 | top | rigth side
    * 3 | bottom | rigth side
    * 4 | bottom | left side
    * 5 | left side | top
    * 6 | right side | top
    * 7 | right side | bottom
    * 8 | left side | bottom
    *
    * For convenience, here is what the letter F would look like if it were
    * tagged correctly and displayed by a program that ignores the orientation
    * tag:
    *
    * 1 2 3 4 5 6 7 8
    *
    * 888888 888888 88 88 8888888888 88 88 8888888888
    * 88 88 88 88 88 88 88 88 88 88 88 88
    * 8888 8888 8888 8888 88 8888888888 8888888888 88
    * 88 88 88 88
    * 88 88 888888 888888
    *
    */

    #include <stdio.h>
    #include <stdlib.h>

    static FILE * myfile; /* My JPEG file */

    static unsigned char exif_data[65536L];

    /* Return next input byte, or EOF if no more */
    #define NEXTBYTE() getc(myfile)

    /* Error exit handler */
    #define ERREXIT(msg) (exit(0))

    /* Read one byte, testing for EOF */
    static int
    read_1_byte (void)
    {
    int c;

    c = NEXTBYTE();
    if (c == EOF)
    ERREXIT("Premature EOF in JPEG file");
    return c;
    }

    /* Read 2 bytes, convert to unsigned int */
    /* All 2-byte quantities in JPEG markers are MSB first */
    static unsigned int
    read_2_bytes (void)
    {
    int c1, c2;

    c1 = NEXTBYTE();
    if (c1 == EOF)
    ERREXIT("Premature EOF in JPEG file");
    c2 = NEXTBYTE();
    if (c2 == EOF)
    ERREXIT("Premature EOF in JPEG file");
    return (((unsigned int) c1) << 8) + ((unsigned int) c2);
    }

    static const char * progname; /* program name for error messages */

    static void
    usage (void)
    /* complain about bad command line */
    {
    fprintf(stderr, "jpegexiforient reads or writes the Exif Orientation Tag ");
    fprintf(stderr, "in a JPEG Exif file.\n");

    fprintf(stderr, "Usage: %s [switches] jpegfile\n", progname);

    fprintf(stderr, "Switches:\n");
    fprintf(stderr, " -n Do not output the trailing newline\n");
    fprintf(stderr, " -1 .. -8 Set orientation value 1 .. 8\n");
    }

    /*
    * The main program.
    */

    int
    main (int argc, char **argv)
    {
    int n_flag, set_flag;
    unsigned int length, i;
    int is_motorola; /* Flag for byte order */
    unsigned int offset, number_of_tags, tagnum;

    progname = argv[0];
    if (progname == NULL || progname[0] == 0)
    progname = "jpegexiforient"; /* in case C library doesn't provide it */

    if (argc < 2) { usage(); return 0; }

    n_flag = 0; set_flag = 0;

    i = 1;
    while (argv[0] == '-') {
    switch (argv[1]) {
    case 'n':
    n_flag = 1;
    break;
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    set_flag = argv[1] - '0';
    break;
    default:
    usage(); return 0;
    }
    if (++i >= argc) { usage(); return 0; }
    }

    if (set_flag) {
    if ((myfile = fopen(argv, "rb+")) == NULL) {
    fprintf(stderr, "%s: can't open %s\n", progname, argv);
    return 0;
    }
    } else {
    if ((myfile = fopen(argv, "rb")) == NULL) {
    fprintf(stderr, "%s: can't open %s\n", progname, argv);
    return 0;
    }
    }

    /* Read File head, check for JPEG SOI + Exif APP1 */
    for (i = 0; i < 4; i++)
    exif_data = (unsigned char) read_1_byte();
    if (exif_data[0] != 0xFF ||
    exif_data[1] != 0xD8 ||
    exif_data[2] != 0xFF ||
    exif_data[3] != 0xE1)
    return 0;

    /* Get the marker parameter length count */
    length = read_2_bytes();
    /* Length includes itself, so must be at least 2 */
    /* Following Exif data length must be at least 6 */
    if (length < 8)
    return 0;
    length -= 8;
    /* Read Exif head, check for "Exif" */
    for (i = 0; i < 6; i++)
    exif_data = (unsigned char) read_1_byte();
    if (exif_data[0] != 0x45 ||
    exif_data[1] != 0x78 ||
    exif_data[2] != 0x69 ||
    exif_data[3] != 0x66 ||
    exif_data[4] != 0 ||
    exif_data[5] != 0)
    return 0;
    /* Read Exif body */
    for (i = 0; i < length; i++)
    exif_data = (unsigned char) read_1_byte();

    if (length < 12) return 0; /* Length of an IFD entry */

    /* Discover byte order */
    if (exif_data[0] == 0x49 && exif_data[1] == 0x49)
    is_motorola = 0;
    else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D)
    is_motorola = 1;
    else
    return 0;

    /* Check Tag Mark */
    if (is_motorola) {
    if (exif_data[2] != 0) return 0;
    if (exif_data[3] != 0x2A) return 0;
    } else {
    if (exif_data[3] != 0) return 0;
    if (exif_data[2] != 0x2A) return 0;
    }

    /* Get first IFD offset (offset to IFD0) */
    if (is_motorola) {
    if (exif_data[4] != 0) return 0;
    if (exif_data[5] != 0) return 0;
    offset = exif_data[6];
    offset <<= 8;
    offset += exif_data[7];
    } else {
    if (exif_data[7] != 0) return 0;
    if (exif_data[6] != 0) return 0;
    offset = exif_data[5];
    offset <<= 8;
    offset += exif_data[4];
    }
    if (offset > length - 2) return 0; /* check end of data segment */

    /* Get the number of directory entries contained in this IFD */
    if (is_motorola) {
    number_of_tags = exif_data[offset];
    number_of_tags <<= 8;
    number_of_tags += exif_data[offset+1];
    } else {
    number_of_tags = exif_data[offset+1];
    number_of_tags <<= 8;
    number_of_tags += exif_data[offset];
    }
    if (number_of_tags == 0) return 0;
    offset += 2;

    /* Search for Orientation Tag in IFD0 */
    for (;;) {
    if (offset > length - 12) return 0; /* check end of data segment */
    /* Get Tag number */
    if (is_motorola) {
    tagnum = exif_data[offset];
    tagnum <<= 8;
    tagnum += exif_data[offset+1];
    } else {
    tagnum = exif_data[offset+1];
    tagnum <<= 8;
    tagnum += exif_data[offset];
    }
    if (tagnum == 0x0112) break; /* found Orientation Tag */
    if (--number_of_tags == 0) return 0;
    offset += 12;
    }

    if (set_flag) {
    /* Set the Orientation value */
    if (is_motorola) {
    exif_data[offset+2] = 0; /* Format = unsigned short (2 octets) */
    exif_data[offset+3] = 3;
    exif_data[offset+4] = 0; /* Number Of Components = 1 */
    exif_data[offset+5] = 0;
    exif_data[offset+6] = 0;
    exif_data[offset+7] = 1;
    exif_data[offset+8] = 0;
    exif_data[offset+9] = (unsigned char)set_flag;
    exif_data[offset+10] = 0;
    exif_data[offset+11] = 0;
    } else {
    exif_data[offset+2] = 3; /* Format = unsigned short (2 octets) */
    exif_data[offset+3] = 0;
    exif_data[offset+4] = 1; /* Number Of Components = 1 */
    exif_data[offset+5] = 0;
    exif_data[offset+6] = 0;
    exif_data[offset+7] = 0;
    exif_data[offset+8] = (unsigned char)set_flag;
    exif_data[offset+9] = 0;
    exif_data[offset+10] = 0;
    exif_data[offset+11] = 0;
    }
    fseek(myfile, (4 + 2 + 6 + 2) + offset, SEEK_SET);
    fwrite(exif_data + 2 + offset, 1, 10, myfile);
    } else {
    /* Get the Orientation value */
    if (is_motorola) {
    if (exif_data[offset+8] != 0) return 0;
    set_flag = exif_data[offset+9];
    } else {
    if (exif_data[offset+9] != 0) return 0;
    set_flag = exif_data[offset+8];
    }
    if (set_flag > 8) return 0;
    }

    /* Write out Orientation value */
    if (n_flag)
    printf("%c", '0' + set_flag);
    else
    printf("%c\n", '0' + set_flag);

    /* All done. */
    return 0;
    }
    ==========8<==========8<==========8<==========8<==========8<==========8<
    Mike Brodbelt, Oct 1, 2003
    #8
  9. Jim Garrison

    C0mdrData Guest

    I definitely recommend Irfanview available free from www.irfanview.com

    It has lossless Jpeg rotation, and great software to boot. Just DON'T use
    the "rotate image" options on the Image menu. The lossless rotation is in
    the options menu.

    Bruce

    "The human adventure is just beginning"

    "Mike Graham" <> wrote in message
    news:...
    > In article <Ig6eb.171228$>, Jim Garrison

    wrote:
    >
    > > Can anyone tell me if ImageMagick does lossless 90-degree rotation?

    >
    > I don't believe that it does. There is a list of lossless rotators at
    > http://www.jpegclub.org, and it's not on the list. Mind you, there is

    only
    > *one* linux app on the list, and I'm finding it to be a pig to install on

    my
    > system, so I'd love to find out that I'm wrong about ImageMagick.
    >
    > --
    > =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    > Mike Graham | Metalworker, rustic, part-time zealot.
    > mike 'at' metalmangler.com |
    > <http://www.metalmangler.com>| Caledon, Ontario, Canada
    >
    > Lousy photographer with a really nice camera - Olympus C3020Zoom.
    > When that's broken I can use my Nikon D100 :cool:
    > <http://www.metalmangler.com/photos/photos.htm>
    > <http://www.photo.net/shared/community-member?user_id=766040>
    C0mdrData, Oct 1, 2003
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Louise

    Why is lossless rotation actually gainful rotation?

    Louise, Jan 28, 2004, in forum: Digital Photography
    Replies:
    19
    Views:
    638
    Guido Vollbeding
    Feb 2, 2004
  2. zulabarr

    Microsoft Picture and Fax Viewer XP--Lossless rotation?

    zulabarr, Feb 4, 2004, in forum: Digital Photography
    Replies:
    8
    Views:
    2,331
  3. nick c

    Re: JPEG 9 new lossless JPEG standard

    nick c, Jan 22, 2013, in forum: Digital Photography
    Replies:
    0
    Views:
    159
    nick c
    Jan 22, 2013
  4. David Dyer-Bennet

    Re: JPEG 9 new lossless JPEG standard

    David Dyer-Bennet, Jan 23, 2013, in forum: Digital Photography
    Replies:
    0
    Views:
    146
    David Dyer-Bennet
    Jan 23, 2013
  5. Martin Brown

    Re: JPEG 9 new lossless JPEG standard

    Martin Brown, Jan 23, 2013, in forum: Digital Photography
    Replies:
    16
    Views:
    469
    Wolfgang Weisselberg
    Feb 13, 2013
Loading...

Share This Page