2009-09-10 4 views
9

¿Hay un ejemplo sucinto de cómo cargar una imagen, cambiar su tamaño, almacenarla en una base de datos y luego mostrar la imagen usando Lift?Levantar imagen cargar, redimensionar, almacenar en la base de datos, mostrar

Estoy seguro de que podría unirlo desde la carga de archivos, Java API 2D, Lift Mapper y Response APIs. Pero, ¿hay algún código de ejemplo que pueda seguir para hacerlo de la manera "correcta" o recomendada?

+2

Sin ofender, pero esto suena como un proyecto decente para escribir usted mismo! Tiene de todo: intriga, aventura y SQL. –

+0

Sí, iba a hacerlo! Solo pensé en buscar consejo antes de comenzar. – Joe

Respuesta

6

Hice esto para un campo Mapper vinculado a s3 creando un nuevo MappedField. También tengo un código para cambiar el tamaño, pero no lo he probado ni lo he implementado (así que úselo con precaución).

class MappedS3Image[T<:Mapper[T]](owner: T, val path:String, maxWidth: String, maxHeight:String) extends MappedString[T](owner, 36) { 

    def url:String = MappedS3Image.fullImgPath(path, is) 

    def setFromUpload(fileHolder: Box[FileParamHolder]) = { 
     S3Sender.uploadImageToS3(path, fileHolder).map(this.set(_)) 
    } 

    override def asHtml:Node = <img src={url} style={"max-width:" + maxWidth + ";max-height:"+maxHeight} /> 
    override def _toForm: Box[Elem] = Full(SHtml.fileUpload(fu=>setFromUpload(Full(fu)))) 

} 


import java.awt.Image 
import java.awt.image.BufferedImage 
import javax.imageio.ImageIO 
import java.awt.Graphics2D 
import java.awt.AlphaComposite 

object ImageResizer { 

    def resize(is:java.io.InputStream, maxWidth:Int, maxHeight:Int):BufferedImage = { 
     val originalImage:BufferedImage = ImageIO.read(is) 

     val height = originalImage.getHeight 
     val width = originalImage.getWidth 

     if (width <= maxWidth && height <= maxHeight) 
      originalImage 
     else { 
      var scaledWidth:Int = width 
      var scaledHeight:Int = height 
      val ratio:Double = width/height 
      if (scaledWidth > maxWidth){ 
       scaledWidth = maxWidth 
       scaledHeight = (scaledWidth.doubleValue/ratio).intValue 
      } 
      if (scaledHeight > maxHeight){ 
       scaledHeight = maxHeight 
       scaledWidth = (scaledHeight.doubleValue*ratio).intValue 
      } 
      val scaledBI = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB) 
      val g = scaledBI.createGraphics 
      g.setComposite(AlphaComposite.Src) 
      g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
      g.dispose 
      scaledBI 
     } 
    } 
} 
+0

Matemática defectuosa. Esto arruina la relación ancho/alto. Respondí con una versión fija (tres años después). Aún así, respondió las preguntas sobre las bibliotecas correctas que debía usar para mí y fue muy útil. –

+0

He agregado una respuesta corregida a continuación. –

3

La otra respuesta describe muy bien cómo cambiar el tamaño de la imagen y almacenar una referencia al archivo en el sistema de archivos.

Si desea utilizar el levantador de mapas para almacenar el contenido real del archivo, debe crear su objeto de modelo personalizado y definir un campo binario en él. Intentar algo como esto:

package code { 
package model { 


import _root_.net.liftweb.mapper._ 
import _root_.net.liftweb.util._ 
import _root_.net.liftweb.common._ 


// singleton object which manipulates storing of Document instances 
object Document extends Document with KeyedMetaMapper[Long, Document] { 
} 



class Document extends KeyedMapper[Long, Document] { 
    def getSingleton = Document 
    def primaryKeyField = id 

    object id extends MappedLongIndex(this) 

    object name extends MappedString(this, 20) { 
    override def displayName = "Name" 
    override def writePermission_? = true 
    } 

    object content extends MappedBinary(this) { 
    override def displayName = "Content" 
    override def writePermission_? = true 
    } 
} 



} 
} 

Luego, en la rutina de carga, anadir este Document al final:

Schemifier.schemify(true, Schemifier.infoF _, User, Document) 

Voila. Usando Document save (new Document) lo almacena en la base de datos. Los campos new Document se pueden configurar mediante el método set. Intente jugar con delete_!, find, findAll métodos del singleton Document para eliminarlo o encontrarlo en la base de datos. Debería ser sencillo a partir de ahora.

Finalmente, para mostrar la imagen, puede anular las reglas de despacho de Lift (en la clase bootstrap, Boot.scala). Trate de jugar un poco con este ejemplo que anula las reglas para las peticiones de PDF:

def getFile(filename: String): Option[Document] = { 
    val alldocs = Document.findAll() 
    alldocs.find(_.name.get == filename) 
} 

LiftRules.statelessDispatchTable.append { 
    case Req("file" :: name :: Nil, "pdf", GetRequest) => 
    () => 
    println("Got request for: " + name + ".pdf") 
    for { 
     stream <- tryo(
     getFile(name + ".pdf") map { 
      doc => new java.io.ByteArrayInputStream(doc.content.get) 
     } getOrElse null 
    ) 
     if null ne stream 
    } yield StreamingResponse(stream, 
          () => stream.close, 
           stream.available, 
           List("Content-Type" -> "application/pdf"), 
           Nil, 
           200) 
} 
2

Sobre la base de la respuesta aceptada por Jon Hoffman, que fija los errores. Su versión arruina la relación de aspecto (siempre se vuelve 1: 1), porque las matemáticas estaban apagadas en algunos puntos. Esta versión cambia el tamaño de las imágenes grandes hasta que quepan y respeta la relación de aspecto.

def resize(is:java.io.InputStream, maxWidth:Int, maxHeight:Int):BufferedImage = { 
    require (maxWidth > 0) 
    require (maxHeight > 0) 
    val originalImage:BufferedImage = ImageIO.read(is) 

    var height = originalImage.getHeight 
    var width = originalImage.getWidth 

    // Shortcut to save a pointless reprocessing in case the image is small enough already 
    if (width <= maxWidth && height <= maxHeight) 
     originalImage 
    else {   
     // If the picture was too big, it will either fit by width or height. 
     // This essentially resizes the dimensions twice, until it fits 
     if (width > maxWidth){ 
      height = (height.doubleValue() * (maxWidth.doubleValue()/width.doubleValue())).intValue 
      width = maxWidth 
     } 
     if (height > maxHeight){ 
      width = (width.doubleValue() * (maxHeight.doubleValue()/height.doubleValue())).intValue 
      height = maxHeight 
     } 
     val scaledBI = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) 
     val g = scaledBI.createGraphics 
     g.setComposite(AlphaComposite.Src) 
     g.drawImage(originalImage, 0, 0, width, height, null); 
     g.dispose 
     scaledBI 
    } 
} 
Cuestiones relacionadas