File: Codecs.hh

package info (click to toggle)
exactimage 1.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,040 kB
  • sloc: cpp: 35,940; ansic: 1,952; xml: 1,447; makefile: 338; perl: 138; sh: 110; python: 45; php: 37; ruby: 12
file content (205 lines) | stat: -rw-r--r-- 6,313 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
 * Copyright (C) 2006 - 2017 René Rebe, ExactCODE GmbH
 * 
 * This program 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; version 2. A copy of the GNU General
 * Public License can be found in the file LICENSE.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-
 * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 *
 * Alternatively, commercial licensing options are available from the
 * copyright holder ExactCODE GmbH Germany.
 */

/* The Image decoder and coder collection.
 *
 * The class itself has static methods to perform the de- and
 * encoding. These methods search thru a loader list to match the
 * file magick (on decoding) or the specified codec / file extension
 * on encoding.
 *
 * The codec might attach a freestanding instance of itself onto the
 * image on decode to allow on-the-fly decoding and reuse of coded
 * data while re-encoding an image where nothing or just meta data was
 * touched while the pixel data remains unmodified.
 *
 * Also some specialized methods are available to optimize some
 * operations that sometimes can work on encoded data.
 */

#ifndef IMAGELOADER_HH
#define IMAGELOADER_HH

#include <stdio.h>

#include <list>
#include <set>

#include <algorithm>
#include <iosfwd>

#include "Image.hh"

// just forward
class Image;

class ImageCodec
{
public:
  ImageCodec ();
  ImageCodec (Image* __image);
  virtual ~ImageCodec ();
  virtual std::string getID () = 0;

  // helpers for parsing the codec spec and filename extension
  static std::string getCodec (std::string& filename);
  static std::string getExtension (const std::string& filename);

  // NEW API, allowing the use of any STL i/o stream derived source. The index i
  // is the page, image, index number within the file (TIFF, GIF, ICO, etc.)
  // Negative returns signal the stream pointer was kept for delayed decoding!
  static int Read (std::istream* stream, Image& image,
		   std::string codec = "", const std::string& decompress = "", int index = 0);
  static bool Write (std::ostream* stream, Image& image,
		     std::string codec, std::string ext = "",
		     int quality = 75, const std::string& compress = "");
  static ImageCodec* MultiWrite (std::ostream* stream,
				 std::string codec, std::string ext = "", const std::string& compress = "");
  
  // OLD API, only left for compatibility.
  // Not const string& because the filename is parsed and the copy is changed intern.
  // 
  // Removed soon!
  static int Read (std::string file, Image& image, const std::string& decompress = "", int index = 0);
  static bool Write (std::string file, Image& image,
		     int quality = 75, const std::string& compress = "");
  
  // Per codec methods, only one set needs to be implemented, the one with
  // index invoke the one without by default (compatibility, ease of implemntation
  // fallback), the ones without return error (as in "not implemented").
  virtual int readImage (std::istream* stream, Image& image,
			 const std::string& decompress);
  virtual int readImage (std::istream* stream, Image& image,
			 const std::string& decompress, int index);

  virtual bool writeImage (std::ostream* stream, Image& image,
			   int quality, const std::string& compress) = 0;
  virtual ImageCodec* instanciateForWrite (std::ostream* stream, const std::string& compress = "");
  // named slightly differently to match the public factory name
  virtual bool Write (Image& image,
		      int quality = 75, const std::string& compress = "", int index = 0);
  
  // not pure-virtual so not every codec needs a NOP
  virtual /*bool*/ void decodeNow (Image* image);
  
  // optional optimizing and/or lossless implementations (JPEG, et al.)
  virtual bool flipX (Image& image);
  virtual bool flipY (Image& image);
  virtual bool rotate (Image& image, double angle);
  virtual bool crop (Image& image, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
  virtual bool toGray (Image& image);
  virtual bool scale (Image& image, double xscale, double yscale, bool fixed);
  
protected:
  
  struct loader_ref {
    const char* ext;
    ImageCodec* loader;
    bool primary_entry;
    bool via_codec_only;
  };
  
  static std::list<loader_ref>* loader;
  
  static void registerCodec (const char* _ext,
			     ImageCodec* _loader,
			     bool _via_codec_only = false,
			     bool push_back = false);
  static void unregisterCodec (ImageCodec* _loader);
  
  // freestanding instance, attached to an image
  const Image* _image;
};

class Args
{
public:
  Args(const std::string& _args, bool ignoreCase = true)
  {
    for (size_t it1 = 0; it1 < _args.size();) {
      size_t it2 = _args.find_first_of(",;|", it1);
      
      if (it2 == std::string::npos)
	it2 = _args.size();
      
      std::string s = _args.substr(it1, it2 - it1);
      if (ignoreCase)
	std::transform(s.begin(), s.end(), s.begin(), tolower);
      args.insert(s);
      
      it1 = it2 + 1;
    }
  }
  
  bool contains(const std::string& arg)
  {
    if (args.find(arg) != args.end())
      return true;
    else
      return false;
  }
  
  void remove(const std::string& arg)
  {
    args.erase(arg);
  }
  
  bool containsAndRemove(const std::string& arg)
  {
    if (contains(arg)) {
      remove(arg);
      return true;
    }
    return false;
  }

  std::string containsPrefixedAndRemove(const std::string& arg)
  {
    for (std::set<std::string>::iterator it = args.begin(); it != args.end(); ++it) {
      const std::string& str = *it;
      if (str.length() < arg.length())
	continue; // we shall not compare out of bounds iterators, ...
      
      int ret = str.compare(0, arg.length(), arg);
      if (ret == 0) {
	std::string ret = str.substr(arg.length());
	remove(str);
	return ret;
      }
    }
    return "";
  }
  
  std::string str()
  {
    std::string ret;
    std::set<std::string>::iterator it = args.begin();
    if (it != args.end())
      ret = *it++;
    
    for (; it != args.end(); ++it) {
      ret += ",";
      ret += *it;
    }
    return ret;
  }
  
protected:
  std::set<std::string> args;
};

#endif