2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-01-24 10:19:29 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-01-24 10:19:29 +00:00
|
|
|
*
|
|
|
|
|
* Contributor(s): Campbell Barton
|
|
|
|
|
*
|
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
2011-02-27 20:23:21 +00:00
|
|
|
/** \file blender/imbuf/intern/jp2.c
|
|
|
|
|
* \ingroup imbuf
|
|
|
|
|
*/
|
|
|
|
|
|
2010-08-18 10:42:00 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2010-05-18 07:28:44 +00:00
|
|
|
#include "BLI_math.h"
|
2012-08-12 23:28:33 +00:00
|
|
|
#include "BLI_fileops.h"
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
#include "IMB_imbuf.h"
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
#include "IMB_filetype.h"
|
2009-01-24 10:19:29 +00:00
|
|
|
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
#include "IMB_colormanagement.h"
|
|
|
|
|
#include "IMB_colormanagement_intern.h"
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
#include "openjpeg.h"
|
|
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2015-07-12 01:43:32 +10:00
|
|
|
static const char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
|
|
|
|
|
static const char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00};
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* We only need this because of how the presets are set */
|
2012-06-11 18:43:16 +00:00
|
|
|
/* this typedef is copied from 'openjpeg-1.5.0/applications/codec/image_to_j2k.c' */
|
2012-04-21 13:37:26 +00:00
|
|
|
typedef struct img_folder {
|
2009-01-24 10:19:29 +00:00
|
|
|
/** The directory path of the folder containing input images*/
|
|
|
|
|
char *imgdirpath;
|
|
|
|
|
/** Output format*/
|
|
|
|
|
char *out_format;
|
|
|
|
|
/** Enable option*/
|
|
|
|
|
char set_imgdir;
|
|
|
|
|
/** Enable Cod Format for output*/
|
|
|
|
|
char set_out_format;
|
|
|
|
|
/** User specified rate stored in case of cinema option*/
|
|
|
|
|
float *rates;
|
2012-04-21 13:37:26 +00:00
|
|
|
} img_fol_t;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2015-07-27 22:34:55 +02:00
|
|
|
enum {
|
|
|
|
|
DCP_CINEMA2K = 3,
|
|
|
|
|
DCP_CINEMA4K = 4,
|
|
|
|
|
};
|
|
|
|
|
|
2016-04-12 11:26:06 +10:00
|
|
|
static bool check_jp2(const unsigned char *mem) /* J2K_CFMT */
|
2009-01-24 10:19:29 +00:00
|
|
|
{
|
2012-08-27 11:59:26 +00:00
|
|
|
return memcmp(JP2_HEAD, mem, sizeof(JP2_HEAD)) ? 0 : 1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-12 11:26:06 +10:00
|
|
|
static bool check_j2k(const unsigned char *mem) /* J2K_CFMT */
|
2012-08-27 11:59:26 +00:00
|
|
|
{
|
|
|
|
|
return memcmp(J2K_HEAD, mem, sizeof(J2K_HEAD)) ? 0 : 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-11 23:52:18 +10:00
|
|
|
int imb_is_a_jp2(const unsigned char *buf)
|
2012-08-27 11:59:26 +00:00
|
|
|
{
|
2010-11-20 14:19:21 +00:00
|
|
|
return check_jp2(buf);
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-03-09 18:28:30 +00:00
|
|
|
* sample error callback expecting a FILE* client object
|
|
|
|
|
*/
|
2011-12-17 00:52:36 +00:00
|
|
|
static void error_callback(const char *msg, void *client_data)
|
|
|
|
|
{
|
2012-05-16 09:26:37 +00:00
|
|
|
FILE *stream = (FILE *)client_data;
|
2009-01-24 10:19:29 +00:00
|
|
|
fprintf(stream, "[ERROR] %s", msg);
|
|
|
|
|
}
|
|
|
|
|
/**
|
2012-03-09 18:28:30 +00:00
|
|
|
* sample warning callback expecting a FILE* client object
|
|
|
|
|
*/
|
2011-12-17 00:52:36 +00:00
|
|
|
static void warning_callback(const char *msg, void *client_data)
|
|
|
|
|
{
|
2012-05-16 09:26:37 +00:00
|
|
|
FILE *stream = (FILE *)client_data;
|
2009-01-24 10:19:29 +00:00
|
|
|
fprintf(stream, "[WARNING] %s", msg);
|
|
|
|
|
}
|
|
|
|
|
/**
|
2012-03-09 18:28:30 +00:00
|
|
|
* sample debug callback expecting no client object
|
|
|
|
|
*/
|
2011-12-17 00:52:36 +00:00
|
|
|
static void info_callback(const char *msg, void *client_data)
|
|
|
|
|
{
|
2016-07-12 17:38:26 +02:00
|
|
|
(void)client_data;
|
|
|
|
|
fprintf(stdout, "[INFO] %s", msg);
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2012-06-12 08:50:40 +00:00
|
|
|
# define PIXEL_LOOPER_BEGIN(_rect) \
|
|
|
|
|
for (y = h - 1; y != (unsigned int)(-1); y--) { \
|
|
|
|
|
for (i = y * w, i_next = (y + 1) * w; \
|
|
|
|
|
i < i_next; \
|
|
|
|
|
i++, _rect += 4) \
|
|
|
|
|
{ \
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2013-02-22 09:20:22 +00:00
|
|
|
# define PIXEL_LOOPER_BEGIN_CHANNELS(_rect, _channels) \
|
|
|
|
|
for (y = h - 1; y != (unsigned int)(-1); y--) { \
|
|
|
|
|
for (i = y * w, i_next = (y + 1) * w; \
|
|
|
|
|
i < i_next; \
|
|
|
|
|
i++, _rect += _channels) \
|
|
|
|
|
{ \
|
|
|
|
|
|
2012-06-12 08:50:40 +00:00
|
|
|
# define PIXEL_LOOPER_END \
|
|
|
|
|
} \
|
2018-04-16 17:16:29 +02:00
|
|
|
} (void)0 \
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
struct ImBuf *imb_jp2_decode(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
|
2012-06-12 08:50:40 +00:00
|
|
|
{
|
2011-09-16 08:20:21 +00:00
|
|
|
struct ImBuf *ibuf = NULL;
|
2014-04-01 11:34:00 +11:00
|
|
|
bool use_float = false; /* for precision higher then 8 use float */
|
|
|
|
|
bool use_alpha = false;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
long signed_offsets[4] = {0, 0, 0, 0};
|
|
|
|
|
int float_divs[4] = {1, 1, 1, 1};
|
2011-01-22 03:50:09 +00:00
|
|
|
|
2012-06-12 08:50:40 +00:00
|
|
|
unsigned int i, i_next, w, h, planes;
|
|
|
|
|
unsigned int y;
|
|
|
|
|
int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */
|
2016-07-12 17:38:26 +02:00
|
|
|
bool is_jp2, is_j2k;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
opj_dparameters_t parameters; /* decompression parameters */
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
opj_event_mgr_t event_mgr; /* event manager */
|
2009-01-24 10:19:29 +00:00
|
|
|
opj_image_t *image = NULL;
|
2016-07-12 17:38:26 +02:00
|
|
|
|
|
|
|
|
opj_dinfo_t *dinfo = NULL; /* handle to a decompressor */
|
|
|
|
|
opj_cio_t *cio = NULL;
|
|
|
|
|
|
|
|
|
|
is_jp2 = check_jp2(mem);
|
|
|
|
|
is_j2k = check_j2k(mem);
|
|
|
|
|
|
|
|
|
|
if (!is_jp2 && !is_j2k)
|
|
|
|
|
return(NULL);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
/* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */
|
|
|
|
|
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
|
|
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* configure the event callbacks (not required) */
|
|
|
|
|
memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
|
|
|
|
|
event_mgr.error_handler = error_callback;
|
|
|
|
|
event_mgr.warning_handler = warning_callback;
|
|
|
|
|
event_mgr.info_handler = info_callback;
|
|
|
|
|
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
/* set decoding parameters to default values */
|
|
|
|
|
opj_set_default_decoder_parameters(¶meters);
|
|
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
/* JPEG 2000 compressed image data */
|
|
|
|
|
|
|
|
|
|
/* get a decoder handle */
|
2016-07-12 17:38:26 +02:00
|
|
|
dinfo = opj_create_decompress(is_jp2 ? CODEC_JP2 : CODEC_J2K);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* catch events using our callbacks and give a local context */
|
|
|
|
|
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* setup the decoder decoding parameters using the current image and user parameters */
|
2016-07-12 17:38:26 +02:00
|
|
|
opj_setup_decoder(dinfo, ¶meters);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* open a byte stream */
|
|
|
|
|
/* note, we can't avoid removing 'const' cast here */
|
|
|
|
|
cio = opj_cio_open((opj_common_ptr)dinfo, (unsigned char *)mem, size);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* decode the stream and fill the image structure */
|
2016-07-12 17:38:26 +02:00
|
|
|
image = opj_decode(dinfo, cio);
|
|
|
|
|
|
|
|
|
|
if (!image) {
|
2009-01-24 10:19:29 +00:00
|
|
|
fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
|
2016-07-12 17:38:26 +02:00
|
|
|
opj_destroy_decompress(dinfo);
|
|
|
|
|
opj_cio_close(cio);
|
|
|
|
|
return NULL;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* close the byte stream */
|
|
|
|
|
opj_cio_close(cio);
|
|
|
|
|
|
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((image->numcomps * image->x1 * image->y1) == 0) {
|
2012-04-29 15:47:02 +00:00
|
|
|
fprintf(stderr, "\nError: invalid raw image parameters\n");
|
2016-07-12 17:38:26 +02:00
|
|
|
return NULL;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2010-04-21 07:49:06 +00:00
|
|
|
w = image->comps[0].w;
|
2009-01-24 10:19:29 +00:00
|
|
|
h = image->comps[0].h;
|
|
|
|
|
|
|
|
|
|
switch (image->numcomps) {
|
2012-07-03 19:09:07 +00:00
|
|
|
case 1: /* Grayscale */
|
2012-05-16 09:26:37 +00:00
|
|
|
case 3: /* Color */
|
|
|
|
|
planes = 24;
|
2014-04-01 11:34:00 +11:00
|
|
|
use_alpha = false;
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2012-07-03 19:09:07 +00:00
|
|
|
default: /* 2 or 4 - Grayscale or Color + alpha */
|
|
|
|
|
planes = 32; /* grayscale + alpha */
|
2014-04-01 11:34:00 +11:00
|
|
|
use_alpha = true;
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = image->numcomps;
|
2012-05-16 09:26:37 +00:00
|
|
|
if (i > 4) i = 4;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
while (i) {
|
|
|
|
|
i--;
|
|
|
|
|
|
|
|
|
|
if (image->comps[i].prec > 8)
|
2014-04-01 11:34:00 +11:00
|
|
|
use_float = true;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
if (image->comps[i].sgnd)
|
2012-05-16 09:26:37 +00:00
|
|
|
signed_offsets[i] = 1 << (image->comps[i].prec - 1);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* only needed for float images but dosnt hurt to calc this */
|
2012-05-16 09:26:37 +00:00
|
|
|
float_divs[i] = (1 << image->comps[i].prec) - 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
ibuf = IMB_allocImBuf(w, h, planes, use_float ? IB_rectfloat : IB_rect);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
if (ibuf == NULL) {
|
2016-07-12 17:38:26 +02:00
|
|
|
if (dinfo)
|
|
|
|
|
opj_destroy_decompress(dinfo);
|
|
|
|
|
return NULL;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-13 13:58:17 +02:00
|
|
|
ibuf->ftype = IMB_FTYPE_JP2;
|
2016-07-12 17:38:26 +02:00
|
|
|
if (is_jp2)
|
2015-07-13 13:58:17 +02:00
|
|
|
ibuf->foptions.flag |= JP2_JP2;
|
2016-07-12 17:38:26 +02:00
|
|
|
else
|
2015-07-13 13:58:17 +02:00
|
|
|
ibuf->foptions.flag |= JP2_J2K;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
if (use_float) {
|
2012-05-16 09:26:37 +00:00
|
|
|
float *rect_float = ibuf->rect_float;
|
2010-04-21 07:49:06 +00:00
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
if (image->numcomps < 3) {
|
2012-06-12 08:50:40 +00:00
|
|
|
r = image->comps[0].data;
|
|
|
|
|
a = (use_alpha) ? image->comps[1].data : NULL;
|
|
|
|
|
|
2012-07-03 19:09:07 +00:00
|
|
|
/* grayscale 12bits+ */
|
2012-06-12 08:50:40 +00:00
|
|
|
if (use_alpha) {
|
|
|
|
|
a = image->comps[1].data;
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float) {
|
|
|
|
|
rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
|
|
|
|
|
rect_float[3] = (a[i] + signed_offsets[1]) / float_divs[1];
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float) {
|
|
|
|
|
rect_float[0] = rect_float[1] = rect_float[2] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
|
2012-05-16 09:26:37 +00:00
|
|
|
rect_float[3] = 1.0f;
|
2012-06-12 08:50:40 +00:00
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-06-12 08:50:40 +00:00
|
|
|
r = image->comps[0].data;
|
|
|
|
|
g = image->comps[1].data;
|
|
|
|
|
b = image->comps[2].data;
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
/* rgb or rgba 12bits+ */
|
2012-06-12 08:50:40 +00:00
|
|
|
if (use_alpha) {
|
|
|
|
|
a = image->comps[3].data;
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float) {
|
|
|
|
|
rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
|
|
|
|
|
rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1];
|
|
|
|
|
rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2];
|
|
|
|
|
rect_float[3] = (float)(a[i] + signed_offsets[3]) / float_divs[3];
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float) {
|
|
|
|
|
rect_float[0] = (float)(r[i] + signed_offsets[0]) / float_divs[0];
|
|
|
|
|
rect_float[1] = (float)(g[i] + signed_offsets[1]) / float_divs[1];
|
|
|
|
|
rect_float[2] = (float)(b[i] + signed_offsets[2]) / float_divs[2];
|
2012-05-16 09:26:37 +00:00
|
|
|
rect_float[3] = 1.0f;
|
2012-06-12 08:50:40 +00:00
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-06-12 08:50:40 +00:00
|
|
|
unsigned char *rect_uchar = (unsigned char *)ibuf->rect;
|
2010-04-21 07:49:06 +00:00
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
if (image->numcomps < 3) {
|
2012-06-12 08:50:40 +00:00
|
|
|
r = image->comps[0].data;
|
|
|
|
|
a = (use_alpha) ? image->comps[1].data : NULL;
|
|
|
|
|
|
2012-07-03 19:09:07 +00:00
|
|
|
/* grayscale */
|
2012-06-12 08:50:40 +00:00
|
|
|
if (use_alpha) {
|
|
|
|
|
a = image->comps[3].data;
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar) {
|
|
|
|
|
rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]);
|
|
|
|
|
rect_uchar[3] = a[i] + signed_offsets[1];
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar) {
|
|
|
|
|
rect_uchar[0] = rect_uchar[1] = rect_uchar[2] = (r[i] + signed_offsets[0]);
|
|
|
|
|
rect_uchar[3] = 255;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-06-12 08:50:40 +00:00
|
|
|
r = image->comps[0].data;
|
|
|
|
|
g = image->comps[1].data;
|
|
|
|
|
b = image->comps[2].data;
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
/* 8bit rgb or rgba */
|
2012-06-12 08:50:40 +00:00
|
|
|
if (use_alpha) {
|
|
|
|
|
a = image->comps[3].data;
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar) {
|
|
|
|
|
rect_uchar[0] = r[i] + signed_offsets[0];
|
|
|
|
|
rect_uchar[1] = g[i] + signed_offsets[1];
|
|
|
|
|
rect_uchar[2] = b[i] + signed_offsets[2];
|
|
|
|
|
rect_uchar[3] = a[i] + signed_offsets[3];
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar) {
|
|
|
|
|
rect_uchar[0] = r[i] + signed_offsets[0];
|
|
|
|
|
rect_uchar[1] = g[i] + signed_offsets[1];
|
|
|
|
|
rect_uchar[2] = b[i] + signed_offsets[2];
|
|
|
|
|
rect_uchar[3] = 255;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-09 21:56:29 +10:00
|
|
|
/* free remaining structures */
|
2016-07-12 17:38:26 +02:00
|
|
|
if (dinfo) {
|
|
|
|
|
opj_destroy_decompress(dinfo);
|
2016-06-09 21:56:29 +10:00
|
|
|
}
|
2016-07-12 17:38:26 +02:00
|
|
|
|
|
|
|
|
/* free image data structure */
|
|
|
|
|
opj_image_destroy(image);
|
|
|
|
|
|
|
|
|
|
if (flags & IB_rect) {
|
|
|
|
|
IMB_rect_from_float(ibuf);
|
2016-06-09 21:56:29 +10:00
|
|
|
}
|
2016-07-12 17:38:26 +02:00
|
|
|
|
|
|
|
|
return(ibuf);
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2012-06-20 16:43:48 +00:00
|
|
|
//static opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp)
|
2009-01-24 10:19:29 +00:00
|
|
|
/* prec can be 8, 12, 16 */
|
|
|
|
|
|
2012-06-12 08:10:34 +00:00
|
|
|
/* use inline because the float passed can be a function call that would end up being called many times */
|
|
|
|
|
#if 0
|
2012-05-16 09:26:37 +00:00
|
|
|
#define UPSAMPLE_8_TO_12(_val) ((_val << 4) | (_val & ((1 << 4) - 1)))
|
|
|
|
|
#define UPSAMPLE_8_TO_16(_val) ((_val << 8) + _val)
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
#define DOWNSAMPLE_FLOAT_TO_8BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val)))
|
|
|
|
|
#define DOWNSAMPLE_FLOAT_TO_12BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val)))
|
|
|
|
|
#define DOWNSAMPLE_FLOAT_TO_16BIT(_val) (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val)))
|
2012-06-12 08:10:34 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
BLI_INLINE int UPSAMPLE_8_TO_12(const unsigned char _val)
|
|
|
|
|
{
|
|
|
|
|
return (_val << 4) | (_val & ((1 << 4) - 1));
|
|
|
|
|
}
|
|
|
|
|
BLI_INLINE int UPSAMPLE_8_TO_16(const unsigned char _val)
|
|
|
|
|
{
|
|
|
|
|
return (_val << 8) + _val;
|
|
|
|
|
}
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-06-12 08:10:34 +00:00
|
|
|
BLI_INLINE int DOWNSAMPLE_FLOAT_TO_8BIT(const float _val)
|
|
|
|
|
{
|
|
|
|
|
return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 255 : (int)(255.0f * (_val)));
|
|
|
|
|
}
|
|
|
|
|
BLI_INLINE int DOWNSAMPLE_FLOAT_TO_12BIT(const float _val)
|
|
|
|
|
{
|
|
|
|
|
return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 4095 : (int)(4095.0f * (_val)));
|
|
|
|
|
}
|
|
|
|
|
BLI_INLINE int DOWNSAMPLE_FLOAT_TO_16BIT(const float _val)
|
|
|
|
|
{
|
|
|
|
|
return (_val) <= 0.0f ? 0 : ((_val) >= 1.0f ? 65535 : (int)(65535.0f * (_val)));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/*
|
2012-03-09 18:28:30 +00:00
|
|
|
* 2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3x12 bits per pixel, XYZ color space
|
|
|
|
|
*
|
2012-11-12 07:33:01 +00:00
|
|
|
* - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the image is used
|
|
|
|
|
* - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the image is used
|
2012-03-09 18:28:30 +00:00
|
|
|
*/
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* ****************************** COPIED FROM image_to_j2k.c */
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
2012-05-16 09:26:37 +00:00
|
|
|
#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/
|
|
|
|
|
#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/
|
|
|
|
|
#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/
|
|
|
|
|
#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
|
2011-12-17 00:52:36 +00:00
|
|
|
static int initialise_4K_poc(opj_poc_t *POC, int numres)
|
|
|
|
|
{
|
2009-01-24 10:19:29 +00:00
|
|
|
POC[0].tile = 1;
|
|
|
|
|
POC[0].resno0 = 0;
|
|
|
|
|
POC[0].compno0 = 0;
|
|
|
|
|
POC[0].layno1 = 1;
|
2012-05-16 09:26:37 +00:00
|
|
|
POC[0].resno1 = numres - 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
POC[0].compno1 = 3;
|
2016-07-12 17:38:26 +02:00
|
|
|
POC[0].prg1 = CPRL;
|
2009-01-24 10:19:29 +00:00
|
|
|
POC[1].tile = 1;
|
2012-05-16 09:26:37 +00:00
|
|
|
POC[1].resno0 = numres - 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
POC[1].compno0 = 0;
|
|
|
|
|
POC[1].layno1 = 1;
|
|
|
|
|
POC[1].resno1 = numres;
|
|
|
|
|
POC[1].compno1 = 3;
|
2016-07-12 17:38:26 +02:00
|
|
|
POC[1].prg1 = CPRL;
|
2009-01-24 10:19:29 +00:00
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-17 00:52:36 +00:00
|
|
|
static void cinema_parameters(opj_cparameters_t *parameters)
|
|
|
|
|
{
|
2014-04-01 11:34:00 +11:00
|
|
|
parameters->tile_size_on = 0; /* false */
|
2012-05-16 09:26:37 +00:00
|
|
|
parameters->cp_tdx = 1;
|
|
|
|
|
parameters->cp_tdy = 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/*Tile part*/
|
|
|
|
|
parameters->tp_flag = 'C';
|
|
|
|
|
parameters->tp_on = 1;
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
/*Tile and Image shall be at (0, 0)*/
|
2009-01-24 10:19:29 +00:00
|
|
|
parameters->cp_tx0 = 0;
|
|
|
|
|
parameters->cp_ty0 = 0;
|
|
|
|
|
parameters->image_offset_x0 = 0;
|
|
|
|
|
parameters->image_offset_y0 = 0;
|
|
|
|
|
|
2012-05-27 19:40:36 +00:00
|
|
|
/*Codeblock size = 32 * 32*/
|
2012-10-21 05:46:41 +00:00
|
|
|
parameters->cblockw_init = 32;
|
2009-01-24 10:19:29 +00:00
|
|
|
parameters->cblockh_init = 32;
|
|
|
|
|
parameters->csty |= 0x01;
|
|
|
|
|
|
|
|
|
|
/*The progression order shall be CPRL*/
|
2016-07-12 17:38:26 +02:00
|
|
|
parameters->prog_order = CPRL;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* No ROI */
|
|
|
|
|
parameters->roi_compno = -1;
|
|
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
parameters->subsampling_dx = 1; parameters->subsampling_dy = 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* 9-7 transform */
|
|
|
|
|
parameters->irreversible = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *image, img_fol_t *img_fol)
|
2011-12-17 00:52:36 +00:00
|
|
|
{
|
2009-01-24 10:19:29 +00:00
|
|
|
int i;
|
|
|
|
|
float temp_rate;
|
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
switch (parameters->cp_cinema) {
|
2016-07-12 17:38:26 +02:00
|
|
|
case CINEMA2K_24:
|
|
|
|
|
case CINEMA2K_48:
|
2012-05-16 09:26:37 +00:00
|
|
|
if (parameters->numresolution > 6) {
|
|
|
|
|
parameters->numresolution = 6;
|
|
|
|
|
}
|
|
|
|
|
if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))) {
|
2016-07-12 17:38:26 +02:00
|
|
|
fprintf(stdout, "Image coordinates %d x %d is not 2K compliant.\nJPEG Digital Cinema Profile-3 "
|
2012-05-16 09:26:37 +00:00
|
|
|
"(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n",
|
|
|
|
|
image->comps[0].w, image->comps[0].h);
|
2016-07-12 17:38:26 +02:00
|
|
|
parameters->cp_rsiz = STD_RSIZ;
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2015-07-27 22:34:55 +02:00
|
|
|
else {
|
|
|
|
|
parameters->cp_rsiz = DCP_CINEMA2K;
|
|
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
case CINEMA4K_24:
|
2012-05-16 09:26:37 +00:00
|
|
|
if (parameters->numresolution < 1) {
|
|
|
|
|
parameters->numresolution = 1;
|
|
|
|
|
}
|
|
|
|
|
else if (parameters->numresolution > 7) {
|
|
|
|
|
parameters->numresolution = 7;
|
|
|
|
|
}
|
|
|
|
|
if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))) {
|
2016-07-12 17:38:26 +02:00
|
|
|
fprintf(stdout, "Image coordinates %d x %d is not 4K compliant.\nJPEG Digital Cinema Profile-4"
|
2012-05-16 09:26:37 +00:00
|
|
|
"(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n",
|
|
|
|
|
image->comps[0].w, image->comps[0].h);
|
2016-07-12 17:38:26 +02:00
|
|
|
parameters->cp_rsiz = STD_RSIZ;
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2015-07-27 22:34:55 +02:00
|
|
|
else {
|
|
|
|
|
parameters->cp_rsiz = DCP_CINEMA2K;
|
|
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution);
|
|
|
|
|
break;
|
2016-07-12 17:38:26 +02:00
|
|
|
case OFF:
|
2012-05-16 09:26:37 +00:00
|
|
|
/* do nothing */
|
|
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
switch (parameters->cp_cinema) {
|
2016-07-12 17:38:26 +02:00
|
|
|
case CINEMA2K_24:
|
|
|
|
|
case CINEMA4K_24:
|
2012-05-16 09:26:37 +00:00
|
|
|
for (i = 0; i < parameters->tcp_numlayers; i++) {
|
|
|
|
|
temp_rate = 0;
|
|
|
|
|
if (img_fol->rates[i] == 0) {
|
|
|
|
|
parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
|
|
|
|
|
(CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-16 09:26:37 +00:00
|
|
|
temp_rate = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
|
|
|
|
|
(img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
|
|
|
if (temp_rate > CINEMA_24_CS) {
|
|
|
|
|
parameters->tcp_rates[i] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
|
|
|
|
|
(CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
parameters->tcp_rates[i] = img_fol->rates[i];
|
|
|
|
|
}
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
parameters->max_comp_size = COMP_24_CS;
|
|
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
case CINEMA2K_48:
|
2012-05-16 09:26:37 +00:00
|
|
|
for (i = 0; i < parameters->tcp_numlayers; i++) {
|
|
|
|
|
temp_rate = 0;
|
|
|
|
|
if (img_fol->rates[i] == 0) {
|
|
|
|
|
parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
|
|
|
|
|
(CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-16 09:26:37 +00:00
|
|
|
temp_rate = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
|
|
|
|
|
(img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
|
|
|
if (temp_rate > CINEMA_48_CS) {
|
|
|
|
|
parameters->tcp_rates[0] = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) /
|
|
|
|
|
(CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
parameters->tcp_rates[i] = img_fol->rates[i];
|
|
|
|
|
}
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
parameters->max_comp_size = COMP_48_CS;
|
|
|
|
|
break;
|
2016-07-12 17:38:26 +02:00
|
|
|
case OFF:
|
2012-05-16 09:26:37 +00:00
|
|
|
/* do nothing */
|
|
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
parameters->cp_disto_alloc = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-24 11:56:07 +00:00
|
|
|
static float channel_colormanage_noop(float value)
|
|
|
|
|
{
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
|
2011-12-17 00:52:36 +00:00
|
|
|
{
|
2012-06-12 08:50:40 +00:00
|
|
|
unsigned char *rect_uchar;
|
2013-01-15 10:00:55 +00:00
|
|
|
float *rect_float, from_straight[4];
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-06-12 08:10:34 +00:00
|
|
|
unsigned int subsampling_dx = parameters->subsampling_dx;
|
|
|
|
|
unsigned int subsampling_dy = parameters->subsampling_dy;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-06-12 08:10:34 +00:00
|
|
|
unsigned int i, i_next, numcomps, w, h, prec;
|
|
|
|
|
unsigned int y;
|
|
|
|
|
int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */
|
2009-01-24 10:19:29 +00:00
|
|
|
OPJ_COLOR_SPACE color_space;
|
2012-05-16 09:26:37 +00:00
|
|
|
opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */
|
|
|
|
|
opj_image_t *image = NULL;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-09-24 11:56:07 +00:00
|
|
|
float (*chanel_colormanage_cb)(float);
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
img_fol_t img_fol; /* only needed for cinema presets */
|
2012-04-29 15:47:02 +00:00
|
|
|
memset(&img_fol, 0, sizeof(img_fol_t));
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2017-08-10 14:11:18 +02:00
|
|
|
if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) {
|
2012-09-24 11:56:07 +00:00
|
|
|
/* float buffer was managed already, no need in color space conversion */
|
|
|
|
|
chanel_colormanage_cb = channel_colormanage_noop;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* standard linear-to-srgb conversion if float buffer wasn't managed */
|
|
|
|
|
chanel_colormanage_cb = linearrgb_to_srgb;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 13:58:17 +02:00
|
|
|
if (ibuf->foptions.flag & JP2_CINE) {
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
if (ibuf->x == 4096 || ibuf->y == 2160)
|
2016-07-12 17:38:26 +02:00
|
|
|
parameters->cp_cinema = CINEMA4K_24;
|
2009-01-24 10:19:29 +00:00
|
|
|
else {
|
2015-07-13 13:58:17 +02:00
|
|
|
if (ibuf->foptions.flag & JP2_CINE_48FPS) {
|
2016-07-12 17:38:26 +02:00
|
|
|
parameters->cp_cinema = CINEMA2K_48;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2016-07-12 17:38:26 +02:00
|
|
|
parameters->cp_cinema = CINEMA2K_24;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
if (parameters->cp_cinema) {
|
2012-05-16 09:26:37 +00:00
|
|
|
img_fol.rates = (float *)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates");
|
|
|
|
|
for (i = 0; i < parameters->tcp_numlayers; i++) {
|
2009-01-24 10:19:29 +00:00
|
|
|
img_fol.rates[i] = parameters->tcp_rates[i];
|
|
|
|
|
}
|
|
|
|
|
cinema_parameters(parameters);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
color_space = (ibuf->foptions.flag & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB;
|
2012-05-16 09:26:37 +00:00
|
|
|
prec = 12;
|
|
|
|
|
numcomps = 3;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-10-21 05:46:41 +00:00
|
|
|
else {
|
2009-01-24 10:19:29 +00:00
|
|
|
/* Get settings from the imbuf */
|
2016-07-12 17:38:26 +02:00
|
|
|
color_space = (ibuf->foptions.flag & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2015-07-13 13:58:17 +02:00
|
|
|
if (ibuf->foptions.flag & JP2_16BIT) prec = 16;
|
|
|
|
|
else if (ibuf->foptions.flag & JP2_12BIT) prec = 12;
|
2012-05-16 09:26:37 +00:00
|
|
|
else prec = 8;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* 32bit images == alpha channel */
|
|
|
|
|
/* grayscale not supported yet */
|
2012-05-16 09:26:37 +00:00
|
|
|
numcomps = (ibuf->planes == 32) ? 4 : 3;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
w = ibuf->x;
|
|
|
|
|
h = ibuf->y;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* initialize image components */
|
2012-06-11 18:43:16 +00:00
|
|
|
memset(&cmptparm, 0, 4 * sizeof(opj_image_cmptparm_t));
|
2012-03-24 06:38:07 +00:00
|
|
|
for (i = 0; i < numcomps; i++) {
|
2009-01-24 10:19:29 +00:00
|
|
|
cmptparm[i].prec = prec;
|
|
|
|
|
cmptparm[i].bpp = prec;
|
|
|
|
|
cmptparm[i].sgnd = 0;
|
|
|
|
|
cmptparm[i].dx = subsampling_dx;
|
|
|
|
|
cmptparm[i].dy = subsampling_dy;
|
|
|
|
|
cmptparm[i].w = w;
|
|
|
|
|
cmptparm[i].h = h;
|
|
|
|
|
}
|
|
|
|
|
/* create the image */
|
|
|
|
|
image = opj_image_create(numcomps, &cmptparm[0], color_space);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!image) {
|
2009-01-24 10:19:29 +00:00
|
|
|
printf("Error: opj_image_create() failed\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set image offset and reference grid */
|
|
|
|
|
image->x0 = parameters->image_offset_x0;
|
|
|
|
|
image->y0 = parameters->image_offset_y0;
|
2012-06-11 18:43:16 +00:00
|
|
|
image->x1 = image->x0 + (w - 1) * subsampling_dx + 1 + image->x0;
|
|
|
|
|
image->y1 = image->y0 + (h - 1) * subsampling_dy + 1 + image->y0;
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
/* set image data */
|
2012-06-12 08:50:40 +00:00
|
|
|
rect_uchar = (unsigned char *) ibuf->rect;
|
2012-05-16 09:26:37 +00:00
|
|
|
rect_float = ibuf->rect_float;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-06-12 08:10:34 +00:00
|
|
|
/* set the destination channels */
|
|
|
|
|
r = image->comps[0].data;
|
|
|
|
|
g = image->comps[1].data;
|
|
|
|
|
b = image->comps[2].data;
|
|
|
|
|
a = (numcomps == 4) ? image->comps[3].data : NULL;
|
|
|
|
|
|
2012-06-12 08:50:40 +00:00
|
|
|
if (rect_float && rect_uchar && prec == 8) {
|
2009-01-24 10:19:29 +00:00
|
|
|
/* No need to use the floating point buffer, just write the 8 bits from the char buffer */
|
2012-05-16 09:26:37 +00:00
|
|
|
rect_float = NULL;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rect_float) {
|
2013-02-22 09:20:22 +00:00
|
|
|
int channels_in_float = ibuf->channels ? ibuf->channels : 4;
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
switch (prec) {
|
2012-05-16 09:26:37 +00:00
|
|
|
case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */
|
2012-06-12 08:10:34 +00:00
|
|
|
if (numcomps == 4) {
|
2013-02-22 09:20:22 +00:00
|
|
|
if (channels_in_float == 4) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float)
|
|
|
|
|
{
|
|
|
|
|
premul_to_straight_v4_v4(from_straight, rect_float);
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
|
|
|
|
|
a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]);
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else if (channels_in_float == 3) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
|
|
|
|
|
a[i] = 255;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = b[i] = r[i];
|
|
|
|
|
a[i] = 255;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2012-06-12 08:10:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2013-02-22 09:20:22 +00:00
|
|
|
if (channels_in_float == 4) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float)
|
|
|
|
|
{
|
|
|
|
|
premul_to_straight_v4_v4(from_straight, rect_float);
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else if (channels_in_float == 3) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = b[i] = r[i];
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
case 12:
|
2012-06-12 08:10:34 +00:00
|
|
|
if (numcomps == 4) {
|
2013-02-22 09:20:22 +00:00
|
|
|
if (channels_in_float == 4) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float)
|
|
|
|
|
{
|
|
|
|
|
premul_to_straight_v4_v4(from_straight, rect_float);
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
|
|
|
|
|
a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]);
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else if (channels_in_float == 3) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
|
|
|
|
|
a[i] = 4095;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = b[i] = r[i];
|
|
|
|
|
a[i] = 4095;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2012-06-12 08:10:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2013-02-22 09:20:22 +00:00
|
|
|
if (channels_in_float == 4) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float)
|
|
|
|
|
{
|
|
|
|
|
premul_to_straight_v4_v4(from_straight, rect_float);
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else if (channels_in_float == 3) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = b[i] = r[i];
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2012-06-12 08:10:34 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
case 16:
|
2012-06-12 08:10:34 +00:00
|
|
|
if (numcomps == 4) {
|
2013-02-24 20:33:21 +00:00
|
|
|
if (channels_in_float == 4) {
|
2013-02-22 09:20:22 +00:00
|
|
|
PIXEL_LOOPER_BEGIN(rect_float)
|
|
|
|
|
{
|
|
|
|
|
premul_to_straight_v4_v4(from_straight, rect_float);
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
|
|
|
|
|
a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]);
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else if (channels_in_float == 3) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
|
|
|
|
|
a[i] = 65535;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = b[i] = r[i];
|
|
|
|
|
a[i] = 65535;
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2012-06-12 08:10:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2013-02-22 09:20:22 +00:00
|
|
|
if (channels_in_float == 4) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN(rect_float)
|
|
|
|
|
{
|
|
|
|
|
premul_to_straight_v4_v4(from_straight, rect_float);
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else if (channels_in_float == 3) {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
|
|
|
|
|
b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
|
|
|
|
|
{
|
|
|
|
|
r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
|
|
|
|
|
g[i] = b[i] = r[i];
|
|
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2009-01-24 10:19:29 +00:00
|
|
|
/* just use rect*/
|
|
|
|
|
switch (prec) {
|
2012-05-16 09:26:37 +00:00
|
|
|
case 8:
|
2012-06-12 08:10:34 +00:00
|
|
|
if (numcomps == 4) {
|
2012-06-12 08:50:40 +00:00
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar)
|
2012-06-12 08:10:34 +00:00
|
|
|
{
|
2012-06-12 08:50:40 +00:00
|
|
|
r[i] = rect_uchar[0];
|
|
|
|
|
g[i] = rect_uchar[1];
|
|
|
|
|
b[i] = rect_uchar[2];
|
|
|
|
|
a[i] = rect_uchar[3];
|
2012-06-12 08:10:34 +00:00
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2012-06-12 08:50:40 +00:00
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar)
|
2012-06-12 08:10:34 +00:00
|
|
|
{
|
2012-06-12 08:50:40 +00:00
|
|
|
r[i] = rect_uchar[0];
|
|
|
|
|
g[i] = rect_uchar[1];
|
|
|
|
|
b[i] = rect_uchar[2];
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2012-06-12 08:10:34 +00:00
|
|
|
PIXEL_LOOPER_END;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */
|
2012-06-12 08:10:34 +00:00
|
|
|
if (numcomps == 4) {
|
2012-06-12 08:50:40 +00:00
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar)
|
2012-06-12 08:10:34 +00:00
|
|
|
{
|
2012-06-12 08:50:40 +00:00
|
|
|
r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]);
|
|
|
|
|
g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]);
|
|
|
|
|
b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]);
|
|
|
|
|
a[i] = UPSAMPLE_8_TO_12(rect_uchar[3]);
|
2012-06-12 08:10:34 +00:00
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2012-06-12 08:50:40 +00:00
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar)
|
2012-06-12 08:10:34 +00:00
|
|
|
{
|
2012-06-12 08:50:40 +00:00
|
|
|
r[i] = UPSAMPLE_8_TO_12(rect_uchar[0]);
|
|
|
|
|
g[i] = UPSAMPLE_8_TO_12(rect_uchar[1]);
|
|
|
|
|
b[i] = UPSAMPLE_8_TO_12(rect_uchar[2]);
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2012-06-12 08:10:34 +00:00
|
|
|
PIXEL_LOOPER_END;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2012-06-12 08:10:34 +00:00
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
case 16:
|
2012-06-12 08:10:34 +00:00
|
|
|
if (numcomps == 4) {
|
2012-06-12 08:50:40 +00:00
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar)
|
2012-06-12 08:10:34 +00:00
|
|
|
{
|
2012-06-12 08:50:40 +00:00
|
|
|
r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]);
|
|
|
|
|
g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]);
|
|
|
|
|
b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]);
|
|
|
|
|
a[i] = UPSAMPLE_8_TO_16(rect_uchar[3]);
|
2012-06-12 08:10:34 +00:00
|
|
|
}
|
|
|
|
|
PIXEL_LOOPER_END;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2012-06-12 08:50:40 +00:00
|
|
|
PIXEL_LOOPER_BEGIN(rect_uchar)
|
2012-06-12 08:10:34 +00:00
|
|
|
{
|
2012-06-12 08:50:40 +00:00
|
|
|
r[i] = UPSAMPLE_8_TO_16(rect_uchar[0]);
|
|
|
|
|
g[i] = UPSAMPLE_8_TO_16(rect_uchar[1]);
|
|
|
|
|
b[i] = UPSAMPLE_8_TO_16(rect_uchar[2]);
|
2012-05-16 09:26:37 +00:00
|
|
|
}
|
2012-06-12 08:10:34 +00:00
|
|
|
PIXEL_LOOPER_END;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
2012-05-16 09:26:37 +00:00
|
|
|
break;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Decide if MCT should be used */
|
|
|
|
|
parameters->tcp_mct = image->numcomps == 3 ? 1 : 0;
|
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (parameters->cp_cinema) {
|
2012-04-29 15:47:02 +00:00
|
|
|
cinema_setup_encoder(parameters, image, &img_fol);
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (img_fol.rates)
|
|
|
|
|
MEM_freeN(img_fol.rates);
|
|
|
|
|
|
|
|
|
|
return image;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */
|
2016-07-12 17:38:26 +02:00
|
|
|
int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags)
|
2011-12-17 00:52:36 +00:00
|
|
|
{
|
2015-07-13 13:58:17 +02:00
|
|
|
int quality = ibuf->foptions.quality;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
int bSuccess;
|
2012-05-16 09:26:37 +00:00
|
|
|
opj_cparameters_t parameters; /* compression parameters */
|
2016-07-12 17:38:26 +02:00
|
|
|
opj_event_mgr_t event_mgr; /* event manager */
|
2009-01-24 10:19:29 +00:00
|
|
|
opj_image_t *image = NULL;
|
|
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
(void)flags; /* unused */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* configure the event callbacks (not required)
|
|
|
|
|
* setting of each callback is optional
|
|
|
|
|
*/
|
|
|
|
|
memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
|
|
|
|
|
event_mgr.error_handler = error_callback;
|
|
|
|
|
event_mgr.warning_handler = warning_callback;
|
|
|
|
|
event_mgr.info_handler = info_callback;
|
|
|
|
|
|
2009-01-24 10:19:29 +00:00
|
|
|
/* set encoding parameters to default values */
|
|
|
|
|
opj_set_default_encoder_parameters(¶meters);
|
|
|
|
|
|
|
|
|
|
/* compression ratio */
|
|
|
|
|
/* invert range, from 10-100, 100-1
|
2012-03-09 18:28:30 +00:00
|
|
|
* where jpeg see's 1 and highest quality (lossless) and 100 is very low quality*/
|
2012-05-16 09:26:37 +00:00
|
|
|
parameters.tcp_rates[0] = ((100 - quality) / 90.0f * 99.0f) + 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
|
2012-07-07 22:51:57 +00:00
|
|
|
parameters.tcp_numlayers = 1; /* only one resolution */
|
2009-01-24 10:19:29 +00:00
|
|
|
parameters.cp_disto_alloc = 1;
|
|
|
|
|
|
2012-05-16 09:26:37 +00:00
|
|
|
image = ibuftoimage(ibuf, ¶meters);
|
2016-07-12 17:38:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
{ /* JP2 format output */
|
|
|
|
|
int codestream_length;
|
|
|
|
|
opj_cio_t *cio = NULL;
|
|
|
|
|
FILE *f = NULL;
|
|
|
|
|
opj_cinfo_t *cinfo = NULL;
|
2009-01-24 10:19:29 +00:00
|
|
|
|
|
|
|
|
/* get a JP2 compressor handle */
|
2016-07-12 17:38:26 +02:00
|
|
|
if (ibuf->foptions.flag & JP2_JP2)
|
|
|
|
|
cinfo = opj_create_compress(CODEC_JP2);
|
|
|
|
|
else if (ibuf->foptions.flag & JP2_J2K)
|
|
|
|
|
cinfo = opj_create_compress(CODEC_J2K);
|
|
|
|
|
else
|
|
|
|
|
BLI_assert(!"Unsupported codec was specified in save settings");
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* catch events using our callbacks and give a local context */
|
|
|
|
|
opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-06-09 21:56:29 +10:00
|
|
|
/* setup the encoder parameters using the current image and using user parameters */
|
2016-07-12 17:38:26 +02:00
|
|
|
opj_setup_encoder(cinfo, ¶meters, image);
|
2009-01-24 10:19:29 +00:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* open a byte stream for writing */
|
|
|
|
|
/* allocate memory for all tiles */
|
|
|
|
|
cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
|
2016-06-09 21:56:29 +10:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* encode the image */
|
|
|
|
|
bSuccess = opj_encode(cinfo, cio, image, NULL); /* last arg used to be parameters.index but this deprecated */
|
|
|
|
|
|
|
|
|
|
if (!bSuccess) {
|
|
|
|
|
opj_cio_close(cio);
|
|
|
|
|
fprintf(stderr, "failed to encode image\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
codestream_length = cio_tell(cio);
|
2016-06-09 21:56:29 +10:00
|
|
|
|
2016-07-12 17:38:26 +02:00
|
|
|
/* write the buffer to disk */
|
|
|
|
|
f = BLI_fopen(name, "wb");
|
|
|
|
|
|
|
|
|
|
if (!f) {
|
|
|
|
|
fprintf(stderr, "failed to open %s for writing\n", name);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
fwrite(cio->buffer, 1, codestream_length, f);
|
|
|
|
|
fclose(f);
|
|
|
|
|
fprintf(stderr, "Generated outfile %s\n", name);
|
|
|
|
|
/* close and free the byte stream */
|
|
|
|
|
opj_cio_close(cio);
|
|
|
|
|
|
|
|
|
|
/* free remaining compression structures */
|
|
|
|
|
opj_destroy_compress(cinfo);
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free image data */
|
2016-07-12 17:38:26 +02:00
|
|
|
opj_image_destroy(image);
|
|
|
|
|
|
|
|
|
|
return 1;
|
2009-01-24 10:19:29 +00:00
|
|
|
}
|