diff options
Diffstat (limited to 'libkdcraw/libraw/src/write/file_write.cpp')
-rw-r--r-- | libkdcraw/libraw/src/write/file_write.cpp | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/libkdcraw/libraw/src/write/file_write.cpp b/libkdcraw/libraw/src/write/file_write.cpp new file mode 100644 index 0000000..bf17ea2 --- /dev/null +++ b/libkdcraw/libraw/src/write/file_write.cpp @@ -0,0 +1,338 @@ +/* -*- C++ -*- + * Copyright 2019-2021 LibRaw LLC ([email protected]) + * + LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder, + dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net. + LibRaw do not use RESTRICTED code from dcraw.c + + LibRaw is free software; you can redistribute it and/or modify + it under the terms of the one of two licenses as you choose: + +1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 + (See file LICENSE.LGPL provided in LibRaw distribution archive for details). + +2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 + (See file LICENSE.CDDL provided in LibRaw distribution archive for details). + + */ + +#include "../../internal/dcraw_defs.h" +#include <vector> + +int LibRaw::flip_index(int row, int col) +{ + if (flip & 4) + SWAP(row, col); + if (flip & 2) + row = iheight - 1 - row; + if (flip & 1) + col = iwidth - 1 - col; + return row * iwidth + col; +} + +void LibRaw::tiff_set(struct tiff_hdr *th, ushort *ntag, ushort tag, + ushort type, int count, int val) +{ + struct libraw_tiff_tag *tt; + int c; + + tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++; + tt->val.i = val; + if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE) && count <= 4) + FORC(4) tt->val.c[c] = val >> (c << 3); + else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII)) + { + count = int(strnlen((char *)th + val, count - 1)) + 1; + if (count <= 4) + FORC(4) tt->val.c[c] = ((char *)th)[val + c]; + } + else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && count <= 2) + FORC(2) tt->val.s[c] = val >> (c << 4); + tt->count = count; + tt->type = type; + tt->tag = tag; +} + +#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) + +void LibRaw::tiff_head(struct tiff_hdr *th, int full) +{ + int c, psize = 0; + struct tm *t; + + memset(th, 0, sizeof *th); + th->t_order = htonl(0x4d4d4949) >> 16; + th->magic = 42; + th->ifd = 10; + th->rat[0] = th->rat[2] = 300; + th->rat[1] = th->rat[3] = 1; + FORC(6) th->rat[4 + c] = 1000000; + th->rat[4] *= shutter; + th->rat[6] *= aperture; + th->rat[8] *= focal_len; + strncpy(th->t_desc, desc, 512); + strncpy(th->t_make, make, 64); + strncpy(th->t_model, model, 64); + strcpy(th->soft, "dcraw v" DCRAW_VERSION); + t = localtime(×tamp); + sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900, + t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + strncpy(th->t_artist, artist, 64); + if (full) + { + tiff_set(th, &th->ntag, 254, 4, 1, 0); + tiff_set(th, &th->ntag, 256, 4, 1, width); + tiff_set(th, &th->ntag, 257, 4, 1, height); + tiff_set(th, &th->ntag, 258, 3, colors, output_bps); + if (colors > 2) + th->tag[th->ntag - 1].val.i = TOFF(th->bps); + FORC4 th->bps[c] = output_bps; + tiff_set(th, &th->ntag, 259, 3, 1, 1); + tiff_set(th, &th->ntag, 262, 3, 1, 1 + (colors > 1)); + } + tiff_set(th, &th->ntag, 270, 2, 512, TOFF(th->t_desc)); + tiff_set(th, &th->ntag, 271, 2, 64, TOFF(th->t_make)); + tiff_set(th, &th->ntag, 272, 2, 64, TOFF(th->t_model)); + if (full) + { + if (oprof) + psize = ntohl(oprof[0]); + tiff_set(th, &th->ntag, 273, 4, 1, sizeof *th + psize); + tiff_set(th, &th->ntag, 277, 3, 1, colors); + tiff_set(th, &th->ntag, 278, 4, 1, height); + tiff_set(th, &th->ntag, 279, 4, 1, + height * width * colors * output_bps / 8); + } + else + tiff_set(th, &th->ntag, 274, 3, 1, "12435867"[flip] - '0'); + tiff_set(th, &th->ntag, 282, 5, 1, TOFF(th->rat[0])); + tiff_set(th, &th->ntag, 283, 5, 1, TOFF(th->rat[2])); + tiff_set(th, &th->ntag, 284, 3, 1, 1); + tiff_set(th, &th->ntag, 296, 3, 1, 2); + tiff_set(th, &th->ntag, 305, 2, 32, TOFF(th->soft)); + tiff_set(th, &th->ntag, 306, 2, 20, TOFF(th->date)); + tiff_set(th, &th->ntag, 315, 2, 64, TOFF(th->t_artist)); + tiff_set(th, &th->ntag, 34665, 4, 1, TOFF(th->nexif)); + if (psize) + tiff_set(th, &th->ntag, 34675, 7, psize, sizeof *th); + tiff_set(th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4])); + tiff_set(th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6])); + tiff_set(th, &th->nexif, 34855, 3, 1, iso_speed); + tiff_set(th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8])); + if (gpsdata[1]) + { + uchar latref[4] = { (uchar)(gpsdata[29]),0,0,0 }, + lonref[4] = { (uchar)(gpsdata[30]),0,0,0 }; + tiff_set(th, &th->ntag, 34853, 4, 1, TOFF(th->ngps)); + tiff_set(th, &th->ngps, 0, 1, 4, 0x202); + tiff_set(th, &th->ngps, 1, 2, 2, TOFF(latref)); + tiff_set(th, &th->ngps, 2, 5, 3, TOFF(th->gps[0])); + tiff_set(th, &th->ngps, 3, 2, 2, TOFF(lonref)); + tiff_set(th, &th->ngps, 4, 5, 3, TOFF(th->gps[6])); + tiff_set(th, &th->ngps, 5, 1, 1, gpsdata[31]); + tiff_set(th, &th->ngps, 6, 5, 1, TOFF(th->gps[18])); + tiff_set(th, &th->ngps, 7, 5, 3, TOFF(th->gps[12])); + tiff_set(th, &th->ngps, 18, 2, 12, TOFF(th->gps[20])); + tiff_set(th, &th->ngps, 29, 2, 12, TOFF(th->gps[23])); + memcpy(th->gps, gpsdata, sizeof th->gps); + } +} + +void LibRaw::jpeg_thumb_writer(FILE *tfp, char *t_humb, int t_humb_length) +{ + ushort exif[5]; + struct tiff_hdr th; + fputc(0xff, tfp); + fputc(0xd8, tfp); + if (strcmp(t_humb + 6, "Exif")) + { + memcpy(exif, "\xff\xe1 Exif\0\0", 10); + exif[1] = htons(8 + sizeof th); + fwrite(exif, 1, sizeof exif, tfp); + tiff_head(&th, 0); + fwrite(&th, 1, sizeof th, tfp); + } + fwrite(t_humb + 2, 1, t_humb_length - 2, tfp); +} +void LibRaw::write_ppm_tiff() +{ + try + { + struct tiff_hdr th; + ushort *ppm2; + int c, row, col, soff, rstep, cstep; + int perc, val, total, t_white = 0x2000; + + perc = width * height * auto_bright_thr; + + if (fuji_width) + perc /= 2; + if (!((highlight & ~2) || no_auto_bright)) + for (t_white = c = 0; c < colors; c++) + { + for (val = 0x2000, total = 0; --val > 32;) + if ((total += histogram[c][val]) > perc) + break; + if (t_white < val) + t_white = val; + } + gamma_curve(gamm[0], gamm[1], 2, (t_white << 3) / bright); + iheight = height; + iwidth = width; + if (flip & 4) + SWAP(height, width); + + std::vector<uchar> ppm(width * colors * output_bps / 8); + ppm2 = (ushort *)ppm.data(); + if (output_tiff) + { + tiff_head(&th, 1); + fwrite(&th, sizeof th, 1, ofp); + if (oprof) + fwrite(oprof, ntohl(oprof[0]), 1, ofp); + } + else if (colors > 3) + { + if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA) + fprintf(ofp, + "P7\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n# ISOSPEED=%d\n" + "# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n# MAKE=%s\n# MODEL=%s\n" + "WIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", + shutter, (int)timestamp, (int)iso_speed,aperture, + focal_len, make, model, + width, height, colors, (1 << output_bps) - 1, cdesc); + else + fprintf( + ofp, + "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", + width, height, colors, (1 << output_bps) - 1, cdesc); + } + else + { + if(imgdata.params.output_flags & LIBRAW_OUTPUT_FLAGS_PPMMETA) + fprintf(ofp, "P%d\n# EXPTIME=%0.5f\n# TIMESTAMP=%d\n" + "# ISOSPEED=%d\n# APERTURE=%0.1f\n# FOCALLEN=%0.1f\n" + "# MAKE=%s\n# MODEL=%s\n%d %d\n%d\n", + colors/2+5, + shutter, (int)timestamp, (int)iso_speed,aperture,focal_len, + make,model, + width, height, (1 << output_bps)-1); + else + fprintf(ofp, "P%d\n%d %d\n%d\n", colors / 2 + 5, width, height, + (1 << output_bps) - 1); + } + soff = flip_index(0, 0); + cstep = flip_index(0, 1) - soff; + rstep = flip_index(1, 0) - flip_index(0, width); + for (row = 0; row < height; row++, soff += rstep) + { + for (col = 0; col < width; col++, soff += cstep) + if (output_bps == 8) + FORCC ppm[col * colors + c] = curve[image[soff][c]] >> 8; + else + FORCC ppm2[col * colors + c] = curve[image[soff][c]]; + if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa) + libraw_swab(ppm2, width * colors * 2); + fwrite(ppm.data(), colors * output_bps / 8, width, ofp); + } + } + catch (...) + { + throw LIBRAW_EXCEPTION_ALLOC; // rethrow + } +} +#if 0 +void LibRaw::ppm_thumb() +{ + try + { + thumb_length = thumb_width * thumb_height * 3; + std::vector<char> thumb(thumb_length); + fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + fread(thumb.data(), 1, thumb_length, ifp); + fwrite(thumb.data(), 1, thumb_length, ofp); + } + catch (...) + { + throw LIBRAW_EXCEPTION_ALLOC; // rethrow + } +} + +void LibRaw::ppm16_thumb() +{ + try + { + unsigned i; + thumb_length = thumb_width * thumb_height * 3; + std::vector<char> thumb(thumb_length * 2, 0); + read_shorts((ushort *)thumb.data(), thumb_length); + for (i = 0; i < thumb_length; i++) + thumb[i] = ((ushort *)thumb.data())[i] >> 8; + fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + fwrite(thumb.data(), 1, thumb_length, ofp); + } + catch (...) + { + throw LIBRAW_EXCEPTION_ALLOC; // rethrow + } +} + +void LibRaw::layer_thumb() +{ + try + { + unsigned int i; + int c; + char map[][4] = { "012", "102" }; + + colors = thumb_misc >> 5 & 7; + thumb_length = thumb_width * thumb_height; + std::vector<char> thumb(colors * thumb_length, 0); + fprintf(ofp, "P%d\n%d %d\n255\n", 5 + (colors >> 1), thumb_width, + thumb_height); + fread(thumb.data(), thumb_length, colors, ifp); + for (i = 0; i < thumb_length; i++) + FORCC putc(thumb[i + thumb_length * (map[thumb_misc >> 8][c] - '0')], ofp); + } + catch (...) + { + throw LIBRAW_EXCEPTION_ALLOC; // rethrow + } +} + +void LibRaw::rollei_thumb() +{ + try + { + unsigned i; + thumb_length = thumb_width * thumb_height; + std::vector<ushort> thumb(thumb_length, 0); + fprintf(ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); + read_shorts(thumb.data(), thumb_length); + for (i = 0; i < thumb_length; i++) + { + putc(thumb[i] << 3, ofp); + putc(thumb[i] >> 5 << 2, ofp); + putc(thumb[i] >> 11 << 3, ofp); + } + } + catch (...) + { + throw LIBRAW_EXCEPTION_ALLOC; // rethrow + } +} + +void LibRaw::jpeg_thumb() +{ + try + { + std::vector<char> thumb(thumb_length); + fread(thumb.data(), 1, thumb_length, ifp); + jpeg_thumb_writer(ofp, thumb.data(), thumb_length); + } + catch (...) + { + throw LIBRAW_EXCEPTION_ALLOC; // rethrow + } +} +#endif |