<commit_before>/** @file pgm.c
 ** @brief Portable graymap format (PGM) parser - Definition
 ** @author <NAME>
 **/

/*
Copyright (C) 2007-12 <NAME> and <NAME>.
Copyright (C) 2013 <NAME>.
All rights reserved.

This file is part of the VLFeat library and is made available under
the terms of the BSD license (see the COPYING file).
*/

/** @file pgm.h

This module implements basic input and ouptut of images in PGM
format.

Extracting an image encoded in PGM format from an imput
file stream involves the following steps:

- use ::vl_pgm_extract_head to extract the image meta data
  (size and bit depth);
- allocate a buffer to store the image data;
- use ::vl_pgm_extract_data to extract the image data to the allocated
  buffer.

Writing an image in PGM format to an ouptut file stream
can be done by using ::vl_pgm_insert.

To quickly read/write a PGM image from/to a given file, use
::vl_pgm_read_new() and ::vl_pgm_write(). To to the same from a
buffer in floating point format use ::vl_pgm_read_new_f() and
::vl_pgm_write_f().

**/

#include "pgm.h"

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

/** ------------------------------------------------------------------
 ** @internal @brief Remove all characters to the next new-line.
 ** @param f file to strip.
 ** @return number of characters removed.
 **/

static int
remove_line(FILE* f)
{
  int count = 0 ;
  int c ;

  while (1) {
    c = fgetc(f) ;
    ++ count ;

    switch(c) {
    case '\n' :
      goto quit_remove_line ;

    case EOF :
      -- count ;
      goto quit_remove_line ;
    }
  }
 quit_remove_line :
  return count ;
}

/** ------------------------------------------------------------------
 ** @internal @brief Remove white-spaces and comments.
 ** @param f file to strip.
 ** @return number of characters removed.
 **/

static int
remove_blanks(FILE* f)
{
  int count = 0 ;
  int c ;

  while (1) {
    c = fgetc(f) ;

    switch(c) {

    case '\t' : case '\n' :
    case '\r' : case ' '  :
      ++ count ;
      break ;

    case '#' :
      count += 1 + remove_line(f) ;
      break ;

    case EOF :
      goto quit_remove_blanks ;

    default:
      ungetc(c, f) ;
      goto quit_remove_blanks ;
    }
  }
 quit_remove_blanks:
  return count ;
}

/** ------------------------------------------------------------------
 ** @brief Get PGM image number of pixels.
 ** @param im PGM image descriptor.
 ** @return number of pixels of the image.
 **
 ** The functions returns the number of pixels of the PGM image @a im.
 **
 ** To calculate the image data size in bytes, this value must be
 ** multiplied by the number of byte per pixels (see
 ** ::vl_pgm_get_bpp()).
 **/

VL_EXPORT vl_size
vl_pgm_get_npixels (VlPgmImage const *im)
{
  return im->width * im->height ;
}

/** ------------------------------------------------------------------
 ** @brief Get PGM image bytes per pixel.
 ** @param im PGM image descriptor.
 ** @return number of bytes per pixel.
 **
 ** The function returns the number of bytes for each pixel of the
 ** PGM image @a im.
 **/

VL_EXPORT vl_size
vl_pgm_get_bpp (VlPgmImage const *im)
{
  return (im->max_value >= 256) + 1 ;
}

/** ------------------------------------------------------------------
 ** @brief Extract PGM header from stream.
 ** @param f  input file.
 ** @param im image structure to fill.
 ** @return error code.
 **
 ** The function extracts from the file @a f the meta-data section of
 ** an image encoded in PGM format. The function fills the structure
 ** ::VlPgmImage accordingly.
 **
 ** The error may be either ::VL_ERR_PGM_INV_HEAD or ::VL_ERR_PGM_INV_META
 ** depending whether the error occurred in decoding the header or
 ** meta section of the PGM file.
 **/

VL_EXPORT int
vl_pgm_extract_head (FILE* f, VlPgmImage *im)
{
  char magic [2] ;
  int c ;
  int is_raw ;
  int width ;
  int height ;
  int max_value ;
  size_t sz ;
  vl_bool good ;

  /* -----------------------------------------------------------------
   *                                                check magic number
   * -------------------------------------------------------------- */
  sz = fread(magic, 1, 2, f) ;

  if (sz < 2) {
    return vl_set_last_error(VL_ERR_PGM_INV_HEAD, "Invalid PGM header") ;
  }

  good = magic [0] == 'P' ;

  switch (magic [1]) {
  case '2' : /* ASCII format */
    is_raw = 0 ;
    break ;

  case '5' : /* RAW format */
    is_raw = 1 ;
    break ;

  default :
    good = 0 ;
    break ;
  }

  if( ! good ) {
    return vl_set_last_error(VL_ERR_PGM_INV_HEAD, "Invalid PGM header") ;
  }

  /* -----------------------------------------------------------------
   *                                    parse width, height, max_value
   * -------------------------------------------------------------- */
  good = 1 ;

  c = remove_blanks(f) ;
  good &= c > 0 ;

  c = fscanf(f, "%d", &width) ;
  good &= c == 1 ;

  c = remove_blanks(f) ;
  good &= c > 0 ;

  c = fscanf(f, "%d", &height) ;
  good &= c == 1 ;

  c = remove_blanks(f) ;
  good &= c > 0 ;

  c = fscanf(f, "%d", &max_value) ;
  good &= c == 1 ;

  /* must end with a single blank */
  c = fgetc(f) ;
  good &=
    c == '\n' ||
    c == '\t' ||
    c == ' '  ||
    c == '\r' ;

  if(! good) {
    return vl_set_last_error(VL_ERR_PGM_INV_META, "Invalid PGM meta information");
  }

  if(! max_value >= 65536) {
    return vl_set_last_error(VL_ERR_PGM_INV_META, "Invalid PGM meta information");
  }

  /* exit */
  im-> width     = width ;
  im-> height    = height ;
  im-> max_value = max_value ;
  im-> is_raw    = is_raw ;
  return 0 ;
}

/** ------------------------------------------------------------------
 ** @brief Extract PGM data from stream.
 ** @param f input file.
 ** @param im PGM image descriptor.
 ** @param data data buffer to fill.
 ** @return error code.
 **
 ** The function extracts from the file @a f the data section of an
 ** image encoded in PGM format. The function fills the buffer @a data
 ** according. The buffer @a data should be ::vl_pgm_get_npixels() by
 ** ::vl_pgm_get_bpp() bytes large.
 **/

VL_EXPORT
int
vl_pgm_extract_data (FILE* f, VlPgmImage const *im, void *data)
{
  vl_size bpp = vl_pgm_get_bpp(im) ;
  vl_size data_size = vl_pgm_get_npixels(im) ;
  vl_bool good = 1 ;
  size_t c ;

  /* -----------------------------------------------------------------
   *                                                         read data
   * -------------------------------------------------------------- */

  /*
     In RAW mode we read directly an array of bytes or shorts.  In
     the latter case, however, we must take care of the
     endianess. PGM files are sorted in big-endian format. If our
     architecture is little endian, we must do a conversion.
  */
  if (im->is_raw) {

    c = fread( data,
               bpp,
               data_size,
               f ) ;
    good = (c == data_size) ;

    /* adjust endianess */
#if defined(VL_ARCH_LITTLE_ENDIAN)
    if (bpp == 2) {
      vl_uindex i ;
      vl_uint8 *pt = (vl_uint8*) data ;
      for(i = 0 ; i < 2 * data_size ; i += 2) {
        vl_uint8 tmp = pt [i] ;
        pt [i]   = pt [i+1] ;
        pt [i+1] = tmp ;
      }
    }
#endif
  }
  /*
     In ASCII mode we read a sequence of decimal numbers separated
     by whitespaces.
  */
  else {
    vl_uindex i ;
    int unsigned v ;
    for(good = 1, i = 0 ;
        i < data_size && good ;
        ++i) {
      c = fscanf(f, " %ud", &v) ;
      if (bpp == 1) {
        * ((vl_uint8* )  data + i) = (vl_uint8)  v ;
      } else {
        * ((vl_uint16*)  data + i) = (vl_uint16) v ;
      }
      good &= c == 1 ;
    }
  }

  if(! good ) {
    return vl_set_last_error(VL_ERR_PGM_INV_DATA, "Invalid PGM data") ;
  }
  return 0 ;
}

/** ------------------------------------------------------------------
 ** @brief Insert a PGM image into a stream.
 ** @param f output file.
 ** @param im   PGM image meta-data.
 ** @param data image data.
 ** @return error code.<commit_msg>pgm.c: bugfix<commit_after>/** @file pgm.c
 ** @brief Portable graymap format (PGM) parser - Definition
 ** @author <NAME>
 **/

/*
Copyright (C) 2007-12 <NAME> and <NAME>.
Copyright (C) 2013 <NAME>.
All rights reserved.

This file is part of the VLFeat library and is made available under
the terms of the BSD license (see the COPYING file).
*/

/** @file pgm.h

This module implements basic input and ouptut of images in PGM
format.

Extracting an image encoded in PGM format from an imput
file stream involves the following steps:

- use ::vl_pgm_extract_head to extract the image meta data
  (size and bit depth);
- allocate a buffer to store the image data;
- use ::vl_pgm_extract_data to extract the image data to the allocated
  buffer.

Writing an image in PGM format to an ouptut file stream
can be done by using ::vl_pgm_insert.

To quickly read/write a PGM image from/to a given file, use
::vl_pgm_read_new() and ::vl_pgm_write(). To to the same from a
buffer in floating point format use ::vl_pgm_read_new_f() and
::vl_pgm_write_f().

**/

#include "pgm.h"

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

/** ------------------------------------------------------------------
 ** @internal @brief Remove all characters to the next new-line.
 ** @param f file to strip.
 ** @return number of characters removed.
 **/

static int
remove_line(FILE* f)
{
  int count = 0 ;
  int c ;

  while (1) {
    c = fgetc(f) ;
    ++ count ;

    switch(c) {
    case '\n' :
      goto quit_remove_line ;

    case EOF :
      -- count ;
      goto quit_remove_line ;
    }
  }
 quit_remove_line :
  return count ;
}

/** ------------------------------------------------------------------
 ** @internal @brief Remove white-spaces and comments.
 ** @param f file to strip.
 ** @return number of characters removed.
 **/

static int
remove_blanks(FILE* f)
{
  int count = 0 ;
  int c ;

  while (1) {
    c = fgetc(f) ;

    switch(c) {

    case '\t' : case '\n' :
    case '\r' : case ' '  :
      ++ count ;
      break ;

    case '#' :
      count += 1 + remove_line(f) ;
      break ;

    case EOF :
      goto quit_remove_blanks ;

    default:
      ungetc(c, f) ;
      goto quit_remove_blanks ;
    }
  }
 quit_remove_blanks:
  return count ;
}

/** ------------------------------------------------------------------
 ** @brief Get PGM image number of pixels.
 ** @param im PGM image descriptor.
 ** @return number of pixels of the image.
 **
 ** The functions returns the number of pixels of the PGM image @a im.
 **
 ** To calculate the image data size in bytes, this value must be
 ** multiplied by the number of byte per pixels (see
 ** ::vl_pgm_get_bpp()).
 **/

VL_EXPORT vl_size
vl_pgm_get_npixels (VlPgmImage const *im)
{
  return im->width * im->height ;
}

/** ------------------------------------------------------------------
 ** @brief Get PGM image bytes per pixel.
 ** @param im PGM image descriptor.
 ** @return number of bytes per pixel.
 **
 ** The function returns the number of bytes for each pixel of the
 ** PGM image @a im.
 **/

VL_EXPORT vl_size
vl_pgm_get_bpp (VlPgmImage const *im)
{
  return (im->max_value >= 256) + 1 ;
}

/** ------------------------------------------------------------------
 ** @brief Extract PGM header from stream.
 ** @param f  input file.
 ** @param im image structure to fill.
 ** @return error code.
 **
 ** The function extracts from the file @a f the meta-data section of
 ** an image encoded in PGM format. The function fills the structure
 ** ::VlPgmImage accordingly.
 **
 ** The error may be either ::VL_ERR_PGM_INV_HEAD or ::VL_ERR_PGM_INV_META
 ** depending whether the error occurred in decoding the header or
 ** meta section of the PGM file.
 **/

VL_EXPORT int
vl_pgm_extract_head (FILE* f, VlPgmImage *im)
{
  char magic [2] ;
  int c ;
  int is_raw ;
  int width ;
  int height ;
  int max_value ;
  size_t sz ;
  vl_bool good ;

  /* -----------------------------------------------------------------
   *                                                check magic number
   * -------------------------------------------------------------- */
  sz = fread(magic, 1, 2, f) ;

  if (sz < 2) {
    return vl_set_last_error(VL_ERR_PGM_INV_HEAD, "Invalid PGM header") ;
  }

  good = magic [0] == 'P' ;

  switch (magic [1]) {
  case '2' : /* ASCII format */
    is_raw = 0 ;
    break ;

  case '5' : /* RAW format */
    is_raw = 1 ;
    break ;

  default :
    good = 0 ;
    break ;
  }

  if( ! good ) {
    return vl_set_last_error(VL_ERR_PGM_INV_HEAD, "Invalid PGM header") ;
  }

  /* -----------------------------------------------------------------
   *                                    parse width, height, max_value
   * -------------------------------------------------------------- */
  good = 1 ;

  c = remove_blanks(f) ;
  good &= c > 0 ;

  c = fscanf(f, "%d", &width) ;
  good &= c == 1 ;

  c = remove_blanks(f) ;
  good &= c > 0 ;

  c = fscanf(f, "%d", &height) ;
  good &= c == 1 ;

  c = remove_blanks(f) ;
  good &= c > 0 ;

  c = fscanf(f, "%d", &max_value) ;
  good &= c == 1 ;

  /* must end with a single blank */
  c = fgetc(f) ;
  good &=
    c == '\n' ||
    c == '\t' ||
    c == ' '  ||
    c == '\r' ;

  if(! good) {
    return vl_set_last_error(VL_ERR_PGM_INV_META, "Invalid PGM meta information");
  }

  if(! (max_value >= 65536)) {
    return vl_set_last_error(VL_ERR_PGM_INV_META, "Invalid PGM meta information");
  }

  /* exit */
  im-> width     = width ;
  im-> height    = height ;
  im-> max_value = max_value ;
  im-> is_raw    = is_raw ;
  return 0 ;
}

/** ------------------------------------------------------------------
 ** @brief Extract PGM data from stream.
 ** @param f input file.
 ** @param im PGM image descriptor.
 ** @param data data buffer to fill.
 ** @return error code.
 **
 ** The function extracts from the file @a f the data section of an
 ** image encoded in PGM format. The function fills the buffer @a data
 ** according. The buffer @a data should be ::vl_pgm_get_npixels() by
 ** ::vl_pgm_get_bpp() bytes large.
 **/

VL_EXPORT
int
vl_pgm_extract_data (FILE* f, VlPgmImage const *im, void *data)
{
  vl_size bpp = vl_pgm_get_bpp(im) ;
  vl_size data_size = vl_pgm_get_npixels(im) ;
  vl_bool good = 1 ;
  size_t c ;

  /* -----------------------------------------------------------------
   *                                                         read data
   * -------------------------------------------------------------- */

  /*
     In RAW mode we read directly an array of bytes or shorts.  In
     the latter case, however, we must take care of the
     endianess. PGM files are sorted in big-endian format. If our
     architecture is little endian, we must do a conversion.
  */
  if (im->is_raw) {

    c = fread( data,
               bpp,
               data_size,
               f ) ;
    good = (c == data_size) ;

    /* adjust endianess */
#if defined(VL_ARCH_LITTLE_ENDIAN)
    if (bpp == 2) {
      vl_uindex i ;
      vl_uint8 *pt = (vl_uint8*) data ;
      for(i = 0 ; i < 2 * data_size ; i += 2) {
        vl_uint8 tmp = pt [i] ;
        pt [i]   = pt [i+1] ;
        pt [i+1] = tmp ;
      }
    }
#endif
  }
  /*
     In ASCII mode we read a sequence of decimal numbers separated
     by whitespaces.
  */
  else {
    vl_uindex i ;
    int unsigned v ;
    for(good = 1, i = 0 ;
        i < data_size && good ;
        ++i) {
      c = fscanf(f, " %ud", &v) ;
      if (bpp == 1) {
        * ((vl_uint8* )  data + i) = (vl_uint8)  v ;
      } else {
        * ((vl_uint16*)  data + i) = (vl_uint16) v ;
      }
      good &= c == 1 ;
    }
  }

  if(! good) {
    return vl_set_last_error(VL_ERR_PGM_INV_DATA, "Invalid PGM data") ;
  }
  return 0 ;
}

/** ------------------------------------------------------------------
 ** @brief Insert a PGM image into a stream.
 ** @param f output file.
 ** @param im   PGM image meta-data.
 ** @param data image data.
 ** @return error code.
{'fraction_non_alphanumeric': 0.21748133274769404, 'fraction_numerical': 0.008031624521553617, 'mean_word_length': 1.6527962716378162, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7258374', 'n_tokens_mistral': 5281, 'n_tokens_neox': 5086, 'n_words': 1704}