|
|
|
/*
|
|
|
|
* This file is a part of Winix
|
|
|
|
* and is distributed under the 2-Clause BSD licence.
|
|
|
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2010-2021, Tomasz Sowa
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <ctime>
|
|
|
|
#include "image.h"
|
|
|
|
#include "utf8/utf8.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "lock.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Winix
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Image::SetDb(Db * pdb)
|
|
|
|
{
|
|
|
|
db = pdb;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Image::SetConfig(Config * pconfig)
|
|
|
|
{
|
|
|
|
config = pconfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Image::SetSystem(System * psystem)
|
|
|
|
{
|
|
|
|
system = psystem;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first thread (objects locked)
|
|
|
|
Image::Scale Image::GetImageScale(long dir_id)
|
|
|
|
{
|
|
|
|
Scale scale;
|
|
|
|
|
|
|
|
Mount * m = system->mounts.CalcMount(dir_id);
|
|
|
|
scale.cx = config->image_cx;
|
|
|
|
scale.cy = config->image_cy;
|
|
|
|
scale.aspect_mode = config->image_mode;
|
|
|
|
scale.quality = config->image_quality;
|
|
|
|
|
|
|
|
// reading width and height from the mount point (if exists)
|
|
|
|
int index = system->mounts.MountParImageSize();
|
|
|
|
|
|
|
|
if( m && m->param[index].defined && m->param[index].arg.size() == 2 )
|
|
|
|
{
|
|
|
|
scale.cx = Tol(m->param[index].arg[0]);
|
|
|
|
scale.cy = Tol(m->param[index].arg[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// reading image mode from the mount point (if exists)
|
|
|
|
index = system->mounts.MountParImageMode();
|
|
|
|
|
|
|
|
if( m && m->param[index].defined && m->param[index].arg.size() == 1 )
|
|
|
|
scale.aspect_mode = Toi(m->param[index].arg[0]);
|
|
|
|
|
|
|
|
// reading image quality from the mount point (if exists)
|
|
|
|
index = system->mounts.MountParImageQuality();
|
|
|
|
|
|
|
|
if( m && m->param[index].defined && m->param[index].arg.size() == 1 )
|
|
|
|
scale.quality = Toi(m->param[index].arg[0]);
|
|
|
|
|
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first thread (objects locked)
|
|
|
|
Image::Scale Image::GetThumbScale(long dir_id)
|
|
|
|
{
|
|
|
|
Scale scale;
|
|
|
|
|
|
|
|
Mount * m = system->mounts.CalcMount(dir_id);
|
|
|
|
scale.cx = config->thumb_cx;
|
|
|
|
scale.cy = config->thumb_cy;
|
|
|
|
scale.aspect_mode = config->thumb_mode;
|
|
|
|
scale.quality = config->thumb_quality;
|
|
|
|
|
|
|
|
// reading width and height from the mount point (if exists)
|
|
|
|
int index = system->mounts.MountParThumbSize();
|
|
|
|
|
|
|
|
if( m && m->param[index].defined && m->param[index].arg.size() == 2 )
|
|
|
|
{
|
|
|
|
scale.cx = Tol(m->param[index].arg[0]);
|
|
|
|
scale.cy = Tol(m->param[index].arg[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// reading thumb mode from the mount point (if exists)
|
|
|
|
index = system->mounts.MountParThumbMode();
|
|
|
|
|
|
|
|
if( m && m->param[index].defined && m->param[index].arg.size() == 1 )
|
|
|
|
scale.aspect_mode = Toi(m->param[index].arg[0]);
|
|
|
|
|
|
|
|
// reading image quality from the mount point (if exists)
|
|
|
|
index = system->mounts.MountParThumbQuality();
|
|
|
|
|
|
|
|
if( m && m->param[index].defined && m->param[index].arg.size() == 1 )
|
|
|
|
scale.quality = Toi(m->param[index].arg[0]);
|
|
|
|
|
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first thread (objects locked)
|
|
|
|
void Image::Resize(long file_id, size_t cx, size_t cy, int aspect_mode, int quality)
|
|
|
|
{
|
|
|
|
item_temp.type = WINIX_IMAGE_TYPE_RESIZE;
|
|
|
|
item_temp.file_id = file_id;
|
|
|
|
item_temp.cx = cx;
|
|
|
|
item_temp.cy = cy;
|
|
|
|
item_temp.aspect_mode = aspect_mode;
|
|
|
|
item_temp.quality = quality;
|
|
|
|
|
|
|
|
CheckParam(item_temp);
|
|
|
|
image_tab.insert(image_tab.end(), item_temp);
|
|
|
|
WakeUpThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first thread (objects locked)
|
|
|
|
void Image::CreateThumb(long file_id, size_t thumb_cx, size_t thumb_cy, int aspect_mode, int quality)
|
|
|
|
{
|
|
|
|
item_temp.type = WINIX_IMAGE_TYPE_CREATE_THUMB;
|
|
|
|
item_temp.file_id = file_id;
|
|
|
|
item_temp.thumb_cx = thumb_cx;
|
|
|
|
item_temp.thumb_cy = thumb_cy;
|
|
|
|
item_temp.aspect_mode = aspect_mode;
|
|
|
|
item_temp.quality = quality;
|
|
|
|
|
|
|
|
CheckParam(item_temp);
|
|
|
|
image_tab.insert(image_tab.end(), item_temp);
|
|
|
|
WakeUpThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first thread (objects locked)
|
|
|
|
void Image::Crop(long file_id, size_t xoffset, size_t yoffset, size_t cx, size_t cy, int quality)
|
|
|
|
{
|
|
|
|
item_temp.type = WINIX_IMAGE_TYPE_CROP;
|
|
|
|
item_temp.file_id = file_id;
|
|
|
|
item_temp.xoffset = xoffset;
|
|
|
|
item_temp.yoffset = yoffset;
|
|
|
|
item_temp.cx = cx;
|
|
|
|
item_temp.cy = cy;
|
|
|
|
item_temp.quality = quality;
|
|
|
|
|
|
|
|
CheckParam(item_temp);
|
|
|
|
image_tab.insert(image_tab.end(), item_temp);
|
|
|
|
WakeUpThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first thread (objects locked)
|
|
|
|
void Image::CropThumb(long file_id, size_t xoffset, size_t yoffset, size_t cx, size_t cy, int quality)
|
|
|
|
{
|
|
|
|
item_temp.type = WINIX_IMAGE_TYPE_CROP_THUMB;
|
|
|
|
item_temp.file_id = file_id;
|
|
|
|
item_temp.xoffset = xoffset;
|
|
|
|
item_temp.yoffset = yoffset;
|
|
|
|
item_temp.cx = cx;
|
|
|
|
item_temp.cy = cy;
|
|
|
|
item_temp.quality = quality;
|
|
|
|
|
|
|
|
CheckParam(item_temp);
|
|
|
|
image_tab.insert(image_tab.end(), item_temp);
|
|
|
|
WakeUpThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first thread (objects locked)
|
|
|
|
void Image::CropNewThumb(long file_id, size_t xoffset, size_t yoffset, size_t cx, size_t cy,
|
|
|
|
size_t thumb_cx, size_t thumb_cy, int aspect_mode, int quality)
|
|
|
|
{
|
|
|
|
item_temp.type = WINIX_IMAGE_TYPE_CREATE_CROP_NEW_THUMB;
|
|
|
|
item_temp.file_id = file_id;
|
|
|
|
item_temp.xoffset = xoffset;
|
|
|
|
item_temp.yoffset = yoffset;
|
|
|
|
item_temp.cx = cx;
|
|
|
|
item_temp.cy = cy;
|
|
|
|
item_temp.thumb_cx = thumb_cx;
|
|
|
|
item_temp.thumb_cy = thumb_cy;
|
|
|
|
item_temp.aspect_mode = aspect_mode;
|
|
|
|
item_temp.quality = quality;
|
|
|
|
|
|
|
|
CheckParam(item_temp);
|
|
|
|
image_tab.insert(image_tab.end(), item_temp);
|
|
|
|
WakeUpThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Image::CheckParam(ImageItem & item)
|
|
|
|
{
|
|
|
|
SetMinMax(item.aspect_mode, 1, 7);
|
|
|
|
SetMinMax(item.quality, 0, 100);
|
|
|
|
SetMinMax(item.cx, 1, 30000);
|
|
|
|
SetMinMax(item.cy, 1, 30000);
|
|
|
|
SetMinMax(item.thumb_cx, 1, 30000);
|
|
|
|
SetMinMax(item.thumb_cy, 1, 30000);
|
|
|
|
SetMinMax(item.xoffset, 0, 30000);
|
|
|
|
SetMinMax(item.yoffset, 0, 30000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects locked)
|
|
|
|
bool Image::SignalReceived()
|
|
|
|
{
|
|
|
|
return !image_tab.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects not locked)
|
|
|
|
void Image::Do()
|
|
|
|
{
|
|
|
|
ImageTab::iterator i;
|
|
|
|
bool end;
|
|
|
|
|
|
|
|
Lock();
|
|
|
|
i = image_tab.begin();
|
|
|
|
Unlock();
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
class Lock lock_object(synchro);
|
|
|
|
|
|
|
|
if( i != image_tab.end() )
|
|
|
|
{
|
|
|
|
item_work = *i;
|
|
|
|
image_tab.erase(i++);
|
|
|
|
end = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
end = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
lock_object.Unlock();
|
|
|
|
|
|
|
|
if( !end )
|
|
|
|
CreateImage();
|
|
|
|
|
|
|
|
}
|
|
|
|
while( !end && !IsExitSignal() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Image::Add(const std::wstring & in, TextStream<std::string> & out)
|
|
|
|
{
|
|
|
|
PT::WideToUTF8(in, add_tempa);
|
|
|
|
out << add_tempa;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Image::EscapePath(const std::string & path, TextStream<std::string> & out, bool clear_stream)
|
|
|
|
{
|
|
|
|
if( clear_stream )
|
|
|
|
out.Clear();
|
|
|
|
|
|
|
|
out << '"';
|
|
|
|
|
|
|
|
for(size_t i=0 ; i<path.size() ; ++i)
|
|
|
|
{
|
|
|
|
if( path[i] == '"' )
|
|
|
|
out << '\\';
|
|
|
|
|
|
|
|
if( path[i] != 0 )
|
|
|
|
out << path[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
out << '\"';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
from: http://www.imagemagick.org/script/command-line-processing.php#geometry
|
|
|
|
|
|
|
|
scale% Height and width both scaled by specified percentage.
|
|
|
|
scale-x%xscale-y% Height and width individually scaled by specified percentages. (Only one % symbol needed.)
|
|
|
|
width Width given, height automagically selected to preserve aspect ratio.
|
|
|
|
xheight Height given, width automagically selected to preserve aspect ratio.
|
|
|
|
widthxheight Maximum values of height and width given, aspect ratio preserved.
|
|
|
|
widthxheight^ Minimum values of width and height given, aspect ratio preserved.
|
|
|
|
widthxheight! Width and height emphatically given, original aspect ratio ignored.
|
|
|
|
widthxheight> Change as per widthxheight but only if an image dimension exceeds a specified dimension.
|
|
|
|
widthxheight< Change dimensions only if both image dimensions exceed specified dimensions.
|
|
|
|
*/
|
|
|
|
void Image::SelectAspect(size_t cx, size_t cy)
|
|
|
|
{
|
|
|
|
switch( item_work.aspect_mode )
|
|
|
|
{
|
|
|
|
case WINIX_IMAGE_MODE_1:
|
|
|
|
command << cx;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINIX_IMAGE_MODE_3:
|
|
|
|
command << cx << "x" << cy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINIX_IMAGE_MODE_4:
|
|
|
|
command << '"' << cx << "x" << cy << "^\"";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINIX_IMAGE_MODE_5:
|
|
|
|
command << '"' << cx << "x" << cy << "!\"";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINIX_IMAGE_MODE_6:
|
|
|
|
command << '"' << cx << "x" << cy << ">\"";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINIX_IMAGE_MODE_7:
|
|
|
|
command << '"' << cx << "x" << cy << "<\"";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINIX_IMAGE_MODE_2:
|
|
|
|
default:
|
|
|
|
command << "x" << cy;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects locked)
|
|
|
|
bool Image::CreateInputFileName()
|
|
|
|
{
|
|
|
|
bool thumb = (item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB);
|
|
|
|
|
|
|
|
if( thumb && !file_work.item_content.file_has_thumb )
|
|
|
|
{
|
|
|
|
log << log1 << "Image: file id: " << file_work.id << ", url: " << file_work.url
|
|
|
|
<< " doesn't have a thumbnail yet (skipping)" << logend;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( system->MakeFilePath(file_work, src_path, thumb) )
|
|
|
|
{
|
|
|
|
PT::WideToUTF8(src_path, input_file_name);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log << log1 << "Image: cannot create a source path" << logend;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects locked)
|
|
|
|
void Image::CreateTmpFileName()
|
|
|
|
{
|
|
|
|
stream_tmp_path.Clear();
|
|
|
|
stream_tmp_path << config->upload_dir << L"/tmp/image_" << std::time(0);
|
|
|
|
PT::WideToUTF8(stream_tmp_path.Str(), tmp_file_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects are not locked)
|
|
|
|
bool Image::CreateCommand()
|
|
|
|
{
|
|
|
|
class Lock lock_object(synchro);
|
|
|
|
|
|
|
|
// iq.SetAll(true, false);
|
|
|
|
// iq.WhereId(item_work.file_id);
|
|
|
|
|
|
|
|
morm::Finder<Item> finder(model_connector);
|
|
|
|
|
|
|
|
{
|
|
|
|
// IMPROVEME we need a seperate model_connector for this thread
|
|
|
|
Lock();
|
|
|
|
file_work = finder.select().where().eq(L"id", item_work.file_id).get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// the file could have been changed especially when there is a long queue of files
|
|
|
|
if( !file_work.found() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if( !CreateInputFileName() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
command.Clear();
|
|
|
|
Add(config->convert_cmd, command);
|
|
|
|
|
|
|
|
command << " ";
|
|
|
|
EscapePath(input_file_name, command, false);
|
|
|
|
command << " -quiet -quality " << item_work.quality;
|
|
|
|
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_RESIZE )
|
|
|
|
{
|
|
|
|
command << " -resize ";
|
|
|
|
SelectAspect(item_work.cx, item_work.cy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CREATE_THUMB )
|
|
|
|
{
|
|
|
|
command << " -strip -thumbnail ";
|
|
|
|
SelectAspect(item_work.thumb_cx, item_work.thumb_cy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CROP )
|
|
|
|
{
|
|
|
|
command << " -crop " << item_work.cx << "x" << item_work.cy
|
|
|
|
<< "+" << item_work.xoffset << "+" << item_work.yoffset << " +repage ";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB )
|
|
|
|
{
|
|
|
|
command << " -strip -crop " << item_work.cx << "x" << item_work.cy
|
|
|
|
<< "+" << item_work.xoffset << "+" << item_work.yoffset
|
|
|
|
<< " +repage ";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CREATE_CROP_NEW_THUMB )
|
|
|
|
{
|
|
|
|
command << " -strip -crop " << item_work.cx << "x" << item_work.cy
|
|
|
|
<< "+" << item_work.xoffset << "+" << item_work.yoffset
|
|
|
|
<< " +repage -thumbnail ";
|
|
|
|
SelectAspect(item_work.thumb_cx, item_work.thumb_cy);
|
|
|
|
}
|
|
|
|
|
|
|
|
CreateTmpFileName();
|
|
|
|
|
|
|
|
command << " ";
|
|
|
|
EscapePath(tmp_file_name, command, false);
|
|
|
|
|
|
|
|
log << log4 << "Image: running: " << command.Str() << logend;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects are locked)
|
|
|
|
void Image::ImageSavedCorrectly()
|
|
|
|
{
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CREATE_THUMB )
|
|
|
|
{
|
|
|
|
if( !file_work.item_content.file_has_thumb )
|
|
|
|
{
|
|
|
|
file_work.item_content.file_has_thumb = true;
|
|
|
|
|
|
|
|
{
|
|
|
|
// IMPROVEME we need a separate model_connector for this thread
|
|
|
|
Lock();
|
|
|
|
file_work.propagate_connector();
|
|
|
|
file_work.item_content.update(false);
|
|
|
|
//db->EditHasThumbById(true, file_work.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log << log3 << "Image: generated a thumbnail: " << dst_path << logend;
|
|
|
|
plugin->Call((Session*)0, WINIX_CREATED_THUMB, &file_work);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_RESIZE )
|
|
|
|
{
|
|
|
|
log << log3 << "Image: image resized: " << dst_path << logend;
|
|
|
|
plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CROP )
|
|
|
|
{
|
|
|
|
log << log3 << "Image: image cropped: " << dst_path << logend;
|
|
|
|
// !! IMPROVE ME add a correct message
|
|
|
|
//plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB )
|
|
|
|
{
|
|
|
|
log << log3 << "Image: image thumbnail cropped: " << dst_path << logend;
|
|
|
|
// !! IMPROVE ME add a correct message
|
|
|
|
//plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if( item_work.type == WINIX_IMAGE_TYPE_CREATE_CROP_NEW_THUMB )
|
|
|
|
{
|
|
|
|
log << log3 << "Image: a new thumbnail from an original image was cropped: " << dst_path << logend;
|
|
|
|
// !! IMPROVE ME add a correct message
|
|
|
|
//plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects are not locked)
|
|
|
|
void Image::SaveImage()
|
|
|
|
{
|
|
|
|
class Lock lock_object(synchro);
|
|
|
|
|
|
|
|
// the file could have been changed especially when creating the image lasted too long
|
|
|
|
//iq.SetAll(true, false);
|
|
|
|
//iq.WhereId(item_work.file_id);
|
|
|
|
|
|
|
|
morm::Finder<Item> finder(model_connector);
|
|
|
|
|
|
|
|
{
|
|
|
|
// IMPROVEME we need a seperate model_connector for this thread
|
|
|
|
Lock();
|
|
|
|
file_work = finder.select().where().eq(L"id", item_work.file_id).get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// the file could have been changed especially when there is a long queue of files
|
|
|
|
if( !file_work.found() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
//if( db->GetItem(file_work, iq) == WINIX_ERR_OK )
|
|
|
|
//{
|
|
|
|
bool thumb = (item_work.type == WINIX_IMAGE_TYPE_CREATE_THUMB ||
|
|
|
|
item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB ||
|
|
|
|
item_work.type == WINIX_IMAGE_TYPE_CREATE_CROP_NEW_THUMB );
|
|
|
|
|
|
|
|
if( system->MakeFilePath(file_work, dst_path, thumb, true, config->upload_dirs_chmod, config->upload_group_int) )
|
|
|
|
{
|
|
|
|
if( RenameFile(stream_tmp_path.Str(), dst_path) )
|
|
|
|
{
|
|
|
|
// it doesn't matter for us if there is an error when chmod/chown on a file
|
|
|
|
// the admin (root) will correct it
|
|
|
|
SetPriv(dst_path, config->upload_files_chmod, config->upload_group_int);
|
|
|
|
ImageSavedCorrectly();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log << log1 << "Image: cannot move a temporary file: " << stream_tmp_path.Str()
|
|
|
|
<< ", to: " << dst_path << logend;
|
|
|
|
|
|
|
|
Winix::RemoveFile(stream_tmp_path.Str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log << log1 << "Image: cannot create a destination path" << logend;
|
|
|
|
}
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects are not locked)
|
|
|
|
void Image::CreateImage()
|
|
|
|
{
|
|
|
|
if( CreateCommand() )
|
|
|
|
{
|
|
|
|
int res = std::system(command.CStr());
|
|
|
|
|
|
|
|
if( res == 0 )
|
|
|
|
{
|
|
|
|
SaveImage();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
class Lock lock_object(synchro);
|
|
|
|
log << log3 << "Image: some problems with creating an image"
|
|
|
|
<< ", 'convert' process returned: " << res << logend;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log << logsave;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// second thread (objects are not locked)
|
|
|
|
// !! there is a problem with GIF files
|
|
|
|
// Bus error (core dumped)
|
|
|
|
/*
|
|
|
|
#include "wand/MagickWand.h"
|
|
|
|
|
|
|
|
// compiler options:
|
|
|
|
// include: -I/usr/local/include/ImageMagick
|
|
|
|
// link with: `MagickWand-config --ldflags --libs`
|
|
|
|
|
|
|
|
void Image::CreateThumbnail()
|
|
|
|
{
|
|
|
|
PT::WideToUTF8(item_work.source, sourcea);
|
|
|
|
PT::WideToUTF8(item_work.dst, dsta);
|
|
|
|
|
|
|
|
MagickWandGenesis();
|
|
|
|
|
|
|
|
MagickWand * wand = NewMagickWand();
|
|
|
|
|
|
|
|
if( MagickReadImage(wand, sourcea.c_str()) )
|
|
|
|
{
|
|
|
|
MagickThumbnailImage(wand, item_work.cx, item_work.cy);
|
|
|
|
|
|
|
|
if( MagickWriteImage(wand, dsta.c_str()) )
|
|
|
|
{
|
|
|
|
Lock();
|
|
|
|
log << log3 << "Image: created a thumbnail: " << dsta << logend;
|
|
|
|
Unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DestroyMagickWand(wand);
|
|
|
|
|
|
|
|
MagickWandTerminus();
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Winix
|
|
|
|
|