From 537ce7ddb32932a2100ae767b1eca51a9dd1c35f Mon Sep 17 00:00:00 2001
From: scuri <scuri>
Date: Thu, 1 Oct 2009 14:14:53 +0000
Subject: New: ASCII compression for RAW format to access text data instead of
 binary.

---
 html/en/history.html    |  2 ++
 include/im_binfile.h    | 10 ++++++
 include/im_format_all.h |  2 +-
 include/im_format_ecw.h |  2 +-
 include/im_format_raw.h | 14 ++++++--
 src/im.def              |  2 ++
 src/im_binfile.cpp      | 68 ++++++++++++++++++++++++++++++++++-
 src/im_format_bmp.cpp   |  4 +--
 src/im_format_krn.cpp   | 77 +++++-----------------------------------
 src/im_format_led.cpp   | 49 ++++++--------------------
 src/im_format_pnm.cpp   | 63 +++++++++------------------------
 src/im_format_raw.cpp   | 94 +++++++++++++++++++++++++++++++++++++++++++------
 12 files changed, 215 insertions(+), 172 deletions(-)

diff --git a/html/en/history.html b/html/en/history.html
index 99da0f2..27c8626 100644
--- a/html/en/history.html
+++ b/html/en/history.html
@@ -24,6 +24,8 @@
 		<li><span style="color: #0000FF">New:</span> file attributes 
 		&quot;FileFormat&quot;, &quot;FileCompression&quot; and &quot;FileImageCount&quot; when reading from 
 		file. Available for all formats.</li>
+		<li><span style="color: #0000FF">New:</span> ASCII compression for RAW 
+		format to access text data instead of binary.</li>
 		<li><span style="color: #008000">Changed:</span> libPNG updated to version 
 	1.2.39. Removed changes to the library that made it incompatible with other 
 		libPNG distributions.</li>
diff --git a/include/im_binfile.h b/include/im_binfile.h
index 6bac31e..08af47a 100644
--- a/include/im_binfile.h
+++ b/include/im_binfile.h
@@ -73,6 +73,16 @@ unsigned long imBinFileWrite(imBinFile* bfile, void* pValues, unsigned long pCou
  * \ingroup binfile */
 unsigned long imBinFilePrintf(imBinFile* bfile, char *format, ...);
 
+/** Reads an integer number from the current position until found a non integer character.
+ * Returns a non zero value if sucessfull.
+ * \ingroup binfile */
+int imBinFileReadInteger(imBinFile* handle, int *value);
+
+/** Reads an floating point number from the current position until found a non number character.
+ * Returns a non zero value if sucessfull.
+ * \ingroup binfile */
+int imBinFileReadFloat(imBinFile* handle, float *value);
+
 /** Moves the file pointer from the begining of the file.\n
  * When writing to a file seeking can go beyond the end of the file.
  * \ingroup binfile */
diff --git a/include/im_format_all.h b/include/im_format_all.h
index bb43816..fc439d5 100644
--- a/include/im_format_all.h
+++ b/include/im_format_all.h
@@ -94,7 +94,7 @@ extern "C" {
         Tags BlackLevel, DefaultCropOrigin and DefaultCropSize are incorrectly interpreted by libTIFF so they are ignored.
         Raw image is loaded in place of the thumbnail image in the main IFD.
         SubIFDCount IM_USHORT (1)    [Number of subifds of the current image.]
-        SubIFDSelect IM_USHORT (1)   [Subifd number to be readed. Must be set before reading image info.]
+        SubIFDSelect IM_USHORT (1)   [Subifd number to be read. Must be set before reading image info.]
       (other attributes can be obtained by using libTIFF directly using the Handle(1) function)
 
     Comments:
diff --git a/include/im_format_ecw.h b/include/im_format_ecw.h
index 701bac3..c9e91a3 100644
--- a/include/im_format_ecw.h
+++ b/include/im_format_ecw.h
@@ -76,7 +76,7 @@ extern "C" {
       Only read support is implemented.
       To read a region of the image you must set the View* attributes before reading the image data.
       After reading a partial image the width and height returned in ReadImageInfo is the view size.
-      The view limits define the region to be readed. 
+      The view limits define the region to be read. 
       The view size is the actual size of the image, so the result can be zoomed.
 \endverbatim
  * \ingroup format */
diff --git a/include/im_format_raw.h b/include/im_format_raw.h
index 80a8203..4600271 100644
--- a/include/im_format_raw.h
+++ b/include/im_format_raw.h
@@ -22,9 +22,10 @@ extern "C" {
  * \par
  * Internal Implementation.
  * \par
- * Supports RAW binary images. This is a unstructured and uncompressed binary data. 
+ * Supports RAW binary images. This is an unstructured and uncompressed binary data. 
  * It is NOT a Camera RAW file generated in many professional digital cameras. \n
- * You must know image parameters a priori and must set the IM_INT attributes "Width", "Height", "ColorMode", "DataType" before the imFileReadImageInfo/imFileWriteImageInfo functions.
+ * You must know image parameters a priori and must set the IM_INT attributes "Width", "Height", "ColorMode", "DataType" 
+ * before the imFileReadImageInfo/imFileWriteImageInfo functions.
  * \par
  * The data must be in binary form, but can start in an arbitrary offset from the begining of the file, use attribute "StartOffset".
  * The default is at 0 offset. 
@@ -36,6 +37,9 @@ extern "C" {
  * \par
  * The lines can be aligned to a BYTE (1), WORD (2) or DWORD (4) boundaries, ue attribute "Padding" with the respective value.
  * \par
+ * If the compression is ASCII the data is stored in textual format, instead of binary. 
+ * In this case SwitchType and ByteOrder are ignored, and Padding should be 0.
+ * \par
  * See \ref im_raw.h
  * 
  * \section Features
@@ -44,7 +48,8 @@ extern "C" {
     Data Types: <all>
     Color Spaces: all, except MAP.
     Compressions: 
-      NONE - no compression 
+      NONE - no compression [default] 
+      ASCII (textual data)
     Can have more than one image, depends on "StartOffset" attribute.
     Can have an alpha channel.
     Components can be packed or not.
@@ -53,6 +58,9 @@ extern "C" {
     Attributes:
       Width, Height, ColorMode, DataType IM_INT (1)
       ImageCount[1], StartOffset[0], SwitchType[FALSE], ByteOrder[IM_LITTLEENDIAN], Padding[0]  IM_INT (1)
+
+    Comments:
+      In fact ASCII is an expansion, not a compression, because the file will be larger than binary data.
 \endverbatim
  * \ingroup format */
 imFormat* imFormatInitRAW(void);
diff --git a/src/im.def b/src/im.def
index 3f49105..2b8ea10 100644
--- a/src/im.def
+++ b/src/im.def
@@ -159,6 +159,8 @@ EXPORTS
   imBinFileRegisterModule
   imBinFileSetCurrentModule
   imBinFilePrintf
+  imBinFileReadInteger
+  imBinFileReadFloat
   imBinFileRead
   imBinFileSize
   imBinFileTell
diff --git a/src/im_binfile.cpp b/src/im_binfile.cpp
index 670623c..7171032 100644
--- a/src/im_binfile.cpp
+++ b/src/im_binfile.cpp
@@ -2,7 +2,7 @@
  * \brief Binary File Access
  *
  * See Copyright Notice in im_lib.h
- * $Id: im_binfile.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $
+ * $Id: im_binfile.cpp,v 1.2 2009/10/01 14:15:47 scuri Exp $
  */
 
 
@@ -637,6 +637,72 @@ unsigned long imBinFilePrintf(imBinFile* bfile, char *format, ...)
   return imBinFileWrite(bfile, buffer, size, 1);
 }
 
+int imBinFileReadInteger(imBinFile* handle, int *value)
+{
+  int i = 0, found = 0;
+  char buffer[11], c;
+
+  while (!found)
+  {
+    imBinFileRead(handle, &c, 1, 1);
+
+    /* if it's an integer, increments the number of characters read */
+    if ((c >= '0' && c <= '9') || (c == '-'))
+    {
+      buffer[i] = c;
+      i++;
+    }
+    else
+    {
+      /* if it's not, and we read some characters, convert them to an integer */
+      if (i > 0)
+      {
+        buffer[i] = 0;
+        *value = atoi(buffer);
+        found = 1;
+      }
+    }
+
+    if (imBinFileError(handle) || i > 10)
+      return 0;
+  } 
+
+  return 1;
+}
+
+int imBinFileReadFloat(imBinFile* handle, float *value)
+{
+  int i = 0, found = 0;
+  char buffer[17], c;
+
+  while (!found)
+  {
+    imBinFileRead(handle, &c, 1, 1);
+
+    /* if it's a floating point number, increments the number of characters read */
+    if ((c >= '0' && c <= '9') || c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E')
+    {
+      buffer[i] = c;
+      i++;
+    }
+    else
+    {
+      /* if it's not, and we read some characters convert them to an integer */
+      if (i > 0)
+      {
+        buffer[i] = 0;
+        *value = (float)atof(buffer);
+        found = 1;
+      }
+    }
+
+    if (imBinFileError(handle) || i > 16)
+      return 0;
+  } 
+
+  return 1;
+}
+
 static imBinFileBase* iBinFileBaseHandle(const char* pFileName)
 {
   imBinFile* bfile = (imBinFile*)pFileName;
diff --git a/src/im_format_bmp.cpp b/src/im_format_bmp.cpp
index b9b52dd..5cfe013 100644
--- a/src/im_format_bmp.cpp
+++ b/src/im_format_bmp.cpp
@@ -2,7 +2,7 @@
  * \brief BMP - Windows Device Independent Bitmap
  *
  * See Copyright Notice in im_lib.h
- * $Id: im_format_bmp.cpp,v 1.3 2009/08/19 18:39:43 scuri Exp $
+ * $Id: im_format_bmp.cpp,v 1.4 2009/10/01 14:15:47 scuri Exp $
  */
 
 #include "im_format.h"
@@ -524,7 +524,7 @@ int imFileFormatBMP::ReadImageInfo(int index)
     return IM_ERR_NONE;
   }
 
-  /* we already readed the compression information */
+  /* we already read the compression information */
   /* jump 8 bytes (compression, image size) */
   imBinFileSeekOffset(handle, 8);
 
diff --git a/src/im_format_krn.cpp b/src/im_format_krn.cpp
index 21261a8..a47d650 100644
--- a/src/im_format_krn.cpp
+++ b/src/im_format_krn.cpp
@@ -2,7 +2,7 @@
  * \brief KRN - IM Kernel File Format
  *
  * See Copyright Notice in im_lib.h
- * $Id: im_format_krn.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $
+ * $Id: im_format_krn.cpp,v 1.3 2009/10/01 14:15:47 scuri Exp $
  */
 
 #include "im_format.h"
@@ -17,66 +17,6 @@
 #include <memory.h>
 #include <math.h>
 
-static int iKRNReadNextInteger(imBinFile* handle, int *value)
-{
-  int c = 0, found = 0;
-  static char buffer[10];
-
-  while (!found)
-  {
-    imBinFileRead(handle, &buffer[c], 1, 1);
-
-    /* if it's a number increments the number of characters readed */
-    if ((buffer[c] >= (int)'0' && buffer[c] <= (int)'9') || buffer[c] == (int)'-')
-      c++;
-    else
-    {
-      /* if it's not a number and we readed some characters convert them to an integer */
-      if (c > 0)
-      {
-        buffer[c] = 0;
-        *value = atoi(buffer);
-        found = 1;
-      }
-    }
-
-    if (imBinFileError(handle) || c > 10)
-      return 0;
-  } 
-
-  return 1;
-}
-
-static int iKRNReadNextReal(imBinFile* handle, float *value)
-{
-  int c = 0, found = 0;
-  static char buffer[16];
-
-  while (!found)
-  {
-    imBinFileRead(handle, &buffer[c], 1, 1);
-
-    /* if it's a number increments the number of characters readed */
-    if ((buffer[c] >= (int)'0' && buffer[c] <= (int)'9') || buffer[c] == (int)'-' || buffer[c] == (int)'.')
-      c++;
-    else
-    {
-      /* if it's not a number and we readed some characters convert them to an integer */
-      if (c > 0)
-      {
-        buffer[c] = 0;
-        *value = (float)atof(buffer);
-        found = 1;
-      }
-    }
-
-    if (imBinFileError(handle) || c > 16)
-      return 0;
-  } 
-
-  return 1;
-}
-
 static int iKRNReadDescription(imBinFile* handle, char* comment, int *size)
 {
   imbyte byte_value = 0;
@@ -239,14 +179,14 @@ int imFileFormatKRN::ReadImageInfo(int index)
   if (desc_size)
     attrib_table->Set("Description", IM_BYTE, desc_size, desc);
 
-  if (!iKRNReadNextInteger(handle, &this->width))
+  if (!imBinFileReadInteger(handle, &this->width))
     return IM_ERR_ACCESS;
 
-  if (!iKRNReadNextInteger(handle, &this->height))
+  if (!imBinFileReadInteger(handle, &this->height))
     return IM_ERR_ACCESS;
 
   int type;
-  if (!iKRNReadNextInteger(handle, &type))
+  if (!imBinFileReadInteger(handle, &type))
     return IM_ERR_ACCESS;
 
   if (type == 0)
@@ -303,7 +243,7 @@ int imFileFormatKRN::ReadImageData(void* data)
       if (this->file_data_type == IM_INT)
       {
         int value;
-        if (!iKRNReadNextInteger(handle, &value))
+        if (!imBinFileReadInteger(handle, &value))
           return IM_ERR_ACCESS;
 
         ((int*)this->line_buffer)[col] = value;
@@ -311,7 +251,7 @@ int imFileFormatKRN::ReadImageData(void* data)
       else
       {
         float value;
-        if (!iKRNReadNextReal(handle, &value))
+        if (!imBinFileReadFloat(handle, &value))
           return IM_ERR_ACCESS;
 
         ((float*)this->line_buffer)[col] = value;
@@ -351,11 +291,10 @@ int imFileFormatKRN::WriteImageData(void* data)
         if (!imBinFilePrintf(handle, "%f ", (double)value))
           return IM_ERR_ACCESS;
       }
-
-      if (col == this->width-1)
-        imBinFileWrite(handle, (void*)"\n", 1, 1);
     }
 
+    imBinFileWrite(handle, (void*)"\n", 1, 1);
+
     if (imBinFileError(handle))
       return IM_ERR_ACCESS;     
 
diff --git a/src/im_format_led.cpp b/src/im_format_led.cpp
index eb7173c..7b75443 100644
--- a/src/im_format_led.cpp
+++ b/src/im_format_led.cpp
@@ -2,7 +2,7 @@
  * \brief LED - IUP image in LED
  *
  * See Copyright Notice in im_lib.h
- * $Id: im_format_led.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $
+ * $Id: im_format_led.cpp,v 1.3 2009/10/01 14:15:47 scuri Exp $
  */
 
 #include "im_format.h"
@@ -46,36 +46,6 @@ LEDImage = IMAGE[
 )
 */
 
-static int iLEDReadNextInteger(imBinFile* handle, int *value)
-{
-  int c = 0, found = 0;
-  static char buffer[10];
-
-  while (!found)
-  {
-    imBinFileRead(handle, &buffer[c], 1, 1);
-
-    /* if it's a number increments the number of characters readed */
-    if (buffer[c] >= (int)'0' && buffer[c] <= (int)'9')
-      c++;
-    else
-    {
-      /* if it's not a number and we readed some characters convert them to an integer */
-      if (c > 0)
-      {
-        buffer[c] = 0;
-        *value = atoi(buffer);
-        found = 1;
-      }
-    }
-
-    if (imBinFileError(handle) || c > 10)
-      return 0;
-  } 
-
-  return 1;
-}
-
 static const char* iLEDCompTable[1] = 
 {
   "NONE"
@@ -222,8 +192,8 @@ int imFileFormatLED::ReadImageInfo(int index)
   if (ReadPalette() != IM_ERR_NONE)
     return IM_ERR_ACCESS;
 
-  iLEDReadNextInteger(handle, &this->width);
-  iLEDReadNextInteger(handle, &this->height);
+  imBinFileReadInteger(handle, &this->width);
+  imBinFileReadInteger(handle, &this->height);
  
   if (imBinFileError(handle))
     return IM_ERR_ACCESS;
@@ -256,10 +226,10 @@ int imFileFormatLED::ReadPalette()
   /* convert the color map to the IM format */
   for (c = 0; c < this->palette_count; c++)
   {
-    iLEDReadNextInteger(handle, &i);
-    iLEDReadNextInteger(handle, &r);
-    iLEDReadNextInteger(handle, &g);
-    iLEDReadNextInteger(handle, &b);
+    imBinFileReadInteger(handle, &i);
+    imBinFileReadInteger(handle, &r);
+    imBinFileReadInteger(handle, &g);
+    imBinFileReadInteger(handle, &b);
 
     this->palette[i] = imColorEncode((unsigned char)r, (unsigned char)g, (unsigned char)b);
 
@@ -305,7 +275,7 @@ int imFileFormatLED::ReadImageData(void* data)
   {
     for (int col = 0; col < this->width; col++)
     {
-      if (!iLEDReadNextInteger(handle, &value))
+      if (!imBinFileReadInteger(handle, &value))
         return IM_ERR_ACCESS;
 
       ((imbyte*)this->line_buffer)[col] = (unsigned char)value;
@@ -330,7 +300,8 @@ int imFileFormatLED::WriteImageData(void* data)
 
     for (int col = 0; col < this->width; col++)
     {
-      imBinFilePrintf(handle, ",%d", (int)((imbyte*)this->line_buffer)[col]);
+      if (!imBinFilePrintf(handle, ",%d", (int)((imbyte*)this->line_buffer)[col]))
+        return IM_ERR_ACCESS;
     }
   
     imBinFileWrite(handle, (void*)"\n", 1, 1);
diff --git a/src/im_format_pnm.cpp b/src/im_format_pnm.cpp
index bd034ad..9347ddc 100644
--- a/src/im_format_pnm.cpp
+++ b/src/im_format_pnm.cpp
@@ -2,7 +2,7 @@
  * \brief PNM - Netpbm Portable Image Map
  *
  * See Copyright Notice in im_lib.h
- * $Id: im_format_pnm.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $
+ * $Id: im_format_pnm.cpp,v 1.3 2009/10/01 14:15:47 scuri Exp $
  */
 
 #include "im_format.h"
@@ -16,35 +16,6 @@
 #include <string.h>
 #include <memory.h>
 
-static int iPNMReadNextInteger(imBinFile* handle, int *value)
-{
-  int c = 0, found = 0;
-  static char buffer[10];
-
-  while (!found)
-  {
-    imBinFileRead(handle, &buffer[c], 1, 1);
-
-    /* if it's a number increments the number of characters readed */
-    if (buffer[c] >= (int)'0' && buffer[c] <= (int)'9')
-      c++;
-    else
-    {
-      /* if it's not a number and we readed some characters convert them to an integer */
-      if (c > 0)
-      {
-        buffer[c] = 0;
-        *value = atoi(buffer);
-        found = 1;
-      }
-    }
-
-    if (imBinFileError(handle) || c > 10)
-      return 0;
-  } 
-
-  return 1;
-}
 
 /* comments start with '#' after the first \n */
 static int iPNMReadComment(imBinFile* handle, char* comment, int *size)
@@ -236,10 +207,10 @@ int imFileFormatPNM::ReadImageInfo(int index)
   if (size)
     attrib_table->Set("Description", IM_BYTE, size, comment);
 
-  if (!iPNMReadNextInteger(handle, &this->width))
+  if (!imBinFileReadInteger(handle, &this->width))
     return IM_ERR_ACCESS;
 
-  if (!iPNMReadNextInteger(handle, &this->height))
+  if (!imBinFileReadInteger(handle, &this->height))
     return IM_ERR_ACCESS;
 
   if (this->height <= 0 || this->width <= 0)
@@ -248,7 +219,7 @@ int imFileFormatPNM::ReadImageInfo(int index)
   int max_val = 255;
   if (this->image_type != '4' && this->image_type != '1')
   {
-    if (!iPNMReadNextInteger(handle, &max_val))
+    if (!imBinFileReadInteger(handle, &max_val))
       return IM_ERR_ACCESS;
   }
 
@@ -264,16 +235,16 @@ int imFileFormatPNM::WriteImageInfo()
   this->file_data_type = this->user_data_type;
   this->file_color_mode = imColorModeSpace(this->user_color_mode);
 
-  int plain;
+  int ascii;
   if (imStrEqual(this->compression, "ASCII"))
-    plain = 1;
+    ascii = 1;
   else
-    plain = 0;
+    ascii = 0;
 
   switch (this->file_color_mode)
   {
   case IM_BINARY:
-    if (plain)
+    if (ascii)
       this->image_type = '1';
     else
     {
@@ -282,13 +253,13 @@ int imFileFormatPNM::WriteImageInfo()
     }
     break;
   case IM_GRAY:
-    if (plain)
+    if (ascii)
       this->image_type = '2';
     else
       this->image_type = '5';
     break;
   case IM_RGB:
-    if (plain)
+    if (ascii)
       this->image_type = '3';
     else
       this->image_type = '6';
@@ -360,18 +331,18 @@ int imFileFormatPNM::ReadImageData(void* data)
   else
     line_raw_size = imImageLineSize(this->width, this->file_color_mode, this->file_data_type);
 
-  int plain = 0;
+  int ascii = 0;
   if (this->image_type == '1' || this->image_type == '2' || this->image_type == '3')
-    plain = 1;
+    ascii = 1;
 
   for (int row = 0; row < this->height; row++)
   {
-    if (plain)
+    if (ascii)
     {
       int value;
       for (int col = 0; col < line_count; col++)
       {
-        if (!iPNMReadNextInteger(handle, &value))
+        if (!imBinFileReadInteger(handle, &value))
           return IM_ERR_ACCESS;
 
         if (this->image_type == '1' && value < 2)
@@ -436,15 +407,15 @@ int imFileFormatPNM::WriteImageData(void* data)
   else
     line_raw_size = imImageLineSize(this->width, this->file_color_mode, this->file_data_type);
 
-  int plain = 0;
+  int ascii = 0;
   if (this->image_type == '1' || this->image_type == '2' || this->image_type == '3')
-    plain = 1;
+    ascii = 1;
 
   for (int row = 0; row < this->height; row++)
   {
     imFileLineBufferWrite(this, data, row, 0);
 
-    if (plain)
+    if (ascii)
     {
       int line_size = 0;
       for (int col = 0; col < line_count; col++)
diff --git a/src/im_format_raw.cpp b/src/im_format_raw.cpp
index 6a6a7fd..56a2096 100644
--- a/src/im_format_raw.cpp
+++ b/src/im_format_raw.cpp
@@ -2,7 +2,7 @@
  * \brief RAW File Format
  *
  * See Copyright Notice in im_lib.h
- * $Id: im_format_raw.cpp,v 1.4 2009/09/10 17:33:35 scuri Exp $
+ * $Id: im_format_raw.cpp,v 1.5 2009/10/01 14:15:47 scuri Exp $
  */
 
 #include "im_format.h"
@@ -15,9 +15,10 @@
 #include <stdlib.h>
 #include <string.h>
 
-static const char* iRAWCompTable[1] = 
+static const char* iRAWCompTable[2] = 
 {
-  "NONE"
+  "NONE",
+  "ASCII"
 };
 
 class imFileFormatRAW: public imFileFormatBase
@@ -49,7 +50,7 @@ public:
               "RAW File Format", 
               "*.*;", 
               iRAWCompTable, 
-              1, 
+              2, 
               1)
     {}
   ~imFormatRAW() {}
@@ -213,15 +214,51 @@ int imFileFormatRAW::ReadImageData(void* data)
     line_count *= 2;
   }
 
+  int ascii;
+  if (imStrEqual(this->compression, "ASCII"))
+    ascii = 1;
+  else
+    ascii = 0;
+
   imCounterTotal(this->counter, count, "Reading RAW...");
 
   int row = 0, plane = 0;
   for (int i = 0; i < count; i++)
   {
-    imBinFileRead(this->handle, (imbyte*)this->line_buffer, line_count, type_size);
-
-    if (imBinFileError(this->handle))
-      return IM_ERR_ACCESS;
+    if (ascii)
+    {
+      for (int col = 0; col < line_count; col++)
+      {
+        if (this->file_data_type == IM_FLOAT)
+        {
+          float value;
+          if (!imBinFileReadFloat(handle, &value))
+            return IM_ERR_ACCESS;
+
+          ((float*)this->line_buffer)[col] = value;
+        }
+        else
+        {
+          int value;
+          if (!imBinFileReadInteger(handle, &value))
+            return IM_ERR_ACCESS;
+
+          if (this->file_data_type == IM_INT)
+            ((int*)this->line_buffer)[col] = value;
+          else if (this->file_data_type == IM_USHORT)
+            ((imushort*)this->line_buffer)[col] = (imushort)value;
+          else
+            ((imbyte*)this->line_buffer)[col] = (unsigned char)value;
+        }
+      }
+    }
+    else
+    {
+      imBinFileRead(this->handle, (imbyte*)this->line_buffer, line_count, type_size);
+
+      if (imBinFileError(this->handle))
+        return IM_ERR_ACCESS;
+    }
 
     imFileLineBufferRead(this, data, row, plane);
 
@@ -250,6 +287,12 @@ int imFileFormatRAW::WriteImageData(void* data)
     line_count *= 2;
   }
 
+  int ascii;
+  if (imStrEqual(this->compression, "ASCII"))
+    ascii = 1;
+  else
+    ascii = 0;
+
   imCounterTotal(this->counter, count, "Writing RAW...");
 
   int row = 0, plane = 0;
@@ -257,7 +300,38 @@ int imFileFormatRAW::WriteImageData(void* data)
   {
     imFileLineBufferWrite(this, data, row, plane);
 
-    imBinFileWrite(this->handle, (imbyte*)this->line_buffer, line_count, type_size);
+    if (ascii)
+    {
+      for (int col = 0; col < line_count; col++)
+      {
+        if (this->file_data_type == IM_FLOAT)
+        {
+          float value = ((float*)this->line_buffer)[col];
+
+          if (!imBinFilePrintf(handle, "%f ", (double)value))
+            return IM_ERR_ACCESS;
+        }
+        else
+        {
+          int value;
+          if (this->file_data_type == IM_INT)
+            value = ((int*)this->line_buffer)[col];
+          else if (this->file_data_type == IM_USHORT)
+            value = ((imushort*)this->line_buffer)[col];
+          else
+            value = ((imbyte*)this->line_buffer)[col];
+
+          if (!imBinFilePrintf(handle, "%d ", value))
+            return IM_ERR_ACCESS;
+        }
+      }
+
+      imBinFileWrite(handle, (void*)"\n", 1, 1);
+    }
+    else
+    {
+      imBinFileWrite(this->handle, (imbyte*)this->line_buffer, line_count, type_size);
+    }
 
     if (imBinFileError(this->handle))
       return IM_ERR_ACCESS;
@@ -285,7 +359,7 @@ int imFormatRAW::CanWrite(const char* compression, int color_mode, int data_type
   if (!compression || compression[0] == 0)
     return IM_ERR_NONE;
 
-  if (!imStrEqual(compression, "NONE"))
+  if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "ASCII"))
     return IM_ERR_COMPRESS;
 
   return IM_ERR_NONE;
-- 
cgit v1.2.3