File indexing completed on 2025-01-05 03:57:05
0001 /* -*- C++ -*- 0002 * Copyright 2019-2021 LibRaw LLC (info@libraw.org) 0003 * 0004 LibRaw is free software; you can redistribute it and/or modify 0005 it under the terms of the one of two licenses as you choose: 0006 0007 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 0008 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 0009 0010 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 0011 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 0012 0013 */ 0014 0015 #include "../../internal/libraw_cxx_defs.h" 0016 0017 libraw_processed_image_t *LibRaw::dcraw_make_mem_thumb(int *errcode) 0018 { 0019 if (!T.thumb) 0020 { 0021 if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 && 0022 load_raw == &LibRaw::broadcom_load_raw) // RPi 0023 ) 0024 { 0025 if (errcode) 0026 *errcode = LIBRAW_NO_THUMBNAIL; 0027 } 0028 else 0029 { 0030 if (errcode) 0031 *errcode = LIBRAW_OUT_OF_ORDER_CALL; 0032 } 0033 return NULL; 0034 } 0035 0036 if (T.tlength < 64u) 0037 { 0038 if (errcode) 0039 *errcode = EINVAL; 0040 return NULL; 0041 } 0042 0043 if (INT64(T.tlength) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB) 0044 { 0045 if (errcode) 0046 *errcode = LIBRAW_TOO_BIG; 0047 return NULL; 0048 } 0049 0050 if (T.tformat == LIBRAW_THUMBNAIL_BITMAP) 0051 { 0052 libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc( 0053 sizeof(libraw_processed_image_t) + T.tlength); 0054 0055 if (!ret) 0056 { 0057 if (errcode) 0058 *errcode = ENOMEM; 0059 return NULL; 0060 } 0061 0062 memset(ret, 0, sizeof(libraw_processed_image_t)); 0063 ret->type = LIBRAW_IMAGE_BITMAP; 0064 ret->height = T.theight; 0065 ret->width = T.twidth; 0066 if (T.tcolors > 0 && T.tcolors < 4) 0067 ret->colors = T.tcolors; 0068 else 0069 ret->colors = 3; // defaults 0070 ret->bits = 8; 0071 ret->data_size = T.tlength; 0072 memmove(ret->data, T.thumb, T.tlength); 0073 if (errcode) 0074 *errcode = 0; 0075 return ret; 0076 } 0077 else if (T.tformat == LIBRAW_THUMBNAIL_JPEG) 0078 { 0079 ushort exif[5]; 0080 int mk_exif = 0; 0081 if (strcmp(T.thumb + 6, "Exif")) 0082 mk_exif = 1; 0083 0084 int dsize = T.tlength + mk_exif * (sizeof(exif) + sizeof(tiff_hdr)); 0085 0086 libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc( 0087 sizeof(libraw_processed_image_t) + dsize); 0088 0089 if (!ret) 0090 { 0091 if (errcode) 0092 *errcode = ENOMEM; 0093 return NULL; 0094 } 0095 0096 memset(ret, 0, sizeof(libraw_processed_image_t)); 0097 0098 ret->type = LIBRAW_IMAGE_JPEG; 0099 ret->data_size = dsize; 0100 0101 ret->data[0] = 0xff; 0102 ret->data[1] = 0xd8; 0103 if (mk_exif) 0104 { 0105 struct tiff_hdr th; 0106 memcpy(exif, "\xff\xe1 Exif\0\0", 10); 0107 exif[1] = htons(8 + sizeof th); 0108 memmove(ret->data + 2, exif, sizeof(exif)); 0109 tiff_head(&th, 0); 0110 memmove(ret->data + (2 + sizeof(exif)), &th, sizeof(th)); 0111 memmove(ret->data + (2 + sizeof(exif) + sizeof(th)), T.thumb + 2, 0112 T.tlength - 2); 0113 } 0114 else 0115 { 0116 memmove(ret->data + 2, T.thumb + 2, T.tlength - 2); 0117 } 0118 if (errcode) 0119 *errcode = 0; 0120 return ret; 0121 } 0122 else 0123 { 0124 if (errcode) 0125 *errcode = LIBRAW_UNSUPPORTED_THUMBNAIL; 0126 return NULL; 0127 } 0128 } 0129 0130 // jlb 0131 // macros for copying pixels to either BGR or RGB formats 0132 #define FORBGR for (c = P1.colors - 1; c >= 0; c--) 0133 #define FORRGB for (c = 0; c < P1.colors; c++) 0134 0135 void LibRaw::get_mem_image_format(int *width, int *height, int *colors, 0136 int *bps) const 0137 0138 { 0139 *width = S.width; 0140 *height = S.height; 0141 if (imgdata.progress_flags < LIBRAW_PROGRESS_FUJI_ROTATE) 0142 { 0143 if (O.use_fuji_rotate) 0144 { 0145 if (IO.fuji_width) 0146 { 0147 int fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink; 0148 *width = (ushort)(fuji_width / sqrt(0.5)); 0149 *height = (ushort)((*height - fuji_width) / sqrt(0.5)); 0150 } 0151 else 0152 { 0153 if (S.pixel_aspect < 0.995) 0154 *height = (ushort)(*height / S.pixel_aspect + 0.5); 0155 if (S.pixel_aspect > 1.005) 0156 *width = (ushort)(*width * S.pixel_aspect + 0.5); 0157 } 0158 } 0159 } 0160 if (S.flip & 4) 0161 { 0162 std::swap(*width, *height); 0163 } 0164 *colors = P1.colors; 0165 *bps = O.output_bps; 0166 } 0167 0168 int LibRaw::copy_mem_image(void *scan0, int stride, int bgr) 0169 0170 { 0171 // the image memory pointed to by scan0 is assumed to be in the format 0172 // returned by get_mem_image_format 0173 if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < 0174 LIBRAW_PROGRESS_PRE_INTERPOLATE) 0175 return LIBRAW_OUT_OF_ORDER_CALL; 0176 0177 if (libraw_internal_data.output_data.histogram) 0178 { 0179 int perc, val, total, t_white = 0x2000, c; 0180 perc = S.width * S.height * O.auto_bright_thr; 0181 if (IO.fuji_width) 0182 perc /= 2; 0183 if (!((O.highlight & ~2) || O.no_auto_bright)) 0184 for (t_white = c = 0; c < P1.colors; c++) 0185 { 0186 for (val = 0x2000, total = 0; --val > 32;) 0187 if ((total += libraw_internal_data.output_data.histogram[c][val]) > 0188 perc) 0189 break; 0190 if (t_white < val) 0191 t_white = val; 0192 } 0193 gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright); 0194 } 0195 0196 int s_iheight = S.iheight; 0197 int s_iwidth = S.iwidth; 0198 int s_width = S.width; 0199 int s_hwight = S.height; 0200 0201 S.iheight = S.height; 0202 S.iwidth = S.width; 0203 0204 if (S.flip & 4) 0205 SWAP(S.height, S.width); 0206 uchar *ppm; 0207 ushort *ppm2; 0208 int c, row, col, soff, rstep, cstep; 0209 0210 soff = flip_index(0, 0); 0211 cstep = flip_index(0, 1) - soff; 0212 rstep = flip_index(1, 0) - flip_index(0, S.width); 0213 0214 for (row = 0; row < S.height; row++, soff += rstep) 0215 { 0216 uchar *bufp = ((uchar *)scan0) + row * stride; 0217 ppm2 = (ushort *)(ppm = bufp); 0218 // keep trivial decisions in the outer loop for speed 0219 if (bgr) 0220 { 0221 if (O.output_bps == 8) 0222 { 0223 for (col = 0; col < S.width; col++, soff += cstep) 0224 FORBGR *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8; 0225 } 0226 else 0227 { 0228 for (col = 0; col < S.width; col++, soff += cstep) 0229 FORBGR *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]]; 0230 } 0231 } 0232 else 0233 { 0234 if (O.output_bps == 8) 0235 { 0236 for (col = 0; col < S.width; col++, soff += cstep) 0237 FORRGB *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8; 0238 } 0239 else 0240 { 0241 for (col = 0; col < S.width; col++, soff += cstep) 0242 FORRGB *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]]; 0243 } 0244 } 0245 0246 // bufp += stride; // go to the next line 0247 } 0248 0249 S.iheight = s_iheight; 0250 S.iwidth = s_iwidth; 0251 S.width = s_width; 0252 S.height = s_hwight; 0253 0254 return 0; 0255 } 0256 #undef FORBGR 0257 #undef FORRGB 0258 0259 libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode) 0260 0261 { 0262 int width, height, colors, bps; 0263 get_mem_image_format(&width, &height, &colors, &bps); 0264 int stride = width * (bps / 8) * colors; 0265 unsigned ds = height * stride; 0266 libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc( 0267 sizeof(libraw_processed_image_t) + ds); 0268 if (!ret) 0269 { 0270 if (errcode) 0271 *errcode = ENOMEM; 0272 return NULL; 0273 } 0274 memset(ret, 0, sizeof(libraw_processed_image_t)); 0275 0276 // metadata init 0277 ret->type = LIBRAW_IMAGE_BITMAP; 0278 ret->height = height; 0279 ret->width = width; 0280 ret->colors = colors; 0281 ret->bits = bps; 0282 ret->data_size = ds; 0283 copy_mem_image(ret->data, stride, 0); 0284 0285 return ret; 0286 } 0287 0288 void LibRaw::dcraw_clear_mem(libraw_processed_image_t *p) 0289 { 0290 if (p) 0291 ::free(p); 0292 }