Logo Search packages:      
Sourcecode: aaphoto version File versions  Download package

aaio.c

/*----------------------------------------------------------------------
    This file is part of aaPhoto.

    aaPhoto is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    aaPhoto is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
------------------------------------------------------------------------*/



// -----------------------------------------------------
// ----------- STRING CONVERT TO LOWER CASE ------------
// -----------------------------------------------------
void STRING_CONVERT_TO_LCASE(char *strin, char *strout)
{
      int i;
      for(i=0; strin[i]!=0; i++){
            if (i < max_char-1){
                  strout[i]=tolower(strin[i]); }
      }
      strout[i]=0;
}




// --------------------------------------------------
// ----------- STRING CONVERT TO INTEGER ------------
// --------------------------------------------------
int STRING_CONVERT_TO_INTEGER(char *str, int *number)
{
      int i, c, d;
      int xx = 0;
      int yy;
      int num;
      int num_max = 8;
      i = 0;
      while ((str[i] != 0) && (i < num_max)){ i++; }
      if (i >= num_max) return 1;
      c = i;
      num = 0;
      if (c > 0){
            d = 1;
            for (i=1; i<=c; i++){

                  yy = 1;
                  if (str[c-i] == '0') { xx = 0; yy = 0; }
                  if (str[c-i] == '1') { xx = 1; yy = 0; }
                  if (str[c-i] == '2') { xx = 2; yy = 0; }
                  if (str[c-i] == '3') { xx = 3; yy = 0; }
                  if (str[c-i] == '4') { xx = 4; yy = 0; }
                  if (str[c-i] == '5') { xx = 5; yy = 0; }
                  if (str[c-i] == '6') { xx = 6; yy = 0; }
                  if (str[c-i] == '7') { xx = 7; yy = 0; }
                  if (str[c-i] == '8') { xx = 8; yy = 0; }
                  if (str[c-i] == '9') { xx = 9; yy = 0; }
                  if (yy) return 1;

                  num += xx * d;
                  d *= 10;
            }
      }
      else{ return 1; }

      *number = num;
      return 0;
}




// -------------------------------------
// ----------- STRING PRINT ------------
// -------------------------------------
// printing text to stdout
void STRING_PRINT(const char str[])
{
      if (!(opt_quiet)){
          int i;
            for (i=0; str[i]!='\0'; i++){
                  printf("%c", str[i]);
                  fflush(stdout);
            }
      }
}




// -------------------------------------
// -------- STRING PRINT ERROR ---------
// -------------------------------------
// printing text to stderr
void STRING_PRINTE(const char str[])
{
//    if (!(opt_quiet)){
          int i;
            for (i=0; str[i]!='\0'; i++){
                  fprintf(stderr, "%c", str[i]);
                  fflush(stderr);
            }
//    }
}




// -------------------------------------
// ------- STRING PRINT VERBOSE --------
// -------------------------------------
// printing text to stdout if in verbose mode
void STRING_PRINTV(const char str[])
{
    if(opt_verbose){
      if (!(opt_quiet)){
          // print time since start in seconds if bigger than 1
          // we decrement the time by 1 because the program may start in a middle of a second, that we don't know
          int t = time(NULL) - mytime;
          if (t > 1){   printf("(%d) ", t-1); }
          // print text
          int i;
            for (i=0; str[i]!='\0'; i++){
                  printf("%c", str[i]);
                  fflush(stdout);
            }
      }
    }
}




// --------------------------------------
// ----------- STRING PRINTD ------------
// --------------------------------------
// printing decimal number to stdout
void STRING_PRINTVD(int num)
{
      if(opt_verbose){
            if (!(opt_quiet)){
                        printf("%d", num);
                  fflush(stdout);
            }
      }
}




// --------------------------------------
// ----------- STRING PRINTF ------------
// --------------------------------------
// printing floating number to stdout
void STRING_PRINTF(double num)
{
      if (!(opt_quiet)){
                  printf("%.2f", num);
            fflush(stdout);
      }
}




// ---------------------------------------
// ----------- STRING COMPARE ------------
// ---------------------------------------
// compare two string values
// result -> 0 if true!
int STRING_COMPARE(char *str1, char *str2)
{
      int i = 0;
      int result = 0;
      while ((str1[i] != 0) && (str2[i] != 0)) {
            if (str1[i] != str2[i]) result = 1;
            i++;
      }
      if (str1[i] != str2[i]) result = 1;
      return result;
}




// ---------------------------------------------------------
// ----------- STRING COMPARE WITH FIXED LENGTH ------------
// ---------------------------------------------------------
int STRING_COMPARE_FIX(char *str1, char *str2, int count)
{
      int result = 0;
      int i;
      for (i=0; i<count; i++)
            if (str1[i] != str2[i]) result = 1;
      return result;
}




// --------------------------------------
// ----------- GET FILE NAME ------------
// --------------------------------------
// getting file name out of path
void GET_FILE_NAME(char *strin, char *strout)
{
      // check length of string
      long len;
      long i, c;
      for (i=0; strin[i]!='\0'; i++);
      len = i;
      // check only path
      c = 0;
      i = len-1;
      while ((i >= 0) && (strin[i] != slsh[0])) { c++; i--; }
      //if (i >= 0) {
            for (i=0; i<c; i++) {
                  if (i < max_char) {
                        strout[i] = strin[i+len-c]; }
            }
            strout[i] = 0;
      //}
}




// -------------------------------------------
// ----------- GET FILE NAME ONLY ------------
// -------------------------------------------
// getting only the file name of path
void GET_FILE_NAME_ONLY(char *strin, char *strout)
{
      // check length of string
      long len;
      long i, c, st;
      for (i=0; strin[i]!='\0'; i++);
      len = i;
      // check only path
      i = len-1;
      while ((i >= 0) && (strin[i] != slsh[0])) { i--; }
    st = i + 1;
      // check extension of file
      c = 0;
      i = len-1;
      while ((i >= 0) && (strin[i] != '.')) { i--; }
      c = i - 1;
      if (c >= st) {
            for (i=0; i<c-st+1; i++) {
                  if (i < max_char-1) {
                        strout[i] = strin[i+st]; }
                  }
            strout[i] = 0;
      }
      else {
            strout[0] = 0;
      }
}




// -------------------------------------------
// ----------- GET FILE EXTENSION ------------
// -------------------------------------------
// getting extenstion of the file from path
void GET_FILE_EXTENSION(char *strin, char *strout)
{
      // check length of string
      long len;
      long i, c;
      for (i=0; strin[i]!='\0'; i++);
      len = i;
      // check extension of file
      c = 0;
      i = len-1;
      while ((i >= 0) && (strin[i] != '.')) { c++; i--; }
      c++;
      if (c > 0) {
            for (i=0; i<c; i++) {
                  if (i < max_char-1) {
                        strout[i] = strin[i+len-c]; } }
            strout[i] = 0;
      }
      else {
            strout[0] = 0;
      }
}




// ------------------------------------------
// ------------- GET FILE PATH --------------
// ------------------------------------------
// Fájl elérési útjának kinyerése
void GET_FILE_PATH(char *strin, char *strout)
{
      // check length of string
      long len;
      long i, c;
      for (i=0; strin[i]!='\0'; i++);
      len = i;
      // check only path
      c = 0;
      i = len-1;
      while ((i >= 0) && (strin[i] != slsh[0])) { c++; i--; }
      if (i >= 0) {
            for (i=0; i<len-c; i++) {
                  if (i < max_char-1) {
                        strout[i] = strin[i]; }
            }
            strout[i] = 0;
      }
      else {
            strout[0] = 0;
      }
}




// ----------------------------------------
// ------------ FILE EXIST? ---------------
// ----------------------------------------
int FILE_EXIST(char *file_name)
{
      FILE *fhandle;
      fhandle = fopen(file_name, "rb");
      if (fhandle == 0) return 0;
      fclose(fhandle);
      return 1;
}




// ----------------------------------------------
// ------------- GET FILE NAME NEW --------------
// ----------------------------------------------
// putting together the new output file name
int GET_FILE_NAME_NEW(char *strin, char *strout)
{
      char fpath [max_char];
      char fname [max_char];
      char fext [max_char];
      char fextj1 [] = ".jpg\0";
      char fextj2 [] = ".jp2\0";
      char fextj3 [] = ".png\0";
      char fextj4 [] = ".bmp\0";
      GET_FILE_PATH(strin, fpath);
      GET_FILE_NAME_ONLY(strin, fname);
      GET_FILE_EXTENSION(strin, fext);

      char fnew [] = "_new";
      long i, c;
      c = 0;

      if (!(opt_output))
      {
            i = 0;
            while (fpath[i] != '\0')
            {
                  if (c >= max_char) return 255;
                  strout[c] = fpath[i];
                  i++; c++;
            }
      }
      else
      {
            i = 0;
            while (opt_output_path[i] != '\0')
            {
                  if (c >= max_char) return 255;
                  strout[c] = opt_output_path[i];
                  i++; c++;
            }
      }

      i = 0;
      while (fname[i] != '\0')
      {
            if (c >= max_char) return 255;
            strout[c] = fname[i];
            i++; c++;
      }

      if (!(opt_overwrite))
      {
            i = 0;
            while (fnew[i] != '\0')
            {
                  if (c >= max_char) return 255;
                  strout[c] = fnew[i];
                  i++; c++;
            }
      }

      i = 0;
      while (fext[i] != '\0')
      {
            if (c >= max_char) return 255;
            if ((!opt_jpg) && (!opt_jp2) && (!opt_png) && (!opt_bmp)) strout[c] = fext[i];
            if (opt_jpg) strout[c] = fextj1[i];
            if (opt_jp2) strout[c] = fextj2[i];
            if (opt_png) strout[c] = fextj3[i];
            if (opt_bmp) strout[c] = fextj4[i];
            i++; c++;
      }
      if (c >= max_char) return 255;
      strout[c] = fext[i];

      if (opt_jpg) bitmap_format_jpg_file_type = 6;
      if (opt_jp2) bitmap_format_jpg_file_type = 4;

      if (!(opt_overwrite) && (FILE_EXIST(strout))) return 1;

      return 0;

}




// --------------------------------------------
// ------------- GET FILE FORMAT --------------
// --------------------------------------------
int GET_FILE_FORMAT(char *file_name)
{
      // JasPer format codes (0-7)
      // ---------------------------
      // 0 - mif
      // 1 - pnm / pgm / ppm
      // 2 - bmp
      // 3 - ras
      // 4 - jp2
      // 5 - jpc
      // 6 - jpg
      // 7 - pgx
      // 8 - png

      char fext[max_char];
      GET_FILE_EXTENSION(file_name, fext);

      char fextl[max_char];
      STRING_CONVERT_TO_LCASE(fext, fextl);

      int res = -1;

      if (!STRING_COMPARE(fextl, ".mif"))  res = 0;
      if (!STRING_COMPARE(fextl, ".pnm"))  res = 1;
      if (!STRING_COMPARE(fextl, ".pgm"))  res = 1;
      if (!STRING_COMPARE(fextl, ".ppm"))  res = 1;
      if (!STRING_COMPARE(fextl, ".bmp"))  res = 2;
      if (!STRING_COMPARE(fextl, ".ras"))  res = 3;
      if (!STRING_COMPARE(fextl, ".jp2"))  res = 4;
      if (!STRING_COMPARE(fextl, ".jpc"))  res = 5;
      if (!STRING_COMPARE(fextl, ".jpg"))  res = 6;
      if (!STRING_COMPARE(fextl, ".jpeg"))  res = 6;
      if (!STRING_COMPARE(fextl, ".jpe"))  res = 6;
      if (!STRING_COMPARE(fextl, ".pgx"))  res = 7;
      if (!STRING_COMPARE(fextl, ".png"))  res = 8;

      return res;
}




// -----------------------------------------
// ----------- FILE LIST ADD ---------------
// -----------------------------------------
int FILE_LIST_ADD(char *file_name)
{
      // isn't file name buffer full yet?
      if (file_name_buffer_pointer + max_char < max_file_name_buffer){

/*
        char fpath [max_char];
            char fname [max_char];
            char fext  [max_char];
            GET_FILE_PATH(file_name, fpath);
            GET_FILE_NAME_ONLY(file_name, fname);
            GET_FILE_EXTENSION(file_name, fext);
*/

        DIR *                   dp;
        DIR *                   dp2;
        const struct dirent *   ent;
        int                     cnt;

      // if the name points to a directory
        dp = opendir(file_name);
        if (dp != NULL){

            // list files in directory
            cnt = 0;
            while (ent = readdir(dp), ent != NULL)
            {

                int res = 0;
                  if (!STRING_COMPARE((char*)(ent->d_name), "."))  res = 1;
                  if (!STRING_COMPARE((char*)(ent->d_name), "..")) res = 1;
                if (res == 0){

                cnt++;

            // create new file name with path
                  char file_name_new [max_char];
                  int i = 0;
                  while (file_name[i] != 0){
                if (i >= max_char) return 255;
                    file_name_new[i] = file_name[i]; i++; }

            // remove '/' characters from the end of directory names if more than 1
                int flag = 0;
                while ((i > 1) && (flag == 0)) {
                    if (file_name_new[i-1] == slsh[0]) { i--; }
                    else { flag = 1; } }
            // add '/' character to directory path
                file_name_new[i] = slsh[0];

            // add found file name to directory path
                i++;
                  int i2 = 0;
                  while (ent->d_name[i2] != 0){
                    file_name_new[i] = ent->d_name[i2]; i++; i2++; }
                file_name_new[i] = 0;


            // if new name is not a dir, then store file name
                dp2 = opendir(file_name_new);
                if (dp2 != NULL){ closedir(dp2); }
                else{
                        int i = 0;
                        while (file_name_new[i] != 0){ i++; }
                  int len = i;
                        for(i=0; i<len; i++){
                              file_name_buffer[file_name_buffer_pointer] = file_name_new[i];
                              file_name_buffer_pointer++;
                        }
                        file_name_buffer[file_name_buffer_pointer] = '\0';
                        file_name_buffer_pointer++;
                        file_name_counter++;

                    //printf("%s\n", file_name_new);
                }

                }

            }
            closedir(dp);
            dp = NULL;
        }

      // the name is a file, so we store it
        else{
            int i = 0;
            while (file_name[i] != 0){ i++; }
            int len = i;
                  for(i=0; i<len; i++){
                        file_name_buffer[file_name_buffer_pointer] = file_name[i];
                        file_name_buffer_pointer++;
                  }
                  file_name_buffer[file_name_buffer_pointer] = '\0';
                  file_name_buffer_pointer++;
                  file_name_counter++;
        }

    }
    else { return 1; }
      return 0;

}




/* -----------------------------------
             --- EXIF ---
   -----------------------------------
    char *exif_buffer;
    long  exif_buffer_length;
    long  exif_file_length;
    int   exif_flag;

    http://en.wikipedia.org/wiki/JPEG
    http://www.media.mit.edu/pia/Research/deepview/exif.html
  ------------------------------------
  ------------------------------------
*/


// --------------------------------------
// ----------- EXIF CLEAR ---------------
// --------------------------------------
// clear exif information and deallocate memory
int EXIF_CLEAR()
{
    if (exif_flag != 0) {
      /* print info */ STRING_PRINTV("freeing exif buffer\n");
        free(exif_buffer);
        exif_buffer_length = 0;
        exif_flag = 0;
    }
    return 0;
}




// ------------------------------------
// ----------- EXIF GET ---------------
// ------------------------------------
// read exif information from file and store it in memory
int EXIF_GET(char *file_name)
{
    exif_flag = 0;

    // if --noexif flag was specified, then don't store exif from image
    if (opt_noexif) { return 1; }

      // open file for reading
      FILE *fhandle;
      fhandle = fopen(file_name, "rb");
      if (fhandle == 0) return 1;
      // determine the length of file
      fseek(fhandle, 0, SEEK_END);
      exif_file_length = ftell(fhandle);
      fseek(fhandle, 0, SEEK_SET);


    // examine exif information and check its length
    long exif_start = 0;
    long exif_offset = 0;
    int ch1 = 0;
    int ch2 = 0;

    // FFD8 JPEG indicator
    fseek(fhandle, 0, SEEK_SET);
    ch1 = fgetc(fhandle);
    ch2 = fgetc(fhandle);
    if ((ch1 != 0xff) || (ch2 != 0xd8)) {
      fclose(fhandle);
        return 1;
    }

    // seek for beginning of exif info (start ofset = 2)
    exif_start = 2;
    int exif_ok = 0;
    int exif_bad = 0;
    while ((exif_ok == 0) && (exif_bad == 0)) {

        // FFE1 Exif indicator
        fseek(fhandle, exif_start + 0, SEEK_SET);
        ch1 = fgetc(fhandle);
        ch2 = fgetc(fhandle);
      // if indicator does not start with FF
      // (the id tag of the next block within JPEG format)
      // then exit, because this is an error
        if (ch1 != 0xff) { exif_bad = 1; }
        else {
          // search for FFE1 exif array indicator
            if ((ch1 != 0xff) || (ch2 != 0xe1)) {

            // check length of exif array
                fseek(fhandle, exif_start + 2, SEEK_SET);
                ch1 = fgetc(fhandle);
                ch2 = fgetc(fhandle);
                exif_offset = (long)(ch1) * 256 + (long)(ch2);
                exif_start += exif_offset + 2;
            // exit if pointer gives bad length
            if (exif_start >= exif_file_length) { exif_bad = 1; }

            }
            else {

                exif_ok = 1;

            // check 'Exif00' pattern 45 78 69 66 00 00
                fseek(fhandle, exif_start + 4, SEEK_SET);
                ch1 = fgetc(fhandle);
                ch2 = fgetc(fhandle);
                if ((ch1 != 0x45) || (ch2 != 0x78)) {
                    exif_ok = 0;
                }
                fseek(fhandle, exif_start + 6, SEEK_SET);
                ch1 = fgetc(fhandle);
                ch2 = fgetc(fhandle);
                if ((ch1 != 0x69) || (ch2 != 0x66)) {
                    exif_ok = 0;
                }
                fseek(fhandle, exif_start + 8, SEEK_SET);
                ch1 = fgetc(fhandle);
                ch2 = fgetc(fhandle);
                if ((ch1 != 0x00) || (ch2 != 0x00)) {
                    exif_ok = 0;
                }

                // check length of exif array
                if (exif_ok == 1) {
                    fseek(fhandle, exif_start + 2, SEEK_SET);
                    ch1 = fgetc(fhandle);
                    ch2 = fgetc(fhandle);
                    exif_buffer_length = (long)(ch1) * 256 + (long)(ch2) + 2;
                }
            else {
                  exif_bad = 1;
            }

            }
        }

    }

    if (exif_ok == 0) {
      fclose(fhandle);
        return 1;
    }

    // allocate memory for file load
    /* print info */ STRING_PRINTV("allocating memory for exif buffer\n");
    exif_buffer = malloc(exif_buffer_length);
    if (exif_buffer == 0) {
        fclose(fhandle);
        return 1;
    }

    // load exif part of file into memory
    fseek(fhandle, exif_start, SEEK_SET);
    if (fread(exif_buffer, 1, exif_buffer_length, fhandle) == 0) {
      fclose(fhandle);
        return 1;
    }

    // close file
    fclose(fhandle);
    exif_flag = 1;
    return 0;
}




// ------------------------------------
// ----------- EXIF PUT ---------------
// ------------------------------------
// put exif information back to the file from memory (if there was any)
int EXIF_PUT(char *file_name)
{
    if (exif_flag) {

      // open file for writing
      FILE *fhandle;
      fhandle = fopen(file_name, "wb+");
      if (fhandle == 0) return 1;
      // write FFD8 JPEG indicator into the first 2 bytes
        if (fputc(0xff, fhandle) == 0) return 1;
        if (fputc(0xd8, fhandle) == 0) return 1;
      // write out the rest of the exif info
      // here the exif info has to be written with 2 bytes less from the end
      // because the JPEG writer wants to add the FFD8 marker by himself too
      // so this prevents FFD8 to be 2 times wrongly
        if (fwrite(exif_buffer, 1, exif_buffer_length - 2, fhandle) == 0) return 1;
        fclose(fhandle);

    }
    return 0;
}




// --------------------------------------------------
// ----------- BITMAP READ IN BMP FORMAT ------------
// --------------------------------------------------
int BITMAP_READ_BMP(char *file_name)
{
      /* print info */ STRING_PRINTV("bmp initializations\n");
      unsigned long f_bm;
      unsigned long f_bitcount;
      unsigned long f_compressed;
      unsigned long f_headersize;
      unsigned long f_offs;
      unsigned long f_width;
      unsigned long f_height;
      unsigned long f_xpixelpermeter;
      unsigned long f_ypixelpermeter;
      unsigned long addr, addr2;
      unsigned long addr_offset;
      unsigned long bw, bh;
      unsigned long x, y;
      unsigned long file_length;
      unsigned char *file_buffer;
      unsigned long i;

      FILE *fhandle;
      // open file for reading
      /* print info */ STRING_PRINTV("opening file for reading\n");
      fhandle = fopen(file_name, "rb");
      if (fhandle == 0) return 1;
      // check length of file
      fseek(fhandle, 0, SEEK_END);
      file_length = ftell(fhandle);
      fseek(fhandle, 0, SEEK_SET);
      // allocate memory for file load
      /* print info */ STRING_PRINTV("allocating memory for bmp object\n");
      file_buffer = malloc(file_length);
      if (file_buffer == 0) return 1;
      // load file into memory
      if (fread(file_buffer, 1, file_length, fhandle) == 0) {
            /* print info */ STRING_PRINTV("freeing bmp object\n");
            free(file_buffer); return 1; }
      // close file
      fclose(fhandle);


      // read BMP indicator
      f_bm = 0;
      f_bm += file_buffer[0] << 0;
      f_bm += file_buffer[1] << 8;
      f_bitcount = 0;
      f_bitcount += file_buffer[28] << 0;
      f_bitcount += file_buffer[29] << 8;
      f_compressed = 0;
      f_compressed += file_buffer[30] << 0;
      f_compressed += file_buffer[31] << 8;
      f_compressed += file_buffer[32] << 16;
      f_compressed += file_buffer[33] << 24;

      // check BMP format (BMP header + uncompressed + 24 bit colors)
      if ((f_bm == 0x00004d42) && ((f_bitcount == 24) || (f_bitcount == 8)) && (f_compressed == 0)) {
        bitmap_format_bmp_clrspc_type = f_bitcount;

        if (f_bitcount == 8){
            // ofset pointing to color palette
            f_headersize = 14;
            f_headersize += file_buffer[14] << 0;
            f_headersize += file_buffer[15] << 8;
            f_headersize += file_buffer[16] << 16;
            f_headersize += file_buffer[17] << 24;
            // check whether the 8 bit image contains only gray colors?
            int gray_flag;
            gray_flag = 1;
            for (i=0; i<256; i++){
                  if ((file_buffer[i*4+f_headersize+0] != file_buffer[i*4+f_headersize+1]) ||
                        (file_buffer[i*4+f_headersize+1] != file_buffer[i*4+f_headersize+2])){ gray_flag = 0; }
            }
            // if not gray then exit, because minimim bitdepth of colors to correct is 24 (or 8 bit gray)
            if (gray_flag == 0) {
                  /* print info */ STRING_PRINTV("freeing bmp object\n");
                  free(file_buffer); return 1; }
            }

            // ofset pointing to RGB datas
            f_offs = 0;
            f_offs += file_buffer[10] << 0;
            f_offs += file_buffer[11] << 8;
            f_offs += file_buffer[12] << 16;
            f_offs += file_buffer[13] << 24;
            // width of image in pixels
            f_width = 0;
            f_width += file_buffer[18] << 0;
            f_width += file_buffer[19] << 8;
            f_width += file_buffer[20] << 16;
            f_width += file_buffer[21] << 24;
            // height of image in pixels
            f_height = 0;
            f_height += file_buffer[22] << 0;
            f_height += file_buffer[23] << 8;
            f_height += file_buffer[24] << 16;
            f_height += file_buffer[25] << 24;
            // x pixel per meter value
            f_xpixelpermeter = 0;
            f_xpixelpermeter += file_buffer[38] << 0;
            f_xpixelpermeter += file_buffer[39] << 8;
            f_xpixelpermeter += file_buffer[40] << 16;
            f_xpixelpermeter += file_buffer[41] << 24;
            // y pixel per meter value
            f_ypixelpermeter = 0;
            f_ypixelpermeter += file_buffer[42] << 0;
            f_ypixelpermeter += file_buffer[43] << 8;
            f_ypixelpermeter += file_buffer[44] << 16;
            f_ypixelpermeter += file_buffer[45] << 24;

            bw = f_width;
            bh = f_height;
            bitmap_width = f_width;
            bitmap_height = f_height;
            xdpi = f_xpixelpermeter;
            ydpi = f_ypixelpermeter;

            /* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
            /* print info */ STRING_PRINTV(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV(" pixels\n");
            /* print info */ STRING_PRINTV("resolution is "); STRING_PRINTVD(xdpi);
            /* print info */ STRING_PRINTV(" x "); STRING_PRINTVD(ydpi); STRING_PRINTV(" pixels per meter\n");
            /* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(f_bitcount);
            /* print info */ STRING_PRINTV(" bit depth\n");

#ifndef __BMP_ONLY__
        if (f_bitcount == 8) { bitmap_format_jpg_clrspc_type = 8; }
        if (f_bitcount == 24){ bitmap_format_jpg_clrspc_type = 24; }
        if (f_bitcount == 8) { bitmap_format_png_clrspc_type = 0; }
        if (f_bitcount == 24){ bitmap_format_png_clrspc_type = 2; }
#endif

      // allocate memory for the unpacked RGB colors
      /* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
      bitmap_buffer = malloc(bw * bh * 3);
      if (bitmap_buffer == 0) return 1;

          /* print info */ STRING_PRINTV("copying colors from bmp object to bitmap buffer\n");
            if (f_bitcount == 8){
                  addr_offset = f_width % 4;
                  if (addr_offset != 0) addr_offset = 4 - addr_offset;
            for (y=0; y<=bh-1; y++){
                  addr2 = y * bw * 1 + y * addr_offset;
                  for (x=0; x<=bw-1; x++){
                        addr = f_offs + addr2 + x * 1;
                        bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0] = file_buffer[addr + 0];
                        bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1] = file_buffer[addr + 0];
                        bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2] = file_buffer[addr + 0];
                  }
            }
            }
            else{
                  addr_offset = (f_width) * 3 % 4;
                  if (addr_offset != 0) addr_offset = 4 - addr_offset;
            for (y=0; y<=bh-1; y++){
                  addr2 = y * bw * 3 + y * addr_offset;
                  for (x=0; x<=bw-1; x++){
                        addr = f_offs + addr2 + x * 3;
                        bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0] = file_buffer[addr + 2];
                        bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1] = file_buffer[addr + 1];
                        bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2] = file_buffer[addr + 0];
                  }
            }
            }

          /* print info */ STRING_PRINTV("freeing bmp object\n");
            free(file_buffer);
          return 0;
      }

      // free memory
      /* print info */ STRING_PRINTV("freeing bmp object\n");
      free(file_buffer);

      return 1;
}




// --------------------------------------------------
// ---------- BITMAP WRITE IN BMP FORMAT ------------
// --------------------------------------------------
int BITMAP_WRITE_BMP(char *file_name)
{
      /* print info */ STRING_PRINTV("bmp initializations\n");
      unsigned long f_offs;
      unsigned long addr, addr2;
      unsigned long addr_offset;
      unsigned long bw, bh;
      unsigned long f_xpixelpermeter;
      unsigned long f_ypixelpermeter;
      unsigned long x, y;
      unsigned long temp, i;
      unsigned long file_length;
      unsigned char *file_buffer;
      unsigned long col;

      bw = bitmap_width;
      bh = bitmap_height;

      f_xpixelpermeter = xdpi;
      f_ypixelpermeter = ydpi;

      // allocate memory for unpacked RGB colors (3 plus bytes more in every width because of the BMP's 4 byte border adjust)
      /* print info */ STRING_PRINTV("allocating memory for bmp object\n");
      if (bitmap_format_bmp_clrspc_type == 8) {
            addr_offset = bw % 4;
              if (addr_offset != 0) addr_offset = 4 - addr_offset;
            file_length = 54 + 4 * 256 + (bw + addr_offset) * bh;
      }
      else {
            addr_offset = (bw * 3) % 4;
                  if (addr_offset != 0) addr_offset = 4 - addr_offset;
            file_length = 54 + (bw * 3 + addr_offset) * bh;
      }

      /* print info */ STRING_PRINTV("allocating memory for bmp object\n");
      file_buffer = malloc(file_length);
      if (file_buffer == 0) return 1;

      // write BMP indicator
      file_buffer[0] = 0x42;
      file_buffer[1] = 0x4d;

      // file length marker
      file_buffer[2] = (file_length & 0x000000ff) >> 0;
      file_buffer[3] = (file_length & 0x0000ff00) >> 8;
      file_buffer[4] = (file_length & 0x00ff0000) >> 16;
      file_buffer[5] = (file_length & 0xff000000) >> 24;

      // zero
      file_buffer[6] = 0;
      file_buffer[7] = 0;
      file_buffer[8] = 0;
      file_buffer[9] = 0;

    if (bitmap_format_bmp_clrspc_type == 8) {
      // bitmap ofset (standard = 54)
      file_buffer[10] = 54;
      file_buffer[11] = 4; // + 4 * 256 pcs of RGB gray colors = $0400 pcs
      file_buffer[12] = 0;
      file_buffer[13] = 0;
      // number of bits per pixel
      file_buffer[28] = 8;
      file_buffer[29] = 0;
    }
    else {
      // bitmap ofset (standard = 54)
      file_buffer[10] = 54;
      file_buffer[11] = 0;
      file_buffer[12] = 0;
      file_buffer[13] = 0;
      // number of bits per pixel
      file_buffer[28] = 24;
      file_buffer[29] = 0;
    }

      // bitmap info header (standard = 40)
      file_buffer[14] = 40;
      file_buffer[15] = 0;
      file_buffer[16] = 0;
      file_buffer[17] = 0;
      // width of image in pixels
      file_buffer[18] = (bw & 0x000000ff) >> 0;
      file_buffer[19] = (bw & 0x0000ff00) >> 8;
      file_buffer[20] = (bw & 0x00ff0000) >> 16;
      file_buffer[21] = (bw & 0xff000000) >> 24;
      // height of image in pixels
      file_buffer[22] = (bh & 0x000000ff) >> 0;
      file_buffer[23] = (bh & 0x0000ff00) >> 8;
      file_buffer[24] = (bh & 0x00ff0000) >> 16;
      file_buffer[25] = (bh & 0xff000000) >> 24;
      // number of planes
      file_buffer[26] = 1;
      file_buffer[27] = 0;
      // compression (standard = 0)
      file_buffer[30] = 0;
      file_buffer[31] = 0;
      file_buffer[32] = 0;
      file_buffer[33] = 0;
      // size of bitmap image in bytes
      if (bitmap_format_bmp_clrspc_type == 8) { temp = (bw + addr_offset) * bh; }
      else                                    { temp = (bw * 3 + addr_offset) * bh; }
      file_buffer[34] = (temp & 0x000000ff) >> 0;
      file_buffer[35] = (temp & 0x0000ff00) >> 8;
      file_buffer[36] = (temp & 0x00ff0000) >> 16;
      file_buffer[37] = (temp & 0xff000000) >> 24;
      // x pixel per meter value
      file_buffer[38] = (f_xpixelpermeter & 0x000000ff) >> 0;
      file_buffer[39] = (f_xpixelpermeter & 0x0000ff00) >> 8;
      file_buffer[40] = (f_xpixelpermeter & 0x00ff0000) >> 16;
      file_buffer[41] = (f_xpixelpermeter & 0xff000000) >> 24;
      // y pixel per meter value
      file_buffer[42] = (f_ypixelpermeter & 0x000000ff) >> 0;
      file_buffer[43] = (f_ypixelpermeter & 0x0000ff00) >> 8;
      file_buffer[44] = (f_ypixelpermeter & 0x00ff0000) >> 16;
      file_buffer[45] = (f_ypixelpermeter & 0xff000000) >> 24;

      for (i=46; i<54; i++) file_buffer[i] = 0;

      /* print info */ STRING_PRINTV("copying colors from bitmap buffer to bmp object\n");
    if (bitmap_format_bmp_clrspc_type == 8) {
      for (i=0; i<256; i++){
            file_buffer[54 + i*4 + 0] = i;
            file_buffer[54 + i*4 + 1] = i;
            file_buffer[54 + i*4 + 2] = i;
            file_buffer[54 + i*4 + 3] = 0;
        }

      f_offs = 54 + 4 * 256;
      addr = 0;
      for (y=0; y<=bh-1; y++){
            addr2 = y * (bw + addr_offset);
            for (x=0; x<=bw-1; x++){
                  addr = f_offs + addr2 + x;
                  col  = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0];
                  col += bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1];
                  col += bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2];
                  file_buffer[addr + 0] = col / 3;
            }
      }
    }
    else {
      f_offs = 54;
      addr = 0;
      for (y=0; y<=bh-1; y++){
            addr2 = y * (bw * 3 + addr_offset);
            for (x=0; x<=bw-1; x++){
                  addr = f_offs + addr2 + x * 3;
                  file_buffer[addr + 0] = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 2];
                  file_buffer[addr + 1] = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 1];
                  file_buffer[addr + 2] = bitmap_buffer[x * 3 + bw * 3 * (bh-1-y) + 0];
            }
      }
    }


      FILE *fhandle;
      // open file for writing
      /* print info */ STRING_PRINTV("opening file for writing\n");
      fhandle = fopen(file_name, "wb");
      if (fhandle == 0) return 1;
      // write and flush file from memory
      /* print info */ STRING_PRINTV("writing image file\n");
      if (fwrite(file_buffer, 1, file_length, fhandle) == 0) return 1;
      // close file
      fclose(fhandle);

      /* print info */ STRING_PRINTV("freeing bmp object\n");
      free(file_buffer);

      return 0;
}


#ifndef __BMP_ONLY__

// --------------------------------------------------
// --------- BITMAP READ IN JASPER FORMAT -----------
// --------------------------------------------------
int BITMAP_READ_JASPER(char *file_name)
{
      // jasper library initialization
      /* print info */ STRING_PRINTV("jasper initializations\n");
      jas_init();
      jas_stream_t *stream;
      jas_image_t *image;
      jas_matrix_t *data;

      // load file and decode format
      /* print info */ STRING_PRINTV("opening file for reading\n");
      stream  = jas_stream_fopen(file_name, "rb");
      if (stream == NULL) return 1;

      // store bitmap format
      bitmap_format_jpg_file_type = jas_image_getfmt(stream);

      /* print info */ STRING_PRINTV("decoding jasper image\n");
      image = jas_image_decode(stream, -1, NULL);
      jas_stream_close(stream);
      if (image == NULL) return 1;
      bitmap_width = jas_image_width(image);
      bitmap_height = jas_image_height(image);
      int clrspc_type = jas_image_clrspc(image);

        if (clrspc_type == JAS_CLRSPC_SGRAY)     { bitmap_format_jpg_clrspc_type = 8;  }
        if (clrspc_type == JAS_CLRSPC_SRGB)      { bitmap_format_jpg_clrspc_type = 24; }

        if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_png_clrspc_type = 0;  }
        if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_png_clrspc_type = 2;  }
        if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_bmp_clrspc_type = 8;  }
        if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_bmp_clrspc_type = 24; }

      /* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
      /* print info */ STRING_PRINTV(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV(" pixels\n");
      /* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(bitmap_format_jpg_clrspc_type);
      /* print info */ STRING_PRINTV(" bit depth\n");

      // check file whether it conatins 24-bit RGB or 8-bit colors?
        int clr_spc;
        clr_spc = jas_clrspc_fam(clrspc_type);
          if ((clr_spc != JAS_CLRSPC_FAM_RGB) && (clr_spc != JAS_CLRSPC_FAM_GRAY)) return 1;
          if (jas_image_cmptprec(image, 0) != 8) return 1;

          // create jasper matrix
          int dx,dy;
          dx = bitmap_width;
          dy = bitmap_height;
          data=jas_matrix_create(dy,dx);

          // allocate memory
          /* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
          bitmap_buffer = malloc(bitmap_width * bitmap_height * 3);
          if (bitmap_buffer == 0) return 1;

          // read datas out of jasper object and copy it to a memory block
          int i, j;
          int channel;

      // determine number of channels -> GRAY = 1 és RGB = 3
        int num_of_channels;
        num_of_channels = 1;
        if (clr_spc == JAS_CLRSPC_FAM_GRAY) { num_of_channels = 1; }
        if (clr_spc == JAS_CLRSPC_FAM_RGB) { num_of_channels = 3; }

      // copy RGB colors to bitmap memory
          /* print info */ STRING_PRINTV("copying colors from jasper object to bitmap buffer\n");
          for(channel=0; channel<num_of_channels; channel++){
            jas_image_readcmpt(image, channel, 0, 0, dx, dy, data);
          jas_image_setcmpttype(image, channel, JAS_IMAGE_CT_RGB_R+channel);
            for(j=0; j<dy; j++){
                  for(i=0; i<dx; i++){
                        int idx=(j * dx + i) * 3;
                    if (num_of_channels == 1){
                        bitmap_buffer[idx+0] = jas_matrix_get(data, j, i);
                        bitmap_buffer[idx+1] = jas_matrix_get(data, j, i);
                        bitmap_buffer[idx+2] = jas_matrix_get(data, j, i); }
                    else{
                        bitmap_buffer[idx+channel] = jas_matrix_get(data, j, i); }
                  }
            }
          }

          // free previously allocated objects
          /* print info */ STRING_PRINTV("freeing jasper object\n");
          jas_image_destroy(image);
          jas_matrix_destroy(data);
          jas_image_clearfmts();
//        jas_cleanup();

      return 0;
}




// --------------------------------------------------
// --------- BITMAP WRITE IN JASPER FORMAT ----------
// --------------------------------------------------
int BITMAP_WRITE_JASPER(char *file_name)
{
          // jasper library initialization
          /* print info */ STRING_PRINTV("jasper initializations\n");
          jas_init();
          jas_stream_t *stream;
          jas_image_t *image;
          jas_image_cmptparm_t cmptparm[3];
          jas_matrix_t *data;
          long i, j;

          // create jasper matrix
          long dx,dy;
          dx = bitmap_width;
          dy = bitmap_height;
          data=jas_matrix_create(dy,dx);

            int clrspc_type = 0;
            if (bitmap_format_jpg_clrspc_type == 8)  { clrspc_type = JAS_CLRSPC_SGRAY; }
            if (bitmap_format_jpg_clrspc_type == 24) { clrspc_type = JAS_CLRSPC_SRGB;  }

          // create new jasper imgae object
          for(i=0; i<3; i++){
            cmptparm[i].tlx         = 0;
            cmptparm[i].tly         = 0;
            cmptparm[i].hstep = 1;
            cmptparm[i].vstep = 1;
            cmptparm[i].width = dx;
            cmptparm[i].height      = dy;
            // number of bits per channel
            cmptparm[i].prec  = 8;
            cmptparm[i].sgnd  = 0;
          }
          image = jas_image_create(3, cmptparm, clrspc_type);

          // read data out of memory block and copy it into jasper object
          /* print info */ STRING_PRINTV("copying colors from bitmap buffer to jasper object\n");
          long channel;
          long idx;
          for(channel=0; channel<3; channel++){
            for(j=0; j<dy; j++){
                  for(i=0; i<dx; i++){
                        idx=(j * dx + i) * 3;
                        jas_matrix_set(data, j, i, bitmap_buffer[idx+channel]);
                  }
            }
            jas_image_writecmpt(image, channel, 0, 0, dx, dy, data);
            jas_image_setcmpttype(image, channel, JAS_IMAGE_CT_RGB_R+channel);
          }

          char *opt = "";
          char opt2[max_char];
//          int fmt = GET_FILE_FORMAT(file_name);
//          if ((fmt < 0) || (fmt > 7)) return 1;
          int fmt = bitmap_format_jpg_file_type;

         // setting quality value
         if (opt_quality < 0)  { opt_quality = 0;   }
         if (opt_quality > 100){ opt_quality = 100; }
         if (!(opt_quality)){
            if (fmt == 4) opt = "rate=0.95";
            if (fmt == 5) opt = "rate=0.95";
            if (fmt == 6) opt = "quality=95";
          }
          else{
            if ((fmt == 4) || (fmt == 5)){
                  opt = "rate=1.00\0";
                  for (i=0; opt[i]!='\0'; i++){ opt2[i] = opt[i]; } opt2[i] = opt[i];
                  if (opt_quality < 100){
                        opt2[5] = '0';
                        opt2[7] = '0' + (opt_quality / 10);
                        opt2[8] = '0' + (opt_quality % 10);
                  }
                  opt = opt2;
            }
            if (fmt == 6){
                  opt = "quality=100\0";
                  for (i=0; opt[i]!='\0'; i++){ opt2[i] = opt[i]; } opt2[i] = opt[i];
                  if (opt_quality < 100){
                        opt2[10] = '\0';
                        opt2[8] = '0' + (opt_quality / 10);
                        opt2[9] = '0' + (opt_quality % 10);
                  }
                  opt = opt2;
            }
          }

          // open file for writing and encode format
          /* print info */ STRING_PRINTV("opening file for writing\n");
          stream = jas_stream_fopen(file_name,"w+b");

          /* print info */ STRING_PRINTV("encoding jasper image\n");
          jas_image_encode(image, stream, fmt, opt);

          // write file
          /* print info */ STRING_PRINTV("writing image file\n");
          jas_stream_flush(stream);
          jas_stream_close(stream);

          // free previously allocated objects
          /* print info */ STRING_PRINTV("freeing jasper object\n");
          jas_image_destroy(image);
          jas_matrix_destroy(data);
          jas_image_clearfmts();
//        jas_cleanup();

      return 0;
}




// -----------------------------------------------
// --------- BITMAP READ IN PNG FORMAT -----------
// -----------------------------------------------
// source code examples for PNG read taken from:
// http://www.libpng.org/pub/png/book/chapter13.html
int BITMAP_READ_PNG(char *file_name)
{
      FILE *fhandle;
        // open file for reading
      /* print info */ STRING_PRINTV("opening file for reading\n");
        fhandle = fopen(file_name, "rb");
        if (fhandle == 0) return 1;

      // check PNG signature
      unsigned char sig[8];
      fread(sig, 1, 8, fhandle);

//    libpng version change to 1.4.0
//    if (!png_check_sig(sig, 8)) return 1;
      if (png_sig_cmp(sig, 0, 8) != 0) return 1;


      png_structp png_ptr;
      png_infop info_ptr;

      /* print info */ STRING_PRINTV("png initializations\n");
      png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
      // out of memory
      if (!png_ptr) return 1;

      info_ptr = png_create_info_struct(png_ptr);
      if (!info_ptr) {
            png_destroy_read_struct(&png_ptr, NULL, NULL);
            return 1;
      }

//    libpng version change to 1.4.0
//    if (setjmp(png_ptr->jmpbuf)) {
      if (setjmp(png_jmpbuf(png_ptr))) {
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            return 1;
      }

      png_init_io(png_ptr, fhandle);
      png_set_sig_bytes(png_ptr, 8);
      png_read_info(png_ptr, info_ptr);

      // get image header info
      png_uint_32 png_width, png_height;
      int bit_depth;

      png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bit_depth, \
            &bitmap_format_png_clrspc_type, &bitmap_format_png_interlace_type, \
            &bitmap_format_png_compression_type, &bitmap_format_png_filter_type);

      bitmap_width = png_width;
      bitmap_height = png_height;

      // get image resolution
      png_uint_32 res_x, res_y;
      int unit_type;

      png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type);

      xdpi = res_x;
      ydpi = res_y;
      udpi = unit_type;

      /* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
      /* print info */ STRING_PRINTV(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV(" pixels\n");
      /* print info */ STRING_PRINTV("resolution is "); STRING_PRINTVD(xdpi);
      /* print info */ STRING_PRINTV(" x "); STRING_PRINTVD(ydpi);
      /* print info */ if (udpi == 1)     { STRING_PRINTV(" pixels per meter\n"); }
      /* print info */ else         { STRING_PRINTV(" with unknown type\n"); }
      /* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(bit_depth);
      /* print info */ STRING_PRINTV(" bit depth\n");

      // bitmap depth must be 8 bit color, RGB or Grayscale
      if (bit_depth != 8) {
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            return 1;
      }

      // checking color types
      // 0 - Gray
      // 2 - RGB
      // 4 - Gray + Alpha
      // 6 - RGB + Alpha
        if (bitmap_format_png_clrspc_type != 0 &&
          bitmap_format_png_clrspc_type != 2 &&
          bitmap_format_png_clrspc_type != 4 &&
          bitmap_format_png_clrspc_type != 6) {
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            return 1;
      }

      // setting color types
        if (bitmap_format_png_clrspc_type == 0 || bitmap_format_png_clrspc_type == 4) {
            bitmap_format_jpg_clrspc_type = 8;
            bitmap_format_bmp_clrspc_type = 8; }
        if (bitmap_format_png_clrspc_type == 2 || bitmap_format_png_clrspc_type == 6) {
            bitmap_format_jpg_clrspc_type = 24;
            bitmap_format_bmp_clrspc_type = 24; }

      // if there is Alpha channel then allocate bigger memory for it
      // RGB + Alpha needs 5 times of the pixels because
      // the bytes need to be rearranged
      int alpha_flag = 0;
        if (bitmap_format_png_clrspc_type == 4) { alpha_flag = 1; }
        if (bitmap_format_png_clrspc_type == 6) { alpha_flag = 2; }

      /* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
      bitmap_buffer = malloc(bitmap_width * bitmap_height * (3 + alpha_flag));
      if (bitmap_buffer == 0) {
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            return 1;
      }


      unsigned long   i, rowbytes;
      unsigned char*  row_pointers[bitmap_height];

      png_read_update_info(png_ptr, info_ptr);
      rowbytes = png_get_rowbytes(png_ptr, info_ptr);


      /* print info */ STRING_PRINTV("copying colors from png object to bitmap buffer\n");
      for (i = 0;  i < bitmap_height;  ++i)
            row_pointers[i] = bitmap_buffer + i*rowbytes;

      png_read_image(png_ptr, row_pointers);

      png_read_end(png_ptr, NULL);

      // destroy png structure and free memory
      /* print info */ STRING_PRINTV("freeing png object\n");
      if (png_ptr && info_ptr) {
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            png_ptr = NULL;
            info_ptr = NULL;
      }



      // if it's Grayscale, then we pack the gray bytes to same RGB bytes
      // because the aaRGB function expects RGB bytes
      // if it's RGB picture with Alpha channel, then we pack the
      // RGB bytes to the begining of the allocated memory
      // and the Alpha bytes to the end
      // so it will be compatible in case of JPG output too
      // only the alpha channel will be lost
      // cause JPG does not support alpha

      long x, y;
      long offs1, offs2;

      /* print info */ STRING_PRINTV("converting colors to different format\n");
      // Gray
        if (bitmap_format_png_clrspc_type == 0){
            // copy Gray bytes to be RGB bytes
            offs1 = bitmap_width * bitmap_height * 1 - 1;
            offs2 = bitmap_width * bitmap_height * 3 - 3;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1];
                        bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1];
                        bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1];
                        offs1--;
                        offs2 = offs2 - 3;
                  }
            }
      }
      // RGB
        if (bitmap_format_png_clrspc_type == 2){
            // do nothing
      }
      // Gray + Alpha
        if (bitmap_format_png_clrspc_type == 4){
            // move Alpha bytes to the end
            offs1 = bitmap_width * bitmap_height * 2 - 1;
            offs2 = bitmap_width * bitmap_height * 4 - 1;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2] = bitmap_buffer[offs1];
                        offs1 = offs1 - 2;
                        offs2--;
                  }
            }
            // copy Gray bytes to be RGB bytes
            offs1 = bitmap_width * bitmap_height * 2 - 2;
            offs2 = offs2 - 2;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1];
                        bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1];
                        bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1];
                        offs1 = offs1 - 2;
                        offs2 = offs2 - 3;
                  }
            }
      }
      // RGB + Alpha
        if (bitmap_format_png_clrspc_type == 6){
            // move Alpha bytes to the 5. endpart
            offs1 = bitmap_width * bitmap_height * 4 - 1;
            offs2 = bitmap_width * bitmap_height * 5 - 1;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2] = bitmap_buffer[offs1];
                        offs1 = offs1 - 4;
                        offs2--;
                  }
            }
            // transfer RGBA bytes into RGB bytes
            offs1 = 0;
            offs2 = 0;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1 + 0];
                        bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1 + 1];
                        bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1 + 2];
                        offs1 = offs1 + 4;
                        offs2 = offs2 + 3;
                  }
            }
            // move Alpha bytes back to the 4. part
            offs1 = bitmap_width * bitmap_height * 5 - 1;
            offs2 = bitmap_width * bitmap_height * 4 - 1;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2] = bitmap_buffer[offs1];
                        offs1--;
                        offs2--;
                  }
            }
      }

      return 0;
}




// ------------------------------------------------
// --------- BITMAP WRITE IN PNG FORMAT -----------
// ------------------------------------------------
// source code examples for PNG write taken from:
// http://www.libpng.org/pub/png/book/chapter15.html
int BITMAP_WRITE_PNG(char *file_name)
{

      // Repacking the Gray and RGB bytes with the Alpha bytes
      /* print info */ STRING_PRINTV("converting colors to different format\n");

      long x, y;
      long offs1, offs2;
      long col;

      // Gray
        if (bitmap_format_png_clrspc_type == 0){
            // copy RGB bytes back as Gray bytes
            offs1 = 0;
            offs2 = 0;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        col = 0;
                        col += bitmap_buffer[offs2 + 0];
                        col += bitmap_buffer[offs2 + 1];
                        col += bitmap_buffer[offs2 + 2];
                        col /= 3;
                        bitmap_buffer[offs1] = col;
                        offs1++;
                        offs2 = offs2 + 3;
                  }
            }
      }
      // RGB
        if (bitmap_format_png_clrspc_type == 2){
            // do nothing
      }
      // Gray + Alpha
        if (bitmap_format_png_clrspc_type == 4){
            // copy RGB bytes back as Gray bytes
            offs1 = 0;
            offs2 = 0;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        col = 0;
                        col += bitmap_buffer[offs2 + 0];
                        col += bitmap_buffer[offs2 + 1];
                        col += bitmap_buffer[offs2 + 2];
                        col /= 3;
                        bitmap_buffer[offs1] = col;
                        offs1 = offs1 + 2;
                        offs2 = offs2 + 3;
                  }
            }
            // copy Alpha bytes back
            offs1 = bitmap_width * bitmap_height * 3 + 0;
            offs2 = 1;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2] = bitmap_buffer[offs1];
                        offs1++;
                        offs2 = offs2 + 2;
                  }
            }
      }
      // RGB + Alpha
        if (bitmap_format_png_clrspc_type == 6){
            // move Alpha bytes back from the 4. to the 5. endpart
            offs1 = bitmap_width * bitmap_height * 4 - 1;
            offs2 = bitmap_width * bitmap_height * 5 - 1;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2] = bitmap_buffer[offs1];
                        offs1--;
                        offs2--;
                  }
            }
            // transfer RGB bytes into RGBA bytes
            offs1 = bitmap_width * bitmap_height * 3 - 3;
            offs2 = bitmap_width * bitmap_height * 4 - 4;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2 + 2] = bitmap_buffer[offs1 + 2];
                        bitmap_buffer[offs2 + 1] = bitmap_buffer[offs1 + 1];
                        bitmap_buffer[offs2 + 0] = bitmap_buffer[offs1 + 0];
                        offs1 = offs1 - 3;
                        offs2 = offs2 - 4;
                  }
            }
            // move Alpha bytes back from the 5. endpart to RGBA
            offs1 = bitmap_width * bitmap_height * 5 - 1;
            offs2 = bitmap_width * bitmap_height * 4 - 1;
            for (y=0; y < bitmap_height; y++){
                  for (x=0; x < bitmap_width; x++){
                        bitmap_buffer[offs2] = bitmap_buffer[offs1];
                        offs1--;
                        offs2 = offs2 - 4;
                  }
            }
      }


      png_structp png_ptr;
      png_infop info_ptr;

      /* print info */ STRING_PRINTV("png initializations\n");
      png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
      // out of memory
      if (!png_ptr) return 1;

      info_ptr = png_create_info_struct(png_ptr);
      if (!info_ptr) {
            png_destroy_write_struct(&png_ptr, NULL);
            return 1;
      }

//    libpng version change to 1.4.0
//    if (setjmp(png_ptr->jmpbuf)) {
      if (setjmp(png_jmpbuf(png_ptr))) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return 1;
      }

        FILE *fhandle;
        // open file for writing
      /* print info */ STRING_PRINTV("opening file for writing\n");
        fhandle = fopen(file_name, "wb");
        if (fhandle == 0) return 1;


      png_init_io(png_ptr, fhandle);
      png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

      // set image header
      png_set_IHDR(png_ptr, info_ptr, bitmap_width, bitmap_height,
//          8, bitmap_format_png_clrspc_type, bitmap_format_png_interlace_type,
//          bitmap_format_png_compression_type, bitmap_format_png_filter_type);
            8, bitmap_format_png_clrspc_type, PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

        // set image resolution
        png_set_pHYs(png_ptr, info_ptr, xdpi, ydpi, udpi);


      png_write_info(png_ptr, info_ptr);
//    png_set_packing(png_ptr);


        unsigned long   i, rowbytes;
        unsigned char*  row_pointers[bitmap_height];

        png_read_update_info(png_ptr, info_ptr);
        rowbytes = png_get_rowbytes(png_ptr, info_ptr);


      /* print info */ STRING_PRINTV("copying colors from bitmap buffer to png object\n");
        for (i = 0;  i < bitmap_height;  ++i)
                row_pointers[i] = bitmap_buffer + i*rowbytes;

      /* print info */ STRING_PRINTV("writing image file\n");
      png_write_image(png_ptr, row_pointers);
      png_write_end(png_ptr, NULL);

      /* print info */ STRING_PRINTV("freeing png object\n");
      if (png_ptr && info_ptr)
            png_destroy_write_struct(&png_ptr, &info_ptr);

      return 0;
}

#endif



// ------------------------------------------------
// --------- BITMAP READ IN JPEG FORMAT -----------
// ------------------------------------------------
// source code examples for reading JPEG taken from libjpeg's example.c
int BITMAP_READ_JPEG(char *file_name)
{
      /* print info */ STRING_PRINTV("reading exif info\n");
      EXIF_GET(file_name);

      /* print info */ STRING_PRINTV("jpeg initializations\n");
      struct jpeg_decompress_struct cinfo;
      struct jpeg_error_mgr jerr;
      FILE *infile;
      JSAMPARRAY buffer;
      int row_stride;

      /* print info */ STRING_PRINTV("opening file for reading\n");
      if ((infile = fopen(file_name, "rb")) == NULL) { return 1; }

      cinfo.err = jpeg_std_error(&jerr);
      jpeg_create_decompress(&cinfo);
      jpeg_stdio_src(&cinfo, infile);
      (void) jpeg_read_header(&cinfo, TRUE);

       /* print info */ STRING_PRINTV("decoding jpeg image\n");
      (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);

      /* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
      bitmap_width = cinfo.output_width;
      bitmap_height = cinfo.output_height;
      bitmap_buffer = malloc(bitmap_width * bitmap_height * 3);
      if (bitmap_buffer == 0) return 1;

      xdpi = cinfo.X_density;
      ydpi = cinfo.Y_density;
      udpi = 0;
      // unit = 0, no units
      // unit = 1, unit is pixels per inch
      // unit = 2, unit is pixels per centimetre
      // here we convert the unit to meter, cause BMP and PNG too stores it as meter with unit being 1
      if (cinfo.density_unit == 1){ xdpi = xdpi * 1000 / 25.4; ydpi = ydpi * 1000 / 25.4; udpi = 1; }
      if (cinfo.density_unit == 2){ xdpi = xdpi * 100; ydpi = ydpi * 100; udpi = 1; }

      // determining colorspace type
      if (cinfo.output_components == 1) { bitmap_format_jpg_clrspc_type = 8; }
      if (cinfo.output_components == 3) { bitmap_format_jpg_clrspc_type = 24; }
        if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_png_clrspc_type = 0;  }
        if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_png_clrspc_type = 2;  }
        if (bitmap_format_jpg_clrspc_type == 8)  { bitmap_format_bmp_clrspc_type = 8;  }
        if (bitmap_format_jpg_clrspc_type == 24) { bitmap_format_bmp_clrspc_type = 24; }

      /* print info */ STRING_PRINTV("dimension is "); STRING_PRINTVD(bitmap_width);
      /* print info */ STRING_PRINTV(" x "); STRING_PRINTVD(bitmap_height); STRING_PRINTV(" pixels\n");
      /* print info */ STRING_PRINTV("resolution is "); STRING_PRINTVD(xdpi);
      /* print info */ STRING_PRINTV(" x "); STRING_PRINTVD(ydpi);
      /* print info */ if (udpi == 1)     { STRING_PRINTV(" pixels per meter\n"); }
      /* print info */ else         { STRING_PRINTV(" with unknown type\n"); }
      /* print info */ STRING_PRINTV("colors have "); STRING_PRINTVD(bitmap_format_jpg_clrspc_type);
      /* print info */ STRING_PRINTV(" bit depth\n");

      /* print info */ STRING_PRINTV("copying colors from jpeg object to bitmap buffer\n");
      while (cinfo.output_scanline < cinfo.output_height) {
            (void) jpeg_read_scanlines(&cinfo, buffer, 1);
//          put_scanline_someplace(buffer[0], row_stride);

            int i;
            if (cinfo.output_components == 3){
                  for(i=0; i<cinfo.output_width; i++){
                        bitmap_buffer[0 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i*3);
                        bitmap_buffer[1 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 1 + i*3);
                        bitmap_buffer[2 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 2 + i*3);
                  }
            }
            else{
                  for(i=0; i<cinfo.output_width; i++){
                        bitmap_buffer[0 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i);
                        bitmap_buffer[1 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i);
                        bitmap_buffer[2 + i*3 + (cinfo.output_scanline-1) * cinfo.output_width*3] = *(*buffer + 0 + i);
                  }
            }
      }

      /* print info */ STRING_PRINTV("freeing jpeg object\n");
      (void) jpeg_finish_decompress(&cinfo);
      jpeg_destroy_decompress(&cinfo);
      fclose(infile);

      return 0;
}




// -------------------------------------------------
// --------- BITMAP WRITE IN JPEG FORMAT -----------
// -------------------------------------------------
// source code examples for writing JPEG taken from libjpeg's example.c
int BITMAP_WRITE_JPEG(char *file_name)
{
      // write back exif info if there exists any
      if (exif_flag != 0) {
            /* print info */ STRING_PRINTV("writing exif info\n");
            EXIF_PUT(file_name);
            EXIF_CLEAR();
            // open file for writing and decode format (apped it to exif info)
            //stream = jas_stream_fopen(file_name,"a+b");
      }

      /* print info */ STRING_PRINTV("jpeg initializations\n");
      struct jpeg_compress_struct cinfo;
      struct jpeg_error_mgr jerr;
      FILE *outfile;
      JSAMPROW row_pointer[1];
      int row_stride;

      cinfo.err = jpeg_std_error(&jerr);
        jpeg_create_compress(&cinfo);

      /* print info */ STRING_PRINTV("opening file for writing\n");
      if ((outfile = fopen(file_name, "wb")) == NULL) { return 1; }

      jpeg_stdio_dest(&cinfo, outfile);

      cinfo.image_width = bitmap_width;
      cinfo.image_height = bitmap_height;
      if (bitmap_format_jpg_clrspc_type == 8){
            cinfo.input_components = 1;
            cinfo.in_color_space = JCS_GRAYSCALE;
      }
      if (bitmap_format_jpg_clrspc_type == 24){
            cinfo.input_components = 3;
            cinfo.in_color_space = JCS_RGB;
      }

      jpeg_set_defaults(&cinfo);

      // setting image resolution
      if (udpi == 0){
            // unknown unit
            cinfo.X_density = xdpi;
            cinfo.Y_density = ydpi;
            cinfo.density_unit = 0;
      }
      if (udpi == 1){
            // converting from pixel per meter to inch with rounding up to the closest decimal
            int xnew = (int)(xdpi * 25.4 / 100);
            int ynew = (int)(ydpi * 25.4 / 100);
            if ((xnew % 10) > 5){ xnew += 5; }
            if ((ynew % 10) > 5){ ynew += 5; }
            xnew /= 10;
            ynew /= 10;
            cinfo.X_density = xnew;
            cinfo.Y_density = ynew;
            cinfo.density_unit = 1;
      }

      // setting default quality to 95 if not set
      if (opt_quality < 0)  { opt_quality = 0;   }
      if (opt_quality > 100){ opt_quality = 100; }
      if (!(opt_quality))   { opt_quality = 95;  }
      jpeg_set_quality(&cinfo, opt_quality, TRUE);

      /* print info */ STRING_PRINTV("encoding jpeg image\n");
      jpeg_start_compress(&cinfo, TRUE);

      row_stride = bitmap_width * cinfo.input_components;

      // if image is 1 component Gray, then copy RGB bytes back as Gray bytes
      if (cinfo.input_components == 1){
                int offs1 = 0;
                int offs2 = 0;
            int col, x, y;
                for (y=0; y < bitmap_height; y++){
                        for (x=0; x < bitmap_width; x++){
                                col = 0;
                                col += bitmap_buffer[offs2 + 0];
                                col += bitmap_buffer[offs2 + 1];
                                col += bitmap_buffer[offs2 + 2];
                                col /= 3;
                                bitmap_buffer[offs1] = col;
                                offs1++;
                                offs2 = offs2 + 3;
                        }
                }
      }

      /* print info */ STRING_PRINTV("copying colors from bitmap buffer to jpeg object\n");
      while (cinfo.next_scanline < cinfo.image_height) {
            row_pointer[0] = &bitmap_buffer[cinfo.next_scanline * row_stride];
            (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
      }

      /* print info */ STRING_PRINTV("freeing jpeg object\n");
      jpeg_finish_compress(&cinfo);
      fclose(outfile);
      jpeg_destroy_compress(&cinfo);

      return 0;
}




// ---------------------------------------
// ----------- BITMAP LOAD ---------------
// ---------------------------------------
// load image and unpack it into memory (memory will be allocated)
int BITMAP_LOAD(char *file_name)
{
    // clear exif flag at new file
    exif_flag = 0;

      // does file exist?
      FILE *fhandle;
      fhandle = fopen(file_name, "rb");
      if (fhandle == 0) {
            return 2;
      }
      fclose(fhandle);

    /* print info */ STRING_PRINTV("file exists\n");
    // if it's a BMP format, then load BMP with custom procedure (and not jasper)
    if (GET_FILE_FORMAT(file_name) == 2){
        if (BITMAP_READ_BMP(file_name)) return 1;
    }
    else{

#ifdef __BMP_ONLY__
    STRING_PRINT("\n"); STRING_PRINTE("BMP_ONLY version. Only BMP format is supported here.\n");
    return 1;
#endif
#ifndef __BMP_ONLY__


      // if it's a PNG format, then load that one
        if (GET_FILE_FORMAT(file_name) == 8){
            if (BITMAP_READ_PNG(file_name)) return 1;
            return 0;
        }

      // if it's a JPEG, then save exif info and load image with libjpeg (and not libjasper)
        if (GET_FILE_FORMAT(file_name) == 6){
            if (BITMAP_READ_JPEG(file_name)) return 1;
            return 0;
        }

      // in every other case, load jasper format
      // because anyway there are no other supported formats
      // and jasper will signal if it's not one of its supported ones
        if (BITMAP_READ_JASPER(file_name)) return 1;
        return 0;


#endif
    }

      return 0;
}




// ---------------------------------------
// ----------- BITMAP SAVE ---------------
// ---------------------------------------
// pack the image file and save it from memory (memory will be freed)
int BITMAP_SAVE(char *file_name)
{
    // if the format is not JPEG, then clear exif info (memory is freed)
    if (GET_FILE_FORMAT(file_name) != 6){ EXIF_CLEAR(); }

    // if it's a BMP format, then save BMP with custom procedure (and not with jasper)
    if (GET_FILE_FORMAT(file_name) == 2){
        if (BITMAP_WRITE_BMP(file_name)) { free(bitmap_buffer); return 1; }

      // free memory on success
      /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
      free(bitmap_buffer);
      return 0;
    }
    else{

#ifdef __BMP_ONLY__
    STRING_PRINT("\n"); STRING_PRINTE("BMP_ONLY version. Only BMP format is supported here.\n");
    /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
    free(bitmap_buffer);
    return 1;
#endif
#ifndef __BMP_ONLY__


    // if it's a PNG, then save PNG
    if (GET_FILE_FORMAT(file_name) == 8){
        if (BITMAP_WRITE_PNG(file_name)) {
          /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
          free(bitmap_buffer); return 1; }

      // free memory on success
      /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
      free(bitmap_buffer);
      return 0;
    }

    // if it's a JPEG, then save it
    if (GET_FILE_FORMAT(file_name) == 6){
        if (BITMAP_WRITE_JPEG(file_name)) {
          /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
          free(bitmap_buffer); return 1; }

      // free memory on success
      /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
      free(bitmap_buffer);
      return 0;
    }


    // in every other case, save jasper format
    // because anyway there are no other supported formats
    // and jasper will signal if it's not one of its supported ones
    if (BITMAP_WRITE_JASPER(file_name)) {
          /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
          free(bitmap_buffer); return 1; }

    // free memory on success
    /* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
    free(bitmap_buffer);
    return 0;

#endif
    }

}


Generated by  Doxygen 1.6.0   Back to index