use high qulity png conversion for the slide, not just the thumbnail

This commit is contained in:
Anton Georgiev 2014-08-07 20:12:55 +00:00
parent fea70bda5f
commit 404ff72914
7 changed files with 153 additions and 118 deletions

View File

@ -240,9 +240,10 @@ class BigBlueButtonInGW(bbbGW: BigBlueButtonGateway) extends IBigBlueButtonInGW
val thumbnail = presBaseUrl + "/thumbnail/" + i
val swfUri = presBaseUrl + "/slide/" + i
val txtUri = presBaseUrl + "/textfiles/slide-" + i + ".txt"
val pngUri = presBaseUrl + "/png/" + i
val p = new Page(id=id, num=num, thumbUri=thumbnail, swfUri=swfUri,
txtUri=txtUri, pngUri=thumbnail,
txtUri=txtUri, pngUri=pngUri,
current=current)
pages += (p.id -> p)
}

View File

@ -24,6 +24,14 @@ class UrlMappings {
"/presentation/$conference/$room/$presentation_name/thumbnail/$id"(controller:"presentation") {
action = [GET:'showThumbnail']
}
"/presentation/$conference/$room/$presentation_name/pngs"(controller:"presentation") {
action = [GET:'numberOfPngs']
}
"/presentation/$conference/$room/$presentation_name/png/$id"(controller:"presentation") {
action = [GET:'showPngImage']
}
"/presentation/$conference/$room/$presentation_name/textfiles"(controller:"presentation") {
action = [GET:'numberOfTextfiles']

View File

@ -297,7 +297,28 @@ class PresentationController {
}
}
}
def numberOfPngs = {
def filename = params.presentation_name
def f = confInfo()
def numPngs = presentationService.numberOfPngs(f.conference, f.room, filename)
withFormat {
xml {
render(contentType:"text/xml") {
conference(id:f.conference, room:f.room) {
presentation(name:filename) {
pngs(count:numPngs) {
for (def i=0;i<numPngs;i++) {
png(name:"pngs/${i}")
}
}
}
}
}
}
}
}
def numberOfTextfiles = {
def filename = params.presentation_name
def f = confInfo()

View File

@ -1,45 +1,45 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2014 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.web.services
import java.util.concurrent.*;
import java.lang.InterruptedException
import org.bigbluebutton.presentation.DocumentConversionService
import org.bigbluebutton.presentation.UploadedPresentation
import java.lang.InterruptedException
import org.bigbluebutton.presentation.DocumentConversionService
import org.bigbluebutton.presentation.UploadedPresentation
class PresentationService {
static transactional = false
DocumentConversionService documentConversionService
def presentationDir
def testConferenceMock
def testRoomMock
def testPresentationName
def testUploadedPresentation
def defaultUploadedPresentation
def presentationBaseUrl
static transactional = false
DocumentConversionService documentConversionService
def presentationDir
def testConferenceMock
def testRoomMock
def testPresentationName
def testUploadedPresentation
def defaultUploadedPresentation
def presentationBaseUrl
def deletePresentation = {conf, room, filename ->
def directory = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + filename)
deleteDirectory(directory)
deleteDirectory(directory)
}
def deleteDirectory = {directory ->
log.debug "delete = ${directory}"
/**
@ -47,7 +47,7 @@ class PresentationService {
* We need to delete files inside a directory before a
* directory can be deleted.
**/
File[] files = directory.listFiles();
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteDirectory(files[i])
@ -56,9 +56,9 @@ class PresentationService {
}
}
// Now that the directory is empty. Delete it.
directory.delete()
directory.delete()
}
def listPresentations = {conf, room ->
def presentationsList = []
def directory = roomDirectory(conf, room)
@ -69,90 +69,95 @@ class PresentationService {
if( file.isDirectory() )
presentationsList.add( file.name )
}
}
}
return presentationsList
}
def getPresentationDir = {
return presentationDir
def getPresentationDir = {
return presentationDir
}
def processUploadedPresentation = {uploadedPres ->
def processUploadedPresentation = {uploadedPres ->
// Run conversion on another thread.
new Timer().runAfter(1000)
new Timer().runAfter(1000)
{
documentConversionService.processDocument(uploadedPres)
documentConversionService.processDocument(uploadedPres)
}
}
def showSlide(String conf, String room, String presentationName, String id) {
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar + "slide-${id}.swf")
}
def showPngImage(String conf, String room, String presentationName, String id) {
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar + "pngs" + File.separatorChar + id)
}
def showPngImage(String conf, String room, String presentationName, String id) {
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar + "pngs" + File.separatorChar + "slide${id}.png")
}
def showPresentation = {conf, room, filename ->
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + filename + File.separatorChar + "slides.swf")
}
def showThumbnail = {conf, room, presentationName, thumb ->
def showThumbnail = {conf, room, presentationName, thumb ->
println "Show thumbnails request for $presentationName $thumb"
def thumbFile = roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar +
"thumbnails" + File.separatorChar + "thumb-${thumb}.png"
log.debug "showing $thumbFile"
new File(thumbFile)
}
def showTextfile = {conf, room, presentationName, textfile ->
println "Show textfiles request for $presentationName $textfile"
def txt = roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar +
"textfiles" + File.separatorChar + "slide-${textfile}.txt"
log.debug "showing $txt"
new File(txt)
}
def showTextfile = {conf, room, presentationName, textfile ->
println "Show textfiles request for $presentationName $textfile"
def txt = roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar +
"textfiles" + File.separatorChar + "slide-${textfile}.txt"
log.debug "showing $txt"
new File(txt)
}
def numberOfThumbnails = {conf, room, name ->
def thumbDir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "thumbnails")
thumbDir.listFiles().length
}
def numberOfTextfiles = {conf, room, name ->
log.debug roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "textfiles"
def textfilesDir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "textfiles")
textfilesDir.listFiles().length
}
def roomDirectory = {conf, room ->
return new File(presentationDir + File.separatorChar + conf + File.separatorChar + room)
}
def testConversionProcess() {
File presDir = new File(roomDirectory(testConferenceMock, testRoomMock).absolutePath + File.separatorChar + testPresentationName)
if (presDir.exists()) {
File pres = new File(presDir.getAbsolutePath() + File.separatorChar + testUploadedPresentation)
if (pres.exists()) {
UploadedPresentation uploadedPres = new UploadedPresentation(testConferenceMock, testRoomMock, testPresentationName);
uploadedPres.setUploadedFile(pres);
// Run conversion on another thread.
new Timer().runAfter(1000)
{
documentConversionService.processDocument(uploadedPres)
}
} else {
log.error "${pres.absolutePath} does NOT exist"
}
} else {
log.error "${presDir.absolutePath} does NOT exist."
}
}
}
def numberOfPngs = {conf, room, name ->
def PngsDir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "pngs")
PngsDir.listFiles().length
}
def numberOfTextfiles = {conf, room, name ->
log.debug roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "textfiles"
def textfilesDir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "textfiles")
textfilesDir.listFiles().length
}
def roomDirectory = {conf, room ->
return new File(presentationDir + File.separatorChar + conf + File.separatorChar + room)
}
def testConversionProcess() {
File presDir = new File(roomDirectory(testConferenceMock, testRoomMock).absolutePath + File.separatorChar + testPresentationName)
if (presDir.exists()) {
File pres = new File(presDir.getAbsolutePath() + File.separatorChar + testUploadedPresentation)
log.warn "\n\n333 " + pres.toString();
if (pres.exists()) {
UploadedPresentation uploadedPres = new UploadedPresentation(testConferenceMock, testRoomMock, testPresentationName);
uploadedPres.setUploadedFile(pres);
// Run conversion on another thread.
new Timer().runAfter(1000)
{
documentConversionService.processDocument(uploadedPres)
}
} else {
log.error "${pres.absolutePath} does NOT exist"
}
} else {
log.error "${presDir.absolutePath} does NOT exist."
}
}
}
/*** Helper classes **/
import java.io.FilenameFilter;
@ -161,4 +166,4 @@ class PngFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
return (name.endsWith(".png"));
}
}
}

View File

@ -64,7 +64,7 @@ public class PdfToSwfSlidesGenerationService {
log.debug("Determined number of pages " + pres.getNumberOfPages());
if (pres.getNumberOfPages() > 0) {
convertPdfToSwf(pres);
// createPngImages(pres);
createPngImages(pres);
createTextFiles(pres);
createThumbnails(pres);
notifier.sendConversionCompletedMessage(pres);

View File

@ -66,7 +66,8 @@ public class PngImageCreatorImp implements PngImageCreator {
for(int i=1; i<=pres.getNumberOfPages(); i++){
File tmp = new File(imagePresentationDir.getAbsolutePath() + File.separatorChar + "tmp" + File.separatorChar + "slide" + i + ".pdf");
File destpng = new File(imagePresentationDir.getAbsolutePath() + File.separatorChar + "slide" + i + ".png");
COMMAND = IMAGEMAGICK_DIR + "/convert -density 300x300 -quality 90 +dither -depth 8 -colors 256 " + File.separatorChar + tmp.getAbsolutePath() + " " + destpng.getAbsolutePath();
COMMAND = IMAGEMAGICK_DIR + "/convert -density 300x300 -quality 90 +dither -depth 8 -colors 256 " + File.separatorChar + tmp.getAbsolutePath() + " " + destpng.getAbsolutePath();
done = new ExternalProcessExecutor().exec(COMMAND, 60000);
if(!done){
break;

View File

@ -1,7 +1,7 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* Copyright (c) 2014 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@ -69,7 +69,6 @@ public class ThumbnailCreatorImp implements ThumbnailCreator {
String source = pres.getUploadedFile().getAbsolutePath();
String dest;
String COMMAND = "";
if(SupportedFileTypes.isImageFile(pres.getFileType())){
dest = thumbsDir.getAbsolutePath() + File.separator + TEMP_THUMB_NAME + ".png";
COMMAND = IMAGEMAGICK_DIR + "/convert -thumbnail 150x150 " + source + " " + dest;
@ -77,22 +76,22 @@ public class ThumbnailCreatorImp implements ThumbnailCreator {
dest = thumbsDir.getAbsolutePath() + File.separator + "thumb-";
COMMAND = IMAGEMAGICK_DIR + "/gs -q -sDEVICE=pngalpha -dBATCH -dNOPAUSE -dNOPROMPT -dDOINTERPOLATE -dPDFFitPage -r16 -sOutputFile=" + dest +"%d.png " + source;
}
boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000);
if (done) {
return true;
} else {
log.warn("Failed to create thumbnails: " + COMMAND);
} else {
log.warn("Failed to create thumbnails: " + COMMAND);
}
return false;
return false;
}
private File determineThumbnailDirectory(File presentationFile) {
return new File(presentationFile.getParent() + File.separatorChar + "thumbnails");
}
private void renameThumbnails(File dir) {
/*
* If more than 1 file, filename like 'temp-thumb-X.png' else filename is 'temp-thumb.png'
@ -137,17 +136,17 @@ public class ThumbnailCreatorImp implements ThumbnailCreator {
}
}
}
private void copyBlankThumbnail(File thumb) {
try {
FileUtils.copyFile(new File(BLANK_THUMBNAIL), thumb);
} catch (IOException e) {
log.error("IOException while copying blank thumbnail.");
}
}
}
private void cleanDirectory(File directory) {
File[] files = directory.listFiles();
private void cleanDirectory(File directory) {
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++) {
files[i].delete();
}