KSquare Utilities
ImageIO.cpp
Go to the documentation of this file.
1 /* ImageIO.cpp -- O/S Independent routines to load and save Raster Images.
2  * Copyright (C) 1994-2014 Kurt Kramer
3  * For conditions of distribution and use, see copyright notice in KKB.h
4  */
5 #include "FirstIncludes.h"
6 #include <iostream>
7 #include <iostream>
8 #include <vector>
9 #include <string.h>
10 
11 #if defined(OS_WINDOWS)
12 #include <windows.h>
13 #include <objidl.h>
14 #include <gdiplus.h>
15 using namespace Gdiplus;
16 #pragma comment (lib,"Gdiplus.lib")
17 #endif
18 
19 #include "MemoryDebug.h"
20 using namespace std;
21 
22 
23 
24 #include "ImageIO.h"
25 
26 #include "BMPImage.h"
27 #include "KKBaseTypes.h"
28 #include "KKException.h"
29 #include "Histogram.h"
30 #include "OSservices.h"
31 #include "Raster.h"
32 using namespace KKB;
33 
34 
35 namespace KKB
36 {
37  RasterPtr ReadImagePGM (const KKStr& imageFileName);
38 
39  RasterPtr ReadImagePPM (const KKStr& imageFileName);
40 
41  RasterPtr ReadImageUsingGDI (const KKStr& imageFileName);
42 
43 
44  KKStr ReadImagePpmField (FILE* in,
45  bool& eof
46  );
47 
48  void SaveImagePGM (const Raster& image,
49  const KKStr& imageFileName
50  );
51 
52  void SaveImagePNG (const Raster& image,
53  const KKStr& imageFileName
54  );
55 
56  void SaveImagePPM (const Raster& image,
57  const KKStr& imageFileName
58  );
59 
60  void DefineImageIoAtExit ();
61 
62  void ImageIoFinaleCleanUp ();
63 
64 
65  bool imageIoAtExitDefined = false;
66 }
67 
68 
69 
71 {
73  {
74  atexit (ImageIoFinaleCleanUp);
75  imageIoAtExitDefined = true;
76  }
77 }
78 
79 
80 
81 void KKB::DisplayImage (const Raster& image)
82 {
83  kkint32 col, row;
84 
85  for (row = 0; row < image.Height (); row++)
86  {
87  for (col = 0; col < image.Width (); col++)
88  {
89  cout << image.GetPixelValue ( row, col) << " ";
90  }
91 
92  cout << std::endl;
93  }
94 } /* DisplayImage */
95 
96 
97 
98 
99 void KKB::DisplayImage (const Raster& raster,
100  const KKStr& title
101  )
102 {
103  DisplayImage (raster);
104 }
105 
106 
107 
108 
109 #ifdef USE_CIMG
110 RasterPtr KKB::ReadImage (const KKStr& imageFileName)
111 {
112  kkint32 row, col;
113 
114  CImg<short> img = imageFileName.Str ();
115 
116  bool color;
117 
118  if (img.dimv () == 1)
119  color = false;
120  else
121  color = true;
122 
123  RasterPtr image = new Raster (img.dimy (), img.dimx ());
124 
125  kkint32 grayValue;
126  kkint32 r, g, b;
127 
128  for (row = 0; row < img.dimy(); row++)
129  {
130  for (col = 0; col < img.dimx(); col++)
131  {
132  if (color)
133  {
134  r = *img.ptr (col, row, 0, 0);
135  g = *img.ptr (col, row, 0, 1);
136  b = *img.ptr (col, row, 0, 2);
137 
138  grayValue = (kkint32)((float)r * (float)0.30 +
139  (float)g * (float)0.59 +
140  (float)b * (float)0.11 +
141  (float)(0.50)
142  );
143 
144  image->SetPixelValue (row, col, grayValue);
145  }
146  else
147  {
148  image->SetPixelValue (row, col, *img.ptr (col, row, 0, 0));
149  }
150  }
151  }
152 
153  image->FileName (imageFileName);
154 
155  return image;
156 } /* ReadImage */
157 
158 
159 
160 void KKB::SaveImage (const Raster& image,
161  const KKStr& imageFileName
162  )
163 {
164  kkint32 row, col;
165 
166  CImg<short> img (image.Width (), image.Height (), 1, 1);
167 
168  for (row = 0; row < image.Height (); row++)
169  {
170  for (col = 0; col < image.Width (); col++)
171  {
172  img.data[img.offset (col, row, 0, 0)] = image.GetPixelValue (row, col);
173  }
174  }
175 
176  img.save_other (imageFileName.Str ());
177 } /* SaveImage */
178 
179 
180 
181 
182 #else
183 
184 
185 
186 
187 
188 RasterPtr KKB::ReadImage (const KKStr& imageFileName)
189 {
190  bool successful = false;
191  RasterPtr image = NULL;
192 
193  KKStr extension = osGetFileExtension (imageFileName).ToLower ();
194  if (extension == "pgm")
195  {
196  image = ReadImagePGM (imageFileName);
197  }
198 
199  else if (extension == "bmp")
200  {
201  BmpImage bmpImage (imageFileName, successful);
202  if (!successful)
203  return NULL;
204  image = new Raster (bmpImage);
205  }
206 
207  else if (extension == "ppm")
208  {
209  image = ReadImagePPM (imageFileName);
210  }
211 
212 #if defined(OS_WINDOWS)
213  else if ((extension == "jpg") || (extension == "tif") || (extension == "tiff"))
214  {
215  image = ReadImageUsingGDI (imageFileName);
216  if (image)
217  {
218  if (!image->Color ())
219  image->ReverseImage ();
220  }
221  }
222 #endif
223 
224  return image;
225 } /* ReadImage */
226 
227 
228 #if defined(OS_WINDOWS)
229 
230 #include <Gdipluspixelformats.h>
231 
232 
233 bool gdiStarted = false;
236 
237 RasterPtr KKB::ReadImageUsingGDI (const KKStr& imageFileName)
238 {
239  if (!gdiStarted)
240  {
241  GdiplusStartupInput gdiplusStartupInput;
242  ULONG_PTR gdiplusToken;
243  // Initialize GDI+.
244  GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
245 
246  //GdiplusShutdown(gdiplusToken);
247 
248  gdiStarted = true;
250  }
251 
252  RasterPtr r = NULL;
253  wchar_t* imageFileNameWide = imageFileName.ToWchar_t ();
254 
255  Bitmap* bm = Bitmap::FromFile (imageFileNameWide, false);
256  if (bm == NULL)
257  {
258  cerr << endl << "KKB::ReadImageUsingGDI ***ERROR*** Reading file: " << imageFileName << endl;
259  }
260  else
261  {
262  kkuint32 height = bm->GetHeight ();
263  kkuint32 width = bm->GetWidth ();
264 
265  BitmapData* bitmapData = new BitmapData ();
266  Gdiplus::Rect rect (0, 0, width, height);
267 
268  bm->LockBits(&rect, Gdiplus::ImageLockModeRead, bm->GetPixelFormat (), bitmapData);
269 
270  Gdiplus::PixelFormat pixFormat = bitmapData->PixelFormat;
271  kkint32 stride = bitmapData->Stride;
272  void* scan0 = bitmapData->Scan0;
273 
274  if (pixFormat == PixelFormat24bppRGB)
275  {
276  r = new Raster (height, width, true);
277 
278  kkint32 nOffset = stride - width * 3;
279  kkint32 bytesPerRow = width * 3 + nOffset;
280 
281  uchar red = 255;
282  uchar green = 255;
283  uchar blue = 255;
284 
285  kkuint32 row, col;
286 
287  bool grayScaleImage = true;
288 
289  uchar* ptr = (uchar*)(void*)scan0;
290  for (row = 0; row < height; ++row)
291  {
292  for (col = 0; col < width; ++col)
293  {
294  red = *ptr; ++ptr;
295  green = *ptr; ++ptr;
296  blue = *ptr; ++ptr;
297  r->SetPixelValue (row, col, red, green, blue);
298 
299  if ((red != green) || (red != blue))
300  grayScaleImage= false;
301  }
302  ptr += nOffset;
303  }
304 
305  if (grayScaleImage)
306  {
307  RasterPtr grayScaleR = r->CreateGrayScale ();
308  delete r;
309  r = grayScaleR;
310  grayScaleR = NULL;
311  }
312  }
313 
314  else if (pixFormat == PixelFormat8bppIndexed)
315  {
316  kkint32 paletteSize = bm->GetPaletteSize ();
317 
318  ColorPalette* palette = (ColorPalette*)malloc (paletteSize);
319  bm->GetPalette (palette, paletteSize);
320 
321  INT paletteHasAlpha = palette->Flags & PaletteFlagsHasAlpha;
322  INT paletteHasGrayScale = palette->Flags & PaletteFlagsGrayScale;
323  INT paletteHasHalftone = palette->Flags & PaletteFlagsHalftone;
324 
325  r = new Raster (height, width, false);
326  kkint32 nOffset = stride - width;
327  kkint32 bytesPerRow = width + nOffset;
328 
329  uchar index = 255;
330 
331  kkuint32 row, col;
332 
333  uchar* ptr = (uchar*)(void*)scan0;
334 
335  for (row = 0; row < height; ++row)
336  {
337  for (col = 0; col < width; ++col)
338  {
339  index = *ptr; ++ptr;
340 
341  ARGB argb = palette->Entries[index];
342 
343  kkint32 grayScaleValue = argb % 256;
344 
345  r->SetPixelValue (row, col, (uchar)grayScaleValue);
346  }
347 
348  ptr += nOffset;
349  }
350 
351  free (palette);
352  palette = NULL;
353  }
354 
355  bm->UnlockBits (bitmapData);
356 
357  delete bitmapData; bitmapData = NULL;
358  delete bm; bm = NULL;
359  }
360 
361  delete imageFileNameWide;
362  imageFileNameWide = NULL;
363  return r;
364 }
365 
366 #endif
367 
368 
369 
370 
371 RasterPtr KKB::ReadImagePGM (const KKStr& imageFileName)
372 {
373  FILE* i = osFOPEN (imageFileName.Str (), "rb");
374  if (!i)
375  return NULL;
376 
377  kkint32 height = -1;
378  kkint32 pixelSize = -1;
379  kkint32 width = -1;
380 
381  {
382  // We are going to read in header part of file.
383  KKStr nextLine = "";
384  bool eof = false;
385  nextLine = osReadRestOfLine2 (i, eof);
386  if (eof || (nextLine[(kkint16)0] != 'P') || (nextLine[(kkint16)1] != '5'))
387  {
388  fclose (i);
389  return NULL;
390  }
391 
392  kkint32 headerFieldsRead = 0;
393  nextLine = osReadRestOfLine2 (i, eof);
394  while (!eof)
395  {
396  if (nextLine[(kkint16)0] != '#')
397  {
398  if (headerFieldsRead == 0)
399  {
400  width = nextLine.ExtractTokenInt (" \t\n\r");
401  height = nextLine.ExtractTokenInt (" \t\n\r");
402  }
403  if (headerFieldsRead == 1)
404  {
405  pixelSize = nextLine.ToInt ();
406  break;
407  }
408  headerFieldsRead++;
409  }
410  nextLine = osReadRestOfLine2 (i, eof);
411  }
412  }
413 
414  if ((pixelSize < 0) || (pixelSize > 255) ||
415  (width < 1) || (height < 1)
416  )
417  {
418  fclose (i);
419  cerr << endl << endl
420  << "ReadImagePGM ***ERROR*** ImageFile[" << imageFileName << "] Invalid Header"
421  << " width[" << width << "] height[" << height << "] pixelSize[" << pixelSize << "]"
422  << endl
423  << endl;
424  return NULL;
425  }
426 
427  RasterPtr image = new Raster (height, width, false);
428 
429  kkint32 row, col;
430 
431  uchar* colBuff = new uchar[width + 10];
432 
433  for (row = 0; row < height; row++)
434  {
435  fread (colBuff, 1, width, i);
436 
437  for (col = 0; col < width; col++)
438  {
439  image->SetPixelValue (row, col, colBuff[col]);
440  }
441  }
442 
443  fclose (i);
444 
445  return image;
446 } /* ReadImagePGM */
447 
448 
449 
450 
452  bool& eof
453  )
454 {
455  eof = false;
456  char token[2048];
457  kkint32 maxTokenLen = sizeof (token) - 1;
458 
459  kkint32 ch = 0;
460 
461  bool startOfTokenFound = false;
462  while (!startOfTokenFound)
463  {
464  // Skip leading white space
465  ch = fgetc (in); eof = (feof (in) != 0);
466  while ((!eof) && (strchr (" #\t\n\r", ch) != NULL) && (ch != '\n') && (ch != '#'))
467  {ch = fgetc (in); eof = (feof (in)!= 0);}
468 
469  if (eof)
470  return KKStr::EmptyStr ();
471 
472  else if (ch == '#')
473  {
474  // Skip the rest of the line.
475  while ((!eof) && (ch != '\n'))
476  {ch = fgetc (in); eof = (feof (in)!= 0);}
477  }
478 
479  else
480  {
481  startOfTokenFound = true;
482  }
483  }
484 
485  kkint32 tokenLen = 0;
486 
487  // Read till first delimiter or eof or eol
488  while ((!eof) && (strchr (" #\t\n\r", ch) == 0))
489  {
490  token[tokenLen] = ch;
491  tokenLen++;
492  if (tokenLen >= maxTokenLen)
493  break;
494  ch = fgetc (in); eof = (feof (in)!= 0);
495  }
496  token[tokenLen] = 0; // Terminating NULL character.
497  if ((!eof) && (ch == '#'))
498  {
499  // Skip the rest of the line.
500  while ((!eof) && (ch != '\n'))
501  {ch = fgetc (in); eof = (feof (in)!= 0);}
502  }
503 
504  if (eof & (tokenLen > 0))
505  {
506  eof = false;
507  ungetc ('\n', in);
508  }
509  return token;
510 } /* ReadImagePpmField */
511 
512 
513 
514 
515 RasterPtr KKB::ReadImagePPM (const KKStr& imageFileName)
516 {
517  FILE* i = osFOPEN (imageFileName.Str (), "rb");
518  if (!i)
519  return NULL;
520 
521  kkint32 height = -1;
522  kkint32 pixelDepth = -1;
523  kkint32 width = -1;
524 
525  bool eof = false;
526 
527  char buff[10];
528  kkint32 bytesRead = (kkint32)fread (buff, 1, 2, i);
529  if (bytesRead < 2)
530  {
531  fclose (i);
532  return NULL;
533  }
534 
535  bool p3Format = ((buff[0] == 'P') && (buff[1] == '3'));
536  bool p6Format = ((buff[0] == 'P') && (buff[1] == '6'));
537 
538  if (!p3Format && !p6Format)
539  {
540  fclose (i);
541  return NULL;
542  }
543 
544  kkint32 fieldNum = 0;
545  KKStr field = ReadImagePpmField (i, eof);
546  while ((fieldNum < 3) && (!eof))
547  {
548  switch (fieldNum)
549  {
550  case 0: width = field.ToInt32 (); break;
551  case 1: height = field.ToInt32 (); break;
552  case 2: pixelDepth = field.ToInt32 (); break;
553  }
554  ++fieldNum;
555  field = ReadImagePpmField (i, eof);
556  }
557 
558  if ((width < 1) || (height < 1) || (pixelDepth < 1) || (pixelDepth > 65535))
559  {
560  cerr << endl << "ReadImagePPM ***ERROR*** Invalid Header Fields: "
561  << "FileName[" << imageFileName << "] "
562  << "Width[" << width << "] Height[" << height << "] PixelDepth[" << pixelDepth << "]"
563  << endl
564  << endl;
565  fclose (i);
566  return NULL;
567  }
568 
569  RasterPtr image = new Raster (height, width, true);
570  int totalPixels = height * width;
571 
572  kkint32 pixelsRead = 0;
573 
574  uchar* red = image->RedArea ();
575  uchar* green = image->RedArea ();
576  uchar* blue = image->RedArea ();
577  if (p3Format)
578  {
579  while ((pixelsRead < totalPixels) && (!eof))
580  {
581  KKStr redField = osReadNextToken (i, "\n\r\t ", eof);
582  KKStr greenField = osReadNextToken (i, "\n\r\t ", eof);
583  KKStr blueField = osReadNextToken (i, "\n\r\t ", eof);
584 
585  kkint32 redValue = Min (redField.ToInt32 (), pixelDepth);
586  kkint32 greenValue = Min (greenField.ToInt32 (), pixelDepth);
587  kkint32 blueValue = Min (blueField.ToInt32 (), pixelDepth);
588 
589  *red = ((255 * redValue) / pixelDepth); ++red;
590  *green = ((255 * greenValue) / pixelDepth); ++green;
591  *blue = ((255 * blueValue) / pixelDepth); ++blue;
592 
593  ++pixelsRead;
594  }
595  }
596  else
597  {
598  char rgbBuff[3];
599  while ((pixelsRead < totalPixels) && (!eof))
600  {
601  fread (rgbBuff, 1, 3, i); eof = (feof (i) != 0);
602  *red = rgbBuff[0]; ++red;
603  *green = rgbBuff[1]; ++green;
604  *blue = rgbBuff[2]; ++blue;
605  ++pixelsRead;
606  }
607  }
608 
609  fclose (i);
610 
611  return image;
612 } /* ReadImagePPM */
613 
614 
615 
616 
617 void KKB::SaveImage (const Raster& image,
618  const KKStr& imageFileName
619  )
620 {
621  KKStr extension = osGetFileExtension (imageFileName);
622  extension.Upper ();
623 
624  if (extension == "BMP")
625  {
626  try
627  {
628  BmpImage bmpImage (image);
629  bmpImage.Save (imageFileName);
630  }
631  catch (const KKStr& errMsg)
632  {
633  throw KKException (errMsg);
634  }
635  catch (const KKException& errMsg)
636  {
637  KKStr msg = "SaveImage Exception Saving image using 'BmpImage'";
638  cerr << std::endl << msg << std::endl << std::endl;
639  throw KKException (msg, errMsg);
640  }
641  catch (...)
642  {
643  KKStr errMsg = "SaveImage Exception occurred calling 'BmpImage::Save' for file[" + imageFileName + "]";
644  cerr << std::endl << errMsg << std::endl << std::endl;
645  throw KKException (errMsg);
646  }
647  }
648 
649  else if (extension == "PGM")
650  {
651  SaveImagePGM (image, imageFileName);
652  }
653 
654  else if (extension == "PNG")
655  {
656  SaveImagePNG (image, imageFileName);
657  }
658 
659  else
660  {
661  KKStr errMsg = "ImageIO::SaveImage Extension[" + extension + "] is not supported.";
662 
663  cerr << std::endl << std::endl << std::endl
664  << "SaveImage *** ERROR *** " << std::endl
665  << errMsg << std::endl
666  << std::endl;
667  throw KKException (errMsg);
668  }
669 
670  return;
671 } /* SaveImage */
672 
673 
674 
675 void KKB::SaveImagePGM (const Raster& image,
676  const KKStr& imageFileName
677  )
678 {
679  FILE* o = osFOPEN (imageFileName.Str (), "wb");
680 
681  {
682  KKStr headerStr (15);
683  headerStr << "P5" << endl
684  << image.Width () << endl
685  << image.Height () << endl
686  << (kkint16)255 << endl;
687 
688  const char* h = headerStr.Str ();
689  fwrite (h, 1, headerStr.Len (), o);
690  }
691 
692  kkint32 totalPixels = image.Height () * image.Width ();
693 
694  if (image.Color ())
695  {
696  RasterPtr grayScaleImage = image.CreateGrayScale ();
697  const uchar* g = grayScaleImage->GreenArea ();
698  fwrite (g, 1, totalPixels, o);
699  delete grayScaleImage;
700  }
701  else
702  {
703  const uchar* g = image.GreenArea ();
704  fwrite (g, 1, totalPixels, o);
705  }
706 
707  fclose (o);
708 } /* SaveImagePGM */
709 
710 
711 
712 void KKB::SaveImagePNG (const Raster& image,
713  const KKStr& imageFileName
714  )
715 {
716  FILE* o = osFOPEN (imageFileName.Str (), "wb");
717  if (!o)
718  {
719  KKStr errMsg = "SaveImagePNG Error opening File[" + imageFileName + "]";
720  cerr << std::endl << errMsg << std::endl << std::endl;
721  throw KKException (errMsg);
722  }
723 
724  {
725  KKStr headerStr (15);
726  headerStr << "P6" << endl
727  << image.Width () << endl
728  << image.Height () << endl
729  << (kkint16)255 << endl;
730 
731  const char* h = headerStr.Str ();
732  fwrite (h, 1, headerStr.Len (), o);
733  }
734 
735  kkint32 totalPixels = image.Height () * image.Width ();
736 
737  if (image.Color ())
738  {
739  const uchar* red = image.RedArea ();
740  const uchar* green = image.GreenArea ();
741  const uchar* blue = image.BlueArea ();
742 
743  for (kkint32 x = 0; x < totalPixels; x++)
744  {
745  fwrite (red, 1, 1, o); ++red;
746  fwrite (green, 1, 1, o); ++green;
747  fwrite (blue, 1, 1, o); ++blue;
748  }
749  }
750  else
751  {
752  uchar* green = image.GreenArea ();
753  uchar buff3[3];
754 
755  for (kkint32 x = 0; x < totalPixels; x++)
756  {
757  uchar intensity = 255 - (*green);
758  buff3[0] = intensity;
759  buff3[1] = intensity;
760  buff3[2] = intensity;
761  fwrite (buff3, 1, 3, o);
762  ++green;
763  }
764  }
765 
766  fclose (o);
767  o = NULL;
768 
769  return ;
770 } /* SaveImagePNG */
771 
772 
773 
774 void KKB::SaveImagePPM (const Raster& image,
775  const KKStr& imageFileName
776  )
777 {
778  FILE* o = osFOPEN (imageFileName.Str (), "wb");
779  if (!o)
780  {
781  KKStr errMsg = "SaveImagePNG Error opening File[" + imageFileName + "]";
782  cerr << std::endl << errMsg << std::endl << std::endl;
783  throw KKException (errMsg);
784  }
785 
786  {
787  KKStr headerStr (15);
788  headerStr << "P6" << endl
789  << image.Width () << endl
790  << image.Height () << endl
791  << (kkint16)255 << endl;
792 
793  const char* h = headerStr.Str ();
794  fwrite (h, 1, headerStr.Len (), o);
795  }
796 
797  kkint32 totalPixels = image.Height () * image.Width ();
798 
799  if (image.Color ())
800  {
801  const uchar* red = image.RedArea ();
802  const uchar* green = image.GreenArea ();
803  const uchar* blue = image.BlueArea ();
804 
805  for (kkint32 x = 0; x < totalPixels; x++)
806  {
807  fwrite (red, 1, 1, o); ++red;
808  fwrite (green, 1, 1, o); ++green;
809  fwrite (blue, 1, 1, o); ++blue;
810  }
811  }
812  else
813  {
814  uchar* green = image.GreenArea ();
815  uchar buff3[3];
816 
817  for (kkint32 x = 0; x < totalPixels; x++)
818  {
819  uchar intensity = *green;
820  buff3[0] = intensity;
821  buff3[1] = intensity;
822  buff3[2] = intensity;
823  fwrite (buff3, 1, 3, o);
824  ++green;
825  }
826  }
827 
828  fclose (o);
829  o = NULL;
830 
831  return ;
832 } /* SaveImagePPM */
833 
834 
835 #endif
836 
837 
838 
839 
840 
841 void KKB::SaveImageInverted (Raster& raster,
842  const KKStr& imageFileName
843  )
844 {
845  RasterPtr invertedImage = new Raster (raster);
846 
847  kkint32 r, c;
848 
849  uchar** g = invertedImage->Green ();
850  uchar** red = invertedImage->Red ();
851  uchar** blue = invertedImage->Blue ();
852 
853  for (r = 0; r < invertedImage->Height (); r++)
854  {
855  for (c = 0; c < invertedImage->Width (); c++)
856  {
857  g[r][c] = 255 - g[r][c];
858  if (invertedImage->Color ())
859  {
860  red [r][c] = 255 - red [r][c];
861  blue[r][c] = 255 - blue[r][c];
862  }
863  }
864  }
865 
866  SaveImage (*invertedImage, imageFileName);
867  delete invertedImage;
868  invertedImage = NULL;
869 } /* SaveImageInverted */
870 
871 
872 
873 
875  const KKStr& _fileName
876  )
877 {
878  KKStr ext = osGetFileExtension (_fileName);
879  if (!ext.EqualIgnoreCase ("BMP"))
880  {
881  KKStr msg;
882  msg << "KKB::SaveImageGrayscaleInverted4Bit Only 'BMP' files are supported; FileName[" << _fileName << "].";
883  cerr << endl << "***ERROR*** " << msg << endl << endl;
884  throw KKException (msg);
885  }
886 
887  try
888  {
889  BmpImage bmpImage (image);
890  bmpImage.SaveGrayscaleInverted4Bit (_fileName);
891  }
892  catch (const KKException& errMsg)
893  {
894  KKStr msg = "SaveImageGrayscaleInverted4Bit Exception Saving image using 'BmpImage' for file[" + _fileName + "]";
895  cerr << std::endl << msg << std::endl << std::endl;
896  throw KKException (msg, errMsg);
897  }
898  catch (...)
899  {
900  KKStr errMsg = "SaveImageGrayscaleInverted4Bit Exception occurred calling 'BmpImage::Save' for file[" + _fileName + "]";
901  cerr << std::endl << errMsg << std::endl << std::endl;
902  throw KKException (errMsg);
903  }
904 } /* SaveImageGrayscaleInverted4Bit */
905 
906 
907 
908 
909 /**
910  *@brief Saves image as BMP using compressed GrayScale where Background = 255 and foreground = 0
911  *@details If image is color will convert to GrayScale 1st.
912  * Palette will be set to 0 = 255, 1 = 254, 2 = 253, ... 255 = 0.
913  */
915  const KKStr& _fileName
916  )
917 {
918  KKStr ext = osGetFileExtension (_fileName);
919  if (!ext.EqualIgnoreCase ("BMP"))
920  {
921  KKStr msg;
922  msg << "KKB::SaveImageGrayscaleInverted4Bit Only 'BMP' files are supported; FileName[" << _fileName << "].";
923  cerr << endl << "***ERROR*** " << msg << endl << endl;
924  throw KKException (msg);
925  }
926 
927  try
928  {
929  BmpImage bmpImage (image);
930  bmpImage.SaveGrayscaleInverted8Bit (_fileName);
931  }
932  catch (const KKException& errMsg)
933  {
934  KKStr msg = "SaveImageGrayscaleInverted8Bit Exception Saving image using 'BmpImage'";
935  cerr << std::endl << "***ERROR*** " << msg << std::endl << std::endl;
936  throw KKException (msg, errMsg);
937  }
938  catch (...)
939  {
940  KKStr errMsg = "SaveImageGrayscaleInverted8Bit Exception occurred calling 'BmpImage::Save' for file[" + _fileName + "]";
941  cerr << std::endl << errMsg << std::endl << std::endl;
942  throw KKException (errMsg);
943  }
944 } /* SaveImageGrayscaleInverted4Bit */
945 
946 
947 
948 bool KKB::SupportedImageFileFormat (const KKStr& imageFileName)
949 {
950  KKStr ext = osGetFileExtension (imageFileName);
951  ext.Upper ();
952 
953  return (
954  (ext == "BMP") ||
955  (ext == "PGM") ||
956  (ext == "PNG")
957  );
958 }
959 
960 
961 
962 
964 {
965  if (gdiStarted)
966  {
967  GdiplusShutdown(gdiplusToken);
968  gdiStarted = false;
969  }
970 }
KKStr(kkint32 size)
Creates a KKStr object that pre-allocates space for &#39;size&#39; characters.
Definition: KKStr.cpp:655
char operator[](kkint16 i) const
Definition: KKStr.cpp:3379
RasterPtr ReadImagePPM(const KKStr &imageFileName)
Definition: ImageIO.cpp:515
KKStr ReadImagePpmField(FILE *in, bool &eof)
Definition: ImageIO.cpp:451
bool EqualIgnoreCase(const char *s2) const
Definition: KKStr.cpp:1257
__int32 kkint32
Definition: KKBaseTypes.h:88
wchar_t * ToWchar_t() const
Definition: KKStr.cpp:3703
KKException(const KKStr &_exceptionStr, const KKException &_innerException)
Definition: KKException.cpp:83
RasterPtr ReadImagePGM(const KKStr &imageFileName)
Definition: ImageIO.cpp:371
void SetPixelValue(kkint32 row, kkint32 col, uchar pixVal)
Definition: Raster.cpp:1390
RasterPtr ReadImageUsingGDI(const KKStr &imageFileName)
Definition: ImageIO.cpp:237
A class that is used by to represent a single image in memory.
Definition: Raster.h:108
kkint32 ToInt() const
Definition: KKStr.cpp:3565
bool operator==(const char *rtStr) const
Definition: KKStr.cpp:1588
void SaveGrayscaleInverted8Bit(const KKStr &_fileName)
Saves image using compressed gray-scale where Background = 255 and foreground = 0.
Definition: BMPImage.cpp:2268
void SaveImagePGM(const Raster &image, const KKStr &imageFileName)
Definition: ImageIO.cpp:675
bool Color() const
Definition: Raster.h:310
KKStr operator+(const char *right) const
Definition: KKStr.cpp:3986
uchar ** Red() const
Definition: Raster.h:326
bool SupportedImageFileFormat(const KKStr &imageFileName)
Definition: ImageIO.cpp:948
void DefineImageIoAtExit()
Definition: ImageIO.cpp:70
KKStr osReadNextToken(FILE *in, const char *delimiters, bool &eof)
Read the next logical token from a file using characters in &#39;delimiters&#39; to separate tokens where &#39; &#39;...
RasterPtr ReadImage(const KKStr &imageFileName)
Definition: ImageIO.cpp:188
KKStr osGetFileExtension(KKStr fullFileName)
ULONG_PTR gdiplusToken
Definition: ImageIO.cpp:235
BmpImage(const Raster &raster)
Constructs a BMPImage instance from a Raster image; this is one way to save a Raster image to disk...
Definition: BMPImage.cpp:706
void ImageIoFinaleCleanUp()
Definition: ImageIO.cpp:963
KKStr & operator=(KKStr &&src)
Definition: KKStr.cpp:1369
void SaveImagePPM(const Raster &image, const KKStr &imageFileName)
Definition: ImageIO.cpp:774
kkint32 Height() const
Definition: Raster.h:319
KKB::KKStr osReadRestOfLine2(FILE *in, bool &eof)
void DisplayImage(const Raster &raster, const KKStr &title)
Definition: ImageIO.cpp:99
KKTHread * KKTHreadPtr
KKStr operator+(const char *left, const KKStr &right)
Definition: KKStr.cpp:3976
Used to encode and decode BMP Images.
Definition: BMPImage.h:49
void SaveImageGrayscaleInverted4Bit(const Raster &image, const KKStr &_fileName)
Saves image as BMP file using 4 bit compressed gray-scale where Background = 255 and foreground = 0...
Definition: ImageIO.cpp:874
void SaveGrayscaleInverted4Bit(const KKStr &_fileName)
Saves image using 4 bit compressed gray-scale where Background = 255 and foreground = 0...
Definition: BMPImage.cpp:2207
GdiplusStartupInput gdiplusStartupInput
Definition: ImageIO.cpp:234
void SaveImage(const Raster &image, const KKStr &imageFileName)
Definition: ImageIO.cpp:617
void SaveImageGrayscaleInverted8Bit(const Raster &image, const KKStr &_fileName)
Saves image as BMP using compressed gray-scale where Background = 255 and foreground = 0...
Definition: ImageIO.cpp:914
void SaveImageInverted(Raster &raster, const KKStr &imageFileName)
Definition: ImageIO.cpp:841
bool gdiStarted
Definition: ImageIO.cpp:233
kkint32 ToInt32() const
Definition: KKStr.cpp:3587
unsigned char uchar
Unsigned character.
Definition: KKBaseTypes.h:77
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of &#39;std::string&#39; strings.
Definition: KKStr.cpp:1082
void Upper()
Converts all characters in string to their Upper case equivalents via &#39;toupper&#39;.
Definition: KKStr.cpp:2461
uchar * RedArea() const
Definition: Raster.h:329
static const KKStr & EmptyStr()
Static method that returns an Empty String.
Definition: KKStr.cpp:3453
void Save(const KKStr &fileName)
Definition: BMPImage.cpp:2331
Raster(kkint32 _height, kkint32 _width, bool _color)
Constructs a blank image with given dimensions.
Definition: Raster.cpp:356
kkint32 ExtractTokenInt(const char *delStr)
Definition: KKStr.cpp:3129
uchar * GreenArea() const
Definition: Raster.h:330
const char * Str() const
Returns a pointer to a ascii string.
Definition: KKStr.h:422
uchar * BlueArea() const
Definition: Raster.h:331
kkint32 Width() const
Definition: Raster.h:324
FILE * osFOPEN(const char *fileName, const char *mode)
Definition: OSservices.cpp:74
Raster(const BmpImage &_bmpImage)
Constructs a Raster from a BMP image loaded from disk.
Definition: Raster.cpp:405
#define OS_WINDOWS
Definition: FirstIncludes.h:11
void ReverseImage()
Definition: Raster.cpp:1198
Raster(const Raster &_raster)
Copy Constructor.
Definition: Raster.cpp:460
bool imageIoAtExitDefined
Definition: ImageIO.cpp:65
uchar ** Blue() const
Definition: Raster.h:328
void DisplayImage(const Raster &image)
Definition: ImageIO.cpp:81
KKException(const KKStr &_exceptionStr)
Definition: KKException.cpp:45
RasterPtr CreateGrayScale() const
Definition: Raster.cpp:6060
uchar ** Green() const
Definition: Raster.h:327
BmpImage(const KKStr &_fileName, bool &successful)
Constructs a BMP image from the file specified by &#39;_fileName&#39;.
Definition: BMPImage.cpp:449
KKStr ToLower() const
Definition: KKStr.cpp:2529
void SaveImagePNG(const Raster &image, const KKStr &imageFileName)
Definition: ImageIO.cpp:712