Skip to content

Commit

Permalink
Add support jpeg Exif.Image.Orientation (fix aseprite#2525)
Browse files Browse the repository at this point in the history
Added tinyexif submodule also.
  • Loading branch information
Gasparoken committed Oct 15, 2024
1 parent 3848134 commit 72b1fb5
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 13 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,6 @@
[submodule "third_party/tinyxml2"]
path = third_party/tinyxml2
url = https://github.com/aseprite/tinyxml2.git
[submodule "third_party/tinyexif"]
path = third_party/tinyexif
url = https://github.com/aseprite/tinyexif.git
20 changes: 16 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ option(USE_SHARED_GIFLIB "Use your installed copy of giflib" off)
option(USE_SHARED_JPEGLIB "Use your installed copy of jpeglib" off)
option(USE_SHARED_ZLIB "Use your installed copy of zlib" off)
option(USE_SHARED_LIBPNG "Use your installed copy of libpng" off)
option(USE_SHARED_TINYXML "Use your installed copy of tinyxml" off)
option(USE_SHARED_PIXMAN "Use your installed copy of pixman" off)
option(USE_SHARED_TINYXML "Use your installed copy of tinyxml" on)
option(USE_SHARED_TINYEXIF "Use your installed copy of tinyexif" off)
option(USE_SHARED_PIXMAN "Use your installed copy of pixman" off)
option(USE_SHARED_FREETYPE "Use shared FreeType library" off)
option(USE_SHARED_HARFBUZZ "Use shared HarfBuzz library" off)
option(ENABLE_ASEPRITE_EXE "Compile main Aseprite executable" on)
Expand Down Expand Up @@ -166,6 +167,7 @@ set(FREETYPE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/freetype2)
set(HARFBUZZ_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/harfbuzz)
set(SIMPLEINI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/simpleini)
set(TINYXML_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/tinyxml2)
set(TINYEXIF_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/tinyexif)
set(ZLIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/zlib)

# Search in the "cmake" directory for additional CMake modules.
Expand Down Expand Up @@ -229,14 +231,24 @@ add_definitions(-DPNG_NO_MMX_CODE) # Do not use MMX optimizations in PNG code

# tinyxml2
if(USE_SHARED_TINYXML)
find_library(TINYXML_LIBRARY NAMES tinyxml2)
find_path(TINYXML_INCLUDE_DIR NAMES tinyxml2.h)
find_package(TINYXML REQUIRED)
else()
set(TINYXML_LIBRARY tinyxml2)
set(TINYXML_INCLUDE_DIR ${TINYXML_DIR})
endif()
include_directories(${TINYXML_INCLUDE_DIR})

# tinyexif
if(USE_SHARED_TINYEXIF)
find_library(TINYEXIF_LIBRARY NAMES tinyexif)
find_path(TINYEXIF_INCLUDE_DIR NAMES tinyexif.h)
else()
set(TINYEXIF_LIBRARY tinyexif)
set(TINYEXIF_INCLUDE_DIR ${TINYEXIF_DIR})
endif()
include_directories(${TINYEXIF_INCLUDE_DIR})


# pixman
if(USE_SHARED_PIXMAN)
find_library(PIXMAN_LIBRARY NAMES pixman pixman-1)
Expand Down
24 changes: 24 additions & 0 deletions cmake/Findtinyxml2.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (C) 2023 Igara Studio S.A.
# Find tinyxml2

function(find_tinyxml2 dir dependencies)
file(GLOB tinyxml2 ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/tinyxml2.cpp)
list(REMOVE_AT ARGV 0)

get_filename_component(tinyxml2name tinyxml2.cpp NAME_WE)

add_executable(${tinyxml2name} tinyxml2.cpp)

if(MSVC)
# Fix problem compiling gen from a Visual Studio solution
set_target_properties(${tinyxml2name}
PROPERTIES LINK_FLAGS -ENTRY:"mainCRTStartup")
endif()

target_link_libraries(${tinyxml2name} tinyxml2 ${ARGV} ${PLATFORM_LIBS})

if(extra_definitions)
set_target_properties(${tinyxml2name}
PROPERTIES COMPILE_FLAGS ${extra_definitions})
endif()
endfunction()
1 change: 1 addition & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ target_link_libraries(app-lib
undo
${CMARK_LIBRARIES}
${TINYXML_LIBRARY}
${TINYEXIF_LIBRARY}
${JPEG_LIBRARIES}
${GIF_LIBRARIES}
${PNG_LIBRARIES}
Expand Down
83 changes: 74 additions & 9 deletions src/app/file/jpeg_format.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2023 Igara Studio S.A.
// Copyright (C) 2018-2024 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
Expand Down Expand Up @@ -31,6 +31,7 @@
#include "jpeg_options.xml.h"

#include "jpeglib.h"
#include "TinyEXIF.h"

namespace app {

Expand Down Expand Up @@ -177,12 +178,18 @@ bool JpegFormat::onLoad(FileOp* fop)
// Start decompressor.
jpeg_start_decompress(&dinfo);

// Get orientation:
TinyEXIF::EXIFInfo info;
info.parseFrom(file->_bf._base, file->_bf._size);
int orientation = info.Orientation;
int outputW = (orientation < 5 ? dinfo.output_width : dinfo.output_height);
int outputH = (orientation < 5 ? dinfo.output_height : dinfo.output_width);
// Create the image.
ImageRef image = fop->sequenceImageToLoad(
(dinfo.out_color_space == JCS_RGB ? IMAGE_RGB:
IMAGE_GRAYSCALE),
dinfo.output_width,
dinfo.output_height);
outputW,
outputH);
if (!image) {
jpeg_destroy_decompress(&dinfo);
return false;
Expand Down Expand Up @@ -217,6 +224,61 @@ bool JpegFormat::onLoad(FileOp* fop)
while (dinfo.output_scanline < dinfo.output_height) {
num_scanlines = jpeg_read_scanlines(&dinfo, buffer, buffer_height);

// Orientation function/variables adjust
std::function<int(int)> start_dst_x;
std::function<int(int)> start_dst_y;
int next_addr_increment = 1;
switch (orientation) {
case 2:
start_dst_x = [image](int y) { return image->width() - 1; };
start_dst_y = [dinfo](int y) {
return dinfo.output_scanline - 1 + y; };
next_addr_increment = -1;
break;
case 3:
start_dst_x = [image](int y) { return image->width() - 1; };
start_dst_y = [image, dinfo](int y) {
return image->height() - dinfo.output_scanline + y; };
next_addr_increment = -1;
break;
case 4:
start_dst_x = [](int y) { return 0; };
start_dst_y = [image, dinfo](int y) {
return image->height() - dinfo.output_scanline - y; };
next_addr_increment = 1;
break;
case 5:
start_dst_x = [dinfo](int y) {
return dinfo.output_scanline - 1 + y; };
start_dst_y = [](int y) { return 0; };
next_addr_increment = image->width();
break;
case 6:
start_dst_x = [image, dinfo](int y) {
return image->width() - dinfo.output_scanline - y; };
start_dst_y = [](int y) { return 0; };
next_addr_increment = image->width();
break;
case 7:
start_dst_x = [image, dinfo](int y) {
return image->width() - dinfo.output_scanline - y; };
start_dst_y = [image](int y) { return image->height() - 1; };
next_addr_increment = -image->width();
break;
case 8:
start_dst_x = [dinfo](int y) {
return dinfo.output_scanline - 1 + y; };
start_dst_y = [image](int y) { return image->height() - 1; };
next_addr_increment = -image->width();
break;
default:
start_dst_x = [](int y) { return 0; };
start_dst_y = [dinfo](int y) {
return dinfo.output_scanline - 1 + y; };
next_addr_increment = 1;
break;
}

// RGB
if (image->pixelFormat() == IMAGE_RGB) {
uint8_t* src_address;
Expand All @@ -225,13 +287,14 @@ bool JpegFormat::onLoad(FileOp* fop)

for (y=0; y<(int)num_scanlines; y++) {
src_address = ((uint8_t**)buffer)[y];
dst_address = (uint32_t*)image->getPixelAddress(0, dinfo.output_scanline-1+y);
dst_address = (uint32_t*)image->getPixelAddress(start_dst_x(y), start_dst_y(y));

for (x=0; x<image->width(); x++) {
for (x=0; x<dinfo.output_width; x++) {
r = *(src_address++);
g = *(src_address++);
b = *(src_address++);
*(dst_address++) = rgba(r, g, b, 255);
*dst_address = rgba(r, g, b, 255);
dst_address += next_addr_increment;
}
}
}
Expand All @@ -243,10 +306,12 @@ bool JpegFormat::onLoad(FileOp* fop)

for (y=0; y<(int)num_scanlines; y++) {
src_address = ((uint8_t**)buffer)[y];
dst_address = (uint16_t*)image->getPixelAddress(0, dinfo.output_scanline-1+y);
dst_address = (uint16_t*)image->getPixelAddress(start_dst_x(y), start_dst_y(y));

for (x=0; x<image->width(); x++)
*(dst_address++) = graya(*(src_address++), 255);
for (x=0; x<dinfo.output_width; x++) {
*dst_address = graya(*(src_address++), 255);
dst_address += next_addr_increment;
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions third_party/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ if(NOT USE_SHARED_TINYXML)
add_subdirectory(tinyxml2)
endif()

# Jpeg exif fields
if(NOT USE_SHARED_TINYEXIF)
set(tinyexif_BUILD_TESTING OFF CACHE BOOL "Build tests for tinyexif")
add_subdirectory(tinyexif)
endif()

if(REQUIRE_CURL AND NOT USE_SHARED_CURL)
set(BUILD_RELEASE_DEBUG_DIRS ON BOOL)
set(BUILD_CURL_EXE OFF CACHE BOOL "Set to ON to build curl executable.")
Expand Down
1 change: 1 addition & 0 deletions third_party/tinyexif
Submodule tinyexif added at d07062

0 comments on commit 72b1fb5

Please sign in to comment.