Commit 10204672 authored by Jouni Pentikäinen's avatar Jouni Pentikäinen

Implement KisAnimationImporter for image sequence importing

parent bb804d82
......@@ -321,6 +321,8 @@ public:
void fetchFrame(int frameId, KisPaintDeviceSP targetDevice);
void uploadFrame(int srcFrameId, int dstFrameId, KisPaintDeviceSP srcDevice);
void uploadFrame(int dstFrameId, KisPaintDeviceSP srcDevice);
void uploadFrameData(DataSP srcData, DataSP dstData);
QRegion syncLodData(int newLod);
......@@ -330,21 +332,28 @@ private:
QRegion syncWholeDevice(Data *srcData);
inline DataSP currentFrameData() const {
DataSP data;
if (contentChannel->keyframeCount() > 1) {
int frameId = contentChannel->frameIdAt(defaultBounds->currentTime());
KIS_ASSERT_RECOVER(m_frames.contains(frameId)) { return m_frames.begin().value(); }
data = m_frames[frameId];
} else {
data = m_frames.begin().value();
}
// sanity check!
KIS_ASSERT_RECOVER_NOOP(!m_data);
return data;
}
inline Data* currentNonLodData() const {
Data *data = m_data.data();
if (contentChannel) {
if (contentChannel->keyframeCount() > 1) {
int frameId = contentChannel->frameIdAt(defaultBounds->currentTime());
KIS_ASSERT_RECOVER(m_frames.contains(frameId)) { return data; }
data = m_frames[frameId].data();
} else {
data = m_frames.begin().value().data();
}
// sanity check!
KIS_ASSERT_RECOVER_NOOP(!m_data);
data = currentFrameData().data();
} else if (isProjectionDevice && defaultBounds->externalFrameActive()) {
if (!m_externalFrameData) {
QMutexLocker l(&m_dataSwitchLock);
......@@ -646,6 +655,20 @@ void KisPaintDevice::Private::uploadFrame(int srcFrameId, int dstFrameId, KisPai
DataSP srcData = srcDevice->m_d->m_frames[srcFrameId];
KIS_ASSERT_RECOVER_RETURN(srcData);
uploadFrameData(srcData, dstData);
}
void KisPaintDevice::Private::uploadFrame(int dstFrameId, KisPaintDeviceSP srcDevice) {
DataSP dstData = m_frames[dstFrameId];
KIS_ASSERT_RECOVER_RETURN(dstData);
DataSP srcData = srcDevice->m_d->m_data;
KIS_ASSERT_RECOVER_RETURN(srcData);
uploadFrameData(srcData, dstData);
}
void KisPaintDevice::Private::uploadFrameData(DataSP srcData, DataSP dstData) {
if (srcData->colorSpace() != dstData->colorSpace() &&
!(*srcData->colorSpace() == *dstData->colorSpace())) {
......@@ -1721,6 +1744,11 @@ void KisPaintDeviceFramesInterface::uploadFrame(int srcFrameId, int dstFrameId,
q->m_d->uploadFrame(srcFrameId, dstFrameId, srcDevice);
}
void KisPaintDeviceFramesInterface::uploadFrame(int dstFrameId, KisPaintDeviceSP srcDevice)
{
q->m_d->uploadFrame(dstFrameId, srcDevice);
}
QRect KisPaintDeviceFramesInterface::frameBounds(int frameId)
{
return q->m_d->frameBounds(frameId);
......
......@@ -66,6 +66,13 @@ public:
*/
void uploadFrame(int srcFrameId, int dstFrameId, KisPaintDeviceSP srcDevice);
/**
* Copy the given paint device contents into the specified frame
* @param dstFrameId ID of the frame to be overwritten (must exist)
* @param sourceDevice paint device to copy from
*/
void uploadFrame(int dstFrameId, KisPaintDeviceSP srcDevice);
/**
* @return extent() of \p frameId
*/
......
......@@ -70,6 +70,15 @@ void KisRasterKeyframeChannel::fetchFrame(KisKeyframeSP keyframe, KisPaintDevice
m_d->paintDevice->framesInterface()->fetchFrame(keyframe->value(), targetDevice);
}
void KisRasterKeyframeChannel::importFrame(int time, KisPaintDeviceSP sourceDevice, KUndo2Command *parentCommand)
{
KisKeyframeSP keyframe = addKeyframe(time, parentCommand);
const int frameId = keyframe->value();
m_d->paintDevice->framesInterface()->uploadFrame(frameId, sourceDevice);
}
QRect KisRasterKeyframeChannel::frameExtents(KisKeyframeSP keyframe)
{
return m_d->paintDevice->framesInterface()->frameBounds(keyframe->value());
......
......@@ -39,15 +39,19 @@ public:
int frameIdAt(int time) const;
/**
* Copy the active frame at given time and offset to target device.
* Note: offset is the number of keyframes back or forth counted
* from the active keyframe at the given time.
* Copy the active frame at given time to target device.
* @param keyframe keyframe to copy from
* @param targetDevice device to copy the frame to
* @param time time to determine base keyframe
* @param offset number of keyframes to offset from base keyframe
*/
void fetchFrame(KisKeyframeSP keyframe, KisPaintDeviceSP targetDevice);
/**
* Copy the content of the sourceDevice into a new keyframe at given time
* @param time position of new keyframe
* @param sourceDevice source for content
*/
void importFrame(int time, KisPaintDeviceSP sourceDevice, KUndo2Command *parentCommand);
QRect frameExtents(KisKeyframeSP keyframe);
QString frameFilename(int frameId) const;
......
......@@ -359,6 +359,7 @@ if (HAVE_OPENGL)
kis_animation_cache_populator.cpp
canvas/kis_animation_player.cpp
kis_animation_exporter.cpp
kis_animation_importer.cpp
)
endif()
......
/*
* Copyright (c) 2015 Jouni Pentikäinen <joupent@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_animation_importer.h"
#include "KoColorSpace.h"
#include "KisPart.h"
#include "KisDocument.h"
#include "kis_image.h"
#include "kis_undo_adapter.h"
#include "kis_paint_layer.h"
#include "kis_group_layer.h"
#include "kis_raster_keyframe_channel.h"
#include "commands/kis_image_layer_add_command.h"
struct KisAnimationImporter::Private
{
KisImageSP image;
};
KisAnimationImporter::KisAnimationImporter(KisImageSP image)
: m_d(new Private())
{
m_d->image = image;
}
KisAnimationImporter::~KisAnimationImporter()
{}
bool KisAnimationImporter::import(QStringList files, int firstFrame, int step)
{
Q_ASSERT(step > 0);
m_d->image->lock();
KisUndoAdapter *undo = m_d->image->undoAdapter();
undo->beginMacro(kundo2_i18n("Import animation"));
KUndo2Command *undoCommand = new KUndo2Command(kundo2_i18n("Import frames"));
QScopedPointer<KisDocument> importDoc(KisPart::instance()->createDocument());
bool errors = false;
int frame = firstFrame;
KisRasterKeyframeChannel *contentChannel = 0;
Q_FOREACH(QString file, files) {
bool successfullyLoaded = importDoc->openUrl(QUrl::fromLocalFile(file), KisDocument::OPEN_URL_FLAG_DO_NOT_ADD_TO_RECENT_FILES);
if (!successfullyLoaded) {
errors = true;
break;
}
if (frame == firstFrame) {
const KoColorSpace *cs = importDoc->image()->colorSpace();
KisPaintLayerSP paintLayer = new KisPaintLayer(m_d->image, m_d->image->nextLayerName(), OPACITY_OPAQUE_U8, cs);
undo->addCommand(new KisImageLayerAddCommand(m_d->image, paintLayer, m_d->image->rootLayer(), m_d->image->rootLayer()->childCount()));
paintLayer->enableAnimation();
contentChannel = qobject_cast<KisRasterKeyframeChannel*>(paintLayer->getKeyframeChannel(KisKeyframeChannel::Content.id()));
}
contentChannel->addKeyframe(frame, undoCommand);
contentChannel->importFrame(frame, importDoc->image()->projection(), undoCommand);
frame += step;
}
undo->endMacro();
m_d->image->unlock();
return !errors;
}
/*
* Copyright (c) 2015 Jouni Pentikäinen <joupent@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_ANIMATION_IMPORTER_H
#define KIS_ANIMATION_IMPORTER_H
#include "kis_types.h"
#include "kritaui_export.h"
class KisDocument;
class KRITAUI_EXPORT KisAnimationImporter : public QObject
{
Q_OBJECT
public:
KisAnimationImporter(KisImageSP image);
~KisAnimationImporter();
bool import(QStringList files, int firstFrame, int step);
private:
class Private;
QScopedPointer<Private> m_d;
};
#endif
......@@ -217,6 +217,12 @@ target_link_libraries(KisAnimationExporterTest kritaui kritaimage ${QT_QTTEST_LI
########### next target ###############
set(kis_animation_importer_test_SRCS kis_animation_importer_test.cpp )
kde4_add_unit_test(KisAnimationImporterTest TESTNAME kritaui-animation_importer_test ${kis_animation_importer_test_SRCS})
target_link_libraries(KisAnimationImporterTest kritaui kritaimage ${QT_QTTEST_LIBRARY})
########### next target ###############
set(kis_animation_frame_cache_test_SRCS kis_animation_frame_cache_test.cpp )
kde4_add_unit_test(KisAnimationFrameCacheTest TESTNAME kritaui-animation_frame_cache_test ${kis_animation_frame_cache_test_SRCS})
target_link_libraries(KisAnimationFrameCacheTest kritaui kritaimage ${QT_QTTEST_LIBRARY})
......
/*
* Copyright (c) 2015 Jouni Pentikäinen <joupent@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_animation_importer_test.h"
#include "KisPart.h"
#include "kis_animation_importer.h"
#include "KisDocument.h"
#include "testutil.h"
#include "kis_keyframe_channel.h"
#include "kis_image_animation_interface.h"
#include "kis_group_layer.h"
void KisAnimationImporterTest::testImport()
{
KisDocument *document = KisPart::instance()->createDocument();
TestUtil::MaskParent mp(QRect(0,0,512,512));
document->setCurrentImage(mp.image);
KisAnimationImporter importer(document->image());
QStringList files;
files.append(QString(FILES_DATA_DIR) + QDir::separator() + "file_layer_source.png");
files.append(QString(FILES_DATA_DIR) + QDir::separator() + "lena.png");
files.append(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png");
importer.import(files, 7, 3);
KisGroupLayerSP root = mp.image->rootLayer();
KisNodeSP importedLayer = root->lastChild();
KisKeyframeChannel* contentChannel = importedLayer->getKeyframeChannel(KisKeyframeChannel::Content.id());
QVERIFY(contentChannel != 0);
QCOMPARE(contentChannel->keyframeCount(), 4); // Three imported ones + blank at time 0
QVERIFY(!contentChannel->keyframeAt(7).isNull());
QVERIFY(!contentChannel->keyframeAt(10).isNull());
QVERIFY(!contentChannel->keyframeAt(13).isNull());
mp.image->animationInterface()->switchCurrentTimeAsync(7);
mp.image->waitForDone();
QImage imported1 = importedLayer->projection()->convertToQImage(importedLayer->colorSpace()->profile());
mp.image->animationInterface()->switchCurrentTimeAsync(10);
mp.image->waitForDone();
QImage imported2 = importedLayer->projection()->convertToQImage(importedLayer->colorSpace()->profile());
mp.image->animationInterface()->switchCurrentTimeAsync(13);
mp.image->waitForDone();
QImage imported3 = importedLayer->projection()->convertToQImage(importedLayer->colorSpace()->profile());
QImage source1(QString(FILES_DATA_DIR) + QDir::separator() + "file_layer_source.png");
QImage source2(QString(FILES_DATA_DIR) + QDir::separator() + "lena.png");
QImage source3(QString(FILES_DATA_DIR) + QDir::separator() + "hakonepa.png");
QPoint pt;
QVERIFY(TestUtil::compareQImages(pt, source1, imported1));
QVERIFY(TestUtil::compareQImages(pt, source2, imported2));
QVERIFY(TestUtil::compareQImages(pt, source3, imported3));
delete document;
}
QTEST_MAIN(KisAnimationImporterTest)
/*
* Copyright (c) 2015 Jouni Pentikäinen <joupent@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_ANIMATION_IMPORTER_TEST_H
#define KIS_ANIMATION_IMPORTER_TEST_H
#include <QTest>
class KisAnimationImporterTest : public QObject {
Q_OBJECT
private Q_SLOTS:
void testImport();
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment