/* Copyright (C) 2005-2011 Fabio Riccardi */
package com.lightcrafts.ui.export;
import com.lightcrafts.image.ImageInfo;
import com.lightcrafts.image.export.*;
import com.lightcrafts.image.metadata.ImageMetadata;
import com.lightcrafts.image.metadata.providers.ResolutionProvider;
import com.lightcrafts.image.types.ImageType;
import com.lightcrafts.image.types.RawImageType;
import com.lightcrafts.image.types.TIFFImageType;
import com.lightcrafts.utils.ColorProfileInfo;
import java.awt.*;
import java.awt.color.ICC_Profile;
import java.io.File;
/**
* This is the home of all the special-case logic that goes into defining
* default ImageExportOptions for edited images.
* <p>
* In general, the settings used to initialize an export dialog depend on:
* <ul>
* <li>The original image (color space, image type)</li>
* <li>Edits made by the user (crop bounds)</li>
* <li>User prefences (workflow settings, default directory)</li>
* <li>Export settings previously used for the current image</li>
* <li>The most recent export settings used</li>
* <li>The most recent export settings used to export each image type (in
* case the user switches image types during the dialog)</li>
* </ul>
*/
public class ExportLogic {
/**
* Figure out new export options when there is no export history
* whatsoever.
*/
public static ImageExportOptions getDefaultExportOptions(
ImageMetadata meta,
Dimension size
) {
ImageExportOptions options = TIFFImageType.INSTANCE.newExportOptions();
File file = meta.getFile();
options.setExportFile(file);
colorProfileFrom(meta, (ImageFileExportOptions)options);
resolutionFrom(meta, (ImageFileExportOptions)options);
maybeUpdateSize(options, size);
return options;
}
/**
* Figure out new export options when export has been performed at least
* once but the image being exported has never been saved or exported
* before.
*/
public static ImageExportOptions getDefaultExportOptions(
ImageExportOptions recent,
ImageMetadata meta,
Dimension size
) {
String name = meta.getFile().getName();
return getDefaultExportOptions(recent, meta, size, name);
}
/**
* Figure out new export options when export has been performed at least
* once, the image being exported has never been exported before, but
* a base name for the export is known anyway, for instance from saving.
*/
public static ImageExportOptions getDefaultExportOptions(
ImageExportOptions recent,
ImageMetadata meta,
Dimension size,
String name
) {
ImageExportOptions options = recent;
File recentFile = recent.getExportFile();
File dir = null;
if (recentFile != null) {
dir = recentFile.getParentFile();
}
if (dir == null) {
// This sometimes happens: an ImageExportOptions with a null file.
// I don't know how, maybe very old export options saved in old
// LZN files or in preferences.
dir = new File(System.getProperty("user.home"));
}
File currentFile = new File(dir, name);
options.setExportFile(currentFile);
if (options instanceof ImageFileExportOptions) {
colorProfileFrom(meta, (ImageFileExportOptions) options);
resolutionFrom(meta, (ImageFileExportOptions)options);
}
maybeUpdateSize(options, size);
return options;
}
/**
* Figure out new ImageExportOptions when the image being exported
* has been exported before.
*/
public static ImageExportOptions getDefaultExportOptions(
ImageExportOptions current,
Dimension size
) {
maybeUpdateSize(current, size);
return current;
}
/**
* If the given export options hold an original size unequal to the given
* size, then slew its original size values and also its resize values
* to the given size.
*/
public static void maybeUpdateSize(
ImageExportOptions options, Dimension size
) {
if ( options.originalWidth.getValue() != size.width ||
options.originalHeight.getValue() != size.height ) {
options.originalWidth.setValue( size.width );
options.originalHeight.setValue( size.height );
if ( options instanceof ImageFileExportOptions ) {
final ImageFileExportOptions fileOptions =
(ImageFileExportOptions)options;
fileOptions.resizeWidth.setValue( size.width );
fileOptions.resizeHeight.setValue( size.height );
}
}
}
/**
* Figure out new ImageExportOptions when a user asks to change the export
* image type and so old options must be merged into new options.
*/
public static void mergeExportOptions(
ImageExportOptions oldOptions,
ImageExportOptions newOptions
) {
// Copy over the file name, updating its suffix:
File file = oldOptions.getExportFile();
ImageType newType = newOptions.getImageType();
if ((file != null) && (! file.isDirectory())) {
file = ExportNameUtility.ensureCompatibleExtension(
file, newType
);
newOptions.setExportFile(file);
}
// Clone values from old to new:
if ( oldOptions instanceof ImageFileExportOptions &&
newOptions instanceof ImageFileExportOptions ) {
final ImageFileExportOptions oldFileOptions =
(ImageFileExportOptions)oldOptions;
final ImageFileExportOptions newFileOptions =
(ImageFileExportOptions)newOptions;
copyOption( oldFileOptions.originalWidth, newFileOptions.originalWidth );
copyOption( oldFileOptions.originalHeight, newFileOptions.originalHeight );
copyOption( oldFileOptions.resizeWidth, newFileOptions.resizeWidth );
copyOption( oldFileOptions.resizeHeight, newFileOptions.resizeHeight );
copyOption( oldFileOptions.colorProfile, newFileOptions.colorProfile );
copyOption( oldFileOptions.renderingIntent, newFileOptions.renderingIntent );
copyOption( oldFileOptions.blackPointCompensation, newFileOptions.blackPointCompensation );
}
// Switches from sidecar TIFF to multilayer TIFF are possible:
ImageType oldType = oldOptions.getImageType();
if ((oldType == TIFFImageType.INSTANCE) &&
(newType == TIFFImageType.INSTANCE)) {
TIFFImageType.ExportOptions oldTiff =
(TIFFImageType.ExportOptions) oldOptions;
TIFFImageType.ExportOptions newTiff =
(TIFFImageType.ExportOptions) newOptions;
copyOption(oldTiff.bitsPerChannel, newTiff.bitsPerChannel);
copyOption(oldTiff.lzwCompression, newTiff.lzwCompression);
}
}
private static void colorProfileFrom(
ImageMetadata meta, ImageFileExportOptions options
) {
if (! (meta.getImageType() instanceof RawImageType)) {
try {
ImageInfo info = ImageInfo.getInstanceFor(meta.getFile());
ICC_Profile profile = info.getImageType().getICCProfile(info);
String profileName = ColorProfileInfo.getNameOf(profile);
options.colorProfile.setValue(profileName);
}
catch (Throwable t) {
// BadImageFileException
// ColorProfileException
// IOException
// UnknownImageTypeException
System.err.println(
"Error cloning color profile: " + t.getClass().getName()
);
}
}
}
private static void resolutionFrom( ImageMetadata metadata,
ImageFileExportOptions options ) {
final int resolution = (int)metadata.getResolution();
final int resolutionUnit = metadata.getResolutionUnit();
if ( resolution > 0 &&
resolutionUnit != ResolutionProvider.RESOLUTION_UNIT_NONE ) {
options.resolution.setValue( resolution );
options.resolutionUnit.setValue( resolutionUnit );
}
}
/**
* Clone ImageExportOption values.
*/
private static void copyOption(
BooleanExportOption source, BooleanExportOption target
) {
target.setValue(source.getValue());
}
/**
* Clone ImageExportOption values.
*/
private static void copyOption(
IntegerExportOption source, IntegerExportOption target
) {
target.setValue(source.getValue());
}
/**
* Clone ImageExportOption values.
*/
private static void copyOption(
ColorProfileOption source, ColorProfileOption target
) {
target.setValue(source.getValue());
}
/**
* Clone ImageExportOption values.
*/
private static void copyOption(
LZWCompressionOption source, LZWCompressionOption target
) {
target.setValue(source.getValue());
}
}