1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2018 Stanislav Yuzvinsky 4141cc406Sopenharmony_ci Based on the work done by viruxx 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 22141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 25141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 26141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 27141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 28141cc406Sopenharmony_ci account of linking the SANE library code into it. 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 31141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 32141cc406Sopenharmony_ci License. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 35141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 36141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 39141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 40141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 41141cc406Sopenharmony_ci*/ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci#include "../include/sane/config.h" 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci#include <assert.h> 46141cc406Sopenharmony_ci#include <stdlib.h> 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_citypedef struct ricoh2_buffer 51141cc406Sopenharmony_ci{ 52141cc406Sopenharmony_ci /* lifetime constants */ 53141cc406Sopenharmony_ci SANE_Byte *data; 54141cc406Sopenharmony_ci SANE_Int size; 55141cc406Sopenharmony_ci SANE_Int pixels_per_line; 56141cc406Sopenharmony_ci SANE_Int info_size; 57141cc406Sopenharmony_ci SANE_Bool is_rgb; 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci /* state */ 60141cc406Sopenharmony_ci SANE_Int current_position; 61141cc406Sopenharmony_ci SANE_Int remain_in_line; 62141cc406Sopenharmony_ci 63141cc406Sopenharmony_ci} 64141cc406Sopenharmony_ciricoh2_buffer; 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_cistatic ricoh2_buffer * 67141cc406Sopenharmony_ciricoh2_buffer_create (SANE_Int size, 68141cc406Sopenharmony_ci SANE_Int pixels_per_line, 69141cc406Sopenharmony_ci SANE_Int info_size, 70141cc406Sopenharmony_ci SANE_Bool is_rgb) 71141cc406Sopenharmony_ci{ 72141cc406Sopenharmony_ci ricoh2_buffer *self; 73141cc406Sopenharmony_ci assert (size > 0); 74141cc406Sopenharmony_ci assert (pixels_per_line > 0); 75141cc406Sopenharmony_ci assert (info_size >= 0); 76141cc406Sopenharmony_ci 77141cc406Sopenharmony_ci self = malloc (sizeof (ricoh2_buffer)); 78141cc406Sopenharmony_ci if (!self) 79141cc406Sopenharmony_ci return NULL; 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci self->data = malloc (size); 82141cc406Sopenharmony_ci if (!self->data) 83141cc406Sopenharmony_ci { 84141cc406Sopenharmony_ci free (self); 85141cc406Sopenharmony_ci return NULL; 86141cc406Sopenharmony_ci } 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci self->size = size; 89141cc406Sopenharmony_ci self->pixels_per_line = pixels_per_line; 90141cc406Sopenharmony_ci self->info_size = info_size; 91141cc406Sopenharmony_ci self->is_rgb = is_rgb; 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci self->current_position = 0; 94141cc406Sopenharmony_ci self->remain_in_line = pixels_per_line; 95141cc406Sopenharmony_ci 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci DBG (192, 98141cc406Sopenharmony_ci "size = %d pixels_per_line = %d info_size = %d rgb? = %d pos = %d\n", 99141cc406Sopenharmony_ci self->size, 100141cc406Sopenharmony_ci self->pixels_per_line, 101141cc406Sopenharmony_ci self->info_size, 102141cc406Sopenharmony_ci self->is_rgb, 103141cc406Sopenharmony_ci self->current_position); 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_ci return self; 106141cc406Sopenharmony_ci} 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_ci/* destructor */ 109141cc406Sopenharmony_cistatic void 110141cc406Sopenharmony_ciricoh2_buffer_dispose (ricoh2_buffer *self) 111141cc406Sopenharmony_ci{ 112141cc406Sopenharmony_ci assert (self); 113141cc406Sopenharmony_ci free (self->data); 114141cc406Sopenharmony_ci free (self); 115141cc406Sopenharmony_ci} 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_cistatic SANE_Byte * 118141cc406Sopenharmony_ciricoh2_buffer_get_internal_buffer (ricoh2_buffer *self) 119141cc406Sopenharmony_ci{ 120141cc406Sopenharmony_ci assert (self); 121141cc406Sopenharmony_ci DBG (192, "engaging a buffer of size %d\n", self->size); 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci self->current_position = 0; 124141cc406Sopenharmony_ci self->remain_in_line = self->pixels_per_line; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci DBG (192, "remain in line = %d\n", self->remain_in_line); 127141cc406Sopenharmony_ci 128141cc406Sopenharmony_ci return self->data; 129141cc406Sopenharmony_ci} 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_cistatic SANE_Int 132141cc406Sopenharmony_ciricoh2_buffer_get_bytes_remain (ricoh2_buffer *self) 133141cc406Sopenharmony_ci{ 134141cc406Sopenharmony_ci assert (self); 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_ci DBG (192, 137141cc406Sopenharmony_ci "bytes remain in the buffer %d\n", 138141cc406Sopenharmony_ci self->size - self->current_position); 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_ci return self->size - self->current_position; 141141cc406Sopenharmony_ci} 142141cc406Sopenharmony_ci 143141cc406Sopenharmony_ciinline static SANE_Int 144141cc406Sopenharmony_cimin (SANE_Int v1, SANE_Int v2) 145141cc406Sopenharmony_ci{ 146141cc406Sopenharmony_ci return v1 < v2 ? v1 : v2; 147141cc406Sopenharmony_ci} 148141cc406Sopenharmony_ci 149141cc406Sopenharmony_cistatic SANE_Int 150141cc406Sopenharmony_ciricoh2_buffer_get_data (ricoh2_buffer *self, 151141cc406Sopenharmony_ci SANE_Byte *dest, 152141cc406Sopenharmony_ci SANE_Int dest_size) 153141cc406Sopenharmony_ci{ 154141cc406Sopenharmony_ci SANE_Int actually_copied = 0; 155141cc406Sopenharmony_ci SANE_Int pixels_to_copy; 156141cc406Sopenharmony_ci SANE_Int bytes_per_pixel; 157141cc406Sopenharmony_ci SANE_Int bytes_per_color; 158141cc406Sopenharmony_ci SANE_Byte *src; 159141cc406Sopenharmony_ci SANE_Byte *end; 160141cc406Sopenharmony_ci 161141cc406Sopenharmony_ci assert (self); 162141cc406Sopenharmony_ci assert (dest); 163141cc406Sopenharmony_ci assert (self->size > self->current_position); 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_ci bytes_per_pixel = self->is_rgb ? 3 : 1; 166141cc406Sopenharmony_ci bytes_per_color = self->pixels_per_line + self->info_size; 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_ci DBG (192, 169141cc406Sopenharmony_ci "trying to get %d bytes from the buffer, " 170141cc406Sopenharmony_ci "while %d bytes in the line\n", 171141cc406Sopenharmony_ci dest_size, 172141cc406Sopenharmony_ci self->remain_in_line); 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci for (pixels_to_copy = 175141cc406Sopenharmony_ci min (dest_size / bytes_per_pixel, self->remain_in_line); 176141cc406Sopenharmony_ci pixels_to_copy && self->size > self->current_position; 177141cc406Sopenharmony_ci pixels_to_copy = 178141cc406Sopenharmony_ci min (dest_size / bytes_per_pixel, self->remain_in_line)) 179141cc406Sopenharmony_ci { 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci DBG (192, 182141cc406Sopenharmony_ci "providing %d bytes to the user (until the end of the line), " 183141cc406Sopenharmony_ci "position in buffer is %d\n", 184141cc406Sopenharmony_ci pixels_to_copy * bytes_per_pixel, 185141cc406Sopenharmony_ci self->current_position); 186141cc406Sopenharmony_ci 187141cc406Sopenharmony_ci for (src = self->data + self->current_position, 188141cc406Sopenharmony_ci end = src + pixels_to_copy; 189141cc406Sopenharmony_ci src < end; 190141cc406Sopenharmony_ci ++src) 191141cc406Sopenharmony_ci { 192141cc406Sopenharmony_ci *(dest++) = *(src); 193141cc406Sopenharmony_ci if (bytes_per_pixel == 3) 194141cc406Sopenharmony_ci { 195141cc406Sopenharmony_ci *(dest++) = *(src + bytes_per_color); 196141cc406Sopenharmony_ci *(dest++) = *(src + 2 * bytes_per_color); 197141cc406Sopenharmony_ci } 198141cc406Sopenharmony_ci } 199141cc406Sopenharmony_ci 200141cc406Sopenharmony_ci dest_size -= pixels_to_copy * bytes_per_pixel; 201141cc406Sopenharmony_ci actually_copied += pixels_to_copy * bytes_per_pixel; 202141cc406Sopenharmony_ci self->current_position += pixels_to_copy; 203141cc406Sopenharmony_ci self->remain_in_line -= pixels_to_copy; 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci // move to the next line 206141cc406Sopenharmony_ci if (!self->remain_in_line) 207141cc406Sopenharmony_ci { 208141cc406Sopenharmony_ci self->current_position += self->info_size; 209141cc406Sopenharmony_ci if (self->is_rgb) 210141cc406Sopenharmony_ci self->current_position += 2 * bytes_per_color; 211141cc406Sopenharmony_ci self->remain_in_line = self->pixels_per_line; 212141cc406Sopenharmony_ci DBG (192, 213141cc406Sopenharmony_ci "Line feed, new position is %d\n", 214141cc406Sopenharmony_ci self->current_position); 215141cc406Sopenharmony_ci } 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci DBG (192, 218141cc406Sopenharmony_ci "left in the buffer: %d\n", 219141cc406Sopenharmony_ci self->size - self->current_position); 220141cc406Sopenharmony_ci } 221141cc406Sopenharmony_ci 222141cc406Sopenharmony_ci /* invariant */ 223141cc406Sopenharmony_ci assert (self->size >= self->current_position); 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci return actually_copied; 226141cc406Sopenharmony_ci} 227