/src/jpegoptim/jpegdest.c
Line | Count | Source |
1 | | /* |
2 | | * jpegdest.c |
3 | | * |
4 | | * Copyright (C) 2014-2022 Timo Kokkonen |
5 | | * All Rights Reserved. |
6 | | * |
7 | | * custom libjpeg "Destination Manager" for saving into RAM |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-3.0-or-later |
10 | | * |
11 | | * This file is part of JPEGoptim. |
12 | | * |
13 | | * JPEGoptim is free software: you can redistribute it and/or modify |
14 | | * it under the terms of the GNU General Public License as published by |
15 | | * the Free Software Foundation, either version 3 of the License, or |
16 | | * (at your option) any later version. |
17 | | * |
18 | | * JPEGoptim is distributed in the hope that it will be useful, |
19 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | | * GNU General Public License for more details. |
22 | | * |
23 | | * You should have received a copy of the GNU General Public License |
24 | | * along with JPEGoptim. If not, see <https://www.gnu.org/licenses/>. |
25 | | */ |
26 | | |
27 | | #include <stdio.h> |
28 | | #include <stdlib.h> |
29 | | #include <string.h> |
30 | | #include <jpeglib.h> |
31 | | #include <jerror.h> |
32 | | |
33 | | #include "jpegoptim.h" |
34 | | |
35 | | |
36 | | |
37 | | /* custom jpeg destination manager object */ |
38 | | |
39 | | typedef struct { |
40 | | struct jpeg_destination_mgr pub; /* public fields */ |
41 | | |
42 | | unsigned char **buf_ptr; |
43 | | size_t *bufsize_ptr; |
44 | | size_t incsize; |
45 | | |
46 | | unsigned char *buf; |
47 | | size_t bufsize; |
48 | | |
49 | | } jpeg_memory_destination_mgr; |
50 | | |
51 | | typedef jpeg_memory_destination_mgr* jpeg_memory_destination_ptr; |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | static void jpeg_memory_init_destination (j_compress_ptr cinfo) |
57 | 0 | { |
58 | 0 | jpeg_memory_destination_ptr dest = (jpeg_memory_destination_ptr) cinfo->dest; |
59 | |
|
60 | 0 | dest->pub.next_output_byte = dest->buf; |
61 | 0 | dest->pub.free_in_buffer = dest->bufsize; |
62 | 0 | } |
63 | | |
64 | | |
65 | | static boolean jpeg_memory_empty_output_buffer (j_compress_ptr cinfo) |
66 | 0 | { |
67 | 0 | jpeg_memory_destination_ptr dest = (jpeg_memory_destination_ptr) cinfo->dest; |
68 | 0 | unsigned char *newbuf; |
69 | | |
70 | | /* abort if incsize is 0 (no expansion of buffer allowed) */ |
71 | 0 | if (dest->incsize == 0) ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 42); |
72 | | |
73 | | /* otherwise, try expanding buffer... */ |
74 | 0 | newbuf = realloc(dest->buf,dest->bufsize + dest->incsize); |
75 | 0 | if (!newbuf) ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 42); |
76 | |
|
77 | 0 | dest->pub.next_output_byte = newbuf + dest->bufsize; |
78 | 0 | dest->pub.free_in_buffer = dest->incsize; |
79 | |
|
80 | 0 | *dest->buf_ptr = newbuf; |
81 | 0 | dest->buf = newbuf; |
82 | 0 | dest->bufsize += dest->incsize; |
83 | 0 | dest->incsize *= 2; |
84 | |
|
85 | 0 | return TRUE; |
86 | 0 | } |
87 | | |
88 | | |
89 | | |
90 | | static void jpeg_memory_term_destination (j_compress_ptr cinfo) |
91 | 0 | { |
92 | 0 | jpeg_memory_destination_ptr dest = (jpeg_memory_destination_ptr) cinfo->dest; |
93 | |
|
94 | 0 | *dest->buf_ptr = dest->buf; |
95 | 0 | *dest->bufsize_ptr = dest->bufsize - dest->pub.free_in_buffer; |
96 | 0 | } |
97 | | |
98 | | |
99 | | |
100 | | void jpeg_memory_dest (j_compress_ptr cinfo, unsigned char **bufptr, size_t *bufsizeptr, size_t incsize) |
101 | 0 | { |
102 | 0 | jpeg_memory_destination_ptr dest; |
103 | |
|
104 | 0 | if (!cinfo || !bufptr || !bufsizeptr) |
105 | 0 | fatal("invalid call to jpeg_memory_dest()"); |
106 | 0 | if (!*bufptr || *bufsizeptr == 0) |
107 | 0 | fatal("invalid buffer passed to jpeg_memory_dest()"); |
108 | | |
109 | | |
110 | | /* Allocate destination manager object for compress object, if needed. */ |
111 | 0 | if (!cinfo->dest) { |
112 | 0 | cinfo->dest = (struct jpeg_destination_mgr *) |
113 | 0 | (*cinfo->mem->alloc_small) ( (j_common_ptr) cinfo, |
114 | 0 | JPOOL_PERMANENT, |
115 | 0 | sizeof(jpeg_memory_destination_mgr) ); |
116 | 0 | } |
117 | |
|
118 | 0 | dest = (jpeg_memory_destination_ptr)cinfo->dest; |
119 | |
|
120 | 0 | dest->buf_ptr = bufptr; |
121 | 0 | dest->buf = *bufptr; |
122 | 0 | dest->bufsize_ptr = bufsizeptr; |
123 | 0 | dest->bufsize = *bufsizeptr; |
124 | 0 | dest->incsize = incsize; |
125 | |
|
126 | 0 | dest->pub.init_destination = jpeg_memory_init_destination; |
127 | 0 | dest->pub.empty_output_buffer = jpeg_memory_empty_output_buffer; |
128 | 0 | dest->pub.term_destination = jpeg_memory_term_destination; |
129 | 0 | } |
130 | | |
131 | | |
132 | | /* eof :-) */ |