Skip to content

Commit

Permalink
New: AVIF transformations support - crop, rotate, mirror
Browse files Browse the repository at this point in the history
  • Loading branch information
sylikc committed Jun 21, 2024
2 parents 8692ff5 + c380b96 commit 7e339ee
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
42 changes: 42 additions & 0 deletions src/JPEGView/AVIFWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "AVIFWrapper.h"
#include "avif/avif.h"
#include "BasicProcessing.h"
#include "MaxImageDef.h"
#include "ICCProfileTransform.h"

Expand Down Expand Up @@ -46,6 +47,7 @@ void* AvifReader::ReadImage(int& width,
memcpy(cache.data, buffer, sizebytes);
cache.decoder = avifDecoderCreate();
cache.decoder->maxThreads = nthreads;
cache.decoder->strictFlags = AVIF_STRICT_DISABLED;
result = avifDecoderSetIOMemory(cache.decoder, cache.data, sizebytes);
if (result != AVIF_RESULT_OK) {
DeleteCache();
Expand Down Expand Up @@ -91,6 +93,46 @@ void* AvifReader::ReadImage(int& width,
DeleteCache();
return NULL;
}

// Handle clap, irot and imir boxes
avifTransformFlags flags = cache.decoder->image->transformFlags;
if (flags & AVIF_TRANSFORM_CLAP) {
avifCleanApertureBox* clap = &cache.decoder->image->clap;
avifCropRect crop;
avifDiagnostics diag;
if (avifCropRectConvertCleanApertureBox(&crop, clap, width, height, cache.decoder->image->yuvFormat, &diag)) {
POINT point = { crop.x, crop.y };
SIZE sz = { crop.width, crop.height };
void* pixels = CBasicProcessing::Crop32bpp(width, height, cache.rgb.pixels, CRect(point, sz));
if (pixels != NULL) {
delete[] cache.rgb.pixels;
cache.rgb.pixels = (uint8_t*)pixels;
width = crop.width;
height = crop.height;
}
}
}
if (flags & AVIF_TRANSFORM_IROT) {
int angle = 360 - cache.decoder->image->irot.angle * 90;
void* pixels = CBasicProcessing::Rotate32bpp(width, height, cache.rgb.pixels, angle);
if (pixels != NULL) {
delete[] cache.rgb.pixels;
cache.rgb.pixels = (uint8_t*)pixels;
if (angle != 180) {
int temp = width;
width = height;
height = temp;
}
}
}
if (flags & AVIF_TRANSFORM_IMIR) {
void* pixels = CBasicProcessing::Mirror32bpp(width, height, cache.rgb.pixels, cache.decoder->image->imir.axis);
if (pixels != NULL) {
delete[] cache.rgb.pixels;
cache.rgb.pixels = (uint8_t*)pixels;
}
}

avifRWData icc = cache.decoder->image->icc;
if (cache.transform == NULL)
cache.transform = ICCProfileTransform::CreateTransform(icc.data, icc.size, ICCProfileTransform::FORMAT_BGRA);
Expand Down
5 changes: 5 additions & 0 deletions src/JPEGView/BasicProcessing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,11 @@ void* CBasicProcessing::Rotate32bpp(int nWidth, int nHeight, const void* pDIBPix
return pTarget;
}

void* CBasicProcessing::Mirror32bpp(int nWidth, int nHeight, const void* pDIBPixels, bool bHorizontally) {
return bHorizontally ? CBasicProcessing::MirrorH32bpp(nWidth, nHeight, pDIBPixels) :
CBasicProcessing::MirrorV32bpp(nWidth, nHeight, pDIBPixels);
}

void* CBasicProcessing::MirrorH32bpp(int nWidth, int nHeight, const void* pDIBPixels) {
uint32* pTarget = new(std::nothrow) uint32[nWidth * nHeight];
if (pTarget == NULL) return NULL;
Expand Down
3 changes: 3 additions & 0 deletions src/JPEGView/BasicProcessing.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class CBasicProcessing
// cases the return value is NULL
static void* Rotate32bpp(int nWidth, int nHeight, const void* pDIBPixels, int nRotationAngleCW);

// Mirror 32 bit DIB
static void* Mirror32bpp(int nWidth, int nHeight, const void* pDIBPixels, bool bHorizontally);

// Mirror 32 bit DIB horizontally
static void* MirrorH32bpp(int nWidth, int nHeight, const void* pDIBPixels);

Expand Down
3 changes: 1 addition & 2 deletions src/JPEGView/JPEGImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,7 @@ bool CJPEGImage::Mirror(bool bHorizontally) {
}

InvalidateAllCachedPixelData();
void* pNewOriginalPixels = bHorizontally ? CBasicProcessing::MirrorH32bpp(m_nOrigWidth, m_nOrigHeight, m_pOrigPixels) :
CBasicProcessing::MirrorV32bpp(m_nOrigWidth, m_nOrigHeight, m_pOrigPixels);
void* pNewOriginalPixels = CBasicProcessing::Mirror32bpp(m_nOrigWidth, m_nOrigHeight, m_pOrigPixels, bHorizontally);
if (pNewOriginalPixels == NULL) return false;
delete[] m_pOrigPixels;
m_pOrigPixels = pNewOriginalPixels;
Expand Down

0 comments on commit 7e339ee

Please sign in to comment.