* Now honours the orientation as specified in the EXIF tags; not very well tested, so
it might happen that some rotations don't come out as expected... * This orientation can be overridden with a special "exif:orientation" setting passed via the ioExtension message. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20635 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
ddcd63762f
commit
9e34f742ae
|
@ -193,15 +193,48 @@ LoadSettings(jpeg_settings *settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - conversion routines
|
static bool
|
||||||
|
x_flipped(int32 orientation)
|
||||||
|
{
|
||||||
|
return orientation == 2 || orientation == 3
|
||||||
|
|| orientation == 6 || orientation == 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
y_flipped(int32 orientation)
|
||||||
|
{
|
||||||
|
return orientation == 3 || orientation == 4
|
||||||
|
|| orientation == 7 || orientation == 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32
|
||||||
|
dest_index(uint32 width, uint32 height, uint32 x, uint32 y, int32 orientation)
|
||||||
|
{
|
||||||
|
if (orientation > 4) {
|
||||||
|
uint32 temp = x;
|
||||||
|
x = y;
|
||||||
|
y = temp;
|
||||||
|
}
|
||||||
|
if (y_flipped(orientation))
|
||||||
|
y = height - 1 - y;
|
||||||
|
if (x_flipped(orientation))
|
||||||
|
x = width - 1 - x;
|
||||||
|
|
||||||
|
return y * width + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - conversion for compression
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_gray1_to_gray8(uchar *in, uchar *out, int in_bytes)
|
convert_from_gray1_to_gray8(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
unsigned char c = in[index++];
|
unsigned char c = in[index++];
|
||||||
for (int b = 128; b; b = b>>1) {
|
for (int b = 128; b; b = b>>1) {
|
||||||
unsigned char color;
|
unsigned char color;
|
||||||
|
@ -216,11 +249,11 @@ convert_from_gray1_to_gray8(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_gray1_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_gray1_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
unsigned char c = in[index++];
|
unsigned char c = in[index++];
|
||||||
for (int b = 128; b; b = b>>1) {
|
for (int b = 128; b; b = b>>1) {
|
||||||
unsigned char color;
|
unsigned char color;
|
||||||
|
@ -237,12 +270,12 @@ convert_from_gray1_to_24(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_cmap8_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_cmap8_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
const color_map * map = system_colors();
|
const color_map * map = system_colors();
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
rgb_color color = map->color_list[in[index++]];
|
rgb_color color = map->color_list[in[index++]];
|
||||||
|
|
||||||
out[index2++] = color.red;
|
out[index2++] = color.red;
|
||||||
|
@ -253,12 +286,12 @@ convert_from_cmap8_to_24(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_15_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_15_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
int16 in_pixel;
|
int16 in_pixel;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
in_pixel = in[index] | (in[index+1] << 8);
|
in_pixel = in[index] | (in[index+1] << 8);
|
||||||
index += 2;
|
index += 2;
|
||||||
|
|
||||||
|
@ -270,12 +303,12 @@ convert_from_15_to_24(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_15b_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_15b_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
int16 in_pixel;
|
int16 in_pixel;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
in_pixel = in[index+1] | (in[index] << 8);
|
in_pixel = in[index+1] | (in[index] << 8);
|
||||||
index += 2;
|
index += 2;
|
||||||
|
|
||||||
|
@ -287,12 +320,12 @@ convert_from_15b_to_24(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_16_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_16_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
int16 in_pixel;
|
int16 in_pixel;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
in_pixel = in[index] | (in[index+1] << 8);
|
in_pixel = in[index] | (in[index+1] << 8);
|
||||||
index += 2;
|
index += 2;
|
||||||
|
|
||||||
|
@ -304,12 +337,12 @@ convert_from_16_to_24(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_16b_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_16b_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
int16 in_pixel;
|
int16 in_pixel;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
in_pixel = in[index+1] | (in[index] << 8);
|
in_pixel = in[index+1] | (in[index] << 8);
|
||||||
index += 2;
|
index += 2;
|
||||||
|
|
||||||
|
@ -321,11 +354,11 @@ convert_from_16b_to_24(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_24_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_24_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 index2 = 0;
|
int32 index2 = 0;
|
||||||
while (index < in_bytes) {
|
while (index < inRowBytes) {
|
||||||
out[index2++] = in[index+2];
|
out[index2++] = in[index+2];
|
||||||
out[index2++] = in[index+1];
|
out[index2++] = in[index+1];
|
||||||
out[index2++] = in[index];
|
out[index2++] = in[index];
|
||||||
|
@ -335,80 +368,94 @@ convert_from_24_to_24(uchar *in, uchar *out, int in_bytes)
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_32_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_32_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
for (int32 i = 0; i < inRowBytes; i++) {
|
||||||
int32 index2 = 0;
|
out[0] = in[2];
|
||||||
while (index < in_bytes) {
|
out[1] = in[1];
|
||||||
out[index2++] = in[index+2];
|
out[2] = in[0];
|
||||||
out[index2++] = in[index+1];
|
|
||||||
out[index2++] = in[index];
|
in += 4;
|
||||||
index+=4;
|
out += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_32b_to_24(uchar *in, uchar *out, int in_bytes)
|
convert_from_32b_to_24(uint8* in, uint8* out, int32 inRowBytes)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
for (int32 i = 0; i < inRowBytes; i++) {
|
||||||
int32 index2 = 0;
|
out[1] = in[0];
|
||||||
while (index < in_bytes) {
|
out[2] = in[1];
|
||||||
index++;
|
out[3] = in[2];
|
||||||
out[index2++] = in[index++];
|
|
||||||
out[index2++] = in[index++];
|
in += 4;
|
||||||
out[index2++] = in[index++];
|
out += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - conversion for decompression
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
convert_from_CMYK_to_32_photoshop(uchar *in, uchar *out, int out_bytes)
|
convert_from_CMYK_to_32_photoshop(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
for (int32 i = 0; i < inRowBytes; i += 4) {
|
||||||
int32 index2 = 0;
|
int32 black = in[3];
|
||||||
int32 black = 0;
|
out[0] = in[2] * black / 255;
|
||||||
while (index < out_bytes) {
|
out[1] = in[1] * black / 255;
|
||||||
black = in[index2+3];
|
out[2] = in[0] * black / 255;
|
||||||
out[index++] = in[index2+2]*black/255;
|
out[3] = 255;
|
||||||
out[index++] = in[index2+1]*black/255;
|
|
||||||
out[index++] = in[index2]*black/255;
|
in += 4;
|
||||||
out[index++] = 255;
|
out += xStep;
|
||||||
index2 += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! !!! UNTESTED !!!
|
//! !!! UNTESTED !!!
|
||||||
inline void
|
inline void
|
||||||
convert_from_CMYK_to_32(uchar *in, uchar *out, int out_bytes)
|
convert_from_CMYK_to_32(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
for (int32 i = 0; i < inRowBytes; i += 4) {
|
||||||
int32 index2 = 0;
|
int32 black = 255 - in[3];
|
||||||
int32 black = 0;
|
out[0] = ((255 - in[2]) * black) / 255;
|
||||||
while (index < out_bytes) {
|
out[1] = ((255 - in[1]) * black) / 255;
|
||||||
black = 255 - in[index2+3];
|
out[2] = ((255 - in[0]) * black) / 255;
|
||||||
out[index++] = ((255-in[index2+2])*black)/255;
|
out[3] = 255;
|
||||||
out[index++] = ((255-in[index2+1])*black)/255;
|
|
||||||
out[index++] = ((255-in[index2])*black)/255;
|
in += 4;
|
||||||
out[index++] = 255;
|
out += xStep;
|
||||||
index2 += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! RGB24 8:8:8 to xRGB 8:8:8:8
|
//! RGB24 8:8:8 to xRGB 8:8:8:8
|
||||||
inline void
|
inline void
|
||||||
convert_from_24_to_32(uchar *in, uchar *out, int out_bytes)
|
convert_from_24_to_32(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
for (int32 i = 0; i < inRowBytes; i += 3) {
|
||||||
int32 index2 = 0;
|
out[0] = in[2];
|
||||||
while (index < out_bytes) {
|
out[1] = in[1];
|
||||||
out[index++] = in[index2+2];
|
out[2] = in[0];
|
||||||
out[index++] = in[index2+1];
|
out[3] = 255;
|
||||||
out[index++] = in[index2];
|
|
||||||
out[index++] = 255;
|
in += 3;
|
||||||
index2 += 3;
|
out += xStep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! 8-bit to 8-bit, only need when rotating the image
|
||||||
|
void
|
||||||
|
translate_8(uint8* in, uint8* out, int32 inRowBytes, int32 xStep)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < inRowBytes; i++) {
|
||||||
|
out[0] = in[0];
|
||||||
|
|
||||||
|
in++;
|
||||||
|
out += xStep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,7 +1181,8 @@ Compress(BPositionIO *in, BPositionIO *out)
|
||||||
|
|
||||||
// Function pointer to convert function
|
// Function pointer to convert function
|
||||||
// It will point to proper function if needed
|
// It will point to proper function if needed
|
||||||
void (*converter)(uchar *inscanline, uchar *outscanline, int inrow_bytes) = NULL;
|
void (*converter)(uchar *inscanline, uchar *outscanline,
|
||||||
|
int32 inRowBytes) = NULL;
|
||||||
|
|
||||||
// Default color info
|
// Default color info
|
||||||
J_COLOR_SPACE jpg_color_space = JCS_RGB;
|
J_COLOR_SPACE jpg_color_space = JCS_RGB;
|
||||||
|
@ -1304,7 +1352,7 @@ Compress(BPositionIO *in, BPositionIO *out)
|
||||||
|
|
||||||
// Convert if needed
|
// Convert if needed
|
||||||
if (converter != NULL)
|
if (converter != NULL)
|
||||||
converter(in_scanline, out_scanline, in_row_bytes-padding);
|
converter(in_scanline, out_scanline, in_row_bytes - padding);
|
||||||
|
|
||||||
// Write scanline
|
// Write scanline
|
||||||
jpeg_write_scanlines(&cinfo, &writeline, 1);
|
jpeg_write_scanlines(&cinfo, &writeline, 1);
|
||||||
|
@ -1331,8 +1379,10 @@ Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
|
||||||
jpeg_create_decompress(&cinfo);
|
jpeg_create_decompress(&cinfo);
|
||||||
be_jpeg_stdio_src(&cinfo, in);
|
be_jpeg_stdio_src(&cinfo, in);
|
||||||
|
|
||||||
|
#if 1
|
||||||
jpeg_save_markers(&cinfo, MARKER_EXIF, 131072);
|
jpeg_save_markers(&cinfo, MARKER_EXIF, 131072);
|
||||||
// make sure the EXIF tag is stored
|
// make sure the EXIF tag is stored
|
||||||
|
#endif
|
||||||
|
|
||||||
// Read info about image
|
// Read info about image
|
||||||
jpeg_read_header(&cinfo, TRUE);
|
jpeg_read_header(&cinfo, TRUE);
|
||||||
|
@ -1363,7 +1413,7 @@ Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
|
||||||
// Function pointer to convert function
|
// Function pointer to convert function
|
||||||
// It will point to proper function if needed
|
// It will point to proper function if needed
|
||||||
void (*converter)(uchar *inScanLine, uchar *outScanLine,
|
void (*converter)(uchar *inScanLine, uchar *outScanLine,
|
||||||
int inRowBytes) = convert_from_24_to_32;
|
int32 inRowBytes, int32 xStep) = convert_from_24_to_32;
|
||||||
|
|
||||||
// If color space isn't rgb
|
// If color space isn't rgb
|
||||||
if (cinfo.out_color_space != JCS_RGB) {
|
if (cinfo.out_color_space != JCS_RGB) {
|
||||||
|
@ -1377,7 +1427,7 @@ Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
|
||||||
// Grayscale
|
// Grayscale
|
||||||
outColorSpace = B_GRAY8;
|
outColorSpace = B_GRAY8;
|
||||||
outColorComponents = 1;
|
outColorComponents = 1;
|
||||||
converter = NULL;
|
converter = translate_8;
|
||||||
} else {
|
} else {
|
||||||
// RGB
|
// RGB
|
||||||
cinfo.out_color_space = JCS_RGB;
|
cinfo.out_color_space = JCS_RGB;
|
||||||
|
@ -1409,20 +1459,42 @@ Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
|
||||||
// Initialize decompression
|
// Initialize decompression
|
||||||
jpeg_start_decompress(&cinfo);
|
jpeg_start_decompress(&cinfo);
|
||||||
|
|
||||||
|
// retrieve orientation from settings/EXIF
|
||||||
int32 orientation;
|
int32 orientation;
|
||||||
if (exif.FindInt32("Orientation", &orientation) != B_OK)
|
if (ioExtension == NULL
|
||||||
orientation = 1;
|
|| ioExtension->FindInt32("exif:orientation", &orientation) != B_OK) {
|
||||||
|
if (exif.FindInt32("Orientation", &orientation) != B_OK)
|
||||||
// Initialize this bounds rect to the size of your image
|
orientation = 1;
|
||||||
BRect bounds(0, 0, cinfo.output_width - 1, cinfo.output_height - 1);
|
|
||||||
if (orientation & 4) {
|
|
||||||
// image is rotated
|
|
||||||
bounds.right = cinfo.output_height - 1;
|
|
||||||
bounds.bottom = cinfo.output_width - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (orientation != 1 && converter == NULL)
|
||||||
|
converter = translate_8;
|
||||||
|
|
||||||
|
int32 outputWidth = orientation > 4 ? cinfo.output_height : cinfo.output_width;
|
||||||
|
int32 outputHeight = orientation > 4 ? cinfo.output_width : cinfo.output_height;
|
||||||
|
|
||||||
|
int32 destOffset = dest_index(outputWidth, outputHeight,
|
||||||
|
0, 0, orientation) * outColorComponents;
|
||||||
|
int32 xStep = dest_index(outputWidth, outputHeight,
|
||||||
|
1, 0, orientation) * outColorComponents - destOffset;
|
||||||
|
int32 yStep = dest_index(outputWidth, outputHeight,
|
||||||
|
0, 1, orientation) * outColorComponents - destOffset;
|
||||||
|
bool needAll = orientation != 1;
|
||||||
|
|
||||||
|
// Initialize this bounds rect to the size of your image
|
||||||
|
BRect bounds(0, 0, outputWidth - 1, outputHeight - 1);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("destOffset = %ld, xStep = %ld, yStep = %ld, input: %ld x %ld, output: %ld x %ld, orientation %ld\n",
|
||||||
|
destOffset, xStep, yStep, (int32)cinfo.output_width, (int32)cinfo.output_height,
|
||||||
|
bounds.IntegerWidth() + 1, bounds.IntegerHeight() + 1, orientation);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Bytes count in one line of image (scanline)
|
// Bytes count in one line of image (scanline)
|
||||||
int64 rowBytes = cinfo.output_width * outColorComponents;
|
int32 inRowBytes = cinfo.output_width * cinfo.output_components;
|
||||||
|
int32 rowBytes = (bounds.IntegerWidth() + 1) * outColorComponents;
|
||||||
|
int32 dataSize = cinfo.output_width * cinfo.output_height
|
||||||
|
* outColorComponents;
|
||||||
|
|
||||||
// Fill out the B_TRANSLATOR_BITMAP's header
|
// Fill out the B_TRANSLATOR_BITMAP's header
|
||||||
TranslatorBitmap header;
|
TranslatorBitmap header;
|
||||||
|
@ -1433,7 +1505,7 @@ Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
|
||||||
header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
|
header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom);
|
||||||
header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(outColorSpace);
|
header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(outColorSpace);
|
||||||
header.rowBytes = B_HOST_TO_BENDIAN_INT32(rowBytes);
|
header.rowBytes = B_HOST_TO_BENDIAN_INT32(rowBytes);
|
||||||
header.dataSize = B_HOST_TO_BENDIAN_INT32(rowBytes * cinfo.output_height);
|
header.dataSize = B_HOST_TO_BENDIAN_INT32(dataSize);
|
||||||
|
|
||||||
// Write out the header
|
// Write out the header
|
||||||
status_t err = out->Write(&header, sizeof(TranslatorBitmap));
|
status_t err = out->Write(&header, sizeof(TranslatorBitmap));
|
||||||
|
@ -1443,39 +1515,53 @@ Decompress(BPositionIO *in, BPositionIO *out, BMessage* ioExtension)
|
||||||
return Error((j_common_ptr)&cinfo, B_ERROR);
|
return Error((j_common_ptr)&cinfo, B_ERROR);
|
||||||
|
|
||||||
// Declare scanlines
|
// Declare scanlines
|
||||||
JSAMPROW in_scanline = NULL;
|
JSAMPROW inScanLine = NULL;
|
||||||
JSAMPROW out_scanline = NULL;
|
uint8* dest = NULL;
|
||||||
JSAMPROW writeline; // Pointer to in_scanline or out_scanline (if there will be conversion)
|
uint8* destLine = NULL;
|
||||||
|
|
||||||
// Allocate scanline
|
// Allocate scanline
|
||||||
// Use libjpeg memory allocation functions, so in case of error it will free them itself
|
// Use libjpeg memory allocation functions, so in case of error it will free them itself
|
||||||
in_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
|
inScanLine = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
|
||||||
JPOOL_PERMANENT, rowBytes);
|
JPOOL_PERMANENT, inRowBytes);
|
||||||
|
|
||||||
// We need 2nd scanline storage only for conversion
|
// We need 2nd scanline storage only for conversion
|
||||||
if (converter != NULL) {
|
if (converter != NULL) {
|
||||||
// There will be conversion, allocate second scanline...
|
// There will be conversion, allocate second scanline...
|
||||||
// Use libjpeg memory allocation functions, so in case of error it will free them itself
|
// Use libjpeg memory allocation functions, so in case of error it will free
|
||||||
out_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
|
// them itself
|
||||||
JPOOL_PERMANENT, rowBytes);
|
dest = (uint8*)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo,
|
||||||
// ... and make it the one to write to file
|
JPOOL_PERMANENT, needAll ? dataSize : rowBytes);
|
||||||
writeline = out_scanline;
|
destLine = dest + destOffset;
|
||||||
} else
|
} else
|
||||||
writeline = in_scanline;
|
destLine = inScanLine;
|
||||||
|
|
||||||
while (cinfo.output_scanline < cinfo.output_height) {
|
while (cinfo.output_scanline < cinfo.output_height) {
|
||||||
// Read scanline
|
// Read scanline
|
||||||
jpeg_read_scanlines(&cinfo, &in_scanline, 1);
|
jpeg_read_scanlines(&cinfo, &inScanLine, 1);
|
||||||
|
|
||||||
// Convert if needed
|
// Convert if needed
|
||||||
if (converter != NULL)
|
if (converter != NULL)
|
||||||
converter(in_scanline, out_scanline, rowBytes);
|
converter(inScanLine, destLine, inRowBytes, xStep);
|
||||||
|
|
||||||
// Write the scanline buffer to the output stream
|
if (!needAll) {
|
||||||
err = out->Write(writeline, rowBytes);
|
// Write the scanline buffer to the output stream
|
||||||
if (err < rowBytes)
|
ssize_t bytesWritten = out->Write(destLine, rowBytes);
|
||||||
return err < B_OK ? Error((j_common_ptr)&cinfo, err)
|
if (bytesWritten < rowBytes) {
|
||||||
|
return bytesWritten < B_OK
|
||||||
|
? Error((j_common_ptr)&cinfo, bytesWritten)
|
||||||
|
: Error((j_common_ptr)&cinfo, B_ERROR);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
destLine += yStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needAll) {
|
||||||
|
ssize_t bytesWritten = out->Write(dest, dataSize);
|
||||||
|
if (bytesWritten < dataSize) {
|
||||||
|
return bytesWritten < B_OK
|
||||||
|
? Error((j_common_ptr)&cinfo, bytesWritten)
|
||||||
: Error((j_common_ptr)&cinfo, B_ERROR);
|
: Error((j_common_ptr)&cinfo, B_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_finish_decompress(&cinfo);
|
jpeg_finish_decompress(&cinfo);
|
||||||
|
|
Loading…
Reference in New Issue