2
* Copyright 2006-2008 The FLWOR Foundation.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
18
#include <zorba/zorba.h>
20
#include <zorba/base64.h>
21
#include <zorba/error_list.h>
22
#include <zorba/user_exception.h>
23
#include <zorba/empty_sequence.h>
24
#include <zorba/singleton_item_sequence.h>
25
#include "image_function.h"
26
#include "image_module.h"
28
namespace zorba { namespace imagemodule {
30
ImageFunction::ImageFunction(const ImageModule* aModule)
35
ImageFunction::~ImageFunction()
40
ImageFunction::getURI() const
42
return theModule->getURI();
45
ImageFunction::throwError(
46
const std::string aErrorMessage,
47
const Error& aErrorType)
49
throw USER_EXCEPTION(aErrorType, aErrorMessage.c_str() );
53
ImageFunction::throwImageError(const DynamicContext* aDynamicContext, const char *aMessage) {
54
std::stringstream lErrorMessage;
55
// constuct error QName
56
String lNamespace = "http://www.zorba-xquery.com/modules/image/error";
57
String lLocalname = "IM001";
59
Iterator_t lDummyIterator;
60
aDynamicContext->getVariable(lNamespace, lLocalname, lQName, lDummyIterator);
61
// if we have zero length image, then tell the user so
62
if (std::string(aMessage).find("zero-length") != std::string::npos) {
63
lErrorMessage << "The passed xs:base64Binary seems to be empty.";
64
USER_EXCEPTION(lQName, lErrorMessage.str());
66
lErrorMessage << "Error while processing xs:base64Binary. Possibly not a valid image type.";
67
USER_EXCEPTION(lQName, lErrorMessage.str());
72
ImageFunction::throwErrorWithQName (const DynamicContext* aDynamicContext, const String& aLocalName, const String& aMessage) {
73
String lNamespace = "http://www.zorba-xquery.com/modules/image/error";
75
Iterator_t lDummyIterator;
76
aDynamicContext->getVariable(lNamespace, aLocalName, lQName, lDummyIterator);
77
USER_EXCEPTION(lQName, aMessage);
81
ImageFunction::checkIfItemIsNull(Item& aItem) {
83
std::stringstream lErrorMessage;
84
lErrorMessage << "Error while building the base64binary item. ";
85
throwError(lErrorMessage.str(), err::XPST0083);
89
ImageFunction::getOneStringArg(
90
const ExternalFunction::Arguments_t& aArgs,
94
Iterator_t arg_iter = aArgs[aPos]->getIterator();
96
if (!arg_iter->next(lItem)) {
97
std::stringstream lErrorMessage;
98
lErrorMessage << "An empty-sequence is not allowed as "
99
<< aPos << ". parameter.";
100
throwError(lErrorMessage.str(), err::XPTY0004);
102
zorba::String lTmpString = lItem.getStringValue();
103
if (arg_iter->next(lItem)) {
104
std::stringstream lErrorMessage;
105
lErrorMessage << "A sequence of more then one item is not allowed as "
106
<< aPos << ". parameter.";
107
throwError(lErrorMessage.str(), err::XPTY0004);
114
ImageFunction::getOneBoolArg(
115
const ExternalFunction::Arguments_t& aArgs,
119
Iterator_t arg_iter = aArgs[aPos]->getIterator();
121
if (!arg_iter->next(lItem)) {
122
std::stringstream lErrorMessage;
123
lErrorMessage << "An empty-sequence is not allowed as "
124
<< aPos << ". parameter.";
125
throwError(lErrorMessage.str(), err::XPTY0004);
127
bool lTmpBool = lItem.getBooleanValue();
128
if (arg_iter->next(lItem)) {
129
std::stringstream lErrorMessage;
130
lErrorMessage << "A sequence of more then one item is not allowed as "
131
<< aPos << ". parameter.";
132
throwError(lErrorMessage.str(), err::XPTY0004);
139
ImageFunction::getOneColorArg(
140
const ExternalFunction::Arguments_t& aArgs,
142
Magick::ColorRGB& aColor)
145
Iterator_t arg_iter = aArgs[aPos]->getIterator();
147
if (!arg_iter->next(lItem)) {
148
aColor = Magick::ColorRGB(0.0,0.0,0.0);
151
zorba::String lTmpString = lItem.getStringValue();
152
if (arg_iter->next(lItem)) {
153
std::stringstream lErrorMessage;
154
lErrorMessage << "A sequence of more then one item is not allowed as "
155
<< aPos << ". parameter.";
156
throwError(lErrorMessage.str(), err::XPTY0004);
159
getColorFromString(lTmpString, aColor);
165
ImageFunction::getColorFromString(const String aColorString,
166
Magick::ColorRGB& aColor)
171
sscanf(aColorString.substr(1,2).c_str(), "%x", &lRed);
172
sscanf(aColorString.substr(3,2).c_str(), "%x", &lGreen);
173
sscanf(aColorString.substr(5,2).c_str(), "%x", &lBlue);
174
aColor = Magick::ColorRGB((double)lRed/(double)255.0, (double)lGreen/(double)255.0, (double)lBlue/(double)255.0);
179
ImageFunction::getOneIntArg(
180
const ExternalFunction::Arguments_t& aArgs,
184
Iterator_t arg_iter = aArgs[aPos]->getIterator();
186
if (!arg_iter->next(lItem)) {
187
std::stringstream lErrorMessage;
188
lErrorMessage << "An empty-sequence is not allowed as "
189
<< (aPos + 1) << ". parameter.";
190
throwError(lErrorMessage.str(), err::XPTY0004);
192
int lTmpInt = (int) lItem.getIntValue();
193
if (arg_iter->next(lItem)) {
194
std::stringstream lErrorMessage;
195
lErrorMessage << "A sequence of more then one item is not allowed as "
196
<< (aPos + 1) << ". parameter.";
197
throwError(lErrorMessage.str(), err::XPTY0004);
205
ImageFunction::getOneUnsignedIntArg(const ExternalFunction::Arguments_t& aArgs,
209
Iterator_t arg_iter = aArgs[aPos]->getIterator();
211
if (!arg_iter->next(lItem)) {
212
std::stringstream lErrorMessage;
213
lErrorMessage << "An empty-sequence is not allowed as "
214
<< (aPos + 1) << ". parameter.";
215
throwError(lErrorMessage.str(), err::XPTY0004);
217
unsigned int lTmpInt = lItem.getUnsignedIntValue();
218
if (arg_iter->next(lItem)) {
219
std::stringstream lErrorMessage;
220
lErrorMessage << "A sequence of more then one item is not allowed as "
221
<< (aPos + 1) << ". parameter.";
222
throwError(lErrorMessage.str(), err::XPTY0004);
230
ImageFunction::getOneDoubleArg(
231
const ExternalFunction::Arguments_t& aArgs,
235
Iterator_t arg_iter = aArgs[aPos]->getIterator();
237
if (!arg_iter->next(lItem)) {
238
std::stringstream lErrorMessage;
239
lErrorMessage << "An empty-sequence is not allowed as "
240
<< (aPos + 1) << ". parameter.";
241
throwError(lErrorMessage.str(), err::XPTY0004);
243
double lTmpDouble = lItem.getDoubleValue();
244
if (arg_iter->next(lItem)) {
245
std::stringstream lErrorMessage;
246
lErrorMessage << "A sequence of more then one item is not allowed as "
247
<< (aPos + 1) << ". parameter.";
248
throwError(lErrorMessage.str(), err::XPTY0004);
256
ImageFunction::getEncodedStringFromBlob(Magick::Blob& aBlob) {
258
std::string lStringOfBlobContent((char *)aBlob.data(), aBlob.length());
259
String lZorbaStringOfBlobContent(lStringOfBlobContent);
261
return zorba::encoding::Base64::encode(lZorbaStringOfBlobContent);
265
ImageFunction::getEncodedStringFromImage(const DynamicContext* aDynamicContext, Magick::Image& aImage) {
268
aImage.write(&lBlob);
269
} catch (Magick::Exception& error) {
270
throwImageError(aDynamicContext, error.what());
272
return getEncodedStringFromBlob(lBlob);
280
ImageFunction::getOneImageArg(const DynamicContext* aDynamicContext,
281
const ExternalFunction::Arguments_t& aArgs,
283
Magick::Image& aImage)
286
lData = getOneStringArg(aArgs, aPos);
287
getImageFromString(aDynamicContext, lData, aImage);
291
ImageFunction::getOneOrMoreImageArg(const DynamicContext* aDynamicContext,
292
const ExternalFunction::Arguments_t& aArgs,
294
std::list<Magick::Image>& aImages,
295
const unsigned int aDelay,
296
const unsigned int aIterations)
300
// make sure there is at least one item at the position
301
Iterator_t arg_iter = aArgs[aPos]->getIterator();
303
if (!arg_iter->next(lItem)) {
304
throwError("An empty sequence is not allowed as first parameter", err::XPTY0004);
307
Magick::Image lFirstImage;
308
ImageFunction::getImageFromString(aDynamicContext, lItem.getStringValue(), lFirstImage);
309
lFirstImage.animationDelay(aDelay);
310
lFirstImage.animationIterations(aIterations);
311
lFirstImage.gifDisposeMethod(3);
312
aImages.push_back(lFirstImage);
313
Magick::Image lTempImage;
314
while (arg_iter->next(lItem)) {
315
getImageFromString(aDynamicContext, lItem.getStringValue(), lTempImage);
316
aImages.push_back(lTempImage);
323
ImageFunction::getImageFromString(const DynamicContext* aDynamicContext, const String aString, Magick::Image& aImage) {
325
String lDecodedContent = zorba::encoding::Base64::decode(aString);
326
Magick::Blob lBlob(lDecodedContent.c_str(), lDecodedContent.size());
331
} catch (Magick::Exception &error) {
332
throwImageError(aDynamicContext, error.what());
338
ImageFunction::getAntiAliasingArg(
339
const ExternalFunction::Arguments_t& aArgs,
343
Iterator_t arg_iter = aArgs[aPos]->getIterator();
345
if (!arg_iter->next(lItem)) {
348
bool lTmpBool = lItem.getBooleanValue();
349
if (arg_iter->next(lItem)) {
350
std::stringstream lErrorMessage;
351
lErrorMessage << "A sequence of more then one item is not allowed as "
352
<< (aPos + 1) << ". parameter.";
353
throwError(lErrorMessage.str(), err::XPTY0004);
360
ImageFunction::getStrokeWidthArg(const ExternalFunction::Arguments_t& aArgs,
364
Iterator_t arg_iter = aArgs[aPos]->getIterator();
366
if (!arg_iter->next(lItem)) {
369
double lTmpDouble = lItem.getDoubleValue();
370
if (arg_iter->next(lItem)) {
371
std::stringstream lErrorMessage;
372
lErrorMessage << "A sequence of more then one item is not allowed as "
373
<< (aPos + 1) << ". parameter.";
374
throwError(lErrorMessage.str(), err::XPTY0004);