-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
33dfd22
commit f160007
Showing
45 changed files
with
5,446 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
This directory contains the 3rd-party dependencies required to build the plug-in. | ||
|
||
### Adobe Photoshop CS5 SDK | ||
|
||
You will need to download the Adobe Photoshop CS5 SDK from http://www.adobe.com/devnet/photoshop/sdk.html and unzip it into this folder. | ||
|
||
### AOM | ||
|
||
Clone AOM from your preferred tag: | ||
|
||
`git clone -b v3.0.0 --depth 1 https://aomedia.googlesource.com/aom` | ||
|
||
Change into the `aom` directory and create a build directory. | ||
In this example a 64-bit build using Visual Studio 2019 is used. | ||
|
||
`cd aom` | ||
`mkdir build64 && cd build64` | ||
`cmake -G "Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=Release -DENABLE_DOCS=0 -DENABLE_EXAMPLES=0 -DENABLE_TESTDATA=0 -DENABLE_TESTS=0 -DENABLE_TOOLS=0 ..` | ||
`cmake --build .` | ||
|
||
The generated AOM library should be located in `aom/build64/Release`, this library will be used when building `libheif`. | ||
|
||
### libheif | ||
|
||
Clone libheif from your preferred tag: | ||
|
||
`git clone -b v1.11.0 --depth 1 https://github.com/strukturag/libheif` | ||
|
||
Change into the `libheif` directory and create a build directory. | ||
In this example a 64-bit build using Visual Studio 2019 is used. | ||
|
||
`cd libheif` | ||
`mkdir build64 && cd build64` | ||
`cmake -G "Visual Studio 16 2019" -DBUILD_SHARED_LIBS=OFF -DWITH_EXAMPLES=OFF -DAOM_INCLUDE_DIR=..\..\aom -DAOM_LIBRARY=..\..\aom\build64\Release\aom.lib ..` | ||
`cmake --build .` | ||
|
||
You will need to add `LIBHEIF_STATIC_BUILD` to the preprocessor settings page in the libheif project properties, | ||
and remove the `HAS_VISIBILITY` definition if present. | ||
|
||
The generated libheif library should be located in `libheif/build64/Release`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
root = true | ||
|
||
[*] | ||
end_of_line = crlf | ||
|
||
[*.{cpp,h}] | ||
indent_size = 4 | ||
indent_style = space | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
/* | ||
* This file is part of avif-format, an AV1 Image (AVIF) file format | ||
* plug-in for Adobe Photoshop(R). | ||
* | ||
* Copyright (c) 2021 Nicholas Hayes | ||
* | ||
* avif-format 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 of | ||
* the License, or (at your option) any later version. | ||
* | ||
* avif-format 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 avif-format. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include "AvifFormat.h" | ||
#include "FileIO.h" | ||
#include <stdexcept> | ||
|
||
namespace | ||
{ | ||
OSErr CreateGlobals(FormatRecordPtr formatRecord, intptr_t* data) | ||
{ | ||
Handle handle; | ||
|
||
OSErr e = NewPIHandle(formatRecord, sizeof(Globals), &handle); | ||
|
||
if (e == noErr) | ||
{ | ||
*data = reinterpret_cast<intptr_t>(handle); | ||
} | ||
|
||
return e; | ||
} | ||
|
||
OSErr DoFilterFile(FormatRecordPtr formatRecord) | ||
{ | ||
constexpr int bufferSize = 50; | ||
uint8_t buffer[bufferSize] = {}; | ||
|
||
OSErr err = ReadData(formatRecord->dataFork, buffer, bufferSize); | ||
|
||
if (err == noErr) | ||
{ | ||
try | ||
{ | ||
if (!heif_has_compatible_brand(buffer, bufferSize, "avif")) | ||
{ | ||
err = formatCannotRead; | ||
} | ||
} | ||
catch (const std::bad_alloc&) | ||
{ | ||
err = memFullErr; | ||
} | ||
catch (...) | ||
{ | ||
err = formatCannotRead; | ||
} | ||
} | ||
|
||
return err; | ||
} | ||
|
||
void InitGlobals(Globals* globals) | ||
{ | ||
globals->context = nullptr; | ||
globals->imageHandle = nullptr; | ||
globals->image = nullptr; | ||
globals->saveOptions.quality = 85; | ||
globals->saveOptions.chromaSubsampling = ChromaSubsampling::Yuv422; | ||
globals->saveOptions.compressionSpeed = CompressionSpeed::Default; | ||
globals->saveOptions.lossless = false; | ||
globals->saveOptions.imageBitDepth = ImageBitDepth::Twelve; // The save UI will default to 8-bit if the image is 8-bit. | ||
globals->saveOptions.keepColorProfile = false; | ||
globals->saveOptions.keepExif = false; | ||
globals->saveOptions.keepXmp = false; | ||
} | ||
} | ||
|
||
void PluginMain(const short selector, FormatRecordPtr formatRecord, intptr_t* data, short* result) | ||
{ | ||
if (selector == formatSelectorAbout) | ||
{ | ||
DoAbout(reinterpret_cast<AboutRecordPtr>(formatRecord)); | ||
*result = noErr; | ||
} | ||
else | ||
{ | ||
if (formatRecord->HostSupports32BitCoordinates) | ||
{ | ||
formatRecord->PluginUsing32BitCoordinates = true; | ||
} | ||
|
||
Globals* globals; | ||
if (*data == 0) | ||
{ | ||
*result = CreateGlobals(formatRecord, data); | ||
if (*result != noErr) | ||
{ | ||
return; | ||
} | ||
|
||
globals = reinterpret_cast<Globals*>(LockPIHandle(formatRecord, reinterpret_cast<Handle>(*data), false)); | ||
InitGlobals(globals); | ||
} | ||
else | ||
{ | ||
globals = reinterpret_cast<Globals*>(LockPIHandle(formatRecord, reinterpret_cast<Handle>(*data), false)); | ||
} | ||
|
||
switch (selector) | ||
{ | ||
case formatSelectorReadPrepare: | ||
*result = DoReadPrepare(formatRecord); | ||
break; | ||
case formatSelectorReadStart: | ||
*result = DoReadStart(formatRecord, globals); | ||
break; | ||
case formatSelectorReadContinue: | ||
*result = DoReadContinue(formatRecord, globals); | ||
break; | ||
case formatSelectorReadFinish: | ||
*result = DoReadFinish(globals); | ||
break; | ||
|
||
case formatSelectorOptionsPrepare: | ||
*result = DoOptionsPrepare(formatRecord); | ||
break; | ||
case formatSelectorOptionsStart: | ||
*result = DoOptionsStart(formatRecord, globals); | ||
break; | ||
case formatSelectorOptionsContinue: | ||
*result = DoOptionsContinue(); | ||
break; | ||
case formatSelectorOptionsFinish: | ||
*result = DoOptionsFinish(); | ||
break; | ||
|
||
case formatSelectorEstimatePrepare: | ||
*result = DoEstimatePrepare(formatRecord); | ||
break; | ||
case formatSelectorEstimateStart: | ||
*result = DoEstimateStart(formatRecord); | ||
break; | ||
case formatSelectorEstimateContinue: | ||
*result = DoEstimateContinue(); | ||
break; | ||
case formatSelectorEstimateFinish: | ||
*result = DoEstimateFinish(); | ||
break; | ||
|
||
case formatSelectorWritePrepare: | ||
*result = DoWritePrepare(formatRecord); | ||
break; | ||
case formatSelectorWriteStart: | ||
*result = DoWriteStart(formatRecord, globals->saveOptions); | ||
break; | ||
case formatSelectorWriteContinue: | ||
*result = DoWriteContinue(); | ||
break; | ||
case formatSelectorWriteFinish: | ||
*result = DoWriteFinish(formatRecord, globals->saveOptions); | ||
break; | ||
|
||
case formatSelectorFilterFile: | ||
*result = DoFilterFile(formatRecord); | ||
break; | ||
|
||
default: | ||
*result = formatBadParameters; | ||
} | ||
|
||
UnlockPIHandle(formatRecord, reinterpret_cast<Handle>(*data)); | ||
} | ||
} | ||
|
||
OSErr HandleErrorMessage(FormatRecordPtr formatRecord, const char* const message, OSErr fallbackErrorCode) | ||
{ | ||
if (formatRecord->errorString != nullptr) | ||
{ | ||
const size_t length = strlen(message); | ||
|
||
if (length <= 254) | ||
{ | ||
uint8* errorReportString = reinterpret_cast<uint8*>(formatRecord->errorString); | ||
|
||
errorReportString[0] = static_cast<uint8>(length); | ||
memcpy(&errorReportString[1], message, length); | ||
errorReportString[length + 1] = 0; | ||
|
||
return errReportString; | ||
} | ||
} | ||
|
||
return ShowErrorDialog(formatRecord, message, fallbackErrorCode); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/* | ||
* This file is part of avif-format, an AV1 Image (AVIF) file format | ||
* plug-in for Adobe Photoshop(R). | ||
* | ||
* Copyright (c) 2021 Nicholas Hayes | ||
* | ||
* avif-format 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 of | ||
* the License, or (at your option) any later version. | ||
* | ||
* avif-format 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 avif-format. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#ifndef AVIFFORMAT_H | ||
#define AVIFFORMAT_H | ||
|
||
#include "Common.h" | ||
|
||
enum class ChromaSubsampling | ||
{ | ||
Yuv420, | ||
Yuv422, | ||
Yuv444 | ||
}; | ||
|
||
enum class CompressionSpeed | ||
{ | ||
Fastest, | ||
Default, | ||
Slowest | ||
}; | ||
|
||
enum class ImageBitDepth | ||
{ | ||
Eight, | ||
Ten, | ||
Twelve | ||
}; | ||
|
||
struct SaveUIOptions | ||
{ | ||
int quality; | ||
ChromaSubsampling chromaSubsampling; | ||
CompressionSpeed compressionSpeed; | ||
ImageBitDepth imageBitDepth; | ||
bool lossless; | ||
bool keepColorProfile; | ||
bool keepExif; | ||
bool keepXmp; | ||
}; | ||
|
||
struct Globals | ||
{ | ||
heif_context* context; | ||
heif_image_handle* imageHandle; | ||
heif_image* image; | ||
|
||
SaveUIOptions saveOptions; | ||
}; | ||
|
||
DLLExport MACPASCAL void PluginMain( | ||
const short selector, | ||
FormatRecordPtr formatParamBlock, | ||
intptr_t* data, | ||
short* result); | ||
|
||
|
||
OSErr HandleErrorMessage(FormatRecordPtr formatRecord, const char* const message, OSErr fallbackErrorCode); | ||
|
||
VPoint GetImageSize(const FormatRecordPtr formatRecord); | ||
void SetRect(FormatRecordPtr formatRecord, int32 top, int32 left, int32 bottom, int32 right); | ||
|
||
OSErr NewPIHandle(const FormatRecordPtr formatRecord, int32 size, Handle* handle); | ||
void DisposePIHandle(const FormatRecordPtr formatRecord, Handle handle); | ||
Ptr LockPIHandle(const FormatRecordPtr formatRecord, Handle handle, Boolean moveHigh); | ||
void UnlockPIHandle(const FormatRecordPtr formatRecord, Handle handle); | ||
|
||
// Platform-specific UI methods | ||
|
||
void DoAbout(const AboutRecordPtr aboutRecord); | ||
bool DoSaveUI(const FormatRecordPtr formatRecord, SaveUIOptions& options); | ||
OSErr ShowErrorDialog(const FormatRecordPtr formatRecord, const char* const message, OSErr fallbackErrorCode); | ||
|
||
// File Format API callbacks | ||
|
||
OSErr DoReadPrepare(FormatRecordPtr formatRecord); | ||
OSErr DoReadStart(FormatRecordPtr formatRecord, Globals* globals); | ||
OSErr DoReadContinue(FormatRecordPtr formatRecord, Globals* globals); | ||
OSErr DoReadFinish(Globals* globals); | ||
|
||
OSErr DoOptionsPrepare(FormatRecordPtr formatRecord); | ||
OSErr DoOptionsStart(FormatRecordPtr formatRecord, Globals* globals); | ||
OSErr DoOptionsContinue(); | ||
OSErr DoOptionsFinish(); | ||
|
||
OSErr DoEstimatePrepare(FormatRecordPtr formatRecord); | ||
OSErr DoEstimateStart(FormatRecordPtr formatRecord); | ||
OSErr DoEstimateContinue(); | ||
OSErr DoEstimateFinish(); | ||
|
||
OSErr DoWritePrepare(FormatRecordPtr formatRecord); | ||
OSErr DoWriteStart(FormatRecordPtr formatRecord, SaveUIOptions& options); | ||
OSErr DoWriteContinue(); | ||
OSErr DoWriteFinish(FormatRecordPtr formatRecord, const SaveUIOptions& options); | ||
|
||
// Scripting | ||
|
||
OSErr ReadScriptParamsOnWrite(FormatRecordPtr formatRecord, SaveUIOptions& options, Boolean* showDialog); | ||
OSErr WriteScriptParamsOnWrite(FormatRecordPtr formatRecord, const SaveUIOptions& options); | ||
|
||
// Utility functions | ||
|
||
bool DescriptorSuiteIsAvaliable(const FormatRecordPtr formatRecord); | ||
bool HandleSuiteIsAvailable(const FormatRecordPtr formatRecord); | ||
bool HostImageModeSupported(const FormatRecordPtr formatRecord); | ||
bool HostSupportsRequiredFeatures(const FormatRecordPtr formatRecord); | ||
bool PropertySuiteIsAvailable(const FormatRecordPtr formatRecord); | ||
|
||
#endif // !AVIFFORMAT_H |
Oops, something went wrong.