mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-06 12:39:57 +00:00
Add support for jpeg image orientation adjustment (fix #2525)
This commit is contained in:
parent
d073ecd9d1
commit
339221c288
@ -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
|
||||
@ -27,10 +27,12 @@
|
||||
#include <csetjmp>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
|
||||
#include "jpeg_options.xml.h"
|
||||
|
||||
#include "jpeglib.h"
|
||||
#include "TinyEXIF.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -177,12 +179,24 @@ bool JpegFormat::onLoad(FileOp* fop)
|
||||
// Start decompressor.
|
||||
jpeg_start_decompress(&dinfo);
|
||||
|
||||
// Get orientation:
|
||||
TinyEXIF::EXIFInfo info;
|
||||
int orientation = 0;
|
||||
{
|
||||
std::ifstream istream(fop->filename(), std::ifstream::in | std::ifstream::binary);
|
||||
// Get EXIF information:
|
||||
TinyEXIF::EXIFInfo info(istream);
|
||||
if (info.Fields != 0)
|
||||
orientation = info.Orientation;
|
||||
}
|
||||
const int outputW = (orientation < 5 ? dinfo.output_width : dinfo.output_height);
|
||||
const 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;
|
||||
@ -217,6 +231,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) { 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) { 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) { 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) { 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) { 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) { 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) { return image->height() - 1; };
|
||||
next_addr_increment = -image->width();
|
||||
break;
|
||||
default:
|
||||
start_dst_x = [](int) { 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;
|
||||
@ -225,13 +294,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -243,10 +313,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user